cool-workflow 0.2.0 → 0.2.2

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 (141) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codex-plugin/plugin.json +1 -1
  3. package/README.md +7 -5
  4. package/apps/architecture-review/app.json +2 -2
  5. package/apps/architecture-review/workflow.js +12 -12
  6. package/apps/architecture-review-fast/app.json +1 -1
  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/cli/dispatch.js +20 -88
  12. package/dist/cli/parseargv.js +6 -3
  13. package/dist/core/capability-data.js +270 -0
  14. package/dist/core/capability-table.js +15 -3519
  15. package/dist/core/format/help.js +30 -7
  16. package/dist/core/hash.js +1 -1
  17. package/dist/core/multi-agent/candidate-scoring.js +1 -1
  18. package/dist/core/multi-agent/collaboration.js +3 -2
  19. package/dist/core/multi-agent/coordinator.js +4 -3
  20. package/dist/core/multi-agent/eval-replay.js +1 -1
  21. package/dist/core/multi-agent/runtime.js +2 -2
  22. package/dist/core/multi-agent/trust-policy.js +1 -1
  23. package/dist/core/pipeline/commit-gate.js +2 -1
  24. package/dist/core/pipeline/contract.js +1 -1
  25. package/dist/core/pipeline/drive-decide.js +1 -1
  26. package/dist/core/state/contract-migration.js +1 -1
  27. package/dist/core/state/migrations.js +2 -2
  28. package/dist/core/state/node-snapshot.js +1 -1
  29. package/dist/core/state/state-explosion/digest.js +3 -2
  30. package/dist/core/state/state-explosion/graph.js +13 -12
  31. package/dist/core/state/state-explosion/helpers.js +5 -4
  32. package/dist/core/state/state-explosion/report.js +1 -1
  33. package/dist/core/state/state-explosion/size.js +1 -1
  34. package/dist/core/state/state-node.js +2 -2
  35. package/dist/core/state/types.js +1 -1
  36. package/dist/core/trust/ledger.js +3 -2
  37. package/dist/core/trust/telemetry-attestation.js +3 -3
  38. package/dist/core/trust/telemetry-ledger.js +2 -2
  39. package/dist/core/types/execution-backend.js +18 -0
  40. package/dist/core/types/observability.js +7 -0
  41. package/dist/core/util/collate.js +23 -0
  42. package/dist/core/version.js +1 -1
  43. package/dist/core/workflow-apps/app-schema.js +1 -1
  44. package/dist/mcp/dispatch.js +1 -1
  45. package/dist/mcp/server.js +1 -1
  46. package/dist/shell/agent-config.js +1 -1
  47. package/dist/shell/audit-cli.js +46 -2
  48. package/dist/shell/commit-summary.js +2 -1
  49. package/dist/shell/doctor.js +17 -4
  50. package/dist/shell/drive.js +47 -19
  51. package/dist/shell/evidence-reasoning.js +4 -3
  52. package/dist/shell/execution-backend/agent.js +42 -10
  53. package/dist/shell/execution-backend/ci.js +1 -1
  54. package/dist/shell/execution-backend/container.js +1 -1
  55. package/dist/shell/execution-backend/envelopes.js +1 -1
  56. package/dist/shell/execution-backend/local.js +1 -1
  57. package/dist/shell/execution-backend/probes.js +1 -1
  58. package/dist/shell/execution-backend/registry.js +3 -2
  59. package/dist/shell/execution-backend/remote.js +1 -1
  60. package/dist/shell/execution-backend/types.js +0 -9
  61. package/dist/shell/fs-atomic.js +15 -2
  62. package/dist/shell/ledger-io.js +1 -1
  63. package/dist/shell/metrics-cli.js +4 -2
  64. package/dist/shell/multi-agent-host.js +1 -1
  65. package/dist/shell/multi-agent-operator-ux.js +4 -3
  66. package/dist/shell/observability.js +12 -11
  67. package/dist/shell/onramp.js +17 -1
  68. package/dist/shell/operator-ux-text.js +2 -1
  69. package/dist/shell/operator-ux.js +7 -6
  70. package/dist/shell/pipeline-cli.js +82 -72
  71. package/dist/shell/reclamation-io.js +3 -2
  72. package/dist/shell/registry-cli.js +15 -0
  73. package/dist/shell/report.js +2 -1
  74. package/dist/shell/run-registry-io.js +1 -1
  75. package/dist/shell/run-store.js +17 -0
  76. package/dist/shell/sandbox-profile.js +1 -1
  77. package/dist/shell/scheduler-io.js +46 -37
  78. package/dist/shell/scheduling-io.js +32 -22
  79. package/dist/shell/state-explosion-cli.js +2 -1
  80. package/dist/shell/telemetry-ledger-io.js +1 -1
  81. package/dist/shell/term.js +1 -1
  82. package/dist/shell/topology-io.js +2 -1
  83. package/dist/shell/trust-audit.js +45 -5
  84. package/dist/shell/workbench-host.js +9 -1
  85. package/dist/shell/workbench.js +6 -11
  86. package/dist/shell/worker-cli.js +9 -1
  87. package/dist/shell/worker-isolation.js +34 -9
  88. package/dist/shell/workflow-app-loader.js +3 -2
  89. package/dist/wiring/capability-table/basics.js +66 -0
  90. package/dist/wiring/capability-table/exec-backend.js +162 -0
  91. package/dist/wiring/capability-table/index.js +42 -0
  92. package/dist/wiring/capability-table/multi-agent.js +623 -0
  93. package/dist/wiring/capability-table/parity.js +466 -0
  94. package/dist/wiring/capability-table/pipeline.js +280 -0
  95. package/dist/wiring/capability-table/registry-core.js +189 -0
  96. package/dist/wiring/capability-table/reporting.js +394 -0
  97. package/dist/wiring/capability-table/scheduling-registry.js +558 -0
  98. package/dist/wiring/capability-table/state.js +173 -0
  99. package/dist/wiring/capability-table/trust-ledger.js +134 -0
  100. package/dist/wiring/capability-table/workflow-apps.js +366 -0
  101. package/docs/agent-delegation-drive.7.md +4 -0
  102. package/docs/cli-mcp-parity.7.md +9 -2
  103. package/docs/contract-migration-tooling.7.md +4 -0
  104. package/docs/control-plane-scheduling.7.md +4 -0
  105. package/docs/durable-state-and-locking.7.md +24 -0
  106. package/docs/evidence-adoption-reasoning-chain.7.md +4 -0
  107. package/docs/execution-backends.7.md +4 -0
  108. package/docs/index.md +1 -0
  109. package/docs/multi-agent-cli-mcp-surface.7.md +4 -0
  110. package/docs/multi-agent-eval-replay-harness.7.md +4 -0
  111. package/docs/multi-agent-operator-ux.7.md +4 -0
  112. package/docs/node-snapshot-diff-replay.7.md +4 -0
  113. package/docs/observability-cost-accounting.7.md +6 -1
  114. package/docs/project-index.md +30 -5
  115. package/docs/real-execution-backends.7.md +4 -0
  116. package/docs/release-and-migration.7.md +4 -0
  117. package/docs/release-tooling.7.md +4 -0
  118. package/docs/remote-source-review.7.md +4 -4
  119. package/docs/report-verifiable-bundle.7.md +1 -1
  120. package/docs/run-registry-control-plane.7.md +4 -0
  121. package/docs/run-retention-reclamation.7.md +4 -0
  122. package/docs/security-trust-hardening.7.md +33 -1
  123. package/docs/state-explosion-management.7.md +4 -0
  124. package/docs/team-collaboration.7.md +4 -0
  125. package/docs/trust-audit-anchor.7.md +69 -0
  126. package/docs/web-desktop-workbench.7.md +15 -1
  127. package/manifest/plugin.manifest.json +1 -1
  128. package/package.json +3 -1
  129. package/scripts/agents/agent-adapter-core.js +22 -2
  130. package/scripts/agents/claude-p-agent.js +8 -3
  131. package/scripts/agents/gemini-agent.js +5 -1
  132. package/scripts/agents/opencode-agent.js +5 -1
  133. package/scripts/bump-version.js +24 -2
  134. package/scripts/canonical-apps.js +4 -4
  135. package/scripts/dogfood-release.js +1 -1
  136. package/scripts/golden-path.js +4 -4
  137. package/scripts/purity-baseline.json +68 -0
  138. package/scripts/purity-gate.js +239 -0
  139. package/scripts/release-check.js +8 -1
  140. package/scripts/version-sync-check.js +33 -12
  141. package/workflows/README.md +19 -0
