cool-workflow 0.1.92 → 0.1.94

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 (81) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codex-plugin/plugin.json +1 -1
  3. package/README.md +104 -129
  4. package/apps/architecture-review/app.json +1 -1
  5. package/apps/architecture-review-fast/app.json +1 -1
  6. package/apps/architecture-review-fast/workflow.js +15 -2
  7. package/apps/end-to-end-golden-path/app.json +1 -1
  8. package/apps/pr-review-fix-ci/app.json +1 -1
  9. package/apps/release-cut/app.json +1 -1
  10. package/apps/research-synthesis/app.json +1 -1
  11. package/dist/capability-core.js +47 -0
  12. package/dist/capability-registry.js +2 -0
  13. package/dist/cli/command-surface.js +165 -1352
  14. package/dist/cli/format.js +56 -0
  15. package/dist/cli/handlers/audit.js +82 -0
  16. package/dist/cli/handlers/blackboard.js +81 -0
  17. package/dist/cli/handlers/candidate.js +40 -0
  18. package/dist/cli/handlers/clones.js +34 -0
  19. package/dist/cli/handlers/collaboration.js +61 -0
  20. package/dist/cli/handlers/eval.js +40 -0
  21. package/dist/cli/handlers/maintenance.js +107 -0
  22. package/dist/cli/handlers/multi-agent.js +165 -0
  23. package/dist/cli/handlers/node.js +41 -0
  24. package/dist/cli/handlers/operational.js +155 -0
  25. package/dist/cli/handlers/operator.js +146 -0
  26. package/dist/cli/handlers/registry.js +68 -0
  27. package/dist/cli/handlers/run.js +153 -0
  28. package/dist/cli/handlers/scheduling.js +126 -0
  29. package/dist/cli/handlers/workbench.js +41 -0
  30. package/dist/cli/handlers/worker.js +45 -0
  31. package/dist/cli/io.js +27 -0
  32. package/dist/cli/run-summary.js +45 -0
  33. package/dist/commit.js +0 -5
  34. package/dist/execution-backend.js +0 -11
  35. package/dist/mcp/tool-call.js +2 -0
  36. package/dist/mcp/tool-definitions.js +8 -0
  37. package/dist/orchestrator/app-operations.js +205 -0
  38. package/dist/orchestrator.js +41 -153
  39. package/dist/state-explosion.js +0 -7
  40. package/dist/term.js +0 -18
  41. package/dist/validation.js +0 -21
  42. package/dist/version.js +1 -1
  43. package/docs/agent-delegation-drive.7.md +13 -7
  44. package/docs/cli-mcp-parity.7.md +19 -2
  45. package/docs/contract-migration-tooling.7.md +3 -1
  46. package/docs/control-plane-scheduling.7.md +3 -1
  47. package/docs/durable-state-and-locking.7.md +3 -1
  48. package/docs/evidence-adoption-reasoning-chain.7.md +3 -1
  49. package/docs/execution-backends.7.md +3 -1
  50. package/docs/mcp-app-surface.7.md +12 -0
  51. package/docs/multi-agent-cli-mcp-surface.7.md +3 -1
  52. package/docs/multi-agent-eval-replay-harness.7.md +3 -1
  53. package/docs/multi-agent-operator-ux.7.md +3 -1
  54. package/docs/node-snapshot-diff-replay.7.md +3 -1
  55. package/docs/observability-cost-accounting.7.md +3 -1
  56. package/docs/project-index.md +16 -3
  57. package/docs/real-execution-backends.7.md +3 -1
  58. package/docs/release-and-migration.7.md +3 -1
  59. package/docs/release-tooling.7.md +3 -1
  60. package/docs/run-registry-control-plane.7.md +27 -3
  61. package/docs/run-retention-reclamation.7.md +3 -1
  62. package/docs/state-explosion-management.7.md +3 -1
  63. package/docs/team-collaboration.7.md +3 -1
  64. package/docs/web-desktop-workbench.7.md +3 -1
  65. package/manifest/plugin.manifest.json +1 -1
  66. package/package.json +1 -1
  67. package/scripts/agents/builtin-templates.json +3 -2
  68. package/scripts/agents/claude-p-agent.js +6 -6
  69. package/scripts/agents/codex-agent.js +17 -3
  70. package/scripts/agents/deepseek-agent.js +23 -0
  71. package/scripts/agents/gemini-opencode-agent.js +25 -0
  72. package/scripts/agents/opencode-agent.js +57 -8
  73. package/scripts/architecture-review-fast.js +19 -5
  74. package/scripts/bump-version.js +16 -0
  75. package/scripts/canonical-apps.js +4 -4
  76. package/scripts/dogfood-release.js +1 -1
  77. package/scripts/golden-path.js +4 -4
  78. package/scripts/parity-check.js +9 -1
  79. package/scripts/release-flow.js +35 -0
  80. package/scripts/vendor-preflight.js +127 -0
  81. package/scripts/version-sync-check.js +5 -0
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleRun = handleRun;
4
+ const capability_core_1 = require("../../capability-core");
5
+ const run_registry_1 = require("../../run-registry");
6
+ const run_summary_1 = require("../run-summary");
7
+ const io_1 = require("../io");
8
+ /** `cw run <app> --drive [--once]` (Agent Delegation Drive) + the run-registry verbs
9
+ * (drive/search/list/show/resume/archive/rerun/export/import/verify-import/inspect-archive/restore). */
10
+ function handleRun(args, runner) {
11
+ // Agent Delegation Drive (v0.1.38): `cw run <app> --drive [--once]` drives a
12
+ // run end-to-end by delegating each worker to the agent backend. Distinct from
13
+ // the run-REGISTRY verbs below. `--preview` (or the `run drive <run-id>` form)
14
+ // is the read-only, deterministic next-step preview.
15
+ //
16
+ // A run-REGISTRY subcommand keyword (resume/show/...) must NOT be intercepted
17
+ // here just because it carries a --drive flag of its own — e.g.
18
+ // `run resume <id> --drive` is the resume verb's opt-in continuation, not
19
+ // `run <app=resume> --drive`. Fall through to the switch for those keywords.
20
+ const runRegistrySubcommand = new Set([
21
+ "drive", "search", "list", "show", "resume", "archive", "rerun", "export", "import", "verify-import", "inspect-archive", "restore"
22
+ ]);
23
+ if (args.options.drive && !runRegistrySubcommand.has(String(args.positionals[0] || ""))) {
24
+ const target = args.positionals[0];
25
+ const runId = (0, io_1.optionalArg)(args.options.run) || (0, io_1.optionalArg)(args.options.runId);
26
+ if (args.options.preview) {
27
+ (0, io_1.printJson)((0, capability_core_1.runDrivePreview)(runner, { ...args.options, runId: runId || target }));
28
+ return;
29
+ }
30
+ const driveArgs = { ...args.options };
31
+ if (runId)
32
+ driveArgs.runId = runId;
33
+ else
34
+ driveArgs.appId = target;
35
+ const dr = (0, capability_core_1.runDrive)(runner, driveArgs);
36
+ (0, io_1.printJson)(dr);
37
+ if (!(0, io_1.wantsJson)(args.options)) {
38
+ (0, run_summary_1.emitRunSummary)(runner, args.options, {
39
+ runId: dr.runId,
40
+ reportPath: dr.reportPath,
41
+ status: dr.status,
42
+ statePath: dr.statePath,
43
+ completedWorkers: dr.completedWorkers,
44
+ plannedWorkers: dr.plannedWorkers,
45
+ agentConfigured: dr.agentConfigured
46
+ });
47
+ }
48
+ return;
49
+ }
50
+ const registry = (0, capability_core_1.runRegistryFor)(args.options, runner);
51
+ const [subcommand, id] = args.positionals;
52
+ switch (subcommand) {
53
+ case "drive": {
54
+ // `run drive <run-id>` = read-only preview; `--step [--once]` = mutating drive.
55
+ if (args.options.step) {
56
+ const driveArgs = { ...args.options };
57
+ if (id)
58
+ driveArgs.runId = id;
59
+ const dr = (0, capability_core_1.runDrive)(runner, driveArgs);
60
+ (0, io_1.printJson)(dr);
61
+ if (!(0, io_1.wantsJson)(args.options)) {
62
+ (0, run_summary_1.emitRunSummary)(runner, args.options, {
63
+ runId: dr.runId,
64
+ reportPath: dr.reportPath,
65
+ status: dr.status,
66
+ statePath: dr.statePath,
67
+ completedWorkers: dr.completedWorkers,
68
+ plannedWorkers: dr.plannedWorkers,
69
+ agentConfigured: dr.agentConfigured
70
+ });
71
+ }
72
+ return;
73
+ }
74
+ (0, io_1.printJson)((0, capability_core_1.runDrivePreview)(runner, { ...args.options, runId: (0, io_1.required)(id, "run id") }));
75
+ return;
76
+ }
77
+ case "search": {
78
+ const result = (0, capability_core_1.runSearch)(registry, args.options);
79
+ if ((0, io_1.wantsJson)(args.options))
80
+ (0, io_1.printJson)(result);
81
+ else
82
+ process.stdout.write(`${(0, run_registry_1.formatRunSearch)(result)}\n`);
83
+ return;
84
+ }
85
+ case "list": {
86
+ const result = (0, capability_core_1.runList)(registry, args.options);
87
+ if ((0, io_1.wantsJson)(args.options))
88
+ (0, io_1.printJson)(result);
89
+ else
90
+ process.stdout.write(`${(0, run_registry_1.formatRunSearch)(result)}\n`);
91
+ return;
92
+ }
93
+ case "show": {
94
+ const result = (0, capability_core_1.runShow)(registry, (0, io_1.required)(id, "run id"), args.options);
95
+ if ((0, io_1.wantsJson)(args.options))
96
+ (0, io_1.printJson)(result);
97
+ else
98
+ process.stdout.write(`${(0, run_registry_1.formatRunShow)(result)}\n`);
99
+ return;
100
+ }
101
+ case "resume": {
102
+ const result = (0, capability_core_1.runResume)(registry, runner, (0, io_1.required)(id, "run id"), args.options);
103
+ if ((0, io_1.wantsJson)(args.options))
104
+ (0, io_1.printJson)(result);
105
+ else
106
+ process.stdout.write(`${(0, run_registry_1.formatResume)(result)}\n`);
107
+ return;
108
+ }
109
+ case "archive":
110
+ (0, io_1.printJson)((0, capability_core_1.runArchive)(registry, id, args.options));
111
+ return;
112
+ case "rerun":
113
+ (0, io_1.printJson)((0, capability_core_1.runRerun)(registry, (0, io_1.required)(id, "run id"), args.options));
114
+ return;
115
+ case "export":
116
+ (0, io_1.printJson)((0, capability_core_1.runExportArchive)(runner, (0, io_1.required)(id || (0, io_1.optionalArg)(args.options.runId || args.options.run), "run id"), args.options));
117
+ return;
118
+ case "import":
119
+ (0, io_1.printJson)((0, capability_core_1.runImportArchive)(runner, { ...args.options, archive: id || args.options.archive || args.options.path }));
120
+ return;
121
+ case "verify-import": {
122
+ const result = (0, capability_core_1.runVerifyImport)(runner, (0, io_1.required)(id || (0, io_1.optionalArg)(args.options.runId || args.options.run), "run id"), args.options);
123
+ (0, io_1.printJson)(result);
124
+ // Fail-closed ONLY behind --strict, so the default exit stays 0
125
+ // (byte-identical). With --strict, any failed restore check — including
126
+ // the new trust-audit row — exits 1 for `verify-import && restore`.
127
+ if (Boolean(args.options.strict) && !result.ok)
128
+ process.exitCode = 1;
129
+ return;
130
+ }
131
+ case "inspect-archive": {
132
+ const result = (0, capability_core_1.runInspectArchive)(runner, { ...args.options, archive: id || args.options.archive || args.options.path });
133
+ (0, io_1.printJson)(result);
134
+ // Read-only diagnostic: exit 1 when the archive fails any integrity check,
135
+ // so `cw run inspect-archive <path> && restore` stops on a bad archive.
136
+ if (!result.ok)
137
+ process.exitCode = 1;
138
+ return;
139
+ }
140
+ case "restore": {
141
+ const result = (0, capability_core_1.runRestoreArchive)(runner, { ...args.options, archive: id || args.options.archive || args.options.path });
142
+ (0, io_1.printJson)(result);
143
+ // Fail-closed: exit 1 when inspect OR verify failed, so a tampered or
144
+ // unverifiable archive never reports a made-up success (mirrors the
145
+ // inspect-archive exit-1 pattern).
146
+ if (!result.ok)
147
+ process.exitCode = 1;
148
+ return;
149
+ }
150
+ default:
151
+ throw new Error("Usage: cw.js run search|list|show|resume|archive|rerun|drive|export|import|verify-import|inspect-archive|restore [run-id|archive] [--scope repo|home] [--json] | cw.js run <app> --drive [--once] [--incremental] [--repo R --question Q]");
152
+ }
153
+ }
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.handleSchedule = handleSchedule;
7
+ exports.handleRoutine = handleRoutine;
8
+ exports.handleSched = handleSched;
9
+ // `cw schedule` / `cw routine` / `cw sched` handlers — the scheduling command
10
+ // family, carved out of the command-surface god-dispatch. Three sibling verbs:
11
+ // schedule — desktop scheduler (create/list/.../daemon) over the Scheduler
12
+ // routine — routine triggers (create/list/delete/fire/events) over the bridge
13
+ // sched — durable run-queue scheduling (plan/lease/release/.../policy)
14
+ const node_fs_1 = __importDefault(require("node:fs"));
15
+ const daemon_1 = require("../../daemon");
16
+ const capability_core_1 = require("../../capability-core");
17
+ const io_1 = require("../io");
18
+ /** `cw schedule create|list|delete|due|complete|pause|resume|run-now|history|daemon`. */
19
+ async function handleSchedule(args, scheduler) {
20
+ const [subcommand, id] = args.positionals;
21
+ switch (subcommand) {
22
+ case "create":
23
+ (0, io_1.printJson)(scheduler.create(args.options));
24
+ return;
25
+ case "list":
26
+ (0, io_1.printJson)(scheduler.list(args.options.status ? String(args.options.status) : undefined));
27
+ return;
28
+ case "delete":
29
+ (0, io_1.printJson)(scheduler.delete((0, io_1.required)(id, "schedule id")));
30
+ return;
31
+ case "due":
32
+ (0, io_1.printJson)(scheduler.due());
33
+ return;
34
+ case "complete":
35
+ (0, io_1.printJson)(scheduler.complete((0, io_1.required)(id, "schedule id"), args.options));
36
+ return;
37
+ case "pause":
38
+ (0, io_1.printJson)(scheduler.pause((0, io_1.required)(id, "schedule id")));
39
+ return;
40
+ case "resume":
41
+ (0, io_1.printJson)(scheduler.resume((0, io_1.required)(id, "schedule id")));
42
+ return;
43
+ case "run-now":
44
+ (0, io_1.printJson)(scheduler.runNow((0, io_1.required)(id, "schedule id")));
45
+ return;
46
+ case "history":
47
+ (0, io_1.printJson)(scheduler.history(id));
48
+ return;
49
+ case "daemon": {
50
+ const daemon = new daemon_1.DesktopSchedulerDaemon({
51
+ cwd: String(args.options.cwd || process.cwd()),
52
+ intervalSeconds: Number(args.options.intervalSeconds || args.options.interval || 60)
53
+ });
54
+ if (args.options.once) {
55
+ (0, io_1.printJson)(daemon.tick());
56
+ return;
57
+ }
58
+ await daemon.run();
59
+ return;
60
+ }
61
+ default:
62
+ throw new Error("Usage: cw.js schedule create|list|delete|due|complete|pause|resume|run-now|history|daemon");
63
+ }
64
+ }
65
+ /** `cw routine create|list|delete|fire|events`. */
66
+ function handleRoutine(args, triggers) {
67
+ const [subcommand, idOrKind, payloadPath] = args.positionals;
68
+ switch (subcommand) {
69
+ case "create":
70
+ (0, io_1.printJson)(triggers.create(args.options));
71
+ return;
72
+ case "list":
73
+ (0, io_1.printJson)(triggers.list(args.options.kind ? String(args.options.kind) : undefined));
74
+ return;
75
+ case "delete":
76
+ (0, io_1.printJson)(triggers.delete((0, io_1.required)(idOrKind, "trigger id")));
77
+ return;
78
+ case "fire": {
79
+ const kind = (0, io_1.required)(idOrKind, "trigger kind");
80
+ const payload = payloadPath ? JSON.parse(node_fs_1.default.readFileSync(payloadPath, "utf8")) : args.options;
81
+ (0, io_1.printJson)(triggers.fire(kind, payload));
82
+ return;
83
+ }
84
+ case "events":
85
+ (0, io_1.printJson)(triggers.events(idOrKind));
86
+ return;
87
+ default:
88
+ throw new Error("Usage: cw.js routine create|list|delete|fire|events");
89
+ }
90
+ }
91
+ /** `cw sched plan|lease|release|complete|reclaim|reset|policy [show|set]` — durable run-queue. */
92
+ function handleSched(args, runner) {
93
+ const registry = (0, capability_core_1.runRegistryFor)(args.options, runner);
94
+ const [subcommand, idArg] = args.positionals;
95
+ switch (subcommand) {
96
+ case "plan":
97
+ (0, io_1.printJson)((0, capability_core_1.schedPlan)(registry, args.options));
98
+ return;
99
+ case "lease":
100
+ (0, io_1.printJson)((0, capability_core_1.schedLease)(registry, args.options));
101
+ return;
102
+ case "release":
103
+ (0, io_1.printJson)((0, capability_core_1.schedRelease)(registry, { ...args.options, leaseId: args.options.leaseId || idArg }));
104
+ return;
105
+ case "complete":
106
+ (0, io_1.printJson)((0, capability_core_1.schedComplete)(registry, { ...args.options, leaseId: args.options.leaseId || idArg }));
107
+ return;
108
+ case "reclaim":
109
+ (0, io_1.printJson)((0, capability_core_1.schedReclaim)(registry, args.options));
110
+ return;
111
+ case "reset":
112
+ (0, io_1.printJson)((0, capability_core_1.schedReset)(registry, { ...args.options, id: args.options.id || idArg }));
113
+ return;
114
+ case "policy": {
115
+ const [, action] = args.positionals;
116
+ if (action === "set") {
117
+ (0, io_1.printJson)((0, capability_core_1.schedPolicySet)(registry, args.options));
118
+ return;
119
+ }
120
+ (0, io_1.printJson)((0, capability_core_1.schedPolicyShow)(registry));
121
+ return;
122
+ }
123
+ default:
124
+ throw new Error("Usage: cw.js sched plan|lease|release|complete|reclaim|reset|policy [show|set] [id] [--maxConcurrent N --maxAttempts N ...]");
125
+ }
126
+ }
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleWorkbench = handleWorkbench;
4
+ const workbench_1 = require("../../workbench");
5
+ const workbench_host_1 = require("../../workbench-host");
6
+ const format_1 = require("../format");
7
+ const io_1 = require("../io");
8
+ /** `cw workbench serve [--port N] [--once] | view <run-id> [--json]` — the optional
9
+ * read-only, localhost-only workbench. Behaviour-identical to the former inline case. */
10
+ async function handleWorkbench(args, runner) {
11
+ const [subcommand, runId] = args.positionals;
12
+ switch (subcommand) {
13
+ case "view": {
14
+ // Read-only five-panel view of one run. Same core entry as cw_workbench_view.
15
+ const view = (0, workbench_1.buildWorkbenchRunView)(runner, (0, io_1.required)(runId, "run id"));
16
+ if ((0, io_1.wantsJson)(args.options))
17
+ (0, io_1.printJson)(view);
18
+ else
19
+ process.stdout.write(`${(0, format_1.formatWorkbenchView)(view)}\n`);
20
+ return;
21
+ }
22
+ case "serve": {
23
+ // The OPTIONAL localhost host. `--once`/`--json` emit the descriptor only
24
+ // (no server); the default starts the read-only, localhost-only host.
25
+ if (args.options.once || (0, io_1.wantsJson)(args.options)) {
26
+ (0, io_1.printJson)((0, workbench_1.buildWorkbenchServeDescriptor)(runner, { ...args.options, once: true }));
27
+ return;
28
+ }
29
+ const host = new workbench_host_1.WorkbenchHost({
30
+ runner,
31
+ cwd: String(args.options.cwd || process.cwd()),
32
+ port: Number(args.options.port) || undefined,
33
+ scope: args.options.scope === "repo" ? "repo" : "home"
34
+ });
35
+ await host.run();
36
+ return;
37
+ }
38
+ default:
39
+ throw new Error("Usage: cw.js workbench serve [--port N] [--once] | view <run-id> [--json]");
40
+ }
41
+ }
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleWorker = handleWorker;
4
+ const operator_ux_1 = require("../../operator-ux");
5
+ const io_1 = require("../io");
6
+ /** `cw worker list|summary|show|manifest|output|fail|validate <run-id> [worker-id] [result-file]`. */
7
+ function handleWorker(args, runner) {
8
+ const [subcommand, runId, workerId, resultPath] = args.positionals;
9
+ switch (subcommand) {
10
+ case "list":
11
+ (0, io_1.printJson)(runner.listWorkers((0, io_1.required)(runId, "run id"), args.options));
12
+ return;
13
+ case "summary": {
14
+ const summary = runner.summarizeWorkerRecords((0, io_1.required)(runId, "run id"));
15
+ if ((0, io_1.wantsJson)(args.options))
16
+ (0, io_1.printJson)(summary);
17
+ else
18
+ process.stdout.write(`${(0, operator_ux_1.formatWorkerSummary)(summary)}\n`);
19
+ return;
20
+ }
21
+ case "show":
22
+ (0, io_1.printJson)(runner.showWorker((0, io_1.required)(runId, "run id"), (0, io_1.required)(workerId, "worker id")));
23
+ return;
24
+ case "manifest":
25
+ (0, io_1.printJson)(runner.showWorkerManifest((0, io_1.required)(runId, "run id"), (0, io_1.required)(workerId, "worker id")));
26
+ return;
27
+ case "output":
28
+ (0, io_1.printJson)(runner.recordWorkerOutput((0, io_1.required)(runId, "run id"), (0, io_1.required)(workerId, "worker id"), (0, io_1.required)(resultPath, "result file"), args.options));
29
+ return;
30
+ case "fail":
31
+ (0, io_1.printJson)(runner.recordWorkerFailure((0, io_1.required)(runId, "run id"), (0, io_1.required)(workerId, "worker id"), String(args.options.message || (0, io_1.required)(resultPath, "failure message")), args.options));
32
+ return;
33
+ case "validate": {
34
+ // Non-null = a boundary violation: a validate verb must report an invalid
35
+ // verdict through its exit code, not just print it and exit 0.
36
+ const violation = runner.validateWorker((0, io_1.required)(runId, "run id"), (0, io_1.required)(workerId, "worker id"), resultPath);
37
+ (0, io_1.printJson)(violation);
38
+ if (violation)
39
+ process.exitCode = 1;
40
+ return;
41
+ }
42
+ default:
43
+ throw new Error("Usage: cw.js worker list|summary|show|manifest|output|fail|validate <run-id> [worker-id] [result-file]");
44
+ }
45
+ }
package/dist/cli/io.js ADDED
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ // Shared CLI input/output helpers, extracted from command-surface.ts so the
3
+ // dispatcher and per-command handler modules import ONE copy instead of carrying
4
+ // these in the god-object. Pure + zero-dep: arg coercion + JSON stdout.
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.required = required;
7
+ exports.optionalArg = optionalArg;
8
+ exports.printJson = printJson;
9
+ exports.wantsJson = wantsJson;
10
+ /** Require a positional/option value or fail with a copy-pasteable recovery tip. */
11
+ function required(value, label) {
12
+ if (!value)
13
+ throw new Error(`Missing ${label}.\n Tip: find run ids with "cw run list" or create one with "cw quickstart"`);
14
+ return value;
15
+ }
16
+ /** Normalize an optional CLI arg to a trimmed non-empty string, else undefined. */
17
+ function optionalArg(value) {
18
+ return typeof value === "string" && value.trim() ? value.trim() : undefined;
19
+ }
20
+ /** Machine payload to stdout (stdout = data; never colored, never chrome). */
21
+ function printJson(value) {
22
+ process.stdout.write(`${JSON.stringify(value, null, 2)}\n`);
23
+ }
24
+ /** True when the caller asked for JSON output (`--json` or `--format json`). */
25
+ function wantsJson(options) {
26
+ return Boolean(options.json || options.format === "json");
27
+ }
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.emitRunSummary = emitRunSummary;
7
+ // Shared calm end-of-run summary helper, lifted out of command-surface.ts so the
8
+ // `audit-run`/`quickstart` path (still in the dispatcher) AND the carved `run`
9
+ // drive paths (src/cli/handlers/run.ts) emit ONE identical summary — no copy.
10
+ // Stderr/human-side ONLY: stdout (the `--json` payload) stays byte-exact.
11
+ const node_fs_1 = __importDefault(require("node:fs"));
12
+ const node_path_1 = __importDefault(require("node:path"));
13
+ const capability_core_1 = require("../capability-core");
14
+ const reporter_1 = require("../reporter");
15
+ /** Emit the calm end-of-run summary (stderr, TTY-gated inside the reporter): the COMPACT findings
16
+ * table re-parsed from each completed worker's `cw:result`, the report path, where the per-worker
17
+ * transcripts live, and — under `--full` — the report inline. Stderr/human-side ONLY: stdout (the
18
+ * `--json` payload printed just before this) stays byte-exact. Shared by the quickstart and the
19
+ * two `run --drive` paths so all three render an identical summary. */
20
+ function emitRunSummary(runner, options, fields) {
21
+ // Anchor run reads to the run's OWN repo (a drive/quickstart may run cross-directory): the run
22
+ // dir is <repo>/.cw/runs/<id>/, holding each worker's transcript.md next to its result.md.
23
+ const runDir = typeof fields.statePath === "string" ? node_path_1.default.dirname(fields.statePath) : undefined;
24
+ const baseDir = runDir ? node_path_1.default.resolve(runDir, "..", "..", "..") : undefined;
25
+ const findings = (0, capability_core_1.collectRunFindings)(runner, fields.runId, baseDir);
26
+ // --full ALSO prints the report inline at run end (the compact table stays the default summary).
27
+ let fullReport;
28
+ if (options.full && fields.reportPath && node_fs_1.default.existsSync(fields.reportPath)) {
29
+ try {
30
+ fullReport = node_fs_1.default.readFileSync(fields.reportPath, "utf8");
31
+ }
32
+ catch { /* best-effort inline */ }
33
+ }
34
+ reporter_1.reporter.runSummary({
35
+ runId: fields.runId,
36
+ reportPath: fields.reportPath,
37
+ status: fields.status,
38
+ completedWorkers: fields.completedWorkers,
39
+ plannedWorkers: fields.plannedWorkers,
40
+ agentConfigured: fields.agentConfigured,
41
+ findings,
42
+ runDir,
43
+ fullReport
44
+ });
45
+ }
package/dist/commit.js CHANGED
@@ -80,11 +80,6 @@ function commitState(run, input) {
80
80
  candidateId: gate.candidateId,
81
81
  selectionId: gate.selectionId,
82
82
  evidence,
83
- // Partial commit (v0.1.59): operator commits only specified tasks.
84
- // Failed/pending tasks remain active for later retry. The verifier gate
85
- // still applies per-task; partial is about scope, not about skipping gates.
86
- partial: Array.isArray(options.partialTaskIds) && options.partialTaskIds.length > 0 || undefined,
87
- partialTaskIds: options.partialTaskIds?.length ? options.partialTaskIds : undefined,
88
83
  acceptanceRationale: gate.rationale
89
84
  ? {
90
85
  ...gate.rationale,
@@ -34,18 +34,15 @@ exports.backendIds = backendIds;
34
34
  exports.isBackendId = isBackendId;
35
35
  exports.getBackendDescriptor = getBackendDescriptor;
36
36
  exports.resolveBackendSelection = resolveBackendSelection;
37
- exports.backendSelectionFrom = backendSelectionFrom;
38
37
  exports.requiredSandboxDimensions = requiredSandboxDimensions;
39
38
  exports.attestSandbox = attestSandbox;
40
39
  exports.probeBackend = probeBackend;
41
40
  exports.runBackend = runBackend;
42
41
  exports.createExecutionBackend = createExecutionBackend;
43
- exports.listExecutionBackends = listExecutionBackends;
44
42
  exports.backendListPayload = backendListPayload;
45
43
  exports.backendShowPayload = backendShowPayload;
46
44
  exports.backendProbePayload = backendProbePayload;
47
45
  exports.buildChildEnv = buildChildEnv;
48
- exports.clearProbeCache = clearProbeCache;
49
46
  const node_fs_1 = __importDefault(require("node:fs"));
50
47
  const node_path_1 = __importDefault(require("node:path"));
51
48
  const node_child_process_1 = require("node:child_process");
@@ -265,10 +262,6 @@ function resolveBackendSelection(requested, env = process.env) {
265
262
  }
266
263
  return { backendId: exports.DEFAULT_BACKEND_ID, source: "default" };
267
264
  }
268
- function backendSelectionFrom(args, env = process.env) {
269
- const requested = (0, util_1.firstString)(args.backend, args.backendId, args.executionBackend);
270
- return resolveBackendSelection(requested, env);
271
- }
272
265
  // ---------------------------------------------------------------------------
273
266
  // Sandbox dimension mapping + attestation. The sandbox profile is the contract.
274
267
  // ---------------------------------------------------------------------------
@@ -852,9 +845,6 @@ function createExecutionBackend(id) {
852
845
  run: (request) => runBackend({ ...request, backendId: id })
853
846
  };
854
847
  }
