cool-workflow 0.1.87 → 0.1.88
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 +107 -71
- 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/agent-config.js +42 -1
- package/dist/capability-core.js +9 -4
- package/dist/capability-registry.js +24 -0
- package/dist/cli/command-surface.js +102 -1
- package/dist/doctor.js +14 -1
- package/dist/drive.js +222 -16
- package/dist/execution-backend.js +4 -4
- package/dist/loop-expansion.js +60 -0
- package/dist/onramp.js +25 -0
- package/dist/orchestrator/lifecycle-operations.js +134 -3
- package/dist/orchestrator.js +24 -76
- package/dist/run-export.js +106 -2
- package/dist/state-node.js +13 -3
- package/dist/state.js +21 -0
- package/dist/telemetry-attestation.js +30 -6
- package/dist/telemetry-demo.js +29 -1
- package/dist/telemetry-ledger.js +6 -0
- package/dist/version.js +1 -1
- package/dist/worker-accept/telemetry-ledger.js +12 -2
- package/dist/workflow-api.js +33 -0
- package/dist/workflow-app-framework.js +20 -0
- package/docs/agent-delegation-drive.7.md +4 -0
- package/docs/capability-topology-registry.7.md +69 -46
- package/docs/cli-mcp-parity.7.md +12 -2
- package/docs/contract-migration-tooling.7.md +4 -0
- package/docs/control-plane-scheduling.7.md +4 -0
- package/docs/durable-state-and-locking.7.md +4 -0
- package/docs/evidence-adoption-reasoning-chain.7.md +4 -0
- package/docs/execution-backends.7.md +4 -0
- package/docs/launch/launch-kit.md +9 -9
- package/docs/multi-agent-cli-mcp-surface.7.md +4 -0
- package/docs/multi-agent-eval-replay-harness.7.md +4 -0
- package/docs/multi-agent-operator-ux.7.md +4 -0
- package/docs/node-snapshot-diff-replay.7.md +4 -0
- package/docs/observability-cost-accounting.7.md +4 -0
- package/docs/project-index.md +20 -5
- package/docs/readme-v0.1.87-full.md +301 -0
- package/docs/real-execution-backends.7.md +4 -0
- package/docs/release-and-migration.7.md +4 -0
- package/docs/release-tooling.7.md +4 -0
- package/docs/report-verifiable-bundle.7.md +34 -2
- package/docs/run-registry-control-plane.7.md +14 -0
- package/docs/run-retention-reclamation.7.md +4 -0
- package/docs/state-explosion-management.7.md +4 -0
- package/docs/team-collaboration.7.md +4 -0
- package/docs/trust-model.md +6 -4
- package/docs/web-desktop-workbench.7.md +4 -0
- package/manifest/plugin.manifest.json +1 -1
- package/manifest/source-context-profiles.json +1 -1
- package/package.json +8 -5
- package/scripts/agents/agent-adapter-core.js +1 -1
- package/scripts/agents/builtin-templates.json +2 -1
- package/scripts/agents/claude-p-agent.js +7 -33
- package/scripts/agents/codex-agent.js +1 -1
- package/scripts/agents/cw-attest-wrap.js +9 -1
- package/scripts/agents/gemini-agent.js +1 -1
- package/scripts/agents/opencode-agent.js +1 -1
- package/scripts/canonical-apps.js +4 -4
- package/scripts/coverage-gate.js +15 -1
- package/scripts/cw.js +0 -0
- package/scripts/dogfood-release.js +1 -1
- package/scripts/golden-path.js +4 -4
- package/scripts/release-flow.js +49 -2
- package/tsconfig.json +3 -1
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# Cool Workflow
|
|
4
|
+
|
|
5
|
+
**Point an AI coding agent at a repo, get a saved report with real citations — not a chat message you lose.**
|
|
6
|
+
|
|
7
|
+
[](https://github.com/coo1white/cool-workflow/actions/workflows/ci.yml)
|
|
8
|
+
[](https://www.npmjs.com/package/cool-workflow)
|
|
9
|
+
[](https://www.npmjs.com/package/cool-workflow)
|
|
10
|
+
[](https://www.npmjs.com/package/cool-workflow)
|
|
11
|
+
[](https://github.com/coo1white/cool-workflow/tags)
|
|
12
|
+
[](LICENSE)
|
|
13
|
+
|
|
14
|
+
<img src="docs/assets/cool-workflow-readme-promo.png" alt="Cool Workflow turns AI agent repo questions into saved, cited, tamper-evident reports." width="100%">
|
|
15
|
+
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
## What is this, really?
|
|
19
|
+
|
|
20
|
+
You put a question to an AI coding agent, it gives an answer in the chat, and
|
|
21
|
+
then the answer is gone. Next week you put the same question and have to start
|
|
22
|
+
all over again.
|
|
23
|
+
|
|
24
|
+
**Cool Workflow (CW) makes that lost question into a kept job.** You point it at
|
|
25
|
+
a code store with a question like *"what are the security risks here?"* It runs
|
|
26
|
+
your AI agent over all the code in ordered steps and puts a **report file** on
|
|
27
|
+
disk — every point backed by an exact `file.js:42` pointer to the line. You are
|
|
28
|
+
able to run it again, give it to others, and even give proof that the report was
|
|
29
|
+
not changed by anyone.
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
you ask once CW gives you
|
|
33
|
+
"what are the risks in my repo?" → a saved report.md with
|
|
34
|
+
cited findings, repeatable
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
It does **not** run the AI model itself. You give your own agent (for one, the
|
|
38
|
+
`claude` command line) and CW keeps it working, makes a record of what took
|
|
39
|
+
place, and checks the answer. Take CW as the *project manager*, and your agent
|
|
40
|
+
as the *worker*.
|
|
41
|
+
|
|
42
|
+
> New to this? You're in the right place — this README is a step-by-step start.
|
|
43
|
+
> Deeper/advanced docs live in the [wiki](https://github.com/coo1white/cool-workflow/wiki).
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Project rule
|
|
48
|
+
|
|
49
|
+
CW should stay a small, trusted tool, not a platform.
|
|
50
|
+
|
|
51
|
+
```text
|
|
52
|
+
ask simple -> run simple -> verify simple -> resume simple
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The engineering base is FreeBSD-like: POLA first, fail closed, no silent
|
|
56
|
+
fallback, stdout as data, stderr as diagnostics, and documented stable
|
|
57
|
+
surfaces. The user-facing spirit is close to Homebrew: a small command
|
|
58
|
+
surface, a strong `doctor` check, and clear next steps when a run is
|
|
59
|
+
blocked or a report does not verify.
|
|
60
|
+
|
|
61
|
+
That means CW should hide orchestration detail behind clear commands,
|
|
62
|
+
keep `.cw/` state open to check, make recovery boring, and prefer a
|
|
63
|
+
small tool that can be trusted over a broad agent platform.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## What you need
|
|
68
|
+
|
|
69
|
+
1. **Node.js** (v18+). Make a check with `node --version`.
|
|
70
|
+
2. **An AI agent on the command line.** The most simple is **Claude Code** —
|
|
71
|
+
after you put it in you will have a `claude` command. Make a check with
|
|
72
|
+
`claude --version`. (CW also works with `codex`, or any command/HTTP agent —
|
|
73
|
+
but make your start with `claude`.)
|
|
74
|
+
|
|
75
|
+
> No agent yet? You are still able to **see CW work** (next part, step 1)
|
|
76
|
+
> without one. The full report needs an agent, because CW never makes a call to
|
|
77
|
+
> a model itself.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Quick start (3 steps)
|
|
82
|
+
|
|
83
|
+
### 1. See it run — no install, no agent, no API key
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
npx cool-workflow demo tamper
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
This gives proof of CW's chief trick in 30 seconds (more on that
|
|
90
|
+
[below](#can-i-trust-the-report)). If you see `VERDICT: tamper-evidence holds ✓`,
|
|
91
|
+
all is working.
|
|
92
|
+
|
|
93
|
+
Not sure what to run next?
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
npx cool-workflow doctor --onramp
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
This prints the short path for a first run, the fast checks for source work, and
|
|
100
|
+
the full gate to use before a release.
|
|
101
|
+
|
|
102
|
+
From a source checkout, use:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
cd plugins/cool-workflow
|
|
106
|
+
node scripts/cw.js doctor --onramp --changed-from origin/main
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### 2. Check, then run a real review on your own repo
|
|
110
|
+
|
|
111
|
+
First make a zero-write check. It does not make a run, write `.cw/`, or call
|
|
112
|
+
your agent:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
npx cool-workflow quickstart architecture-review --check \
|
|
116
|
+
--repo /path/to/your/project \
|
|
117
|
+
--question "What are the main risks in this codebase?" \
|
|
118
|
+
--agent-command builtin:claude
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
If the check is good, run the review:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
npx cool-workflow quickstart architecture-review \
|
|
125
|
+
--repo /path/to/your/project \
|
|
126
|
+
--question "What are the main risks in this codebase?" \
|
|
127
|
+
--agent-command builtin:claude
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
If the report has to go to someone else, make the checked bundle in the same
|
|
131
|
+
run:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
npx cool-workflow quickstart architecture-review \
|
|
135
|
+
--repo /path/to/your/project \
|
|
136
|
+
--question "What are the main risks in this codebase?" \
|
|
137
|
+
--agent-command builtin:claude \
|
|
138
|
+
--bundle
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
- `--repo` — the folder you have a wish to get looked at.
|
|
142
|
+
- `--question` — what you have a wish to be certain of.
|
|
143
|
+
- `--agent-command builtin:claude` — make use of the Claude wrapper that comes
|
|
144
|
+
with it (read-only; it never makes changes to your code).
|
|
145
|
+
- `--agent-command builtin:codex` — make use of the Codex wrapper that comes
|
|
146
|
+
with it (read-only; it never makes changes to your code).
|
|
147
|
+
|
|
148
|
+
CW makes a plan of the work, keeps your agent working over your repo in steps,
|
|
149
|
+
and gives out where it kept the report. For a living view in the window while
|
|
150
|
+
every worker is at work, take it up with `CW_AGENT_STREAM=1`; the view goes to
|
|
151
|
+
stderr only and the kept answer is not changed.
|
|
152
|
+
|
|
153
|
+
> **No agent put in place?** CW comes to a safe stop and says so
|
|
154
|
+
> (`status: blocked`) — it never makes up an answer. Put in `claude` and run it
|
|
155
|
+
> again.
|
|
156
|
+
|
|
157
|
+
### 3. Read the report
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
cat /path/to/your/project/.cw/runs/<run-id>/report.md
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
You get a short account, ordered points, and **clickable pointers** like
|
|
164
|
+
`src/server.js:18` for every point made — so you are able to make a check of
|
|
165
|
+
each one yourself.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Install it (optional)
|
|
170
|
+
|
|
171
|
+
`npx` is ever working with no need to put it in. To get the short `cw` command
|
|
172
|
+
everywhere:
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
npm install -g cool-workflow # then use: cw … instead of npx cool-workflow …
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## What else can it do?
|
|
181
|
+
|
|
182
|
+
CW comes with a number of ready-made "jobs" (run `cw list` to see them all):
|
|
183
|
+
|
|
184
|
+
| Command | What it does |
|
|
185
|
+
|---|---|
|
|
186
|
+
| `architecture-review` | Make a map of a repo's structure and put its true risks in order, with facts. |
|
|
187
|
+
| `pr-review-fix-ci` | Go over a pull request, put forward fixes, make a check of CI. |
|
|
188
|
+
| `research-synthesis` | Get together and make into one a fact-backed answer to a question. |
|
|
189
|
+
| `release-cut` | Keep a gated, gone-over release moving. |
|
|
190
|
+
|
|
191
|
+
It also puts the same acts out over **MCP**, so editors like Claude Desktop /
|
|
192
|
+
Cursor / VS Code are able to make a call to CW as a tool. See the
|
|
193
|
+
[wiki](https://github.com/coo1white/cool-workflow/wiki) for that and for
|
|
194
|
+
multi-agent runs.
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Can I trust the report?
|
|
199
|
+
|
|
200
|
+
This is what makes CW not the same as the rest. Because CW only *gives the work
|
|
201
|
+
over* to your agent, it keeps a record of every step that makes any false change
|
|
202
|
+
come to light: every agent's given token use is signed by secret-key science and
|
|
203
|
+
chained by hash, so **changing the record after the fact has the chain broken** —
|
|
204
|
+
and anyone is able to make the check again offline with only a public key.
|
|
205
|
+
|
|
206
|
+
See it for yourself — the `demo tamper` from step 1 makes a false record in two
|
|
207
|
+
ways and gets both:
|
|
208
|
+
|
|
209
|
+
```text
|
|
210
|
+
▶ LEDGER tamper
|
|
211
|
+
after: ✗ DETECTED — the hash chain caught it: chain-link[2]: telemetry-chain-broken
|
|
212
|
+
▶ SIGNATURE tamper
|
|
213
|
+
after: ✗ DETECTED — signature does not match reported usage
|
|
214
|
+
VERDICT: tamper-evidence holds ✓ — every forgery caught offline, with only the public key.
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
On a true run, make a check of any run's record yourself:
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
cw telemetry verify <run-id>
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
CW makes use of this on its own code — see the kept living-run proof in
|
|
224
|
+
[`plugins/cool-workflow/docs/dogfood/`](plugins/cool-workflow/docs/dogfood/).
|
|
225
|
+
|
|
226
|
+
The plain point: *the thing that uses up the tokens is not the thing that keeps
|
|
227
|
+
the books.* That keeping-apart is normal in account-keeping — CW gives it to AI
|
|
228
|
+
agents.
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## Hand the report to someone — they can check it on their own
|
|
233
|
+
|
|
234
|
+
A report you keep on your own machine is one thing. A report you can **give to
|
|
235
|
+
someone** who then makes the check themselves is what you are really after. Add
|
|
236
|
+
`--bundle` to the one command and CW seals the finished run into a single,
|
|
237
|
+
self-checking file:
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
npx cool-workflow quickstart architecture-review \
|
|
241
|
+
--repo /path/to/your/project --question "What are the main risks?" \
|
|
242
|
+
--agent-command builtin:claude --bundle --with-trust-key ./trust-pub.pem
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
This puts a `report.cwrun.json` file **where you are** (not in the looked-at
|
|
246
|
+
repo). The one file holds the report, the `file.js:42` pointers, the signed and
|
|
247
|
+
hash-chained record, **and the public key**.
|
|
248
|
+
|
|
249
|
+
Give that file to anyone. With no need for your repo, your keys given over on the
|
|
250
|
+
side, or a put-in past `npx`, they make the check on their own — offline, with
|
|
251
|
+
only the file:
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
npx cool-workflow report verify-bundle report.cwrun.json
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
If the bundle was changed in any way after the fact — the record, a signature, or
|
|
258
|
+
the bytes — the check says so and comes to a stop (it gives back `ok: false` and a
|
|
259
|
+
non-zero code), so a bundle you send on can never be a quiet lie. CW still never
|
|
260
|
+
runs the model itself; it only keeps the books and makes the check.
|
|
261
|
+
|
|
262
|
+
Want to see the whole thing in 30 seconds, with no agent and no key of your own?
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
npx cool-workflow demo bundle
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
It makes a real sealed bundle, makes two false changes to it, and shows the check
|
|
269
|
+
getting **both** — offline, with only the public key the bundle carries.
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## Troubleshooting
|
|
274
|
+
|
|
275
|
+
| Problem | Fix |
|
|
276
|
+
|---|---|
|
|
277
|
+
| `status: blocked`, `agentConfigured: false` | No agent is in place. Put in `claude` (or give `--agent-command`). |
|
|
278
|
+
| `claude: command not found` | Put in Claude Code so the `claude` command is there, then run again. |
|
|
279
|
+
| Want to see the plan without running the AI | Put in `--preview` — it gives the steps and starts nothing. |
|
|
280
|
+
| Want a live agent trace | Put `CW_AGENT_STREAM=1`. It is stderr-only, TTY-gated, and `CW_NO_STREAM=1` puts it off. |
|
|
281
|
+
| Where did my report go? | The command gives out `reportPath`; it is under `<your-repo>/.cw/runs/<id>/report.md`. |
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
## How it works (one paragraph)
|
|
286
|
+
|
|
287
|
+
CW is a small TypeScript/Node run-time that needs no other parts. It makes a
|
|
288
|
+
record of the agent loop out in the open — *plan → dispatch → record → verify →
|
|
289
|
+
commit → report* — as long-lasting files on disk, so a run is open to looking-at
|
|
290
|
+
and able to be played again in place of a chat you let go. It never puts a model
|
|
291
|
+
SDK inside and keeps no API key; your put-in-place agent does the thinking, CW
|
|
292
|
+
does the book-keeping and the checking. For the structure, multi-agent
|
|
293
|
+
working-together, execution backends, and the full CLI/MCP face, see the
|
|
294
|
+
**[wiki](https://github.com/coo1white/cool-workflow/wiki)** and
|
|
295
|
+
[`plugins/cool-workflow/docs/`](plugins/cool-workflow/docs/).
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## License
|
|
300
|
+
|
|
301
|
+
BSD-2-Clause. See [LICENSE](LICENSE). Built by COOLWHITE LLC.
|
|
@@ -165,3 +165,7 @@ No other change to this page in v0.1.84.
|
|
|
165
165
|
## 0.1.87 (v0.1.87)
|
|
166
166
|
|
|
167
167
|
npm test parallel, 4-vendor wrappers (Claude/Codex/Gemini/OpenCode), Homebrew-style CLI UX (colors/did-you-mean/categorized help/error tips/cw info/cw search/cw man/doctor --fix), post-success summaries, agent execution timing
|
|
168
|
+
|
|
169
|
+
## 0.1.88 (v0.1.88)
|
|
170
|
+
|
|
171
|
+
_No behavioral change in v0.1.88 (the container/remote/ci delegating integrations and their canonical evidence are unchanged; the streaming-default and incremental-resume work this release lives in the agent execution path and the drive, not in these backends)._
|
|
@@ -305,3 +305,7 @@ No other change to this page in v0.1.84.
|
|
|
305
305
|
## 0.1.87 (v0.1.87)
|
|
306
306
|
|
|
307
307
|
npm test parallel, 4-vendor wrappers (Claude/Codex/Gemini/OpenCode), Homebrew-style CLI UX (colors/did-you-mean/categorized help/error tips/cw info/cw search/cw man/doctor --fix), post-success summaries, agent execution timing
|
|
308
|
+
|
|
309
|
+
## 0.1.88 (v0.1.88)
|
|
310
|
+
|
|
311
|
+
_No behavioral change in v0.1.88 (`release:check` and the durable run-state compatibility/`state check` path are unchanged; this release's release-flow verdict-capture work lives in the Release Tooling scripts, not in the release-check or migration discipline)._
|
|
@@ -243,3 +243,7 @@ Loaders fail closed on corrupt state; store writes are made safe under more than
|
|
|
243
243
|
## 0.1.87 (v0.1.87)
|
|
244
244
|
|
|
245
245
|
npm test parallel, 4-vendor wrappers (Claude/Codex/Gemini/OpenCode), Homebrew-style CLI UX (colors/did-you-mean/categorized help/error tips/cw info/cw search/cw man/doctor --fix), post-success summaries, agent execution timing
|
|
246
|
+
|
|
247
|
+
## 0.1.88 (v0.1.88)
|
|
248
|
+
|
|
249
|
+
The release flow now captures the reviewer's verdict from agent stdout (`release-flow.js`), so the cut records the gate decision deterministically instead of relying on a hand-entered verdict; the kernel runtime stays untouched.
|
|
@@ -67,10 +67,42 @@ The POLICY is fail-closed and self-describing:
|
|
|
67
67
|
with an embedded key verifies the same on any machine; the override/env only
|
|
68
68
|
apply when the bundle omits a key.
|
|
69
69
|
- `ok` is true only when the archive bytes, the telemetry chain, and the
|
|
70
|
-
trust-audit chain all verify
|
|
70
|
+
trust-audit chain all verify, no attested signature failed re-verification, AND
|
|
71
|
+
the report ⇄ result cross-check holds.
|
|
72
|
+
- **Report ⇄ result ⇄ signature cross-check** (`reportFindingsVerified`) — the
|
|
73
|
+
FORWARD guarantee: every SIGNED finding is present in the report and unaltered.
|
|
74
|
+
Driven by the signature-verified, result-COVERING ledger records (not the archive's
|
|
75
|
+
`run.tasks` list, which is bound by nothing). For each such record: (1) its
|
|
76
|
+
`resultDigest` is anchored by the executor's ed25519 signature — a usage-only
|
|
77
|
+
(4-field) signature is excluded, so an injected digest is never trusted
|
|
78
|
+
(`coversResult` required); (2) the matching completed task's **restored result file
|
|
79
|
+
must hash to that signed digest** (`result-missing` / `result-digest-mismatch:<task>`
|
|
80
|
+
otherwise) — so an edited, missing, dropped, or substituted result is caught because
|
|
81
|
+
the signed digest does not move; (3) `report.md` embeds the result at the task's own
|
|
82
|
+
`### <taskId>` section, body-first (`report-result-mismatch:<task>` otherwise) — so
|
|
83
|
+
an edited report, or a decoy copy buried elsewhere, fails. Editing the report breaks
|
|
84
|
+
(3); editing the result breaks (2); editing **both** to one consistent lie still
|
|
85
|
+
breaks (2). Any failure ⇒ `report-findings`, `ok:false`.
|
|
86
|
+
- **Scope (read this).** The guarantee is FORWARD only: each of the agent's *signed*
|
|
87
|
+
findings is in the report unaltered. It does **not** assert the report contains
|
|
88
|
+
*only* signed findings. CW holds no key to sign the rendered report (it delegates;
|
|
89
|
+
it never signs), and the telemetry ledger chain is self-recomputable, so the report
|
|
90
|
+
MAY carry additional **unsigned content** — prose, an executive summary, ordering,
|
|
91
|
+
or extra sections — and a determined local re-chainer can **omit** a signed finding
|
|
92
|
+
(a shorter, self-consistent history). Verify the findings you act on against the
|
|
93
|
+
signed results; do not read more into a green verdict than "the signed findings are
|
|
94
|
+
present and unaltered." Closing report-completeness fully needs an external
|
|
95
|
+
append-only anchor (declined by design here); see the [Trust Model](trust-model.md).
|
|
96
|
+
- **Trust level** (`trustLevel`): `"signed"` means the agent's signed findings are
|
|
97
|
+
present and unaltered — at least one **result-covering** signature re-verified
|
|
98
|
+
against a key, none failed, and the forward cross-check held. A usage-only (4-field)
|
|
99
|
+
signature, an unverifiable one (no key), or a tampered signed finding all yield
|
|
100
|
+
`"unsigned"`. It attests the signed findings, **not** report exhaustiveness.
|
|
71
101
|
- A bundle with attested telemetry but no available key DEGRADES by default
|
|
72
102
|
(`signatureKeyProvided: false`, the intact chain still decides `ok`).
|
|
73
|
-
`--strict-signatures` refuses such a bundle instead.
|
|
103
|
+
`--strict-signatures` refuses such a bundle instead. `--require-signatures` is
|
|
104
|
+
stronger: it refuses any bundle whose `trustLevel` is `"unsigned"` (closing the
|
|
105
|
+
fail-open where an unsigned-but-intact bundle returned `ok: true`).
|
|
74
106
|
- `--extract-report <path>` writes the bundle's `report.md` out for a human to
|
|
75
107
|
read alongside the machine verdict. If extraction is requested but the bundle
|
|
76
108
|
has no `report.md` (or the write fails), that is a failure, not a silent no-op:
|
|
@@ -177,6 +177,16 @@ whose top-level integrity block is *absent* — closing the legacy fail-open sea
|
|
|
177
177
|
where a stripped-integrity archive imported unverified. Unset (the default) keeps
|
|
178
178
|
legacy integrity-less archives byte-identical; the flag is mechanism, not policy.
|
|
179
179
|
|
|
180
|
+
The archive's run id becomes a directory name under `DIR/.cw/runs/`, so import
|
|
181
|
+
also refuses any run id that is not a single safe path segment (`[A-Za-z0-9._-]`,
|
|
182
|
+
with no separator and not the `.` or `..` component) and asserts the resolved run
|
|
183
|
+
directory stays inside the target's runs root — both *before* the directory is
|
|
184
|
+
made — so a crafted id such as `../../etc` can never write outside the runs tree.
|
|
185
|
+
(An embedded `..` such as `v1..2` is a safe directory name, not a traversal, and
|
|
186
|
+
is allowed so a legitimately-minted run id always round-trips.) The same refusal
|
|
187
|
+
protects `cw report verify-bundle`, which restores an untrusted bundle into a
|
|
188
|
+
throwaway temporary directory.
|
|
189
|
+
|
|
180
190
|
`run verify-import <run-id> [--cwd DIR]` reads the restore manifest again, works out
|
|
181
191
|
every restored file digest again, checks the manifest digest, checks the telemetry
|
|
182
192
|
ledger when one was restored, and proves the **trust-audit hash chain** again (the
|
|
@@ -416,3 +426,7 @@ No other change to this page in v0.1.84.
|
|
|
416
426
|
## 0.1.87 (v0.1.87)
|
|
417
427
|
|
|
418
428
|
npm test parallel, 4-vendor wrappers (Claude/Codex/Gemini/OpenCode), Homebrew-style CLI UX (colors/did-you-mean/categorized help/error tips/cw info/cw search/cw man/doctor --fix), post-success summaries, agent execution timing
|
|
429
|
+
|
|
430
|
+
## 0.1.88 (v0.1.88)
|
|
431
|
+
|
|
432
|
+
Security: archive import now refuses path-traversal run ids (`..`/absolute/separator-bearing ids) before any run dir is minted, closing a write-outside-the-registry vector; run resolution and the run-state schema are otherwise unchanged.
|
|
@@ -216,3 +216,7 @@ No other change to this page in v0.1.84.
|
|
|
216
216
|
## 0.1.87 (v0.1.87)
|
|
217
217
|
|
|
218
218
|
npm test parallel, 4-vendor wrappers (Claude/Codex/Gemini/OpenCode), Homebrew-style CLI UX (colors/did-you-mean/categorized help/error tips/cw info/cw search/cw man/doctor --fix), post-success summaries, agent execution timing
|
|
219
|
+
|
|
220
|
+
## 0.1.88 (v0.1.88)
|
|
221
|
+
|
|
222
|
+
_No behavioral change in v0.1.88 (the tiered, append-only, cryptographically-verifiable reclamation transition is unchanged)._
|
|
@@ -294,3 +294,7 @@ No other change to this page in v0.1.84.
|
|
|
294
294
|
## 0.1.87 (v0.1.87)
|
|
295
295
|
|
|
296
296
|
npm test parallel, 4-vendor wrappers (Claude/Codex/Gemini/OpenCode), Homebrew-style CLI UX (colors/did-you-mean/categorized help/error tips/cw info/cw search/cw man/doctor --fix), post-success summaries, agent execution timing
|
|
297
|
+
|
|
298
|
+
## 0.1.88 (v0.1.88)
|
|
299
|
+
|
|
300
|
+
_No behavioral change in v0.1.88 (the summarization/compaction layer and its fail-closed derived summaries are untouched)._
|
|
@@ -230,3 +230,7 @@ No other change to this page in v0.1.84.
|
|
|
230
230
|
## 0.1.87 (v0.1.87)
|
|
231
231
|
|
|
232
232
|
npm test parallel, 4-vendor wrappers (Claude/Codex/Gemini/OpenCode), Homebrew-style CLI UX (colors/did-you-mean/categorized help/error tips/cw info/cw search/cw man/doctor --fix), post-success summaries, agent execution timing
|
|
233
|
+
|
|
234
|
+
## 0.1.88 (v0.1.88)
|
|
235
|
+
|
|
236
|
+
_No behavioral change in v0.1.88 (the host-attested actor, append-only approvals/comments/handoffs, and the review gate that stacks on the verifier gate are unchanged)._
|
package/docs/trust-model.md
CHANGED
|
@@ -249,10 +249,12 @@ than the math will back up.
|
|
|
249
249
|
signature mismatches fail closed. Mirrored as `cw_telemetry_verify` on the MCP
|
|
250
250
|
surface.
|
|
251
251
|
- `cw demo tamper` — a sealed, offline, one-command proof: it builds a real
|
|
252
|
-
ed25519-signed ledger and then fakes it
|
|
253
|
-
works out the *local* record hash again (the chain still breaks),
|
|
254
|
-
signature again over blown-up tokens (ed25519 turns it down)
|
|
255
|
-
|
|
252
|
+
ed25519-signed ledger and then fakes it three ways — flips a recorded verdict and
|
|
253
|
+
works out the *local* record hash again (the chain still breaks), uses a
|
|
254
|
+
signature again over blown-up tokens (ed25519 turns it down), and edits a signed
|
|
255
|
+
finding after signing so the re-derived sha256(result) no longer joins the
|
|
256
|
+
signature (the verify turns it down). Everything is checked with the public key
|
|
257
|
+
only. The `✗ DETECTED` lines are the point.
|
|
256
258
|
- Re-run either with **only the public key** on a machine we do not control. If it
|
|
257
259
|
does not come out the same, our integrity claim is false — hold us to it.
|
|
258
260
|
|
|
@@ -238,3 +238,7 @@ No other change to this page in v0.1.84.
|
|
|
238
238
|
## 0.1.87 (v0.1.87)
|
|
239
239
|
|
|
240
240
|
npm test parallel, 4-vendor wrappers (Claude/Codex/Gemini/OpenCode), Homebrew-style CLI UX (colors/did-you-mean/categorized help/error tips/cw info/cw search/cw man/doctor --fix), post-success summaries, agent execution timing
|
|
241
|
+
|
|
242
|
+
## 0.1.88 (v0.1.88)
|
|
243
|
+
|
|
244
|
+
_No behavioral change in v0.1.88 (the five operator surfaces and the registry cross-run entry are unchanged; the Workbench still derives everything from state the CLI/MCP already expose)._
|
|
@@ -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.88",
|
|
6
6
|
"license": "BSD-2-Clause",
|
|
7
7
|
"homepage": "https://github.com/coo1white/cool-workflow",
|
|
8
8
|
"author": {
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"runtime": {
|
|
27
27
|
"description": "Runtime-kernel source context for state, orchestration, scheduling, execution, and shared types.",
|
|
28
|
-
"maxLines":
|
|
28
|
+
"maxLines": 44000,
|
|
29
29
|
"include": [
|
|
30
30
|
"plugins/cool-workflow/src/**",
|
|
31
31
|
"plugins/cool-workflow/package.json",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cool-workflow",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.88",
|
|
4
4
|
"bin": {
|
|
5
5
|
"cool-workflow": "scripts/cw.js",
|
|
6
6
|
"cw": "scripts/cw.js"
|
|
@@ -16,6 +16,9 @@
|
|
|
16
16
|
},
|
|
17
17
|
"description": "A workflow control plane and run-time you are able to check: it sends out jobs in TypeScript, makes certain of work against facts before it goes through, puts state into fixed records, orders jobs by time, runs jobs again and again, gets a group of agents to do their parts together, and talks MCP. It gives the doing of the work to outside agents — it never runs the models itself.",
|
|
18
18
|
"type": "commonjs",
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=18"
|
|
21
|
+
},
|
|
19
22
|
"license": "BSD-2-Clause",
|
|
20
23
|
"author": {
|
|
21
24
|
"name": "COOLWHITE LLC"
|
|
@@ -57,10 +60,10 @@
|
|
|
57
60
|
"onramp:check": "node scripts/onramp-check.js --check",
|
|
58
61
|
"version:sync": "node scripts/version-sync-check.js",
|
|
59
62
|
"release:check": "node scripts/release-check.js",
|
|
60
|
-
"test": "node dist/cli.js
|
|
61
|
-
"test:fast": "npm run build --if-present && node dist/cli.js
|
|
62
|
-
"test:ci": "node dist/cli.js
|
|
63
|
-
"test:coverage": "node dist/cli.js
|
|
63
|
+
"test": "node dist/cli.js version > /dev/null && node test/run-all.js",
|
|
64
|
+
"test:fast": "npm run build --if-present && node dist/cli.js version > /dev/null && node test/run-all.js --concurrency auto",
|
|
65
|
+
"test:ci": "node dist/cli.js version > /dev/null && node test/run-all.js --concurrency auto",
|
|
66
|
+
"test:coverage": "node dist/cli.js version > /dev/null && node scripts/coverage-gate.js --concurrency auto",
|
|
64
67
|
"eval:replay": "tsc -p tsconfig.json && node test/multi-agent-eval-replay-harness-smoke.js",
|
|
65
68
|
"ci": "npm run build && npm run check && npm run test && npm run release:check",
|
|
66
69
|
"validate:schema": "node scripts/validate-run-state-schema.js"
|
|
@@ -39,7 +39,7 @@ function buildPrompt(inputPath) {
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
function streamEnabled(env = process.env) {
|
|
42
|
-
return env.CW_AGENT_STREAM
|
|
42
|
+
return env.CW_AGENT_STREAM !== "0" && env.CW_NO_STREAM !== "1";
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
function traceEnabled(env = process.env, stderr = process.stderr) {
|
|
@@ -29,6 +29,11 @@
|
|
|
29
29
|
|
|
30
30
|
const fs = require("node:fs");
|
|
31
31
|
const { spawn, spawnSync } = require("node:child_process");
|
|
32
|
+
// Share the ONE canonical result contract with the codex/gemini/opencode
|
|
33
|
+
// wrappers instead of carrying a private copy. A drifted inline copy (ASCII
|
|
34
|
+
// hyphens silently became em-dashes here) meant claude was sent a different
|
|
35
|
+
// instruction text than the other providers for the same contract.
|
|
36
|
+
const { buildPrompt } = require("./agent-adapter-core");
|
|
32
37
|
|
|
33
38
|
const inputPath = process.argv[2];
|
|
34
39
|
const resultPath = process.argv[3];
|
|
@@ -37,39 +42,8 @@ if (!inputPath || !resultPath) {
|
|
|
37
42
|
process.exit(2);
|
|
38
43
|
}
|
|
39
44
|
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
You have NO file-write access. Do NOT attempt to write, create, or edit any file —
|
|
43
|
-
result.md is persisted FOR YOU from your final message, so writing it yourself is
|
|
44
|
-
neither needed nor possible. Use ONLY read-only tools (read files, grep, list).
|
|
45
|
-
Respond with ONLY your FINAL answer as Markdown, and it MUST END WITH a fenced
|
|
46
|
-
cw:result block that EXACTLY follows this schema:
|
|
47
|
-
|
|
48
|
-
\`\`\`cw:result
|
|
49
|
-
{
|
|
50
|
-
"summary": "one-paragraph direct answer",
|
|
51
|
-
"findings": [
|
|
52
|
-
{
|
|
53
|
-
"id": "unique-kebab-id",
|
|
54
|
-
"title": "short risk title",
|
|
55
|
-
"severity": "P0",
|
|
56
|
-
"classification": "real",
|
|
57
|
-
"evidence": ["path/to/file.ts:42"]
|
|
58
|
-
}
|
|
59
|
-
],
|
|
60
|
-
"evidence": ["path/to/file.ts:42", "path/to/other.ts:10"]
|
|
61
|
-
}
|
|
62
|
-
\`\`\`
|
|
63
|
-
|
|
64
|
-
HARD RULES (the result is REJECTED otherwise):
|
|
65
|
-
- Every object in "findings" MUST have a unique "id" (non-empty string).
|
|
66
|
-
- "classification", if present, MUST be one of: real, conditional, non-issue, unknown.
|
|
67
|
-
- Any finding with "severity" P0, P1, or P2 MUST include a NON-EMPTY "evidence" array.
|
|
68
|
-
- The top-level "evidence" array MUST be NON-EMPTY with REAL file:line locators from this repo.
|
|
69
|
-
- If you have no structured findings, use "findings": [] (empty) — never omit a finding's id.`;
|
|
70
|
-
|
|
71
|
-
const prompt = `${fs.readFileSync(inputPath, "utf8")}\n${CONTRACT}`;
|
|
72
|
-
const streamEnabled = process.env.CW_AGENT_STREAM === "1" && process.env.CW_NO_STREAM !== "1";
|
|
45
|
+
const prompt = buildPrompt(inputPath);
|
|
46
|
+
const streamEnabled = process.env.CW_AGENT_STREAM !== "0" && process.env.CW_NO_STREAM !== "1";
|
|
73
47
|
const traceEnabled = streamEnabled && Boolean(process.stderr.isTTY);
|
|
74
48
|
|
|
75
49
|
if (!streamEnabled) {
|
|
@@ -86,7 +86,7 @@ child.stdout.on("data", (chunk) => {
|
|
|
86
86
|
child.stderr.setEncoding("utf8");
|
|
87
87
|
child.stderr.on("data", (chunk) => {
|
|
88
88
|
childStderr += chunk;
|
|
89
|
-
if (process.env.CW_AGENT_STREAM
|
|
89
|
+
if (process.env.CW_AGENT_STREAM !== "0" && process.env.CW_NO_STREAM !== "1" && process.stderr.isTTY) {
|
|
90
90
|
process.stderr.write(chunk);
|
|
91
91
|
}
|
|
92
92
|
});
|
|
@@ -120,10 +120,18 @@ function main() {
|
|
|
120
120
|
if (report && report.usage && privateKey && manifest) {
|
|
121
121
|
const inputPath = manifest.inputPath;
|
|
122
122
|
const promptDigest = inputPath && fs.existsSync(inputPath) ? sha256(fs.readFileSync(inputPath, "utf8")) : sha256(manifest.prompt || "");
|
|
123
|
+
// Bind the agent's RESULT into the signature too, so editing the findings —
|
|
124
|
+
// not just the usage — is detected. The inner agent ran synchronously, so
|
|
125
|
+
// result.md is on disk now; CW digests the SAME bytes at intake (raw file,
|
|
126
|
+
// shared sha256). Absent/unreadable ⇒ sign without it (a 4-field signature
|
|
127
|
+
// CW still verifies — back-compat).
|
|
128
|
+
const resultPath = manifest.resultPath;
|
|
129
|
+
const resultDigest = resultPath && fs.existsSync(resultPath) ? sha256(fs.readFileSync(resultPath, "utf8")) : undefined;
|
|
123
130
|
const signature = ta.signTelemetry(report.usage, privateKey, {
|
|
124
131
|
runId: manifest.runId,
|
|
125
132
|
taskId: manifest.taskId,
|
|
126
|
-
promptDigest
|
|
133
|
+
promptDigest,
|
|
134
|
+
...(resultDigest ? { resultDigest } : {})
|
|
127
135
|
});
|
|
128
136
|
out = JSON.stringify({ ...report, usageSignature: signature });
|
|
129
137
|
} else if (report) {
|
|
@@ -75,7 +75,7 @@ child.stdout.on("data", (chunk) => {
|
|
|
75
75
|
child.stderr.setEncoding("utf8");
|
|
76
76
|
child.stderr.on("data", (chunk) => {
|
|
77
77
|
childStderr += chunk;
|
|
78
|
-
if (process.env.CW_AGENT_STREAM
|
|
78
|
+
if (process.env.CW_AGENT_STREAM !== "0" && process.env.CW_NO_STREAM !== "1" && process.stderr.isTTY) {
|
|
79
79
|
process.stderr.write(chunk);
|
|
80
80
|
}
|
|
81
81
|
});
|
|
@@ -79,7 +79,7 @@ child.stdout.on("data", (chunk) => {
|
|
|
79
79
|
child.stderr.setEncoding("utf8");
|
|
80
80
|
child.stderr.on("data", (chunk) => {
|
|
81
81
|
childStderr += chunk;
|
|
82
|
-
if (process.env.CW_AGENT_STREAM
|
|
82
|
+
if (process.env.CW_AGENT_STREAM !== "0" && process.env.CW_NO_STREAM !== "1" && process.stderr.isTTY) {
|
|
83
83
|
process.stderr.write(chunk);
|
|
84
84
|
}
|
|
85
85
|
});
|