@cassiomc1/forgeloop 1.3.0 → 1.5.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.
Files changed (76) hide show
  1. package/.github/copilot-instructions.md +1 -0
  2. package/AGENTS.md +1 -0
  3. package/CLAUDE.md +1 -0
  4. package/DOCS_INDEX.md +7 -0
  5. package/EXECUTION_STATE.md +40 -0
  6. package/LOOP_ENGINEERING.md +54 -5
  7. package/LOOP_SYSTEM_DESIGN.md +22 -1
  8. package/PROTOCOL_INTEGRATION.md +41 -0
  9. package/README.md +38 -0
  10. package/TERMINOLOGY.md +15 -0
  11. package/THIRD_PARTY_NOTICES.md +15 -0
  12. package/THREAT_MODEL.md +20 -1
  13. package/docs/ARTIFACT_REFERENCE.md +43 -0
  14. package/docs/CLI_REFERENCE.md +97 -3
  15. package/docs/CROSS_HARNESS_CONTINUITY.md +23 -0
  16. package/docs/DOCUMENTATION_GUIDE.md +14 -0
  17. package/docs/GETTING_STARTED.md +1 -0
  18. package/docs/MCP.md +126 -0
  19. package/docs/RECIPES.md +82 -0
  20. package/docs/RELEASE_CHECKLIST_1_4.md +38 -0
  21. package/docs/RELEASE_CHECKLIST_1_5_MCP.md +78 -0
  22. package/docs/TROUBLESHOOTING.md +111 -1
  23. package/docs/UNIVERSAL_INTEGRATION.md +48 -0
  24. package/package.json +14 -3
  25. package/schemas/task-recovery.schema.json +61 -0
  26. package/src/cli.js +173 -347
  27. package/src/commands/audit.js +5 -0
  28. package/src/commands/inspect.js +6 -0
  29. package/src/commands/progress.js +6 -2
  30. package/src/commands/status.js +17 -0
  31. package/src/commands/task-create.js +39 -1
  32. package/src/commands/task-list.js +14 -1
  33. package/src/commands/task-lock-status.js +2 -2
  34. package/src/commands/task-recover.js +202 -0
  35. package/src/commands/task-repair-legacy-recovery.js +417 -0
  36. package/src/commands/task-resume.js +172 -0
  37. package/src/commands/task-scope.js +23 -4
  38. package/src/commands/task-show.js +18 -4
  39. package/src/commands/validate-protocol.js +19 -2
  40. package/src/core/artifact-registry.js +12 -0
  41. package/src/core/audit.js +20 -4
  42. package/src/core/bundles.js +15 -0
  43. package/src/core/cli-command-definitions.js +50 -4
  44. package/src/core/command-executors.js +387 -0
  45. package/src/core/command-input.js +107 -0
  46. package/src/core/command-runtime.js +106 -0
  47. package/src/core/completion-artifacts.js +2 -3
  48. package/src/core/completion-ownership.js +88 -0
  49. package/src/core/error-codes.js +118 -1
  50. package/src/core/events.js +130 -1
  51. package/src/core/filesystem.js +55 -6
  52. package/src/core/inspect.js +27 -0
  53. package/src/core/integration-invocation-policy.js +170 -0
  54. package/src/core/integration-limits.js +20 -0
  55. package/src/core/integration-resources.js +127 -0
  56. package/src/core/next-action-model.js +60 -0
  57. package/src/core/next-action.js +31 -0
  58. package/src/core/phase.js +2 -1
  59. package/src/core/project-root.js +21 -0
  60. package/src/core/protocol-info.js +13 -0
  61. package/src/core/reconcile-closure.js +32 -10
  62. package/src/core/recovery-history.js +116 -0
  63. package/src/core/schema-validation.js +1 -0
  64. package/src/core/task-claim-state.js +272 -0
  65. package/src/core/task-command.js +5 -1
  66. package/src/core/task-conflict-inspection.js +321 -0
  67. package/src/core/task-context.js +32 -29
  68. package/src/core/task-discovery.js +14 -1
  69. package/src/core/task-lock.js +216 -22
  70. package/src/core/task-paths.js +3 -2
  71. package/src/core/task-recovery-migration.js +192 -0
  72. package/src/core/task-recovery.js +205 -0
  73. package/src/core/task-scope.js +33 -1
  74. package/src/core/templates.js +1 -0
  75. package/src/core/transaction.js +28 -2
  76. package/src/integration.js +47 -0
package/src/cli.js CHANGED
@@ -4,53 +4,55 @@ import { readFile } from "node:fs/promises";
4
4
  import path from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
6
 