855
- function listExecutionBackends() {
856
- return backendIds().map(createExecutionBackend);
857
- }
858
848
  // ---- inspection payloads (shared by CLI + MCP via the orchestrator) --------
859
849
  function backendListPayload() {
860
850
  return { schemaVersion: 1, default: exports.DEFAULT_BACKEND_ID, backends: listBackendDescriptors() };
@@ -916,4 +906,3 @@ function cachedProbeBackend(id, context) {
916
906
  _probeCache.set(key, { result, at: Date.now() });
917
907
  return result;
918
908
  }
919
- function clearProbeCache() { _probeCache.clear(); }
@@ -364,6 +364,8 @@ function callTool(name, args) {
364
364
  return (0, capability_core_1.runVerifyImport)(runner, String(args.runId || ""), args);
365
365
  case "cw_run_inspect_archive":
366
366
  return (0, capability_core_1.runInspectArchive)(runner, args);
367
+ case "cw_run_restore":
368
+ return (0, capability_core_1.runRestoreArchive)(runner, args);
367
369
  case "cw_report_verify_bundle":
368
370
  return (0, capability_core_1.runVerifyReportBundle)(runner, args);
369
371
  case "cw_report_bundle":
@@ -837,6 +837,14 @@ function toolDefinitions() {
837
837
  file: stringSchema("Alias for archive"),
838
838
  cwd: stringSchema("Invocation workspace")
839
839
  }),
840
+ capabilityTool("run.restore", "Fail-closed restore of a portable run archive in one step: integrity-inspect the bundle first (writes nothing), import it, then verify the imported run. Reports ok:true only when both inspect and verify pass; refuses (ok:false, exit 1) a tampered or unverifiable bundle, importing nothing. Peer of `cw run restore`.", {
841
+ archive: stringSchema("Archive path"),
842
+ path: stringSchema("Alias for archive"),
843
+ file: stringSchema("Alias for archive"),
844
+ target: stringSchema("Restore target repo directory"),
845
+ repo: stringSchema("Alias for target"),
846
+ cwd: stringSchema("Invocation workspace")
847
+ }),
840
848
  capabilityTool("report.verify-bundle", "Offline, self-contained verify of a portable run bundle: proves the archive bytes, the telemetry hash chain, the trust-audit chain, and (with the bundle's embedded public key) the ed25519 signatures — no source repo, no pre-existing .cw tree, no out-of-band key. Restores into a throwaway tmpdir and writes nothing. A forged or edited bundle fails it. Peer of `cw report verify-bundle`.", {
841
849
  archive: stringSchema("Bundle (.cwrun.json) path"),
842
850
  path: stringSchema("Alias for archive"),