cool-workflow 0.1.95 → 0.1.97

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 (89) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codex-plugin/plugin.json +1 -1
  3. package/apps/architecture-review/app.json +1 -1
  4. package/apps/architecture-review/workflow.js +3 -3
  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/agent-config.js +2 -1
  11. package/dist/candidate-scoring.js +3 -3
  12. package/dist/capability-core.js +6 -1
  13. package/dist/cli/handlers/scheduling.js +7 -1
  14. package/dist/dispatch.js +12 -6
  15. package/dist/drive.js +10 -0
  16. package/dist/evidence-grounding.js +18 -13
  17. package/dist/execution-backend/agent.js +1 -1
  18. package/dist/execution-backend/probes.js +22 -6
  19. package/dist/execution-backend.js +61 -8
  20. package/dist/mcp-server.js +4 -0
  21. package/dist/node-snapshot.js +3 -3
  22. package/dist/onramp.js +2 -0
  23. package/dist/orchestrator/app-operations.js +6 -0
  24. package/dist/orchestrator/cli-options.js +8 -2
  25. package/dist/orchestrator/lifecycle-operations.js +16 -5
  26. package/dist/orchestrator/migration-operations.js +1 -1
  27. package/dist/orchestrator.js +26 -1
  28. package/dist/reclamation.js +8 -2
  29. package/dist/run-export.js +10 -1
  30. package/dist/run-registry/derive.js +4 -1
  31. package/dist/sandbox-profile.js +6 -1
  32. package/dist/scheduler.js +14 -14
  33. package/dist/schema-validate.js +8 -2
  34. package/dist/state-explosion/helpers.js +4 -21
  35. package/dist/state-explosion/size.js +63 -0
  36. package/dist/state-explosion.js +18 -71
  37. package/dist/state.js +47 -9
  38. package/dist/triggers.js +7 -1
  39. package/dist/trust-audit.js +27 -2
  40. package/dist/util/fingerprint.js +19 -0
  41. package/dist/util/fingerprint.test.js +27 -0
  42. package/dist/version.js +1 -1
  43. package/dist/workbench-host.js +17 -0
  44. package/dist/workbench.js +19 -17
  45. package/dist/worker-isolation.js +25 -1
  46. package/docs/agent-delegation-drive.7.md +66 -1
  47. package/docs/cli-mcp-parity.7.md +4 -0
  48. package/docs/contract-migration-tooling.7.md +4 -0
  49. package/docs/control-plane-scheduling.7.md +4 -0
  50. package/docs/demo.7.md +80 -0
  51. package/docs/doctor.7.md +97 -0
  52. package/docs/durable-state-and-locking.7.md +4 -0
  53. package/docs/evidence-adoption-reasoning-chain.7.md +4 -0
  54. package/docs/execution-backends.7.md +4 -0
  55. package/docs/fix.7.md +44 -0
  56. package/docs/init.7.md +62 -0
  57. package/docs/multi-agent-cli-mcp-surface.7.md +4 -0
  58. package/docs/multi-agent-eval-replay-harness.7.md +4 -0
  59. package/docs/multi-agent-operator-ux.7.md +4 -0
  60. package/docs/node-snapshot-diff-replay.7.md +4 -0
  61. package/docs/observability-cost-accounting.7.md +4 -0
  62. package/docs/pipeline-verbs.7.md +93 -0
  63. package/docs/project-index.md +20 -4
  64. package/docs/real-execution-backends.7.md +4 -0
  65. package/docs/release-and-migration.7.md +4 -0
  66. package/docs/release-tooling.7.md +20 -0
  67. package/docs/routine.7.md +73 -0
  68. package/docs/routines.md +30 -0
  69. package/docs/run-registry-control-plane.7.md +4 -0
  70. package/docs/run-retention-reclamation.7.md +4 -0
  71. package/docs/sandbox-profiles.7.md +15 -0
  72. package/docs/state-explosion-management.7.md +4 -0
  73. package/docs/team-collaboration.7.md +4 -0
  74. package/docs/web-desktop-workbench.7.md +4 -0
  75. package/manifest/README.md +16 -10
  76. package/manifest/plugin.manifest.json +1 -1
  77. package/package.json +5 -3
  78. package/scripts/agents/agent-adapter-core.js +25 -1
  79. package/scripts/agents/claude-p-agent.js +10 -2
  80. package/scripts/agents/codex-agent.js +22 -2
  81. package/scripts/agents/gemini-agent.js +10 -2
  82. package/scripts/agents/opencode-agent.js +10 -2
  83. package/scripts/canonical-apps.js +4 -4
  84. package/scripts/children/batch-delegate-child.js +10 -3
  85. package/scripts/children/http-delegate-child.js +2 -1
  86. package/scripts/dogfood-release.js +1 -1
  87. package/scripts/golden-path.js +4 -4
  88. package/scripts/release-flow.js +24 -6
  89. package/scripts/release-gate.sh +1 -1
