cool-workflow 0.1.97 → 0.2.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 (309) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codex-plugin/plugin.json +1 -1
  3. package/README.md +11 -2
  4. package/apps/architecture-review/app.json +1 -1
  5. package/apps/architecture-review-fast/app.json +1 -1
  6. package/apps/end-to-end-golden-path/app.json +1 -1
  7. package/apps/pr-review-fix-ci/app.json +1 -1
  8. package/apps/release-cut/app.json +1 -1
  9. package/apps/research-synthesis/app.json +1 -1
  10. package/dist/cli/dispatch.js +236 -0
  11. package/dist/cli/entry.js +120 -0
  12. package/dist/cli/io.js +21 -4
  13. package/dist/cli/parseargv.js +157 -0
  14. package/dist/cli.js +6 -33
  15. package/dist/core/capability-table.js +3534 -0
  16. package/dist/core/format/help.js +314 -0
  17. package/dist/{state-explosion/format.js → core/format/state-explosion-text.js} +10 -1
  18. package/dist/core/hash.js +137 -0
  19. package/dist/core/multi-agent/candidate-scoring.js +219 -0
  20. package/dist/core/multi-agent/collaboration.js +481 -0
  21. package/dist/core/multi-agent/coordinator.js +515 -0
  22. package/dist/core/multi-agent/eval-replay.js +306 -0
  23. package/dist/core/multi-agent/runtime.js +929 -0
  24. package/dist/core/multi-agent/topology.js +298 -0
  25. package/dist/core/multi-agent/trust-policy.js +197 -0
  26. package/dist/core/pipeline/commit-gate.js +320 -0
  27. package/dist/{pipeline-contract.js → core/pipeline/contract.js} +24 -37
  28. package/dist/core/pipeline/dispatch.js +103 -0
  29. package/dist/core/pipeline/drive-decide.js +227 -0
  30. package/dist/core/pipeline/error-feedback.js +161 -0
  31. package/dist/core/pipeline/loop-expansion.js +124 -0
  32. package/dist/{result-normalize.js → core/pipeline/result-normalize.js} +14 -37
  33. package/dist/core/pipeline/runner.js +230 -0
  34. package/dist/{contract-migration.js → core/state/contract-migration.js} +68 -92
  35. package/dist/{state-migrations.js → core/state/migrations.js} +103 -96
  36. package/dist/core/state/node-projection.js +95 -0
  37. package/dist/core/state/node-snapshot.js +230 -0
  38. package/dist/core/state/run-paths.js +93 -0
  39. package/dist/{schema-validate.js → core/state/schema-validate.js} +35 -28
  40. package/dist/core/state/schema.js +50 -0
  41. package/dist/core/state/state-explosion/digest.js +243 -0
  42. package/dist/core/state/state-explosion/graph.js +527 -0
  43. package/dist/{state-explosion → core/state/state-explosion}/helpers.js +34 -3
  44. package/dist/core/state/state-explosion/report.js +187 -0
  45. package/dist/{state-explosion → core/state/state-explosion}/size.js +25 -7
  46. package/dist/{state-node.js → core/state/state-node.js} +90 -113
  47. package/dist/core/state/types.js +19 -0
  48. package/dist/{validation.js → core/state/validation.js} +64 -131
  49. package/dist/core/trust/evidence-grounding.js +134 -0
  50. package/dist/core/trust/ledger.js +199 -0
  51. package/dist/{telemetry-attestation.js → core/trust/telemetry-attestation.js} +94 -68
  52. package/dist/core/trust/telemetry-ledger.js +127 -0
  53. package/dist/core/types.js +20 -0
  54. package/dist/core/version.js +16 -0
  55. package/dist/{workflow-app-framework.js → core/workflow-apps/app-schema.js} +337 -426
  56. package/dist/mcp/dispatch.js +104 -0
  57. package/dist/mcp/server.js +144 -0
  58. package/dist/mcp-server.js +6 -84
  59. package/dist/{agent-config.js → shell/agent-config.js} +118 -71
  60. package/dist/shell/app-run-cli.js +88 -0
  61. package/dist/shell/audit-cli.js +259 -0
  62. package/dist/shell/audit-provenance.js +83 -0
  63. package/dist/shell/candidate-scoring-io.js +459 -0
  64. package/dist/shell/collaboration-io.js +264 -0
  65. package/dist/shell/commit-summary.js +104 -0
  66. package/dist/shell/commit.js +290 -0
  67. package/dist/shell/coordinator-io.js +476 -0
  68. package/dist/shell/demo-cli.js +19 -0
  69. package/dist/shell/dispatch.js +162 -0
  70. package/dist/{doctor.js → shell/doctor.js} +123 -56
  71. package/dist/shell/drive.js +873 -0
  72. package/dist/shell/error-feedback-io.js +305 -0
  73. package/dist/shell/eval-io.js +473 -0
  74. package/dist/{multi-agent-eval/format.js → shell/eval-text.js} +78 -49
  75. package/dist/{evidence-reasoning.js → shell/evidence-reasoning.js} +124 -255
  76. package/dist/shell/exec-backend-cli.js +88 -0
  77. package/dist/shell/execution-backend/agent.js +475 -0
  78. package/dist/shell/execution-backend/ci.js +15 -0
  79. package/dist/shell/execution-backend/container.js +69 -0
  80. package/dist/shell/execution-backend/envelopes.js +55 -0
  81. package/dist/shell/execution-backend/local.js +113 -0
  82. package/dist/shell/execution-backend/probes.js +175 -0
  83. package/dist/shell/execution-backend/registry.js +402 -0
  84. package/dist/shell/execution-backend/remote.js +128 -0
  85. package/dist/shell/execution-backend/types.js +11 -0
  86. package/dist/shell/feedback-cli.js +81 -0
  87. package/dist/shell/feedback-operations.js +48 -0
  88. package/dist/shell/fs-atomic.js +276 -0
  89. package/dist/shell/harness.js +98 -0
  90. package/dist/shell/ledger-cli.js +212 -0
  91. package/dist/shell/ledger-io.js +169 -0
  92. package/dist/shell/man-cli.js +89 -0
  93. package/dist/shell/metrics-cli.js +98 -0
  94. package/dist/shell/multi-agent-cli.js +1002 -0
  95. package/dist/shell/multi-agent-host.js +563 -0
  96. package/dist/shell/multi-agent-io.js +387 -0
  97. package/dist/{multi-agent-operator-ux.js → shell/multi-agent-operator-ux.js} +234 -191
  98. package/dist/shell/node-store.js +124 -0
  99. package/dist/{observability/format.js → shell/observability-format.js} +7 -1
  100. package/dist/{observability/intake.js → shell/observability-intake.js} +79 -56
  101. package/dist/{observability.js → shell/observability.js} +159 -332
  102. package/dist/{onramp.js → shell/onramp.js} +11 -0
  103. package/dist/{operator-ux/format.js → shell/operator-ux-text.js} +250 -239
  104. package/dist/shell/operator-ux.js +431 -0
  105. package/dist/shell/orchestrator.js +231 -0
  106. package/dist/shell/pipeline-cli.js +667 -0
  107. package/dist/shell/pipeline.js +217 -0
  108. package/dist/shell/reclamation-io.js +1366 -0
  109. package/dist/shell/registry-cli.js +329 -0
  110. package/dist/{remote-source.js → shell/remote-source.js} +12 -5
  111. package/dist/shell/report-cli.js +101 -0
  112. package/dist/shell/report-view-cli.js +117 -0
  113. package/dist/{orchestrator → shell}/report.js +289 -282
  114. package/dist/shell/reporter.js +62 -0
  115. package/dist/shell/run-export-cli.js +106 -0
  116. package/dist/shell/run-export.js +680 -0
  117. package/dist/shell/run-registry-io.js +1014 -0
  118. package/dist/shell/run-store.js +164 -0
  119. package/dist/{sandbox-profile.js → shell/sandbox-profile.js} +134 -95
  120. package/dist/{scheduler.js → shell/scheduler-io.js} +248 -48
  121. package/dist/shell/scheduling-io.js +311 -0
  122. package/dist/shell/state-cli.js +181 -0
  123. package/dist/shell/state-explosion-cli.js +197 -0
  124. package/dist/shell/telemetry-cli.js +85 -0
  125. package/dist/{telemetry-demo.js → shell/telemetry-demo.js} +149 -119
  126. package/dist/shell/telemetry-ledger-io.js +132 -0
  127. package/dist/{term.js → shell/term.js} +36 -46
  128. package/dist/shell/topology-io.js +361 -0
  129. package/dist/shell/trust-audit.js +471 -0
  130. package/dist/{multi-agent-trust.js → shell/trust-policy-io.js} +67 -205
  131. package/dist/shell/verifier.js +48 -0
  132. package/dist/shell/workbench-host.js +250 -0
  133. package/dist/shell/workbench-text.js +18 -0
  134. package/dist/shell/workbench.js +175 -0
  135. package/dist/shell/worker-cli.js +124 -0
  136. package/dist/shell/worker-isolation.js +852 -0
  137. package/dist/shell/workflow-app-loader.js +650 -0
  138. package/docs/agent-delegation-drive.7.md +4 -0
  139. package/docs/cli-mcp-parity.7.md +284 -211
  140. package/docs/contract-migration-tooling.7.md +4 -0
  141. package/docs/control-plane-scheduling.7.md +4 -0
  142. package/docs/cross-agent-ledger.7.md +217 -0
  143. package/docs/designs/handoff-ledger.md +145 -0
  144. package/docs/durable-state-and-locking.7.md +4 -0
  145. package/docs/evidence-adoption-reasoning-chain.7.md +4 -0
  146. package/docs/execution-backends.7.md +4 -0
  147. package/docs/handoff-setup.md +120 -0
  148. package/docs/multi-agent-cli-mcp-surface.7.md +4 -0
  149. package/docs/multi-agent-eval-replay-harness.7.md +4 -0
  150. package/docs/multi-agent-operator-ux.7.md +4 -0
  151. package/docs/node-snapshot-diff-replay.7.md +4 -0
  152. package/docs/observability-cost-accounting.7.md +4 -0
  153. package/docs/project-index.md +143 -71
  154. package/docs/real-execution-backends.7.md +4 -0
  155. package/docs/release-and-migration.7.md +4 -0
  156. package/docs/release-tooling.7.md +4 -0
  157. package/docs/run-registry-control-plane.7.md +4 -0
  158. package/docs/run-retention-reclamation.7.md +25 -0
  159. package/docs/state-explosion-management.7.md +4 -0
  160. package/docs/team-collaboration.7.md +4 -0
  161. package/docs/web-desktop-workbench.7.md +4 -0
  162. package/manifest/plugin.manifest.json +1 -1
  163. package/manifest/source-context-profiles.json +9 -13
  164. package/package.json +1 -1
  165. package/scripts/agents/codex-agent.js +34 -4
  166. package/scripts/agents/cw-attest-wrap.js +2 -2
  167. package/scripts/bump-version.js +4 -3
  168. package/scripts/canonical-apps.js +4 -4
  169. package/scripts/children/batch-delegate-child.js +30 -10
  170. package/scripts/dogfood-architecture-review.js +2 -3
  171. package/scripts/dogfood-release.js +3 -3
  172. package/scripts/gen-parity-doc.js +15 -2
  173. package/scripts/golden-path.js +4 -4
  174. package/scripts/onramp-check.js +1 -1
  175. package/scripts/parity-check.js +38 -21
  176. package/scripts/release-flow.js +9 -3
  177. package/scripts/sync-project-index.js +51 -27
  178. package/scripts/validate-run-state-schema.js +2 -2
  179. package/scripts/version-sync-check.js +30 -30
  180. package/dist/candidate-scoring.js +0 -729
  181. package/dist/capability-core.js +0 -1186
  182. package/dist/capability-registry.js +0 -879
  183. package/dist/cli/command-surface.js +0 -490
  184. package/dist/cli/format.js +0 -56
  185. package/dist/cli/handlers/audit.js +0 -82
  186. package/dist/cli/handlers/blackboard.js +0 -81
  187. package/dist/cli/handlers/candidate.js +0 -40
  188. package/dist/cli/handlers/clones.js +0 -34
  189. package/dist/cli/handlers/collaboration.js +0 -61
  190. package/dist/cli/handlers/eval.js +0 -40
  191. package/dist/cli/handlers/maintenance.js +0 -107
  192. package/dist/cli/handlers/multi-agent.js +0 -165
  193. package/dist/cli/handlers/node.js +0 -41
  194. package/dist/cli/handlers/operational.js +0 -155
  195. package/dist/cli/handlers/operator.js +0 -146
  196. package/dist/cli/handlers/registry.js +0 -68
  197. package/dist/cli/handlers/run.js +0 -153
  198. package/dist/cli/handlers/scheduling.js +0 -132
  199. package/dist/cli/handlers/workbench.js +0 -41
  200. package/dist/cli/handlers/worker.js +0 -45
  201. package/dist/cli/run-summary.js +0 -45
  202. package/dist/clones.js +0 -162
  203. package/dist/collaboration.js +0 -726
  204. package/dist/commit.js +0 -592
  205. package/dist/compare.js +0 -18
  206. package/dist/coordinator/classify.js +0 -45
  207. package/dist/coordinator/paths.js +0 -42
  208. package/dist/coordinator/util.js +0 -126
  209. package/dist/coordinator.js +0 -990
  210. package/dist/daemon.js +0 -44
  211. package/dist/dispatch.js +0 -250
  212. package/dist/drive.js +0 -827
  213. package/dist/error-feedback.js +0 -419
  214. package/dist/evidence-grounding.js +0 -184
  215. package/dist/execution-backend/agent.js +0 -294
  216. package/dist/execution-backend/probes.js +0 -112
  217. package/dist/execution-backend/util.js +0 -47
  218. package/dist/execution-backend.js +0 -961
  219. package/dist/gates.js +0 -48
  220. package/dist/harness.js +0 -61
  221. package/dist/loop-expansion.js +0 -60
  222. package/dist/mcp/tool-call.js +0 -434
  223. package/dist/mcp/tool-definitions.js +0 -1040
  224. package/dist/mcp-surface.js +0 -30
  225. package/dist/multi-agent/graph.js +0 -84
  226. package/dist/multi-agent/helpers.js +0 -141
  227. package/dist/multi-agent/ids.js +0 -20
  228. package/dist/multi-agent/paths.js +0 -22
  229. package/dist/multi-agent-eval/normalize.js +0 -51
  230. package/dist/multi-agent-eval.js +0 -678
  231. package/dist/multi-agent-host.js +0 -777
  232. package/dist/multi-agent.js +0 -984
  233. package/dist/node-projection.js +0 -59
  234. package/dist/node-snapshot.js +0 -260
  235. package/dist/operator-ux.js +0 -631
  236. package/dist/orchestrator/app-operations.js +0 -211
  237. package/dist/orchestrator/audit-operations.js +0 -182
  238. package/dist/orchestrator/candidate-operations.js +0 -117
  239. package/dist/orchestrator/cli-options.js +0 -294
  240. package/dist/orchestrator/collaboration-operations.js +0 -86
  241. package/dist/orchestrator/feedback-operations.js +0 -81
  242. package/dist/orchestrator/host-operations.js +0 -78
  243. package/dist/orchestrator/lifecycle-operations.js +0 -626
  244. package/dist/orchestrator/migration-operations.js +0 -44
  245. package/dist/orchestrator/multi-agent-operations.js +0 -362
  246. package/dist/orchestrator/topology-operations.js +0 -84
  247. package/dist/orchestrator.js +0 -917
  248. package/dist/pipeline-runner.js +0 -285
  249. package/dist/reclamation/hash.js +0 -72
  250. package/dist/reclamation.js +0 -812
  251. package/dist/reporter.js +0 -67
  252. package/dist/run-export.js +0 -784
  253. package/dist/run-registry/derive.js +0 -175
  254. package/dist/run-registry/format.js +0 -124
  255. package/dist/run-registry/gc.js +0 -251
  256. package/dist/run-registry/policy.js +0 -16
  257. package/dist/run-registry/queue.js +0 -115
  258. package/dist/run-registry.js +0 -850
  259. package/dist/run-state-schema.js +0 -68
  260. package/dist/scheduling.js +0 -184
  261. package/dist/state-explosion.js +0 -1014
  262. package/dist/state.js +0 -367
  263. package/dist/telemetry-ledger.js +0 -196
  264. package/dist/topology.js +0 -565
  265. package/dist/triggers.js +0 -184
  266. package/dist/trust-audit.js +0 -644
  267. package/dist/types/blackboard.js +0 -2
  268. package/dist/types/candidate.js +0 -2
  269. package/dist/types/collaboration.js +0 -2
  270. package/dist/types/core.js +0 -2
  271. package/dist/types/drive.js +0 -10
  272. package/dist/types/error-feedback.js +0 -2
  273. package/dist/types/evidence-reasoning.js +0 -2
  274. package/dist/types/execution-backend.js +0 -2
  275. package/dist/types/multi-agent.js +0 -2
  276. package/dist/types/observability.js +0 -2
  277. package/dist/types/pipeline.js +0 -2
  278. package/dist/types/reclamation.js +0 -8
  279. package/dist/types/report-bundle.js +0 -6
  280. package/dist/types/result.js +0 -2
  281. package/dist/types/run-registry.js +0 -2
  282. package/dist/types/run.js +0 -2
  283. package/dist/types/sandbox.js +0 -2
  284. package/dist/types/schedule.js +0 -2
  285. package/dist/types/state-node.js +0 -2
  286. package/dist/types/topology.js +0 -2
  287. package/dist/types/trust.js +0 -2
  288. package/dist/types/workbench.js +0 -2
  289. package/dist/types/worker.js +0 -2
  290. package/dist/types/workflow-app.js +0 -2
  291. package/dist/types.js +0 -44
  292. package/dist/util/fingerprint.js +0 -19
  293. package/dist/util/fingerprint.test.js +0 -27
  294. package/dist/verifier.js +0 -78
  295. package/dist/version.js +0 -8
  296. package/dist/workbench-host.js +0 -182
  297. package/dist/workbench.js +0 -192
  298. package/dist/worker-accept/acceptance.js +0 -114
  299. package/dist/worker-accept/blackboard-fanout.js +0 -80
  300. package/dist/worker-accept/blackboard-linkage.js +0 -19
  301. package/dist/worker-accept/context.js +0 -2
  302. package/dist/worker-accept/telemetry-ledger.js +0 -126
  303. package/dist/worker-accept/validation.js +0 -77
  304. package/dist/worker-accept/verifier-completion.js +0 -73
  305. package/dist/worker-isolation/helpers.js +0 -51
  306. package/dist/worker-isolation/paths.js +0 -46
  307. package/dist/worker-isolation.js +0 -656
  308. package/dist/workflow-api.js +0 -131
  309. /package/dist/{types → core/types}/boundary.js +0 -0