7
- import { runDoctor } from "./commands/doctor.js";
8
- import { formatStatusResult, runStatus } from "./commands/status.js";
9
- import { formatValidateStateResult, runValidateState } from "./commands/validate-state.js";
10
- import { formatClearStateResult, runClearState } from "./commands/clear-state.js";
11
- import { formatInspectResult, inspectTarget } from "./commands/inspect.js";
12
- import { runInit } from "./commands/init.js";
13
- import { formatRouteResult, runRoute } from "./commands/route.js";
14
- import { runValidateReceipt } from "./commands/validate-receipt.js";
15
- import { formatValidateProtocolResult, runValidateProtocol } from "./commands/validate-protocol.js";
16
- import { runUpdate } from "./commands/update.js";
17
- import { formatActivateResult, runActivate } from "./commands/activate.js";
18
- import { formatAdvanceResult, runAdvance } from "./commands/advance.js";
19
- import { formatPreflightResult, runPreflight } from "./commands/preflight.js";
20
- import { formatCompleteResult, runComplete } from "./commands/complete.js";
21
- import { formatAuditResult, runAudit } from "./commands/audit.js";
22
- import { formatReportResult, runReport } from "./commands/report.js";
23
- import { formatPolicyResult, runPolicy } from "./commands/policy.js";
24
- import { formatPolicyDiscoverResult, runPolicyDiscover } from "./commands/policy-discover.js";
25
- import { formatPolicyStatusResult, runPolicyStatus } from "./commands/policy-status.js";
26
- import { formatPolicyDiffResult, runPolicyDiff } from "./commands/policy-diff.js";
27
- import { formatRuleVerifyResult, runRuleVerify } from "./commands/rule-verify.js";
28
- import { formatBaselineResult, runBaseline } from "./commands/baseline.js";
29
- import { formatProfileInterviewResult, runProfileInterview } from "./commands/profile-interview.js";
30
- import { formatBundleResult, runBundle } from "./commands/bundle.js";
31
- import { formatPrepareCompletionResult, runPrepareCompletion } from "./commands/prepare-completion.js";
32
- import { formatRecordCheckResult, runRecordCheck } from "./commands/record-check.js";
33
- import { formatRunCheckResult, runCheck } from "./commands/run-check.js";
34
- import { formatReconcileClosureResult, reconcileClosure } from "./commands/reconcile-closure.js";
35
- import { formatRecordTerminalResult, runRecordTerminalResult } from "./commands/record-terminal-result.js";
36
- import { formatRecordDiagnosisResult, runRecordDiagnosis } from "./commands/record-diagnosis.js";
37
- import { formatProgressResult, runProgress } from "./commands/progress.js";
38
- import { formatRecordDecisionCriterionResult, runRecordDecisionCriterion } from "./commands/record-decision-criterion.js";
39
- import { formatNextActionResult, runNext } from "./commands/next.js";
40
- import { formatContinuityResult, runContinuity } from "./commands/continuity.js";
41
- import { formatRecordContinuityResult, runRecordContinuity } from "./commands/record-continuity.js";
42
- import { formatReconcileContinuityResult, runReconcileContinuity } from "./commands/reconcile-continuity.js";
43
- import { formatClearContinuityResult, runClearContinuity } from "./commands/clear-continuity.js";
44
- import { formatTaskCreateResult, runTaskCreate } from "./commands/task-create.js";
45
- import { formatTaskListResult, runTaskList } from "./commands/task-list.js";
46
- import { formatTaskShowResult, runTaskShow } from "./commands/task-show.js";
47
- import { formatTaskScopeResult, runTaskScope } from "./commands/task-scope.js";
48
- import { formatTaskMigrateResult, runTaskMigrate } from "./commands/task-migrate.js";
49
- import { formatMigrateProtocolResult, runMigrateProtocol } from "./commands/migrate-protocol.js";
50
- import { formatTaskUnlockResult, runTaskUnlock } from "./commands/task-unlock.js";
51
- import { formatTaskLockStatusResult, runTaskLockStatus } from "./commands/task-lock-status.js";
52
- import { formatProtocolInfoResult, runProtocolInfo } from "./commands/protocol-info.js";
53
- import { continuityOptionDefaults, validateContinuityOptions } from "./core/continuity-cli-options.js";
7
+ import { formatStatusResult } from "./commands/status.js";
8
+ import { formatValidateStateResult } from "./commands/validate-state.js";
9
+ import { formatClearStateResult } from "./commands/clear-state.js";
10
+ import { formatInspectResult } from "./commands/inspect.js";
11
+ import { formatRouteResult } from "./commands/route.js";
12
+ import { formatValidateProtocolResult } from "./commands/validate-protocol.js";
13
+ import { formatActivateResult } from "./commands/activate.js";
14
+ import { formatAdvanceResult } from "./commands/advance.js";
15
+ import { formatPreflightResult } from "./commands/preflight.js";
16
+ import { formatCompleteResult } from "./commands/complete.js";
17
+ import { formatAuditResult } from "./commands/audit.js";
18
+ import { formatReportResult } from "./commands/report.js";
19
+ import { formatPolicyResult } from "./commands/policy.js";
20
+ import { formatPolicyDiscoverResult } from "./commands/policy-discover.js";
21
+ import { formatPolicyStatusResult } from "./commands/policy-status.js";
22
+ import { formatPolicyDiffResult } from "./commands/policy-diff.js";
23
+ import { formatRuleVerifyResult } from "./commands/rule-verify.js";
24
+ import { formatBaselineResult } from "./commands/baseline.js";
25
+ import { formatProfileInterviewResult } from "./commands/profile-interview.js";
26
+ import { formatBundleResult } from "./commands/bundle.js";
27
+ import { formatPrepareCompletionResult } from "./commands/prepare-completion.js";
28
+ import { formatRecordCheckResult } from "./commands/record-check.js";
29
+ import { formatRunCheckResult } from "./commands/run-check.js";
30
+ import { formatReconcileClosureResult } from "./commands/reconcile-closure.js";
31
+ import { formatRecordTerminalResult } from "./commands/record-terminal-result.js";
32
+ import { formatRecordDiagnosisResult } from "./commands/record-diagnosis.js";
33
+ import { formatProgressResult } from "./commands/progress.js";
34
+ import { formatRecordDecisionCriterionResult } from "./commands/record-decision-criterion.js";
35
+ import { formatNextActionResult } from "./commands/next.js";
36
+ import { formatContinuityResult } from "./commands/continuity.js";
37
+ import { formatRecordContinuityResult } from "./commands/record-continuity.js";
38
+ import { formatReconcileContinuityResult } from "./commands/reconcile-continuity.js";
39
+ import { formatClearContinuityResult } from "./commands/clear-continuity.js";
40
+ import { formatTaskCreateResult } from "./commands/task-create.js";
41
+ import { formatTaskListResult } from "./commands/task-list.js";
42
+ import { formatTaskShowResult } from "./commands/task-show.js";
43
+ import { formatTaskScopeResult } from "./commands/task-scope.js";
44
+ import { formatTaskMigrateResult } from "./commands/task-migrate.js";
45
+ import { formatMigrateProtocolResult } from "./commands/migrate-protocol.js";
46
+ import { formatTaskUnlockResult } from "./commands/task-unlock.js";
47
+ import { formatTaskRecoverResult } from "./commands/task-recover.js";
48
+ import { formatTaskResumeResult } from "./commands/task-resume.js";
49
+ import {
50
+ formatTaskRepairLegacyRecoveryResult,
51
+ } from "./commands/task-repair-legacy-recovery.js";
52
+ import { formatTaskLockStatusResult } from "./commands/task-lock-status.js";
53
+ import { formatProtocolInfoResult } from "./commands/protocol-info.js";
54
+ import { defaultCommandInputValues, validateForgeLoopCommandInput } from "./core/command-input.js";
55
+ import { COMMAND_EXECUTORS } from "./core/command-executors.js";
54
56
  import { resolveTarget } from "./core/filesystem.js";