@@ -0,0 +1,280 @@
1
+ "use strict";
2
+ // wiring/capability-table/pipeline.ts — MILESTONE 6+7 (plan, run.drive*,
3
+ // dispatch, result, commit, commit.summary) + MILESTONE 11's run.export/
4
+ // import/verify-import/inspect-archive/restore CLI bindings. Split out of
5
+ // core/capability-table.ts, byte-for-byte (extracted with sed, not
6
+ // retyped).
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ const registry_core_1 = require("./registry-core");
9
+ const io_1 = require("../../cli/io");
10
+ const io_2 = require("../../cli/io");
11
+ // MILESTONE 6+7 (combined; see docs/rebuild/PLAN.md Open risk 10) CLI bindings:
12
+ // plan, quickstart, run --drive, run drive (preview), dispatch, result,
13
+ // commit. Handler BODIES live in shell/pipeline-cli.ts (impure — they
14
+ // plan/drive/dispatch/commit real run state on disk); this table only
15
+ // wires argv shape -> handler call, per cli/dispatch.ts's generic
16
+ // executor contract.
17
+ // ---------------------------------------------------------------------
18
+ const pipeline_cli_1 = require("../../shell/pipeline-cli");
19
+ const commit_summary_1 = require("../../shell/commit-summary");
20
+ (0, registry_core_1.attachCliBinding)("plan", {
21
+ path: ["plan"],
22
+ jsonMode: "default",
23
+ handler: (args) => {
24
+ const workflowId = (0, io_2.optionalArg)(args.positionals[0]);
25
+ if (!workflowId) {
26
+ throw new Error('Missing workflow id.\n Tip: plan an architecture review with "cw plan architecture-review"');
27
+ }
28
+ return { json: (0, pipeline_cli_1.planRun)({ ...args.options, workflowId }) };
29
+ },
30
+ });
31
+ // `cw run <app> --drive [--once]` and `cw run drive <run-id> [--step]`
32
+ // share the single `run` dispatch path (byte-exact to the old build's
33
+ // handleRun: a run-REGISTRY subcommand keyword is never hijacked by the
34
+ // bare `--drive` intercept just because it carries its own --drive/--step
35
+ // flag). Both rows below dispatch on `["run"]`; the FIRST one registered
36
+ // (run.drive.step) is found first by findCapabilityByCliPath's linear
37
+ // scan, so its handler carries the full branch — the second row exists
38
+ // only so `cw help run` lists both capabilities.
39
+ (0, registry_core_1.attachCliBinding)("run.drive.step", {
40
+ path: ["run"],
41
+ helpPath: ["run", "drive"],
42
+ jsonMode: "default",
43
+ handler: (args) => {
44
+ const registrySubcommands = new Set(["drive", "search", "list", "show", "resume", "archive", "rerun", "export", "import", "verify-import", "inspect-archive", "restore"]);
45
+ const target = args.positionals[0];
46
+ if (args.options.drive && !registrySubcommands.has(String(target || ""))) {
47
+ const runId = (0, io_2.optionalArg)(args.options.run) || (0, io_2.optionalArg)(args.options.runId);
48
+ if (args.options.preview)
49
+ return { json: (0, pipeline_cli_1.runDrivePreview)({ ...args.options, runId: runId || target }) };
50
+ const driveArgs = { ...args.options };
51
+ if (runId)
52
+ driveArgs.runId = runId;
53
+ else
54
+ driveArgs.appId = target;
55
+ return { json: (0, pipeline_cli_1.runDriveStep)(driveArgs) };
56
+ }
57
+ const [subcommand, id] = args.positionals;
58
+ if (subcommand === "drive") {
59
+ if (args.options.step) {
60
+ const driveArgs = { ...args.options };
61
+ if (id)
62
+ driveArgs.runId = id;
63
+ return { json: (0, pipeline_cli_1.runDriveStep)(driveArgs) };
64
+ }
65
+ return { json: (0, pipeline_cli_1.runDrivePreview)({ ...args.options, runId: (0, io_1.required)(id, "run id") }) };
66
+ }
67
+ // MILESTONE 11 (reporting/run-export) — the archive family. Handler
68
+ // bodies live in shell/run-export-cli.ts; this arm only wires argv
69
+ // shape -> handler call.
70
+ if (subcommand === "export") {
71
+ const result = (0, run_export_cli_1.runExportCli)((0, io_1.required)(id, "run id"), args.options);
72
+ return { json: result };
73
+ }
74
+ if (subcommand === "import") {
75
+ const result = (0, run_export_cli_1.runImportCli)((0, io_1.required)(id, "archive path"), args.options);
76
+ return { json: result };
77
+ }
78
+ if (subcommand === "verify-import") {
79
+ const result = (0, run_export_cli_1.runVerifyImportCli)((0, io_1.required)(id, "run id"), args.options);
80
+ return { json: result, exitCode: args.options.strict && !result.ok ? 1 : undefined };
81
+ }
82
+ if (subcommand === "inspect-archive") {
83
+ const result = (0, run_export_cli_1.runInspectArchiveCli)((0, io_1.required)(id, "archive path"), args.options);
84
+ return { json: result, exitCode: result.ok ? undefined : 1 };
85
+ }
86
+ if (subcommand === "restore") {
87
+ const result = (0, run_export_cli_1.runRestoreCli)((0, io_1.required)(id, "archive path"), args.options);
88
+ return { json: result, exitCode: result.ok ? undefined : 1 };
89
+ }
90
+ 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]");
91
+ },
92
+ });
93
+ // PARITY: `run.drive` (the read-only MCP preview tool) now ALSO carries
94
+ // its own two-token `cli.path` ["run","drive"], same as the old build's
95
+ // registry row (cli.path ["run","drive"]) and the same reversed-
96
+ // candidate-order pattern already used for run.search/run.list/etc.
97
+ // (see those rows' own comment below): findCapabilityByCliPath tries the
98
+ // 2-token candidate BEFORE the 1-token ["run"] row, so this row — not
99
+ // run.drive.step's combined switch — now serves `cw run drive <run-id>`
100
+ // [--step]. Behavior is unchanged (same runDrivePreview/runDriveStep
101
+ // calls, same --step branch run.drive.step's switch already used); only
102
+ // WHICH row answers the dispatch changes, so run.drive becomes a real
103
+ // both-surface, dual-bound capability for the payload-identity probe.
104
+ (0, registry_core_1.attachCliBinding)("run.drive", {
105
+ path: ["run", "drive"],
106
+ jsonMode: "default",
107
+ handler: (args) => {
108
+ const id = args.positionals[0];
109
+ if (args.options.step) {
110
+ const driveArgs = { ...args.options };
111
+ if (id)
112
+ driveArgs.runId = id;
113
+ return { json: (0, pipeline_cli_1.runDriveStep)(driveArgs) };
114
+ }
115
+ return { json: (0, pipeline_cli_1.runDrivePreview)({ ...args.options, runId: (0, io_1.required)(id, "run id") }) };
116
+ },
117
+ });
118
+ registry_core_1.REGISTRY_BY_CAPABILITY.get("run.drive").mcp.handler = (args) => (0, pipeline_cli_1.runDrivePreview)(args);
119
+ registry_core_1.REGISTRY_BY_CAPABILITY.get("run.drive.step").mcp.handler = (args) => (0, pipeline_cli_1.runDriveStep)(args);
120
+ // PARITY: `run.drive.step` advances the run by spawning the external
121
+ // agent per worker and recording attested output — not a read probe.
122
+ // CLI (--drive/--step) and MCP route through the same drive() core; the
123
+ // opt-out is the documented divergence, not undocumented drift.
124
+ registry_core_1.REGISTRY_BY_CAPABILITY.get("run.drive.step").payloadIdentical = false;
125
+ registry_core_1.REGISTRY_BY_CAPABILITY.get("run.drive.step").reason =
126
+ "Mutating: advances the run by spawning the external agent per worker and recording attested output — not a read probe. CLI (--drive/--step) and MCP route through the same drive() core.";
127
+ registry_core_1.REGISTRY_BY_CAPABILITY.get("plan").mcp.handler = (args) => (0, pipeline_cli_1.planRun)(args);
128
+ // GAP #24: dispatchRun reads the sandbox profile from `args.sandbox` only
129
+ // (the CLI's --sandbox flag). The cw_dispatch MCP tool also accepts the
130
+ // `sandboxProfile`/`sandboxProfileId` aliases (its declared properties), so
131
+ // normalize them onto `sandbox` here — mirrors the old build's
132
+ // sandboxProfileIdFrom() alias set — before handing off.
133
+ registry_core_1.REGISTRY_BY_CAPABILITY.get("dispatch").mcp.handler = (args) => (0, pipeline_cli_1.dispatchRun)({ ...args, sandbox: args.sandbox ?? args.sandboxProfile ?? args.sandboxProfileId });
134
+ registry_core_1.REGISTRY_BY_CAPABILITY.get("result").mcp.handler = (args) => (0, pipeline_cli_1.recordResultRun)(args);
135
+ // `cw_commit` returns the FLAT commit envelope (verifierGated/checkpoint/
136
+ // selectionId/… at the top level, plus a nested `commit`), matching the old
137
+ // build's commitEnvelope. `commitRun` (CLI shape) returns `{ runId, commit }`;
138
+ // lift the commit's key fields to the top for the MCP surface.
139
+ registry_core_1.REGISTRY_BY_CAPABILITY.get("commit").mcp.handler = (args) => {
140
+ const result = (0, pipeline_cli_1.commitRun)(args);
141
+ const commit = result.commit || {};
142
+ return {
143
+ runId: result.runId,
144
+ commitId: commit.id,
145
+ verifierGated: commit.verifierGated,
146
+ checkpoint: commit.checkpoint,
147
+ verifierNodeId: commit.verifierNodeId,
148
+ candidateId: commit.candidateId,
149
+ selectionId: commit.selectionId,
150
+ evidenceCount: Array.isArray(commit.evidence) ? commit.evidence.length : 0,
151
+ snapshotPath: commit.snapshotPath,
152
+ commit,
153
+ };
154
+ };
155
+ // PARITY: `commit` is the one declared payload projection (byte-compat
156
+ // item 5 above). Both surfaces route through the single core entry
157
+ // runner.commit (commitRun); the CLI keeps the raw StateCommitResult for
158
+ // scripting while cw_commit lifts an operator-facing envelope on top (see
159
+ // the mcp.handler just above). Marked here, not silently let drift, so
160
+ // the parity payload probe (core/capability-table.ts's
161
+ // payloadIdenticalCapabilities) skips it with a paper trail instead of
162
+ // tripping on an undocumented divergence.
163
+ registry_core_1.REGISTRY_BY_CAPABILITY.get("commit").payloadIdentical = false;
164
+ registry_core_1.REGISTRY_BY_CAPABILITY.get("commit").reason =
165
+ "Both surfaces route through the single core entry runner.commit. The CLI emits the raw StateCommitResult for scripting (commit.id, commit.evidence, commit.gate); cw_commit emits the operator commit envelope (commitId, verifierGated, checkpoint, evidenceCount, snapshotPath, nextActions, plus the raw result under `commit`). Declared projection, not drift.";
166
+ // MILESTONE 11 — run.export/import/verify-import/inspect-archive/restore
167
+ // MCP handlers (the CLI side is served by run.drive.step's combined
168
+ // handler above; these tools are called directly by name over MCP, so
169
+ // each needs its own mcp.handler per byte-compat item 5's two-field
170
+ // row shape).
171
+ const run_export_cli_1 = require("../../shell/run-export-cli");
172
+ registry_core_1.REGISTRY_BY_CAPABILITY.get("run.export").mcp.handler = (args) => (0, run_export_cli_1.runExportCli)((0, io_1.required)((0, io_2.optionalArg)(args.runId), "run id"), args);
173
+ registry_core_1.REGISTRY_BY_CAPABILITY.get("run.import").mcp.handler = (args) => (0, run_export_cli_1.runImportCli)((0, io_1.required)((0, io_2.optionalArg)(args.archive || args.path || args.file), "archive path"), args);
174
+ registry_core_1.REGISTRY_BY_CAPABILITY.get("run.verify-import").mcp.handler = (args) => (0, run_export_cli_1.runVerifyImportCli)((0, io_1.required)((0, io_2.optionalArg)(args.runId), "run id"), args);
175
+ registry_core_1.REGISTRY_BY_CAPABILITY.get("run.inspect-archive").mcp.handler = (args) => (0, run_export_cli_1.runInspectArchiveCli)((0, io_1.required)((0, io_2.optionalArg)(args.archive || args.path || args.file), "archive path"), args);
176
+ registry_core_1.REGISTRY_BY_CAPABILITY.get("run.restore").mcp.handler = (args) => (0, run_export_cli_1.runRestoreCli)((0, io_1.required)((0, io_2.optionalArg)(args.archive || args.path || args.file), "archive path"), args);
177
+ // `run export|import|verify-import|inspect-archive|restore` each carry their
178
+ // own two-token cli.path (found before the ["run"] run.drive.step catch-all
179
+ // per the reversed candidate order), calling the same shell fns with the
180
+ // same [subcommand, id] positional mapping and exit-code shape the catch-all
181
+ // switch already used. `hiddenFromHelp` keeps the byte-pinned `cw help run`
182
+ // fixture's rows coming from the single literal COMMAND_HELP_ROWS.run block.
183
+ (0, registry_core_1.attachCliBinding)("run.export", {
184
+ path: ["run", "export"],
185
+ jsonMode: "default",
186
+ hiddenFromHelp: true,
187
+ handler: (args) => ({ json: (0, run_export_cli_1.runExportCli)((0, io_1.required)(args.positionals[0], "run id"), args.options) }),
188
+ });
189
+ (0, registry_core_1.attachCliBinding)("run.import", {
190
+ path: ["run", "import"],
191
+ jsonMode: "default",
192
+ hiddenFromHelp: true,
193
+ handler: (args) => ({ json: (0, run_export_cli_1.runImportCli)((0, io_1.required)(args.positionals[0], "archive path"), args.options) }),
194
+ });
195
+ (0, registry_core_1.attachCliBinding)("run.verify-import", {
196
+ path: ["run", "verify-import"],
197
+ jsonMode: "default",
198
+ hiddenFromHelp: true,
199
+ handler: (args) => {
200
+ const result = (0, run_export_cli_1.runVerifyImportCli)((0, io_1.required)(args.positionals[0], "run id"), args.options);
201
+ return { json: result, exitCode: args.options.strict && !result.ok ? 1 : undefined };
202
+ },
203
+ });
204
+ (0, registry_core_1.attachCliBinding)("run.inspect-archive", {
205
+ path: ["run", "inspect-archive"],
206
+ jsonMode: "default",
207
+ hiddenFromHelp: true,
208
+ handler: (args) => {
209
+ const result = (0, run_export_cli_1.runInspectArchiveCli)((0, io_1.required)(args.positionals[0], "archive path"), args.options);
210
+ return { json: result, exitCode: result.ok ? undefined : 1 };
211
+ },
212
+ });
213
+ (0, registry_core_1.attachCliBinding)("run.restore", {
214
+ path: ["run", "restore"],
215
+ jsonMode: "default",
216
+ hiddenFromHelp: true,
217
+ handler: (args) => {
218
+ const result = (0, run_export_cli_1.runRestoreCli)((0, io_1.required)(args.positionals[0], "archive path"), args.options);
219
+ return { json: result, exitCode: result.ok ? undefined : 1 };
220
+ },
221
+ });
222
+ (0, registry_core_1.addCliOnlyCapability)("quickstart", "ONE-COMMAND quickstart: --check preflights without writes; otherwise plan(app, default architecture-review) -> run --drive -> report in a single invocation (--preview for a read-only dry run; --bundle [--with-trust-key K] seals a completed run into a self-verified portable bundle).", {
223
+ path: ["quickstart"],
224
+ // `audit-run` is a CLI-only alias that dispatches to the same quickstart
225
+ // wrapper (byte-behavior port of the old build's caseTokens).
226
+ caseTokens: ["quickstart", "audit-run"],
227
+ jsonMode: "default",
228
+ handler: (args) => {
229
+ const appId = (0, io_2.optionalArg)(args.positionals[0]);
230
+ const result = (0, pipeline_cli_1.quickstartRun)({ ...args.options, appId });
231
+ // Fail closed on both known bad outcomes: a --check preflight that
232
+ // found a blocking gap, OR a --bundle that did not self-verify.
233
+ const bundle = result.bundle;
234
+ const bundleFailed = Boolean(bundle && bundle.ok === false);
235
+ const exitCode = (result.mode === "check" && result.ok === false) || bundleFailed ? 1 : undefined;
236
+ return { json: result, exitCode };
237
+ },
238
+ }, "quickstart composes plan/runDrive/report; SPEC/mcp.md's declared cli-only list names it explicitly (no MCP peer). `audit-run` is a CLI-only alias of the same wrapper.", "quickstart");
239
+ (0, registry_core_1.attachCliBinding)("dispatch", {
240
+ path: ["dispatch"],
241
+ jsonMode: "default",
242
+ handler: (args) => {
243
+ const runId = (0, io_1.required)((0, io_2.optionalArg)(args.positionals[0]), "run id");
244
+ return { json: (0, pipeline_cli_1.dispatchRun)({ ...args.options, runId }) };
245
+ },
246
+ });
247
+ (0, registry_core_1.attachCliBinding)("result", {
248
+ path: ["result"],
249
+ jsonMode: "default",
250
+ handler: (args) => {
251
+ const runId = (0, io_1.required)((0, io_2.optionalArg)(args.positionals[0]), "run id");
252
+ const taskId = (0, io_1.required)((0, io_2.optionalArg)(args.positionals[1]), "task id");
253
+ const resultPath = (0, io_1.required)((0, io_2.optionalArg)(args.positionals[2]), "result file path");
254
+ return { json: (0, pipeline_cli_1.recordResultRun)({ ...args.options, runId, taskId, resultPath }) };
255
+ },
256
+ });
257
+ (0, registry_core_1.attachCliBinding)("commit", {
258
+ path: ["commit"],
259
+ jsonMode: "default",
260
+ handler: (args) => {
261
+ const runId = (0, io_1.required)((0, io_2.optionalArg)(args.positionals[0]), "run id");
262
+ return { json: (0, pipeline_cli_1.commitRun)({ ...args.options, runId }) };
263
+ },
264
+ });
265
+ // GAP #26: restore `cw commit summary <run-id>` (CLI + help row). The old
266
+ // build had commit.summary with cli path ["commit","summary"] surface "both"
267
+ // (capability-registry.ts:260-266); v2 kept only the cw_commit_summary MCP
268
+ // tool and dropped both the CLI binding and the COMMAND_HELP_ROWS entry, so
269
+ // `cw commit summary` mis-read "summary" as the run id. Path ["commit","summary"]
270
+ // is 2 tokens; dispatch consumes 1, so positionals[0] is the run id.
271
+ (0, registry_core_1.attachCliBinding)("commit.summary", {
272
+ path: ["commit", "summary"],
273
+ jsonMode: "flag",
274
+ handler: (args) => {
275
+ const summary = (0, commit_summary_1.commitSummaryCli)({ ...args.options, runId: (0, io_1.required)(args.positionals[0], "run id") });
276
+ return { json: summary, text: `${(0, commit_summary_1.formatCommitSummaryText)(summary)}\n` };
277
+ },
278
+ });
279
+ registry_core_1.REGISTRY_BY_CAPABILITY.get("commit.summary").mcp.handler = (args) => (0, commit_summary_1.commitSummaryCli)(args);
280
+ // ---------------------------------------------------------------------
@@ -0,0 +1,189 @@
1
+ "use strict";
2
+ // wiring/capability-table/registry-core.ts — the shared machinery every
3
+ // domain slice registers into: REGISTRY, REGISTRY_BY_CAPABILITY,
4
+ // attachCliBinding, addCliOnlyCapability, and the read-only query
5
+ // functions (findCapability*, cliCapabilities, mcpToolDefinitions,
6
+ // declaredMcpTools). Also owns the small set of capability BODIES that
7
+ // must be in scope when MCP_TOOL_DATA.map() builds REGISTRY at module
8
+ // load (MCP_REAL_HANDLERS below) — kept here, not in a domain slice, to
9
+ // avoid a circular import (a slice needing attachCliBinding from this
10
+ // file, while this file would need a handler body FROM that slice).
11
+ //
12
+ // No slice file imports another slice file; every slice imports ONLY
13
+ // from this file, core/capability-data.ts, and shell/core as needed.
14
+ // index.ts imports this file plus every slice and composes them in the
15
+ // exact original source order (REGISTRY order is a pinned behavior —
16
+ // tools/list order, gen-parity-doc's byte-diff gate, cw help line order).
17
+ //
18
+ // Split out of core/capability-table.ts's "Public table-derived API"
19
+ // section, byte-for-byte (this file's body is the ORIGINAL file's own
20
+ // text, extracted with sed line ranges, not retyped).
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.REGISTRY_BY_CAPABILITY = exports.REGISTRY = void 0;
23
+ exports.listBundledWorkflows = listBundledWorkflows;
24
+ exports.listBundledSandboxProfiles = listBundledSandboxProfiles;
25
+ exports.statusPayload = statusPayload;
26
+ exports.attachCliBinding = attachCliBinding;
27
+ exports.addCliOnlyCapability = addCliOnlyCapability;
28
+ exports.findCapability = findCapability;
29
+ exports.findCapabilityByCliPath = findCapabilityByCliPath;
30
+ exports.cliCapabilities = cliCapabilities;
31
+ exports.mcpToolDefinitions = mcpToolDefinitions;
32
+ exports.declaredMcpTools = declaredMcpTools;
33
+ exports.findCapabilityByMcpTool = findCapabilityByMcpTool;
34
+ const capability_data_1 = require("../../core/capability-data");
35
+ const io_1 = require("../../cli/io");
36
+ const run_store_1 = require("../../shell/run-store");
37
+ const operator_ux_1 = require("../../shell/operator-ux");
38
+ const workflow_app_loader_1 = require("../../shell/workflow-app-loader");
39
+ const state_explosion_cli_1 = require("../../shell/state-explosion-cli");
40
+ /** Real handlers implemented at THIS milestone, keyed by capability id.
41
+ * Every tool row not listed here gets `notYetImplemented`. Kept as a
42
+ * small side table (rather than inlined into MCP_TOOL_DATA above) so the
43
+ * 196-row literal above stays a pure, mechanically-checkable transcript
44
+ * of the spec table — handler wiring is a separate, obviously-later-
45
+ * editable concern. */
46
+ const MCP_REAL_HANDLERS = {
47
+ list: () => listBundledWorkflows(),
48
+ "sandbox.list": () => listBundledSandboxProfiles(),
49
+ status: (args) => statusPayload(optionalString(args.runId)),
50
+ "summary.refresh": (args) => (0, state_explosion_cli_1.summaryRefreshCli)((0, io_1.required)(optionalString(args.runId), "run id"), args),
51
+ "summary.show": (args) => (0, state_explosion_cli_1.summaryShowCli)((0, io_1.required)(optionalString(args.runId), "run id"), args),
52
+ };
53
+ function optionalString(value) {
54
+ return typeof value === "string" && value.trim() ? value.trim() : undefined;
55
+ }
56
+ /** `cw list` / `cw_list` (MILESTONE 12) — the real discovery over every
57
+ * `apps/*\/app.json` + legacy `workflows/*.workflow.js` on disk, per
58
+ * `listWorkflowsShallow` (shell/workflow-app-loader.ts). */
59
+ function listBundledWorkflows() {
60
+ return (0, workflow_app_loader_1.listWorkflowsShallow)();
61
+ }
62
+ /** PLACEHOLDER (milestone 5, execution-backend/sandbox) — the real
63
+ * `sandbox.list` resolves and stamps each of the 4 bundled profiles
64
+ * (default/readonly/workspace-write/locked-down) with real path lists
65
+ * via `resolveSandboxProfile` (SPEC/execution-backend.md). This
66
+ * milestone reproduces only the id/title/schemaVersion subset that
67
+ * mcp-basic.case.js checks. */
68
+ function listBundledSandboxProfiles() {
69
+ return [
70
+ { schemaVersion: 1, id: "default", title: "Default Worker Boundary" },
71
+ { schemaVersion: 1, id: "readonly", title: "Readonly Workspace" },
72
+ { schemaVersion: 1, id: "workspace-write", title: "Workspace Write" },
73
+ { schemaVersion: 1, id: "locked-down", title: "Locked Down" },
74
+ ];
75
+ }
76
+ /** `cw status` / `cw_status` — SPEC/cli-surface.md pins the no-id JSON
77
+ * shape exactly (`{runId:null, nextActions}`); a real run id resolves to
78
+ * `summarizeRun`'s payload (MILESTONE 11, reporting/observability). */
79
+ function statusPayload(runId, cwd) {
80
+ if (!runId) {
81
+ return { runId: null, nextActions: (0, operator_ux_1.adviseNoRun)() };
82
+ }
83
+ const run = (0, run_store_1.loadRunFromCwd)(runId, cwd || process.cwd());
84
+ return (0, operator_ux_1.summarizeRun)(run);
85
+ }
86
+ // ---------------------------------------------------------------------
87
+ // Public table-derived API
88
+ // ---------------------------------------------------------------------
89
+ function buildMcpBinding(row) {
90
+ const handler = MCP_REAL_HANDLERS[row.capability] ?? (0, capability_data_1.notYetImplemented)(row.capability);
91
+ // A transcript entry like "runId, workerId" is TWO AND-required args (the
92
+ // spec table's comma form), while "topicId|id" is one OR-group. mcp/dispatch's
93
+ // validator only splits on `|`, so expand each comma-joined transcript entry
94
+ // into its separate AND-groups here (the one place the row shape is turned
95
+ // into the runtime McpBinding.requiredArgs contract).
96
+ const requiredArgs = row.requiredArgs.flatMap((group) => group.split(",").map((entry) => entry.trim()).filter(Boolean));
97
+ return {
98
+ tool: row.tool,
99
+ requiredArgs: requiredArgs.length ? requiredArgs : undefined,
100
+ properties: row.properties,
101
+ description: row.description,
102
+ handler,
103
+ };
104
+ }
105
+ /** The full capability table: one row per MCP tool (196, per SPEC/mcp.md),
106
+ * in the exact source order `tools/list` must report. CLI bindings are
107
+ * layered on top for the small set of capabilities this milestone also
108
+ * exposes on the CLI front door (see `CLI_ROWS` below); every other row
109
+ * is MCP-only AT THIS MILESTONE (not a permanent `mcp-only` declaration —
110
+ * just not yet CLI-wired; later milestones add the `cli` binding without
111
+ * touching this array's mcp side). */
112
+ exports.REGISTRY = capability_data_1.MCP_TOOL_DATA.map((row) => ({
113
+ capability: row.capability,
114
+ summary: row.description,
115
+ surface: "both",
116
+ mcp: buildMcpBinding(row),
117
+ }));
118
+ exports.REGISTRY_BY_CAPABILITY = new Map(exports.REGISTRY.map((row) => [row.capability, row]));
119
+ /** Attach (or replace) a CLI binding for an already-declared MCP capability.
120
+ * Used once below to wire `list`/`status`/`sandbox.list` onto the CLI
121
+ * front door too, without duplicating their row data. */
122
+ function attachCliBinding(capability, cli) {
123
+ const row = exports.REGISTRY_BY_CAPABILITY.get(capability);
124
+ if (!row)
125
+ throw new Error(`capability-table: cannot attach cli binding to undeclared capability ${capability}`);
126
+ row.cli = cli;
127
+ }
128
+ /** Declare a capability that is CLI-only at this milestone (`help`,
129
+ * `version` — both are permanently `cli-only` per SPEC/mcp.md's
130
+ * declared one-surface list, so no mcp row is created for them). */
131
+ function addCliOnlyCapability(capability, summary, cli, reason, entry) {
132
+ const row = { capability, summary, surface: "cli-only", cli, reason, ...(entry ? { entry } : {}) };
133
+ exports.REGISTRY.push(row);
134
+ exports.REGISTRY_BY_CAPABILITY.set(capability, row);
135
+ }
136
+ /** Returns the declared row for a capability id, or undefined. */
137
+ function findCapability(capability) {
138
+ return exports.REGISTRY_BY_CAPABILITY.get(capability);
139
+ }
140
+ /** Returns the declared row whose `cli.path` matches `path` exactly
141
+ * (path[0] is the verb). Used by cli/dispatch.ts's generic executor.
142
+ * A single-token command also matches a row's `caseTokens` alias list, so
143
+ * an alias (e.g. `audit-run`) dispatches to the same handler as its verb. */
144
+ function findCapabilityByCliPath(path) {
145
+ for (const row of exports.REGISTRY) {
146
+ if (row.cli && row.cli.path.length === path.length && row.cli.path.every((p, i) => p === path[i])) {
147
+ return row;
148
+ }
149
+ }
150
+ if (path.length === 1) {
151
+ for (const row of exports.REGISTRY) {
152
+ if (row.cli && row.cli.caseTokens && row.cli.caseTokens.includes(path[0]))
153
+ return row;
154
+ }
155
+ }
156
+ return undefined;
157
+ }
158
+ /** Every capability row that declares a `cli` binding, in registry order.
159
+ * Used to derive `formatCommandHelp`'s per-verb subcommand rows. */
160
+ function cliCapabilities() {
161
+ return exports.REGISTRY.filter((row) => Boolean(row.cli));
162
+ }
163
+ /** `tools/list`'s exact array, in the pinned source order. */
164
+ function mcpToolDefinitions() {
165
+ const definitions = [];
166
+ for (const row of exports.REGISTRY) {
167
+ if (!row.mcp)
168
+ continue;
169
+ const overrides = capability_data_1.PROPERTY_OVERRIDES[row.mcp.tool] ?? {};
170
+ const properties = {};
171
+ for (const propName of row.mcp.properties) {
172
+ properties[propName] = overrides[propName] ?? (0, capability_data_1.stringProperty)(propName);
173
+ }
174
+ definitions.push({
175
+ name: row.mcp.tool,
176
+ description: row.mcp.description,
177
+ inputSchema: { type: "object", properties, additionalProperties: true },
178
+ });
179
+ }
180
+ return definitions;
181
+ }
182
+ /** Every declared MCP tool name, in `tools/list` order. */
183
+ function declaredMcpTools() {
184
+ return exports.REGISTRY.filter((row) => row.mcp).map((row) => row.mcp.tool);
185
+ }
186
+ /** Look up a capability row by its MCP tool name. */
187
+ function findCapabilityByMcpTool(tool) {
188
+ return exports.REGISTRY.find((row) => row.mcp && row.mcp.tool === tool);
189
+ }