@@ -1,879 +0,0 @@
1
- "use strict";
2
- // CLI <-> MCP Capability Registry — the SINGLE declared source of truth for
3
- // every capability Cool Workflow exposes, and the contract both front doors are
4
- // validated against.
5
- //
6
- // BSD discipline:
7
- // - SEPARATE MECHANISM FROM POLICY. Each capability names ONE shared core
8
- // `entry` (the mechanism, the single source). `cli` and `mcp` are two
9
- // renderings (policy) of that entry's canonical payload.
10
- // - ONE SOURCE, TWO RENDERINGS. A capability marked `payloadIdentical` MUST
11
- // return a byte-for-byte equal JSON payload from `cw <cmd> --json` and from
12
- // the `cw_<tool>` MCP result (whitespace aside). Any divergence is drift.
13
- // - LEAST ASTONISHMENT. Names, flags, and argument order line up across
14
- // surfaces so a human who learns one can predict the other.
15
- // - FAIL CLOSED ON DRIFT. A capability reachable on one surface but absent on
16
- // the other, an MCP tool or CLI command not declared here, or an undeclared
17
- // payload divergence, is a release-blocking error — see scripts/parity-check.js.
18
- // - STABLE INTERFACES. We add what is missing and map the rest; we never drop
19
- // or rename a shipped CLI command or MCP tool to force symmetry.
20
- //
21
- // When a capability is intentionally on one surface only, or intentionally
22
- // renders different payloads per surface, it MUST carry a `reason`. A
23
- // surface-specific or payload-divergent capability WITHOUT a recorded reason is
24
- // itself release-blocking (a fail-closed default), exactly like the vendor
25
- // manifest generator's `--check`.
26
- Object.defineProperty(exports, "__esModule", { value: true });
27
- exports.CAPABILITY_REGISTRY = void 0;
28
- exports.declaredMcpTools = declaredMcpTools;
29
- exports.mcpCapabilityForTool = mcpCapabilityForTool;
30
- exports.mcpCapabilityForId = mcpCapabilityForId;
31
- exports.mcpRequiredArgsForTool = mcpRequiredArgsForTool;
32
- exports.mcpToolDefinition = mcpToolDefinition;
33
- exports.declaredCliTokens = declaredCliTokens;
34
- exports.declaredCliHelpTokens = declaredCliHelpTokens;
35
- exports.requiresReason = requiresReason;
36
- exports.isPayloadProbeOptOut = isPayloadProbeOptOut;
37
- exports.payloadIdenticalCapabilities = payloadIdenticalCapabilities;
38
- exports.payloadProbeTargets = payloadProbeTargets;
39
- exports.deferredPayloadProbeCapabilities = deferredPayloadProbeCapabilities;
40
- exports.buildPayloadProbePlan = buildPayloadProbePlan;
41
- exports.payloadProbePlan = payloadProbePlan;
42
- exports.buildParityReport = buildParityReport;
43
- // ---------------------------------------------------------------------------
44
- // Builtin entries. Grouped to mirror the CLI dispatch and the MCP tool list.
45
- // ---------------------------------------------------------------------------
46
- const BUILTIN_CAPABILITIES = [
47
- // ---- top-level workflow & run lifecycle ---------------------------------
48
- {
49
- capability: "help",
50
- summary: "Print the human CLI help text.",
51
- entry: "formatHelp",
52
- surface: "cli-only",
53
- cli: { path: ["help"], jsonMode: "human" },
54
- reason: "Human help text. MCP hosts enumerate capabilities via tools/list, not a help command."
55
- },
56
- {
57
- capability: "version",
58
- summary: "Print the current cool-workflow version.",
59
- entry: "CURRENT_COOL_WORKFLOW_VERSION",
60
- surface: "cli-only",
61
- cli: { path: ["version"], jsonMode: "human" },
62
- reason: "Version string — no structured data contract."
63
- },
64
- {
65
- capability: "update",
66
- summary: "Update cool-workflow to the latest release via npm.",
67
- entry: "npmUpdate",
68
- surface: "cli-only",
69
- cli: { path: ["update"], jsonMode: "human" },
70
- reason: "Self-update via npm — inherently local shell operation, no MCP surface."
71
- },
72
- {
73
- capability: "fix",
74
- summary: "Print consolidated fix commands for CW setup issues.",
75
- entry: "runDoctor",
76
- surface: "cli-only",
77
- cli: { path: ["fix"], jsonMode: "human" },
78
- reason: "Environment fix commands are local diagnostics, same reasoning as doctor."
79
- },
80
- {
81
- capability: "list",
82
- summary: "List bundled CW workflows.",
83
- entry: "listWorkflows",
84
- surface: "both",
85
- cli: { path: ["list"], jsonMode: "default" },
86
- mcp: { tool: "cw_list" }
87
- },
88
- {
89
- capability: "info",
90
- summary: "Show what a workflow app does: title, description, inputs, sandbox, phases, and a runnable example.",
91
- entry: "showApp",
92
- surface: "cli-only",
93
- cli: { path: ["info"], jsonMode: "flag" },
94
- reason: "Human-focused workflow discovery tool (like Homebrew's `brew info`). MCP agents discover workflows via cw_list and cw_app_show tools."
95
- },
96
- {
97
- capability: "search",
98
- summary: "Search workflow apps by keyword (title, description, id).",
99
- entry: "listApps",
100
- surface: "cli-only",
101
- cli: { path: ["search"], jsonMode: "flag" },
102
- reason: "Human-focused workflow discovery (like Homebrew's `brew search`). MCP agents discover workflows via cw_list tool."
103
- },
104
- {
105
- capability: "man",
106
- summary: "Show a man page from docs/ (e.g. cw man release-tooling).",
107
- entry: "n/a",
108
- surface: "cli-only",
109
- cli: { path: ["man"], jsonMode: "human" },
110
- reason: "Human documentation viewer. MCP agents read docs/ directly via file tools."
111
- },
112
- {
113
- capability: "doctor",
114
- summary: "Diagnose the host for setup problems (Node version, agent backend, agent binary on PATH, git, writable home/repo state) and print an actionable fix per check.",
115
- entry: "runDoctor",
116
- surface: "cli-only",
117
- cli: { path: ["doctor"], jsonMode: "flag" },
118
- reason: "Environment diagnostics are inherently local to the CLI host — Node version, $PATH, $CW_HOME/cwd writability. An MCP client diagnosing the server process's environment is not meaningful; agents already receive the same readiness facts in their typed results (e.g. status: blocked, agentConfigured). Inspired by `brew doctor`."
119
- },
120
- {
121
- capability: "init",
122
- summary: "Scaffold a new workflow definition.",
123
- entry: "init",
124
- surface: "both",
125
- cli: { path: ["init"], jsonMode: "default" },
126
- mcp: { tool: "cw_init", requiredArgs: ["workflowId"] }
127
- },
128
- {
129
- capability: "plan",
130
- summary: "Create a CW run and return its canonical plan summary.",
131
- entry: "planSummary",
132
- surface: "both",
133
- cli: { path: ["plan"], jsonMode: "default" },
134
- mcp: { tool: "cw_plan", requiredArgs: ["workflowId"] }
135
- },
136
- {
137
- capability: "status",
138
- summary: "Read run checkpoint status.",
139
- entry: "status",
140
- surface: "both",
141
- cli: { path: ["status"], jsonMode: "flag" },
142
- mcp: { tool: "cw_status", requiredArgs: ["runId"] }
143
- },
144
- {
145
- capability: "next",
146
- summary: "Read the next recommended tasks for a run.",
147
- entry: "next",
148
- surface: "both",
149
- cli: { path: ["next"], jsonMode: "default" },
150
- mcp: { tool: "cw_next", requiredArgs: ["runId"] }
151
- },
152
- {
153
- capability: "dispatch",
154
- summary: "Create a subagent dispatch manifest.",
155
- entry: "dispatch",
156
- surface: "both",
157
- cli: { path: ["dispatch"], jsonMode: "default" },
158
- mcp: { tool: "cw_dispatch", requiredArgs: ["runId"] }
159
- },
160
- {
161
- capability: "result",
162
- summary: "Record a subagent result file against a task.",
163
- entry: "recordResult",
164
- surface: "both",
165
- cli: { path: ["result"], jsonMode: "default" },
166
- mcp: { tool: "cw_result", requiredArgs: ["runId"] }
167
- },
168
- {
169
- capability: "commit",
170
- summary: "Create a verifier-gated commit or checkpoint.",
171
- entry: "commit",
172
- surface: "both",
173
- cli: { path: ["commit"], jsonMode: "default" },
174
- mcp: { tool: "cw_commit", requiredArgs: ["runId"] },
175
- payloadIdentical: false,
176
- reason: "Both surfaces route through the single core entry runner.commit. The CLI emits the raw StateCommitResult for scripting (commit.id, commit.evidence, commit.gate, commit.acceptanceRationale); cw_commit emits the operator commit envelope (commitId, verifierGated, checkpoint, evidenceCount, snapshotPath, nextActions, plus the raw result under `commit`). Declared projection via capability-core.commitEnvelope, not drift."
177
- },
178
- {
179
- capability: "commit.summary",
180
- summary: "Read the structured commit summary for a run.",
181
- entry: "summarizeCommitRecords",
182
- surface: "both",
183
- cli: { path: ["commit", "summary"], jsonMode: "flag" },
184
- mcp: { tool: "cw_commit_summary", requiredArgs: ["runId"] }
185
- },
186
- {
187
- capability: "report",
188
- summary: "Render a run report and return its canonical descriptor.",
189
- entry: "report",
190
- surface: "both",
191
- cli: { path: ["report"], jsonMode: "flag" },
192
- mcp: { tool: "cw_report", requiredArgs: ["runId"] }
193
- },
194
- {
195
- capability: "graph",
196
- summary: "Read the structured Operator UX run graph.",
197
- entry: "operatorGraph",
198
- surface: "both",
199
- cli: { path: ["graph"], jsonMode: "flag" },
200
- mcp: { tool: "cw_operator_graph", requiredArgs: ["runId"] }
201
- },
202
- {
203
- capability: "loop",
204
- summary: "Create a recurring loop schedule.",
205
- entry: "scheduler.create",
206
- surface: "cli-only",
207
- cli: { path: ["loop"], jsonMode: "default" },
208
- reason: "Convenience alias of `schedule create` with kind=loop. MCP hosts use cw_schedule_create with kind=loop."
209
- },
210
- // ---- operator inspection ------------------------------------------------
211
- {
212
- capability: "operator.status",
213
- summary: "Read the structured Operator UX run status.",
214
- entry: "operatorStatus",
215
- surface: "both",
216
- cli: { path: ["operator", "status"], jsonMode: "flag" },
217
- mcp: { tool: "cw_operator_status", requiredArgs: ["runId"] }
218
- },
219
- {
220
- capability: "operator.report",
221
- summary: "Refresh and read the structured Operator UX report summary.",
222
- entry: "operatorReport",
223
- surface: "both",
224
- cli: { path: ["operator", "report"], jsonMode: "flag" },
225
- mcp: { tool: "cw_operator_report", requiredArgs: ["runId"] }
226
- },
227
- // ---- app management -----------------------------------------------------
228
- { capability: "app.list", summary: "List CW workflow apps.", entry: "listApps", surface: "both", cli: { path: ["app", "list"], jsonMode: "default" }, mcp: { tool: "cw_app_list" } },
229
- { capability: "app.show", summary: "Show a CW workflow app contract.", entry: "showApp", surface: "both", cli: { path: ["app", "show"], jsonMode: "default" }, mcp: { tool: "cw_app_show" } },
230
- { capability: "app.validate", summary: "Validate an app by path or id.", entry: "validateApp", surface: "both", cli: { path: ["app", "validate"], jsonMode: "default" }, mcp: { tool: "cw_app_validate" } },
231
- { capability: "app.init", summary: "Create a CW workflow app directory.", entry: "initApp", surface: "both", cli: { path: ["app", "init"], jsonMode: "default" }, mcp: { tool: "cw_app_init" } },
232
- { capability: "app.package", summary: "Package an app as a JSON artifact.", entry: "packageApp", surface: "both", cli: { path: ["app", "package"], jsonMode: "default" }, mcp: { tool: "cw_app_package" } },
233
- { capability: "app.run", summary: "Create a run from an app id + structured inputs.", entry: "appRun", surface: "both", cli: { path: ["app", "run"], jsonMode: "default" }, mcp: { tool: "cw_app_run", requiredArgs: ["appId"] } },
234
- // ---- state / contract / node --------------------------------------------
235
- { capability: "state.check", summary: "Check run-state schema compatibility.", entry: "checkState", surface: "both", cli: { path: ["state", "check"], jsonMode: "default" }, mcp: { tool: "cw_state_check", requiredArgs: ["runId"] } },
236
- { capability: "contract.show", summary: "Show a run's pipeline contract.", entry: "showContract", surface: "both", cli: { path: ["contract", "show"], jsonMode: "default" }, mcp: { tool: "cw_contract_show", requiredArgs: ["runId"] } },
237
- { capability: "node.list", summary: "List state nodes for a run.", entry: "listNodes", surface: "both", cli: { path: ["node", "list"], jsonMode: "default" }, mcp: { tool: "cw_node_list", requiredArgs: ["runId"] } },
238
- { capability: "node.show", summary: "Show one state node for a run.", entry: "showNode", surface: "both", cli: { path: ["node", "show"], jsonMode: "default" }, mcp: { tool: "cw_node_show", requiredArgs: ["runId", "nodeId"] } },
239
- { capability: "node.graph", summary: "Read the state-node graph for a run.", entry: "graphNodes", surface: "both", cli: { path: ["node", "graph"], jsonMode: "flag" }, mcp: { tool: "cw_node_graph", requiredArgs: ["runId"] } },
240
- { capability: "node.snapshot", summary: "Snapshot one state node (derived + fingerprinted).", entry: "nodeSnapshot", surface: "both", cli: { path: ["node", "snapshot"], caseTokens: ["node", "snapshot"], jsonMode: "default" }, mcp: { tool: "cw_node_snapshot" } },
241
- { capability: "node.diff", summary: "Structurally diff two node snapshots.", entry: "nodeDiff", surface: "both", cli: { path: ["node", "diff"], caseTokens: ["node", "diff"], jsonMode: "default" }, mcp: { tool: "cw_node_diff" } },
242
- { capability: "node.replay", summary: "Deterministically replay one node from a snapshot.", entry: "nodeReplay", surface: "both", cli: { path: ["node", "replay"], caseTokens: ["node", "replay"], jsonMode: "default" }, mcp: { tool: "cw_node_replay" } },
243
- { capability: "node.replay.verify", summary: "Verify a node replay against its source.", entry: "nodeReplayVerify", surface: "both", cli: { path: ["node", "verify"], caseTokens: ["node", "verify"], jsonMode: "default" }, mcp: { tool: "cw_node_replay_verify" } },
244
- { capability: "migration.list", summary: "List the declared migration registry.", entry: "migrationList", surface: "both", cli: { path: ["migration", "list"], caseTokens: ["migration", "list"], jsonMode: "default" }, mcp: { tool: "cw_migration_list" } },
245
- { capability: "migration.check", summary: "Dry-run migration verdict for a target.", entry: "migrationCheck", surface: "both", cli: { path: ["migration", "check"], caseTokens: ["migration", "check"], jsonMode: "default" }, mcp: { tool: "cw_migration_check" } },
246
- { capability: "migration.prove", summary: "Round-trip / non-destruction migration proof for a target.", entry: "migrationProve", surface: "both", cli: { path: ["migration", "prove"], caseTokens: ["migration", "prove"], jsonMode: "default" }, mcp: { tool: "cw_migration_prove" } },
247
- // ---- topology -----------------------------------------------------------
248
- { capability: "topology.list", summary: "List official topology definitions.", entry: "listTopologies", surface: "both", cli: { path: ["topology", "list"], jsonMode: "default" }, mcp: { tool: "cw_topology_list" } },
249
- { capability: "topology.show", summary: "Show a topology definition or run.", entry: "showTopology", surface: "both", cli: { path: ["topology", "show"], jsonMode: "default" }, mcp: { tool: "cw_topology_show", requiredArgs: ["topologyId|id"] } },
250
- { capability: "topology.validate", summary: "Validate a topology definition.", entry: "validateTopology", surface: "both", cli: { path: ["topology", "validate"], jsonMode: "default" }, mcp: { tool: "cw_topology_validate", requiredArgs: ["topologyId|id"] } },
251
- { capability: "topology.apply", summary: "Apply a topology to a run.", entry: "applyTopology", surface: "both", cli: { path: ["topology", "apply"], jsonMode: "default" }, mcp: { tool: "cw_topology_apply", requiredArgs: ["runId", "topologyId|id"] } },
252
- { capability: "topology.summary", summary: "Read topology progress and next actions.", entry: "topologySummary", surface: "both", cli: { path: ["topology", "summary"], jsonMode: "flag" }, mcp: { tool: "cw_topology_summary", requiredArgs: ["runId"] } },
253
- { capability: "topology.graph", summary: "Read topology graph nodes and edges.", entry: "topologyGraph", surface: "both", cli: { path: ["topology", "graph"], jsonMode: "flag" }, mcp: { tool: "cw_topology_graph", requiredArgs: ["runId"] } },
254
- // ---- state-explosion summaries ------------------------------------------
255
- { capability: "summary.refresh", summary: "Refresh state-explosion summaries.", entry: "summaryRefresh", surface: "both", cli: { path: ["summary", "refresh"], jsonMode: "flag" }, mcp: { tool: "cw_summary_refresh", requiredArgs: ["runId"] } },
256
- { capability: "summary.show", summary: "Read the persisted state-explosion report.", entry: "summaryShow", surface: "both", cli: { path: ["summary", "show"], jsonMode: "flag" }, mcp: { tool: "cw_summary_show", requiredArgs: ["runId"] } },
257
- // ---- multi-agent host loop ----------------------------------------------
258
- { capability: "multi-agent.run", summary: "Create or attach a topology-backed multi-agent run.", entry: "hostMultiAgentRun", surface: "both", cli: { path: ["multi-agent", "run"], jsonMode: "default" }, mcp: { tool: "cw_multi_agent_run" } },
259
- { capability: "multi-agent.status", summary: "Read combined topology/blackboard/worker status.", entry: "hostMultiAgentStatus", surface: "both", cli: { path: ["multi-agent", "status"], jsonMode: "flag" }, mcp: { tool: "cw_multi_agent_status", requiredArgs: ["runId"] } },
260
- { capability: "multi-agent.step", summary: "Perform one safe deterministic host step.", entry: "hostMultiAgentStep", surface: "both", cli: { path: ["multi-agent", "step"], jsonMode: "default" }, mcp: { tool: "cw_multi_agent_step", requiredArgs: ["runId"] } },
261
- { capability: "multi-agent.blackboard", summary: "Operate on the active multi-agent blackboard.", entry: "hostMultiAgentBlackboard", surface: "both", cli: { path: ["multi-agent", "blackboard"], jsonMode: "default" }, mcp: { tool: "cw_multi_agent_blackboard", requiredArgs: ["runId"] } },
262
- { capability: "multi-agent.score", summary: "Score a candidate with evidence.", entry: "hostMultiAgentScore", surface: "both", cli: { path: ["multi-agent", "score"], jsonMode: "default" }, mcp: { tool: "cw_multi_agent_score", requiredArgs: ["runId"] } },
263
- { capability: "multi-agent.select", summary: "Select a candidate with the verifier gate.", entry: "hostMultiAgentSelect", surface: "both", cli: { path: ["multi-agent", "select"], jsonMode: "default" }, mcp: { tool: "cw_multi_agent_select", requiredArgs: ["runId"] } },
264
- { capability: "multi-agent.summary", summary: "Read the structured multi-agent runtime summary for a run.", entry: "multiAgentSummary", surface: "both", cli: { path: ["multi-agent", "summary"], jsonMode: "flag" }, mcp: { tool: "cw_multi_agent_summary", requiredArgs: ["runId"] } },
265
- { capability: "multi-agent.summarize", summary: "Read the combined state-explosion report.", entry: "multiAgentSummarize", surface: "both", cli: { path: ["multi-agent", "summarize"], jsonMode: "flag" }, mcp: { tool: "cw_multi_agent_summarize", requiredArgs: ["runId"] } },
266
- { capability: "multi-agent.graph", summary: "Read the structured multi-agent operator graph for a run.", entry: "multiAgentOperatorGraph", surface: "both", cli: { path: ["multi-agent", "graph"], jsonMode: "flag" }, mcp: { tool: "cw_multi_agent_graph", requiredArgs: ["runId"] } },
267
- { capability: "multi-agent.graph.compact", summary: "Read a compact/focused multi-agent graph view.", entry: "multiAgentGraphView", surface: "both", cli: { path: ["multi-agent", "graph"], caseTokens: ["multi-agent", "graph"], jsonMode: "flag" }, mcp: { tool: "cw_multi_agent_graph_compact", requiredArgs: ["runId"] } },
268
- { capability: "multi-agent.dependencies", summary: "Read derived multi-agent dependency edges for operator inspection.", entry: "multiAgentDependencies", surface: "both", cli: { path: ["multi-agent", "dependencies"], jsonMode: "flag" }, mcp: { tool: "cw_multi_agent_dependencies", requiredArgs: ["runId"] } },
269
- { capability: "multi-agent.failures", summary: "Read failed, blocked, rejected, and ambiguous multi-agent records.", entry: "multiAgentFailures", surface: "both", cli: { path: ["multi-agent", "failures"], jsonMode: "flag" }, mcp: { tool: "cw_multi_agent_failures", requiredArgs: ["runId"] } },
270
- { capability: "multi-agent.evidence", summary: "Read evidence adoption status from worker output through selection and commit. Each row carries a derived rationaleStatus (explained|unexplained|not-applicable).", entry: "multiAgentEvidence", surface: "both", cli: { path: ["multi-agent", "evidence"], jsonMode: "flag" }, mcp: { tool: "cw_multi_agent_evidence", requiredArgs: ["runId"] } },
271
- { capability: "multi-agent.reasoning", summary: "Explain why each evidence item was adopted/rejected.", entry: "multiAgentReasoning", surface: "both", cli: { path: ["multi-agent", "reasoning"], jsonMode: "flag" }, mcp: { tool: "cw_evidence_reasoning", requiredArgs: ["runId"] } },
272
- { capability: "multi-agent.reasoning.refresh", summary: "Refresh the durable evidence-reasoning index.", entry: "multiAgentReasoningRefresh", surface: "both", cli: { path: ["multi-agent", "reasoning"], caseTokens: ["multi-agent", "reasoning"], jsonMode: "default" }, mcp: { tool: "cw_evidence_reasoning_refresh", requiredArgs: ["runId"] } },
273
- // ---- multi-agent lifecycle records --------------------------------------
274
- { capability: "multi-agent.run.create", summary: "Create a MultiAgentRun state record.", entry: "createMultiAgentRun", surface: "both", cli: { path: ["multi-agent", "run"], caseTokens: ["multi-agent", "run"], jsonMode: "default" }, mcp: { tool: "cw_multi_agent_run_create", requiredArgs: ["runId"] } },
275
- { capability: "multi-agent.run.transition", summary: "Transition a MultiAgentRun lifecycle.", entry: "transitionMultiAgentRun", surface: "both", cli: { path: ["multi-agent", "run"], caseTokens: ["multi-agent", "run"], jsonMode: "default" }, mcp: { tool: "cw_multi_agent_run_transition", requiredArgs: ["runId"] } },
276
- { capability: "multi-agent.run.show", summary: "Show one MultiAgentRun record.", entry: "showMultiAgentRun", surface: "both", cli: { path: ["multi-agent", "show"], jsonMode: "default" }, mcp: { tool: "cw_multi_agent_run_show", requiredArgs: ["runId"] } },
277
- { capability: "multi-agent.role.create", summary: "Create an AgentRole record.", entry: "createAgentRole", surface: "both", cli: { path: ["multi-agent", "role"], jsonMode: "default" }, mcp: { tool: "cw_multi_agent_role_create", requiredArgs: ["runId"] } },
278
- { capability: "multi-agent.role.show", summary: "Show one AgentRole record.", entry: "showAgentRole", surface: "both", cli: { path: ["multi-agent", "role"], caseTokens: ["multi-agent", "role"], jsonMode: "default" }, mcp: { tool: "cw_multi_agent_role_show", requiredArgs: ["runId", "roleId"] } },
279
- { capability: "multi-agent.group.create", summary: "Create an AgentGroup record.", entry: "createAgentGroup", surface: "both", cli: { path: ["multi-agent", "group"], jsonMode: "default" }, mcp: { tool: "cw_multi_agent_group_create", requiredArgs: ["runId"] } },
280
- { capability: "multi-agent.group.show", summary: "Show one AgentGroup record.", entry: "showAgentGroup", surface: "both", cli: { path: ["multi-agent", "group"], caseTokens: ["multi-agent", "group"], jsonMode: "default" }, mcp: { tool: "cw_multi_agent_group_show", requiredArgs: ["runId", "groupId"] } },
281
- { capability: "multi-agent.membership.create", summary: "Create an AgentMembership record.", entry: "assignAgentMembership", surface: "both", cli: { path: ["multi-agent", "membership"], jsonMode: "default" }, mcp: { tool: "cw_multi_agent_membership_create", requiredArgs: ["runId"] } },
282
- { capability: "multi-agent.membership.show", summary: "Show one AgentMembership record.", entry: "showAgentMembership", surface: "both", cli: { path: ["multi-agent", "membership"], caseTokens: ["multi-agent", "membership"], jsonMode: "default" }, mcp: { tool: "cw_multi_agent_membership_show", requiredArgs: ["runId", "membershipId"] } },
283
- { capability: "multi-agent.fanout.create", summary: "Create an AgentFanout record.", entry: "createAgentFanout", surface: "both", cli: { path: ["multi-agent", "fanout"], jsonMode: "default" }, mcp: { tool: "cw_multi_agent_fanout_create", requiredArgs: ["runId"] } },
284
- { capability: "multi-agent.fanout.show", summary: "Show one AgentFanout record.", entry: "showAgentFanout", surface: "both", cli: { path: ["multi-agent", "fanout"], caseTokens: ["multi-agent", "fanout"], jsonMode: "default" }, mcp: { tool: "cw_multi_agent_fanout_show", requiredArgs: ["runId", "fanoutId"] } },
285
- { capability: "multi-agent.fanin.collect", summary: "Collect an AgentFanin with evidence coverage.", entry: "collectAgentFanin", surface: "both", cli: { path: ["multi-agent", "fanin"], jsonMode: "default" }, mcp: { tool: "cw_multi_agent_fanin_collect", requiredArgs: ["runId"] } },
286
- { capability: "multi-agent.fanin.show", summary: "Show one AgentFanin record.", entry: "showAgentFanin", surface: "both", cli: { path: ["multi-agent", "fanin"], caseTokens: ["multi-agent", "fanin"], jsonMode: "default" }, mcp: { tool: "cw_multi_agent_fanin_show", requiredArgs: ["runId", "faninId"] } },
287
- // ---- eval & replay ------------------------------------------------------
288
- { capability: "eval.snapshot", summary: "Create a deterministic replay snapshot.", entry: "evalSnapshot", surface: "both", cli: { path: ["eval", "snapshot"], jsonMode: "flag" }, mcp: { tool: "cw_eval_snapshot", requiredArgs: ["runId"] } },
289
- { capability: "eval.replay", summary: "Replay a snapshot without live agents.", entry: "evalReplay", surface: "both", cli: { path: ["eval", "replay"], jsonMode: "flag" }, mcp: { tool: "cw_eval_replay", requiredArgs: ["snapshot|snapshotId|path"] } },
290
- { capability: "eval.compare", summary: "Compare baseline and replay deterministically.", entry: "evalCompare", surface: "both", cli: { path: ["eval", "compare"], jsonMode: "flag" }, mcp: { tool: "cw_eval_compare", requiredArgs: ["baseline|baselinePath", "replay|replayPath"] } },
291
- { capability: "eval.score", summary: "Score replay quality.", entry: "evalScore", surface: "both", cli: { path: ["eval", "score"], jsonMode: "flag" }, mcp: { tool: "cw_eval_score", requiredArgs: ["replay|replayPath|path"] } },
292
- { capability: "eval.gate", summary: "Run the eval/replay regression gate.", entry: "evalGate", surface: "both", cli: { path: ["eval", "gate"], jsonMode: "flag" }, mcp: { tool: "cw_eval_gate", requiredArgs: ["suite|suiteId|path"] } },
293
- { capability: "eval.report", summary: "Render an eval/replay report.", entry: "evalReport", surface: "both", cli: { path: ["eval", "report"], jsonMode: "flag" }, mcp: { tool: "cw_eval_report", requiredArgs: ["replay|replayPath|path"] } },
294
- // ---- blackboard & coordinator -------------------------------------------
295
- { capability: "blackboard.summary", summary: "Read the blackboard/coordinator summary.", entry: "blackboardSummary", surface: "both", cli: { path: ["blackboard", "summary"], jsonMode: "default" }, mcp: { tool: "cw_blackboard_summary", requiredArgs: ["runId"] } },
296
- { capability: "blackboard.summarize", summary: "Read a blackboard digest with conflicts/evidence.", entry: "blackboardSummarize", surface: "both", cli: { path: ["blackboard", "summarize"], jsonMode: "flag" }, mcp: { tool: "cw_blackboard_summarize", requiredArgs: ["runId"] } },
297
- { capability: "blackboard.graph", summary: "Read blackboard graph nodes and edges.", entry: "blackboardGraph", surface: "both", cli: { path: ["blackboard", "graph"], jsonMode: "default" }, mcp: { tool: "cw_blackboard_graph", requiredArgs: ["runId"] } },
298
- { capability: "blackboard.resolve", summary: "Create or resolve a run blackboard.", entry: "resolveRunBlackboard", surface: "both", cli: { path: ["blackboard", "resolve"], jsonMode: "default" }, mcp: { tool: "cw_blackboard_resolve", requiredArgs: ["runId"] } },
299
- { capability: "blackboard.topic.create", summary: "Create a blackboard topic.", entry: "createBlackboardTopic", surface: "both", cli: { path: ["blackboard", "topic", "create"], caseTokens: ["blackboard", "topic"], jsonMode: "default" }, mcp: { tool: "cw_blackboard_topic_create", requiredArgs: ["runId"] } },
300
- { capability: "blackboard.message.post", summary: "Post a blackboard message.", entry: "postBlackboardMessage", surface: "both", cli: { path: ["blackboard", "message", "post"], caseTokens: ["blackboard", "message"], jsonMode: "default" }, mcp: { tool: "cw_blackboard_message_post", requiredArgs: ["runId"] } },
301
- { capability: "blackboard.message.list", summary: "List blackboard messages.", entry: "listBlackboardMessages", surface: "both", cli: { path: ["blackboard", "message", "list"], caseTokens: ["blackboard", "message"], jsonMode: "default" }, mcp: { tool: "cw_blackboard_message_list", requiredArgs: ["runId"] } },
302
- { capability: "blackboard.context.put", summary: "Publish a shared context frame.", entry: "putBlackboardContext", surface: "both", cli: { path: ["blackboard", "context", "put"], caseTokens: ["blackboard", "context"], jsonMode: "default" }, mcp: { tool: "cw_blackboard_context_put", requiredArgs: ["runId"] } },
303
- { capability: "blackboard.artifact.add", summary: "Index an artifact in the blackboard.", entry: "addBlackboardArtifact", surface: "both", cli: { path: ["blackboard", "artifact", "add"], caseTokens: ["blackboard", "artifact"], jsonMode: "default" }, mcp: { tool: "cw_blackboard_artifact_add", requiredArgs: ["runId"] } },
304
- { capability: "blackboard.artifact.list", summary: "List blackboard artifact refs.", entry: "listBlackboardArtifacts", surface: "both", cli: { path: ["blackboard", "artifact", "list"], caseTokens: ["blackboard", "artifact"], jsonMode: "default" }, mcp: { tool: "cw_blackboard_artifact_list", requiredArgs: ["runId"] } },
305
- { capability: "blackboard.snapshot", summary: "Create a durable blackboard snapshot.", entry: "snapshotBlackboard", surface: "both", cli: { path: ["blackboard", "snapshot"], jsonMode: "default" }, mcp: { tool: "cw_blackboard_snapshot", requiredArgs: ["runId"] } },
306
- { capability: "coordinator.summary", summary: "Read the coordinator summary.", entry: "coordinatorSummary", surface: "both", cli: { path: ["coordinator", "summary"], jsonMode: "default" }, mcp: { tool: "cw_coordinator_summary", requiredArgs: ["runId"] } },
307
- { capability: "coordinator.decision", summary: "Record a coordinator decision.", entry: "recordCoordinatorDecision", surface: "both", cli: { path: ["coordinator", "decision"], jsonMode: "default" }, mcp: { tool: "cw_coordinator_decision", requiredArgs: ["runId"] } },
308
- // ---- audit & trust ------------------------------------------------------
309
- { capability: "audit.summary", summary: "Read the trust/audit summary.", entry: "auditSummary", surface: "both", cli: { path: ["audit", "summary"], jsonMode: "default" }, mcp: { tool: "cw_audit_summary", requiredArgs: ["runId"] } },
310
- { capability: "audit.verify", summary: "Re-prove a run's trust-audit hash chain (fail-closed exit).", entry: "auditVerify", surface: "both", cli: { path: ["audit", "verify"], jsonMode: "default" }, mcp: { tool: "cw_audit_verify", requiredArgs: ["runId"] } },
311
- { capability: "audit.worker", summary: "Read trust/audit for one worker.", entry: "workerAudit", surface: "both", cli: { path: ["audit", "worker"], jsonMode: "default" }, mcp: { tool: "cw_audit_worker", requiredArgs: ["runId"] } },
312
- { capability: "audit.provenance", summary: "Inspect evidence provenance.", entry: "evidenceProvenance", surface: "both", cli: { path: ["audit", "provenance"], jsonMode: "default" }, mcp: { tool: "cw_audit_provenance", requiredArgs: ["runId"] } },
313
- { capability: "audit.multi-agent", summary: "Read the multi-agent trust/policy/provenance audit.", entry: "auditMultiAgent", surface: "both", cli: { path: ["audit", "multi-agent"], jsonMode: "flag" }, mcp: { tool: "cw_audit_multi_agent", requiredArgs: ["runId"] } },
314
- { capability: "audit.policy", summary: "Read role policies and permission decisions.", entry: "auditPolicy", surface: "both", cli: { path: ["audit", "policy"], jsonMode: "flag" }, mcp: { tool: "cw_audit_policy", requiredArgs: ["runId"] } },
315
- { capability: "audit.role", summary: "Read policy/audit for one role.", entry: "auditRole", surface: "both", cli: { path: ["audit", "role"], jsonMode: "flag" }, mcp: { tool: "cw_audit_role", requiredArgs: ["runId"] } },
316
- { capability: "audit.blackboard", summary: "Read the blackboard write audit.", entry: "auditBlackboard", surface: "both", cli: { path: ["audit", "blackboard"], jsonMode: "flag" }, mcp: { tool: "cw_audit_blackboard", requiredArgs: ["runId"] } },
317
- { capability: "audit.judge", summary: "Read judge rationale/panel decision audit.", entry: "auditJudge", surface: "both", cli: { path: ["audit", "judge"], jsonMode: "flag" }, mcp: { tool: "cw_audit_judge", requiredArgs: ["runId"] } },
318
- { capability: "audit.attest", summary: "Record a host/operator sandbox attestation.", entry: "recordAuditAttestation", surface: "both", cli: { path: ["audit", "attest"], jsonMode: "default" }, mcp: { tool: "cw_audit_attest", requiredArgs: ["runId"] } },
319
- { capability: "audit.decision", summary: "Validate and record a sandbox decision.", entry: "recordAuditDecision", surface: "both", cli: { path: ["audit", "decision"], jsonMode: "default" }, mcp: { tool: "cw_audit_decision", requiredArgs: ["runId"] } },
320
- // ---- sandbox profiles ---------------------------------------------------
321
- { capability: "sandbox.list", summary: "List bundled sandbox profiles.", entry: "listSandboxProfiles", surface: "both", cli: { path: ["sandbox", "list"], jsonMode: "default" }, mcp: { tool: "cw_sandbox_list" } },
322
- { capability: "sandbox.show", summary: "Show a resolved sandbox profile.", entry: "showSandboxProfile", surface: "both", cli: { path: ["sandbox", "show"], jsonMode: "default" }, mcp: { tool: "cw_sandbox_show", requiredArgs: ["profileId"] } },
323
- { capability: "sandbox.validate", summary: "Validate a sandbox profile JSON file.", entry: "validateSandboxProfile", surface: "both", cli: { path: ["sandbox", "validate"], jsonMode: "default" }, mcp: { tool: "cw_sandbox_validate", requiredArgs: ["profileFile"] } },
324
- { capability: "sandbox.choose", summary: "Resolve and validate a sandbox profile choice.", entry: "sandboxChoose", surface: "both", cli: { path: ["sandbox", "choose"], jsonMode: "default" }, mcp: { tool: "cw_sandbox_choose" } },
325
- { capability: "sandbox.resolve", summary: "Alias of sandbox.choose.", entry: "sandboxChoose", surface: "both", cli: { path: ["sandbox", "resolve"], jsonMode: "default" }, mcp: { tool: "cw_sandbox_resolve" } },
326
- // ---- execution backends (v0.1.29) ---------------------------------------
327
- { capability: "backend.list", summary: "List available execution backends and their capabilities.", entry: "listBackends", surface: "both", cli: { path: ["backend", "list"], jsonMode: "default" }, mcp: { tool: "cw_backend_list" } },
328
- { capability: "backend.show", summary: "Show one execution backend descriptor.", entry: "showBackend", surface: "both", cli: { path: ["backend", "show"], jsonMode: "default" }, mcp: { tool: "cw_backend_show" } },
329
- { capability: "backend.probe", summary: "Probe execution backend readiness (live, deterministic).", entry: "probeBackend", surface: "both", cli: { path: ["backend", "probe"], jsonMode: "default" }, mcp: { tool: "cw_backend_probe" } },
330
- // ---- agent delegation drive (v0.1.38) -----------------------------------
331
- { capability: "backend.agent.config.show", summary: "Show the effective agent delegation config (flags>env>file, secret-stripped, host-stable).", entry: "backendAgentConfigShow", surface: "both", cli: { path: ["backend", "agent", "config"], caseTokens: ["backend", "agent"], jsonMode: "default" }, mcp: { tool: "cw_backend_agent_config_show" } },
332
- { capability: "backend.agent.config.set", summary: "Set the durable agent delegation config (command-template/endpoint/model; API keys never written).", entry: "backendAgentConfigSet", surface: "both", cli: { path: ["backend", "agent", "config"], caseTokens: ["backend", "agent"], jsonMode: "default" }, mcp: { tool: "cw_backend_agent_config_set" }, payloadIdentical: false, reason: "Mutating: persists $CW_HOME/agent-config.json (secret-stripped) before returning the effective config; both surfaces perform the same write — it is a surface-mutating verb, not a read probe." },
333
- // ---- worker isolation ---------------------------------------------------
334
- { capability: "worker.list", summary: "List worker isolation scopes.", entry: "listWorkers", surface: "both", cli: { path: ["worker", "list"], jsonMode: "default" }, mcp: { tool: "cw_worker_list", requiredArgs: ["runId"] } },
335
- { capability: "worker.summary", summary: "Read the structured worker summary for a run.", entry: "summarizeWorkerRecords", surface: "both", cli: { path: ["worker", "summary"], jsonMode: "flag" }, mcp: { tool: "cw_worker_summary", requiredArgs: ["runId"] } },
336
- { capability: "worker.show", summary: "Show one worker isolation scope.", entry: "showWorker", surface: "both", cli: { path: ["worker", "show"], jsonMode: "default" }, mcp: { tool: "cw_worker_show", requiredArgs: ["runId", "workerId"] } },
337
- { capability: "worker.manifest", summary: "Write and return a worker manifest.", entry: "showWorkerManifest", surface: "both", cli: { path: ["worker", "manifest"], jsonMode: "default" }, mcp: { tool: "cw_worker_manifest", requiredArgs: ["runId"] } },
338
- { capability: "worker.output", summary: "Record worker output.", entry: "recordWorkerOutput", surface: "both", cli: { path: ["worker", "output"], jsonMode: "default" }, mcp: { tool: "cw_worker_output", requiredArgs: ["runId"] } },
339
- { capability: "worker.fail", summary: "Record a structured worker failure.", entry: "recordWorkerFailure", surface: "both", cli: { path: ["worker", "fail"], jsonMode: "default" }, mcp: { tool: "cw_worker_fail", requiredArgs: ["runId"] } },
340
- { capability: "worker.validate", summary: "Validate a worker output boundary.", entry: "validateWorker", surface: "both", cli: { path: ["worker", "validate"], jsonMode: "default" }, mcp: { tool: "cw_worker_validate", requiredArgs: ["runId"] } },
341
- // ---- candidate scoring & selection --------------------------------------
342
- { capability: "candidate.list", summary: "List candidates for a run.", entry: "listCandidates", surface: "both", cli: { path: ["candidate", "list"], jsonMode: "default" }, mcp: { tool: "cw_candidate_list", requiredArgs: ["runId"] } },
343
- { capability: "candidate.show", summary: "Show one candidate.", entry: "showCandidate", surface: "both", cli: { path: ["candidate", "show"], jsonMode: "default" }, mcp: { tool: "cw_candidate_show", requiredArgs: ["runId", "candidateId"] } },
344
- { capability: "candidate.register", summary: "Register a candidate from evidence.", entry: "registerCandidate", surface: "both", cli: { path: ["candidate", "register"], jsonMode: "default" }, mcp: { tool: "cw_candidate_register", requiredArgs: ["runId"] } },
345
- { capability: "candidate.score", summary: "Score a candidate with criteria/evidence.", entry: "scoreCandidate", surface: "both", cli: { path: ["candidate", "score"], jsonMode: "default" }, mcp: { tool: "cw_candidate_score", requiredArgs: ["runId"] } },
346
- { capability: "candidate.rank", summary: "Rank candidates with gates.", entry: "rankCandidates", surface: "both", cli: { path: ["candidate", "rank"], jsonMode: "default" }, mcp: { tool: "cw_candidate_rank", requiredArgs: ["runId"] } },
347
- { capability: "candidate.select", summary: "Select a candidate with the verifier gate.", entry: "selectCandidate", surface: "both", cli: { path: ["candidate", "select"], jsonMode: "default" }, mcp: { tool: "cw_candidate_select", requiredArgs: ["runId"] } },
348
- { capability: "candidate.reject", summary: "Reject a candidate with a reason.", entry: "rejectCandidate", surface: "both", cli: { path: ["candidate", "reject"], jsonMode: "default" }, mcp: { tool: "cw_candidate_reject", requiredArgs: ["runId"] } },
349
- { capability: "candidate.summary", summary: "Read the structured candidate summary for a run.", entry: "summarizeCandidateOperatorRecords", surface: "both", cli: { path: ["candidate", "summary"], jsonMode: "flag" }, mcp: { tool: "cw_candidate_summary", requiredArgs: ["runId"] } },
350
- // ---- feedback -----------------------------------------------------------
351
- { capability: "feedback.list", summary: "List run feedback records.", entry: "listFeedback", surface: "both", cli: { path: ["feedback", "list"], jsonMode: "default" }, mcp: { tool: "cw_feedback_list", requiredArgs: ["runId"] } },
352
- { capability: "feedback.show", summary: "Show a run feedback record.", entry: "showFeedback", surface: "both", cli: { path: ["feedback", "show"], jsonMode: "default" }, mcp: { tool: "cw_feedback_show", requiredArgs: ["runId", "feedbackId"] } },
353
- { capability: "feedback.collect", summary: "Collect feedback from failed nodes.", entry: "collectFeedback", surface: "both", cli: { path: ["feedback", "collect"], jsonMode: "default" }, mcp: { tool: "cw_feedback_collect", requiredArgs: ["runId"] } },
354
- { capability: "feedback.summary", summary: "Read the structured feedback summary for a run.", entry: "summarizeFeedbackRecords", surface: "both", cli: { path: ["feedback", "summary"], jsonMode: "flag" }, mcp: { tool: "cw_feedback_summary", requiredArgs: ["runId"] } },
355
- { capability: "feedback.task", summary: "Create a correction task for feedback.", entry: "createFeedbackTask", surface: "both", cli: { path: ["feedback", "task"], jsonMode: "default" }, mcp: { tool: "cw_feedback_task", requiredArgs: ["runId"] } },
356
- { capability: "feedback.resolve", summary: "Resolve or reject feedback.", entry: "resolveFeedback", surface: "both", cli: { path: ["feedback", "resolve"], jsonMode: "default" }, mcp: { tool: "cw_feedback_resolve", requiredArgs: ["runId"] } },
357
- // ---- scheduling ---------------------------------------------------------
358
- { capability: "schedule.create", summary: "Create a scheduled CW task.", entry: "scheduler.create", surface: "both", cli: { path: ["schedule", "create"], jsonMode: "default" }, mcp: { tool: "cw_schedule_create" } },
359
- { capability: "schedule.list", summary: "List scheduled CW tasks.", entry: "scheduler.list", surface: "both", cli: { path: ["schedule", "list"], jsonMode: "default" }, mcp: { tool: "cw_schedule_list" } },
360
- { capability: "schedule.delete", summary: "Delete a scheduled CW task.", entry: "scheduler.delete", surface: "both", cli: { path: ["schedule", "delete"], jsonMode: "default" }, mcp: { tool: "cw_schedule_delete", requiredArgs: ["id"] } },
361
- { capability: "schedule.due", summary: "List due scheduled CW tasks.", entry: "scheduler.due", surface: "both", cli: { path: ["schedule", "due"], jsonMode: "default" }, mcp: { tool: "cw_schedule_due" } },
362
- { capability: "schedule.complete", summary: "Mark a scheduled task complete.", entry: "scheduler.complete", surface: "both", cli: { path: ["schedule", "complete"], jsonMode: "default" }, mcp: { tool: "cw_schedule_complete", requiredArgs: ["id"] } },
363
- { capability: "schedule.pause", summary: "Pause a scheduled CW task.", entry: "scheduler.pause", surface: "both", cli: { path: ["schedule", "pause"], jsonMode: "default" }, mcp: { tool: "cw_schedule_pause", requiredArgs: ["id"] } },
364
- { capability: "schedule.resume", summary: "Resume a scheduled CW task.", entry: "scheduler.resume", surface: "both", cli: { path: ["schedule", "resume"], jsonMode: "default" }, mcp: { tool: "cw_schedule_resume", requiredArgs: ["id"] } },
365
- { capability: "schedule.run-now", summary: "Create an immediate scheduled-task run record.", entry: "scheduler.runNow", surface: "both", cli: { path: ["schedule", "run-now"], jsonMode: "default" }, mcp: { tool: "cw_schedule_run_now", requiredArgs: ["id"] } },
366
- { capability: "schedule.history", summary: "List scheduled-task run history.", entry: "scheduler.history", surface: "both", cli: { path: ["schedule", "history"], jsonMode: "default" }, mcp: { tool: "cw_schedule_history" } },
367
- {
368
- capability: "schedule.daemon",
369
- summary: "Run the desktop scheduler daemon loop.",
370
- entry: "DesktopSchedulerDaemon.run",
371
- surface: "cli-only",
372
- cli: { path: ["schedule", "daemon"], jsonMode: "human" },
373
- reason: "Long-running desktop daemon process, not a request/response tool. MCP hosts drive ticks via cw_schedule_due + cw_schedule_run_now."
374
- },
375
- // ---- routines / triggers ------------------------------------------------
376
- { capability: "routine.create", summary: "Create a routine-style API/GitHub trigger.", entry: "triggers.create", surface: "both", cli: { path: ["routine", "create"], jsonMode: "default" }, mcp: { tool: "cw_routine_create" } },
377
- { capability: "routine.list", summary: "List routine-style triggers.", entry: "triggers.list", surface: "both", cli: { path: ["routine", "list"], jsonMode: "default" }, mcp: { tool: "cw_routine_list" } },
378
- { capability: "routine.delete", summary: "Delete a routine-style trigger.", entry: "triggers.delete", surface: "both", cli: { path: ["routine", "delete"], jsonMode: "default" }, mcp: { tool: "cw_routine_delete", requiredArgs: ["id"] } },
379
- { capability: "routine.fire", summary: "Record an API/GitHub trigger event.", entry: "triggers.fire", surface: "both", cli: { path: ["routine", "fire"], jsonMode: "default" }, mcp: { tool: "cw_routine_fire", requiredArgs: ["kind"] } },
380
- { capability: "routine.events", summary: "List routine trigger events.", entry: "triggers.events", surface: "both", cli: { path: ["routine", "events"], jsonMode: "default" }, mcp: { tool: "cw_routine_events" } },
381
- // ---- run registry / control plane (v0.1.28) -----------------------------
382
- // A derived, fingerprinted, fail-closed index over `.cw/runs/<id>/state.json`
383
- // across repos. Every verb is declared once here so the CLI and MCP surfaces
384
- // are two renderings of one source and pass the parity gate. `cw <cmd> --json`
385
- // is schema-identical to `cw_<tool>`; the per-run state.json remains the truth.
386
- { capability: "registry.refresh", summary: "Recompute and persist the derived run registry index.", entry: "runRegistry.refresh", surface: "both", cli: { path: ["registry", "refresh"], jsonMode: "flag" }, mcp: { tool: "cw_registry_refresh" } },
387
- { capability: "registry.show", summary: "Read the run registry index with valid|stale|absent freshness.", entry: "runRegistry.show", surface: "both", cli: { path: ["registry", "show"], jsonMode: "flag" }, mcp: { tool: "cw_registry_show" } },
388
- { capability: "run.search", summary: "Search runs by app/status/time/repo/free-text, deterministic + paginated.", entry: "runRegistry.search", surface: "both", cli: { path: ["run", "search"], jsonMode: "flag" }, mcp: { tool: "cw_run_search" } },
389
- { capability: "run.list", summary: "List indexed runs across repos (search with no filters).", entry: "runRegistry.list", surface: "both", cli: { path: ["run", "list"], jsonMode: "flag" }, mcp: { tool: "cw_run_list" } },
390
- { capability: "run.show", summary: "Resolve one run by id across the registry; fail closed on missing source.", entry: "runRegistry.showRun", surface: "both", cli: { path: ["run", "show"], jsonMode: "flag" }, mcp: { tool: "cw_run_show", requiredArgs: ["runId"] } },
391
- { capability: "run.resume", summary: "Resolve a run by id and return its next runnable tasks/actions (read-only by default; the opt-in --drive/--once mode hands it to the shared agent-drive core, which mutates and is covered by run.drive.step).", entry: "runRegistry.resume", surface: "both", cli: { path: ["run", "resume"], jsonMode: "flag" }, mcp: { tool: "cw_run_resume", requiredArgs: ["runId"] } },
392
- { capability: "run.archive", summary: "Archive/unarchive a run (overlay mark; never deletes source).", entry: "runRegistry.archive", surface: "both", cli: { path: ["run", "archive"], jsonMode: "default" }, mcp: { tool: "cw_run_archive", requiredArgs: ["runId|olderThanDays"] } },
393
- { capability: "run.rerun", summary: "Re-run a failed run as a NEW run linked to the original by provenance.", entry: "runRegistry.rerun", surface: "both", cli: { path: ["run", "rerun"], jsonMode: "default" }, mcp: { tool: "cw_run_rerun", requiredArgs: ["runId"] } },
394
- { capability: "run.export", summary: "Export a run to a portable archive with run-local files and digest integrity.", entry: "runExportArchive", surface: "both", cli: { path: ["run", "export"], jsonMode: "default" }, mcp: { tool: "cw_run_export", requiredArgs: ["runId"] } },
395
- { capability: "run.import", summary: "Restore a portable run archive into a target repo and verify restored file digests.", entry: "runImportArchive", surface: "both", cli: { path: ["run", "import"], jsonMode: "default" }, mcp: { tool: "cw_run_import", requiredArgs: ["archive|path|file"] } },
396
- { capability: "run.verify-import", summary: "Verify an imported run against its restore manifest and telemetry chain.", entry: "runVerifyImport", surface: "both", cli: { path: ["run", "verify-import"], jsonMode: "default" }, mcp: { tool: "cw_run_verify_import", requiredArgs: ["runId"] } },
397
- { capability: "run.inspect-archive", summary: "Read-only integrity inspection of a portable run archive without importing it.", entry: "runInspectArchive", surface: "both", cli: { path: ["run", "inspect-archive"], jsonMode: "default" }, mcp: { tool: "cw_run_inspect_archive", requiredArgs: ["archive|path|file"] } },
398
- { capability: "run.restore", summary: "Fail-closed restore of a portable run archive: integrity-inspect, import, and verify in one step; refuses anything that does not verify.", entry: "runRestoreArchive", surface: "both", cli: { path: ["run", "restore"], jsonMode: "default" }, mcp: { tool: "cw_run_restore", requiredArgs: ["archive|path|file"] } },
399
- { capability: "report.verify-bundle", summary: "Offline self-contained verify of a portable run bundle: archive bytes + telemetry chain + trust-audit chain + embedded-key signatures.", entry: "runVerifyReportBundle", surface: "both", cli: { path: ["report", "verify-bundle"], caseTokens: ["report"], jsonMode: "default" }, mcp: { tool: "cw_report_verify_bundle", requiredArgs: ["archive|path|file|bundle"] } },
400
- { capability: "report.bundle", summary: "Produce-and-prove: export a run to a portable bundle sealed with the trust key, then self-verify it offline (fail-closed) so the producer knows it is verifiable before shipping.", entry: "reportBundle", surface: "both", cli: { path: ["report", "bundle"], caseTokens: ["report"], jsonMode: "default" }, mcp: { tool: "cw_report_bundle", requiredArgs: ["runId"] } },
401
- { capability: "run.drive", summary: "Preview the next agent-delegation drive step for a run (read-only, deterministic).", entry: "runDrivePreview", surface: "both", cli: { path: ["run", "drive"], caseTokens: ["run", "drive"], jsonMode: "default" }, mcp: { tool: "cw_run_drive" } },
402
- { capability: "run.drive.step", summary: "Drive a run by delegating each worker to the agent backend (plan->dispatch->fulfill->accept->commit; --once for one step).", entry: "runDrive", surface: "both", cli: { path: ["run", "drive"], caseTokens: ["run", "drive"], jsonMode: "default" }, mcp: { tool: "cw_run_drive_step" }, payloadIdentical: false, reason: "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." },
403
- {
404
- capability: "quickstart",
405
- summary: "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).",
406
- entry: "quickstart",
407
- surface: "cli-only",
408
- cli: { path: ["quickstart"], caseTokens: ["quickstart", "audit-run"], jsonMode: "default" },
409
- reason: "CLI UX convenience layer (newcomer first value in one command) over the existing run.drive.step + report verbs; it spawns nothing new and delegates worker execution to the operator's agent backend. MCP hosts compose the same outcome from cw_run_drive_step + cw_report (+ cw_report_bundle for --bundle). `audit-run` is a CLI-only alias of the same wrapper."
410
- },
411
- { capability: "queue.add", summary: "Enqueue a pending/planned run with explicit ordering policy.", entry: "runRegistry.queueAdd", surface: "both", cli: { path: ["queue", "add"], jsonMode: "default" }, mcp: { tool: "cw_queue_add" } },
412
- { capability: "queue.list", summary: "List the durable run queue in policy order.", entry: "runRegistry.queueList", surface: "both", cli: { path: ["queue", "list"], jsonMode: "flag" }, mcp: { tool: "cw_queue_list" } },
413
- { capability: "queue.drain", summary: "Mark the next ready queue entries drained (the host still executes).", entry: "runRegistry.queueDrain", surface: "both", cli: { path: ["queue", "drain"], jsonMode: "default" }, mcp: { tool: "cw_queue_drain" } },
414
- { capability: "queue.show", summary: "Show one durable queue entry.", entry: "runRegistry.queueShow", surface: "both", cli: { path: ["queue", "show"], jsonMode: "default" }, mcp: { tool: "cw_queue_show", requiredArgs: ["id"] } },
415
- // ---- control-plane scheduling (v0.1.37) ---------------------------------
416
- { capability: "sched.plan", summary: "Read-only control-plane lease plan for the queue+policy+now.", entry: "schedPlan", surface: "both", cli: { path: ["sched", "plan"], caseTokens: ["sched", "plan"], jsonMode: "default" }, mcp: { tool: "cw_sched_plan" } },
417
- { capability: "sched.lease", summary: "Claim eligible queue entries as leases (concurrency-bounded).", entry: "schedLease", surface: "both", cli: { path: ["sched", "lease"], caseTokens: ["sched", "lease"], jsonMode: "default" }, mcp: { tool: "cw_sched_lease" } },
418
- { capability: "sched.release", summary: "Release a held lease (failed -> retry/backoff or park).", entry: "schedRelease", surface: "both", cli: { path: ["sched", "release"], caseTokens: ["sched", "release"], jsonMode: "default" }, mcp: { tool: "cw_sched_release" } },
419
- { capability: "sched.complete", summary: "Complete a held lease (terminal success).", entry: "schedComplete", surface: "both", cli: { path: ["sched", "complete"], caseTokens: ["sched", "complete"], jsonMode: "default" }, mcp: { tool: "cw_sched_complete" } },
420
- { capability: "sched.reclaim", summary: "Reclaim expired leases (each counts a failed attempt).", entry: "schedReclaim", surface: "both", cli: { path: ["sched", "reclaim"], caseTokens: ["sched", "reclaim"], jsonMode: "default" }, mcp: { tool: "cw_sched_reclaim" } },
421
- { capability: "sched.reset", summary: "Reset a parked entry to ready (operator recovery).", entry: "schedReset", surface: "both", cli: { path: ["sched", "reset"], caseTokens: ["sched", "reset"], jsonMode: "default" }, mcp: { tool: "cw_sched_reset" } },
422
- { capability: "sched.policy.show", summary: "Show the scheduling policy (file or default).", entry: "schedPolicyShow", surface: "both", cli: { path: ["sched", "policy"], caseTokens: ["sched", "policy"], jsonMode: "default" }, mcp: { tool: "cw_sched_policy_show" } },
423
- { capability: "sched.policy.set", summary: "Set scheduling policy fields (concurrency/attempts/backoff/TTL).", entry: "schedPolicySet", surface: "both", cli: { path: ["sched", "policy"], caseTokens: ["sched", "policy"], jsonMode: "default" }, mcp: { tool: "cw_sched_policy_set" } },
424
- // ---- run retention & provable reclamation (v0.1.39) ---------------------
425
- // Tiered, append-only, cryptographically-verifiable run reclamation. `plan` and
426
- // `verify` are read-only + deterministic (only generatedAt is now-derived ISO);
427
- // `run` is the disk-freeing tier. All three route through the single core.
428
- { capability: "gc.plan", summary: "Dry-run plan of run reclamation (per-kind bytes + capability downgrade); frees nothing.", entry: "gcPlan", surface: "both", cli: { path: ["gc", "plan"], caseTokens: ["gc", "plan"], jsonMode: "flag" }, mcp: { tool: "cw_gc_plan" } },
429
- { capability: "gc.run", summary: "Execute the write-ahead reclamation transaction (skeleton -> tombstone -> fsync -> free).", entry: "gcRun", surface: "both", cli: { path: ["gc", "run"], caseTokens: ["gc", "run"], jsonMode: "flag" }, mcp: { tool: "cw_gc_run" }, payloadIdentical: false, reason: "Mutating: frees disk and appends a tombstone; both surfaces perform the identical transaction but the payload reports now-derived bytesFreed/tombstone." },
430
- { capability: "gc.verify", summary: "Re-prove a reclaimed run: skeleton-complete, tombstone chain untampered, artifacts reconstructable.", entry: "gcVerify", surface: "both", cli: { path: ["gc", "verify"], caseTokens: ["gc", "verify"], jsonMode: "flag" }, mcp: { tool: "cw_gc_verify", requiredArgs: ["runId"] } },
431
- { capability: "clones.list", summary: "List the cached remote-source checkouts that --link/URL reviews populate (origin URL, kind, commit, age, bytes). Read-only.", entry: "listClones", surface: "both", cli: { path: ["clones", "list"], caseTokens: ["clones", "list"], jsonMode: "flag" }, mcp: { tool: "cw_clones_list" } },
432
- { capability: "clones.gc", summary: "Reclaim cached remote-source checkouts: a TTL sweep (--older-than-days, default 30) or --all. Deletes only inside the clones cache.", entry: "gcClones", surface: "both", cli: { path: ["clones", "gc"], caseTokens: ["clones", "gc"], jsonMode: "flag" }, mcp: { tool: "cw_clones_gc" }, payloadIdentical: false, reason: "Mutating: removes cache directories and reports now-derived freedBytes/removed; both surfaces perform the identical reclamation." },
433
- { capability: "telemetry.verify", summary: "Re-prove a run's telemetry attestation ledger offline: chain linkage + independent hash recompute, and (with --pubkey / CW_AGENT_ATTEST_PUBKEY) re-verify each attested hop's ed25519 signature against the public key.", entry: "telemetryVerify", surface: "both", cli: { path: ["telemetry", "verify"], caseTokens: ["telemetry"], jsonMode: "flag" }, mcp: { tool: "cw_telemetry_verify", requiredArgs: ["runId"] } },
434
- { capability: "demo.tamper", summary: "Prove tamper-evidence: build a signed telemetry ledger, forge it, watch verification fail offline.", entry: "demoTamper", surface: "cli-only", cli: { path: ["demo", "tamper"], caseTokens: ["demo", "tamper"], jsonMode: "flag" }, reason: "Human-facing demonstration (operator/newcomer onboarding); the underlying integrity check is exposed programmatically as the both-surface telemetry.verify. No agent or MCP client needs to invoke a demo." },
435
- { capability: "demo.bundle", summary: "Prove portable-bundle verification: export a sealed report bundle, forge it two ways, watch report verify-bundle catch both offline with only the embedded public key.", entry: "demoBundle", surface: "cli-only", cli: { path: ["demo", "bundle"], caseTokens: ["demo", "bundle"], jsonMode: "flag" }, reason: "Human-facing demonstration (operator/newcomer onboarding); the underlying integrity check is exposed programmatically as the both-surface report.verify-bundle. No agent or MCP client needs to invoke a demo." },
436
- { capability: "history", summary: "Read a cross-repo unified run timeline (newest first).", entry: "runRegistry.history", surface: "both", cli: { path: ["history"], jsonMode: "flag" }, mcp: { tool: "cw_history" } },
437
- // ---- web / desktop workbench (v0.1.30) ----------------------------------
438
- // A THIRD FRONT DOOR — a read-only renderer, not a new brain. Both verbs route
439
- // through the single core in src/workbench.ts; each panel of `workbench.view`
440
- // embeds, verbatim, the canonical `--json` payload of an already-declared
441
- // capability (graph/blackboard/worker/candidate/audit), so the Workbench can
442
- // show nothing the CLI/MCP cannot. It holds zero authoritative state.
443
- { capability: "workbench.view", summary: "Read the read-only five-panel Workbench view of one run (graph, blackboard, worker, candidate, audit).", entry: "buildWorkbenchRunView", surface: "both", cli: { path: ["workbench", "view"], jsonMode: "flag" }, mcp: { tool: "cw_workbench_view", requiredArgs: ["runId"] } },
444
- { capability: "workbench.serve", summary: "Describe/serve the optional localhost-only, read-only Workbench host.", entry: "buildWorkbenchServeDescriptor", surface: "both", cli: { path: ["workbench", "serve"], jsonMode: "flag" }, mcp: { tool: "cw_workbench_serve" },
445
- payloadIdentical: false,
446
- reason: "Both surfaces route through the single core entry buildWorkbenchServeDescriptor and return the IDENTICAL serve descriptor under `cw workbench serve --json`/`--once` and `cw_workbench_serve`. They diverge only in side effect, not payload: the CLI's default `cw workbench serve` (no --once) additionally STARTS the blocking localhost host (like `schedule daemon`), which an MCP stdio host cannot do, so cw_workbench_serve only ever returns the descriptor. Declared divergence, not drift." },
447
- // ---- observability + cost accounting (v0.1.31) --------------------------
448
- // DERIVED metrics + ATTESTED cost over existing durable state — no metrics db,
449
- // no collector daemon, no hidden counter. Per-run `metrics.show` and cross-repo
450
- // `metrics.summary` are two renderings of ONE core (src/observability.ts):
451
- // `cw <cmd> --json` is byte-identical to the MCP tool (durations come from
452
- // recorded timestamps, only the ISO `generatedAt` is now-derived), and the
453
- // v0.1.30 Workbench metrics panel embeds the same payload read-only.
454
- { capability: "metrics.show", summary: "Read the derived per-run observability + attested-cost report (durations, failure/verifier/acceptance rates with sample counts, attested usage, cost, coverage).", entry: "metricsShow", surface: "both", cli: { path: ["metrics", "show"], jsonMode: "flag" }, mcp: { tool: "cw_metrics_show", requiredArgs: ["runId"] } },
455
- { capability: "metrics.summary", summary: "Read the cross-repo observability + cost rollup over the v0.1.28 run registry, with per-app and per-backend breakdowns.", entry: "metricsSummary", surface: "both", cli: { path: ["metrics", "summary"], jsonMode: "flag" }, mcp: { tool: "cw_metrics_summary" } },
456
- // ---- team collaboration (v0.1.32) ---------------------------------------
457
- // The human-decision layer: append-only, host-ATTESTED (never authenticated)
458
- // approvals/comments/handoffs provenance-linked to a durable target, plus a
459
- // review-gate POLICY that STACKS ON the verifier gate. Each verb routes through
460
- // ONE orchestrator method, so `cw <cmd> --json` is identical to `cw_<tool>`.
461
- // Mutating verbs (approve/reject/comment add/handoff/review policy) are
462
- // both-surface and payload-identical but excluded from the read-only payload
463
- // probe; the read-only review status / comment list ARE probed.
464
- { capability: "approve", summary: "Append a host-attested approval of a candidate/commit/selection.", entry: "collaborationApprove", surface: "both", cli: { path: ["approve"], jsonMode: "default" }, mcp: { tool: "cw_approve", requiredArgs: ["runId", "targetKind|kind", "targetId|target"] } },
465
- { capability: "reject", summary: "Append a host-attested rejection (blocking veto) of a candidate/commit/selection.", entry: "collaborationReject", surface: "both", cli: { path: ["reject"], jsonMode: "default" }, mcp: { tool: "cw_reject", requiredArgs: ["runId", "targetKind|kind", "targetId|target"] } },
466
- { capability: "comment.add", summary: "Append a comment to a durable target.", entry: "collaborationComment", surface: "both", cli: { path: ["comment", "add"], caseTokens: ["comment"], jsonMode: "default" }, mcp: { tool: "cw_comment_add", requiredArgs: ["runId", "targetKind|kind", "targetId|target", "body|message|text"] } },
467
- { capability: "comment.list", summary: "List append-only comments for a run (optionally one target).", entry: "collaborationCommentList", surface: "both", cli: { path: ["comment", "list"], caseTokens: ["comment"], jsonMode: "flag" }, mcp: { tool: "cw_comment_list", requiredArgs: ["runId"] } },
468
- { capability: "handoff", summary: "Record an ownership transfer (from-actor → to-actor) of a run/task.", entry: "collaborationHandoff", surface: "both", cli: { path: ["handoff"], jsonMode: "default" }, mcp: { tool: "cw_handoff", requiredArgs: ["runId", "targetKind|kind", "targetId|target", "to|toActor"] } },
469
- { capability: "review.status", summary: "Read the derived per-target review state + collaboration timeline for a run.", entry: "reviewStatus", surface: "both", cli: { path: ["review", "status"], caseTokens: ["review"], jsonMode: "flag" }, mcp: { tool: "cw_review_status", requiredArgs: ["runId"] } },
470
- { capability: "review.policy", summary: "Set the run's review-gate policy (required approvals, authorized roles, self-approval rule).", entry: "reviewPolicy", surface: "both", cli: { path: ["review", "policy"], caseTokens: ["review"], jsonMode: "default" }, mcp: { tool: "cw_review_policy", requiredArgs: ["runId"] } }
471
- ];
472
- /** The capability registry — the single source of truth, deduplicated by
473
- * capability id (last declaration wins). Derived directly from the table above:
474
- * there is no load-order-sensitive registration step, so nothing can be a
475
- * silently-dead duplicate the way the old snapshot-then-register design allowed. */
476
- exports.CAPABILITY_REGISTRY = Array.from(new Map(BUILTIN_CAPABILITIES.map((cap) => [cap.capability, cap])).values());
477
- // ---------------------------------------------------------------------------
478
- // Payload probe classification.
479
- // ---------------------------------------------------------------------------
480
- const GLOBAL_PAYLOAD_PROBE_CAPABILITIES = [
481
- "list",
482
- "app.list",
483
- "topology.list",
484
- "sandbox.list",
485
- "backend.list",
486
- "backend.agent.config.show",
487
- "metrics.summary"
488
- ];
489
- const RUN_PAYLOAD_PROBE_CAPABILITIES = [
490
- "status",
491
- "operator.status",
492
- "operator.report",
493
- "graph",
494
- "report",
495
- "next",
496
- "state.check",
497
- "contract.show",
498
- "node.list",
499
- "node.graph",
500
- "worker.summary",
501
- "candidate.summary",
502
- "feedback.summary",
503
- "commit.summary",
504
- "audit.summary",
505
- "multi-agent.summary",
506
- "workbench.view",
507
- "metrics.show",
508
- "review.status",
509
- "comment.list",
510
- "run.drive",
511
- "gc.plan",
512
- "gc.verify"
513
- ];
514
- const SCENARIO_PAYLOAD_PROBE_CAPABILITIES = [
515
- "plan",
516
- "app.show",
517
- "app.validate",
518
- "app.package",
519
- "topology.show",
520
- "topology.validate",
521
- "topology.apply",
522
- "topology.summary",
523
- "topology.graph",
524
- "summary.refresh",
525
- "summary.show",
526
- "sandbox.show",
527
- "sandbox.validate",
528
- "sandbox.choose",
529
- "sandbox.resolve",
530
- "approve",
531
- "reject",
532
- "comment.add",
533
- "handoff",
534
- "review.policy",
535
- "worker.list",
536
- "worker.show",
537
- "worker.manifest",
538
- "worker.output",
539
- "worker.fail",
540
- "worker.validate",
541
- "candidate.list",
542
- "candidate.show",
543
- "candidate.register",
544
- "candidate.score",
545
- "candidate.rank",
546
- "candidate.select",
547
- "candidate.reject",
548
- "feedback.list",
549
- "feedback.show",
550
- "feedback.collect",
551
- "feedback.task",
552
- "feedback.resolve",
553
- "node.show",
554
- "node.snapshot",
555
- "node.diff",
556
- "node.replay",
557
- "node.replay.verify"
558
- ];
559
- const PAYLOAD_PROBE_DEFERRED_GROUPS = [
560
- {
561
- reason: "Not safe for the deterministic bootstrap parity probe yet: this capability needs extra target ids/files, mutates durable state, depends on external state, or needs a dedicated fixture beyond cwd/runId.",
562
- capabilities: [
563
- "init",
564
- "dispatch",
565
- "result",
566
- // clones.list is payload-identical by construction (both surfaces call listClones), but it
567
- // reads the external filesystem clone cache (absolute paths + per-entry bytes/timestamps),
568
- // so it is not byte-probed by the deterministic bootstrap.
569
- "clones.list",
570
- "app.init",
571
- "app.run",
572
- "migration.list",
573
- "migration.check",
574
- "migration.prove",
575
- "multi-agent.run",
576
- "multi-agent.status",
577
- "multi-agent.step",
578
- "multi-agent.blackboard",
579
- "multi-agent.score",
580
- "multi-agent.select",
581
- "multi-agent.summarize",
582
- "multi-agent.graph",
583
- "multi-agent.graph.compact",
584
- "multi-agent.dependencies",
585
- "multi-agent.failures",
586
- "multi-agent.evidence",
587
- "multi-agent.reasoning",
588
- "multi-agent.reasoning.refresh",
589
- "multi-agent.run.create",
590
- "multi-agent.run.transition",
591
- "multi-agent.run.show",
592
- "multi-agent.role.create",
593
- "multi-agent.role.show",
594
- "multi-agent.group.create",
595
- "multi-agent.group.show",
596
- "multi-agent.membership.create",
597
- "multi-agent.membership.show",
598
- "multi-agent.fanout.create",
599
- "multi-agent.fanout.show",
600
- "multi-agent.fanin.collect",
601
- "multi-agent.fanin.show",
602
- "eval.snapshot",
603
- "eval.replay",
604
- "eval.compare",
605
- "eval.score",
606
- "eval.gate",
607
- "eval.report",
608
- "blackboard.summary",
609
- "blackboard.summarize",
610
- "blackboard.graph",
611
- "blackboard.resolve",
612
- "blackboard.topic.create",
613
- "blackboard.message.post",
614
- "blackboard.message.list",
615
- "blackboard.context.put",
616
- "blackboard.artifact.add",
617
- "blackboard.artifact.list",
618
- "blackboard.snapshot",
619
- "coordinator.summary",
620
- "coordinator.decision",
621
- "audit.verify",
622
- "audit.worker",
623
- "audit.provenance",
624
- "audit.multi-agent",
625
- "audit.policy",
626
- "audit.role",
627
- "audit.blackboard",
628
- "audit.judge",
629
- "audit.attest",
630
- "audit.decision",
631
- "backend.show",
632
- "backend.probe",
633
- "schedule.create",
634
- "schedule.list",
635
- "schedule.delete",
636
- "schedule.due",
637
- "schedule.complete",
638
- "schedule.pause",
639
- "schedule.resume",
640
- "schedule.run-now",
641
- "schedule.history",
642
- "routine.create",
643
- "routine.list",
644
- "routine.delete",
645
- "routine.fire",
646
- "routine.events",
647
- "registry.refresh",
648
- "registry.show",
649
- "run.search",
650
- "run.list",
651
- "run.show",
652
- "run.resume",
653
- "run.archive",
654
- "run.rerun",
655
- "run.export",
656
- "run.import",
657
- "run.verify-import",
658
- "run.inspect-archive",
659
- "run.restore",
660
- "report.verify-bundle",
661
- "report.bundle",
662
- "queue.add",
663
- "queue.list",
664
- "queue.drain",
665
- "queue.show",
666
- "sched.plan",
667
- "sched.lease",
668
- "sched.release",
669
- "sched.complete",
670
- "sched.reclaim",
671
- "sched.reset",
672
- "sched.policy.show",
673
- "sched.policy.set",
674
- "telemetry.verify",
675
- "history"
676
- ]
677
- }
678
- ];
679
- // ---------------------------------------------------------------------------
680
- // Derivations + the fail-closed parity report builder.
681
- // ---------------------------------------------------------------------------
682
- /** The MCP tool names this registry declares. */
683
- function declaredMcpTools() {
684
- return exports.CAPABILITY_REGISTRY.filter((cap) => cap.mcp).map((cap) => cap.mcp.tool);
685
- }
686
- /** The descriptor for a registry-declared MCP tool name. */
687
- function mcpCapabilityForTool(tool) {
688
- return exports.CAPABILITY_REGISTRY.find((capability) => capability.mcp?.tool === tool);
689
- }
690
- /** The descriptor for a registry-declared capability id. */
691
- function mcpCapabilityForId(capabilityId) {
692
- const descriptor = exports.CAPABILITY_REGISTRY.find((capability) => capability.capability === capabilityId);
693
- return descriptor?.mcp ? descriptor : undefined;
694
- }
695
- /** Required MCP argument groups for a registry-declared tool. */
696
- function mcpRequiredArgsForTool(tool) {
697
- return mcpCapabilityForTool(tool)?.mcp?.requiredArgs ?? [];
698
- }
699
- function mcpToolDefinition(capabilityId, descriptionOrProperties, maybeProperties) {
700
- const descriptor = mcpCapabilityForId(capabilityId);
701
- if (!descriptor?.mcp)
702
- throw new Error(`MCP capability not declared: ${capabilityId}`);
703
- const description = typeof descriptionOrProperties === "string" ? descriptionOrProperties : descriptor.summary;
704
- const properties = typeof descriptionOrProperties === "string" ? maybeProperties : descriptionOrProperties;
705
- if (!properties)
706
- throw new Error(`MCP capability ${capabilityId} missing input schema properties.`);
707
- return {
708
- name: descriptor.mcp.tool,
709
- description,
710
- inputSchema: {
711
- type: "object",
712
- properties,
713
- additionalProperties: true
714
- }
715
- };
716
- }
717
- /** The CLI `case` tokens this registry declares (deduped). */
718
- function declaredCliTokens() {
719
- const tokens = new Set();
720
- for (const cap of exports.CAPABILITY_REGISTRY) {
721
- if (!cap.cli)
722
- continue;
723
- for (const token of cap.cli.caseTokens ?? cap.cli.path)
724
- tokens.add(token);
725
- }
726
- return [...tokens].sort();
727
- }
728
- /** The top-level CLI commands that should be visible in `cw help`. Subcommands
729
- * are intentionally collapsed to their first token; aliases such as audit-run
730
- * stay visible. */
731
- function declaredCliHelpTokens() {
732
- const tokens = new Set();
733
- for (const cap of exports.CAPABILITY_REGISTRY) {
734
- if (!cap.cli)
735
- continue;
736
- const subcommandTokens = new Set(cap.cli.path.slice(1));
737
- tokens.add(cap.cli.path[0]);
738
- for (const token of cap.cli.caseTokens || []) {
739
- if (!subcommandTokens.has(token))
740
- tokens.add(token);
741
- }
742
- }
743
- tokens.delete("help");
744
- return [...tokens].sort();
745
- }
746
- /** Whether a descriptor MUST carry a reason (surface-specific or divergent). */
747
- function requiresReason(cap) {
748
- if (cap.surface !== "both")
749
- return true;
750
- if (cap.payloadIdentical === false)
751
- return true;
752
- return false;
753
- }
754
- /**
755
- * Whether a `surface:"both"` capability is DOCUMENTED out of the payload-identity
756
- * probe. The probe defaults capabilities IN (every both-surface, dual-bound verb —
757
- * including write/complex-arg verbs) and requires an EXPLICIT, REASONED opt-out to
758
- * fall out of scope. A capability escapes the probe only when it carries BOTH
759
- * `payloadIdentical: false` AND a non-empty `reason`. A bare `payloadIdentical:
760
- * false` with no recorded reason does NOT silently escape — it stays in the probe
761
- * set so the undocumented divergence trips the gate (FAIL CLOSED). This mirrors the
762
- * `requiresReason`/`reasonlessExceptions` gate, but enforces it at the probe-scope
763
- * boundary too, so the marshalling-drift surface cannot be narrowed without a paper
764
- * trail.
765
- */
766
- function isPayloadProbeOptOut(cap) {
767
- return cap.payloadIdentical === false && !!(cap.reason && cap.reason.trim());
768
- }
769
- /** Descriptors for the payload-identity probe. Defaults to EVERY both-surface,
770
- * dual-bound capability (read OR write); a capability is excluded only by a
771
- * documented opt-out (`payloadIdentical: false` + a non-empty `reason`) — see
772
- * `isPayloadProbeOptOut`. Fail-closed: an undocumented `payloadIdentical: false`
773
- * stays in scope so its divergence is caught, not silently excused. */
774
- function payloadIdenticalCapabilities() {
775
- return exports.CAPABILITY_REGISTRY.filter((cap) => cap.surface === "both" && cap.cli && cap.mcp && !isPayloadProbeOptOut(cap));
776
- }
777
- function payloadProbeTargets() {
778
- return [
779
- ...GLOBAL_PAYLOAD_PROBE_CAPABILITIES.map((capability) => ({ capability, kind: "global" })),
780
- ...RUN_PAYLOAD_PROBE_CAPABILITIES.map((capability) => ({ capability, kind: "run" })),
781
- ...SCENARIO_PAYLOAD_PROBE_CAPABILITIES.map((capability) => ({ capability, kind: "scenario" }))
782
- ];
783
- }
784
- function deferredPayloadProbeCapabilities() {
785
- return PAYLOAD_PROBE_DEFERRED_GROUPS.flatMap((group) => group.capabilities.map((capability) => ({ capability, reason: group.reason })));
786
- }
787
- function buildPayloadProbePlan(targets, deferred) {
788
- const candidateIds = new Set(payloadIdenticalCapabilities().map((cap) => cap.capability));
789
- const counts = new Map();
790
- const classified = [...targets.map((entry) => entry.capability), ...deferred.map((entry) => entry.capability)];
791
- for (const capability of classified)
792
- counts.set(capability, (counts.get(capability) || 0) + 1);
793
- const classifiedIds = new Set(classified);
794
- return {
795
- targets,
796
- deferred,
797
- unclassified: [...candidateIds].filter((capability) => !classifiedIds.has(capability)).sort(),
798
- duplicateClassifications: [...counts.entries()].filter(([, count]) => count > 1).map(([capability]) => capability).sort(),
799
- invalidClassifications: [...classifiedIds].filter((capability) => !candidateIds.has(capability)).sort()
800
- };
801
- }
802
- function payloadProbePlan() {
803
- return buildPayloadProbePlan(payloadProbeTargets(), deferredPayloadProbeCapabilities());
804
- }
805
- function lintRegistry() {
806
- const issues = [];
807
- const seenCaps = new Set();
808
- const seenTools = new Set();
809
- for (const cap of exports.CAPABILITY_REGISTRY) {
810
- if (seenCaps.has(cap.capability))
811
- issues.push(`duplicate capability id: ${cap.capability}`);
812
- seenCaps.add(cap.capability);
813
- if (cap.mcp) {
814
- if (seenTools.has(cap.mcp.tool))
815
- issues.push(`duplicate MCP tool: ${cap.mcp.tool}`);
816
- seenTools.add(cap.mcp.tool);
817
- }
818
- if (cap.surface === "both" && (!cap.cli || !cap.mcp)) {
819
- issues.push(`${cap.capability}: surface "both" requires both cli and mcp bindings`);
820
- }
821
- if (cap.surface === "cli-only" && (cap.mcp || !cap.cli)) {
822
- issues.push(`${cap.capability}: surface "cli-only" requires a cli binding and no mcp binding`);
823
- }
824
- if (cap.surface === "mcp-only" && (cap.cli || !cap.mcp)) {
825
- issues.push(`${cap.capability}: surface "mcp-only" requires an mcp binding and no cli binding`);
826
- }
827
- }
828
- return issues;
829
- }
830
- /**
831
- * Compare the declared registry against the ACTUAL surfaces and report every
832
- * fail-closed gap. `mcpTools` is the live `tools/list` result; `cliTokens` is the
833
- * set of `case "<token>"` strings parsed from the CLI source.
834
- */
835
- function buildParityReport(input) {
836
- const declaredTools = new Set(declaredMcpTools());
837
- const actualTools = new Set(input.mcpTools);
838
- const declaredTokens = new Set(declaredCliTokens());
839
- const actualTokens = new Set(input.cliTokens);
840
- const declaredHelpTokens = new Set(declaredCliHelpTokens());
841
- const actualHelpTokens = new Set(input.helpTokens || []);
842
- const missingMcpTools = [...declaredTools].filter((tool) => !actualTools.has(tool)).sort();
843
- const undeclaredMcpTools = [...actualTools].filter((tool) => !declaredTools.has(tool)).sort();
844
- const missingCliTokens = [...declaredTokens].filter((token) => !actualTokens.has(token)).sort();
845
- const undeclaredCliTokens = [...actualTokens].filter((token) => !declaredTokens.has(token)).sort();
846
- const helpMissingCliTokens = input.helpTokens ? [...declaredHelpTokens].filter((token) => !actualHelpTokens.has(token)).sort() : [];
847
- const helpUndeclaredCliTokens = input.helpTokens ? [...actualHelpTokens].filter((token) => !declaredHelpTokens.has(token)).sort() : [];
848
- const reasonlessExceptions = exports.CAPABILITY_REGISTRY.filter((cap) => requiresReason(cap) && !(cap.reason && cap.reason.trim()))
849
- .map((cap) => cap.capability)
850
- .sort();
851
- const payloadPlan = payloadProbePlan();
852
- const registryLint = lintRegistry();
853
- const ok = missingMcpTools.length === 0 &&
854
- undeclaredMcpTools.length === 0 &&
855
- missingCliTokens.length === 0 &&
856
- undeclaredCliTokens.length === 0 &&
857
- helpMissingCliTokens.length === 0 &&
858
- helpUndeclaredCliTokens.length === 0 &&
859
- reasonlessExceptions.length === 0 &&
860
- payloadPlan.unclassified.length === 0 &&
861
- payloadPlan.duplicateClassifications.length === 0 &&
862
- payloadPlan.invalidClassifications.length === 0 &&
863
- registryLint.length === 0;
864
- return {
865
- ok,
866
- registrySize: exports.CAPABILITY_REGISTRY.length,
867
- missingMcpTools,
868
- undeclaredMcpTools,
869
- missingCliTokens,
870
- undeclaredCliTokens,
871
- helpMissingCliTokens,
872
- helpUndeclaredCliTokens,
873
- reasonlessExceptions,
874
- payloadProbeUnclassified: payloadPlan.unclassified,
875
- payloadProbeDuplicateClassifications: payloadPlan.duplicateClassifications,
876
- payloadProbeInvalidClassifications: payloadPlan.invalidClassifications,
877
- registryLint
878
- };
879
- }