55
57
  import { getPackageRoot } from "./core/templates.js";
56
58
  import { CLI_COMMAND_DEFINITIONS, buildOptionLookup, getPositionalDefinitions } from "./core/cli-command-definitions.js";
@@ -196,48 +198,7 @@ export function discoverCommand(argv) {
196
198
  }
197
199
 
198
200
  export function parseCliSyntax(argv) {
199
- const options = {
200
- path: ".",
201
- dryRun: false,
202
- json: false,
203
- strict: false,
204
- fix: false,
205
- adopt: [],
206
- work: null,
207
- surfaces: [],
208
- risks: [],
209
- platforms: [],
210
- behaviorChange: false,
211
- executableChange: false,
212
- to: null,
213
- file: null,
214
- contractFile: null,
215
- routeFile: null,
216
- stateFile: null,
217
- receiptFile: null,
218
- continuityFile: null,
219
- ...continuityOptionDefaults(),
220
- taskBriefFiles: [],
221
- delegatedResultFiles: [],
222
- checkId: null,
223
- checkKind: null,
224
- checkRequirement: null,
225
- checkStatus: null,
226
- checkEvidenceKind: null,
227
- checkCommand: null,
228
- checkResult: null,
229
- checkExitCode: null,
230
- checkDetails: null,
231
- checkExecutionRef: null,
232
- checkProvenance: null,
233
- commandArgv: [],
234
- checkType: null,
235
- checkSource: null,
236
- policy: null,
237
- task: null,
238
- help: false,
239
- version: false,
240
- };
201
+ const options = defaultCommandInputValues();
241
202
 
242
203
  const command = discoverCommand(argv);
243
204
  const bootstrapLookup = buildOptionLookup(null);
@@ -314,53 +275,7 @@ export function parseCliSyntax(argv) {
314
275
  }
315
276
 
316
277
  export function validateCliSemantics({ command, options } = {}) {
317
- if (!command) return;
318
-
319
- if (command === "policy" && !options.policy) {
320
- throw new Error("policy requires a name");
321
- }
322
- if (command !== "policy" && options.policy) {
323
- throw new Error(`Policy name is not valid for ${command}`);
324
- }
325
- if (command === "bundle" && !options.task) {
326
- throw new Error("bundle requires --task");
327
- }
328
- if (command === "task-create" && !options.task) {
329
- throw new Error("task-create requires --task");
330
- }
331
-
332
- validateContinuityOptions(command, options);
333
-
334
- if (command === "record-check" && !options.help) {
335
- if (!options.checkId) throw new Error("record-check requires --id");
336
- if (!options.checkRequirement) throw new Error("record-check requires --requirement");
337
- if (!options.checkStatus) throw new Error("record-check requires --status");
338
- if (!options.checkEvidenceKind) throw new Error("record-check requires --evidence-kind");
339
- if (!options.checkCommand && !options.checkResult) throw new Error("record-check requires --command or --result");
340
- }
341
- if (command === "run-check" && !options.help) {
342
- if (!options.checkId) throw new Error("run-check requires --id");
343
- if (!options.checkRequirement) throw new Error("run-check requires --requirement");
344
- if (options.checkKind || options.checkStatus || options.checkEvidenceKind || options.checkCommand
345
- || options.checkResult || options.checkExitCode !== null || options.checkExecutionRef || options.checkProvenance) {
346
- throw new Error("run-check accepts only --id, --requirement, --details, --timeout-ms, and -- <argv>");
347
- }
348
- if (!Array.isArray(options.commandArgv) || options.commandArgv.length === 0) {
349
- throw new Error("run-check requires -- followed by an exact command argv");
350
- }
351
- }
352
- if (command === "reconcile-closure" && !options.help) {
353
- if (!options.task) throw new Error("reconcile-closure requires --task");
354
- if (!options.checkId) throw new Error("reconcile-closure requires --id");
355
- if (!options.checkRequirement) throw new Error("reconcile-closure requires --requirement");
356
- if (options.checkKind || options.checkStatus || options.checkEvidenceKind || options.checkCommand
357
- || options.checkResult || options.checkExitCode !== null || options.checkExecutionRef || options.checkProvenance) {
358
- throw new Error("reconcile-closure accepts only --id, --requirement, --details, and -- <argv>");
359
- }
360
- if (!Array.isArray(options.commandArgv) || options.commandArgv.length === 0) {
361
- throw new Error("reconcile-closure requires -- followed by an exact command argv");
362
- }
363
- }
278
+ validateForgeLoopCommandInput({ command, input: options, help: options?.help ?? false });
364
279
  }
365
280
 
366
281
  export function parseArgs(argv) {
@@ -383,25 +298,23 @@ function printActions(actions) {
383
298
  }
384
299
  }
385
300
 
301
+ function renderJsonOr(options, result, formatter) {
302
+ console.log(options.json ? JSON.stringify(result, null, 2) : formatter(result));
303
+ }
304
+
386
305
  export const COMMAND_HANDLERS = Object.freeze({
387
306
  "protocol-info": async ({ packageVersion, options }) => {
388
- const result = await runProtocolInfo({ packageVersion });
389
- console.log(options.json ? JSON.stringify(result, null, 2) : formatProtocolInfoResult(result));
307
+ const { result } = await COMMAND_EXECUTORS["protocol-info"]({ packageVersion, options });
308
+ renderJsonOr(options, result, formatProtocolInfoResult);
390
309
  return 0;
391
310
  },
392
311
  init: async ({ target, packageRoot, packageVersion, options }) => {
393
- const result = await runInit({ target, dryRun: options.dryRun, packageRoot, packageVersion });
312
+ const { result } = await COMMAND_EXECUTORS.init({ target, packageRoot, packageVersion, options });
394
313
  printActions(result.actions);
395
314
  return 0;
396
315
  },
397
316
  doctor: async ({ target, packageRoot, options }) => {
398
- const result = await runDoctor({
399
- target,
400
- packageRoot,
401
- adoptPaths: options.adopt,
402
- strict: options.strict,
403
- fix: options.fix,
404
- });
317
+ const { result } = await COMMAND_EXECUTORS.doctor({ target, packageRoot, options });
405
318
  if (options.json) {
406
319
  console.log(JSON.stringify(result, null, 2));
407
320
  } else {
@@ -413,328 +326,241 @@ export const COMMAND_HANDLERS = Object.freeze({
413
326
  return result.ok ? 0 : 1;
414
327
  },
415
328
  route: async ({ target, packageRoot, options }) => {
416
- const result = await runRoute({
417
- target,
418
- packageRoot,
419
- workType: options.work,
420
- surfaces: options.surfaces,
421
- risks: options.risks,
422
- platforms: options.platforms,
423
- behaviorChange: options.behaviorChange,
424
- executableChange: options.executableChange,
425
- taskId: options.task,
426
- });
427
- console.log(options.json ? JSON.stringify(result, null, 2) : formatRouteResult(result));
329
+ const { result } = await COMMAND_EXECUTORS.route({ target, packageRoot, options });
330
+ renderJsonOr(options, result, formatRouteResult);
428
331
  return 0;
429
332
  },
430
333
  activate: async ({ target, packageRoot, options }) => {
431
- const result = await runActivate({ target, packageRoot });
432
- console.log(options.json ? JSON.stringify(result, null, 2) : formatActivateResult(result));
334
+ const { result } = await COMMAND_EXECUTORS.activate({ target, packageRoot, options });
335
+ renderJsonOr(options, result, formatActivateResult);
433
336
  return 0;
434
337
  },
435
338
  preflight: async ({ target, packageRoot, options }) => {
436
- const result = await runPreflight({ target, packageRoot, strict: options.strict, taskId: options.task });
437
- console.log(options.json ? JSON.stringify(result, null, 2) : formatPreflightResult(result));
438
- return result.status === "READY" ? 0 : 1;
339
+ const { result, exitCode } = await COMMAND_EXECUTORS.preflight({ target, packageRoot, options });
340
+ renderJsonOr(options, result, formatPreflightResult);
341
+ return exitCode;
439
342
  },
440
343
  advance: async ({ target, packageRoot, options }) => {
441
- const result = await runAdvance({ target, packageRoot, to: options.to, taskId: options.task });
442
- console.log(options.json ? JSON.stringify(result, null, 2) : formatAdvanceResult(result));
344
+ const { result } = await COMMAND_EXECUTORS.advance({ target, packageRoot, options });
345
+ renderJsonOr(options, result, formatAdvanceResult);
443
346
  return 0;
444
347
  },
445
348
  next: async ({ target, packageRoot, options }) => {
446
- const result = await runNext({ target, packageRoot, taskId: options.task });
447
- console.log(options.json ? JSON.stringify(result, null, 2) : formatNextActionResult(result));
349
+ const { result } = await COMMAND_EXECUTORS.next({ target, packageRoot, options });
350
+ renderJsonOr(options, result, formatNextActionResult);
448
351
  return 0;
449
352
  },
450
353
  continuity: async ({ target, packageRoot, options }) => {
451
- const result = await runContinuity({ target, packageRoot, taskId: options.task });
452
- console.log(options.json ? JSON.stringify(result, null, 2) : formatContinuityResult(result));
354
+ const { result } = await COMMAND_EXECUTORS.continuity({ target, packageRoot, options });
355
+ renderJsonOr(options, result, formatContinuityResult);
453
356
  return 0;
454
357
  },
455
358
  "record-continuity": async ({ target, packageRoot, options }) => {
456
- const result = await runRecordContinuity({
457
- target, packageRoot,
458
- focusId: options.continuityFocusId,
459
- focusSummary: options.continuityFocusSummary,
460
- remaining: options.continuityRemaining,
461
- knownIssues: options.continuityKnownIssues,
462
- changedAreas: options.continuityChangedAreas,
463
- inspectFirst: options.continuityInspectFirst,
464
- resumeNote: options.continuityResumeNote,
465
- taskId: options.task,
466
- });
467
- console.log(options.json ? JSON.stringify(result, null, 2) : formatRecordContinuityResult(result));
359
+ const { result } = await COMMAND_EXECUTORS["record-continuity"]({ target, packageRoot, options });
360
+ renderJsonOr(options, result, formatRecordContinuityResult);
468
361
  return 0;
469
362
  },
470
363
  "reconcile-continuity": async ({ target, packageRoot, options }) => {
471
- const result = await runReconcileContinuity({ target, packageRoot, taskId: options.task });
472
- console.log(options.json ? JSON.stringify(result, null, 2) : formatReconcileContinuityResult(result));
364
+ const { result } = await COMMAND_EXECUTORS["reconcile-continuity"]({ target, packageRoot, options });
365
+ renderJsonOr(options, result, formatReconcileContinuityResult);
473
366
  return 0;
474
367
  },
475
368
  "clear-continuity": async ({ target, options }) => {
476
- const result = await runClearContinuity({ target, taskId: options.task });
477
- console.log(options.json ? JSON.stringify(result, null, 2) : formatClearContinuityResult(result));
369
+ const { result } = await COMMAND_EXECUTORS["clear-continuity"]({ target, options });
370
+ renderJsonOr(options, result, formatClearContinuityResult);
478
371
  return 0;
479
372
  },
480
373
  "prepare-completion": async ({ target, packageRoot, options }) => {
481
- const result = await runPrepareCompletion({ target, packageRoot, taskId: options.task });
482
- console.log(options.json ? JSON.stringify(result, null, 2) : formatPrepareCompletionResult(result));
374
+ const { result } = await COMMAND_EXECUTORS["prepare-completion"]({ target, packageRoot, options });
375
+ renderJsonOr(options, result, formatPrepareCompletionResult);
483
376
  return 0;
484
377
  },
485
378
  "run-check": async ({ target, packageRoot, options }) => {
486
- const result = await runCheck({
487
- target,
488
- packageRoot,
489
- id: options.checkId,
490
- requirement: options.checkRequirement,
491
- argv: options.commandArgv,
492
- details: options.checkDetails ?? undefined,
493
- timeoutMs: options.timeoutMs ?? undefined,
494
- taskId: options.task,
495
- });
496
- console.log(options.json ? JSON.stringify(result, null, 2) : formatRunCheckResult(result));
497
- return result.check.status === "passed" ? 0 : 1;
379
+ const { result, exitCode } = await COMMAND_EXECUTORS["run-check"]({ target, packageRoot, options });
380
+ renderJsonOr(options, result, formatRunCheckResult);
381
+ return exitCode;
498
382
  },
499
383
  "record-check": async ({ target, packageRoot, options }) => {
500
- const result = await runRecordCheck({
501
- target,
502
- packageRoot,
503
- id: options.checkId,
504
- kind: options.checkKind ?? "command",
505
- requirement: options.checkRequirement,
506
- status: options.checkStatus,
507
- evidenceKind: options.checkEvidenceKind,
508
- command: options.checkCommand ?? undefined,
509
- result: options.checkResult ?? undefined,
510
- ...(options.checkExitCode === null ? {} : { exitCode: options.checkExitCode }),
511
- details: options.checkDetails ?? undefined,
512
- executionRef: options.checkExecutionRef ?? undefined,
513
- provenance: options.checkProvenance ?? undefined,
514
- taskId: options.task,
515
- });
516
- console.log(options.json ? JSON.stringify(result, null, 2) : formatRecordCheckResult(result));
384
+ const { result } = await COMMAND_EXECUTORS["record-check"]({ target, packageRoot, options });
385
+ renderJsonOr(options, result, formatRecordCheckResult);
517
386
  return 0;
518
387
  },
519
388
  "record-terminal-result": async ({ target, packageRoot, options }) => {
520
- const result = await runRecordTerminalResult({
521
- target,
522
- packageRoot,
523
- requirement: options.checkRequirement,
524
- type: options.checkType,
525
- status: options.checkStatus,
526
- source: options.checkSource ?? options.checkCommand,
527
- result: options.checkResult,
528
- details: options.checkDetails ?? undefined,
529
- taskId: options.task,
530
- });
531
- console.log(options.json ? JSON.stringify(result, null, 2) : formatRecordTerminalResult(result));
389
+ const { result } = await COMMAND_EXECUTORS["record-terminal-result"]({ target, packageRoot, options });
390
+ renderJsonOr(options, result, formatRecordTerminalResult);
532
391
  return 0;
533
392
  },
534
393
  "record-diagnosis": async ({ target, packageRoot, options }) => {
535
- const result = await runRecordDiagnosis({
536
- target,
537
- packageRoot,
538
- hypothesis: options.hypothesis,
539
- failureClass: options.failureClass,
540
- evidenceRefs: options.evidenceRefs,
541
- settledBy: options.settledBy,
542
- nextSafeAction: options.nextSafeAction,
543
- taskId: options.task,
544
- });
545
- console.log(options.json ? JSON.stringify(result, null, 2) : formatRecordDiagnosisResult(result));
394
+ const { result } = await COMMAND_EXECUTORS["record-diagnosis"]({ target, packageRoot, options });
395
+ renderJsonOr(options, result, formatRecordDiagnosisResult);
546
396
  return 0;
547
397
  },
548
398
  progress: async ({ target, packageRoot, options }) => {
549
- const result = await runProgress({ target, packageRoot, taskId: options.task });
550
- console.log(options.json ? JSON.stringify(result, null, 2) : formatProgressResult(result));
551
- return result.status === "STALLED" ? 1 : 0;
399
+ const { result, exitCode } = await COMMAND_EXECUTORS.progress({ target, packageRoot, options });
400
+ renderJsonOr(options, result, formatProgressResult);
401
+ return exitCode;
552
402
  },
553
403
  "record-decision-criterion": async ({ target, packageRoot, options }) => {
554
- const result = await runRecordDecisionCriterion({
555
- target,
556
- packageRoot,
557
- decision: options.decision,
558
- settledBy: options.settledBy,
559
- taskId: options.task,
560
- });
561
- console.log(options.json ? JSON.stringify(result, null, 2) : formatRecordDecisionCriterionResult(result));
404
+ const { result } = await COMMAND_EXECUTORS["record-decision-criterion"]({ target, packageRoot, options });
405
+ renderJsonOr(options, result, formatRecordDecisionCriterionResult);
562
406
  return 0;
563
407
  },
564
408
  complete: async ({ target, packageRoot, options }) => {
565
- const result = await runComplete({ target, packageRoot, strict: options.strict, taskId: options.task });
566
- console.log(options.json ? JSON.stringify(result, null, 2) : formatCompleteResult(result));
567
- return result.status === "VALID" ? 0 : 1;
409
+ const { result, exitCode } = await COMMAND_EXECUTORS.complete({ target, packageRoot, options });
410
+ renderJsonOr(options, result, formatCompleteResult);
411
+ return exitCode;
568
412
  },
569
413
  audit: async ({ target, packageRoot, options }) => {
570
- const result = await runAudit({ target, packageRoot, strict: options.strict, taskId: options.task });
571
- console.log(options.json ? JSON.stringify(result, null, 2) : formatAuditResult(result));
572
- return result.status === "VALID" ? 0 : 1;
414
+ const { result, exitCode } = await COMMAND_EXECUTORS.audit({ target, packageRoot, options });
415
+ renderJsonOr(options, result, formatAuditResult);
416
+ return exitCode;
573
417
  },
574
418
  report: async ({ target, packageRoot, options }) => {
575
- const result = await runReport({ target, packageRoot, strict: options.strict, taskId: options.task });
576
- console.log(options.json ? JSON.stringify(result, null, 2) : formatReportResult(result));
577
- return result.verdict === "VALID" ? 0 : 1;
419
+ const { result, exitCode } = await COMMAND_EXECUTORS.report({ target, packageRoot, options });
420
+ renderJsonOr(options, result, formatReportResult);
421
+ return exitCode;
578
422
  },
579
423
  policy: async ({ target, packageRoot, options }) => {
580
- const result = await runPolicy({ target, packageRoot, name: options.policy, taskId: options.task });
581
- console.log(options.json ? JSON.stringify(result, null, 2) : formatPolicyResult(result));
424
+ const { result } = await COMMAND_EXECUTORS.policy({ target, packageRoot, options });
425
+ renderJsonOr(options, result, formatPolicyResult);
582
426
  return 0;
583
427
  },
584
428
  "policy-discover": async ({ target, packageRoot, options }) => {
585
- const result = await runPolicyDiscover({ target, packageRoot, write: options.write });
586
- console.log(options.json ? JSON.stringify(result, null, 2) : formatPolicyDiscoverResult(result));
429
+ const { result } = await COMMAND_EXECUTORS["policy-discover"]({ target, packageRoot, options });
430
+ renderJsonOr(options, result, formatPolicyDiscoverResult);
587
431
  return 0;
588
432
  },
589
433
  "policy-status": async ({ target, packageRoot, options }) => {
590
- const result = await runPolicyStatus({ target, packageRoot, taskId: options.task });
591
- console.log(options.json ? JSON.stringify(result, null, 2) : formatPolicyStatusResult(result));
592
- return result.status === "VALID" ? 0 : 1;
434
+ const { result, exitCode } = await COMMAND_EXECUTORS["policy-status"]({ target, packageRoot, options });
435
+ renderJsonOr(options, result, formatPolicyStatusResult);
436
+ return exitCode;
593
437
  },
594
438
  "policy-diff": async ({ target, packageRoot, options }) => {
595
- const result = await runPolicyDiff({ target, packageRoot, taskId: options.task, before: options.before, after: options.after });
596
- console.log(options.json ? JSON.stringify(result, null, 2) : formatPolicyDiffResult(result));
439
+ const { result } = await COMMAND_EXECUTORS["policy-diff"]({ target, packageRoot, options });
440
+ renderJsonOr(options, result, formatPolicyDiffResult);
597
441
  return 0;
598
442
  },
599
443
  "rule-verify": async ({ target, packageRoot, options }) => {
600
- const result = await runRuleVerify({ target, packageRoot, rule: options.rule });
601
- console.log(options.json ? JSON.stringify(result, null, 2) : formatRuleVerifyResult(result));
602
- return result.status === "VALID" ? 0 : 1;
444
+ const { result, exitCode } = await COMMAND_EXECUTORS["rule-verify"]({ target, packageRoot, options });
445
+ renderJsonOr(options, result, formatRuleVerifyResult);
446
+ return exitCode;
603
447
  },
604
448
  baseline: async ({ target, packageRoot, options }) => {
605
- const result = await runBaseline({
606
- target,
607
- packageRoot,
608
- record: options.record,
609
- update: options.update,
610
- policyResetAuthorized: options.policyResetAuthorized,
611
- });
612
- console.log(options.json ? JSON.stringify(result, null, 2) : formatBaselineResult(result));
449
+ const { result } = await COMMAND_EXECUTORS.baseline({ target, packageRoot, options });
450
+ renderJsonOr(options, result, formatBaselineResult);
613
451
  return 0;
614
452
  },
615
453
  "profile-interview": async ({ target, packageRoot, options }) => {
616
- const result = await runProfileInterview({ target, packageRoot, dryRun: options.dryRun });
617
- console.log(options.json ? JSON.stringify(result, null, 2) : formatProfileInterviewResult(result));
454
+ const { result } = await COMMAND_EXECUTORS["profile-interview"]({ target, packageRoot, options });
455
+ renderJsonOr(options, result, formatProfileInterviewResult);
618
456
  return 0;
619
457
  },
620
458
  bundle: async ({ target, packageRoot, options }) => {
621
- const result = await runBundle({ target, packageRoot, taskId: options.task });
622
- console.log(options.json ? JSON.stringify(result, null, 2) : formatBundleResult(result));
459
+ const { result } = await COMMAND_EXECUTORS.bundle({ target, packageRoot, options });
460
+ renderJsonOr(options, result, formatBundleResult);
623
461
  return 0;
624
462
  },
625
463
  inspect: async ({ target, packageRoot, options }) => {
626
- const result = await inspectTarget({ target, packageRoot, contractFile: options.contractFile, taskId: options.task });
627
- console.log(options.json ? JSON.stringify(result, null, 2) : formatInspectResult(result));
628
- return result.ok ? 0 : 1;
464
+ const { result, exitCode } = await COMMAND_EXECUTORS.inspect({ target, packageRoot, options });
465
+ renderJsonOr(options, result, formatInspectResult);
466
+ return exitCode;
629
467
  },
630
468
  "validate-receipt": async ({ target, packageRoot, options }) => {
631
- const result = await runValidateReceipt({ target, packageRoot, file: options.file, taskId: options.task });
469
+ const { result } = await COMMAND_EXECUTORS["validate-receipt"]({ target, packageRoot, options });
632
470
  console.log(options.json ? JSON.stringify(result, null, 2) : "valid: execution receipt");
633
471
  return 0;
634
472
  },
635
473
  "validate-protocol": async ({ target, packageRoot, options }) => {
636
- const result = await runValidateProtocol({
637
- target,
638
- packageRoot,
639
- stateFile: options.stateFile,
640
- receiptFile: options.receiptFile,
641
- routeFile: options.routeFile,
642
- contractFile: options.contractFile,
643
- continuityFile: options.continuityFile,
644
- taskBriefFiles: options.taskBriefFiles,
645
- delegatedResultFiles: options.delegatedResultFiles,
646
- taskId: options.task,
647
- });
648
- console.log(options.json ? JSON.stringify(result, null, 2) : formatValidateProtocolResult(result));
649
- return result.status === "VALID" ? 0 : 1;
474
+ const { result, exitCode } = await COMMAND_EXECUTORS["validate-protocol"]({ target, packageRoot, options });
475
+ renderJsonOr(options, result, formatValidateProtocolResult);
476
+ return exitCode;
650
477
  },
651
478
  status: async ({ target, packageRoot, options }) => {
652
- const result = await runStatus({ target, packageRoot, contractFile: options.contractFile, taskId: options.task });
653
- console.log(options.json ? JSON.stringify(result, null, 2) : formatStatusResult(result));
479
+ const { result } = await COMMAND_EXECUTORS.status({ target, packageRoot, options });
480
+ renderJsonOr(options, result, formatStatusResult);
654
481
  return 0;
655
482
  },
656
483
  "validate-state": async ({ target, packageRoot, options }) => {
657
- const result = await runValidateState({ target, packageRoot, taskId: options.task });
658
- console.log(options.json ? JSON.stringify(result, null, 2) : formatValidateStateResult(result));
659
- return result.ok ? 0 : 1;
484
+ const { result, exitCode } = await COMMAND_EXECUTORS["validate-state"]({ target, packageRoot, options });
485
+ renderJsonOr(options, result, formatValidateStateResult);
486
+ return exitCode;
660
487
  },
661
488
  "clear-state": async ({ target, options }) => {
662
- const result = await runClearState({ target, taskId: options.task });
663
- console.log(options.json ? JSON.stringify(result, null, 2) : formatClearStateResult(result));
489
+ const { result } = await COMMAND_EXECUTORS["clear-state"]({ target, options });
490
+ renderJsonOr(options, result, formatClearStateResult);
664
491
  return 0;
665
492
  },
666
493
  "task-create": async ({ target, packageRoot, options }) => {
667
- const result = await runTaskCreate({
668
- target,
669
- packageRoot,
670
- taskId: options.task,
671
- claims: options.claims,
672
- contractFile: options.contractFile,
673
- });
674
- console.log(options.json ? JSON.stringify(result, null, 2) : formatTaskCreateResult(result));
494
+ const { result } = await COMMAND_EXECUTORS["task-create"]({ target, packageRoot, options });
495
+ renderJsonOr(options, result, formatTaskCreateResult);
675
496
  return 0;
676
497
  },
677
498
  "task-list": async ({ target, packageRoot, options }) => {
678
- const result = await runTaskList({ target, packageRoot });
679
- console.log(options.json ? JSON.stringify(result, null, 2) : formatTaskListResult(result));
499
+ const { result } = await COMMAND_EXECUTORS["task-list"]({ target, packageRoot, options });
500
+ renderJsonOr(options, result, formatTaskListResult);
680
501
  return 0;
681
502
  },
682
503
  "task-show": async ({ target, packageRoot, options }) => {
683
- const result = await runTaskShow({ target, packageRoot, taskId: options.task });
684
- console.log(options.json ? JSON.stringify(result, null, 2) : formatTaskShowResult(result));
504
+ const { result } = await COMMAND_EXECUTORS["task-show"]({ target, packageRoot, options });
505
+ renderJsonOr(options, result, formatTaskShowResult);
685
506
  return 0;
686
507
  },
687
508
  "task-lock-status": async ({ target, packageRoot, options }) => {
688
- const result = await runTaskLockStatus({ target, packageRoot, taskId: options.task });
689
- console.log(options.json ? JSON.stringify(result, null, 2) : formatTaskLockStatusResult(result));
509
+ const { result } = await COMMAND_EXECUTORS["task-lock-status"]({ target, packageRoot, options });
510
+ renderJsonOr(options, result, formatTaskLockStatusResult);
690
511
  return 0;
691
512
  },
692
513
  "task-scope": async ({ target, packageRoot, options }) => {
693
- const result = await runTaskScope({
694
- target,
695
- packageRoot,
696
- taskId: options.task,
697
- claims: options.claims,
698
- });
699
- console.log(options.json ? JSON.stringify(result, null, 2) : formatTaskScopeResult(result));
514
+ const { result } = await COMMAND_EXECUTORS["task-scope"]({ target, packageRoot, options });
515
+ renderJsonOr(options, result, formatTaskScopeResult);
700
516
  return 0;
701
517
  },
702
518
  "task-migrate": async ({ target, packageRoot, options }) => {
703
- const result = await runTaskMigrate({ target, packageRoot, dryRun: options.dryRun });
704
- console.log(options.json ? JSON.stringify(result, null, 2) : formatTaskMigrateResult(result));
519
+ const { result } = await COMMAND_EXECUTORS["task-migrate"]({ target, packageRoot, options });
520
+ renderJsonOr(options, result, formatTaskMigrateResult);
705
521
  return 0;
706
522
  },
707
523
  "migrate-protocol": async ({ target, packageRoot, options }) => {
708
- const result = await runMigrateProtocol({ target, packageRoot, to: options.to, dryRun: options.dryRun });
709
- console.log(options.json ? JSON.stringify(result, null, 2) : formatMigrateProtocolResult(result));
524
+ const { result } = await COMMAND_EXECUTORS["migrate-protocol"]({ target, packageRoot, options });
525
+ renderJsonOr(options, result, formatMigrateProtocolResult);
710
526
  return 0;
711
527
  },
712
528
  "task-unlock": async ({ target, packageRoot, options }) => {
713
- const result = await runTaskUnlock({ target, packageRoot, taskId: options.task, force: options.force, staleOnly: options.staleOnly });
714
- console.log(options.json ? JSON.stringify(result, null, 2) : formatTaskUnlockResult(result));
529
+ const { result } = await COMMAND_EXECUTORS["task-unlock"]({ target, packageRoot, options });
530
+ renderJsonOr(options, result, formatTaskUnlockResult);
531
+ return 0;
532
+ },
533
+ "task-recover": async ({ target, packageRoot, options }) => {
534
+ if (options.operatorAuthorized && !options.acknowledgeRecovery) {
535
+ console.error("DEPRECATION: --operator-authorized is caller acknowledgement, not host attestation; use --acknowledge-recovery.");
536
+ }
537
+ const { result } = await COMMAND_EXECUTORS["task-recover"]({ target, packageRoot, options });
538
+ renderJsonOr(options, result, formatTaskRecoverResult);
539
+ return 0;
540
+ },
541
+ "task-resume": async ({ target, packageRoot, options }) => {
542
+ const { result } = await COMMAND_EXECUTORS["task-resume"]({ target, packageRoot, options });
543
+ renderJsonOr(options, result, formatTaskResumeResult);
544
+ return 0;
545
+ },
546
+ "task-repair-legacy-recovery": async ({ target, packageRoot, options }) => {
547
+ const { result } = await COMMAND_EXECUTORS["task-repair-legacy-recovery"]({ target, packageRoot, options });
548
+ renderJsonOr(options, result, formatTaskRepairLegacyRecoveryResult);
715
549
  return 0;
716
550
  },
717
551
  "reconcile-closure": async ({ target, packageRoot, options }) => {
718
- const result = await reconcileClosure({
719
- target,
720
- packageRoot,
721
- taskId: options.task,
722
- checkId: options.checkId,
723
- checkRequirement: options.checkRequirement,
724
- checkDetails: options.checkDetails,
725
- commandArgv: options.commandArgv,
726
- });
727
- console.log(options.json ? JSON.stringify(result, null, 2) : formatReconcileClosureResult(result));
552
+ const { result } = await COMMAND_EXECUTORS["reconcile-closure"]({ target, packageRoot, options });
553
+ renderJsonOr(options, result, formatReconcileClosureResult);
728
554
  return 0;
729
555
  },
730
556
  update: async ({ target, packageRoot, packageVersion, options }) => {
731
- const result = await runUpdate({ target, dryRun: options.dryRun, packageRoot, packageVersion });
557
+ const { result, exitCode } = await COMMAND_EXECUTORS.update({ target, packageRoot, packageVersion, options });
732
558
  printActions(result.actions);
733
559
  for (const conflict of result.conflicts) {
734
560
  const code = conflict.code ? `${conflict.code}: ` : "";
735
561
  console.log(`conflict: ${code}${conflict.path} - ${conflict.message}`);
736
562
  }
737
- return result.conflicts.length === 0 ? 0 : 1;
563
+ return exitCode;
738
564
  },
739
565
  });
740
566