thehood 0.1.0-preview.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CODE_OF_CONDUCT.md +21 -0
- package/CONTRIBUTING.md +58 -0
- package/LICENSE +21 -0
- package/PRIVACY.md +49 -0
- package/README.md +264 -0
- package/SECURITY.md +31 -0
- package/dist/bridges/chatgptWebBridge.d.ts +2 -0
- package/dist/bridges/chatgptWebBridge.js +981 -0
- package/dist/bridges/chatgptWebBridge.js.map +1 -0
- package/dist/cli/args.d.ts +9 -0
- package/dist/cli/args.js +82 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/format.d.ts +56 -0
- package/dist/cli/format.js +752 -0
- package/dist/cli/format.js.map +1 -0
- package/dist/cli/main.d.ts +2 -0
- package/dist/cli/main.js +996 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/mcpConfig.d.ts +36 -0
- package/dist/cli/mcpConfig.js +98 -0
- package/dist/cli/mcpConfig.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/protocol.d.ts +44 -0
- package/dist/mcp/protocol.js +33 -0
- package/dist/mcp/protocol.js.map +1 -0
- package/dist/mcp/server.d.ts +1 -0
- package/dist/mcp/server.js +106 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools.d.ts +10 -0
- package/dist/mcp/tools.js +2200 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/mcp/validation.d.ts +8 -0
- package/dist/mcp/validation.js +67 -0
- package/dist/mcp/validation.js.map +1 -0
- package/dist/providers/chatgptWeb.d.ts +2 -0
- package/dist/providers/chatgptWeb.js +26 -0
- package/dist/providers/chatgptWeb.js.map +1 -0
- package/dist/providers/claudeCode.d.ts +4 -0
- package/dist/providers/claudeCode.js +32 -0
- package/dist/providers/claudeCode.js.map +1 -0
- package/dist/providers/codexCli.d.ts +6 -0
- package/dist/providers/codexCli.js +25 -0
- package/dist/providers/codexCli.js.map +1 -0
- package/dist/providers/codexCliModels.d.ts +23 -0
- package/dist/providers/codexCliModels.js +147 -0
- package/dist/providers/codexCliModels.js.map +1 -0
- package/dist/providers/localCommand.d.ts +26 -0
- package/dist/providers/localCommand.js +614 -0
- package/dist/providers/localCommand.js.map +1 -0
- package/dist/providers/markdownPayload.d.ts +7 -0
- package/dist/providers/markdownPayload.js +29 -0
- package/dist/providers/markdownPayload.js.map +1 -0
- package/dist/providers/responseSchema.d.ts +3 -0
- package/dist/providers/responseSchema.js +187 -0
- package/dist/providers/responseSchema.js.map +1 -0
- package/dist/providers/router.d.ts +3 -0
- package/dist/providers/router.js +21 -0
- package/dist/providers/router.js.map +1 -0
- package/dist/providers/stub.d.ts +2 -0
- package/dist/providers/stub.js +177 -0
- package/dist/providers/stub.js.map +1 -0
- package/dist/providers/types.d.ts +37 -0
- package/dist/providers/types.js +2 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/runtime/agentBoard.d.ts +79 -0
- package/dist/runtime/agentBoard.js +166 -0
- package/dist/runtime/agentBoard.js.map +1 -0
- package/dist/runtime/agentBoardArtifact.d.ts +9 -0
- package/dist/runtime/agentBoardArtifact.js +171 -0
- package/dist/runtime/agentBoardArtifact.js.map +1 -0
- package/dist/runtime/agentRunner.d.ts +17 -0
- package/dist/runtime/agentRunner.js +92 -0
- package/dist/runtime/agentRunner.js.map +1 -0
- package/dist/runtime/approvalInbox.d.ts +54 -0
- package/dist/runtime/approvalInbox.js +143 -0
- package/dist/runtime/approvalInbox.js.map +1 -0
- package/dist/runtime/approvalPolicy.d.ts +11 -0
- package/dist/runtime/approvalPolicy.js +58 -0
- package/dist/runtime/approvalPolicy.js.map +1 -0
- package/dist/runtime/artifacts.d.ts +23 -0
- package/dist/runtime/artifacts.js +48 -0
- package/dist/runtime/artifacts.js.map +1 -0
- package/dist/runtime/browserManager.d.ts +37 -0
- package/dist/runtime/browserManager.js +356 -0
- package/dist/runtime/browserManager.js.map +1 -0
- package/dist/runtime/canonicalMemory.d.ts +23 -0
- package/dist/runtime/canonicalMemory.js +134 -0
- package/dist/runtime/canonicalMemory.js.map +1 -0
- package/dist/runtime/chatGptPageReadiness.d.ts +16 -0
- package/dist/runtime/chatGptPageReadiness.js +74 -0
- package/dist/runtime/chatGptPageReadiness.js.map +1 -0
- package/dist/runtime/commandRunner.d.ts +18 -0
- package/dist/runtime/commandRunner.js +115 -0
- package/dist/runtime/commandRunner.js.map +1 -0
- package/dist/runtime/commandSafety.d.ts +7 -0
- package/dist/runtime/commandSafety.js +61 -0
- package/dist/runtime/commandSafety.js.map +1 -0
- package/dist/runtime/config.d.ts +10 -0
- package/dist/runtime/config.js +107 -0
- package/dist/runtime/config.js.map +1 -0
- package/dist/runtime/crewLanes.d.ts +2 -0
- package/dist/runtime/crewLanes.js +123 -0
- package/dist/runtime/crewLanes.js.map +1 -0
- package/dist/runtime/criticPolicy.d.ts +17 -0
- package/dist/runtime/criticPolicy.js +50 -0
- package/dist/runtime/criticPolicy.js.map +1 -0
- package/dist/runtime/defaults.d.ts +5 -0
- package/dist/runtime/defaults.js +100 -0
- package/dist/runtime/defaults.js.map +1 -0
- package/dist/runtime/directives.d.ts +3 -0
- package/dist/runtime/directives.js +218 -0
- package/dist/runtime/directives.js.map +1 -0
- package/dist/runtime/doctor.d.ts +36 -0
- package/dist/runtime/doctor.js +185 -0
- package/dist/runtime/doctor.js.map +1 -0
- package/dist/runtime/errors.d.ts +20 -0
- package/dist/runtime/errors.js +41 -0
- package/dist/runtime/errors.js.map +1 -0
- package/dist/runtime/externalTransfer.d.ts +20 -0
- package/dist/runtime/externalTransfer.js +156 -0
- package/dist/runtime/externalTransfer.js.map +1 -0
- package/dist/runtime/fanout.d.ts +64 -0
- package/dist/runtime/fanout.js +263 -0
- package/dist/runtime/fanout.js.map +1 -0
- package/dist/runtime/gitEvidence.d.ts +10 -0
- package/dist/runtime/gitEvidence.js +80 -0
- package/dist/runtime/gitEvidence.js.map +1 -0
- package/dist/runtime/handoffs.d.ts +32 -0
- package/dist/runtime/handoffs.js +100 -0
- package/dist/runtime/handoffs.js.map +1 -0
- package/dist/runtime/ids.d.ts +2 -0
- package/dist/runtime/ids.js +4 -0
- package/dist/runtime/ids.js.map +1 -0
- package/dist/runtime/localStateIgnore.d.ts +9 -0
- package/dist/runtime/localStateIgnore.js +98 -0
- package/dist/runtime/localStateIgnore.js.map +1 -0
- package/dist/runtime/loop.d.ts +14 -0
- package/dist/runtime/loop.js +1863 -0
- package/dist/runtime/loop.js.map +1 -0
- package/dist/runtime/loopRecommendation.d.ts +109 -0
- package/dist/runtime/loopRecommendation.js +566 -0
- package/dist/runtime/loopRecommendation.js.map +1 -0
- package/dist/runtime/loopResponsibilities.d.ts +2 -0
- package/dist/runtime/loopResponsibilities.js +395 -0
- package/dist/runtime/loopResponsibilities.js.map +1 -0
- package/dist/runtime/loopRunner.d.ts +28 -0
- package/dist/runtime/loopRunner.js +81 -0
- package/dist/runtime/loopRunner.js.map +1 -0
- package/dist/runtime/operatorNextActions.d.ts +2 -0
- package/dist/runtime/operatorNextActions.js +344 -0
- package/dist/runtime/operatorNextActions.js.map +1 -0
- package/dist/runtime/paths.d.ts +9 -0
- package/dist/runtime/paths.js +14 -0
- package/dist/runtime/paths.js.map +1 -0
- package/dist/runtime/permissions.d.ts +9 -0
- package/dist/runtime/permissions.js +73 -0
- package/dist/runtime/permissions.js.map +1 -0
- package/dist/runtime/progressPacket.d.ts +12 -0
- package/dist/runtime/progressPacket.js +512 -0
- package/dist/runtime/progressPacket.js.map +1 -0
- package/dist/runtime/protectedPaths.d.ts +6 -0
- package/dist/runtime/protectedPaths.js +48 -0
- package/dist/runtime/protectedPaths.js.map +1 -0
- package/dist/runtime/providers.d.ts +13 -0
- package/dist/runtime/providers.js +60 -0
- package/dist/runtime/providers.js.map +1 -0
- package/dist/runtime/reconciliation.d.ts +17 -0
- package/dist/runtime/reconciliation.js +283 -0
- package/dist/runtime/reconciliation.js.map +1 -0
- package/dist/runtime/redaction.d.ts +1 -0
- package/dist/runtime/redaction.js +5 -0
- package/dist/runtime/redaction.js.map +1 -0
- package/dist/runtime/remoteRepoContext.d.ts +77 -0
- package/dist/runtime/remoteRepoContext.js +316 -0
- package/dist/runtime/remoteRepoContext.js.map +1 -0
- package/dist/runtime/repoContext.d.ts +50 -0
- package/dist/runtime/repoContext.js +399 -0
- package/dist/runtime/repoContext.js.map +1 -0
- package/dist/runtime/repoGateway.d.ts +64 -0
- package/dist/runtime/repoGateway.js +308 -0
- package/dist/runtime/repoGateway.js.map +1 -0
- package/dist/runtime/responseContracts.d.ts +3 -0
- package/dist/runtime/responseContracts.js +86 -0
- package/dist/runtime/responseContracts.js.map +1 -0
- package/dist/runtime/reviewLanes.d.ts +2 -0
- package/dist/runtime/reviewLanes.js +343 -0
- package/dist/runtime/reviewLanes.js.map +1 -0
- package/dist/runtime/reviewRouting.d.ts +51 -0
- package/dist/runtime/reviewRouting.js +152 -0
- package/dist/runtime/reviewRouting.js.map +1 -0
- package/dist/runtime/revisionPacket.d.ts +38 -0
- package/dist/runtime/revisionPacket.js +144 -0
- package/dist/runtime/revisionPacket.js.map +1 -0
- package/dist/runtime/revisionTrail.d.ts +2 -0
- package/dist/runtime/revisionTrail.js +162 -0
- package/dist/runtime/revisionTrail.js.map +1 -0
- package/dist/runtime/role-assignment.d.ts +4 -0
- package/dist/runtime/role-assignment.js +21 -0
- package/dist/runtime/role-assignment.js.map +1 -0
- package/dist/runtime/roleRoster.d.ts +28 -0
- package/dist/runtime/roleRoster.js +96 -0
- package/dist/runtime/roleRoster.js.map +1 -0
- package/dist/runtime/runInsights.d.ts +121 -0
- package/dist/runtime/runInsights.js +305 -0
- package/dist/runtime/runInsights.js.map +1 -0
- package/dist/runtime/runMonitor.d.ts +33 -0
- package/dist/runtime/runMonitor.js +143 -0
- package/dist/runtime/runMonitor.js.map +1 -0
- package/dist/runtime/runtime.d.ts +15 -0
- package/dist/runtime/runtime.js +199 -0
- package/dist/runtime/runtime.js.map +1 -0
- package/dist/runtime/runtimeInfo.d.ts +9 -0
- package/dist/runtime/runtimeInfo.js +76 -0
- package/dist/runtime/runtimeInfo.js.map +1 -0
- package/dist/runtime/store.d.ts +4 -0
- package/dist/runtime/store.js +48 -0
- package/dist/runtime/store.js.map +1 -0
- package/dist/runtime/summons.d.ts +25 -0
- package/dist/runtime/summons.js +403 -0
- package/dist/runtime/summons.js.map +1 -0
- package/dist/runtime/teamPresets.d.ts +14 -0
- package/dist/runtime/teamPresets.js +153 -0
- package/dist/runtime/teamPresets.js.map +1 -0
- package/dist/runtime/types.d.ts +505 -0
- package/dist/runtime/types.js +28 -0
- package/dist/runtime/types.js.map +1 -0
- package/dist/runtime/validationCommands.d.ts +18 -0
- package/dist/runtime/validationCommands.js +106 -0
- package/dist/runtime/validationCommands.js.map +1 -0
- package/dist/tui/dashboard.d.ts +41 -0
- package/dist/tui/dashboard.js +1115 -0
- package/dist/tui/dashboard.js.map +1 -0
- package/docs/ARCHITECTURE.md +277 -0
- package/docs/CLI_SPEC.md +396 -0
- package/docs/CODEX_SETUP.md +288 -0
- package/docs/COMPLETION_CONTRACT.md +52 -0
- package/docs/CONTRIBUTOR_GUIDE.md +70 -0
- package/docs/DEMO.md +62 -0
- package/docs/GLOSSARY.md +46 -0
- package/docs/GOAL_LOOP_SCHEDULE.md +50 -0
- package/docs/KNOWN_LIMITATIONS.md +29 -0
- package/docs/LICENSING.md +21 -0
- package/docs/LOOP_RECIPES.md +290 -0
- package/docs/LOOP_SELECTION_UX.md +118 -0
- package/docs/MCP_SPEC.md +689 -0
- package/docs/MEMORY_AND_RECONCILIATION.md +222 -0
- package/docs/NPM_PUBLISHING.md +51 -0
- package/docs/OPEN_DECISIONS.md +81 -0
- package/docs/PROMPT_SCHEMAS.md +411 -0
- package/docs/PROVIDER_ADAPTERS.md +323 -0
- package/docs/PROVIDER_MATRIX.md +21 -0
- package/docs/PUBLIC_REPO_READINESS.md +49 -0
- package/docs/RESEARCH_NOTES.md +92 -0
- package/docs/ROADMAP.md +94 -0
- package/docs/ROLE_CONTRACTS.md +252 -0
- package/docs/RUNTIME_LOOP.md +240 -0
- package/docs/SECURITY_AND_PRIVACY.md +161 -0
- package/docs/TESTING_AND_VERIFICATION.md +180 -0
- package/docs/TRUST_MODEL.md +65 -0
- package/docs/decisions/0001-runtime-first-cli-and-mcp.md +23 -0
- package/docs/decisions/0002-provider-neutral-role-mapping.md +43 -0
- package/docs/decisions/0003-separate-implementation-and-verification.md +27 -0
- package/docs/product/README.md +14 -0
- package/docs/product/model-selection.md +88 -0
- package/docs/product/positioning.md +37 -0
- package/docs/product/pro-usage-modes.md +70 -0
- package/docs/product/roadmap.md +57 -0
- package/docs/product/role-policy.md +89 -0
- package/docs/product/runtime-invariants.md +44 -0
- package/docs/release/v0.1.0-preview.0.md +48 -0
- package/examples/stub-demo/README.md +25 -0
- package/package.json +55 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ExternalTransferManifest, ExternalTransferPurpose, JsonObject, RoleAssignment, RunArtifact, RunRecord, RuntimeRole } from "./types.js";
|
|
2
|
+
export interface BuildExternalTransferManifestInput {
|
|
3
|
+
run: RunRecord;
|
|
4
|
+
role: RuntimeRole;
|
|
5
|
+
destination: RoleAssignment;
|
|
6
|
+
purpose: ExternalTransferPurpose;
|
|
7
|
+
approvalPhrase: string;
|
|
8
|
+
artifacts: RunArtifact[];
|
|
9
|
+
}
|
|
10
|
+
export interface ExternalTransferPreview {
|
|
11
|
+
manifestArtifact: RunArtifact;
|
|
12
|
+
manifest: ExternalTransferManifest;
|
|
13
|
+
}
|
|
14
|
+
export declare const buildExternalTransferManifest: (input: BuildExternalTransferManifestInput) => Promise<ExternalTransferManifest>;
|
|
15
|
+
export declare const writeExternalTransferManifestArtifact: (input: BuildExternalTransferManifestInput) => Promise<{
|
|
16
|
+
manifest: ExternalTransferManifest;
|
|
17
|
+
artifact: RunArtifact;
|
|
18
|
+
}>;
|
|
19
|
+
export declare const readLatestExternalTransferManifest: (run: RunRecord) => Promise<ExternalTransferPreview>;
|
|
20
|
+
export declare const transferManifestSummary: (manifest: ExternalTransferManifest) => JsonObject;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import { readRunArtifact, writeRunArtifact } from "./artifacts.js";
|
|
3
|
+
import { InputError } from "./errors.js";
|
|
4
|
+
import { newId, nowIso } from "./ids.js";
|
|
5
|
+
const maxArtifactBytes = 200_000;
|
|
6
|
+
const previewBytes = 4_000;
|
|
7
|
+
const secretPatterns = [
|
|
8
|
+
/(?:api[_-]?key|secret|password|token)\s*[:=]\s*["']?[A-Za-z0-9_./+=-]{8,}/i,
|
|
9
|
+
/authorization:\s*bearer/i,
|
|
10
|
+
/ssh-rsa|-----BEGIN [A-Z ]*PRIVATE KEY-----/
|
|
11
|
+
];
|
|
12
|
+
const sha256 = (value) => crypto.createHash("sha256").update(value).digest("hex");
|
|
13
|
+
const artifactRiskClass = (purpose) => {
|
|
14
|
+
switch (purpose) {
|
|
15
|
+
case "progress_packet":
|
|
16
|
+
case "memory_packet":
|
|
17
|
+
case "reconciliation":
|
|
18
|
+
return "private_runtime_memory";
|
|
19
|
+
case "repo_context":
|
|
20
|
+
return "repo_context";
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
const detectSecretPatternHits = (content) => secretPatterns.filter((pattern) => pattern.test(content)).length;
|
|
24
|
+
const buildRisk = (purpose, artifactContents) => {
|
|
25
|
+
const secretPatternHits = artifactContents.reduce((count, content) => count + detectSecretPatternHits(content), 0);
|
|
26
|
+
const reasons = [
|
|
27
|
+
purpose === "repo_context"
|
|
28
|
+
? "Transfer includes runtime-captured repository context."
|
|
29
|
+
: "Transfer includes private TheHood runtime memory."
|
|
30
|
+
];
|
|
31
|
+
if (secretPatternHits > 0) {
|
|
32
|
+
reasons.push("Secret-like text was detected in the transfer source artifact preview.");
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
class: secretPatternHits > 0 ? "secret_risk" : artifactRiskClass(purpose),
|
|
36
|
+
reasons,
|
|
37
|
+
secretPatternHits
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
const artifactRef = async (run, artifact) => {
|
|
41
|
+
const result = await readRunArtifact({
|
|
42
|
+
repoPath: run.repoPath,
|
|
43
|
+
runId: run.runId,
|
|
44
|
+
ref: artifact.ref,
|
|
45
|
+
maxBytes: maxArtifactBytes
|
|
46
|
+
});
|
|
47
|
+
if (result.truncated) {
|
|
48
|
+
throw new InputError(`External transfer source artifact is too large to review safely: ${artifact.ref}`);
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
ref: {
|
|
52
|
+
kind: artifact.kind,
|
|
53
|
+
ref: artifact.ref,
|
|
54
|
+
summary: artifact.summary,
|
|
55
|
+
byteLength: result.byteLength,
|
|
56
|
+
truncated: result.truncated,
|
|
57
|
+
sha256: sha256(result.content)
|
|
58
|
+
},
|
|
59
|
+
content: result.content
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
const previewContent = (contents) => {
|
|
63
|
+
const joined = contents.join("\n\n--- artifact boundary ---\n\n");
|
|
64
|
+
const truncated = Buffer.byteLength(joined, "utf8") > previewBytes;
|
|
65
|
+
return {
|
|
66
|
+
content: joined.slice(0, previewBytes),
|
|
67
|
+
truncated
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
export const buildExternalTransferManifest = async (input) => {
|
|
71
|
+
const inspected = await Promise.all(input.artifacts.map((artifact) => artifactRef(input.run, artifact)));
|
|
72
|
+
const contents = inspected.map((item) => item.content);
|
|
73
|
+
const preview = previewContent(contents);
|
|
74
|
+
const approvalHint = `I approve ${input.approvalPhrase} for run ${input.run.runId}.`;
|
|
75
|
+
return {
|
|
76
|
+
schemaVersion: 1,
|
|
77
|
+
kind: "external_transfer_manifest",
|
|
78
|
+
runId: input.run.runId,
|
|
79
|
+
createdAt: nowIso(),
|
|
80
|
+
destination: input.destination,
|
|
81
|
+
role: input.role,
|
|
82
|
+
purpose: input.purpose,
|
|
83
|
+
approvalPhrase: input.approvalPhrase,
|
|
84
|
+
approvalHint,
|
|
85
|
+
artifacts: inspected.map((item) => item.ref),
|
|
86
|
+
totalBytes: inspected.reduce((total, item) => total + item.ref.byteLength, 0),
|
|
87
|
+
risk: buildRisk(input.purpose, contents),
|
|
88
|
+
redaction: {
|
|
89
|
+
status: "not_applied",
|
|
90
|
+
notes: [
|
|
91
|
+
"The manifest previews the exact bounded artifact content before external transfer.",
|
|
92
|
+
"Source artifacts remain canonical; provider-visible packets are built from these artifacts."
|
|
93
|
+
]
|
|
94
|
+
},
|
|
95
|
+
preview: {
|
|
96
|
+
maxBytes: previewBytes,
|
|
97
|
+
content: preview.content,
|
|
98
|
+
truncated: preview.truncated
|
|
99
|
+
},
|
|
100
|
+
provenance: {
|
|
101
|
+
sourceArtifactRefs: input.artifacts.map((artifact) => artifact.ref),
|
|
102
|
+
notes: [
|
|
103
|
+
"Generated by the runtime before an external provider transfer approval gate.",
|
|
104
|
+
"Approval should be based on this manifest, not on provider session context."
|
|
105
|
+
]
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
export const writeExternalTransferManifestArtifact = async (input) => {
|
|
110
|
+
const manifest = await buildExternalTransferManifest(input);
|
|
111
|
+
const artifact = await writeRunArtifact({
|
|
112
|
+
repoPath: input.run.repoPath,
|
|
113
|
+
runId: input.run.runId,
|
|
114
|
+
kind: "transfer_manifest",
|
|
115
|
+
name: `${input.purpose}-${input.destination.provider}-${newId("transfer")}.json`,
|
|
116
|
+
content: `${JSON.stringify(manifest, null, 2)}\n`,
|
|
117
|
+
summary: `${input.purpose} transfer manifest for ${input.destination.provider}:${input.destination.model}.`
|
|
118
|
+
});
|
|
119
|
+
return {
|
|
120
|
+
manifest,
|
|
121
|
+
artifact
|
|
122
|
+
};
|
|
123
|
+
};
|
|
124
|
+
const isManifest = (value) => value !== null &&
|
|
125
|
+
typeof value === "object" &&
|
|
126
|
+
!Array.isArray(value) &&
|
|
127
|
+
value.kind === "external_transfer_manifest";
|
|
128
|
+
export const readLatestExternalTransferManifest = async (run) => {
|
|
129
|
+
const manifestArtifact = run.artifacts.filter((artifact) => artifact.kind === "transfer_manifest").at(-1);
|
|
130
|
+
if (!manifestArtifact) {
|
|
131
|
+
throw new InputError(`Run ${run.runId} does not have a transfer manifest artifact.`);
|
|
132
|
+
}
|
|
133
|
+
const result = await readRunArtifact({
|
|
134
|
+
repoPath: run.repoPath,
|
|
135
|
+
runId: run.runId,
|
|
136
|
+
ref: manifestArtifact.ref,
|
|
137
|
+
maxBytes: maxArtifactBytes
|
|
138
|
+
});
|
|
139
|
+
const parsed = JSON.parse(result.content);
|
|
140
|
+
if (!isManifest(parsed)) {
|
|
141
|
+
throw new InputError(`Transfer manifest artifact is invalid: ${manifestArtifact.ref}`);
|
|
142
|
+
}
|
|
143
|
+
return {
|
|
144
|
+
manifestArtifact,
|
|
145
|
+
manifest: parsed
|
|
146
|
+
};
|
|
147
|
+
};
|
|
148
|
+
export const transferManifestSummary = (manifest) => ({
|
|
149
|
+
destination: `${manifest.destination.provider}:${manifest.destination.model}`,
|
|
150
|
+
purpose: manifest.purpose,
|
|
151
|
+
riskClass: manifest.risk.class,
|
|
152
|
+
totalBytes: manifest.totalBytes,
|
|
153
|
+
artifactCount: manifest.artifacts.length,
|
|
154
|
+
approvalPhrase: manifest.approvalPhrase
|
|
155
|
+
});
|
|
156
|
+
//# sourceMappingURL=externalTransfer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"externalTransfer.js","sourceRoot":"","sources":["../../src/runtime/externalTransfer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { AgentResponse } from "../providers/types.js";
|
|
2
|
+
import type { JsonObject, RoleAssignment, RunArtifact, RunRecord, RuntimeRole } from "./types.js";
|
|
3
|
+
export type FanoutStatus = "completed" | "blocked" | "failed";
|
|
4
|
+
export type FanoutItemStatus = "completed" | "blocked" | "failed";
|
|
5
|
+
export interface FanoutItemInput {
|
|
6
|
+
role: RuntimeRole;
|
|
7
|
+
brief: string;
|
|
8
|
+
summonKind?: string;
|
|
9
|
+
persona?: string;
|
|
10
|
+
agent?: RoleAssignment;
|
|
11
|
+
constraints?: string[];
|
|
12
|
+
evidenceRefs?: string[];
|
|
13
|
+
}
|
|
14
|
+
export interface FanoutAgentsInput {
|
|
15
|
+
repoPath: string;
|
|
16
|
+
runId: string;
|
|
17
|
+
items: FanoutItemInput[];
|
|
18
|
+
maxItems?: number;
|
|
19
|
+
}
|
|
20
|
+
export interface FanoutBounds {
|
|
21
|
+
requestedItems: number;
|
|
22
|
+
maxItems: number;
|
|
23
|
+
hardMaxItems: number;
|
|
24
|
+
executedItems: number;
|
|
25
|
+
execution: "sequential";
|
|
26
|
+
}
|
|
27
|
+
export interface FanoutItemResult {
|
|
28
|
+
index: number;
|
|
29
|
+
role: RuntimeRole;
|
|
30
|
+
summonKind: string;
|
|
31
|
+
brief: string;
|
|
32
|
+
status: FanoutItemStatus;
|
|
33
|
+
stopReason: string;
|
|
34
|
+
providerResponseCount: number;
|
|
35
|
+
assignment?: RoleAssignment;
|
|
36
|
+
providerStatus?: AgentResponse["status"];
|
|
37
|
+
directiveArtifact?: RunArtifact;
|
|
38
|
+
responseArtifact?: RunArtifact;
|
|
39
|
+
error?: string;
|
|
40
|
+
}
|
|
41
|
+
export interface FanoutAgentsResult {
|
|
42
|
+
run: RunRecord;
|
|
43
|
+
status: FanoutStatus;
|
|
44
|
+
bounds: FanoutBounds;
|
|
45
|
+
items: FanoutItemResult[];
|
|
46
|
+
artifact: RunArtifact;
|
|
47
|
+
}
|
|
48
|
+
export interface FanoutArtifactPayload {
|
|
49
|
+
schemaVersion: 1;
|
|
50
|
+
kind: "fanout";
|
|
51
|
+
runId: string;
|
|
52
|
+
createdAt: string;
|
|
53
|
+
status: FanoutStatus;
|
|
54
|
+
bounds: FanoutBounds;
|
|
55
|
+
safety: {
|
|
56
|
+
sidecarOnly: boolean;
|
|
57
|
+
readOnlyRolesOnly: boolean;
|
|
58
|
+
canSatisfyRequiredGates: boolean;
|
|
59
|
+
instruction: string;
|
|
60
|
+
};
|
|
61
|
+
items: JsonObject[];
|
|
62
|
+
}
|
|
63
|
+
export declare const defaultFanoutMaxItems = 8;
|
|
64
|
+
export declare const fanoutAgents: (input: FanoutAgentsInput) => Promise<FanoutAgentsResult>;
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import { writeRunArtifact } from "./artifacts.js";
|
|
2
|
+
import { loadConfig } from "./config.js";
|
|
3
|
+
import { InputError } from "./errors.js";
|
|
4
|
+
import { newId, nowIso } from "./ids.js";
|
|
5
|
+
import { defaultRolePermissions } from "./permissions.js";
|
|
6
|
+
import { loadRun, saveRun } from "./store.js";
|
|
7
|
+
import { summonAgent } from "./summons.js";
|
|
8
|
+
const fanoutRoles = [
|
|
9
|
+
"orchestrator",
|
|
10
|
+
"planner",
|
|
11
|
+
"researcher",
|
|
12
|
+
"qa",
|
|
13
|
+
"verifier",
|
|
14
|
+
"critic"
|
|
15
|
+
];
|
|
16
|
+
export const defaultFanoutMaxItems = 8;
|
|
17
|
+
const hardFanoutMaxItems = 8;
|
|
18
|
+
const maxTextLength = 500;
|
|
19
|
+
const createEvent = (type, message, data) => ({
|
|
20
|
+
id: newId("event"),
|
|
21
|
+
createdAt: nowIso(),
|
|
22
|
+
type,
|
|
23
|
+
message,
|
|
24
|
+
...(data ? { data } : {})
|
|
25
|
+
});
|
|
26
|
+
const truncateText = (value) => value.length <= maxTextLength ? value : `${value.slice(0, maxTextLength - 3)}...`;
|
|
27
|
+
const isFanoutRole = (role) => fanoutRoles.includes(role) && !defaultRolePermissions[role].edit;
|
|
28
|
+
const normalizeItems = (items, maxItems) => {
|
|
29
|
+
if (items.length === 0) {
|
|
30
|
+
throw new InputError("Fan-out requires at least one item.");
|
|
31
|
+
}
|
|
32
|
+
if (items.length > maxItems) {
|
|
33
|
+
throw new InputError(`Fan-out accepts at most ${maxItems} item(s) for this call.`);
|
|
34
|
+
}
|
|
35
|
+
return items.map((item, index) => {
|
|
36
|
+
if (!isFanoutRole(item.role)) {
|
|
37
|
+
throw new InputError(`Fan-out item ${index + 1} role must be orchestrator, planner, researcher, qa, verifier, or critic.`);
|
|
38
|
+
}
|
|
39
|
+
const brief = item.brief.trim();
|
|
40
|
+
if (!brief) {
|
|
41
|
+
throw new InputError(`Fan-out item ${index + 1} brief cannot be empty.`);
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
role: item.role,
|
|
45
|
+
brief,
|
|
46
|
+
...(item.summonKind ? { summonKind: item.summonKind } : {}),
|
|
47
|
+
...(item.persona ? { persona: item.persona } : {}),
|
|
48
|
+
...(item.agent ? { agent: item.agent } : {}),
|
|
49
|
+
constraints: item.constraints ?? [],
|
|
50
|
+
evidenceRefs: item.evidenceRefs ?? []
|
|
51
|
+
};
|
|
52
|
+
});
|
|
53
|
+
};
|
|
54
|
+
const resolveConfiguredMaxItems = (value) => {
|
|
55
|
+
if (!Number.isSafeInteger(value) || value < 1) {
|
|
56
|
+
throw new InputError("Configured defaults.fanoutMaxItems must be a positive integer.");
|
|
57
|
+
}
|
|
58
|
+
if (value > hardFanoutMaxItems) {
|
|
59
|
+
throw new InputError(`Configured defaults.fanoutMaxItems cannot exceed ${hardFanoutMaxItems}.`);
|
|
60
|
+
}
|
|
61
|
+
return value;
|
|
62
|
+
};
|
|
63
|
+
const resolveMaxItems = (value, configuredMaxItems) => {
|
|
64
|
+
const policyMaxItems = resolveConfiguredMaxItems(configuredMaxItems);
|
|
65
|
+
if (value === undefined) {
|
|
66
|
+
return policyMaxItems;
|
|
67
|
+
}
|
|
68
|
+
if (!Number.isSafeInteger(value) || value < 1) {
|
|
69
|
+
throw new InputError("Fan-out maxItems must be a positive integer.");
|
|
70
|
+
}
|
|
71
|
+
if (value > policyMaxItems) {
|
|
72
|
+
throw new InputError(`Fan-out maxItems cannot exceed configured defaults.fanoutMaxItems (${policyMaxItems}).`);
|
|
73
|
+
}
|
|
74
|
+
if (value > hardFanoutMaxItems) {
|
|
75
|
+
throw new InputError(`Fan-out maxItems cannot exceed ${hardFanoutMaxItems}.`);
|
|
76
|
+
}
|
|
77
|
+
return value;
|
|
78
|
+
};
|
|
79
|
+
const itemStatusFromResponse = (run, response) => {
|
|
80
|
+
if (run.approvalRequired || response?.status === "blocked") {
|
|
81
|
+
return "blocked";
|
|
82
|
+
}
|
|
83
|
+
if (response?.status === "failed") {
|
|
84
|
+
return "failed";
|
|
85
|
+
}
|
|
86
|
+
return "completed";
|
|
87
|
+
};
|
|
88
|
+
const resultFromSummon = (index, brief, result) => {
|
|
89
|
+
const latestResponse = result.providerResponses.at(-1);
|
|
90
|
+
const status = itemStatusFromResponse(result.run, latestResponse);
|
|
91
|
+
return {
|
|
92
|
+
index,
|
|
93
|
+
role: result.role,
|
|
94
|
+
summonKind: result.summonKind,
|
|
95
|
+
brief: truncateText(brief),
|
|
96
|
+
status,
|
|
97
|
+
stopReason: result.stopReason,
|
|
98
|
+
providerResponseCount: result.providerResponses.length,
|
|
99
|
+
assignment: result.assignment,
|
|
100
|
+
...(latestResponse ? { providerStatus: latestResponse.status } : {}),
|
|
101
|
+
...(result.directiveArtifact ? { directiveArtifact: result.directiveArtifact } : {}),
|
|
102
|
+
...(result.responseArtifact ? { responseArtifact: result.responseArtifact } : {})
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
const failedItem = (index, item, error) => {
|
|
106
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
107
|
+
return {
|
|
108
|
+
index,
|
|
109
|
+
role: item.role,
|
|
110
|
+
summonKind: item.summonKind ?? (item.role === "qa" ? "qa" : "review"),
|
|
111
|
+
brief: truncateText(item.brief),
|
|
112
|
+
status: "failed",
|
|
113
|
+
stopReason: message,
|
|
114
|
+
providerResponseCount: 0,
|
|
115
|
+
...(item.agent ? { assignment: item.agent } : {}),
|
|
116
|
+
error: message
|
|
117
|
+
};
|
|
118
|
+
};
|
|
119
|
+
const fanoutStatus = (items) => {
|
|
120
|
+
if (items.some((item) => item.status === "blocked")) {
|
|
121
|
+
return "blocked";
|
|
122
|
+
}
|
|
123
|
+
if (items.some((item) => item.status === "failed")) {
|
|
124
|
+
return "failed";
|
|
125
|
+
}
|
|
126
|
+
return "completed";
|
|
127
|
+
};
|
|
128
|
+
const artifactSummary = (artifact) => artifact
|
|
129
|
+
? {
|
|
130
|
+
kind: artifact.kind,
|
|
131
|
+
ref: artifact.ref,
|
|
132
|
+
summary: artifact.summary
|
|
133
|
+
}
|
|
134
|
+
: undefined;
|
|
135
|
+
const assignmentSummary = (assignment) => assignment
|
|
136
|
+
? {
|
|
137
|
+
provider: assignment.provider,
|
|
138
|
+
model: assignment.model
|
|
139
|
+
}
|
|
140
|
+
: undefined;
|
|
141
|
+
const itemPayload = (item) => {
|
|
142
|
+
const assignment = assignmentSummary(item.assignment);
|
|
143
|
+
const directiveArtifact = artifactSummary(item.directiveArtifact);
|
|
144
|
+
const responseArtifact = artifactSummary(item.responseArtifact);
|
|
145
|
+
return {
|
|
146
|
+
index: item.index,
|
|
147
|
+
role: item.role,
|
|
148
|
+
summonKind: item.summonKind,
|
|
149
|
+
status: item.status,
|
|
150
|
+
brief: item.brief,
|
|
151
|
+
stopReason: item.stopReason,
|
|
152
|
+
providerResponseCount: item.providerResponseCount,
|
|
153
|
+
...(item.providerStatus ? { providerStatus: item.providerStatus } : {}),
|
|
154
|
+
...(assignment ? { assignment } : {}),
|
|
155
|
+
...(directiveArtifact ? { directiveArtifact } : {}),
|
|
156
|
+
...(responseArtifact ? { responseArtifact } : {}),
|
|
157
|
+
...(item.error ? { error: item.error } : {})
|
|
158
|
+
};
|
|
159
|
+
};
|
|
160
|
+
const buildFanoutPayload = (run, status, bounds, items) => ({
|
|
161
|
+
schemaVersion: 1,
|
|
162
|
+
kind: "fanout",
|
|
163
|
+
runId: run.runId,
|
|
164
|
+
createdAt: nowIso(),
|
|
165
|
+
status,
|
|
166
|
+
bounds,
|
|
167
|
+
safety: {
|
|
168
|
+
sidecarOnly: true,
|
|
169
|
+
readOnlyRolesOnly: true,
|
|
170
|
+
canSatisfyRequiredGates: false,
|
|
171
|
+
instruction: "Fan-out evidence is advisory. It cannot satisfy verifier, runtime QA, approval, or completion gates."
|
|
172
|
+
},
|
|
173
|
+
items: items.map(itemPayload)
|
|
174
|
+
});
|
|
175
|
+
const appendFanoutArtifact = async (run, status, bounds, items) => {
|
|
176
|
+
const latest = await loadRun(run.repoPath, run.runId);
|
|
177
|
+
const payload = buildFanoutPayload(latest, status, bounds, items);
|
|
178
|
+
const artifact = await writeRunArtifact({
|
|
179
|
+
repoPath: latest.repoPath,
|
|
180
|
+
runId: latest.runId,
|
|
181
|
+
kind: "fanout",
|
|
182
|
+
name: `fanout-${newId("fanout")}.json`,
|
|
183
|
+
content: `${JSON.stringify(payload, null, 2)}\n`,
|
|
184
|
+
summary: `Agent fan-out ${status}: ${bounds.executedItems}/${bounds.requestedItems} item(s)`
|
|
185
|
+
});
|
|
186
|
+
const updated = {
|
|
187
|
+
...latest,
|
|
188
|
+
updatedAt: nowIso(),
|
|
189
|
+
artifacts: [...latest.artifacts, artifact],
|
|
190
|
+
events: [
|
|
191
|
+
...latest.events,
|
|
192
|
+
createEvent("agent_fanout_completed", artifact.summary, {
|
|
193
|
+
status,
|
|
194
|
+
artifactRef: artifact.ref,
|
|
195
|
+
requestedItems: bounds.requestedItems,
|
|
196
|
+
executedItems: bounds.executedItems,
|
|
197
|
+
maxItems: bounds.maxItems
|
|
198
|
+
})
|
|
199
|
+
]
|
|
200
|
+
};
|
|
201
|
+
await saveRun(updated);
|
|
202
|
+
return {
|
|
203
|
+
run: updated,
|
|
204
|
+
artifact
|
|
205
|
+
};
|
|
206
|
+
};
|
|
207
|
+
export const fanoutAgents = async (input) => {
|
|
208
|
+
const config = await loadConfig(input.repoPath);
|
|
209
|
+
const maxItems = resolveMaxItems(input.maxItems, config.defaults.fanoutMaxItems);
|
|
210
|
+
const items = normalizeItems(input.items, maxItems);
|
|
211
|
+
const initialRun = await loadRun(input.repoPath, input.runId);
|
|
212
|
+
if (initialRun.approvalRequired) {
|
|
213
|
+
throw new InputError(`Run ${initialRun.runId} is waiting for approval: ${initialRun.approvalReason ?? "approval required"}.`);
|
|
214
|
+
}
|
|
215
|
+
let currentRun = initialRun;
|
|
216
|
+
const results = [];
|
|
217
|
+
for (const [index, item] of items.entries()) {
|
|
218
|
+
try {
|
|
219
|
+
const result = await summonAgent({
|
|
220
|
+
repoPath: input.repoPath,
|
|
221
|
+
runId: input.runId,
|
|
222
|
+
role: item.role,
|
|
223
|
+
brief: item.brief,
|
|
224
|
+
...(item.summonKind ? { summonKind: item.summonKind } : {}),
|
|
225
|
+
...(item.persona ? { persona: item.persona } : {}),
|
|
226
|
+
...(item.agent ? { agent: item.agent } : {}),
|
|
227
|
+
constraints: item.constraints ?? [],
|
|
228
|
+
evidenceRefs: item.evidenceRefs ?? []
|
|
229
|
+
});
|
|
230
|
+
const itemResult = resultFromSummon(index, item.brief, result);
|
|
231
|
+
results.push(itemResult);
|
|
232
|
+
currentRun = result.run;
|
|
233
|
+
if (itemResult.status !== "completed" && currentRun.approvalRequired) {
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
catch (error) {
|
|
238
|
+
const itemResult = failedItem(index, item, error);
|
|
239
|
+
results.push(itemResult);
|
|
240
|
+
currentRun = await loadRun(input.repoPath, input.runId);
|
|
241
|
+
if (currentRun.approvalRequired) {
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
const status = fanoutStatus(results);
|
|
247
|
+
const bounds = {
|
|
248
|
+
requestedItems: items.length,
|
|
249
|
+
maxItems,
|
|
250
|
+
hardMaxItems: hardFanoutMaxItems,
|
|
251
|
+
executedItems: results.length,
|
|
252
|
+
execution: "sequential"
|
|
253
|
+
};
|
|
254
|
+
const appended = await appendFanoutArtifact(currentRun, status, bounds, results);
|
|
255
|
+
return {
|
|
256
|
+
run: appended.run,
|
|
257
|
+
status,
|
|
258
|
+
bounds,
|
|
259
|
+
items: results,
|
|
260
|
+
artifact: appended.artifact
|
|
261
|
+
};
|
|
262
|
+
};
|
|
263
|
+
//# sourceMappingURL=fanout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fanout.js","sourceRoot":"","sources":["../../src/runtime/fanout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AA8E3C,MAAM,WAAW,GAAkB;IACjC,cAAc;IACd,SAAS;IACT,YAAY;IACZ,IAAI;IACJ,UAAU;IACV,QAAQ;CACT,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC;AACvC,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAC7B,MAAM,aAAa,GAAG,GAAG,CAAC;AAE1B,MAAM,WAAW,GAAG,CAAC,IAAY,EAAE,OAAe,EAAE,IAAiB,EAAY,EAAE,CAAC,CAAC;IACnF,EAAE,EAAE,KAAK,CAAC,OAAO,CAAC;IAClB,SAAS,EAAE,MAAM,EAAE;IACnB,IAAI;IACJ,OAAO;IACP,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;CAC1B,CAAC,CAAC;AAEH,MAAM,YAAY,GAAG,CAAC,KAAa,EAAU,EAAE,CAC7C,KAAK,CAAC,MAAM,IAAI,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC;AAEpF,MAAM,YAAY,GAAG,CAAC,IAAiB,EAAW,EAAE,CAClD,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;AAEnE,MAAM,cAAc,GAAG,CAAC,KAAwB,EAAE,QAAgB,EAAqB,EAAE;IACvF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,UAAU,CAAC,qCAAqC,CAAC,CAAC;IAC9D,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,GAAG,QAAQ,EAAE,CAAC;QAC5B,MAAM,IAAI,UAAU,CAAC,2BAA2B,QAAQ,yBAAyB,CAAC,CAAC;IACrF,CAAC;IAED,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAC/B,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,UAAU,CAClB,gBAAgB,KAAK,GAAG,CAAC,2EAA2E,CACrG,CAAC;QACJ,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAChC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,UAAU,CAAC,gBAAgB,KAAK,GAAG,CAAC,yBAAyB,CAAC,CAAC;QAC3E,CAAC;QAED,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,KAAK;YACL,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3D,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAClD,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5C,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,EAAE;YACnC,YAAY,EAAE,IAAI,CAAC,YAAY,IAAI,EAAE;SACtC,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,yBAAyB,GAAG,CAAC,KAAa,EAAU,EAAE;IAC1D,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,UAAU,CAAC,gEAAgE,CAAC,CAAC;IACzF,CAAC;IAED,IAAI,KAAK,GAAG,kBAAkB,EAAE,CAAC;QAC/B,MAAM,IAAI,UAAU,CAAC,oDAAoD,kBAAkB,GAAG,CAAC,CAAC;IAClG,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,CAAC,KAAyB,EAAE,kBAA0B,EAAU,EAAE;IACxF,MAAM,cAAc,GAAG,yBAAyB,CAAC,kBAAkB,CAAC,CAAC;IAErE,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,cAAc,CAAC;IACxB,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,UAAU,CAAC,8CAA8C,CAAC,CAAC;IACvE,CAAC;IAED,IAAI,KAAK,GAAG,cAAc,EAAE,CAAC;QAC3B,MAAM,IAAI,UAAU,CAAC,sEAAsE,cAAc,IAAI,CAAC,CAAC;IACjH,CAAC;IAED,IAAI,KAAK,GAAG,kBAAkB,EAAE,CAAC;QAC/B,MAAM,IAAI,UAAU,CAAC,kCAAkC,kBAAkB,GAAG,CAAC,CAAC;IAChF,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,sBAAsB,GAAG,CAC7B,GAAc,EACd,QAAmC,EACjB,EAAE;IACpB,IAAI,GAAG,CAAC,gBAAgB,IAAI,QAAQ,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;QAC3D,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,QAAQ,EAAE,MAAM,KAAK,QAAQ,EAAE,CAAC;QAClC,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,OAAO,WAAW,CAAC;AACrB,CAAC,CAAC;AAEF,MAAM,gBAAgB,GAAG,CACvB,KAAa,EACb,KAAa,EACb,MAA+C,EAC7B,EAAE;IACpB,MAAM,cAAc,GAAG,MAAM,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACvD,MAAM,MAAM,GAAG,sBAAsB,CAAC,MAAM,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;IAElE,OAAO;QACL,KAAK;QACL,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC;QAC1B,MAAM;QACN,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,qBAAqB,EAAE,MAAM,CAAC,iBAAiB,CAAC,MAAM;QACtD,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,cAAc,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACpE,GAAG,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,MAAM,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACpF,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,MAAM,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAClF,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,CACjB,KAAa,EACb,IAAqB,EACrB,KAAc,EACI,EAAE;IACpB,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAEvE,OAAO;QACL,KAAK;QACL,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC;QACrE,KAAK,EAAE,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC;QAC/B,MAAM,EAAE,QAAQ;QAChB,UAAU,EAAE,OAAO;QACnB,qBAAqB,EAAE,CAAC;QACxB,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjD,KAAK,EAAE,OAAO;KACf,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,YAAY,GAAG,CAAC,KAAyB,EAAgB,EAAE;IAC/D,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,EAAE,CAAC;QACpD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,EAAE,CAAC;QACnD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,OAAO,WAAW,CAAC;AACrB,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,CAAC,QAAiC,EAA0B,EAAE,CACpF,QAAQ;IACN,CAAC,CAAC;QACE,IAAI,EAAE,QAAQ,CAAC,IAAI;QACnB,GAAG,EAAE,QAAQ,CAAC,GAAG;QACjB,OAAO,EAAE,QAAQ,CAAC,OAAO;KAC1B;IACH,CAAC,CAAC,SAAS,CAAC;AAEhB,MAAM,iBAAiB,GAAG,CAAC,UAAsC,EAA0B,EAAE,CAC3F,UAAU;IACR,CAAC,CAAC;QACE,QAAQ,EAAE,UAAU,CAAC,QAAQ;QAC7B,KAAK,EAAE,UAAU,CAAC,KAAK;KACxB;IACH,CAAC,CAAC,SAAS,CAAC;AAEhB,MAAM,WAAW,GAAG,CAAC,IAAsB,EAAc,EAAE;IACzD,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACtD,MAAM,iBAAiB,GAAG,eAAe,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAClE,MAAM,gBAAgB,GAAG,eAAe,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAEhE,OAAO;QACL,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,qBAAqB,EAAE,IAAI,CAAC,qBAAqB;QACjD,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvE,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACrC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnD,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjD,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC7C,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CACzB,GAAc,EACd,MAAoB,EACpB,MAAoB,EACpB,KAAyB,EACF,EAAE,CAAC,CAAC;IAC3B,aAAa,EAAE,CAAC;IAChB,IAAI,EAAE,QAAQ;IACd,KAAK,EAAE,GAAG,CAAC,KAAK;IAChB,SAAS,EAAE,MAAM,EAAE;IACnB,MAAM;IACN,MAAM;IACN,MAAM,EAAE;QACN,WAAW,EAAE,IAAI;QACjB,iBAAiB,EAAE,IAAI;QACvB,uBAAuB,EAAE,KAAK;QAC9B,WAAW,EAAE,sGAAsG;KACpH;IACD,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC;CAC9B,CAAC,CAAC;AAEH,MAAM,oBAAoB,GAAG,KAAK,EAChC,GAAc,EACd,MAAoB,EACpB,MAAoB,EACpB,KAAyB,EAC2B,EAAE;IACtD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;IACtD,MAAM,OAAO,GAAG,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;IAClE,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC;QACtC,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,UAAU,KAAK,CAAC,QAAQ,CAAC,OAAO;QACtC,OAAO,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI;QAChD,OAAO,EAAE,iBAAiB,MAAM,KAAK,MAAM,CAAC,aAAa,IAAI,MAAM,CAAC,cAAc,UAAU;KAC7F,CAAC,CAAC;IACH,MAAM,OAAO,GAAc;QACzB,GAAG,MAAM;QACT,SAAS,EAAE,MAAM,EAAE;QACnB,SAAS,EAAE,CAAC,GAAG,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC;QAC1C,MAAM,EAAE;YACN,GAAG,MAAM,CAAC,MAAM;YAChB,WAAW,CAAC,wBAAwB,EAAE,QAAQ,CAAC,OAAO,EAAE;gBACtD,MAAM;gBACN,WAAW,EAAE,QAAQ,CAAC,GAAG;gBACzB,cAAc,EAAE,MAAM,CAAC,cAAc;gBACrC,aAAa,EAAE,MAAM,CAAC,aAAa;gBACnC,QAAQ,EAAE,MAAM,CAAC,QAAQ;aAC1B,CAAC;SACH;KACF,CAAC;IAEF,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAEvB,OAAO;QACL,GAAG,EAAE,OAAO;QACZ,QAAQ;KACT,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,EAAE,KAAwB,EAA+B,EAAE;IAC1F,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAChD,MAAM,QAAQ,GAAG,eAAe,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;IACjF,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACpD,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAE9D,IAAI,UAAU,CAAC,gBAAgB,EAAE,CAAC;QAChC,MAAM,IAAI,UAAU,CAClB,OAAO,UAAU,CAAC,KAAK,6BAA6B,UAAU,CAAC,cAAc,IAAI,mBAAmB,GAAG,CACxG,CAAC;IACJ,CAAC;IAED,IAAI,UAAU,GAAG,UAAU,CAAC;IAC5B,MAAM,OAAO,GAAuB,EAAE,CAAC;IAEvC,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;QAC5C,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC;gBAC/B,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC3D,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAClD,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC5C,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,EAAE;gBACnC,YAAY,EAAE,IAAI,CAAC,YAAY,IAAI,EAAE;aACtC,CAAC,CAAC;YACH,MAAM,UAAU,GAAG,gBAAgB,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;YAC/D,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACzB,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC;YAExB,IAAI,UAAU,CAAC,MAAM,KAAK,WAAW,IAAI,UAAU,CAAC,gBAAgB,EAAE,CAAC;gBACrE,MAAM;YACR,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,UAAU,GAAG,UAAU,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;YAClD,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACzB,UAAU,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;YAExD,IAAI,UAAU,CAAC,gBAAgB,EAAE,CAAC;gBAChC,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IACrC,MAAM,MAAM,GAAiB;QAC3B,cAAc,EAAE,KAAK,CAAC,MAAM;QAC5B,QAAQ;QACR,YAAY,EAAE,kBAAkB;QAChC,aAAa,EAAE,OAAO,CAAC,MAAM;QAC7B,SAAS,EAAE,YAAY;KACxB,CAAC;IACF,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAEjF,OAAO;QACL,GAAG,EAAE,QAAQ,CAAC,GAAG;QACjB,MAAM;QACN,MAAM;QACN,KAAK,EAAE,OAAO;QACd,QAAQ,EAAE,QAAQ,CAAC,QAAQ;KAC5B,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type ProtectedPathMatch } from "./protectedPaths.js";
|
|
2
|
+
import type { RunArtifact, RunRecord } from "./types.js";
|
|
3
|
+
export interface GitEvidenceResult {
|
|
4
|
+
run: RunRecord;
|
|
5
|
+
changedPaths: string[];
|
|
6
|
+
protectedChanges: ProtectedPathMatch[];
|
|
7
|
+
artifacts: RunArtifact[];
|
|
8
|
+
}
|
|
9
|
+
export declare const parseGitStatusPaths: (stdout: string) => string[];
|
|
10
|
+
export declare const captureGitEvidence: (repoPathInput: string, runId: string) => Promise<GitEvidenceResult>;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { writeRunArtifact } from "./artifacts.js";
|
|
2
|
+
import { runRuntimeCommand } from "./commandRunner.js";
|
|
3
|
+
import { loadConfig } from "./config.js";
|
|
4
|
+
import { newId, nowIso } from "./ids.js";
|
|
5
|
+
import { findProtectedPathMatches } from "./protectedPaths.js";
|
|
6
|
+
import { resolveRepoPath } from "./paths.js";
|
|
7
|
+
import { loadRun, saveRun } from "./store.js";
|
|
8
|
+
const parseStatusPath = (line) => {
|
|
9
|
+
const payload = line.slice(3).trim();
|
|
10
|
+
if (!payload)
|
|
11
|
+
return [];
|
|
12
|
+
if (payload.includes(" -> ")) {
|
|
13
|
+
return payload.split(" -> ").map((value) => value.trim()).filter(Boolean);
|
|
14
|
+
}
|
|
15
|
+
return [payload.replace(/^"|"$/g, "")];
|
|
16
|
+
};
|
|
17
|
+
export const parseGitStatusPaths = (stdout) => Array.from(new Set(stdout
|
|
18
|
+
.split("\n")
|
|
19
|
+
.filter((line) => line.trim().length > 0)
|
|
20
|
+
.flatMap(parseStatusPath))).sort((left, right) => left.localeCompare(right));
|
|
21
|
+
export const captureGitEvidence = async (repoPathInput, runId) => {
|
|
22
|
+
const repoPath = resolveRepoPath(repoPathInput);
|
|
23
|
+
const config = await loadConfig(repoPath);
|
|
24
|
+
const statusResult = await runRuntimeCommand({
|
|
25
|
+
repoPath,
|
|
26
|
+
runId,
|
|
27
|
+
tool: "git_status",
|
|
28
|
+
command: "git",
|
|
29
|
+
args: ["status", "--short", "--untracked-files=all", "--", ".", ":(exclude).thehood"]
|
|
30
|
+
});
|
|
31
|
+
const diffResult = await runRuntimeCommand({
|
|
32
|
+
repoPath,
|
|
33
|
+
runId,
|
|
34
|
+
tool: "git_diff",
|
|
35
|
+
command: "git",
|
|
36
|
+
args: ["diff", "--no-ext-diff", "--", ".", ":(exclude).thehood"]
|
|
37
|
+
});
|
|
38
|
+
const changedPaths = parseGitStatusPaths(statusResult.stdout);
|
|
39
|
+
const protectedChanges = findProtectedPathMatches(changedPaths, config.defaults.protectedTestPaths);
|
|
40
|
+
const summaryArtifact = await writeRunArtifact({
|
|
41
|
+
repoPath,
|
|
42
|
+
runId,
|
|
43
|
+
kind: "metadata",
|
|
44
|
+
name: "git-evidence-summary.json",
|
|
45
|
+
content: `${JSON.stringify({
|
|
46
|
+
changedPaths,
|
|
47
|
+
protectedChanges,
|
|
48
|
+
statusRef: statusResult.event.stdoutRef,
|
|
49
|
+
diffRef: diffResult.event.stdoutRef
|
|
50
|
+
}, null, 2)}\n`,
|
|
51
|
+
summary: `Git evidence summary for ${changedPaths.length} changed path(s).`
|
|
52
|
+
});
|
|
53
|
+
const run = await loadRun(repoPath, runId);
|
|
54
|
+
const updated = {
|
|
55
|
+
...run,
|
|
56
|
+
updatedAt: nowIso(),
|
|
57
|
+
artifacts: [...run.artifacts, summaryArtifact],
|
|
58
|
+
events: [
|
|
59
|
+
...run.events,
|
|
60
|
+
{
|
|
61
|
+
id: newId("event"),
|
|
62
|
+
createdAt: nowIso(),
|
|
63
|
+
type: "git_evidence_captured",
|
|
64
|
+
message: `Captured git evidence for ${changedPaths.length} changed path(s).`,
|
|
65
|
+
data: {
|
|
66
|
+
changedPathCount: changedPaths.length,
|
|
67
|
+
protectedChangeCount: protectedChanges.length
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
};
|
|
72
|
+
await saveRun(updated);
|
|
73
|
+
return {
|
|
74
|
+
run: updated,
|
|
75
|
+
changedPaths,
|
|
76
|
+
protectedChanges,
|
|
77
|
+
artifacts: [summaryArtifact]
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
//# sourceMappingURL=gitEvidence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gitEvidence.js","sourceRoot":"","sources":["../../src/runtime/gitEvidence.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { RunHandoffEvent, RunHandoffKind, RunRecord, RunState, RuntimeRole } from "./types.js";
|
|
2
|
+
export interface CreateRunHandoffInput {
|
|
3
|
+
kind: RunHandoffKind;
|
|
4
|
+
reason: string;
|
|
5
|
+
stateAfter: RunState;
|
|
6
|
+
fromRole?: RuntimeRole | undefined;
|
|
7
|
+
toRole?: RuntimeRole | undefined;
|
|
8
|
+
gate?: string | undefined;
|
|
9
|
+
approvalEventId?: string | undefined;
|
|
10
|
+
artifactRefs?: string[] | undefined;
|
|
11
|
+
}
|
|
12
|
+
export interface RunHandoffSummary {
|
|
13
|
+
id: string;
|
|
14
|
+
createdAt: string;
|
|
15
|
+
kind: RunHandoffKind;
|
|
16
|
+
reason: string;
|
|
17
|
+
stateBefore: RunState;
|
|
18
|
+
stateAfter: RunState;
|
|
19
|
+
fromLabel?: string;
|
|
20
|
+
fromAssignment?: string;
|
|
21
|
+
toLabel?: string;
|
|
22
|
+
toAssignment?: string;
|
|
23
|
+
gate?: string;
|
|
24
|
+
artifactRefs?: string[];
|
|
25
|
+
}
|
|
26
|
+
export declare const roleLaneLabel: (role: RuntimeRole) => string;
|
|
27
|
+
export declare const createRunHandoff: (run: RunRecord, input: CreateRunHandoffInput) => RunHandoffEvent;
|
|
28
|
+
export declare const appendRunHandoffs: (run: RunRecord, handoffs: RunHandoffEvent[]) => RunRecord;
|
|
29
|
+
export declare const latestRunHandoff: (run: RunRecord) => RunHandoffEvent | undefined;
|
|
30
|
+
export declare const recentRunHandoffs: (run: RunRecord, limit: number) => RunHandoffEvent[];
|
|
31
|
+
export declare const summarizeRunHandoff: (handoff: RunHandoffEvent) => RunHandoffSummary;
|
|
32
|
+
export declare const recentRunHandoffSummaries: (run: RunRecord, limit: number) => RunHandoffSummary[];
|