cool-workflow 0.1.83 → 0.1.85
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.
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +6 -0
- package/apps/architecture-review/app.json +1 -1
- package/apps/architecture-review-fast/app.json +1 -1
- package/apps/end-to-end-golden-path/app.json +1 -1
- package/apps/pr-review-fix-ci/app.json +1 -1
- package/apps/release-cut/app.json +1 -1
- package/apps/research-synthesis/app.json +1 -1
- package/dist/capability-core.js +89 -2
- package/dist/capability-registry.js +269 -2
- package/dist/cli/command-surface.js +1362 -0
- package/dist/cli.js +2 -1318
- package/dist/mcp-server.js +5 -1452
- package/dist/mcp-surface.js +1467 -0
- package/dist/run-export.js +139 -1
- package/dist/telemetry-demo.js +119 -0
- package/dist/types/report-bundle.js +6 -0
- package/dist/types.js +1 -0
- package/dist/version.js +1 -1
- package/dist/worker-accept/acceptance.js +114 -0
- package/dist/worker-accept/blackboard-fanout.js +80 -0
- package/dist/worker-accept/blackboard-linkage.js +19 -0
- package/dist/worker-accept/context.js +2 -0
- package/dist/worker-accept/telemetry-ledger.js +116 -0
- package/dist/worker-accept/validation.js +77 -0
- package/dist/worker-accept/verifier-completion.js +73 -0
- package/dist/worker-isolation.js +19 -444
- package/docs/agent-delegation-drive.7.md +6 -0
- package/docs/cli-mcp-parity.7.md +13 -3
- package/docs/contract-migration-tooling.7.md +6 -0
- package/docs/control-plane-scheduling.7.md +6 -0
- package/docs/durable-state-and-locking.7.md +6 -0
- package/docs/evidence-adoption-reasoning-chain.7.md +6 -0
- package/docs/execution-backends.7.md +6 -0
- package/docs/index.md +1 -0
- package/docs/multi-agent-cli-mcp-surface.7.md +6 -0
- package/docs/multi-agent-eval-replay-harness.7.md +6 -0
- package/docs/multi-agent-operator-ux.7.md +6 -0
- package/docs/node-snapshot-diff-replay.7.md +6 -0
- package/docs/observability-cost-accounting.7.md +6 -0
- package/docs/project-index.md +17 -6
- package/docs/real-execution-backends.7.md +6 -0
- package/docs/release-and-migration.7.md +6 -0
- package/docs/release-tooling.7.md +16 -1
- package/docs/report-verifiable-bundle.7.md +123 -0
- package/docs/run-registry-control-plane.7.md +6 -0
- package/docs/run-retention-reclamation.7.md +6 -0
- package/docs/state-explosion-management.7.md +6 -0
- package/docs/team-collaboration.7.md +6 -0
- package/docs/web-desktop-workbench.7.md +6 -0
- package/manifest/plugin.manifest.json +1 -1
- package/package.json +1 -1
- package/scripts/bump-version.js +9 -1
- package/scripts/canonical-apps.js +4 -4
- package/scripts/dogfood-release.js +1 -1
- package/scripts/golden-path.js +4 -4
- package/scripts/parity-check.js +27 -57
- package/scripts/release-flow.js +7 -6
- package/scripts/sync-project-index.js +1 -1
|
@@ -325,3 +325,9 @@ _No changes in v0.1.82._
|
|
|
325
325
|
## Hardening and Onboarding (v0.1.83)
|
|
326
326
|
|
|
327
327
|
Loaders fail closed on corrupt state; store writes are made safe under more than one writer; a new cw doctor checks your setup; help lists every command; and the docs are put into Basic English.
|
|
328
|
+
|
|
329
|
+
## Privacy Release (v0.1.84)
|
|
330
|
+
|
|
331
|
+
No other change to this page in v0.1.84.
|
|
332
|
+
|
|
333
|
+
0.1.85
|
|
@@ -146,3 +146,9 @@ _No change in behavior in v0.1.82 (the node projection field set was brought tog
|
|
|
146
146
|
## Hardening and Onboarding (v0.1.83)
|
|
147
147
|
|
|
148
148
|
Loaders fail closed on corrupt state; store writes are made safe under more than one writer; a new cw doctor checks your setup; help lists every command; and the docs are put into Basic English.
|
|
149
|
+
|
|
150
|
+
## Privacy Release (v0.1.84)
|
|
151
|
+
|
|
152
|
+
No other change to this page in v0.1.84.
|
|
153
|
+
|
|
154
|
+
0.1.85
|
|
@@ -205,3 +205,9 @@ _No changes in v0.1.82._
|
|
|
205
205
|
## Hardening and Onboarding (v0.1.83)
|
|
206
206
|
|
|
207
207
|
Loaders fail closed on corrupt state; store writes are made safe under more than one writer; a new cw doctor checks your setup; help lists every command; and the docs are put into Basic English.
|
|
208
|
+
|
|
209
|
+
## Privacy Release (v0.1.84)
|
|
210
|
+
|
|
211
|
+
No other change to this page in v0.1.84.
|
|
212
|
+
|
|
213
|
+
0.1.85
|
package/docs/project-index.md
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
# Cool Workflow Project Index
|
|
2
2
|
|
|
3
|
-
Generated from the current repository code on 2026-06-
|
|
3
|
+
Generated from the current repository code on 2026-06-18 by `npm run sync:project-index`.
|
|
4
4
|
|
|
5
5
|
## Snapshot
|
|
6
6
|
|
|
7
7
|
- Package: `cool-workflow`
|
|
8
|
-
- Version: `0.1.
|
|
9
|
-
- Source modules: `
|
|
8
|
+
- Version: `0.1.85`
|
|
9
|
+
- Source modules: `62`
|
|
10
10
|
- Workflow apps: `7`
|
|
11
|
-
- Docs: `
|
|
12
|
-
- Smoke tests: `
|
|
13
|
-
- Repository:
|
|
11
|
+
- Docs: `50`
|
|
12
|
+
- Smoke tests: `101`
|
|
13
|
+
- Repository: https://github.com/coo1white/cool-workflow
|
|
14
14
|
|
|
15
15
|
## Architecture
|
|
16
16
|
|
|
@@ -92,6 +92,7 @@ multi-agent host -> topology -> blackboard/coordinator
|
|
|
92
92
|
- [evidence-reasoning.ts](../src/evidence-reasoning.ts)
|
|
93
93
|
- [execution-backend.ts](../src/execution-backend.ts)
|
|
94
94
|
- [gates.ts](../src/gates.ts)
|
|
95
|
+
- [mcp-surface.ts](../src/mcp-surface.ts)
|
|
95
96
|
- [multi-agent-eval.ts](../src/multi-agent-eval.ts)
|
|
96
97
|
- [multi-agent-operator-ux.ts](../src/multi-agent-operator-ux.ts)
|
|
97
98
|
- [multi-agent-trust.ts](../src/multi-agent-trust.ts)
|
|
@@ -160,6 +161,7 @@ multi-agent host -> topology -> blackboard/coordinator
|
|
|
160
161
|
- [Real Execution Backend Integrations](real-execution-backends.7.md)
|
|
161
162
|
- [Release And Migration Discipline](release-and-migration.7.md)
|
|
162
163
|
- [Release Tooling](release-tooling.7.md)
|
|
164
|
+
- [Verifiable Report Bundle](report-verifiable-bundle.7.md)
|
|
163
165
|
- [Routines](routines.md)
|
|
164
166
|
- [Run Registry / Control Plane](run-registry-control-plane.7.md)
|
|
165
167
|
- [Run Retention & Provable Reclamation](run-retention-reclamation.7.md)
|
|
@@ -189,9 +191,11 @@ Smoke tests mirror the public contracts. The high-signal suites are:
|
|
|
189
191
|
- [audit-verify-smoke.js](../test/audit-verify-smoke.js)
|
|
190
192
|
- [backend-registry-smoke.js](../test/backend-registry-smoke.js)
|
|
191
193
|
- [block-unapproved-tag-smoke.js](../test/block-unapproved-tag-smoke.js)
|
|
194
|
+
- [bump-version-idempotent-smoke.js](../test/bump-version-idempotent-smoke.js)
|
|
192
195
|
- [candidate-scoring-smoke.js](../test/candidate-scoring-smoke.js)
|
|
193
196
|
- [canonical-workflow-apps-smoke.js](../test/canonical-workflow-apps-smoke.js)
|
|
194
197
|
- [claude-p-agent-wrapper-smoke.js](../test/claude-p-agent-wrapper-smoke.js)
|
|
198
|
+
- [cli-command-surface-smoke.js](../test/cli-command-surface-smoke.js)
|
|
195
199
|
- [cli-jsonmode-parity-smoke.js](../test/cli-jsonmode-parity-smoke.js)
|
|
196
200
|
- [cli-mcp-parity-smoke.js](../test/cli-mcp-parity-smoke.js)
|
|
197
201
|
- [concurrent-failure-semantics-smoke.js](../test/concurrent-failure-semantics-smoke.js)
|
|
@@ -199,6 +203,7 @@ Smoke tests mirror the public contracts. The high-signal suites are:
|
|
|
199
203
|
- [contract-migration-tooling-smoke.js](../test/contract-migration-tooling-smoke.js)
|
|
200
204
|
- [control-plane-scheduling-smoke.js](../test/control-plane-scheduling-smoke.js)
|
|
201
205
|
- [coordinator-blackboard-smoke.js](../test/coordinator-blackboard-smoke.js)
|
|
206
|
+
- [demo-bundle-smoke.js](../test/demo-bundle-smoke.js)
|
|
202
207
|
- [det-ids-b-smoke.js](../test/det-ids-b-smoke.js)
|
|
203
208
|
- [doctor-smoke.js](../test/doctor-smoke.js)
|
|
204
209
|
- [dogfood-release-smoke.js](../test/dogfood-release-smoke.js)
|
|
@@ -213,6 +218,7 @@ Smoke tests mirror the public contracts. The high-signal suites are:
|
|
|
213
218
|
- [freebsd-audit-fixes-smoke.js](../test/freebsd-audit-fixes-smoke.js)
|
|
214
219
|
- [h7-custom-profile-persist-smoke.js](../test/h7-custom-profile-persist-smoke.js)
|
|
215
220
|
- [mcp-app-surface-smoke.js](../test/mcp-app-surface-smoke.js)
|
|
221
|
+
- [mcp-surface-registry-smoke.js](../test/mcp-surface-registry-smoke.js)
|
|
216
222
|
- [multi-agent-cli-mcp-surface-smoke.js](../test/multi-agent-cli-mcp-surface-smoke.js)
|
|
217
223
|
- [multi-agent-eval-determinism-regression-smoke.js](../test/multi-agent-eval-determinism-regression-smoke.js)
|
|
218
224
|
- [multi-agent-eval-replay-harness-smoke.js](../test/multi-agent-eval-replay-harness-smoke.js)
|
|
@@ -228,15 +234,19 @@ Smoke tests mirror the public contracts. The high-signal suites are:
|
|
|
228
234
|
- [operator-ux-smoke.js](../test/operator-ux-smoke.js)
|
|
229
235
|
- [parallel-onramp-smoke.js](../test/parallel-onramp-smoke.js)
|
|
230
236
|
- [parity-doc-sync-smoke.js](../test/parity-doc-sync-smoke.js)
|
|
237
|
+
- [pii-redaction-smoke.js](../test/pii-redaction-smoke.js)
|
|
231
238
|
- [pipeline-auto-advance-smoke.js](../test/pipeline-auto-advance-smoke.js)
|
|
232
239
|
- [pipeline-runner-smoke.js](../test/pipeline-runner-smoke.js)
|
|
233
240
|
- [project-index-sync-smoke.js](../test/project-index-sync-smoke.js)
|
|
241
|
+
- [quickstart-bundle-smoke.js](../test/quickstart-bundle-smoke.js)
|
|
234
242
|
- [quickstart-smoke.js](../test/quickstart-smoke.js)
|
|
235
243
|
- [real-execution-backends-smoke.js](../test/real-execution-backends-smoke.js)
|
|
236
244
|
- [registry-corrupt-fail-closed-smoke.js](../test/registry-corrupt-fail-closed-smoke.js)
|
|
237
245
|
- [release-flow-smoke.js](../test/release-flow-smoke.js)
|
|
238
246
|
- [release-gate-smoke.js](../test/release-gate-smoke.js)
|
|
239
247
|
- [release-tooling-smoke.js](../test/release-tooling-smoke.js)
|
|
248
|
+
- [report-bundle-smoke.js](../test/report-bundle-smoke.js)
|
|
249
|
+
- [report-verify-bundle-smoke.js](../test/report-verify-bundle-smoke.js)
|
|
240
250
|
- [result-normalize-smoke.js](../test/result-normalize-smoke.js)
|
|
241
251
|
- [robustness-failclosed-smoke.js](../test/robustness-failclosed-smoke.js)
|
|
242
252
|
- [robustness-hardening-smoke.js](../test/robustness-hardening-smoke.js)
|
|
@@ -271,6 +281,7 @@ Smoke tests mirror the public contracts. The high-signal suites are:
|
|
|
271
281
|
- [verifier-gated-commit-smoke.js](../test/verifier-gated-commit-smoke.js)
|
|
272
282
|
- [verify-import-audit-chain-smoke.js](../test/verify-import-audit-chain-smoke.js)
|
|
273
283
|
- [web-desktop-workbench-smoke.js](../test/web-desktop-workbench-smoke.js)
|
|
284
|
+
- [worker-accept-path-architecture-smoke.js](../test/worker-accept-path-architecture-smoke.js)
|
|
274
285
|
- [worker-isolation-smoke.js](../test/worker-isolation-smoke.js)
|
|
275
286
|
- [worker-retry-count-smoke.js](../test/worker-retry-count-smoke.js)
|
|
276
287
|
- [workflow-app-framework-smoke.js](../test/workflow-app-framework-smoke.js)
|
|
@@ -153,3 +153,9 @@ _No behavioral change in v0.1.82 (delegated child programs moved out to `scripts
|
|
|
153
153
|
## Hardening and Onboarding (v0.1.83)
|
|
154
154
|
|
|
155
155
|
Loaders fail closed on corrupt state; store writes are made safe under more than one writer; a new cw doctor checks your setup; help lists every command; and the docs are put into Basic English.
|
|
156
|
+
|
|
157
|
+
## Privacy Release (v0.1.84)
|
|
158
|
+
|
|
159
|
+
No other change to this page in v0.1.84.
|
|
160
|
+
|
|
161
|
+
0.1.85
|
|
@@ -293,3 +293,9 @@ _No changes in v0.1.82._
|
|
|
293
293
|
## Hardening and Onboarding (v0.1.83)
|
|
294
294
|
|
|
295
295
|
Loaders fail closed on corrupt state; store writes are made safe under more than one writer; a new cw doctor checks your setup; help lists every command; and the docs are put into Basic English.
|
|
296
|
+
|
|
297
|
+
## Privacy Release (v0.1.84)
|
|
298
|
+
|
|
299
|
+
No other change to this page in v0.1.84.
|
|
300
|
+
|
|
301
|
+
0.1.85
|
|
@@ -143,12 +143,21 @@ The per-platform difference is config, not code — set the reviewer agent here:
|
|
|
143
143
|
|
|
144
144
|
| Platform | Reviewer config |
|
|
145
145
|
|---|---|
|
|
146
|
-
| Claude | `CW_AGENT_COMMAND="claude -p {{input}}"` |
|
|
146
|
+
| Claude | `CW_AGENT_COMMAND="claude -p --permission-mode acceptEdits {{input}}"` |
|
|
147
147
|
| Codex | `CW_AGENT_COMMAND="codex exec {{input}}"` |
|
|
148
148
|
| Gemini | `CW_AGENT_COMMAND="gemini -p {{input}}"` |
|
|
149
149
|
| OpenCode | `CW_AGENT_COMMAND="opencode run -m <provider/model> {{input}}"` |
|
|
150
150
|
| DeepSeek | via OpenCode (`-m deepseek/deepseek-chat`) or `CW_AGENT_ENDPOINT=<deepseek-compatible HTTP agent>` |
|
|
151
151
|
|
|
152
|
+
The reviewer's last act is to **write** the verdict file, so a headless agent
|
|
153
|
+
needs file-write permission. For `claude -p`, recent CLIs default to a mode that
|
|
154
|
+
silently denies `Write` (no prompt in headless mode), so the reviewer reaches a
|
|
155
|
+
verdict but cannot persist it and the flow fails closed at `[3/3] verify` with
|
|
156
|
+
`no verdict written`. The `--permission-mode acceptEdits` flag in the preset above
|
|
157
|
+
fixes this; Read/Bash (which the review itself needs) keep working. The reviewer
|
|
158
|
+
CLI must also be logged in (`claude auth login` / `claude auth status` →
|
|
159
|
+
`loggedIn: true`) — a fresh shell or CI runner is not.
|
|
160
|
+
|
|
152
161
|
`{{input}}` is put in place of the reviewer prompt file path. Gemini and OpenCode
|
|
153
162
|
also get generated MCP manifests (`.gemini-plugin/`, `.opencode-plugin/`) so the
|
|
154
163
|
`cw_*` tools are there as MCP tools in those hosts. The verdict path
|
|
@@ -200,3 +209,9 @@ _No changes to the release-tooling contract in v0.1.82._
|
|
|
200
209
|
## Hardening and Onboarding (v0.1.83)
|
|
201
210
|
|
|
202
211
|
Loaders fail closed on corrupt state; store writes are made safe under more than one writer; a new cw doctor checks your setup; help lists every command; and the docs are put into Basic English.
|
|
212
|
+
|
|
213
|
+
## Privacy Release (v0.1.84)
|
|
214
|
+
|
|
215
|
+
`release-flow` now writes reviewer input with repo-local paths, so local user home names do not enter the saved review prompt.
|
|
216
|
+
|
|
217
|
+
0.1.85
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Verifiable Report Bundle
|
|
2
|
+
|
|
3
|
+
CW v0.1.85 adds the Verifiable Report Bundle: a way to hand someone a run's report
|
|
4
|
+
that they can check themselves, OFFLINE, with one command — no source repo, no
|
|
5
|
+
pre-existing `.cw` tree, and no key passed on the side.
|
|
6
|
+
|
|
7
|
+
Before this, a run could be exported to a portable `<id>.cwrun.json` archive
|
|
8
|
+
([Run Registry / Control Plane](run-registry-control-plane.7.md)) and its bytes
|
|
9
|
+
re-proven with `cw run inspect-archive`. But two things stopped a stranger from
|
|
10
|
+
fully verifying it:
|
|
11
|
+
|
|
12
|
+
- The ed25519 PUBLIC key that re-checks the signed telemetry came only from
|
|
13
|
+
`--pubkey` or the `CW_AGENT_ATTEST_PUBKEY` environment variable — it did not
|
|
14
|
+
travel with the archive.
|
|
15
|
+
- `inspect-archive` proves the archive's own file digests, not the telemetry hash
|
|
16
|
+
chain or the signatures. Re-proving those meant `cw run import` into a real
|
|
17
|
+
`.cw` tree and then `cw run verify-import` — too much to ask of a recipient.
|
|
18
|
+
|
|
19
|
+
The Verifiable Report Bundle closes both gaps without a new archive format.
|
|
20
|
+
|
|
21
|
+
## Mechanism vs Policy
|
|
22
|
+
|
|
23
|
+
The MECHANISM is three small additions to the existing export/verify path:
|
|
24
|
+
|
|
25
|
+
1. `cw run export <run> --with-trust-key <pem-or-path>` embeds the operator's
|
|
26
|
+
ed25519 PUBLIC key into the archive under a new optional `trust` block
|
|
27
|
+
(`{ publicKeyPem, algorithm: "ed25519" }`). Only a public key is ever embedded;
|
|
28
|
+
CW never exports a private key. The flag defaults to `CW_AGENT_ATTEST_PUBKEY`,
|
|
29
|
+
so one configured key both attests at record-time and travels with the export.
|
|
30
|
+
A raw inline PEM begins with `-----`, which the CLI parses as a flag — so the
|
|
31
|
+
CLI form takes a key FILE PATH; an inline PEM is accepted programmatically and
|
|
32
|
+
via the environment variable.
|
|
33
|
+
|
|
34
|
+
2. `cw report verify-bundle <bundle>` verifies the bundle SELF-CONTAINED and
|
|
35
|
+
OFFLINE. It reuses the existing verifiers end to end: `inspectArchive` for the
|
|
36
|
+
archive bytes, then a restore into a throwaway temp dir (auto-removed) so
|
|
37
|
+
`verifyImportedRun` re-proves the telemetry hash chain and the trust-audit
|
|
38
|
+
chain, then `verifyTelemetrySignatures` re-runs ed25519 over each attested hop
|
|
39
|
+
using the key the bundle carries. It writes nothing to any registry.
|
|
40
|
+
|
|
41
|
+
3. `cw report bundle <run>` is the PRODUCER counterpart: it exports a sealed
|
|
42
|
+
bundle (step 1) and then immediately self-verifies it (step 2), returning the
|
|
43
|
+
archive path and the verification verdict together. It fails closed — a solo
|
|
44
|
+
operator never hands off a report whose bundle does not verify (for example, no
|
|
45
|
+
trust key configured under `--strict-signatures`). `--extract-report` also
|
|
46
|
+
writes the human-readable `report.md` next to the bundle so the shippable pair
|
|
47
|
+
is produced in one command. It is pure composition; it spawns nothing.
|
|
48
|
+
|
|
49
|
+
`cw quickstart <app> --bundle [--with-trust-key K]` folds step 3 into the
|
|
50
|
+
one-command entry: after the drive reaches `status: complete`, it seals the run
|
|
51
|
+
with `reportBundle` (anchored to the run's own repo) and returns the verdict as
|
|
52
|
+
`result.bundle`. It is gated on completion — a blocked/partial run is **never**
|
|
53
|
+
sealed (the operator gets a `hint`, not a half-shipped artifact) — and the CLI
|
|
54
|
+
exits non-zero when `result.bundle.ok` is false. `quickstart` stays `cli-only`;
|
|
55
|
+
MCP hosts compose `cw_run_drive_step` + `cw_report_bundle` for the same outcome.
|
|
56
|
+
|
|
57
|
+
Because the README headline runs quickstart cross-directory (your shell cwd is not
|
|
58
|
+
the `--repo`), the run is resolved from its own repo, but the bundle's OUTPUT —
|
|
59
|
+
the `.cwrun.json` and any `--extract-report` — lands in **your cwd**, not the
|
|
60
|
+
analyzed repo (so `cw quickstart … --bundle --extract-report out.md && send out.md`
|
|
61
|
+
works and the repo's working tree is never polluted). `result.bundle.archivePath`
|
|
62
|
+
and `result.bundle.reportExtractedTo` report the absolute paths.
|
|
63
|
+
|
|
64
|
+
The POLICY is fail-closed and self-describing:
|
|
65
|
+
|
|
66
|
+
- Key precedence is **bundle > `--pubkey` > `CW_AGENT_ATTEST_PUBKEY`**, so a bundle
|
|
67
|
+
with an embedded key verifies the same on any machine; the override/env only
|
|
68
|
+
apply when the bundle omits a key.
|
|
69
|
+
- `ok` is true only when the archive bytes, the telemetry chain, and the
|
|
70
|
+
trust-audit chain all verify AND no attested signature failed re-verification.
|
|
71
|
+
- A bundle with attested telemetry but no available key DEGRADES by default
|
|
72
|
+
(`signatureKeyProvided: false`, the intact chain still decides `ok`).
|
|
73
|
+
`--strict-signatures` refuses such a bundle instead.
|
|
74
|
+
- `--extract-report <path>` writes the bundle's `report.md` out for a human to
|
|
75
|
+
read alongside the machine verdict. If extraction is requested but the bundle
|
|
76
|
+
has no `report.md` (or the write fails), that is a failure, not a silent no-op:
|
|
77
|
+
a `extract-report` / `report-md-unavailable` check is recorded and `ok` is
|
|
78
|
+
false — so a producer never ships a green verdict with no report attached.
|
|
79
|
+
|
|
80
|
+
## Fail closed
|
|
81
|
+
|
|
82
|
+
`cw report verify-bundle` exits non-zero whenever `ok` is false, so
|
|
83
|
+
`cw report verify-bundle <file> && ship` cannot pass on a forgery. This holds even
|
|
84
|
+
for a telemetry chain forged so that every archive file digest still matches: the
|
|
85
|
+
file-digest layer (`inspect-archive`) would wave it through, but the embedded hash
|
|
86
|
+
chain breaks at the next record and the signature re-verification rejects inflated
|
|
87
|
+
usage. A missing, unreadable, or schema-unsupported bundle is also `ok: false`.
|
|
88
|
+
|
|
89
|
+
## Usage
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
# See it in 30 seconds, hermetic — no agent, no API key, no repo:
|
|
93
|
+
npx cool-workflow demo bundle
|
|
94
|
+
# -> builds a sealed bundle, forges it two ways, and shows verify-bundle
|
|
95
|
+
# catching both offline with only the embedded public key.
|
|
96
|
+
|
|
97
|
+
# Run the review AND get a shippable, client-verifiable bundle from ONE command:
|
|
98
|
+
cw quickstart architecture-review --repo . --question "What are the risks?" \
|
|
99
|
+
--agent-command "claude -p" --bundle --with-trust-key ./trust-pub.pem
|
|
100
|
+
# -> after the drive COMPLETES, the run is sealed into a self-verified bundle and
|
|
101
|
+
# the verdict is folded into the quickstart JSON (result.bundle). Exits non-zero
|
|
102
|
+
# if that bundle would not verify. A run that did not complete is never sealed.
|
|
103
|
+
|
|
104
|
+
# Produce-and-prove from an existing run: export sealed + self-verify + emit the report.
|
|
105
|
+
cw report bundle <run-id> --with-trust-key ./trust-pub.pem \
|
|
106
|
+
--output report.cwrun.json --extract-report report.md
|
|
107
|
+
# -> exits non-zero if the produced bundle would not verify (don't ship it).
|
|
108
|
+
|
|
109
|
+
# Or the two steps separately:
|
|
110
|
+
cw run export <run-id> --with-trust-key ./trust-pub.pem --output report.cwrun.json
|
|
111
|
+
|
|
112
|
+
# Anyone, anywhere, offline — no repo, no key handed over, no install beyond npx:
|
|
113
|
+
npx cool-workflow report verify-bundle report.cwrun.json
|
|
114
|
+
npx cool-workflow report verify-bundle report.cwrun.json --extract-report report.md
|
|
115
|
+
npx cool-workflow report verify-bundle report.cwrun.json --strict-signatures --json
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
The same capability is on the MCP surface as `cw_report_verify_bundle`, so an agent
|
|
119
|
+
host re-verifies a bundle through the identical core entry.
|
|
120
|
+
|
|
121
|
+
See also [Security / Trust Hardening](security-trust-hardening.7.md) and the trust
|
|
122
|
+
model's honest ceiling: a signature proves non-repudiable attribution to the key
|
|
123
|
+
holder, not ground-truth measurement.
|
|
@@ -404,3 +404,9 @@ _No behavioral change in v0.1.82 (run resolution now threads an explicit base di
|
|
|
404
404
|
## Hardening and Onboarding (v0.1.83)
|
|
405
405
|
|
|
406
406
|
Loaders fail closed on corrupt state; store writes are made safe under more than one writer; a new cw doctor checks your setup; help lists every command; and the docs are put into Basic English.
|
|
407
|
+
|
|
408
|
+
## Privacy Release (v0.1.84)
|
|
409
|
+
|
|
410
|
+
No other change to this page in v0.1.84.
|
|
411
|
+
|
|
412
|
+
0.1.85
|
|
@@ -204,3 +204,9 @@ _No changes in v0.1.82._
|
|
|
204
204
|
## Hardening and Onboarding (v0.1.83)
|
|
205
205
|
|
|
206
206
|
Loaders fail closed on corrupt state; store writes are made safe under more than one writer; a new cw doctor checks your setup; help lists every command; and the docs are put into Basic English.
|
|
207
|
+
|
|
208
|
+
## Privacy Release (v0.1.84)
|
|
209
|
+
|
|
210
|
+
No other change to this page in v0.1.84.
|
|
211
|
+
|
|
212
|
+
0.1.85
|
|
@@ -282,3 +282,9 @@ _No changes in v0.1.82._
|
|
|
282
282
|
## Hardening and Onboarding (v0.1.83)
|
|
283
283
|
|
|
284
284
|
Loaders fail closed on corrupt state; store writes are made safe under more than one writer; a new cw doctor checks your setup; help lists every command; and the docs are put into Basic English.
|
|
285
|
+
|
|
286
|
+
## Privacy Release (v0.1.84)
|
|
287
|
+
|
|
288
|
+
No other change to this page in v0.1.84.
|
|
289
|
+
|
|
290
|
+
0.1.85
|
|
@@ -218,3 +218,9 @@ _No changes in v0.1.82._
|
|
|
218
218
|
## Hardening and Onboarding (v0.1.83)
|
|
219
219
|
|
|
220
220
|
Loaders fail closed on corrupt state; store writes are made safe under more than one writer; a new cw doctor checks your setup; help lists every command; and the docs are put into Basic English.
|
|
221
|
+
|
|
222
|
+
## Privacy Release (v0.1.84)
|
|
223
|
+
|
|
224
|
+
No other change to this page in v0.1.84.
|
|
225
|
+
|
|
226
|
+
0.1.85
|
|
@@ -226,3 +226,9 @@ _No changes in v0.1.82._
|
|
|
226
226
|
## Hardening and Onboarding (v0.1.83)
|
|
227
227
|
|
|
228
228
|
Loaders fail closed on corrupt state; store writes are made safe under more than one writer; a new cw doctor checks your setup; help lists every command; and the docs are put into Basic English.
|
|
229
|
+
|
|
230
|
+
## Privacy Release (v0.1.84)
|
|
231
|
+
|
|
232
|
+
No other change to this page in v0.1.84.
|
|
233
|
+
|
|
234
|
+
0.1.85
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"_comment": "SINGLE SOURCE OF TRUTH for every vendor manifest. Edit THIS file, then run `npm run gen:manifests`. Do NOT hand-edit the generated vendor manifests (.claude-plugin/, .codex-plugin/, .agents/, .mcp.json) — `npm run gen:manifests -- --check` (run by release:check) will fail if they drift from this source.",
|
|
3
3
|
"identity": {
|
|
4
4
|
"name": "cool-workflow",
|
|
5
|
-
"version": "0.1.
|
|
5
|
+
"version": "0.1.85",
|
|
6
6
|
"license": "BSD-2-Clause",
|
|
7
7
|
"homepage": "https://github.com/coo1white/cool-workflow",
|
|
8
8
|
"author": {
|
package/package.json
CHANGED
package/scripts/bump-version.js
CHANGED
|
@@ -59,7 +59,15 @@ function main() {
|
|
|
59
59
|
if (!SEMVER.test(next)) fail(`"${next}" is not a x.y.z version`);
|
|
60
60
|
|
|
61
61
|
const current = JSON.parse(fs.readFileSync(path.join(pluginRoot, "package.json"), "utf8")).version;
|
|
62
|
-
if (next === current)
|
|
62
|
+
if (next === current) {
|
|
63
|
+
// Idempotent: re-running the bump for the same version is a no-op (exit 0)
|
|
64
|
+
// rather than a hard fail. Required by `release-flow --cut --version X` when
|
|
65
|
+
// the bump was already landed in a prior PR (e.g. a release-prep PR that
|
|
66
|
+
// committed the version surfaces, then a follow-up fix on top — cut should
|
|
67
|
+
// still be able to commit the verdict and tag without re-bumping).
|
|
68
|
+
process.stdout.write(`bump:version: already at ${next}, no surfaces to update\n`);
|
|
69
|
+
process.exit(0);
|
|
70
|
+
}
|
|
63
71
|
|
|
64
72
|
const touched = [];
|
|
65
73
|
const note = (rel) => touched.push(rel);
|
|
@@ -83,7 +83,7 @@ const canonicalApps = [
|
|
|
83
83
|
"--source",
|
|
84
84
|
"plugins/cool-workflow/docs/workflow-app-framework.7.md",
|
|
85
85
|
"--scope",
|
|
86
|
-
"Cool Workflow v0.1.
|
|
86
|
+
"Cool Workflow v0.1.85",
|
|
87
87
|
"--freshness",
|
|
88
88
|
"as of release preparation"
|
|
89
89
|
]
|
|
@@ -117,14 +117,14 @@ function main() {
|
|
|
117
117
|
assert.ok(summary, `${app.id} must appear in app list`);
|
|
118
118
|
assert.equal(summary.sourceKind, "app-directory");
|
|
119
119
|
assert.equal(summary.legacy, false);
|
|
120
|
-
assert.equal(summary.version, "0.1.
|
|
120
|
+
assert.equal(summary.version, "0.1.85");
|
|
121
121
|
|
|
122
122
|
const validation = runJson(["app", "validate", manifestPath]);
|
|
123
123
|
assert.equal(validation.valid, true, `${app.id} manifest must validate`);
|
|
124
124
|
|
|
125
125
|
const shown = runJson(["app", "show", app.id]);
|
|
126
126
|
assert.equal(shown.app.id, app.id);
|
|
127
|
-
assert.equal(shown.app.version, "0.1.
|
|
127
|
+
assert.equal(shown.app.version, "0.1.85");
|
|
128
128
|
assert.ok(shown.app.metadata.canonical, `${app.id} must be marked canonical`);
|
|
129
129
|
assert.ok(shown.app.sandboxProfiles.length > 0, `${app.id} must declare sandbox profiles`);
|
|
130
130
|
assertTaskIdsUnique(shown);
|
|
@@ -135,7 +135,7 @@ function main() {
|
|
|
135
135
|
const plan = runJson(["plan", app.id, ...app.args(workspace)]);
|
|
136
136
|
const state = JSON.parse(fs.readFileSync(plan.statePath, "utf8"));
|
|
137
137
|
assert.equal(state.workflow.app.id, app.id);
|
|
138
|
-
assert.equal(state.workflow.app.version, "0.1.
|
|
138
|
+
assert.equal(state.workflow.app.version, "0.1.85");
|
|
139
139
|
assert.equal(state.workflow.app.metadata.canonical, true);
|
|
140
140
|
assert.ok(state.tasks.some((task) => task.requiresEvidence), `${app.id} plan must include evidence gates`);
|
|
141
141
|
assert.ok(state.tasks.every((task) => task.sandboxProfileId), `${app.id} plan must include sandbox hints`);
|
|
@@ -5,7 +5,7 @@ const { spawnSync } = require("node:child_process");
|
|
|
5
5
|
const fs = require("node:fs");
|
|
6
6
|
const path = require("node:path");
|
|
7
7
|
|
|
8
|
-
const TARGET_VERSION = "0.1.
|
|
8
|
+
const TARGET_VERSION = "0.1.85";
|
|
9
9
|
const PREVIOUS_VERSION = "0.1.31";
|
|
10
10
|
const pluginRoot = path.resolve(__dirname, "..");
|
|
11
11
|
const repoRoot = path.resolve(pluginRoot, "..", "..");
|
package/scripts/golden-path.js
CHANGED
|
@@ -33,7 +33,7 @@ function main() {
|
|
|
33
33
|
const appValidation = runJson(["app", "validate", "end-to-end-golden-path"], pluginRoot);
|
|
34
34
|
assert.equal(appValidation.valid, true);
|
|
35
35
|
assert.equal(appValidation.summary.id, "end-to-end-golden-path");
|
|
36
|
-
assert.equal(appValidation.summary.version, "0.1.
|
|
36
|
+
assert.equal(appValidation.summary.version, "0.1.85");
|
|
37
37
|
|
|
38
38
|
const plan = runJson(
|
|
39
39
|
[
|
|
@@ -42,7 +42,7 @@ function main() {
|
|
|
42
42
|
"--repo",
|
|
43
43
|
tmp,
|
|
44
44
|
"--question",
|
|
45
|
-
"Prove the deterministic v0.1.
|
|
45
|
+
"Prove the deterministic v0.1.85 end-to-end golden path."
|
|
46
46
|
],
|
|
47
47
|
pluginRoot
|
|
48
48
|
);
|
|
@@ -52,7 +52,7 @@ function main() {
|
|
|
52
52
|
|
|
53
53
|
let state = readJson(plan.statePath);
|
|
54
54
|
assert.equal(state.workflow.app.id, "end-to-end-golden-path");
|
|
55
|
-
assert.equal(state.workflow.app.version, "0.1.
|
|
55
|
+
assert.equal(state.workflow.app.version, "0.1.85");
|
|
56
56
|
assert.equal(state.loopStage, "interpret");
|
|
57
57
|
|
|
58
58
|
const dispatch = runJson(["dispatch", plan.runId, "--limit", "1", "--sandbox", "readonly"], tmp);
|
|
@@ -195,7 +195,7 @@ function main() {
|
|
|
195
195
|
assert.equal(reportPath, plan.reportPath);
|
|
196
196
|
assert.ok(fs.existsSync(reportPath));
|
|
197
197
|
const report = fs.readFileSync(reportPath, "utf8");
|
|
198
|
-
assert.match(report, /Workflow App: end-to-end-golden-path@0\.1\.
|
|
198
|
+
assert.match(report, /Workflow App: end-to-end-golden-path@0\.1\.85/);
|
|
199
199
|
assert.match(report, /## Candidates/);
|
|
200
200
|
assert.match(report, /## Trust Audit/);
|
|
201
201
|
assert.match(report, /## Acceptance Rationale/);
|
package/scripts/parity-check.js
CHANGED
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
// FAIL CLOSED ON DRIFT (BSD discipline, same shape as gen-manifests --check):
|
|
10
10
|
// 1. STATIC parity — the declared capability registry must exactly match the
|
|
11
11
|
// live MCP tool list (tools/list) and the CLI dispatch tokens parsed from
|
|
12
|
-
//
|
|
13
|
-
// declared in src/capability-registry.ts, is release-blocking.
|
|
12
|
+
// the built CLI dispatch surface. A tool or command on one surface but not
|
|
13
|
+
// the other, or not declared in src/capability-registry.ts, is release-blocking.
|
|
14
14
|
// 2. PAYLOAD parity — for every capability declared `payloadIdentical`, the
|
|
15
15
|
// `cw <cmd> --json` payload must equal the `cw_<tool>` MCP result on a real
|
|
16
16
|
// bootstrap run (whitespace + generation-moment ISO timestamps aside).
|
|
@@ -31,50 +31,16 @@ const cli = path.join(pluginRoot, "dist", "cli.js");
|
|
|
31
31
|
const mcpServer = path.join(pluginRoot, "dist", "mcp-server.js");
|
|
32
32
|
const registry = require(path.join(pluginRoot, "dist", "capability-registry.js"));
|
|
33
33
|
|
|
34
|
-
// Read capabilities that are safe to probe on a freshly planned run with only a
|
|
35
|
-
// runId (or no args). Each: [capability, cliArgvAfterRunId, mcpTool].
|
|
36
|
-
// runId-less reads use [] for cli args and {} mcp args.
|
|
37
|
-
const RUN_PROBES = [
|
|
38
|
-
["status", ["--json"], "cw_status"],
|
|
39
|
-
["operator.status", ["--json"], "cw_operator_status"],
|
|
40
|
-
["operator.report", ["--json"], "cw_operator_report"],
|
|
41
|
-
["graph", ["--json"], "cw_operator_graph"],
|
|
42
|
-
["report", ["--json"], "cw_report"],
|
|
43
|
-
["next", [], "cw_next"],
|
|
44
|
-
["state.check", [], "cw_state_check"],
|
|
45
|
-
["contract.show", [], "cw_contract_show"],
|
|
46
|
-
["node.list", [], "cw_node_list"],
|
|
47
|
-
["node.graph", ["--json"], "cw_node_graph"],
|
|
48
|
-
["worker.summary", ["--json"], "cw_worker_summary"],
|
|
49
|
-
["candidate.summary", ["--json"], "cw_candidate_summary"],
|
|
50
|
-
["feedback.summary", ["--json"], "cw_feedback_summary"],
|
|
51
|
-
["commit.summary", ["--json"], "cw_commit_summary"],
|
|
52
|
-
["audit.summary", [], "cw_audit_summary"],
|
|
53
|
-
["multi-agent.summary", ["--json"], "cw_multi_agent_summary"],
|
|
54
|
-
["workbench.view", ["--json"], "cw_workbench_view"],
|
|
55
|
-
["metrics.show", ["--json"], "cw_metrics_show"],
|
|
56
|
-
["review.status", ["--json"], "cw_review_status"],
|
|
57
|
-
["comment.list", ["--json"], "cw_comment_list"],
|
|
58
|
-
["run.drive", ["--json"], "cw_run_drive"],
|
|
59
|
-
["gc.plan", ["--json"], "cw_gc_plan"],
|
|
60
|
-
["gc.verify", ["--json"], "cw_gc_verify"]
|
|
61
|
-
];
|
|
62
|
-
const GLOBAL_PROBES = [
|
|
63
|
-
["list", "cw_list"],
|
|
64
|
-
["app.list", "cw_app_list"],
|
|
65
|
-
["topology.list", "cw_topology_list"],
|
|
66
|
-
["sandbox.list", "cw_sandbox_list"],
|
|
67
|
-
["backend.list", "cw_backend_list"],
|
|
68
|
-
["backend.agent.config.show", "cw_backend_agent_config_show"],
|
|
69
|
-
["metrics.summary", "cw_metrics_summary"]
|
|
70
|
-
];
|
|
71
|
-
|
|
72
34
|
function capById(id) {
|
|
73
35
|
const cap = registry.CAPABILITY_REGISTRY.find((entry) => entry.capability === id);
|
|
74
36
|
assert.ok(cap, `probe references unknown capability ${id}`);
|
|
75
37
|
return cap;
|
|
76
38
|
}
|
|
77
39
|
|
|
40
|
+
function jsonFlag(cap) {
|
|
41
|
+
return cap.cli.jsonMode === "flag" ? ["--json"] : [];
|
|
42
|
+
}
|
|
43
|
+
|
|
78
44
|
// ---- 1. static surface parity ---------------------------------------------
|
|
79
45
|
function liveMcpTools() {
|
|
80
46
|
const result = execFileSync(node, [mcpServer], {
|
|
@@ -91,10 +57,14 @@ function liveMcpTools() {
|
|
|
91
57
|
}
|
|
92
58
|
|
|
93
59
|
function cliDispatchTokens() {
|
|
94
|
-
const source = fs.readFileSync(
|
|
60
|
+
const source = cliDispatchSources().map((file) => fs.readFileSync(file, "utf8")).join("\n");
|
|
95
61
|
return [...new Set([...source.matchAll(/case\s+"([^"]+)":/g)].map((match) => match[1]))];
|
|
96
62
|
}
|
|
97
63
|
|
|
64
|
+
function cliDispatchSources() {
|
|
65
|
+
return [cli, path.join(pluginRoot, "dist", "cli", "command-surface.js")].filter((file) => fs.existsSync(file));
|
|
66
|
+
}
|
|
67
|
+
|
|
98
68
|
// ---- 2. payload identity ---------------------------------------------------
|
|
99
69
|
// Generation-moment ISO timestamps are presentation metadata, not capability
|
|
100
70
|
// data: the same field carries the wall-clock instant of the render. Neutralize
|
|
@@ -144,31 +114,28 @@ async function payloadParity() {
|
|
|
144
114
|
const runId = plan.runId;
|
|
145
115
|
const mismatches = [];
|
|
146
116
|
const checked = [];
|
|
117
|
+
const probePlan = registry.payloadProbePlan();
|
|
118
|
+
assert.deepEqual(probePlan.unclassified, [], "payload probe classification has unclassified capabilities");
|
|
119
|
+
assert.deepEqual(probePlan.duplicateClassifications, [], "payload probe classification has duplicates");
|
|
120
|
+
assert.deepEqual(probePlan.invalidClassifications, [], "payload probe classification names non-payload capabilities");
|
|
147
121
|
const mcp = openMcp();
|
|
148
122
|
try {
|
|
149
123
|
await mcp.rpc("initialize", {});
|
|
150
|
-
for (const
|
|
151
|
-
const cap = capById(capability);
|
|
152
|
-
assert.equal(cap.mcp.tool, mcpTool, `probe/registry MCP tool mismatch for ${capability}`);
|
|
124
|
+
for (const target of registry.payloadProbeTargets()) {
|
|
125
|
+
const cap = capById(target.capability);
|
|
153
126
|
// jsonMode is the single source for the CLI's --json policy; this probe only
|
|
154
127
|
// appends --json for "flag" verbs and JSON.parse-es the result. The human
|
|
155
128
|
// rendering and "default"-verb no-flag JSON are pinned to cap.cli.jsonMode by
|
|
156
129
|
// the companion test/cli-jsonmode-parity-smoke.js, so cli.ts can't silently
|
|
157
130
|
// re-encode that policy by hand and drift from this registry data.
|
|
158
|
-
const cliArgv =
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
checked.push(capability);
|
|
162
|
-
if (canonical(cliOut) !== canonical(mcpOut)) mismatches.push(capability);
|
|
163
|
-
}
|
|
164
|
-
for (const [capability, extraArgv, mcpTool] of RUN_PROBES) {
|
|
165
|
-
const cap = capById(capability);
|
|
166
|
-
assert.equal(cap.mcp.tool, mcpTool, `probe/registry MCP tool mismatch for ${capability}`);
|
|
167
|
-
const cliArgv = [...cap.cli.path, runId, ...extraArgv];
|
|
131
|
+
const cliArgv = target.kind === "run"
|
|
132
|
+
? [...cap.cli.path, runId, ...jsonFlag(cap)]
|
|
133
|
+
: [...cap.cli.path, ...jsonFlag(cap)];
|
|
168
134
|
const cliOut = JSON.parse(execFileSync(node, [cli, ...cliArgv], { cwd: workspace, encoding: "utf8" }));
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
|
|
135
|
+
const mcpArgs = target.kind === "run" ? { cwd: workspace, runId } : { cwd: workspace };
|
|
136
|
+
const mcpOut = await mcp.tool(cap.mcp.tool, mcpArgs);
|
|
137
|
+
checked.push(target.capability);
|
|
138
|
+
if (canonical(cliOut) !== canonical(mcpOut)) mismatches.push(target.capability);
|
|
172
139
|
}
|
|
173
140
|
} finally {
|
|
174
141
|
mcp.server.kill();
|
|
@@ -204,6 +171,9 @@ async function main() {
|
|
|
204
171
|
if (report.missingCliTokens.length) lines.push(` - registry declares CLI tokens absent from dist/cli.js: ${report.missingCliTokens.join(", ")}`);
|
|
205
172
|
if (report.undeclaredCliTokens.length) lines.push(` - dist/cli.js dispatches tokens not declared in the registry: ${report.undeclaredCliTokens.join(", ")}`);
|
|
206
173
|
if (report.reasonlessExceptions.length) lines.push(` - surface-specific / payload-divergent capabilities missing a recorded reason: ${report.reasonlessExceptions.join(", ")}`);
|
|
174
|
+
if (report.payloadProbeUnclassified.length) lines.push(` - payload-identical capabilities neither probed nor deferred: ${report.payloadProbeUnclassified.join(", ")}`);
|
|
175
|
+
if (report.payloadProbeDuplicateClassifications.length) lines.push(` - payload probe duplicate classifications: ${report.payloadProbeDuplicateClassifications.join(", ")}`);
|
|
176
|
+
if (report.payloadProbeInvalidClassifications.length) lines.push(` - payload probe classifications for invalid capabilities: ${report.payloadProbeInvalidClassifications.join(", ")}`);
|
|
207
177
|
if (report.registryLint.length) lines.push(` - registry lint: ${report.registryLint.join("; ")}`);
|
|
208
178
|
if (payload.mismatches.length) lines.push(` - cw --json != cw_<tool> payload for: ${payload.mismatches.join(", ")}`);
|
|
209
179
|
lines.push("Reconcile src/capability-registry.ts, cli.ts, and mcp-server.ts so both surfaces render one data source.\n");
|