cool-workflow 0.1.87 → 0.1.89

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 (75) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codex-plugin/plugin.json +1 -1
  3. package/README.md +111 -71
  4. package/apps/architecture-review/app.json +1 -1
  5. package/apps/architecture-review-fast/app.json +1 -1
  6. package/apps/end-to-end-golden-path/app.json +1 -1
  7. package/apps/pr-review-fix-ci/app.json +1 -1
  8. package/apps/release-cut/app.json +1 -1
  9. package/apps/research-synthesis/app.json +1 -1
  10. package/dist/agent-config.js +42 -1
  11. package/dist/capability-core.js +16 -4
  12. package/dist/capability-registry.js +24 -0
  13. package/dist/cli/command-surface.js +105 -2
  14. package/dist/cli.js +2 -1
  15. package/dist/doctor.js +14 -1
  16. package/dist/drive.js +222 -16
  17. package/dist/execution-backend.js +4 -4
  18. package/dist/loop-expansion.js +60 -0
  19. package/dist/onramp.js +25 -0
  20. package/dist/orchestrator/lifecycle-operations.js +134 -3
  21. package/dist/orchestrator.js +48 -77
  22. package/dist/run-export.js +106 -2
  23. package/dist/state-node.js +13 -3
  24. package/dist/state.js +21 -0
  25. package/dist/telemetry-attestation.js +30 -6
  26. package/dist/telemetry-demo.js +29 -1
  27. package/dist/telemetry-ledger.js +6 -0
  28. package/dist/version.js +1 -1
  29. package/dist/worker-accept/telemetry-ledger.js +12 -2
  30. package/dist/workflow-api.js +33 -0
  31. package/dist/workflow-app-framework.js +20 -0
  32. package/docs/agent-delegation-drive.7.md +8 -0
  33. package/docs/capability-topology-registry.7.md +69 -46
  34. package/docs/cli-mcp-parity.7.md +16 -2
  35. package/docs/contract-migration-tooling.7.md +8 -0
  36. package/docs/control-plane-scheduling.7.md +8 -0
  37. package/docs/durable-state-and-locking.7.md +8 -0
  38. package/docs/evidence-adoption-reasoning-chain.7.md +8 -0
  39. package/docs/execution-backends.7.md +8 -0
  40. package/docs/launch/launch-kit.md +9 -9
  41. package/docs/multi-agent-cli-mcp-surface.7.md +8 -0
  42. package/docs/multi-agent-eval-replay-harness.7.md +8 -0
  43. package/docs/multi-agent-operator-ux.7.md +8 -0
  44. package/docs/node-snapshot-diff-replay.7.md +8 -0
  45. package/docs/observability-cost-accounting.7.md +8 -0
  46. package/docs/project-index.md +22 -5
  47. package/docs/readme-v0.1.87-full.md +301 -0
  48. package/docs/real-execution-backends.7.md +8 -0
  49. package/docs/release-and-migration.7.md +8 -0
  50. package/docs/release-tooling.7.md +8 -0
  51. package/docs/report-verifiable-bundle.7.md +34 -2
  52. package/docs/run-registry-control-plane.7.md +18 -0
  53. package/docs/run-retention-reclamation.7.md +8 -0
  54. package/docs/state-explosion-management.7.md +8 -0
  55. package/docs/team-collaboration.7.md +8 -0
  56. package/docs/trust-model.md +6 -4
  57. package/docs/web-desktop-workbench.7.md +8 -0
  58. package/manifest/plugin.manifest.json +1 -1
  59. package/manifest/source-context-profiles.json +1 -1
  60. package/package.json +8 -5
  61. package/scripts/agents/agent-adapter-core.js +1 -1
  62. package/scripts/agents/builtin-templates.json +2 -1
  63. package/scripts/agents/claude-p-agent.js +7 -33
  64. package/scripts/agents/codex-agent.js +1 -1
  65. package/scripts/agents/cw-attest-wrap.js +9 -1
  66. package/scripts/agents/gemini-agent.js +1 -1
  67. package/scripts/agents/opencode-agent.js +1 -1
  68. package/scripts/canonical-apps.js +4 -4
  69. package/scripts/coverage-gate.js +15 -1
  70. package/scripts/cw.js +0 -0
  71. package/scripts/dogfood-release.js +1 -1
  72. package/scripts/golden-path.js +4 -4
  73. package/scripts/release-flow.js +49 -2
  74. package/scripts/release-gate.sh +11 -2
  75. package/tsconfig.json +3 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "cool-workflow",
3
3
  "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.",
