@cassiomc1/forgeloop 1.3.0 → 1.6.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/.github/copilot-instructions.md +1 -0
- package/AGENTS.md +1 -0
- package/CLAUDE.md +1 -0
- package/DOCS_INDEX.md +20 -8
- package/EXECUTION_STATE.md +60 -0
- package/LOOP_ENGINEERING.md +135 -5
- package/LOOP_SYSTEM_DESIGN.md +54 -1
- package/PROTOCOL_INTEGRATION.md +87 -0
- package/QUALITY_SCORECARD.md +2 -0
- package/README.md +69 -9
- package/TERMINOLOGY.md +15 -0
- package/THIRD_PARTY_NOTICES.md +30 -0
- package/THREAT_MODEL.md +59 -1
- package/docs/ARTIFACT_REFERENCE.md +183 -0
- package/docs/CLI_REFERENCE.md +391 -6
- package/docs/CROSS_HARNESS_CONTINUITY.md +23 -0
- package/docs/DIAGNOSTIC_MODEL.md +181 -0
- package/docs/DOCUMENTATION_GUIDE.md +36 -13
- package/docs/EXECUTION_TRACE.md +76 -0
- package/docs/GETTING_STARTED.md +1 -0
- package/docs/MCP.md +159 -0
- package/docs/RECIPES.md +149 -0
- package/docs/RELEASE_CHECKLIST_1_4.md +38 -0
- package/docs/RELEASE_CHECKLIST_1_5_MCP.md +78 -0
- package/docs/TROUBLESHOOTING.md +217 -3
- package/docs/UNIVERSAL_INTEGRATION.md +48 -0
- package/docs/assets/diagrams/forgeloop-engineering-flow.html +13797 -0
- package/docs/assets/diagrams/forgeloop-engineering-flow.receipt.json +37 -0
- package/docs/assets/diagrams/forgeloop-engineering-flow.svg +5002 -0
- package/docs/diagrams/README.md +55 -0
- package/docs/diagrams/forgeloop-engineering-flow.workflow.json +122 -0
- package/docs/diagrams/manifest.json +42 -0
- package/docs/diagrams/reviews/forgeloop-engineering-flow.review.json +20 -0
- package/package.json +21 -8
- package/schemas/action.schema.json +100 -0
- package/schemas/approval.schema.json +51 -0
- package/schemas/capability-policy.schema.json +41 -0
- package/schemas/diagnostic-case.schema.json +85 -0
- package/schemas/execution-receipt.schema.json +16 -0
- package/schemas/hypothesis-disposition.schema.json +16 -0
- package/schemas/intervention.schema.json +27 -0
- package/schemas/policy-lock.schema.json +1 -0
- package/schemas/policy-snapshot.schema.json +2 -0
- package/schemas/task-recovery.schema.json +61 -0
- package/schemas/trajectory-evaluation.schema.json +64 -0
- package/schemas/trajectory-scenario.schema.json +42 -0
- package/src/cli.js +267 -347
- package/src/commands/action-authorize.js +41 -0
- package/src/commands/action-propose.js +10 -0
- package/src/commands/action-reconcile.js +10 -0
- package/src/commands/action-record.js +47 -0
- package/src/commands/action-show.js +10 -0
- package/src/commands/action-verify.js +10 -0
- package/src/commands/advance.js +7 -2
- package/src/commands/approval-request.js +64 -0
- package/src/commands/approval-resolve.js +10 -0
- package/src/commands/audit.js +5 -0
- package/src/commands/baseline.js +3 -3
- package/src/commands/eval.js +6 -0
- package/src/commands/history.js +18 -0
- package/src/commands/init.js +2 -2
- package/src/commands/inspect.js +55 -0
- package/src/commands/metrics.js +7 -0
- package/src/commands/next.js +8 -2
- package/src/commands/policy-discover.js +2 -2
- package/src/commands/progress.js +6 -2
- package/src/commands/record-diagnosis.js +37 -1
- package/src/commands/record-hypothesis-disposition.js +45 -0
- package/src/commands/record-intervention.js +35 -0
- package/src/commands/reflect.js +38 -0
- package/src/commands/report.js +9 -1
- package/src/commands/run-action.js +18 -0
- package/src/commands/status.js +17 -0
- package/src/commands/task-create.js +39 -1
- package/src/commands/task-list.js +14 -1
- package/src/commands/task-lock-status.js +2 -2
- package/src/commands/task-recover.js +202 -0
- package/src/commands/task-repair-legacy-recovery.js +417 -0
- package/src/commands/task-resume.js +172 -0
- package/src/commands/task-scope.js +23 -4
- package/src/commands/task-show.js +18 -4
- package/src/commands/trace.js +34 -0
- package/src/commands/validate-protocol.js +40 -15
- package/src/core/action-authorization.js +106 -0
- package/src/core/action-constants.js +86 -0
- package/src/core/action-execution.js +105 -0
- package/src/core/action-ledger-projection.js +302 -0
- package/src/core/action-model.js +581 -0
- package/src/core/action-readiness.js +141 -0
- package/src/core/action-reconciliation-policy.js +49 -0
- package/src/core/action-reconciliation.js +66 -0
- package/src/core/action-verification.js +111 -0
- package/src/core/actions.js +462 -0
- package/src/core/approvals.js +405 -0
- package/src/core/artifact-registry.js +60 -0
- package/src/core/audit.js +45 -4
- package/src/core/bundles.js +30 -0
- package/src/core/capability-policy.js +226 -0
- package/src/core/cli-command-definitions.js +260 -5
- package/src/core/command-executors.js +543 -0
- package/src/core/command-input.js +107 -0
- package/src/core/command-runtime.js +117 -0
- package/src/core/completion-artifacts.js +39 -15
- package/src/core/completion-ownership.js +88 -0
- package/src/core/completion-recovery-rebind.js +194 -0
- package/src/core/completion.js +70 -0
- package/src/core/continuity-reconciliation.js +24 -5
- package/src/core/diagnostic-model.js +396 -0
- package/src/core/diagnostic-projection.js +51 -0
- package/src/core/diagnostic-record.js +360 -0
- package/src/core/error-codes.js +461 -1
- package/src/core/events.js +171 -2
- package/src/core/execution-prerequisites.js +4 -1
- package/src/core/execution.js +26 -188
- package/src/core/failure-signature.js +70 -0
- package/src/core/failure-surface.js +57 -0
- package/src/core/filesystem.js +55 -6
- package/src/core/history.js +110 -0
- package/src/core/hypothesis-projection.js +85 -0
- package/src/core/information-gain-projection.js +283 -0
- package/src/core/information-gain.js +138 -0
- package/src/core/inspect.js +132 -7
- package/src/core/integration-invocation-policy.js +217 -0
- package/src/core/integration-limits.js +20 -0
- package/src/core/integration-resources.js +178 -0
- package/src/core/next-action-model.js +94 -0
- package/src/core/next-action.js +490 -3
- package/src/core/phase.js +42 -22
- package/src/core/policy-engine.js +113 -6
- package/src/core/preflight-consistency.js +31 -5
- package/src/core/preflight.js +19 -2
- package/src/core/prepared-execution.js +227 -0
- package/src/core/progress.js +41 -4
- package/src/core/project-root.js +21 -0
- package/src/core/protocol-info.js +61 -0
- package/src/core/protocol.js +14 -0
- package/src/core/receipt.js +1 -0
- package/src/core/reconcile-closure.js +35 -10
- package/src/core/recovery-history.js +116 -0
- package/src/core/reflection.js +305 -0
- package/src/core/resumability.js +57 -3
- package/src/core/schema-validation.js +9 -0
- package/src/core/strategy-analysis.js +97 -0
- package/src/core/task-claim-state.js +272 -0
- package/src/core/task-command.js +5 -1
- package/src/core/task-conflict-inspection.js +321 -0
- package/src/core/task-context.js +32 -29
- package/src/core/task-discovery.js +14 -1
- package/src/core/task-lock.js +216 -22
- package/src/core/task-paths.js +31 -2
- package/src/core/task-recovery-migration.js +192 -0
- package/src/core/task-recovery.js +205 -0
- package/src/core/task-scope.js +33 -1
- package/src/core/task-snapshot.js +53 -0
- package/src/core/templates.js +9 -0
- package/src/core/trace.js +548 -0
- package/src/core/trajectory-evaluation.js +71 -0
- package/src/core/trajectory-metrics.js +80 -0
- package/src/core/transaction.js +36 -2
- package/src/core/work-state.js +10 -5
- package/src/integration.js +47 -0
- package/docs/assets/forgeloop-flow.svg +0 -1
- package/docs/forgeloop-flow.mmd +0 -51
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { runProtocolInfo } from "../commands/protocol-info.js";
|
|
3
|
+
import { readContract } from "./contract.js";
|
|
4
|
+
import { discoverTasks } from "./task-discovery.js";
|
|
5
|
+
import { resolveTaskClaimState } from "./task-claim-state.js";
|
|
6
|
+
import { runStatus } from "../commands/status.js";
|
|
7
|
+
import { runContinuity } from "../commands/continuity.js";
|
|
8
|
+
import { listActions, readAction } from "./actions.js";
|
|
9
|
+
import { listApprovals } from "./approvals.js";
|
|
10
|
+
import { buildTrajectoryMetrics } from "./trajectory-metrics.js";
|
|
11
|
+
import { loadCapabilityPolicy } from "./capability-policy.js";
|
|
12
|
+
import { readdir } from "node:fs/promises";
|
|
13
|
+
import { readJsonArtifact } from "./artifacts.js";
|
|
14
|
+
import { taskDirectory } from "./task-paths.js";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Canonical integration resource allowlist.
|
|
18
|
+
*
|
|
19
|
+
* This is NOT a replacement for ARTIFACT_REGISTRY: the artifact registry
|
|
20
|
+
* describes persisted protocol artifacts; this registry describes what is
|
|
21
|
+
* safe to expose through structured integrations. Anything not listed here
|
|
22
|
+
* must never be readable through an integration transport.
|
|
23
|
+
*
|
|
24
|
+
* task/ownership is derived exclusively from resolveTaskClaimState() — the
|
|
25
|
+
* canonical claim resolver. Integrations must present these values; they
|
|
26
|
+
* must never derive them from raw artifacts such as task.json or
|
|
27
|
+
* recovery.json.
|
|
28
|
+
*/
|
|
29
|
+
export const INTEGRATION_RESOURCE_DEFINITIONS = Object.freeze({
|
|
30
|
+
"protocol/info": Object.freeze({
|
|
31
|
+
scope: "PROJECT",
|
|
32
|
+
description: "ForgeLoop protocol version, schema compatibility, features, and command metadata.",
|
|
33
|
+
}),
|
|
34
|
+
"project/tasks": Object.freeze({
|
|
35
|
+
scope: "PROJECT",
|
|
36
|
+
description: "All discovered tasks with canonical ownership projection fields.",
|
|
37
|
+
}),
|
|
38
|
+
"task/status": Object.freeze({
|
|
39
|
+
scope: "TASK",
|
|
40
|
+
description: "Canonical status projection for one task, including ownership fields.",
|
|
41
|
+
}),
|
|
42
|
+
"task/ownership": Object.freeze({
|
|
43
|
+
scope: "TASK",
|
|
44
|
+
description: "Canonical validated claim ownership for one task.",
|
|
45
|
+
}),
|
|
46
|
+
"task/contract": Object.freeze({
|
|
47
|
+
scope: "TASK",
|
|
48
|
+
description: "The task's current contract.",
|
|
49
|
+
}),
|
|
50
|
+
"task/continuity": Object.freeze({
|
|
51
|
+
scope: "TASK",
|
|
52
|
+
description: "Cross-harness continuity state for one task.",
|
|
53
|
+
}),
|
|
54
|
+
"task/actions": Object.freeze({ scope: "TASK", description: "Canonical durable action summaries for one task." }),
|
|
55
|
+
"task/action": Object.freeze({ scope: "TASK", description: "One canonical durable action artifact." }),
|
|
56
|
+
"task/approvals": Object.freeze({ scope: "TASK", description: "Durable approval artifacts for one task." }),
|
|
57
|
+
"task/metrics": Object.freeze({ scope: "TASK", description: "Read-only trajectory metrics for one task." }),
|
|
58
|
+
"task/evaluations": Object.freeze({ scope: "TASK", description: "Persisted trajectory evaluations for one task." }),
|
|
59
|
+
"project/capability-policy": Object.freeze({ scope: "PROJECT", description: "Project capability policy, never host authority." }),
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
function ownershipProjection(projection) {
|
|
63
|
+
return {
|
|
64
|
+
taskId: projection.taskId,
|
|
65
|
+
phase: projection.phase,
|
|
66
|
+
claimState: projection.claimState,
|
|
67
|
+
mutationAllowed: projection.mutationAllowed,
|
|
68
|
+
ownershipValid: projection.ownershipValid,
|
|
69
|
+
recoveryStatus: projection.recoveryStatus,
|
|
70
|
+
historicalWriteClaims: [...projection.historicalWriteClaims],
|
|
71
|
+
effectiveWriteClaims: [...projection.effectiveWriteClaims],
|
|
72
|
+
reasonCodes: [...projection.reasonCodes],
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export async function readForgeLoopIntegrationResource(uri, {
|
|
77
|
+
projectPath = ".",
|
|
78
|
+
packageRoot = undefined,
|
|
79
|
+
packageVersion = null,
|
|
80
|
+
taskId = null,
|
|
81
|
+
actionId = null,
|
|
82
|
+
} = {}) {
|
|
83
|
+
const resource = INTEGRATION_RESOURCE_DEFINITIONS[uri];
|
|
84
|
+
if (!resource) {
|
|
85
|
+
const error = new Error(`Unknown ForgeLoop integration resource: ${uri}`);
|
|
86
|
+
error.code = "E_INTEGRATION_RESOURCE_UNKNOWN";
|
|
87
|
+
throw error;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
switch (uri) {
|
|
91
|
+
case "protocol/info": {
|
|
92
|
+
return { uri, data: await runProtocolInfo({ packageVersion }) };
|
|
93
|
+
}
|
|
94
|
+
case "project/tasks": {
|
|
95
|
+
const tasks = await discoverTasks(projectPath, packageRoot);
|
|
96
|
+
return {
|
|
97
|
+
uri,
|
|
98
|
+
data: {
|
|
99
|
+
count: tasks.length,
|
|
100
|
+
tasks: tasks.map((task) => ({
|
|
101
|
+
taskId: task.taskId,
|
|
102
|
+
healthy: task.healthy !== false,
|
|
103
|
+
phase: task.phase ?? null,
|
|
104
|
+
mutationAllowed: task.mutationAllowed !== false,
|
|
105
|
+
})),
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
case "task/status":
|
|
110
|
+
case "task/ownership":
|
|
111
|
+
case "task/contract":
|
|
112
|
+
case "task/continuity": {
|
|
113
|
+
if (typeof taskId !== "string" || !taskId) {
|
|
114
|
+
const error = new Error(`Resource ${uri} requires a taskId`);
|
|
115
|
+
error.code = "E_TASK_REQUIRED";
|
|
116
|
+
throw error;
|
|
117
|
+
}
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
case "task/actions":
|
|
121
|
+
case "task/action":
|
|
122
|
+
case "task/approvals":
|
|
123
|
+
case "task/metrics":
|
|
124
|
+
case "task/evaluations": {
|
|
125
|
+
if (typeof taskId !== "string" || !taskId) {
|
|
126
|
+
const error = new Error(`Resource ${uri} requires a taskId`); error.code = "E_TASK_REQUIRED"; throw error;
|
|
127
|
+
}
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (uri === "task/ownership") {
|
|
133
|
+
const projection = await resolveTaskClaimState(projectPath, { taskId, packageRoot });
|
|
134
|
+
return { uri, taskId, data: ownershipProjection(projection) };
|
|
135
|
+
}
|
|
136
|
+
if (uri === "task/actions") {
|
|
137
|
+
const actions = await listActions(projectPath, { packageRoot, taskId });
|
|
138
|
+
return { uri, taskId, data: { actions } };
|
|
139
|
+
}
|
|
140
|
+
if (uri === "task/action") {
|
|
141
|
+
if (!actionId) { const error = new Error("Resource task/action requires actionId"); error.code = "E_ACTION_INVALID"; throw error; }
|
|
142
|
+
return { uri, taskId, data: await readAction(projectPath, { packageRoot, taskId, actionId }) };
|
|
143
|
+
}
|
|
144
|
+
if (uri === "task/approvals") {
|
|
145
|
+
return { uri, taskId, data: { approvals: await listApprovals(projectPath, { packageRoot, taskId }) } };
|
|
146
|
+
}
|
|
147
|
+
if (uri === "task/metrics") {
|
|
148
|
+
return { uri, taskId, data: await buildTrajectoryMetrics({ target: projectPath, packageRoot, taskId }) };
|
|
149
|
+
}
|
|
150
|
+
if (uri === "task/evaluations") {
|
|
151
|
+
const dir = path.join(projectPath, taskDirectory(taskId), "evaluations");
|
|
152
|
+
let names = []; try { names = await readdir(dir); } catch { /* absent is an empty projection */ }
|
|
153
|
+
const evaluations = [];
|
|
154
|
+
for (const name of names.filter((entry) => /^eval-[A-Za-z0-9_-]+\.json$/.test(entry)).sort()) {
|
|
155
|
+
evaluations.push((await readJsonArtifact(projectPath, `${taskDirectory(taskId)}/evaluations/${name}`, "trajectory-evaluation", packageRoot)).value);
|
|
156
|
+
}
|
|
157
|
+
return { uri, taskId, data: { evaluations } };
|
|
158
|
+
}
|
|
159
|
+
if (uri === "project/capability-policy") {
|
|
160
|
+
return { uri, data: await loadCapabilityPolicy(projectPath, packageRoot) };
|
|
161
|
+
}
|
|
162
|
+
if (uri === "task/status") {
|
|
163
|
+
const result = await runStatus({ target: projectPath, packageRoot, taskId });
|
|
164
|
+
return { uri, taskId, data: result };
|
|
165
|
+
}
|
|
166
|
+
if (uri === "task/contract") {
|
|
167
|
+
try {
|
|
168
|
+
const contract = await readContract(projectPath, packageRoot, { taskId });
|
|
169
|
+
return { uri, taskId, data: contract.value };
|
|
170
|
+
} catch (error) {
|
|
171
|
+
error.message = `Resource task/contract unavailable: ${error.message}`;
|
|
172
|
+
throw error;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
// task/continuity
|
|
176
|
+
const continuity = await runContinuity({ target: projectPath, packageRoot, taskId });
|
|
177
|
+
return { uri, taskId, data: continuity };
|
|
178
|
+
}
|
|
@@ -16,6 +16,9 @@ export const NEXT_ACTIONS = Object.freeze({
|
|
|
16
16
|
RECORD_DIAGNOSIS: "RECORD_DIAGNOSIS",
|
|
17
17
|
CORRECT: "CORRECT",
|
|
18
18
|
CHANGE_STRATEGY: "CHANGE_STRATEGY",
|
|
19
|
+
REQUIRE_NEW_DIAGNOSTIC_INFORMATION: "REQUIRE_NEW_DIAGNOSTIC_INFORMATION",
|
|
20
|
+
INTRODUCE_NEW_OBSERVATION: "INTRODUCE_NEW_OBSERVATION",
|
|
21
|
+
RECORD_INTERVENTION: "RECORD_INTERVENTION",
|
|
19
22
|
ENTER_REVIEWING: "ENTER_REVIEWING",
|
|
20
23
|
RECORD_TERMINAL_RESULT: "RECORD_TERMINAL_RESULT",
|
|
21
24
|
PREPARE_COMPLETION: "PREPARE_COMPLETION",
|
|
@@ -31,9 +34,74 @@ export const NEXT_ACTIONS = Object.freeze({
|
|
|
31
34
|
REPAIR_POLICY: "REPAIR_POLICY",
|
|
32
35
|
RESTORE_BASELINE: "RESTORE_BASELINE",
|
|
33
36
|
CONTINUE_WITH_EXISTING_BASELINE: "CONTINUE_WITH_EXISTING_BASELINE",
|
|
37
|
+
RECONCILE_CLOSURE: "RECONCILE_CLOSURE",
|
|
38
|
+
RECONCILE_ACTION: "RECONCILE_ACTION",
|
|
39
|
+
AUTHORIZE_ACTION: "AUTHORIZE_ACTION",
|
|
40
|
+
REQUEST_ACTION_APPROVAL: "REQUEST_ACTION_APPROVAL",
|
|
41
|
+
RESOLVE_ACTION_APPROVAL: "RESOLVE_ACTION_APPROVAL",
|
|
42
|
+
VERIFY_EXTERNAL_ACTION: "VERIFY_EXTERNAL_ACTION",
|
|
43
|
+
RECOVER_TASK: "RECOVER_TASK",
|
|
44
|
+
RESUME_RECOVERED_TASK: "RESUME_RECOVERED_TASK",
|
|
45
|
+
RESOLVE_RECOVERY_INCONSISTENCY: "RESOLVE_RECOVERY_INCONSISTENCY",
|
|
34
46
|
NONE: "NONE",
|
|
35
47
|
});
|
|
36
48
|
|
|
49
|
+
export function directCommandSpec(commandId, taskId, requiredInputs = []) {
|
|
50
|
+
return {
|
|
51
|
+
commandId,
|
|
52
|
+
executable: "forgeloop",
|
|
53
|
+
subcommand: commandId,
|
|
54
|
+
argv: [commandId, `--task=${taskId}`, "--json"],
|
|
55
|
+
requiredInputs,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function recoveryGuidanceForClassification(classification, taskId) {
|
|
60
|
+
if (classification === "RECOVERABLE") {
|
|
61
|
+
return {
|
|
62
|
+
nextAction: NEXT_ACTIONS.RECONCILE_CLOSURE,
|
|
63
|
+
commands: ["forgeloop reconcile-closure --task <id>"],
|
|
64
|
+
commandSpecs: [directCommandSpec("reconcile-closure", taskId, [
|
|
65
|
+
{ name: "checkId", option: "--id=<contract-verification-id>" },
|
|
66
|
+
{ name: "requirement", option: "--requirement=<exact-contract-verification-text>" },
|
|
67
|
+
{ name: "command", option: "-- <verification-command...>" },
|
|
68
|
+
])],
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
if (classification === "STALE" || classification === "ABANDONED") {
|
|
72
|
+
return {
|
|
73
|
+
nextAction: NEXT_ACTIONS.RECOVER_TASK,
|
|
74
|
+
commands: ["forgeloop task-recover --task <id> --acknowledge-recovery --json"],
|
|
75
|
+
commandSpecs: [directCommandSpec("task-recover", taskId, [
|
|
76
|
+
{
|
|
77
|
+
name: "acknowledgeRecovery",
|
|
78
|
+
option: "--acknowledge-recovery",
|
|
79
|
+
description: "Caller acknowledgement only; not host-attested authority.",
|
|
80
|
+
},
|
|
81
|
+
])],
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
if (classification === "RECOVERED") {
|
|
85
|
+
return {
|
|
86
|
+
nextAction: NEXT_ACTIONS.RESUME_RECOVERED_TASK,
|
|
87
|
+
commands: ["forgeloop task-resume --task <id> --json"],
|
|
88
|
+
commandSpecs: [directCommandSpec("task-resume", taskId)],
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
if (classification === "INCONSISTENT") {
|
|
92
|
+
return {
|
|
93
|
+
nextAction: NEXT_ACTIONS.RESOLVE_RECOVERY_INCONSISTENCY,
|
|
94
|
+
commands: ["forgeloop validate-protocol --task <id> --json"],
|
|
95
|
+
commandSpecs: [directCommandSpec("validate-protocol", taskId)],
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
nextAction: NEXT_ACTIONS.RESOLVE_BLOCKER,
|
|
100
|
+
commands: ["forgeloop task-show --task <id> --json"],
|
|
101
|
+
commandSpecs: [directCommandSpec("task-show", taskId)],
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
37
105
|
export function result({
|
|
38
106
|
taskId = "unknown",
|
|
39
107
|
currentPhase = "RECEIVED",
|
|
@@ -44,6 +112,12 @@ export function result({
|
|
|
44
112
|
requiredArtifacts = [],
|
|
45
113
|
missingArtifacts = [],
|
|
46
114
|
progress = undefined,
|
|
115
|
+
diagnosticGuidance = undefined,
|
|
116
|
+
authorityRequired = undefined,
|
|
117
|
+
hostActionRequired = undefined,
|
|
118
|
+
approvalRequired = undefined,
|
|
119
|
+
capabilityDecision = undefined,
|
|
120
|
+
reconciliationAuthorityRequired = undefined,
|
|
47
121
|
}) {
|
|
48
122
|
const normalizedReasons = reasons
|
|
49
123
|
.map((reason) => {
|
|
@@ -76,6 +150,14 @@ export function result({
|
|
|
76
150
|
requiredArtifacts: uniqueSorted(requiredArtifacts),
|
|
77
151
|
missingArtifacts: uniqueSorted(missingArtifacts),
|
|
78
152
|
...(progress ? { progress: structuredClone(progress) } : {}),
|
|
153
|
+
...(diagnosticGuidance ? { diagnosticGuidance: structuredClone(diagnosticGuidance) } : {}),
|
|
154
|
+
...(authorityRequired ? { authorityRequired: structuredClone(authorityRequired) } : {}),
|
|
155
|
+
...(hostActionRequired ? { hostActionRequired: structuredClone(hostActionRequired) } : {}),
|
|
156
|
+
...(approvalRequired ? { approvalRequired: structuredClone(approvalRequired) } : {}),
|
|
157
|
+
...(capabilityDecision ? { capabilityDecision: structuredClone(capabilityDecision) } : {}),
|
|
158
|
+
...(reconciliationAuthorityRequired
|
|
159
|
+
? { reconciliationAuthorityRequired: structuredClone(reconciliationAuthorityRequired) }
|
|
160
|
+
: {}),
|
|
79
161
|
};
|
|
80
162
|
}
|
|
81
163
|
|
|
@@ -126,6 +208,18 @@ export function recordDiagnosisCommandSpec() {
|
|
|
126
208
|
};
|
|
127
209
|
}
|
|
128
210
|
|
|
211
|
+
export function recordInterventionCommandSpec(taskId = null) {
|
|
212
|
+
return {
|
|
213
|
+
commandId: "record-intervention",
|
|
214
|
+
executable: "forgeloop",
|
|
215
|
+
subcommand: "record-intervention",
|
|
216
|
+
argv: ["record-intervention", ...(taskId ? [`--task=${taskId}`] : [])],
|
|
217
|
+
requiredInputs: [
|
|
218
|
+
{ name: "file", option: "--file=<intervention-json-path>" },
|
|
219
|
+
],
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
129
223
|
export function recordTerminalResultCommandSpec(requirement) {
|
|
130
224
|
const reqId = requirement.id ?? requirement;
|
|
131
225
|
const type = requirement.type ?? "PUBLICATION";
|