cool-workflow 0.1.78

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 (193) hide show
  1. package/.claude-plugin/plugin.json +20 -0
  2. package/.codex-plugin/mcp.json +10 -0
  3. package/.codex-plugin/plugin.json +38 -0
  4. package/.mcp.json +10 -0
  5. package/LICENSE +24 -0
  6. package/README.md +638 -0
  7. package/apps/architecture-review/app.json +51 -0
  8. package/apps/architecture-review/workflow.js +116 -0
  9. package/apps/end-to-end-golden-path/app.json +30 -0
  10. package/apps/end-to-end-golden-path/workflow.js +33 -0
  11. package/apps/pr-review-fix-ci/app.json +59 -0
  12. package/apps/pr-review-fix-ci/workflow.js +90 -0
  13. package/apps/release-cut/app.json +54 -0
  14. package/apps/release-cut/workflow.js +82 -0
  15. package/apps/research-synthesis/app.json +50 -0
  16. package/apps/research-synthesis/workflow.js +76 -0
  17. package/apps/workflow-app-framework-demo/app.json +29 -0
  18. package/apps/workflow-app-framework-demo/workflow.js +44 -0
  19. package/dist/agent-config.js +223 -0
  20. package/dist/candidate-scoring.js +715 -0
  21. package/dist/capability-core.js +630 -0
  22. package/dist/capability-dispatcher.js +86 -0
  23. package/dist/capability-registry.js +523 -0
  24. package/dist/cli.js +1276 -0
  25. package/dist/collaboration.js +727 -0
  26. package/dist/commit.js +570 -0
  27. package/dist/contract-migration.js +234 -0
  28. package/dist/coordinator.js +1163 -0
  29. package/dist/daemon.js +44 -0
  30. package/dist/dispatch.js +201 -0
  31. package/dist/drive.js +503 -0
  32. package/dist/error-feedback.js +415 -0
  33. package/dist/evidence-grounding.js +179 -0
  34. package/dist/evidence-reasoning.js +733 -0
  35. package/dist/execution-backend.js +1279 -0
  36. package/dist/harness.js +61 -0
  37. package/dist/mcp-server.js +1615 -0
  38. package/dist/multi-agent-eval.js +857 -0
  39. package/dist/multi-agent-host.js +764 -0
  40. package/dist/multi-agent-operator-ux.js +537 -0
  41. package/dist/multi-agent-trust.js +366 -0
  42. package/dist/multi-agent.js +1173 -0
  43. package/dist/node-snapshot.js +270 -0
  44. package/dist/observability.js +922 -0
  45. package/dist/operator-ux.js +971 -0
  46. package/dist/orchestrator/audit-operations.js +182 -0
  47. package/dist/orchestrator/candidate-operations.js +117 -0
  48. package/dist/orchestrator/cli-options.js +288 -0
  49. package/dist/orchestrator/collaboration-operations.js +86 -0
  50. package/dist/orchestrator/feedback-operations.js +81 -0
  51. package/dist/orchestrator/host-operations.js +78 -0
  52. package/dist/orchestrator/lifecycle-operations.js +462 -0
  53. package/dist/orchestrator/migration-operations.js +44 -0
  54. package/dist/orchestrator/multi-agent-operations.js +362 -0
  55. package/dist/orchestrator/report.js +369 -0
  56. package/dist/orchestrator/topology-operations.js +84 -0
  57. package/dist/orchestrator.js +874 -0
  58. package/dist/pipeline-contract.js +92 -0
  59. package/dist/pipeline-runner.js +285 -0
  60. package/dist/reclamation.js +882 -0
  61. package/dist/result-normalize.js +194 -0
  62. package/dist/run-export.js +64 -0
  63. package/dist/run-registry.js +1347 -0
  64. package/dist/run-state-schema.js +67 -0
  65. package/dist/sandbox-profile.js +471 -0
  66. package/dist/scheduler.js +266 -0
  67. package/dist/scheduling.js +184 -0
  68. package/dist/schema-validate.js +98 -0
  69. package/dist/state-explosion.js +1213 -0
  70. package/dist/state-migrations.js +463 -0
  71. package/dist/state-node.js +301 -0
  72. package/dist/state.js +308 -0
  73. package/dist/telemetry-attestation.js +156 -0
  74. package/dist/telemetry-ledger.js +145 -0
  75. package/dist/topology.js +527 -0
  76. package/dist/triggers.js +159 -0
  77. package/dist/trust-audit.js +475 -0
  78. package/dist/types/blackboard.js +2 -0
  79. package/dist/types/boundary.js +29 -0
  80. package/dist/types/candidate.js +2 -0
  81. package/dist/types/collaboration.js +2 -0
  82. package/dist/types/core.js +2 -0
  83. package/dist/types/drive.js +10 -0
  84. package/dist/types/error-feedback.js +2 -0
  85. package/dist/types/evidence-reasoning.js +2 -0
  86. package/dist/types/execution-backend.js +2 -0
  87. package/dist/types/multi-agent.js +2 -0
  88. package/dist/types/observability.js +2 -0
  89. package/dist/types/pipeline.js +2 -0
  90. package/dist/types/reclamation.js +8 -0
  91. package/dist/types/result.js +2 -0
  92. package/dist/types/run-registry.js +2 -0
  93. package/dist/types/run.js +2 -0
  94. package/dist/types/sandbox.js +2 -0
  95. package/dist/types/schedule.js +2 -0
  96. package/dist/types/state-node.js +2 -0
  97. package/dist/types/topology.js +2 -0
  98. package/dist/types/trust.js +2 -0
  99. package/dist/types/workbench.js +2 -0
  100. package/dist/types/worker.js +2 -0
  101. package/dist/types/workflow-app.js +2 -0
  102. package/dist/types.js +43 -0
  103. package/dist/verifier-registry.js +46 -0
  104. package/dist/verifier.js +78 -0
  105. package/dist/version.js +8 -0
  106. package/dist/workbench-host.js +172 -0
  107. package/dist/workbench.js +190 -0
  108. package/dist/worker-isolation.js +1028 -0
  109. package/dist/workflow-api.js +98 -0
  110. package/dist/workflow-app-framework.js +626 -0
  111. package/docs/agent-delegation-drive.7.md +190 -0
  112. package/docs/agent-framework.md +176 -0
  113. package/docs/candidate-scoring.7.md +106 -0
  114. package/docs/canonical-workflow-apps.7.md +137 -0
  115. package/docs/capability-topology-registry.7.md +168 -0
  116. package/docs/cli-mcp-parity.7.md +373 -0
  117. package/docs/contract-migration-tooling.7.md +123 -0
  118. package/docs/control-plane-scheduling.7.md +110 -0
  119. package/docs/coordinator-blackboard.7.md +183 -0
  120. package/docs/dogfood/architecture-review-cool-workflow.md +16 -0
  121. package/docs/dogfood-one-real-repo.7.md +168 -0
  122. package/docs/durable-state-and-locking.7.md +107 -0
  123. package/docs/end-to-end-golden-path.7.md +117 -0
  124. package/docs/error-feedback.7.md +153 -0
  125. package/docs/evidence-adoption-reasoning-chain.7.md +270 -0
  126. package/docs/execution-backends.7.md +300 -0
  127. package/docs/getting-started.md +99 -0
  128. package/docs/index.md +41 -0
  129. package/docs/mcp-app-surface.7.md +235 -0
  130. package/docs/multi-agent-cli-mcp-surface.7.md +265 -0
  131. package/docs/multi-agent-eval-replay-harness.7.md +302 -0
  132. package/docs/multi-agent-operator-ux.7.md +314 -0
  133. package/docs/multi-agent-runtime-core.7.md +231 -0
  134. package/docs/multi-agent-topologies.7.md +103 -0
  135. package/docs/multi-agent-trust-policy-audit.7.md +154 -0
  136. package/docs/node-snapshot-diff-replay.7.md +135 -0
  137. package/docs/observability-cost-accounting.7.md +194 -0
  138. package/docs/operator-ux.7.md +180 -0
  139. package/docs/pipeline-runner.7.md +136 -0
  140. package/docs/project-index.md +261 -0
  141. package/docs/real-execution-backends.7.md +142 -0
  142. package/docs/release-and-migration.7.md +280 -0
  143. package/docs/release-tooling.7.md +159 -0
  144. package/docs/routines.md +48 -0
  145. package/docs/run-registry-control-plane.7.md +312 -0
  146. package/docs/run-retention-reclamation.7.md +191 -0
  147. package/docs/sandbox-profiles.7.md +137 -0
  148. package/docs/scheduled-tasks.md +80 -0
  149. package/docs/security-trust-hardening.7.md +117 -0
  150. package/docs/state-explosion-management.7.md +264 -0
  151. package/docs/state-node.7.md +96 -0
  152. package/docs/team-collaboration.7.md +207 -0
  153. package/docs/unix-principles.md +192 -0
  154. package/docs/verifier-gated-commit.7.md +140 -0
  155. package/docs/web-desktop-workbench.7.md +215 -0
  156. package/docs/worker-isolation.7.md +167 -0
  157. package/docs/workflow-app-framework.7.md +274 -0
  158. package/manifest/README.md +43 -0
  159. package/manifest/plugin.manifest.json +316 -0
  160. package/manifest/pricing.policy.json +14 -0
  161. package/package.json +79 -0
  162. package/scripts/agents/claude-p-agent.js +104 -0
  163. package/scripts/agents/claude-p-agent.sh +9 -0
  164. package/scripts/agents/cw-attest-keygen.js +55 -0
  165. package/scripts/agents/cw-attest-wrap.js +143 -0
  166. package/scripts/block-unapproved-tag.sh +39 -0
  167. package/scripts/bump-version.js +249 -0
  168. package/scripts/canonical-apps.js +171 -0
  169. package/scripts/cw.js +4 -0
  170. package/scripts/dist-drift-check.js +79 -0
  171. package/scripts/dogfood-architecture-review.js +237 -0
  172. package/scripts/dogfood-release.js +624 -0
  173. package/scripts/forward-ref-docs.js +73 -0
  174. package/scripts/gen-manifests.js +232 -0
  175. package/scripts/golden-path.js +300 -0
  176. package/scripts/mcp-server.js +4 -0
  177. package/scripts/new-feature.js +121 -0
  178. package/scripts/parity-check.js +213 -0
  179. package/scripts/release-check.js +118 -0
  180. package/scripts/release-flow.js +272 -0
  181. package/scripts/release-gate.sh +85 -0
  182. package/scripts/sync-project-index.js +387 -0
  183. package/scripts/validate-run-state-schema.js +126 -0
  184. package/scripts/verify-container-selfref.js +64 -0
  185. package/scripts/version-sync-check.js +237 -0
  186. package/skills/cool-workflow/SKILL.md +162 -0
  187. package/skills/cool-workflow/references/commands.md +282 -0
  188. package/tsconfig.json +16 -0
  189. package/ui/workbench/app.css +76 -0
  190. package/ui/workbench/app.js +159 -0
  191. package/ui/workbench/index.html +32 -0
  192. package/workflows/architecture-review.workflow.js +84 -0
  193. package/workflows/research-synthesis.workflow.js +47 -0