@@ -355,3 +355,7 @@ _No behavioral change in v0.1.89 (CLI-surface golden-path + help-output fixes on
355
355
  0.1.94
356
356
 
357
357
  0.1.95
358
+
359
+ 0.1.96
360
+
361
+ 0.1.97
@@ -176,3 +176,7 @@ _No behavioral change in v0.1.89 (CLI-surface golden-path + help-output fixes on
176
176
  0.1.94
177
177
 
178
178
  0.1.95
179
+
180
+ 0.1.96
181
+
182
+ 0.1.97
@@ -235,3 +235,7 @@ _No behavioral change in v0.1.89 (CLI-surface golden-path + help-output fixes on
235
235
  0.1.94
236
236
 
237
237
  0.1.95
238
+
239
+ 0.1.96
240
+
241
+ 0.1.97
@@ -0,0 +1,93 @@
1
+ # PIPELINE-VERBS(7)
2
+
3
+ ## NAME
4
+
5
+ `cw plan`, `cw dispatch`, `cw result` — the three core pipeline engine verbs
6
+
7
+ ## SYNOPSIS
8
+
9
+ ```text
10
+ node dist/cli.js plan <workflow-id> [--question Q] [--repo PATH] [--sandbox PROFILE]
11
+ node dist/cli.js dispatch <run-id> [--sandbox PROFILE]
12
+ node dist/cli.js result <run-id> <task-id> <result-file>
13
+ ```
14
+
15
+ ## DESCRIPTION
16
+
17
+ These three verbs are the engine that drives every CW run. A run goes through
18
+ three stages: plan (get ready), dispatch (hand out work), and result (take work
19
+ back). Together they make the CW pipeline loop — a worker gets a task, does it,
20
+ and hands in a result file; CW checks the result and moves the run forward.
21
+
22
+ None of these verbs starts or stops the agent host. They give the control-plane
23
+ data that the host reads and acts on. The host keeps its own loop: call
24
+ `dispatch`, give the task to an agent, get back a result file, call `result`.
25
+
26
+ ## PLAN
27
+
28
+ `cw plan <workflow-id>` makes a new run and gives back its canonical plan
29
+ summary in JSON. The plan has the run id, the first task (or tasks) to do,
30
+ the sandbox profile, and the state of the run.
31
+
32
+ The workflow id names a workflow app that gives the run its shape: inputs,
33
+ steps, evidence gates, and sandbox policy. Use `cw list` to see the workflow
34
+ apps you have.
35
+
36
+ The plan output is stable JSON, good for scripts and the agent host.
37
+
38
+ Options:
39
+ : `--question`, `--repo`, `--sandbox` — the same inputs the workflow app
40
+ expects. Different apps take different inputs; see `cw info <workflow-id>`
41
+ for the list.
42
+
43
+ ## DISPATCH
44
+
45
+ `cw dispatch <run-id>` makes the next task ready for a worker. It gives back
46
+ a dispatch manifest in JSON: the task id, the prompt, the sandbox profile, and
47
+ the input and output paths the worker should use.
48
+
49
+ The dispatch picks the next runnable task in the pipeline. If no task is ready
50
+ — for example, all tasks are done or waiting on evidence — the dispatch payload
51
+ says so, and the host should wait or check the run status.
52
+
53
+ Options:
54
+ : `--sandbox PROFILE` — pick a sandbox profile for the worker. The default is
55
+ the one the workflow app asked for.
56
+
57
+ ## RESULT
58
+
59
+ `cw result <run-id> <task-id> <result-file>` records a worker's result against
60
+ a task. The result file is a Markdown file the agent wrote — it must have a
61
+ `cw:result` JSON fence with the agent's `findings` and `evidence`.
62
+
63
+ CW accepts the result, checks it, and advances the run pipeline. If the result
64
+ is bad (missing, broken, or the evidence does not check out), CW rejects it and
65
+ gives back an error feedback record. The host can then try again or give the
66
+ task a different agent.
67
+
68
+ After `result`, the run may be done or have more tasks waiting. Check with
69
+ `cw status <run-id>` or `cw next <run-id>`.
70
+
71
+ ## FILES
72
+
73
+ ```text
74
+ .cw/runs/<run-id>/state.json
75
+ .cw/runs/<run-id>/dispatches/<dispatch-id>.json
76
+ .cw/runs/<run-id>/tasks/<task-id>.json
77
+ .cw/runs/<run-id>/results/<task-id>.md
78
+ .cw/runs/<run-id>/workers/<worker-id>/worker.json
79
+ ```
80
+
81
+ ## PIPELINE FLOW
82
+
83
+ ```text
84
+ plan -> dispatch -> [agent does work] -> result -> [dispatch...] -> done
85
+ └─ rejected -> feedback -> retry
86
+ ```
87
+
88
+ ## SEE ALSO
89
+
90
+ cw init — make a new workflow definition from nothing
91
+ cw status — see the current state of a run
92
+ cw next — find the next action for a run
93
+ pipeline-runner.7.md — the full pipeline engine detail
@@ -1,15 +1,15 @@
1
1
  # Cool Workflow Project Index
2
2
 
3
- Generated from the current repository code on 2026-06-27 by `npm run sync:project-index`.
3
+ Generated from the current repository code on 2026-06-30 by `npm run sync:project-index`.
4
4
 
5
5
  ## Snapshot
6
6
 
7
7
  - Package: `cool-workflow`
8
- - Version: `0.1.95`
8
+ - Version: `0.1.97`
9
9
  - Source modules: `68`
10
10
  - Workflow apps: `8`
11
- - Docs: `53`
12
- - Smoke tests: `154`
11
+ - Docs: `59`
12
+ - Smoke tests: `164`
13
13
  - Repository: https://github.com/coo1white/cool-workflow
14
14
 
15
15
  ## Architecture
@@ -145,14 +145,18 @@ multi-agent host -> topology -> blackboard/coordinator
145
145
  - [Contract Migration Tooling](contract-migration-tooling.7.md)
146
146
  - [Control-Plane Scheduling](control-plane-scheduling.7.md)
147
147
  - [Coordinator / Blackboard](coordinator-blackboard.7.md)
148
+ - [DEMO(7)](demo.7.md)
149
+ - [DOCTOR(7)](doctor.7.md)
148
150
  - [Dogfood One Real Repo](dogfood-one-real-repo.7.md)
149
151
  - [Durable State & Locking](durable-state-and-locking.7.md)
150
152
  - [End-to-End Golden Path](end-to-end-golden-path.7.md)
151
153
  - [ERROR-FEEDBACK(7)](error-feedback.7.md)
152
154
  - [Evidence Adoption Reasoning Chain](evidence-adoption-reasoning-chain.7.md)
153
155
  - [EXECUTION-BACKENDS(7)](execution-backends.7.md)
156
+ - [FIX(7)](fix.7.md)
154
157
  - [Getting Started](getting-started.md)
155
158
  - [Cool Workflow Docs](index.md)
159
+ - [INIT(7)](init.7.md)
156
160
  - [MCP App Surface](mcp-app-surface.7.md)
157
161
  - [Multi-Agent CLI + MCP Surface](multi-agent-cli-mcp-surface.7.md)
158
162
  - [Multi-Agent Eval & Replay Harness](multi-agent-eval-replay-harness.7.md)
@@ -164,6 +168,7 @@ multi-agent host -> topology -> blackboard/coordinator
164
168
  - [Observability + Cost Accounting](observability-cost-accounting.7.md)
165
169
  - [Operator UX](operator-ux.7.md)
166
170
  - [PIPELINE-RUNNER(7)](pipeline-runner.7.md)
171
+ - [PIPELINE-VERBS(7)](pipeline-verbs.7.md)
167
172
  - [Cool Workflow Project Index](project-index.md)
168
173
  - [Cool Workflow](readme-v0.1.87-full.md)
169
174
  - [Real Execution Backend Integrations](real-execution-backends.7.md)
@@ -172,6 +177,7 @@ multi-agent host -> topology -> blackboard/coordinator
172
177
  - [Release Tooling](release-tooling.7.md)
173
178
  - [Remote-Source Review (`--link`)](remote-source-review.7.md)
174
179
  - [Verifiable Report Bundle](report-verifiable-bundle.7.md)
180
+ - [ROUTINE(7)](routine.7.md)
175
181
  - [Routines](routines.md)
176
182
  - [Run Registry / Control Plane](run-registry-control-plane.7.md)
177
183
  - [Run Retention & Provable Reclamation](run-retention-reclamation.7.md)
@@ -194,7 +200,9 @@ multi-agent host -> topology -> blackboard/coordinator
194
200
 
195
201
  Smoke tests mirror the public contracts. The high-signal suites are:
196
202
 
203
+ - [agent-config-atomic-write-smoke.js](../test/agent-config-atomic-write-smoke.js)
197
204
  - [agent-delegation-drive-smoke.js](../test/agent-delegation-drive-smoke.js)
205
+ - [agent-stream-gate-smoke.js](../test/agent-stream-gate-smoke.js)
198
206
  - [append-run-node-no-realloc-smoke.js](../test/append-run-node-no-realloc-smoke.js)
199
207
  - [architecture-review-fast-automation-smoke.js](../test/architecture-review-fast-automation-smoke.js)
200
208
  - [architecture-review-fast-phase-cache-smoke.js](../test/architecture-review-fast-phase-cache-smoke.js)
@@ -224,6 +232,7 @@ Smoke tests mirror the public contracts. The high-signal suites are:
224
232
  - [cli-render-smoke.js](../test/cli-render-smoke.js)
225
233
  - [clones-gc-smoke.js](../test/clones-gc-smoke.js)
226
234
  - [codex-agent-wrapper-smoke.js](../test/codex-agent-wrapper-smoke.js)
235
+ - [collaboration-ops-unit-smoke.js](../test/collaboration-ops-unit-smoke.js)
227
236
  - [concurrency-default-smoke.js](../test/concurrency-default-smoke.js)
228
237
  - [concurrent-failure-semantics-smoke.js](../test/concurrent-failure-semantics-smoke.js)
229
238
  - [concurrent-workflow-dsl-smoke.js](../test/concurrent-workflow-dsl-smoke.js)
@@ -248,6 +257,7 @@ Smoke tests mirror the public contracts. The high-signal suites are:
248
257
  - [execution-backend-agent-smoke.js](../test/execution-backend-agent-smoke.js)
249
258
  - [execution-backend-ci-smoke.js](../test/execution-backend-ci-smoke.js)
250
259
  - [execution-backends-smoke.js](../test/execution-backends-smoke.js)
260
+ - [feedback-ops-unit-smoke.js](../test/feedback-ops-unit-smoke.js)
251
261
  - [freebsd-audit-fixes-smoke.js](../test/freebsd-audit-fixes-smoke.js)
252
262
  - [gemini-agent-wrapper-smoke.js](../test/gemini-agent-wrapper-smoke.js)
253
263
  - [gemini-opencode-agent-wrapper-smoke.js](../test/gemini-opencode-agent-wrapper-smoke.js)
@@ -257,6 +267,7 @@ Smoke tests mirror the public contracts. The high-signal suites are:
257
267
  - [loop-bounded-expansion-smoke.js](../test/loop-bounded-expansion-smoke.js)
258
268
  - [mcp-app-surface-smoke.js](../test/mcp-app-surface-smoke.js)
259
269
  - [mcp-surface-registry-smoke.js](../test/mcp-surface-registry-smoke.js)
270
+ - [mcp-tool-call-coverage-smoke.js](../test/mcp-tool-call-coverage-smoke.js)
260
271
  - [multi-agent-cli-mcp-surface-smoke.js](../test/multi-agent-cli-mcp-surface-smoke.js)
261
272
  - [multi-agent-eval-determinism-regression-smoke.js](../test/multi-agent-eval-determinism-regression-smoke.js)
262
273
  - [multi-agent-eval-replay-harness-smoke.js](../test/multi-agent-eval-replay-harness-smoke.js)
@@ -278,6 +289,9 @@ Smoke tests mirror the public contracts. The high-signal suites are:
278
289
  - [operator-ux-smoke.js](../test/operator-ux-smoke.js)
279
290
  - [parallel-onramp-smoke.js](../test/parallel-onramp-smoke.js)
280
291
  - [parity-doc-sync-smoke.js](../test/parity-doc-sync-smoke.js)
292
+ - [parse-guard-smoke.js](../test/parse-guard-smoke.js)
293
+ - [parse-hardening-round2-smoke.js](../test/parse-hardening-round2-smoke.js)
294
+ - [path-containment-smoke.js](../test/path-containment-smoke.js)
281
295
  - [pdca-blackboard-loop-smoke.js](../test/pdca-blackboard-loop-smoke.js)
282
296
  - [pii-redaction-smoke.js](../test/pii-redaction-smoke.js)
283
297
  - [pipeline-auto-advance-smoke.js](../test/pipeline-auto-advance-smoke.js)
@@ -296,6 +310,7 @@ Smoke tests mirror the public contracts. The high-signal suites are:
296
310
  - [release-check-skip-smoke.js](../test/release-check-skip-smoke.js)
297
311
  - [release-flow-smoke.js](../test/release-flow-smoke.js)
298
312
  - [release-gate-smoke.js](../test/release-gate-smoke.js)
313
+ - [release-pipeline-hygiene-smoke.js](../test/release-pipeline-hygiene-smoke.js)
299
314
  - [release-tooling-smoke.js](../test/release-tooling-smoke.js)
300
315
  - [remote-link-archive-smoke.js](../test/remote-link-archive-smoke.js)
301
316
  - [remote-link-git-smoke.js](../test/remote-link-git-smoke.js)
@@ -319,6 +334,7 @@ Smoke tests mirror the public contracts. The high-signal suites are:
319
334
  - [run-resume-drive-smoke.js](../test/run-resume-drive-smoke.js)
320
335
  - [run-retention-reclamation-smoke.js](../test/run-retention-reclamation-smoke.js)
321
336
  - [sample-determinism-smoke.js](../test/sample-determinism-smoke.js)
337
+ - [sandbox-env-batch-hardening-smoke.js](../test/sandbox-env-batch-hardening-smoke.js)
322
338
  - [sandbox-profile-smoke.js](../test/sandbox-profile-smoke.js)
323
339
  - [sched-policy-validation-smoke.js](../test/sched-policy-validation-smoke.js)
324
340
  - [schedule-routine-daemon-smoke.js](../test/schedule-routine-daemon-smoke.js)
@@ -183,3 +183,7 @@ _No behavioral change in v0.1.89 (CLI-surface golden-path + help-output fixes on
183
183
  0.1.94
184
184
 
185
185
  0.1.95
186
+
187
+ 0.1.96
188
+
189
+ 0.1.97
@@ -323,3 +323,7 @@ _No behavioral change in v0.1.89 (CLI-surface golden-path + help-output fixes on
323
323
  0.1.94
324
324
 
325
325
  0.1.95
326
+
327
+ 0.1.96
328
+
329
+ 0.1.97
@@ -85,6 +85,22 @@ The dogfood release smoke and the architecture-review dogfood smoke are separate
85
85
  test files. The split keeps the same release and agent-drive proof, but lets
86
86
  `test:ci` schedule the two long checks in parallel.
87
87
 
88
+ ## PR CI Merge Notes
89
+
90
+ When a PR is ready, list open PRs by creation time and merge the oldest ready
91
+ one first. After each merge, check the next PR again; a new main commit may make
92
+ it need a rebase.
93
+
94
+ If main moved after the PR branch was made, replay the PR commits on top of the
95
+ new main in a clean worktree. Keep local unrelated changes out of the rebase and
96
+ out of the PR.
97
+
98
+ Treat CI as the source of truth for what blocks the merge. Read the failed step
99
+ first, fix only that drift, then push again. A common drift is the npm README:
100
+ when `readme-sync-smoke.js` says the package README is stale, run
101
+ `npm run sync:readme`, add only `plugins/cool-workflow/README.md`, and let CI run
102
+ again.
103
+
88
104
  ## Boundary
89
105
 
90
106
  Release Tooling touches only the build/release surfaces. It adds no runtime
@@ -270,3 +286,7 @@ _No behavioral change in v0.1.89 (CLI-surface golden-path + help-output fixes on
270
286
  0.1.94
271
287
 
272
288
  0.1.95
289
+
290
+ 0.1.96
291
+
292
+ 0.1.97
@@ -0,0 +1,73 @@
1
+ # ROUTINE(7)
2
+
3
+ ## NAME
4
+
5
+ `cw routine` — make and manage trigger-based workflow routines
6
+
7
+ ## SYNOPSIS
8
+
9
+ ```text
10
+ node dist/cli.js routine create --kind api|github --prompt PROMPT [--match JSON]
11
+ node dist/cli.js routine list [--kind KIND]
12
+ node dist/cli.js routine delete <trigger-id>
13
+ node dist/cli.js routine fire <kind> <payload-file>
14
+ node dist/cli.js routine events [<trigger-id>]
15
+ ```
16
+
17
+ ## DESCRIPTION
18
+
19
+ `cw routine` is the local trigger bridge for CW. It lets you make named
20
+ triggers that fire when something happens — an API event, a GitHub webhook, or
21
+ another outside signal. Each trigger carries a prompt template; when fired,
22
+ the prompt gets filled with the event data and handed to an agent host.
23
+
24
+ CW keeps routine data in:
25
+
26
+ ```text
27
+ .cw/routines/triggers.json
28
+ .cw/routines/payloads/
29
+ ```
30
+
31
+ CW itself does not run a web server or listen for webhooks. The routine bridge
32
+ is a local data store that can be joined to GitHub Actions, webhooks, cron, or
33
+ a small HTTP adapter.
34
+
35
+ ## COMMANDS
36
+
37
+ **create**
38
+ : Make a new trigger. `--kind` is `api` or `github`. `--prompt` is the prompt
39
+ template the agent will see. `--match` is an optional JSON object that filters
40
+ events (for example, `{"action":"opened"}` for GitHub pull requests).
41
+
42
+ **list**
43
+ : List all triggers, or filter by kind with `--kind`.
44
+
45
+ **delete**
46
+ : Remove a trigger by its id.
47
+
48
+ **fire**
49
+ : Record an event against a trigger. Give the trigger kind and a path to a
50
+ JSON payload file. CW matches the payload against the trigger's match rules
51
+ and fills out the prompt.
52
+
53
+ **events**
54
+ : List the events that have been recorded for a trigger.
55
+
56
+ ## FILES
57
+
58
+ ```text
59
+ .cw/routines/triggers.json
60
+ .cw/routines/payloads/<event-id>.json
61
+ ```
62
+
63
+ ## EXIT CODES
64
+
65
+ | Exit | Meaning |
66
+ | --- | --- |
67
+ | 0 | Command done |
68
+ | 1 | Error (bad arguments, missing trigger, etc.) |
69
+
70
+ ## SEE ALSO
71
+
72
+ cw sched — durable run-queue scheduling for workflow runs
73
+ control-plane-scheduling.7.md — the full scheduling and run management design
package/docs/routines.md CHANGED
@@ -64,6 +64,36 @@ report path and digest.
64
64
  The `--metrics` flag is not required and it gives back foreground time used plus
65
65
  agent-spawn and result-cache-hit counts for the fast run.
66
66
 
67
+ ## PDCA Blackboard Development Lessons
68
+
69
+ When a task asks for agents to work together, first try the parts CW already
70
+ has:
71
+
72
+ - workflow apps give the work shape
73
+ - worker output gives checked facts
74
+ - the blackboard gives shared state
75
+ - MCP gives tool access to the same state
76
+ - smoke tests prove the loop
77
+
78
+ Do not make a new MCP server when the existing server can show the same run
79
+ state. Add a workflow app first, then prove the app with one smoke that uses
80
+ both CLI and MCP.
81
+
82
+ For a three-agent loop, keep the order plain:
83
+
84
+ ```text
85
+ plan -> build -> audit -> next action
86
+ ```
87
+
88
+ Each agent should write one blackboard message and, when there is a result
89
+ file, one artifact ref. Take a snapshot after the audit and after the next
90
+ action. If audit evidence is missing, let the worker evidence gate refuse the
91
+ result instead of adding a new policy layer.
92
+
93
+ Before a PR, base the branch on `origin/main`, run the generated-doc checks,
94
+ and sync generated docs when the gate says they are stale. This keeps unrelated
95
+ local commits and generated README/index drift out of the work.
96
+
67
97
  ## Boundary
68
98
 
69
99
  CW v0.1.1 does not give managed cloud infrastructure. It gives a local
@@ -466,3 +466,7 @@ _No behavioral change in v0.1.89 (CLI-surface golden-path + help-output fixes on
466
466
  0.1.94
467
467
 
468
468
  0.1.95
469
+
470
+ 0.1.96
471
+
472
+ 0.1.97
@@ -234,3 +234,7 @@ _No behavioral change in v0.1.89 (CLI-surface golden-path + help-output fixes on
234
234
  0.1.94
235
235
 
236
236
  0.1.95
237
+
238
+ 0.1.96
239
+
240
+ 0.1.97
@@ -26,6 +26,21 @@ normalization, worker result acceptance, and durable feedback for denied worker
26
26
  output. The agent host has to do OS-level file access, process execution,
27
27
  network access, and environment filtering.
28
28
 
29
+ **IMPORTANT**: Under the default `node` backend, a sandbox profile's
30
+ `execute`, `network`, and `env` policy is **attested, not enforced**. CW
31
+ validates the policy, records it in the worker manifest, and attests that
32
+ these limits were declared — but the actual enforcement of command execution
33
+ restrictions, network isolation, and environment variable filtering is
34
+ DELEGATED to the host runtime. For full enforcement, use the `container`
35
+ backend (`--backend container`) with Docker/Podman, or apply OS-level
36
+ sandboxing to the agent process. Without OS enforcement, a worker under a
37
+ `locked-down` profile can still run arbitrary commands and access the network.
38
+
39
+ CW also now (v0.1.95) applies `buildChildEnv(policy)` as a baseline for agent
40
+ spawns — only `PATH`, `HOME`, explicit `expose` entries, and well-known
41
+ `CW_*` + LLM provider API key environment variables pass through. The
42
+ operator's other process environment is not inherited by default.
43
+
29
44
  The design goal is simple:
30
45
 
31
46
  ```text
@@ -312,3 +312,7 @@ _No behavioral change in v0.1.89 (CLI-surface golden-path + help-output fixes on
312
312
  0.1.94
313
313
 
314
314
  0.1.95
315
+
316
+ 0.1.96
317
+
318
+ 0.1.97
@@ -248,3 +248,7 @@ _No behavioral change in v0.1.89 (CLI-surface golden-path + help-output fixes on
248
248
  0.1.94
249
249
 
250
250
  0.1.95
251
+
252
+ 0.1.96
253
+
254
+ 0.1.97
@@ -256,3 +256,7 @@ _No behavioral change in v0.1.89 (CLI-surface golden-path + help-output fixes on
256
256
  0.1.94
257
257
 
258
258
  0.1.95
259
+
260
+ 0.1.96
261
+
262
+ 0.1.97
@@ -1,11 +1,12 @@
1
1
  # Vendor Manifest Source of Truth
2
2
 
3
3
  Every agent host scans a different, hard-coded manifest directory
4
- (`.claude-plugin/`, `.codex-plugin/`, `.agents/`) with a different JSON shape.
5
- You cannot unify the directory or the schema so we do not try. Instead, all
6
- vendor manifests are **generated** from one neutral source and point at the same
7
- shared runtime (`skills/`, `dist/`, `apps/`, the MCP server). No vendor forks the
8
- logic; each manifest is a thin adapter.
4
+ (`.claude-plugin/`, `.codex-plugin/`, `.agents/`, `.gemini-plugin/`,
5
+ `.opencode-plugin/`) with a different JSON shape. You cannot unify the directory
6
+ or the schema so we do not try. Instead, all vendor manifests are **generated**
7
+ from one neutral source and point at the same shared runtime (`skills/`, `dist/`,
8
+ `apps/`, the MCP server). No vendor forks the logic; each manifest is a thin
9
+ adapter.
9
10
 
10
11
  This is the mechanism/policy split: shared assets are mechanism, per-vendor
11
12
  manifests are policy.
@@ -25,13 +26,18 @@ npm run gen:manifests -- --check # fail (exit 1) if any generated file drifted
25
26
 
26
27
  ## Generated outputs (do NOT hand-edit)
27
28
 
29
+ Five vendors are generated today. Paths are repo-root-relative.
30
+
28
31
  | Vendor | Marketplace | Plugin manifest | MCP config | MCP path var |
29
32
  | --- | --- | --- | --- | --- |
30
- | Claude Code | `../../../.claude-plugin/marketplace.json` | `../.claude-plugin/plugin.json` | `../.mcp.json` (auto-discovered) | `${CLAUDE_PLUGIN_ROOT}/` |
31
- | Codex / `.agents` | `../../../.agents/plugins/marketplace.json` | `../.codex-plugin/plugin.json` | `../.codex-plugin/mcp.json` | `./` |
32
-
33
- The two vendors read **different** MCP files, so the plugin-root path variable
34
- never collides.
33
+ | Claude Code | `.claude-plugin/marketplace.json` | `plugins/cool-workflow/.claude-plugin/plugin.json` | `plugins/cool-workflow/.mcp.json` (auto-discovered) | `${CLAUDE_PLUGIN_ROOT}/` |
34
+ | Codex | `.agents/plugins/marketplace.json` | `plugins/cool-workflow/.codex-plugin/plugin.json` | `plugins/cool-workflow/.codex-plugin/mcp.json` | `./` |
35
+ | `.agents` | — | `.agents/plugins/cool-workflow/plugin.json` | `.agents/plugins/cool-workflow/mcp.json` | `./` |
36
+ | Gemini | | `plugins/cool-workflow/.gemini-plugin/plugin.json` | `plugins/cool-workflow/.gemini-plugin/mcp.json` | `./` |
37
+ | OpenCode | — | `plugins/cool-workflow/.opencode-plugin/plugin.json` | `plugins/cool-workflow/.opencode-plugin/mcp.json` | `./` |
38
+
39
+ Each vendor reads its **own** MCP file, so the plugin-root path variable never
40
+ collides.
35
41
 
36
42
  ## Adding a new vendor (Cursor, Windsurf, …)
37
43
 
@@ -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.95",
5
+ "version": "0.1.97",
6
6
  "license": "BSD-2-Clause",
7
7
  "homepage": "https://github.com/coo1white/cool-workflow",
8
8
  "author": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cool-workflow",
3
- "version": "0.1.95",
3
+ "version": "0.1.97",
4
4
  "bin": {
5
5
  "cool-workflow": "scripts/cw.js",
6
6
  "cw": "scripts/cw.js"
@@ -62,9 +62,11 @@
62
62
  "onramp:check": "node scripts/onramp-check.js --check",
63
63
  "version:sync": "node scripts/version-sync-check.js",
64
64
  "release:check": "node scripts/release-check.js",
65
- "test": "node dist/cli.js version > /dev/null && node test/run-all.js",
65
+ "test": "node dist/cli.js version > /dev/null && node test/run-all.js --fast --sample 35",
66
+ "test:full": "node dist/cli.js version > /dev/null && node test/run-all.js --sample 55",
67
+ "test:gate": "node dist/cli.js version > /dev/null && node test/run-all.js",
66
68
  "test:fast": "npm run build --if-present && node dist/cli.js version > /dev/null && node test/run-all.js --concurrency auto",
67
- "test:ci": "node dist/cli.js version > /dev/null && node test/run-all.js --concurrency auto",
69
+ "test:ci": "npm run build && node dist/cli.js version > /dev/null && node test/run-all.js --sample 55",
68
70
  "test:coverage": "node dist/cli.js version > /dev/null && node scripts/coverage-gate.js --concurrency auto",
69
71
  "eval:replay": "tsc -p tsconfig.json && node test/multi-agent-eval-replay-harness-smoke.js",
70
72
  "ci": "npm run build && npm run check && npm run test && npm run release:check",
@@ -2,6 +2,7 @@
2
2
  "use strict";
3
3
 
4
4
  const fs = require("node:fs");
5
+ const path = require("node:path");
5
6
 
6
7
  const RESULT_CONTRACT = `
7
8
  === HOW TO RETURN YOUR ANSWER (overrides any 'write to result.md' instruction above) ===
@@ -448,6 +449,28 @@ function emitReport(model, usage, resultText) {
448
449
  process.stdout.write(JSON.stringify({ model, usage, result: resultText }));
449
450
  }
450
451
 
452
+ // Drop the failed agent's stderr beside the worker's result.md so a `failed (exit
453
+ // 1)` is readable AFTER the fact. CW core keeps only the child's stdout + exit
454
+ // code (byte-stable evidence), so without this the real reason — a relay 5xx, an
455
+ // auth error, a killed run — is lost. The worker dir already has a `logs/` folder
456
+ // (src/worker-isolation.ts); resultPath is `<workerDir>/result.md`, so its
457
+ // `logs/agent-stderr.log` sibling is the natural home. Advisory only: never throws,
458
+ // never changes the exit code or the recorded evidence.
459
+ function persistStderr(resultPath, text) {
460
+ let t = String(text || "").trim();
461
+ if (!t || !resultPath) return;
462
+ try {
463
+ t = String(t).replace(/\b(sk-[A-Za-z0-9_-]{20,}|ghp_[A-Za-z0-9]{20,}|xox[bprs]-[A-Za-z0-9-]{20,}|Bearer\s+\S+|Authorization:\s*\S+|api[_-]?key[=:]\s*\S+|token[=:]\s*\S+)/gi, (match) => match.slice(0, 4) + "***[REDACTED]");
464
+ const cap = 4096;
465
+ if (t.length > cap) t = t.slice(0, cap) + `\n [truncated from ${t.length} bytes]`;
466
+ const dir = path.join(path.dirname(resultPath), "logs");
467
+ fs.mkdirSync(dir, { recursive: true });
468
+ fs.writeFileSync(path.join(dir, "agent-stderr.log"), `${t}\n`, "utf8");
469
+ } catch {
470
+ /* advisory only — diagnostics must never break the run */
471
+ }
472
+ }
473
+
451
474
  module.exports = {
452
475
  RESULT_CONTRACT,
453
476
  buildPrompt,
@@ -461,5 +484,6 @@ module.exports = {
461
484
  parseJsonLines,
462
485
  flushJsonLines,
463
486
  writeResult,
464
- emitReport
487
+ emitReport,
488
+ persistStderr // save a failed agent's stderr to <workerDir>/logs/agent-stderr.log (shared by all wrappers)
465
489
  };
@@ -34,7 +34,7 @@ const { spawn, spawnSync } = require("node:child_process");
34
34
  // wrappers instead of carrying a private copy. A drifted inline copy (ASCII
35
35
  // hyphens silently became em-dashes here) meant claude was sent a different
36
36
  // instruction text than the other providers for the same contract.
37
- const { buildPrompt, createRenderer, toolLabel, summarizeToolResult } = require("./agent-adapter-core");
37
+ const { buildPrompt, createRenderer, persistStderr, toolLabel, summarizeToolResult } = require("./agent-adapter-core");
38
38
 
39
39
  const inputPath = process.argv[2];
40
40
  const resultPath = process.argv[3];
@@ -56,11 +56,14 @@ if (!streamEnabled) {
56
56
  shell: false
57
57
  });
58
58
  if (child.error) {
59
+ persistStderr(resultPath, `claude spawn failed: ${child.error.message}`);
59
60
  process.stderr.write(`claude spawn failed: ${child.error.message}\n`);
60
61
  process.exit(1);
61
62
  }
62
63
  if (child.status !== 0) {
63
- process.stderr.write(String(child.stderr || `claude exited ${child.status}`));
64
+ const detail = String(child.stderr || `claude exited ${child.status}`);
65
+ persistStderr(resultPath, detail);
66
+ process.stderr.write(detail);
64
67
  process.exit(child.status === null ? 1 : child.status);
65
68
  }
66
69
 
@@ -69,6 +72,7 @@ if (!streamEnabled) {
69
72
  try {
70
73
  parsed = JSON.parse(out);
71
74
  } catch (error) {
75
+ persistStderr(resultPath, `claude output was not JSON: ${error.message}`);
72
76
  process.stderr.write(`claude output was not JSON: ${error.message}\n`);
73
77
  process.exit(1);
74
78
  }
@@ -166,6 +170,7 @@ function renderEvent(ev) {
166
170
 
167
171
  child.on("error", (err) => {
168
172
  render.finishLive(); // restore the terminal before exiting
173
+ persistStderr(resultPath, `claude spawn failed: ${err.message}`);
169
174
  process.stderr.write(`claude spawn failed: ${err.message}\n`);
170
175
  process.exit(1);
171
176
  });
@@ -174,12 +179,15 @@ child.on("close", (code) => {
174
179
  render.finishLive(); // stop the spinner + restore the cursor BEFORE any further output
175
180
  render.writeTranscript(transcriptPath); // full narration + tool I/O always saved
176
181
  if (code !== 0) {
182
+ const detail = childStderr.trim() || `claude exited ${code === null ? "(timeout/killed)" : code}`;
183
+ persistStderr(resultPath, detail);
177
184
  if (childStderr.trim()) process.stderr.write(`${childStderr.trim()}\n`);
178
185
  process.stderr.write(`claude exited ${code === null ? "(timeout/killed)" : code}\n`);
179
186
  process.exit(code === null ? 1 : code);
180
187
  }
181
188
  if (typeof resultText !== "string") {
182
189
  // Fail closed: no result event ⇒ no result.md ⇒ CW records a failed hop.
190
+ persistStderr(resultPath, childStderr.trim() || "claude produced no result event — refusing to fabricate a result");
183
191
  process.stderr.write("claude produced no result event — refusing to fabricate a result\n");
184
192
  process.exit(1);
185
193
  }