4
- "version": "0.1.87",
4
+ "version": "0.1.89",
5
5
  "author": {
6
6
  "name": "COOLWHITE LLC"
7
7
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cool-workflow",
3
- "version": "0.1.87",
3
+ "version": "0.1.89",
4
4
  "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.",
5
5
  "author": {
6
6
  "name": "COOLWHITE LLC"
package/README.md CHANGED
@@ -1,122 +1,139 @@
1
+ <div align="center">
2
+
1
3
  # Cool Workflow
2
4
 
3
- ```text
4
- ══════════════════════════════════════════════════════════════════════
5
- auditable agent-workflow control-plane — delegate, don't execute
6
- plan → dispatch → record → verify → commit → report
7
- ══════════════════════════════════════════════════════════════════════
8
- ```
5
+ **Get a saved, cited report from your AI agent — not a chat message you lose.**
9
6
 
10
7
  [![CI](https://img.shields.io/github/actions/workflow/status/coo1white/cool-workflow/ci.yml?branch=main&style=flat-square&label=CI)](https://github.com/coo1white/cool-workflow/actions/workflows/ci.yml)
11
8
  [![npm](https://img.shields.io/npm/v/cool-workflow?style=flat-square&label=npm&color=cb3837)](https://www.npmjs.com/package/cool-workflow)
12
9
  [![downloads](https://img.shields.io/npm/dm/cool-workflow?style=flat-square&label=downloads)](https://www.npmjs.com/package/cool-workflow)
10
+ [![provenance](https://img.shields.io/badge/npm-provenance-3178C6?style=flat-square)](https://www.npmjs.com/package/cool-workflow)
13
11
  [![release](https://img.shields.io/github/v/tag/coo1white/cool-workflow?style=flat-square&label=release&color=brightgreen&sort=semver)](https://github.com/coo1white/cool-workflow/tags)
14
- [![license](https://img.shields.io/badge/license-BSD--2--Clause-blue?style=flat-square)](../../LICENSE)
12
+ [![license](https://img.shields.io/badge/license-BSD--2--Clause-blue?style=flat-square)](https://github.com/coo1white/cool-workflow/blob/main/LICENSE)
15
13
  ![MCP](https://img.shields.io/badge/MCP-native-8A2BE2?style=flat-square)
16
14
  ![runtime](https://img.shields.io/badge/runtime-TypeScript%20%C2%B7%20Node-3178C6?style=flat-square)
17
15
 
18
- **[Start Here](#start-here)** · [Quickstart](#quickstart) · [Developer Loop](#developer-loop) · [Commands](#commands) · [Release History](docs/release-history.md)
16
+ <img src="https://raw.githubusercontent.com/coo1white/cool-workflow/main/docs/assets/cool-workflow-readme-promo.png" alt="Cool Workflow turns AI agent repo questions into saved, cited, tamper-evident reports." width="100%">
19
17
 
20
- Cool Workflow, or CW, is a free-standing agent workflow control-plane put up as a
21
- TypeScript runtime. It gives a COL-Architecture: Router / Orchestrator,
22
- Subagent Dispatch, Deterministic Harness, Adversarial Verifier, Git/State
23
- Commit, and MCP JSON-RPC 2.0 bridge.
18
+ </div>
24
19
 
25
- The way to see it is a base system plus userland apps: CW gives the runtime and
26
- contracts, while makers write apps they can use again in
27
- `apps/<app-id>/app.json`. Old `workflows/*.workflow.js` files still
28
- load as fit-together wrappers.
20
+ > An auditable agent-workflow control-plane **delegate, don't execute**.
21
+ > `plan dispatch record verify commit → report`
29
22
 
30
- CW writes down the model workflow loop in a clear way:
23
+ ## Install
31
24
 
32
- ```text
33
- interpret -> act -> observe -> adjust -> checkpoint
25
+ ```bash
26
+ npm install -g cool-workflow
34
27
  ```
35
28
 
36
- These loop stages are kept in `state.json`, task records, reports, and state
37
- commit snapshots.
38
-
39
- CW keeps orchestration state and task queues in files. An agent host does
40
- the tasks and gives results back to the workflow.
41
-
42
- CW keeps to a small set of Unix-based workflow rules: small kernel,
43
- clear state, pipes that join, workers kept apart, and verifier-gated commits.
44
- See [docs/unix-principles.md](docs/unix-principles.md).
29
+ What you need: **Node.js v18+** (`node --version`) and one AI agent CLI on your machine
30
+ (`claude`, `codex`, `gemini`, or `opencode`). No agent? `cw demo` still works — CW never runs a model itself.
45
31
 
46
- ## Start Here
32
+ ## Quick Start (3 steps)
47
33
 
48
- Use the short path first. The long notes below are history and deep reference,
49
- not the first run.
34
+ ### 1. Prove it works (30 seconds, no agent needed)
50
35
 
51
36
  ```bash
52
37
  cw demo tamper
53
- cw doctor --onramp
54
- cw quickstart architecture-review --check --repo /path/to/repo \
55
- --question "What are the main risks?" --agent-command builtin:claude
56
- cw quickstart architecture-review --repo /path/to/repo \
57
- --question "What are the main risks?" --agent-command builtin:claude --bundle
58
- cw report verify-bundle report.cwrun.json
38
+ # VERDICT: tamper-evidence holds ✓
59
39
  ```
60
40
 
61
- For source work, keep the loop small:
41
+ ### 2. Run a review on your code — one command
62
42
 
63
43
  ```bash
64
- npm run build
65
- node test/<nearest-smoke>.js
66
- npm run test:fast
44
+ cw -q "What are the main risks here?"
67
45
  ```
68
46
 
69
- Run `npm run release:check` only when the batch is ready for the full gate. Start
70
- with `quickstart` and `report` before the multi-agent pages.
47
+ CW auto-detects the repo (current folder) and your agent (first found on PATH).
48
+ Pick a specific agent with a flag:
71
49
 
72
- For the full capability and release history, see [docs/release-history.md](docs/release-history.md).
73
- This README tracks CW v0.1.85.
50
+ ```bash
51
+ cw -q "What are the security risks?" -claude
52
+ cw -q "What are the security risks?" -codex
53
+ cw -q "What are the security risks?" -deepseek
54
+ ```
74
55
 
75
- ## Quickstart
56
+ You will see live streaming output as the agent works — no env vars needed.
76
57
 
77
- **30-second proof, no install** — see that a recorded telemetry verdict can't be faked:
58
+ ### 3. Open the report
78
59
 
79
60
  ```bash
80
- npx cool-workflow demo tamper
81
- # builds a signed ed25519 ledger, forges it 2 ways, both caught offline
82
- # -> VERDICT: tamper-evidence holds ✓
61
+ cat .cw/runs/<run-id>/report.md
62
+ # findings with clickable file.ts:42 pointers for every claim
83
63
  ```
84
64
 
85
- **Try a real run** no clone needed; drive an architecture review with your own agent:
65
+ ## What Else Can It Do?
86
66
 
87
67
  ```bash
88
- npx cool-workflow quickstart architecture-review --repo /path/to/repo \
89
- --question "Is this architecture sound?" --agent-command builtin:claude
68
+ cw version # show version
69
+ cw update # update to latest release
70
+ cw doctor # check your setup
71
+ cw fix # show fix commands for setup issues
90
72
  ```
91
73
 
92
- Add `--bundle` when the report has to go to someone else; then check the file
93
- offline with `cw report verify-bundle report.cwrun.json`.
74
+ | Workflow | Does |
75
+ |---|---|
76
+ | `architecture-review` | Map a repo, rank risks, back every claim with evidence |
77
+ | `pr-review-fix-ci` | Review a pull request, suggest fixes, verify CI |
78
+ | `research-synthesis` | Answer a question with fact-backed research |
79
+ | `release-cut` | Run a gated, reviewed release |
80
+
81
+ **Multi-agent, when you need it.** Fan work out across agents with built-in topologies,
82
+ compose flows (a task can run a whole child workflow with `subWorkflow`, or a `loop()` phase
83
+ can keep iterating until a predicate or a token budget says stop) — and re-run fast:
84
+ `cw run <app> --drive --incremental` reuses every step whose inputs didn't change.
94
85
 
95
- CW DELEGATES worker execution to your own agent. With no `--agent-command` (or
96
- `CW_AGENT_COMMAND`) the drive fails closed (status `blocked`) it never makes up a
97
- result. `--agent-command builtin:claude` points to a bundled read-only `claude -p`
98
- wrapper (needs `claude` on your PATH). `--agent-command builtin:codex` points to
99
- the bundled read-only Codex wrapper (needs `codex` on your PATH). With
100
- `CW_AGENT_STREAM=1`, both wrappers can show a live stderr trace while stdout stays
101
- the kept data channel.
86
+ CW also has an **MCP** surface **Claude Desktop, Cursor, and VS Code call CW as a tool**, so
87
+ your agent can plan a run, drive it, and verify a report without leaving the editor.
102
88
 
103
- **Re-prove a finished run, offline** (`cw` is the installed bin; or `npx cool-workflow <cmd>`):
89
+ ## Can I Trust the Report?
90
+
91
+ CW does not run the AI model — it keeps the books. The agent signs its findings (ed25519), and
92
+ `cw report verify-bundle` checks — offline, with nothing but the public key — that every signed
93
+ finding is in the report **unaltered**: edit a finding, in the report or in the agent's own result,
94
+ and the check fails. CW holds no private key — the agent signs, CW only verifies.
104
95
 
105
96
  ```bash
106
- cw telemetry verify <run-id> # re-checks the hash-chained ledger
107
- cw telemetry verify <run-id> --pubkey pub.pem # also re-runs ed25519 signature checks
108
- cw audit verify <run-id> # re-proves the trust-audit hash chain
97
+ cw demo tamper # proves it in 30s — edits a signed result, watch it fail
98
+ cw telemetry verify <run-id> # checks a real run
99
+ cw audit verify <run-id> # re-proves the trust-audit hash chain
109
100
  ```
110
101
 
111
- More: `cw quickstart <app> --preview` (read-only dry run), `cw run resume <run-id> --drive`
112
- (go on with a run that was stopped), `cw run inspect-archive <archive>` (integrity-check a
113
- portable run archive without bringing it in).
102
+ Give the report to another person they need nothing but the file:
103
+
104
+ ```bash
105
+ cw -q "…" --bundle # seal into one portable file
106
+ cw report verify-bundle report.cwrun.json # they check it offline
107
+ cw report verify-bundle report.cwrun.json \
108
+ --require-signatures # …and insist the findings are signed
109
+ ```
110
+
111
+ This attests the agent's **signed findings** — not that the report holds nothing else, and not that
112
+ none were left out. CW has no key to sign the rendered report, and a determined re-chainer can drop a
113
+ signed finding entirely — so check the findings you act on against the signed results. For exactly
114
+ what is and is not proven, see the [Trust Model](docs/trust-model.md).
115
+
116
+ ## Troubleshooting
117
+
118
+ | Problem | Fix |
119
+ |---|---|
120
+ | No agent found | Run `cw doctor` — it shows which agents are on your machine |
121
+ | `status: blocked` | CW failing closed (it never makes up a result). Set `CW_AGENT_COMMAND=builtin:claude` or pass `-claude`; `cw doctor` names the exact reason |
122
+ | `claude: command not found` | Install Claude Code (`npm install -g @anthropic-ai/claude-code`) and run again |
123
+ | Where is my report? | `<repo>/.cw/runs/<id>/report.md` |
124
+ | Preflight before a spawn | `cw quickstart --check` — a zero-write check |
125
+
126
+ ---
127
+
128
+ The rest of this README is the **developer / operator reference**: the build loop, repo
129
+ structure, the full command surface, scheduling, and the result-envelope contract.
114
130
 
115
131
  ## Developer Loop
116
132
 
117
- Use the shortest check that fits the change:
133
+ Use the shortest check that fits the change (from `plugins/cool-workflow/`):
118
134
 
119
135
  ```bash
136
+ cd plugins/cool-workflow
120
137
  npm run build
121
138
  node test/<nearest-smoke>.js
122
139
  npm run test:fast
@@ -189,6 +206,22 @@ node scripts/cw.js app package architecture-review
189
206
  node scripts/cw.js app init my-app --title "My App"
190
207
  ```
191
208
 
209
+ Compose flows from smaller verified ones (app-authoring surface, `workflow-api.ts`):
210
+
211
+ - **Sub-workflow nesting** — a task can run a whole child app instead of one agent:
212
+ `subWorkflow(id, appId, { inputs?, bindResult? })`. The drive plans and drives the
213
+ child, then binds its report (or verdict result) back as the task's result, so the
214
+ parent's verifier/schema gate consumes it like any other. Leaf work stays external-agent
215
+ delegation at every depth; recursion is depth- and cycle-bounded, fail-closed.
216
+ - **Bounded dynamic loops** — converge without unbounded recursion:
217
+ `loop(name, tasks, { maxRounds, until })` is a per-round template. After each round a
218
+ named, registered pure predicate (`until: { kind: "predicate", ref }`) decides whether to
219
+ append another round or stop, hard-capped at `maxRounds`; built-ins `no-new-findings` and
220
+ `single-round`. Or scale by budget — `until: { kind: "budget-target", target }` keeps
221
+ going while recorded (attested-only) usage stays under `target`, with the fail-closed
222
+ `limits.tokenBudget` cap as the absolute backstop. Predicates are registry refs (not
223
+ closures), so runs replay byte-identically; an unregistered predicate stops fail-closed.
224
+
192
225
  Create a reusable workflow script:
193
226
 
194
227
  ```bash
@@ -325,6 +358,7 @@ node scripts/cw.js registry refresh --scope home
325
358
  node scripts/cw.js run search --app architecture-review --status failed
326
359
  node scripts/cw.js run show <run-id>
327
360
  node scripts/cw.js run resume <run-id>
361
+ node scripts/cw.js run resume <run-id> --drive --incremental # re-drive, reusing every step whose inputs are unchanged
328
362
  node scripts/cw.js run rerun <failed-run-id> --reason "retry"
329
363
  node scripts/cw.js run archive <run-id> --reason "old"
330
364
  node scripts/cw.js queue add --app release-cut --priority 10
@@ -428,7 +462,13 @@ Verification and synthesis tasks need a structured result block:
428
462
  ```
429
463
  ````
430
464
 
431
- v0.1.86
465
+ ## 0.1.89 (v0.1.89)
466
+
467
+ Headline golden-path fixes: `cw -q "question"` asks the question (was read as an app id), auto-detects the cwd as the repo (run anywhere, no `--repo`/`cd`), and `cw help` renders a clean wrapped command list with a trailing newline; plus a vendor-agnostic UI/UX prevention gate (a headline-command smoke + a real `npm install -g` run-from-anywhere smoke) so a CLI-surface regression can't ship invisibly again.
468
+
469
+ ## 0.1.88 (v0.1.88)
470
+
471
+ Orchestration-parity for the agent drive — inline `subWorkflow()` nesting, bounded dynamic `loop()` phases (a `predicate` or a `budget-target` token `until`), and `cw run --drive --incremental` step-level resume; the agent now signs its findings (result-bound ed25519) and `cw report verify-bundle --require-signatures` proves offline that every signed finding is in the report unaltered; CLI simplified to 6 commands with agent streaming on by default; path-traversal run ids refused on archive import.
432
472
 
433
473
  ## 0.1.87 (v0.1.87)
434
474
 
@@ -3,7 +3,7 @@
3
3
  "id": "architecture-review",
4
4
  "title": "Architecture Review",
5
5
  "summary": "Map a repository architecture, assess risks, verify important findings, and synthesize an evidence-backed verdict.",
6
- "version": "0.1.87",
6
+ "version": "0.1.89",
7
7
  "author": "COOLWHITE LLC",
8
8
  "inputs": [
9
9
  {
@@ -3,7 +3,7 @@
3
3
  "id": "architecture-review-fast",
4
4
  "title": "Architecture Review Fast",
5
5
  "summary": "Run a shorter architecture review with parallel map and assess phases for faster first results.",
6
- "version": "0.1.87",
6
+ "version": "0.1.89",
7
7
  "author": "COOLWHITE LLC",
8
8
  "inputs": [
9
9
  {
@@ -3,7 +3,7 @@
3
3
  "id": "end-to-end-golden-path",
4
4
  "title": "End-to-End Golden Path",
5
5
  "summary": "Deterministic one-worker workflow app for proving the CW integration chain.",
6
- "version": "0.1.87",
6
+ "version": "0.1.89",
7
7
  "author": "COOLWHITE LLC",
8
8
  "inputs": [
9
9
  {
@@ -3,7 +3,7 @@
3
3
  "id": "pr-review-fix-ci",
4
4
  "title": "PR Review Fix CI",
5
5
  "summary": "Review a pull request or branch, inspect CI failures, diagnose actionable issues, optionally patch, verify, and summarize with evidence.",
6
- "version": "0.1.87",
6
+ "version": "0.1.89",
7
7
  "author": "COOLWHITE LLC",
8
8
  "inputs": [
9
9
  {
@@ -3,7 +3,7 @@
3
3
  "id": "release-cut",
4
4
  "title": "Release Cut",
5
5
  "summary": "Prepare a release with checklist discipline: version checks, changelog, tests, packaging, release notes, and final verification.",
6
- "version": "0.1.87",
6
+ "version": "0.1.89",
7
7
  "author": "COOLWHITE LLC",
8
8
  "inputs": [
9
9
  {
@@ -3,7 +3,7 @@
3
3
  "id": "research-synthesis",
4
4
  "title": "Research Synthesis",
5
5
  "summary": "Split a research question into claims, investigate sources, cross-check evidence, verify claims, and synthesize a concise answer.",
6
- "version": "0.1.87",
6
+ "version": "0.1.89",
7
7
  "author": "COOLWHITE LLC",
8
8
  "inputs": [
9
9
  {
@@ -146,6 +146,31 @@ function agentConfigFromArgs(args) {
146
146
  // in scripts/agents/builtin-templates.json (vendor name -> wrapper script name).
147
147
  // Adding a vendor is a content/distribution step (drop a wrapper + a JSON line),
148
148
  // not a kernel edit — keeping CW vendor-agnostic at the source level.
149
+ /** Detect which known agent CLIs are on PATH. Returns the first found, or undefined.
150
+ * Skipped when CW_NO_AUTO_AGENT=1 (test sandboxes, CI without real agents). */
151
+ function detectAgentFromPath(env = process.env) {
152
+ if (env.CW_NO_AUTO_AGENT === "1")
153
+ return undefined;
154
+ const known = ["claude", "codex", "gemini", "opencode"];
155
+ const dirs = (env.PATH || "").split(node_path_1.default.delimiter).filter(Boolean);
156
+ const exts = process.platform === "win32" ? (env.PATHEXT || ".EXE;.CMD;.BAT").split(";") : [""];
157
+ for (const name of known) {
158
+ // Also check if the builtin template exists (so we don't suggest an unsupported agent).
159
+ const templates = builtinAgentTemplates();
160
+ if (!templates[name])
161
+ continue;
162
+ for (const dir of dirs) {
163
+ for (const ext of exts) {
164
+ try {
165
+ if (node_fs_1.default.statSync(node_path_1.default.join(dir, name + ext)).isFile())
166
+ return name;
167
+ }
168
+ catch { /* keep looking */ }
169
+ }
170
+ }
171
+ }
172
+ return undefined;
173
+ }
149
174
  function builtinAgentTemplates() {
150
175
  const agentsDir = node_path_1.default.join(__dirname, "..", "scripts", "agents");
151
176
  const manifest = JSON.parse(node_fs_1.default.readFileSync(node_path_1.default.join(agentsDir, "builtin-templates.json"), "utf8"));
@@ -186,7 +211,23 @@ function resolveAgentConfig(args = {}, env = process.env) {
186
211
  : fileCfg && (fileCfg.command || fileCfg.endpoint)
187
212
  ? "file"
188
213
  : "none";
189
- return { schemaVersion: 1, command, args: cfgArgs, endpoint, model, timeoutMs, attestPublicKey, requireAttestedTelemetry, source };
214
+ // Auto-detect: if no agent is configured, check PATH for known agent CLIs and
215
+ // resolve via builtin:<name>. This makes `cw quickstart` work without
216
+ // --agent-command on machines where claude/codex/gemini/opencode are installed.
217
+ let finalCommand = command;
218
+ let finalSource = source;
219
+ let finalModel = model;
220
+ if (!finalCommand && !endpoint) {
221
+ const detected = detectAgentFromPath(env);
222
+ if (detected) {
223
+ finalCommand = expandBuiltinAgentCommand(`builtin:${detected}`);
224
+ finalSource = "auto";
225
+ // Store the detected vendor name as the model hint so doctor can show it.
226
+ if (!finalModel)
227
+ finalModel = `builtin:${detected}`;
228
+ }
229
+ }
230
+ return { schemaVersion: 1, command: finalCommand, args: cfgArgs, endpoint, model: finalModel, timeoutMs, attestPublicKey, requireAttestedTelemetry, source: finalSource };
190
231
  }
191
232
  /** True iff a command-template OR endpoint is configured (after resolution). */
192
233
  function agentConfigured(args = {}, env = process.env) {
@@ -324,7 +324,8 @@ function reportBundle(runner, runId, args) {
324
324
  const verification = (0, run_export_1.verifyReportBundle)(exported.path, {
325
325
  pubkey: optionalString(args.pubkey || args.pubKey || args.publicKey),
326
326
  extractReportTo: extractReportTo ? node_path_1.default.resolve(base, extractReportTo) : undefined,
327
- strictSignatures: Boolean(args["strict-signatures"] || args.strictSignatures || args.strictSigs)
327
+ strictSignatures: Boolean(args["strict-signatures"] || args.strictSignatures || args.strictSigs),
328
+ requireSignatures: Boolean(args["require-signatures"] || args.requireSignatures || args.requireSigs)
328
329
  });
329
330
  return {
330
331
  schemaVersion: 1,
@@ -349,7 +350,8 @@ function runVerifyReportBundle(_runner, args) {
349
350
  return (0, run_export_1.verifyReportBundle)(node_path_1.default.resolve(base, archive), {
350
351
  pubkey: optionalString(args.pubkey || args.pubKey || args.publicKey),
351
352
  extractReportTo: extractReportTo ? node_path_1.default.resolve(base, extractReportTo) : undefined,
352
- strictSignatures: Boolean(args["strict-signatures"] || args.strictSignatures || args.strictSigs)
353
+ strictSignatures: Boolean(args["strict-signatures"] || args.strictSignatures || args.strictSigs),
354
+ requireSignatures: Boolean(args["require-signatures"] || args.requireSignatures || args.requireSigs)
353
355
  });
354
356
  }
355
357
  function queueAdd(reg, args) {
@@ -494,7 +496,8 @@ const DRIVE_RUNTIME_KEYS = [
494
496
  "agent-model",
495
497
  "agentTimeoutMs",
496
498
  "agent-timeout-ms",
497
- "resume"
499
+ "resume",
500
+ "incremental"
498
501
  ];
499
502
  function planInputsFor(args) {
500
503
  const copy = withoutRuntimeKeys(args);
@@ -527,6 +530,7 @@ function runDrive(runner, args) {
527
530
  return (0, drive_1.drive)(runner.withBaseDir(target), driveRunId, {
528
531
  once: isTrue(args.once),
529
532
  now: optionalString(args.now),
533
+ incremental: isTrue(args.incremental),
530
534
  args
531
535
  });
532
536
  }
@@ -544,6 +548,13 @@ exports.QUICKSTART_DEFAULT_APP = "architecture-review";
544
548
  * the drive fails closed (status=blocked) and we never fabricate a completion. */
545
549
  function quickstart(runner, args) {
546
550
  const appId = String(args.appId || args.app || args.workflowId || exports.QUICKSTART_DEFAULT_APP);
551
+ // Run anywhere (like brew): default the repo-under-review to the caller's cwd when no
552
+ // --repo/--cwd is given, mirroring quickstartCheck — so `cw -q "…"` works from any
553
+ // project directory without a flag, instead of failing validateInputs with "Missing
554
+ // required input --repo".
555
+ if (!optionalString(args.repo) && !optionalString(args.cwd)) {
556
+ args.repo = invocationCwd(args);
557
+ }
547
558
  const agentConfigured = Boolean((0, agent_config_1.resolveAgentConfig)(args).command || (0, agent_config_1.resolveAgentConfig)(args).endpoint);
548
559
  if (isTrue(args.check))
549
560
  return quickstartCheck(runner, appId, args, agentConfigured);
@@ -970,7 +981,8 @@ function auditVerify(runner, args) {
970
981
  }
971
982
  // ---- demo: tamper-evidence (the one-command proof) -------------------------
972
983
  // Hermetic, deterministic-shape: builds a real ed25519-signed telemetry ledger,
973
- // then forges it two ways and shows both tamper-evidence layers catch it. CLI-only
984
+ // then forges it three ways and shows all three tamper-evidence layers (ledger,
985
+ // signature, result) catch it. CLI-only
974
986
  // (a human-facing demonstration; the underlying verify is the telemetry.verify verb).
975
987
  function demoTamper(_runner, _args = {}) {
976
988
  return (0, telemetry_demo_1.runTamperDemo)();
@@ -53,6 +53,30 @@ const BUILTIN_CAPABILITIES = [
53
53
  cli: { path: ["help"], jsonMode: "human" },
54
54
  reason: "Human help text. MCP hosts enumerate capabilities via tools/list, not a help command."
55
55
  },
56
+ {
57
+ capability: "version",
58
+ summary: "Print the current cool-workflow version.",
59
+ entry: "CURRENT_COOL_WORKFLOW_VERSION",
60
+ surface: "cli-only",
61
+ cli: { path: ["version"], jsonMode: "human" },
62
+ reason: "Version string — no structured data contract."
63
+ },
64
+ {
65
+ capability: "update",
66
+ summary: "Update cool-workflow to the latest release via npm.",
67
+ entry: "npmUpdate",
68
+ surface: "cli-only",
69
+ cli: { path: ["update"], jsonMode: "human" },
70
+ reason: "Self-update via npm — inherently local shell operation, no MCP surface."
71
+ },
72
+ {
73
+ capability: "fix",
74
+ summary: "Print consolidated fix commands for CW setup issues.",
75
+ entry: "runDoctor",
76
+ surface: "cli-only",
77
+ cli: { path: ["fix"], jsonMode: "human" },
78
+ reason: "Environment fix commands are local diagnostics, same reasoning as doctor."
79
+ },
56
80
  {
57
81
  capability: "list",
58
82
  summary: "List bundled CW workflows.",
@@ -1,4 +1,37 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
37
  };
@@ -6,6 +39,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
39
  exports.runCli = runCli;
7
40
  const node_fs_1 = __importDefault(require("node:fs"));
8
41
  const node_path_1 = __importDefault(require("node:path"));
42
+ const node_child_process_1 = require("node:child_process");
43
+ const readline = __importStar(require("node:readline"));
9
44
  const orchestrator_1 = require("../orchestrator");
10
45
  const capability_core_1 = require("../capability-core");
11
46
  const observability_1 = require("../observability");
@@ -24,8 +59,38 @@ const evidence_reasoning_1 = require("../evidence-reasoning");
24
59
  const doctor_1 = require("../doctor");
25
60
  const orchestrator_2 = require("../orchestrator");
26
61
  const term_1 = require("../term");
62
+ const version_1 = require("../version");
27
63
  async function runCli(argv = process.argv.slice(2)) {
28
64
  const args = (0, orchestrator_1.parseArgv)(argv);
65
+ // Top-level flags: accept --version / -v / --help / -h before command lookup.
66
+ if (args.command?.startsWith("-") || !args.command) {
67
+ if (args.command === "--version" || args.command === "-v" || args.options.v || args.options.version) {
68
+ process.stdout.write(`${version_1.CURRENT_COOL_WORKFLOW_VERSION}\n`);
69
+ return;
70
+ }
71
+ if (!args.command || args.command === "--help" || args.command === "-h" || args.options.h || args.options.help) {
72
+ process.stdout.write((0, orchestrator_1.formatHelp)() + "\n");
73
+ return;
74
+ }
75
+ }
76
+ // Map vendor shorthand flags (-claude, -codex, -deepseek) to --agent-command.
77
+ if (args.options.claude)
78
+ args.options["agent-command"] = "builtin:claude";
79
+ if (args.options.codex)
80
+ args.options["agent-command"] = "builtin:codex";
81
+ if (args.options.deepseek)
82
+ args.options["agent-command"] = "builtin:deepseek";
83
+ // Bare -q / --question -> redirect to quickstart (auto-detect repo/agent/app).
84
+ // CONSUME the positional (shift) so the question never survives as positionals[0]
85
+ // — otherwise the quickstart handler reads it as the app id ("Workflow app not found").
86
+ if (args.command === "-q" || args.command === "--question") {
87
+ if (!args.options.question && args.positionals[0])
88
+ args.options.question = args.positionals.shift();
89
+ args.command = "quickstart";
90
+ }
91
+ else if (!args.command && typeof args.options.question === "string") {
92
+ args.command = "quickstart";
93
+ }
29
94
  const runner = new orchestrator_1.CoolWorkflowRunner({
30
95
  pluginRoot: node_path_1.default.resolve(__dirname, "../..")
31
96
  });
@@ -34,8 +99,31 @@ async function runCli(argv = process.argv.slice(2)) {
34
99
  switch (args.command) {
35
100
  case "help":
36
101
  case undefined:
37
- process.stdout.write((0, orchestrator_1.formatHelp)());
102
+ process.stdout.write((0, orchestrator_1.formatHelp)() + "\n");
103
+ return;
104
+ case "version":
105
+ process.stdout.write(`${version_1.CURRENT_COOL_WORKFLOW_VERSION}\n`);
38
106
  return;
107
+ case "update": {
108
+ process.stderr.write("Updating cool-workflow...\n");
109
+ const npm = (0, node_child_process_1.spawnSync)("npm", ["update", "-g", "cool-workflow"], { encoding: "utf8", stdio: "inherit" });
110
+ if (npm.status !== 0) {
111
+ process.stderr.write("Update failed, trying install...\n");
112
+ const install = (0, node_child_process_1.spawnSync)("npm", ["install", "-g", "cool-workflow@latest"], { encoding: "utf8", stdio: "inherit" });
113
+ if (install.status !== 0) {
114
+ process.stderr.write("Install failed. Check npm and try again.\n");
115
+ process.exitCode = 1;
116
+ }
117
+ }
118
+ return;
119
+ }
120
+ case "fix": {
121
+ const report = (0, doctor_1.runDoctor)(args.options, process.env, String(args.options.cwd || process.cwd()));
122
+ process.stdout.write(`${(0, doctor_1.formatDoctorFixes)(report)}\n`);
123
+ if (!report.ok)
124
+ process.exitCode = 1;
125
+ return;
126
+ }
39
127
  case "list":
40
128
  printJson(runner.listWorkflows());
41
129
  return;
@@ -144,6 +232,7 @@ async function runCli(argv = process.argv.slice(2)) {
144
232
  // fails closed (status=blocked) when none is set. No new executor/scheduler.
145
233
  const [appId] = args.positionals;
146
234
  const runId = optionalArg(args.options.run) || optionalArg(args.options.runId);
235
+ await promptQuestion(args.options);
147
236
  const qs = (0, capability_core_1.quickstart)(runner, { ...args.options, ...(appId ? { appId } : {}), ...(runId ? { runId } : {}) });
148
237
  printJson(qs);
149
238
  const qr = qs;
@@ -1202,7 +1291,7 @@ async function runCli(argv = process.argv.slice(2)) {
1202
1291
  return;
1203
1292
  }
1204
1293
  default:
1205
- throw new Error("Usage: cw.js run search|list|show|resume|archive|rerun|drive|export|import|verify-import|inspect-archive [run-id|archive] [--scope repo|home] [--json] | cw.js run <app> --drive [--once] [--repo R --question Q]");
1294
+ throw new Error("Usage: cw.js run search|list|show|resume|archive|rerun|drive|export|import|verify-import|inspect-archive [run-id|archive] [--scope repo|home] [--json] | cw.js run <app> --drive [--once] [--incremental] [--repo R --question Q]");
1206
1295
  }
1207
1296
  }
1208
1297
  case "queue": {
@@ -1419,6 +1508,20 @@ function printJson(value) {
1419
1508
  function wantsJson(options) {
1420
1509
  return Boolean(options.json || options.format === "json");
1421
1510
  }
1511
+ /** Prompt the user for a question interactively when --question is missing on a TTY. */
1512
+ async function promptQuestion(options) {
1513
+ if (options.question || !process.stdin.isTTY)
1514
+ return;
1515
+ const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
1516
+ return new Promise((resolve) => {
1517
+ rl.question("Question: ", (answer) => {
1518
+ rl.close();
1519
+ if (answer.trim())
1520
+ options.question = answer.trim();
1521
+ resolve();
1522
+ });
1523
+ });
1524
+ }
1422
1525
  function formatWorkbenchView(view) {
1423
1526
  const lines = [
1424
1527
  `Workbench view ${view.runId} (${view.resolved ? "resolved" : "UNRESOLVED"})`,