@@ -0,0 +1,168 @@
1
+ # CAPABILITY-TOPOLOGY-REGISTRY(7) — Cool Workflow Agent-Driven Self-Evolution
2
+
3
+ ## Name
4
+
5
+ `capability-dispatcher`, `registerCapabilityHandler`, `registerTopology` — open registries for agent-driven CW extension
6
+
7
+ ## Description
8
+
9
+ v0.1.53 introduces two open registries that let agents extend CW at runtime
10
+ without manual wiring in multiple files. New capabilities self-register and
11
+ auto-work across CLI, MCP, and Workbench. New topologies self-register and
12
+ auto-appear in `topology list`, `topology validate`, and `topology apply`.
13
+
14
+ BSD discipline: **mechanism** (Map / pipe) separate from **policy** (entries).
15
+ Fail-closed on unknown ids.
16
+
17
+ ## Capability Registry
18
+
19
+ ### Interface
20
+
21
+ ```typescript
22
+ interface CapabilityHandler {
23
+ descriptor: CapabilityDescriptor;
24
+ run(args: Record<string, unknown>, ctx: CapabilityContext): unknown | Promise<unknown>;
25
+ }
26
+
27
+ interface CapabilityContext {
28
+ runner: CoolWorkflowRunner;
29
+ cwd: string;
30
+ }
31
+ ```
32
+
33
+ ### Registering a new capability
34
+
35
+ ```typescript
36
+ import { registerCapabilityHandler } from "./capability-registry";
37
+
38
+ registerCapabilityHandler({
39
+ descriptor: {
40
+ capability: "my.new.tool", // canonical dot-namespaced id
41
+ summary: "Does something useful.", // one-line description
42
+ entry: "myNewTool", // core entry name
43
+ surface: "both", // "both" | "cli-only" | "mcp-only"
44
+ cli: { path: ["my", "new-tool"], jsonMode: "default" },
45
+ mcp: { tool: "cw_my_new_tool" }
46
+ },
47
+ run: async (args, ctx) => {
48
+ // ctx.runner exposes all orchestrator methods
49
+ return ctx.runner.listWorkflows();
50
+ }
51
+ });
52
+ ```
53
+
54
+ ### How it works
55
+
56
+ 1. `registerCapabilityHandler()` stores the handler in a `Map<string, CapabilityHandler>`
57
+ 2. CLI: `resolveCliPath(["my", "new-tool"])` resolves the CLI path to the capability id
58
+ 3. MCP: `resolveMcpTool("cw_my_new_tool")` resolves the tool name to the capability id
59
+ 4. `dispatchCapability(id, args, ctx)` invokes `handler.run(args, ctx)`
60
+ 5. Both the CLI and MCP surfaces fall through to the dynamic dispatcher when
61
+ their hardcoded switch statements don't match an unknown command/tool
62
+
63
+ ### Existing capabilities
64
+
65
+ All existing 182 capabilities continue to work through their hardcoded switch
66
+ cases in `cli.ts` and `mcp-server.ts`. The dynamic dispatch is a **fallback**
67
+ — it only activates for commands/tools not found in the legacy switches.
68
+
69
+ ## Topology Registry
70
+
71
+ ### Interface
72
+
73
+ ```typescript
74
+ interface MultiAgentTopologyDefinition {
75
+ schemaVersion: 1;
76
+ id: string; // open string namespace (was closed union)
77
+ title: string;
78
+ summary: string;
79
+ roles: TopologyRoleSpec[];
80
+ groups: Array<{ id: string; title: string; roleIds: string[] }>;
81
+ blackboardTopics: Array<{ id: string; title: string; description: string }>;
82
+ phases: TopologyPhaseSpec[];
83
+ fanoutStrategy: string;
84
+ faninStrategy: string;
85
+ requiredEvidence: string[];
86
+ coordinatorDecisions: CoordinatorDecisionKind[];
87
+ candidateExpectations: string[];
88
+ verifierGates: string[];
89
+ }
90
+
91
+ interface TopologyRoleSpec {
92
+ id: string;
93
+ title: string;
94
+ responsibilities: string[];
95
+ count?: number; // NEW: materialize N instances of this role
96
+ requiredEvidence: string[];
97
+ expectedArtifacts: string[];
98
+ faninObligations: string[];
99
+ }
100
+ ```
101
+
102
+ ### Registering a new topology
103
+
104
+ ```typescript
105
+ import { registerTopology } from "./topology";
106
+
107
+ registerTopology({
108
+ schemaVersion: 1,
109
+ id: "swarm",
110
+ title: "Swarm",
111
+ summary: "Parallel swarm agents with consensus voting.",
112
+ roles: [
113
+ { id: "swarm-agent", title: "Swarm Agent",
114
+ responsibilities: ["Produce shard result with evidence."],
115
+ requiredEvidence: ["swarm output artifact"],
116
+ expectedArtifacts: ["swarm result"],
117
+ faninObligations: ["indexed swarm artifact"],
118
+ count: 5 }
119
+ ],
120
+ groups: [{ id: "swarm", title: "Swarm Group", roleIds: ["swarm-agent"] }],
121
+ blackboardTopics: [
122
+ { id: "swarm-outputs", title: "Swarm Outputs", description: "Agent results." }
123
+ ],
124
+ phases: [
125
+ { id: "execute", title: "Execute", roleIds: ["swarm-agent"],
126
+ fanout: true, fanin: false,
127
+ requiredEvidence: ["swarm output artifact"],
128
+ coordinatorDecisionKinds: ["artifact-index"] },
129
+ { id: "consensus", title: "Consensus", roleIds: ["synthesizer"],
130
+ fanout: false, fanin: true,
131
+ requiredEvidence: ["all swarm evidence"],
132
+ coordinatorDecisionKinds: ["candidate-synthesis"] }
133
+ ],
134
+ fanoutStrategy: "one membership per swarm agent role",
135
+ faninStrategy: "consensus requires all swarm agent evidence",
136
+ requiredEvidence: ["swarm output artifact", "consensus synthesis"],
137
+ coordinatorDecisions: ["artifact-index", "candidate-synthesis"],
138
+ candidateExpectations: ["Synthesis cites swarm agent provenance."],
139
+ verifierGates: ["Swarm fanin must be ready before commit."]
140
+ });
141
+ ```
142
+
143
+ ### How it works
144
+
145
+ 1. `registerTopology()` stores the definition in a `Map<string, MultiAgentTopologyDefinition>`
146
+ 2. `listTopologyDefinitions()` returns official + registered, registered wins on id collision
147
+ 3. `getTopologyDefinition(id)` checks registered first, then official
148
+ 4. `materializedRoles()` uses `role.count` for replication — no more hardcoded
149
+ mapper/judge switch logic
150
+ 5. `applyTopology()` works identically for official and registered topologies
151
+
152
+ ### Data-driven role expansion
153
+
154
+ Before v0.1.53, `materializedRoles()` hardcoded "mapper" and "judge" role
155
+ expansion. Now it checks `role.count` on each role spec:
156
+ - `role.count > 1`: creates `role-1`, `role-2`, ... `role-N`
157
+ - `role.count` undefined or 1: creates a single role instance
158
+ - For backward compat with official topologies, `mapperCount` and `judgeCount`
159
+ input overrides still apply
160
+
161
+ ## See Also
162
+
163
+ - `capability-registry.ts` — the single source of truth for all capabilities
164
+ - `capability-dispatcher.ts` — the thin Map-based dispatch pipe
165
+ - `topology.ts` — topology definitions and the registry
166
+ - `types/topology.ts` — topology type definitions
167
+ - `docs/cli-mcp-parity.7.md` — CLI <-> MCP parity gate
168
+ - `docs/multi-agent-topologies.7.md` — official topology recipes
@@ -0,0 +1,373 @@
1
+ # CLI ↔ MCP Parity
2
+
3
+ CW v0.1.27 adds CLI ↔ MCP Parity. CW has two front doors. The CLI
4
+ (`node scripts/cw.js ...`, `dist/cli.js`) serves human speed: terse, scannable
5
+ text with meaningful exit codes. The MCP server (`cw_*` JSON-RPC tools) serves
6
+ machine context: complete, stable, structured JSON. This release makes the two
7
+ doors two renderings of one data source — declared, derived, and enforced — so
8
+ the same capability cannot drift between surfaces.
9
+
10
+ The design follows a base-system discipline that separates mechanism from
11
+ policy:
12
+
13
+ - one source of truth: the capability registry, not two hand-maintained lists
14
+ - mechanism (shared core) is separate from policy (per-surface rendering)
15
+ - one source, two renderings; no undeclared divergence
16
+ - principle of least astonishment: matching names, flags, order, and defaults
17
+ across surfaces
18
+ - the surfaces do not interfere: human formatting never leaks into machine
19
+ output, machine completeness never bloats the default human view
20
+ - fail closed on drift; a surface mismatch is a release-blocking error
21
+ - stable interfaces, backward compatible; old names remain aliases or wrappers
22
+ - it is not done until it is documented and tested
23
+
24
+ ## Mechanism vs Policy
25
+
26
+ The mechanism is the capability registry at `src/capability-registry.ts`
27
+ (compiled to `dist/capability-registry.js`). It is the single source of truth.
28
+ Every capability declares one shared core `entry` — the mechanism both surfaces
29
+ route through — plus its CLI command, its MCP tool, the surface it lives on, and
30
+ whether its payload is identical across surfaces.
31
+
32
+ No business logic is stranded in `cli.ts` or `mcp-server.ts`. Composite
33
+ capabilities live in `src/capability-core.ts` (`planSummary`, `appRun`,
34
+ `sandboxChoose`, `commitEnvelope`), so both surfaces call the same core entry
35
+ and differ only in how they render its result. The CLI renders for a human; the
36
+ MCP tool renders for a machine; neither owns the logic.
37
+
38
+ A new runtime capability is added once, in the registry, against one core entry.
39
+ The CLI command and the MCP tool are then two policies over that one mechanism —
40
+ which is exactly what the parity gate checks.
41
+
42
+ ## Human vs Machine Contract
43
+
44
+ The two surfaces have different contracts and must not interfere:
45
+
46
+ - CLI = human speed. The default output is terse, scannable text with meaningful
47
+ exit codes. The canonical payload is available on demand via `--json` or
48
+ `--format json`. Human formatting is never emitted on the machine path.
49
+ - MCP = machine context. The result is always complete, stable, structured
50
+ JSON. Machine completeness is never forced into the default human view.
51
+
52
+ A capability marked `payloadIdentical` returns the same canonical JSON from
53
+ `cw <cmd> --json` and from the `cw_<tool>` MCP result — whitespace and
54
+ generation-moment ISO timestamps aside. The `--json` payload is the contract,
55
+ and it is the same bytes the MCP tool returns. The human text view is policy
56
+ layered on top; it never changes the payload.
57
+
58
+ ## The Parity Matrix
59
+
60
+ The matrix below is derived from the live registry — one row per capability,
61
+ showing its CLI command, MCP tool, shared core entry, surface, and payload
62
+ relationship. `identical` means `cw <cmd> --json` equals the `cw_<tool>`
63
+ payload; `projected` means a declared, reasoned divergence; `cli-only` marks a
64
+ surface-specific capability with a recorded reason. The matrix is
65
+ machine-complete by design: 132 capabilities, 129 MCP tools.
66
+
67
+ | Capability | CLI command | MCP tool | Core entry | Surface | Payload |
68
+ | --- | --- | --- | --- | --- | --- |
69
+ | `help` | `cw help` | `—` | `formatHelp` | cli-only | cli-only |
70
+ | `list` | `cw list` | `cw_list` | `listWorkflows` | both | identical |
71
+ | `init` | `cw init` | `cw_init` | `init` | both | identical |
72
+ | `plan` | `cw plan` | `cw_plan` | `planSummary` | both | identical |
73
+ | `status` | `cw status --json` | `cw_status` | `status` | both | identical |
74
+ | `next` | `cw next` | `cw_next` | `next` | both | identical |
75
+ | `dispatch` | `cw dispatch` | `cw_dispatch` | `dispatch` | both | identical |
76
+ | `result` | `cw result` | `cw_result` | `recordResult` | both | identical |
77
+ | `commit` | `cw commit` | `cw_commit` | `commit` | both | projected |
78
+ | `commit.summary` | `cw commit summary --json` | `cw_commit_summary` | `summarizeCommitRecords` | both | identical |
79
+ | `report` | `cw report --json` | `cw_report` | `report` | both | identical |
80
+ | `graph` | `cw graph --json` | `cw_operator_graph` | `operatorGraph` | both | identical |
81
+ | `loop` | `cw loop` | `—` | `scheduler.create` | cli-only | cli-only |
82
+ | `operator.status` | `cw operator status --json` | `cw_operator_status` | `operatorStatus` | both | identical |
83
+ | `operator.report` | `cw operator report --json` | `cw_operator_report` | `operatorReport` | both | identical |
84
+ | `app.list` | `cw app list` | `cw_app_list` | `listApps` | both | identical |
85
+ | `app.show` | `cw app show` | `cw_app_show` | `showApp` | both | identical |
86
+ | `app.validate` | `cw app validate` | `cw_app_validate` | `validateApp` | both | identical |
87
+ | `app.init` | `cw app init` | `cw_app_init` | `initApp` | both | identical |
88
+ | `app.package` | `cw app package` | `cw_app_package` | `packageApp` | both | identical |
89
+ | `app.run` | `cw app run` | `cw_app_run` | `appRun` | both | identical |
90
+ | `state.check` | `cw state check` | `cw_state_check` | `checkState` | both | identical |
91
+ | `contract.show` | `cw contract show` | `cw_contract_show` | `showContract` | both | identical |
92
+ | `node.list` | `cw node list` | `cw_node_list` | `listNodes` | both | identical |
93
+ | `node.show` | `cw node show` | `cw_node_show` | `showNode` | both | identical |
94
+ | `node.graph` | `cw node graph --json` | `cw_node_graph` | `graphNodes` | both | identical |
95
+ | `topology.list` | `cw topology list` | `cw_topology_list` | `listTopologies` | both | identical |
96
+ | `topology.show` | `cw topology show` | `cw_topology_show` | `showTopology` | both | identical |
97
+ | `topology.validate` | `cw topology validate` | `cw_topology_validate` | `validateTopology` | both | identical |
98
+ | `topology.apply` | `cw topology apply` | `cw_topology_apply` | `applyTopology` | both | identical |
99
+ | `topology.summary` | `cw topology summary --json` | `cw_topology_summary` | `topologySummary` | both | identical |
100
+ | `topology.graph` | `cw topology graph --json` | `cw_topology_graph` | `topologyGraph` | both | identical |
101
+ | `summary.refresh` | `cw summary refresh --json` | `cw_summary_refresh` | `summaryRefresh` | both | identical |
102
+ | `summary.show` | `cw summary show --json` | `cw_summary_show` | `summaryShow` | both | identical |
103
+ | `multi-agent.run` | `cw multi-agent run` | `cw_multi_agent_run` | `hostMultiAgentRun` | both | identical |
104
+ | `multi-agent.status` | `cw multi-agent status --json` | `cw_multi_agent_status` | `hostMultiAgentStatus` | both | identical |
105
+ | `multi-agent.step` | `cw multi-agent step` | `cw_multi_agent_step` | `hostMultiAgentStep` | both | identical |
106
+ | `multi-agent.blackboard` | `cw multi-agent blackboard` | `cw_multi_agent_blackboard` | `hostMultiAgentBlackboard` | both | identical |
107
+ | `multi-agent.score` | `cw multi-agent score` | `cw_multi_agent_score` | `hostMultiAgentScore` | both | identical |
108
+ | `multi-agent.select` | `cw multi-agent select` | `cw_multi_agent_select` | `hostMultiAgentSelect` | both | identical |
109
+ | `multi-agent.summary` | `cw multi-agent summary --json` | `cw_multi_agent_summary` | `multiAgentSummary` | both | identical |
110
+ | `multi-agent.summarize` | `cw multi-agent summarize --json` | `cw_multi_agent_summarize` | `multiAgentSummarize` | both | identical |
111
+ | `multi-agent.graph` | `cw multi-agent graph --json` | `cw_multi_agent_graph` | `multiAgentOperatorGraph` | both | identical |
112
+ | `multi-agent.graph.compact` | `cw multi-agent graph --json` | `cw_multi_agent_graph_compact` | `multiAgentGraphView` | both | identical |
113
+ | `multi-agent.dependencies` | `cw multi-agent dependencies --json` | `cw_multi_agent_dependencies` | `multiAgentDependencies` | both | identical |
114
+ | `multi-agent.failures` | `cw multi-agent failures --json` | `cw_multi_agent_failures` | `multiAgentFailures` | both | identical |
115
+ | `multi-agent.evidence` | `cw multi-agent evidence --json` | `cw_multi_agent_evidence` | `multiAgentEvidence` | both | identical |
116
+ | `multi-agent.reasoning` | `cw multi-agent reasoning --json` | `cw_evidence_reasoning` | `multiAgentReasoning` | both | identical |
117
+ | `multi-agent.reasoning.refresh` | `cw multi-agent reasoning` | `cw_evidence_reasoning_refresh` | `multiAgentReasoningRefresh` | both | identical |
118
+ | `multi-agent.run.create` | `cw multi-agent run` | `cw_multi_agent_run_create` | `createMultiAgentRun` | both | identical |
119
+ | `multi-agent.run.transition` | `cw multi-agent run` | `cw_multi_agent_run_transition` | `transitionMultiAgentRun` | both | identical |
120
+ | `multi-agent.run.show` | `cw multi-agent show` | `cw_multi_agent_run_show` | `showMultiAgentRun` | both | identical |
121
+ | `multi-agent.role.create` | `cw multi-agent role` | `cw_multi_agent_role_create` | `createAgentRole` | both | identical |
122
+ | `multi-agent.role.show` | `cw multi-agent role` | `cw_multi_agent_role_show` | `showAgentRole` | both | identical |
123
+ | `multi-agent.group.create` | `cw multi-agent group` | `cw_multi_agent_group_create` | `createAgentGroup` | both | identical |
124
+ | `multi-agent.group.show` | `cw multi-agent group` | `cw_multi_agent_group_show` | `showAgentGroup` | both | identical |
125
+ | `multi-agent.membership.create` | `cw multi-agent membership` | `cw_multi_agent_membership_create` | `assignAgentMembership` | both | identical |
126
+ | `multi-agent.membership.show` | `cw multi-agent membership` | `cw_multi_agent_membership_show` | `showAgentMembership` | both | identical |
127
+ | `multi-agent.fanout.create` | `cw multi-agent fanout` | `cw_multi_agent_fanout_create` | `createAgentFanout` | both | identical |
128
+ | `multi-agent.fanout.show` | `cw multi-agent fanout` | `cw_multi_agent_fanout_show` | `showAgentFanout` | both | identical |
129
+ | `multi-agent.fanin.collect` | `cw multi-agent fanin` | `cw_multi_agent_fanin_collect` | `collectAgentFanin` | both | identical |
130
+ | `multi-agent.fanin.show` | `cw multi-agent fanin` | `cw_multi_agent_fanin_show` | `showAgentFanin` | both | identical |
131
+ | `eval.snapshot` | `cw eval snapshot --json` | `cw_eval_snapshot` | `evalSnapshot` | both | identical |
132
+ | `eval.replay` | `cw eval replay --json` | `cw_eval_replay` | `evalReplay` | both | identical |
133
+ | `eval.compare` | `cw eval compare --json` | `cw_eval_compare` | `evalCompare` | both | identical |
134
+ | `eval.score` | `cw eval score --json` | `cw_eval_score` | `evalScore` | both | identical |
135
+ | `eval.gate` | `cw eval gate --json` | `cw_eval_gate` | `evalGate` | both | identical |
136
+ | `eval.report` | `cw eval report --json` | `cw_eval_report` | `evalReport` | both | identical |
137
+ | `blackboard.summary` | `cw blackboard summary` | `cw_blackboard_summary` | `blackboardSummary` | both | identical |
138
+ | `blackboard.summarize` | `cw blackboard summarize --json` | `cw_blackboard_summarize` | `blackboardSummarize` | both | identical |
139
+ | `blackboard.graph` | `cw blackboard graph` | `cw_blackboard_graph` | `blackboardGraph` | both | identical |
140
+ | `blackboard.resolve` | `cw blackboard resolve` | `cw_blackboard_resolve` | `resolveRunBlackboard` | both | identical |
141
+ | `blackboard.topic.create` | `cw blackboard topic create` | `cw_blackboard_topic_create` | `createBlackboardTopic` | both | identical |
142
+ | `blackboard.message.post` | `cw blackboard message post` | `cw_blackboard_message_post` | `postBlackboardMessage` | both | identical |
143
+ | `blackboard.message.list` | `cw blackboard message list` | `cw_blackboard_message_list` | `listBlackboardMessages` | both | identical |
144
+ | `blackboard.context.put` | `cw blackboard context put` | `cw_blackboard_context_put` | `putBlackboardContext` | both | identical |
145
+ | `blackboard.artifact.add` | `cw blackboard artifact add` | `cw_blackboard_artifact_add` | `addBlackboardArtifact` | both | identical |
146
+ | `blackboard.artifact.list` | `cw blackboard artifact list` | `cw_blackboard_artifact_list` | `listBlackboardArtifacts` | both | identical |
147
+ | `blackboard.snapshot` | `cw blackboard snapshot` | `cw_blackboard_snapshot` | `snapshotBlackboard` | both | identical |
148
+ | `coordinator.summary` | `cw coordinator summary` | `cw_coordinator_summary` | `coordinatorSummary` | both | identical |
149
+ | `coordinator.decision` | `cw coordinator decision` | `cw_coordinator_decision` | `recordCoordinatorDecision` | both | identical |
150
+ | `audit.summary` | `cw audit summary` | `cw_audit_summary` | `auditSummary` | both | identical |
151
+ | `audit.worker` | `cw audit worker` | `cw_audit_worker` | `workerAudit` | both | identical |
152
+ | `audit.provenance` | `cw audit provenance` | `cw_audit_provenance` | `evidenceProvenance` | both | identical |
153
+ | `audit.multi-agent` | `cw audit multi-agent --json` | `cw_audit_multi_agent` | `auditMultiAgent` | both | identical |
154
+ | `audit.policy` | `cw audit policy --json` | `cw_audit_policy` | `auditPolicy` | both | identical |
155
+ | `audit.role` | `cw audit role --json` | `cw_audit_role` | `auditRole` | both | identical |
156
+ | `audit.blackboard` | `cw audit blackboard --json` | `cw_audit_blackboard` | `auditBlackboard` | both | identical |
157
+ | `audit.judge` | `cw audit judge --json` | `cw_audit_judge` | `auditJudge` | both | identical |
158
+ | `audit.attest` | `cw audit attest` | `cw_audit_attest` | `recordAuditAttestation` | both | identical |
159
+ | `audit.decision` | `cw audit decision` | `cw_audit_decision` | `recordAuditDecision` | both | identical |
160
+ | `sandbox.list` | `cw sandbox list` | `cw_sandbox_list` | `listSandboxProfiles` | both | identical |
161
+ | `sandbox.show` | `cw sandbox show` | `cw_sandbox_show` | `showSandboxProfile` | both | identical |
162
+ | `sandbox.validate` | `cw sandbox validate` | `cw_sandbox_validate` | `validateSandboxProfile` | both | identical |
163
+ | `sandbox.choose` | `cw sandbox choose` | `cw_sandbox_choose` | `sandboxChoose` | both | identical |
164
+ | `sandbox.resolve` | `cw sandbox resolve` | `cw_sandbox_resolve` | `sandboxChoose` | both | identical |
165
+ | `worker.list` | `cw worker list` | `cw_worker_list` | `listWorkers` | both | identical |
166
+ | `worker.summary` | `cw worker summary --json` | `cw_worker_summary` | `summarizeWorkerRecords` | both | identical |
167
+ | `worker.show` | `cw worker show` | `cw_worker_show` | `showWorker` | both | identical |
168
+ | `worker.manifest` | `cw worker manifest` | `cw_worker_manifest` | `showWorkerManifest` | both | identical |
169
+ | `worker.output` | `cw worker output` | `cw_worker_output` | `recordWorkerOutput` | both | identical |
170
+ | `worker.fail` | `cw worker fail` | `cw_worker_fail` | `recordWorkerFailure` | both | identical |
171
+ | `worker.validate` | `cw worker validate` | `cw_worker_validate` | `validateWorker` | both | identical |
172
+ | `candidate.list` | `cw candidate list` | `cw_candidate_list` | `listCandidates` | both | identical |
173
+ | `candidate.show` | `cw candidate show` | `cw_candidate_show` | `showCandidate` | both | identical |
174
+ | `candidate.register` | `cw candidate register` | `cw_candidate_register` | `registerCandidate` | both | identical |
175
+ | `candidate.score` | `cw candidate score` | `cw_candidate_score` | `scoreCandidate` | both | identical |
176
+ | `candidate.rank` | `cw candidate rank` | `cw_candidate_rank` | `rankCandidates` | both | identical |
177
+ | `candidate.select` | `cw candidate select` | `cw_candidate_select` | `selectCandidate` | both | identical |
178
+ | `candidate.reject` | `cw candidate reject` | `cw_candidate_reject` | `rejectCandidate` | both | identical |
179
+ | `candidate.summary` | `cw candidate summary --json` | `cw_candidate_summary` | `summarizeCandidateOperatorRecords` | both | identical |
180
+ | `feedback.list` | `cw feedback list` | `cw_feedback_list` | `listFeedback` | both | identical |
181
+ | `feedback.show` | `cw feedback show` | `cw_feedback_show` | `showFeedback` | both | identical |
182
+ | `feedback.collect` | `cw feedback collect` | `cw_feedback_collect` | `collectFeedback` | both | identical |
183
+ | `feedback.summary` | `cw feedback summary --json` | `cw_feedback_summary` | `summarizeFeedbackRecords` | both | identical |
184
+ | `feedback.task` | `cw feedback task` | `cw_feedback_task` | `createFeedbackTask` | both | identical |
185
+ | `feedback.resolve` | `cw feedback resolve` | `cw_feedback_resolve` | `resolveFeedback` | both | identical |
186
+ | `schedule.create` | `cw schedule create` | `cw_schedule_create` | `scheduler.create` | both | identical |
187
+ | `schedule.list` | `cw schedule list` | `cw_schedule_list` | `scheduler.list` | both | identical |
188
+ | `schedule.delete` | `cw schedule delete` | `cw_schedule_delete` | `scheduler.delete` | both | identical |
189
+ | `schedule.due` | `cw schedule due` | `cw_schedule_due` | `scheduler.due` | both | identical |
190
+ | `schedule.complete` | `cw schedule complete` | `cw_schedule_complete` | `scheduler.complete` | both | identical |
191
+ | `schedule.pause` | `cw schedule pause` | `cw_schedule_pause` | `scheduler.pause` | both | identical |
192
+ | `schedule.resume` | `cw schedule resume` | `cw_schedule_resume` | `scheduler.resume` | both | identical |
193
+ | `schedule.run-now` | `cw schedule run-now` | `cw_schedule_run_now` | `scheduler.runNow` | both | identical |
194
+ | `schedule.history` | `cw schedule history` | `cw_schedule_history` | `scheduler.history` | both | identical |
195
+ | `schedule.daemon` | `cw schedule daemon` | `—` | `DesktopSchedulerDaemon.run` | cli-only | cli-only |
196
+ | `routine.create` | `cw routine create` | `cw_routine_create` | `triggers.create` | both | identical |
197
+ | `routine.list` | `cw routine list` | `cw_routine_list` | `triggers.list` | both | identical |
198
+ | `routine.delete` | `cw routine delete` | `cw_routine_delete` | `triggers.delete` | both | identical |
199
+ | `routine.fire` | `cw routine fire` | `cw_routine_fire` | `triggers.fire` | both | identical |
200
+ | `routine.events` | `cw routine events` | `cw_routine_events` | `triggers.events` | both | identical |
201
+
202
+ v0.1.27 closed the historical gaps. It added MCP peers `cw_init`, `cw_next`,
203
+ `cw_state_check`, `cw_contract_show`, `cw_node_list`, `cw_node_show`, and
204
+ `cw_node_graph`; and CLI peers `app run`, `operator status`, `operator report`,
205
+ `sandbox choose`, `sandbox resolve`, and `report --json`. Everything else is on
206
+ both surfaces.
207
+
208
+ ## Surface-Specific Capabilities
209
+
210
+ A capability may live on one surface only, but never silently — it must carry a
211
+ recorded reason in the registry. Three capabilities are CLI-only:
212
+
213
+ - `help` — human help text. MCP hosts enumerate capabilities via `tools/list`,
214
+ not a help command.
215
+ - `loop` — a convenience alias of `schedule create` with `kind=loop`. MCP hosts
216
+ use `cw_schedule_create` with `kind=loop`.
217
+ - `schedule daemon` — a long-running desktop daemon process, not a
218
+ request/response tool. MCP hosts drive ticks via `cw_schedule_due` and
219
+ `cw_schedule_run_now`.
220
+
221
+ One capability is intentionally payload-divergent (`projected`):
222
+
223
+ - `commit` — both surfaces route through the single core entry `runner.commit`.
224
+ The CLI emits the raw `StateCommitResult` for scripting (`commit.id`,
225
+ `commit.evidence`, `commit.gate`, `commit.acceptanceRationale`); `cw_commit`
226
+ emits the operator commit envelope (`commitId`, `verifierGated`, `checkpoint`,
227
+ `evidenceCount`, `snapshotPath`, `nextActions`, plus the raw result under
228
+ `commit`). This is a declared projection via `capability-core.commitEnvelope`,
229
+ not drift.
230
+
231
+ ## Fail-Closed Rules
232
+
233
+ The parity gate fails closed. Any of the following is a release-blocking error:
234
+
235
+ - a capability present on one surface but missing from the other
236
+ - an MCP tool that is live but not declared in the registry
237
+ - a CLI command or token that is live but not declared in the registry
238
+ - a surface-specific or payload-divergent capability with no recorded `reason`
239
+ - a payload divergence on a capability marked `payloadIdentical` — that is,
240
+ `cw <cmd> --json` and `cw_<tool>` returning different canonical JSON
241
+
242
+ There is no "fix it later" path. A surface mismatch blocks the release until the
243
+ registry, the surfaces, and the recorded reasons agree.
244
+
245
+ ## Enforcement & Smoke Coverage
246
+
247
+ Parity is checked by `scripts/parity-check.js --check`, run by
248
+ `npm run parity:check` and wired into `npm run release:check`. The check loads
249
+ the registry, enumerates the live CLI commands and MCP tools, and fails closed on
250
+ any of the rules above.
251
+
252
+ `test/cli-mcp-parity-smoke.js` proves the contract end to end. It verifies
253
+ registry ⇄ CLI ⇄ MCP coverage (every declared capability resolves on its
254
+ declared surfaces and nothing live is undeclared), confirms `--json` output
255
+ equals the MCP payload for every `payloadIdentical` capability, confirms the
256
+ declared `commit` projection, and confirms fail-closed behavior by injecting
257
+ drift — a removed peer, an undeclared tool, a reasonless exception, a mutated
258
+ payload — and asserting the gate rejects each one. It is included in `npm test`
259
+ and `npm run release:check`.
260
+
261
+ In CW, parity is not a convention; it is a derived, declared, and enforced
262
+ property of the build. It is not done until it is documented and tested.
263
+
264
+ ## Run Registry / Control Plane (v0.1.28)
265
+
266
+ v0.1.28 adds 13 control-plane capabilities — `registry refresh|show`, `run
267
+ search|list|show|resume|archive|rerun`, `queue add|list|drain|show`, and
268
+ `history` — declared once in the capability registry and validated by the same
269
+ fail-closed parity gate, so each `cw <cmd> --json` is schema-identical to its
270
+ `cw_<tool>`. See [run-registry-control-plane.7.md](run-registry-control-plane.7.md).
271
+
272
+ ## Execution Backends (v0.1.29)
273
+
274
+ v0.1.29 lifts execution into a pluggable driver layer: one narrow `ExecutionBackend`
275
+ contract with interchangeable `node`/`bun`/`shell`/`container`/`remote`/`ci`
276
+ drivers, selected by `--backend` (parallel to `--sandbox`) and inspected via
277
+ `backend list|show|probe`. The result/evidence envelope is schema-identical across
278
+ backends; the backend id + sandbox attestation are recorded as provenance, so this
279
+ surface is unchanged regardless of which backend executed a run. See
280
+ [execution-backends.7.md](execution-backends.7.md).
281
+ ## Web / Desktop Workbench (v0.1.30)
282
+
283
+ v0.1.30 adds the Web / Desktop Workbench: a read-only, localhost-only human
284
+ console that renders this surface (and the other four operator panels — run
285
+ graph, blackboard, worker logs, candidate compare, audit timeline) for any run,
286
+ reading the SAME capability `--json` payloads. It is a THIRD FRONT DOOR alongside
287
+ the CLI and MCP that holds no authoritative state and forks no schema: each panel
288
+ equals its `cw <cmd> --json` payload byte-for-byte (parity-gated), and refresh
289
+ re-derives everything from disk. See
290
+ [web-desktop-workbench.7.md](web-desktop-workbench.7.md).
291
+
292
+ ## Observability + Cost Accounting (v0.1.31)
293
+
294
+ v0.1.31 adds Observability + Cost Accounting: `metrics show`/`metrics summary`
295
+ derive durations, failure/verifier/acceptance rates (with sample counts and
296
+ fail-closed `n/a`), and host-attested token/cost from existing durable run state
297
+ — no metrics database, no collector daemon, no hidden counter. Usage is additive
298
+ and optional (absent ⇒ `unreported`, never 0); cost is `attested` (attested usage
299
+ × a recorded pricing policy) or clearly `estimated`, with pricing as policy. Both
300
+ verbs are parity-gated and render read-only in the v0.1.30 Workbench. See
301
+ [observability-cost-accounting.7.md](observability-cost-accounting.7.md).
302
+
303
+
304
+ ## Team Collaboration (v0.1.32)
305
+
306
+ v0.1.32 adds Team Collaboration: a host-attested actor and append-only
307
+ approvals/rejections/comments/handoffs provenance-linked to a durable target,
308
+ plus a review gate that STACKS ON the verifier gate — required approvals from
309
+ authorized roles, enforced inside `resolveCommitGate` AFTER the verifier checks
310
+ and never instead of them, failing closed on quorum/authority/self-approval and
311
+ recording who approved the very artifact that shipped. Policy (required approvals,
312
+ authorized roles, self-approval) is data, default off (pre-v0.1.32 behavior
313
+ unchanged). The verbs are parity-gated and render read-only in the v0.1.30
314
+ Workbench. See [Team Collaboration](team-collaboration.7.md).
315
+
316
+ ## Release Tooling (v0.1.33)
317
+
318
+ the per-tag mechanical surfaces (version bump across 17 surfaces, feature scaffold, and the forward-reference docs) become deterministic scripts, with a de-duplicated release gate. See release-tooling(7).
319
+
320
+ ## Real Execution Backend Integrations (v0.1.34)
321
+
322
+ container/remote/ci backends really execute (docker/podman run, remote/CI POST-and-poll) under the sandbox contract, with byte-stable evidence vs node and fail-closed refusal when a runtime/endpoint is unavailable. See real-execution-backends(7).
323
+
324
+ ## Node Snapshot / Diff / Replay (v0.1.35)
325
+
326
+ per-node snapshot, structural diff, and isolated deterministic replay over StateNode, reusing the v0.1.23 eval harness; fail-closed on source drift (valid|stale|absent). See node-snapshot-diff-replay(7).
327
+
328
+ ## Contract Migration Tooling (v0.1.36)
329
+
330
+ first-class declared migration registry (run-state + workflow-app) with per-edge compatibility proofs, fail-closed reachability, and a round-trip/non-destruction prover. See contract-migration-tooling(7).
331
+
332
+ ## Control-Plane Scheduling (v0.1.37)
333
+
334
+ priority + concurrency limits + lease lifecycle + retry/backoff + fail-closed park over the v0.1.28 Run Registry queue; policy-as-data, deterministic. See control-plane-scheduling(7).
335
+
336
+ ## Agent Delegation Drive (v0.1.38)
337
+
338
+ spawn an external agent process per worker, capture result.md + attestation, auto-drive plan->dispatch->fulfill->accept->commit
339
+
340
+ ## Run Retention & Provable Reclamation (v0.1.39)
341
+
342
+ tiered, append-only, cryptographically-verifiable run reclamation: seal the audit skeleton, free the reconstructable bulk, prove it
343
+
344
+ ## Durable State & Locking (v0.1.40)
345
+
346
+ atomic temp->rename writes + fsync-durability for authoritative stores; portable stale-stealing file lock serializing the cross-process read-modify-write stores
347
+
348
+ ## Self-Audit Hardening & Pure-Router Decomposition (v0.1.41)
349
+
350
+ evidence grounding + durable audit append + symlink-hardened containment + deterministic worker ids + recursive redaction; BackendRegistry self-describing drivers (no per-id switches); orchestrator god-object decomposed into per-domain operation modules (pure loadRun->delegate router)
351
+
352
+ ## Robust Result Ingest (v0.1.42)
353
+
354
+ capture findings/evidence from any reasonable agent shape (alt keys + prose), CW derives grounded evidence itself, warn on empty capture — closes the v0.1.41 live-drive 'accepted with 0 captured' failure
355
+
356
+ ## No-False-Green Gate & Launch Prep (v0.1.43)
357
+
358
+ Hard gate blocking empty-capture verifier-gated commits, plus quickstart and launch-prep docs.
359
+
360
+ ## Release-Gate Determinism & Agents Vendor (v0.1.44)
361
+
362
+ Release-readiness checks now validate the committed blob (`git show HEAD:<path>`) instead of the mutable working tree — eliminating false-red/false-green from concurrent working-tree writes (iCloud/Spotlight/editor). Adds the `agents` vendor manifest target: a generated `.agents/plugins/cool-workflow/` adapter giving any non-Claude AI agent one common interface to CW.
363
+
364
+ ## P1-P2 Fixes & CI Content Surfaces (v0.1.49)
365
+
366
+ Migration DAG with reversible edges (v0.1.45), capability auto-discovery (v0.1.46), vendor-adapter registry (v0.1.47), state auto-compaction and P2 fixes (v0.1.48), plus CI content-surface determinism hardening (v0.1.49).
367
+ 0.1.51
368
+
369
+ 0.1.76
370
+
371
+ 0.1.77
372
+
373
+ 0.1.78
@@ -0,0 +1,123 @@
1
+ # Contract Migration Tooling
2
+
3
+ CW v0.1.36 makes schema migration a first-class, declared subsystem. Before
4
+ v0.1.36 migration was ad-hoc and run-state-only: `RUN_STATE_MIGRATIONS` was an
5
+ inline step array walked by `migrateRunState`, with no declared `up`-transform
6
+ registry, no recorded compatibility PROOF, no round-trip/non-destruction
7
+ guarantee, and NOTHING covering the workflow-app schema (an old app schema was
8
+ flatly rejected, never migrated). v0.1.36 adds a declared registry, per-edge
9
+ compatibility proofs, fail-closed reachability, and a round-trip prover — reusing
10
+ the existing `migrateRunState` transform (no logic forked).
11
+
12
+ ## The declared registry
13
+
14
+ `migration list` is the single declared source for "what versions exist and how
15
+ to advance them": one `MigrationContract` per schema (`run-state`,
16
+ `workflow-app`), each with `currentVersion`, `minVersion`, and an array of
17
+ `MigrationEdge { from, to, description, proof }`. The run-state edges ARE
18
+ `RUN_STATE_MIGRATIONS` (the transform is not duplicated). Each edge carries a
19
+ mechanically-checkable `MigrationCompatibilityProof` — the invariant it preserves
20
+ (`addsDefaulted`, `dropsNothing`), as data, not prose.
21
+
22
+ ```text
23
+ migration list [--json]
24
+ ```
25
+
26
+ ## Fail closed on reachability
27
+
28
+ Before transforming, the chain `detected -> current` is resolved. If a contract's
29
+ detected version is below `minVersion`, above `currentVersion`, or has no chained
30
+ path, the verdict is `unsupported` with a named reason and NO write — never a
31
+ best-effort partial migration. (An older workflow-app, for which no edge exists
32
+ yet, fails closed with a precise reason instead of being silently accepted.)
33
+
34
+ ```text
35
+ migration check <target> [--contract run-state|workflow-app] [--json]
36
+ ```
37
+
38
+ `<target>` is a run id (resolves to `.cw/runs/<id>/state.json`) or a path to a
39
+ `state.json` / app manifest. The verdict reports `status`
40
+ (`current|migrated|normalized|unsupported`), the detected/current versions, the
41
+ resolved `chain`, the change count, and any errors.
42
+
43
+ ## Round-trip / non-destruction proof
44
+
45
+ ```text
46
+ migration prove <target> [--contract run-state|workflow-app] [--json]
47
+ ```
48
+
49
+ `migration prove` runs the chain and PROVES four properties, emitting a
50
+ deterministic, sha256-fingerprinted `MigrationProof`:
51
+
52
+ - **validatesAtCurrent** — the result validates at `currentVersion`.
53
+ - **appendOnly** — every source record/key survives into the output (recursive);
54
+ nothing is destroyed.
55
+ - **idempotent** — re-running migration on the output yields no further change.
56
+ - **sourceImmutable** — `sourceHash == resultHash`-of-source: the original
57
+ snapshot is byte-unchanged (`migrateRunState` clones; the source `state.json` is
58
+ never mutated).
59
+
60
+ `pass` is the conjunction. An `unsupported` verdict never transforms and never
61
+ claims a positive proof.
62
+
63
+ ## Append-only proof storage
64
+
65
+ `migration prove` persists the `MigrationProof` beside the target under
66
+ `migration/<fingerprint>.json` — a NEW file, never overwriting `state.json` or the
67
+ source manifest. Re-deriving from disk reproduces the same fingerprint.
68
+
69
+ ## Surfaces & Compatibility
70
+
71
+ `migration.list`/`check`/`prove` are declared `surface: "both"`, so
72
+ `cw migration <verb> --json` and the `cw_migration_*` MCP tools render one core
73
+ (`src/contract-migration.ts`). Additive: the run-state and workflow-app schema
74
+ versions and `migrateRunState` are unchanged; the registry declares and proves
75
+ over the existing transform. Pre-0.1.36 runs and apps load unchanged.
76
+
77
+ ## See Also
78
+
79
+ release-and-migration(7), state-explosion-management(7), workflow-app-framework(7),
80
+ cli-mcp-parity(7)
81
+
82
+ ## Control-Plane Scheduling (v0.1.37)
83
+
84
+ priority + concurrency limits + lease lifecycle + retry/backoff + fail-closed park over the v0.1.28 Run Registry queue; policy-as-data, deterministic. See control-plane-scheduling(7).
85
+
86
+ ## Agent Delegation Drive (v0.1.38)
87
+
88
+ spawn an external agent process per worker, capture result.md + attestation, auto-drive plan->dispatch->fulfill->accept->commit
89
+
90
+ ## Run Retention & Provable Reclamation (v0.1.39)
91
+
92
+ tiered, append-only, cryptographically-verifiable run reclamation: seal the audit skeleton, free the reconstructable bulk, prove it
93
+
94
+ ## Durable State & Locking (v0.1.40)
95
+
96
+ atomic temp->rename writes + fsync-durability for authoritative stores; portable stale-stealing file lock serializing the cross-process read-modify-write stores
97
+
98
+ ## Self-Audit Hardening & Pure-Router Decomposition (v0.1.41)
99
+
100
+ evidence grounding + durable audit append + symlink-hardened containment + deterministic worker ids + recursive redaction; BackendRegistry self-describing drivers (no per-id switches); orchestrator god-object decomposed into per-domain operation modules (pure loadRun->delegate router)
101
+
102
+ ## Robust Result Ingest (v0.1.42)
103
+
104
+ capture findings/evidence from any reasonable agent shape (alt keys + prose), CW derives grounded evidence itself, warn on empty capture — closes the v0.1.41 live-drive 'accepted with 0 captured' failure
105
+
106
+ ## No-False-Green Gate & Launch Prep (v0.1.43)
107
+
108
+ Hard gate blocking empty-capture verifier-gated commits, plus quickstart and launch-prep docs.
109
+
110
+ ## Release-Gate Determinism & Agents Vendor (v0.1.44)
111
+
112
+ Release-readiness checks now validate the committed blob (`git show HEAD:<path>`) instead of the mutable working tree — eliminating false-red/false-green from concurrent working-tree writes (iCloud/Spotlight/editor). Adds the `agents` vendor manifest target: a generated `.agents/plugins/cool-workflow/` adapter giving any non-Claude AI agent one common interface to CW.
113
+
114
+ ## P1-P2 Fixes & CI Content Surfaces (v0.1.49)
115
+
116
+ Migration DAG with reversible edges (v0.1.45), capability auto-discovery (v0.1.46), vendor-adapter registry (v0.1.47), state auto-compaction and P2 fixes (v0.1.48), plus CI content-surface determinism hardening (v0.1.49).
117
+ 0.1.51
118
+
119
+ 0.1.76
120
+
121
+ 0.1.77
122
+
123
+ 0.1.78