cool-workflow 0.1.89 → 0.1.91

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 (56) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codex-plugin/plugin.json +1 -1
  3. package/README.md +42 -1
  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/capability-core.js +151 -9
  11. package/dist/capability-registry.js +6 -0
  12. package/dist/cli/command-surface.js +143 -6
  13. package/dist/cli.js +26 -1
  14. package/dist/clones.js +162 -0
  15. package/dist/drive.js +37 -2
  16. package/dist/mcp/tool-call.js +4 -0
  17. package/dist/mcp/tool-definitions.js +5 -0
  18. package/dist/orchestrator/report.js +6 -0
  19. package/dist/orchestrator.js +15 -4
  20. package/dist/remote-source.js +444 -0
  21. package/dist/reporter.js +67 -0
  22. package/dist/term.js +127 -9
  23. package/dist/version.js +1 -1
  24. package/docs/agent-delegation-drive.7.md +41 -22
  25. package/docs/cli-mcp-parity.7.md +9 -2
  26. package/docs/contract-migration-tooling.7.md +4 -0
  27. package/docs/control-plane-scheduling.7.md +4 -0
  28. package/docs/durable-state-and-locking.7.md +4 -0
  29. package/docs/evidence-adoption-reasoning-chain.7.md +4 -0
  30. package/docs/execution-backends.7.md +4 -0
  31. package/docs/multi-agent-cli-mcp-surface.7.md +4 -0
  32. package/docs/multi-agent-eval-replay-harness.7.md +4 -0
  33. package/docs/multi-agent-operator-ux.7.md +4 -0
  34. package/docs/node-snapshot-diff-replay.7.md +4 -0
  35. package/docs/observability-cost-accounting.7.md +4 -0
  36. package/docs/project-index.md +15 -4
  37. package/docs/real-execution-backends.7.md +4 -0
  38. package/docs/release-and-migration.7.md +4 -0
  39. package/docs/release-tooling.7.md +4 -0
  40. package/docs/remote-source-review.7.md +88 -0
  41. package/docs/run-registry-control-plane.7.md +4 -0
  42. package/docs/run-retention-reclamation.7.md +4 -0
  43. package/docs/state-explosion-management.7.md +4 -0
  44. package/docs/team-collaboration.7.md +4 -0
  45. package/docs/web-desktop-workbench.7.md +4 -0
  46. package/manifest/plugin.manifest.json +1 -1
  47. package/manifest/source-context-profiles.json +1 -1
  48. package/package.json +1 -1
  49. package/scripts/agents/agent-adapter-core.js +137 -3
  50. package/scripts/agents/claude-p-agent.js +24 -15
  51. package/scripts/agents/codex-agent.js +11 -8
  52. package/scripts/agents/gemini-agent.js +11 -8
  53. package/scripts/agents/opencode-agent.js +11 -8
  54. package/scripts/canonical-apps.js +4 -4
  55. package/scripts/dogfood-release.js +1 -1
  56. package/scripts/golden-path.js +4 -4
package/dist/term.js CHANGED
@@ -16,10 +16,29 @@ exports.cyan = cyan;
16
16
  exports.doctorGlyph = doctorGlyph;
17
17
  exports.cwLabel = cwLabel;
18
18
  exports.indent = indent;
19
+ exports.nextHint = nextHint;
20
+ exports.tryHint = tryHint;
21
+ exports.sectionHeader = sectionHeader;
22
+ exports.phaseProgressLine = phaseProgressLine;
23
+ exports.formatDuration = formatDuration;
19
24
  exports.printSuccessSummary = printSuccessSummary;
25
+ exports.stripAnsi = stripAnsi;
26
+ exports.visibleWidth = visibleWidth;
27
+ exports.truncate = truncate;
28
+ exports.formatFindingsSummary = formatFindingsSummary;
20
29
  function isTTY(stream = process.stderr) {
21
30
  return Boolean(stream.isTTY);
22
31
  }
32
+ /** Whether to emit ANSI color on a stream, honoring the de-facto env standards:
33
+ * NO_COLOR / CW_NO_COLOR (any non-empty value) disable; FORCE_COLOR (non-"0") forces on
34
+ * even when piped; otherwise fall back to isTTY. The `--no-color` flag sets CW_NO_COLOR. */
35
+ function colorEnabled(stream, env = process.env) {
36
+ if ((env.NO_COLOR ?? "") !== "" || (env.CW_NO_COLOR ?? "") !== "")
37
+ return false;
38
+ if (env.FORCE_COLOR !== undefined && env.FORCE_COLOR !== "" && env.FORCE_COLOR !== "0")
39
+ return true;
40
+ return isTTY(stream);
41
+ }
23
42
  // ---- ansi codes ----
24
43
  const ansi = {
25
44
  reset: "\x1b[0m",
@@ -32,7 +51,7 @@ const ansi = {
32
51
  };
33
52
  // ---- styled text ----
34
53
  function style(code, text, stream) {
35
- if (!isTTY(stream))
54
+ if (!colorEnabled(stream))
36
55
  return text;
37
56
  return `${code}${text}${ansi.reset}`;
38
57
  }
@@ -74,20 +93,119 @@ function indent(text, spaces = 2) {
74
93
  const prefix = " ".repeat(spaces);
75
94
  return text.split("\n").map((line) => `${prefix}${line}`).join("\n");
76
95
  }
77
- /** Print a success summary to stderr (TTY-gated). Shows the report path and a
78
- * suggested next command. Pipe-friendly: silent when stderr is not a TTY. */
96
+ /** A `Next: <cmd>` hint line (the command stays plain so it is copy-pasteable). */
97
+ function nextHint(cmd, stream) {
98
+ return `${dim("Next:", stream)} ${cmd}`;
99
+ }
100
+ /** A `Try: <cmd>` recovery hint (brew-style; the command stays plain to copy). */
101
+ function tryHint(cmd, stream) {
102
+ return `${dim("Try:", stream)} ${cmd}`;
103
+ }
104
+ /** A `==> Title` section header (brew-style). */
105
+ function sectionHeader(title, stream) {
106
+ return `${bold("==>", stream)} ${title}`;
107
+ }
108
+ /** A phase-progress line: `==> Map ✓ (6/6)` / `==> Assess … (3/6)`. Parallel phases
109
+ * use ⇉, sequential use …; a finished phase uses a green ✓. */
110
+ function phaseProgressLine(name, done, total, mode, stream) {
111
+ const complete = total > 0 && done >= total;
112
+ const glyph = complete ? green("✓", stream) : (mode === "parallel" ? "⇉" : "…");
113
+ const count = total > 0 ? ` (${done}/${total})` : "";
114
+ return `${sectionHeader(name, stream)} ${glyph}${count}`;
115
+ }
116
+ /** Format a DURATION in ms as `850ms` / `5.2s` / `1m02s`. Pure (no clock) — the
117
+ * caller measures elapsed via process.hrtime, so this never reads wall-clock time. */
118
+ function formatDuration(ms) {
119
+ if (ms < 1000)
120
+ return `${Math.max(0, Math.round(ms))}ms`;
121
+ const s = Math.round(ms / 100) / 10;
122
+ if (s < 60)
123
+ return `${s}s`;
124
+ const m = Math.floor(s / 60);
125
+ const rem = Math.round(s % 60);
126
+ return `${m}m${String(rem).padStart(2, "0")}s`;
127
+ }
128
+ /** Print a success summary to stderr (TTY-gated). Shows the report path, a one-line
129
+ * status (with N/N worker counts when known), and a copy-pasteable next/recovery
130
+ * command. Pipe-friendly: silent when stderr is not a TTY, so it never pollutes
131
+ * piped/`--json` stdout. A non-complete run with no agent configured gets a brew-style
132
+ * `Try: cw doctor` recovery line; otherwise `Next: cw status <id>` to inspect. */
79
133
  function printSuccessSummary(fields, stream) {
80
134
  if (!isTTY(stream))
81
135
  return;
82
136
  const s = stream || process.stderr;
83
- s.write(`\n${green("")} Report: ${fields.reportPath}\n`);
137
+ const counts = (typeof fields.completedWorkers === "number" && typeof fields.plannedWorkers === "number")
138
+ ? ` — ${fields.completedWorkers}/${fields.plannedWorkers}` : "";
139
+ s.write(`\n${green("✓", s)} Report: ${fields.reportPath}\n`);
84
140
  if (fields.status === "complete") {
85
- s.write(` Next: cw status ${fields.runId} --brief\n`);
86
- if (fields.bundle !== false) {
87
- s.write(` Bundle: cw report bundle ${fields.runId}\n`);
88
- }
141
+ s.write(` ${green("✓", s)} Status: complete${counts}\n`);
142
+ s.write(` ${nextHint(`cw report ${fields.runId} --show`, s)}\n`);
89
143
  }
90
144
  else {
91
- s.write(` ${yellow("!")} Status: ${fields.status}. Next: cw status ${fields.runId}\n`);
145
+ s.write(` ${yellow("!", s)} Status: ${fields.status}${counts}\n`);
146
+ // No agent backend is the #1 first-run blocker — point at the one command that
147
+ // diagnoses and prints the fix, brew-style. Otherwise inspect the run's state.
148
+ if (fields.agentConfigured === false)
149
+ s.write(` ${tryHint("cw doctor", s)}\n`);
150
+ else
151
+ s.write(` ${nextHint(`cw status ${fields.runId}`, s)}\n`);
152
+ }
153
+ }
154
+ // ---- width-aware truncation (zero-dep) ----
155
+ const ANSI_RE = /\x1b\[[0-9;]*m/g;
156
+ /** Strip ANSI SGR codes (for measuring visible width). */
157
+ function stripAnsi(text) {
158
+ return text.replace(ANSI_RE, "");
159
+ }
160
+ /** Visible width of a string, ignoring ANSI. Counts each code point as width 1 — a known
161
+ * minor caveat for wide (CJK/emoji) glyphs, acceptable for one-line status truncation. */
162
+ function visibleWidth(text) {
163
+ return [...stripAnsi(text)].length;
164
+ }
165
+ /** Truncate a (possibly styled) string to `maxWidth` visible columns, appending `…` when cut.
166
+ * Operates on the PLAIN text (callers truncate before styling), so no ANSI is split. */
167
+ function truncate(text, maxWidth) {
168
+ if (maxWidth <= 0)
169
+ return "";
170
+ const chars = [...stripAnsi(text)];
171
+ if (chars.length <= maxWidth)
172
+ return text;
173
+ if (maxWidth === 1)
174
+ return "…";
175
+ return `${chars.slice(0, maxWidth - 1).join("")}…`;
176
+ }
177
+ // ---- findings summary table (end-of-run, compact) ----
178
+ /** Severity order for sorting + counting (most severe first). */
179
+ const SEVERITY_ORDER = ["P0", "P1", "P2", "P3", "none"];
180
+ /** Render a compact findings summary assembled from the run's `cw:result` blocks: a one-line
181
+ * count headline (e.g. `Findings: 3 — 2×P1, 1×P2`) plus a small id/severity/class table. This
182
+ * is the end-of-run summary — NOT the full prose (that stays in report.md + the transcript).
183
+ * Returns "" when there are no findings (caller prints nothing). */
184
+ function formatFindingsSummary(findings, stream) {
185
+ if (!findings.length)
186
+ return "";
187
+ const bySev = new Map();
188
+ for (const f of findings)
189
+ bySev.set(f.severity || "none", (bySev.get(f.severity || "none") || 0) + 1);
190
+ const order = (s) => {
191
+ const i = SEVERITY_ORDER.indexOf(s);
192
+ return i === -1 ? SEVERITY_ORDER.length : i;
193
+ };
194
+ const counts = [...bySev.entries()]
195
+ .sort((a, b) => order(a[0]) - order(b[0]))
196
+ .map(([sev, n]) => `${n}×${sev}`)
197
+ .join(", ");
198
+ const rows = [...findings].sort((a, b) => order(a.severity) - order(b.severity));
199
+ const sevW = Math.max(8, ...rows.map((r) => (r.severity || "none").length));
200
+ const clsW = Math.max(5, ...rows.map((r) => (r.classification || "unknown").length));
201
+ const lines = [
202
+ `${bold("Findings:", stream)} ${findings.length} — ${counts}`,
203
+ dim(` ${"SEVERITY".padEnd(sevW)} ${"CLASS".padEnd(clsW)} ID`, stream)
204
+ ];
205
+ for (const r of rows) {
206
+ const sev = (r.severity || "none").padEnd(sevW);
207
+ const cls = (r.classification || "unknown").padEnd(clsW);
208
+ lines.push(` ${sev} ${cls} ${truncate(r.id || "(unnamed)", 60)}`);
92
209
  }
210
+ return lines.join("\n");
93
211
  }
package/dist/version.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MIN_SUPPORTED_RUN_STATE_SCHEMA_VERSION = exports.LEGACY_RUN_STATE_SCHEMA_VERSION = exports.CURRENT_RUN_STATE_SCHEMA_VERSION = exports.WORKFLOW_APP_SCHEMA_VERSION = exports.CURRENT_COOL_WORKFLOW_VERSION = void 0;
4
- exports.CURRENT_COOL_WORKFLOW_VERSION = "0.1.89";
4
+ exports.CURRENT_COOL_WORKFLOW_VERSION = "0.1.91";
5
5
  exports.WORKFLOW_APP_SCHEMA_VERSION = 1;
6
6
  exports.CURRENT_RUN_STATE_SCHEMA_VERSION = 1;
7
7
  exports.LEGACY_RUN_STATE_SCHEMA_VERSION = 0;
@@ -198,28 +198,43 @@ string). Each verb is declared once in `capability-registry.ts`, so `cw <cmd>
198
198
  --json` is byte-identical to the matching `cw_<tool>` MCP tool for the read-only
199
199
  preview/config-show verbs.
200
200
 
201
- ## Live output — opt-in stderr passthrough (Unix-clean)
202
-
203
- A drive can show the agent's activity live, without touching the evidence
204
- contract, when the operator opts in with `CW_AGENT_STREAM=1`:
205
-
206
- - **Default stays buffered.** Without `CW_AGENT_STREAM=1`, the bundled wrapper
207
- keeps the buffered path and writes one JSON report to stdout after writing
208
- `result.md`.
209
- - **The opt-in wrapper renders; stderr only.** With `CW_AGENT_STREAM=1`, the
210
- bundled Claude wrapper runs claude in `--output-format stream-json`, and the
211
- bundled Codex wrapper runs `codex exec --json --output-last-message`.
212
- Each wrapper renders a short human trace (tool uses, assistant text, per-turn
213
- summaries where present) to its **stderr**diagnostics, never data. It builds
214
- the single `{model, usage, result}` object for stdout after the final answer is
215
- captured.
216
- - **Core forwards, never parses.** `runAgentProcess` passes the agent child's
217
- stderr straight through to the operator's terminal (`stdio` inherit) only when
218
- `CW_AGENT_STREAM=1`, CW's own stderr is a TTY, and `CW_NO_STREAM` is not set.
219
- Piped / CI runs stay quiet (the Rule of Silence). Vendor-specific rendering
220
- lives in the wrapper (policy), not the kernel (mechanism).
221
- - **Determinism intact.** The backend evidence triple hashes stdout only, so
222
- the live stderr stream never changes recorded evidence or replay.
201
+ ## Live output — a calm live view, on stderr, Unix-clean
202
+
203
+ A drive shows the agent's activity live without ever touching the evidence
204
+ contract. The async per-vendor wrapper owns the live region (it parses
205
+ `--output-format stream-json` and its event loop is free); cw renders the calm
206
+ orchestration between agents plus the end-of-run summary. **Everything goes to
207
+ stderr stdout stays the byte-exact data channel** (the `cw:result` fence, the
208
+ wrapper's `{model, usage, result}` JSON, cw's `--json` payload), so a pipe is
209
+ never polluted.
210
+
211
+ - **Interactive (TTY).** The wrapper renders ONE in-place status line: a Braille
212
+ spinner + the current action + elapsed (e.g. `⠹ Read app.js 1.2s`). Tool calls
213
+ fold to a single line eachspinning while running, then resolving to
214
+ `✓ Read app.js (0.3s)` / `✗ Bash (1.1s)` (dimmed, args width-truncated). The
215
+ cursor is hidden while the spinner runs and **ALWAYS restored** on exit /
216
+ Ctrl-C / SIGTERM (Ctrl-C exits non-zero, leaving a clean terminal).
217
+ - **Non-TTY stays SILENT by default** (the Rule of Silence). `CW_AGENT_STREAM=1`
218
+ opts a CI/piped run into a **plain append-only** trace (`→ …` / `✓ … (Xs)`
219
+ lines, zero ANSI/cursor bytes) for debuggability mirroring `CW_DRIVE_PROGRESS=1`.
220
+ - **Verbosity.** Default is compact: the current action + folded tool lines, with
221
+ the model's narration/reasoning HIDDEN. `--verbose` (sets `CW_VERBOSE=1`)
222
+ surfaces the full narration inline; `--full` (sets `CW_OUTPUT=full`) implies
223
+ verbose AND prints the report inline at run end.
224
+ - **Transcript always on disk.** Regardless of verbosity — even when the screen
225
+ view is silent or compact — the wrapper writes the COMPLETE narration + tool I/O
226
+ to `transcript.md` next to that worker's `result.md`. The end-of-run summary
227
+ prints the run dir where the transcripts live, so nothing is ever lost to a
228
+ compact view.
229
+ - **Color control.** `NO_COLOR` / `CW_NO_COLOR` (the `--no-color` flag sets the
230
+ latter) disable ANSI; `FORCE_COLOR` forces it even when piped; otherwise color
231
+ follows isTTY. Honored identically by cw (`term.ts`) and every wrapper.
232
+ - **End-of-run summary (cw side).** A COMPACT findings table — id / severity /
233
+ classification + counts, re-parsed from each completed worker's `cw:result` —
234
+ plus the report path, status, and run dir. NOT the full prose (that stays in
235
+ `report.md` + the transcript); `--full` also prints the report inline.
236
+ - **Determinism intact.** The backend evidence triple hashes stdout only, so the
237
+ live stderr view never changes recorded evidence or replay.
223
238
 
224
239
  The built-in templates are:
225
240
 
@@ -317,3 +332,7 @@ Orchestration-parity for the agent drive: `run --drive --incremental` step-level
317
332
  ## 0.1.89 (v0.1.89)
318
333
 
319
334
  The one-command `cw -q` headline now routes the question and defaults the repo to the caller cwd before driving the agent; the delegation contract, drive, and accept path are unchanged.
335
+
336
+ 0.1.90
337
+
338
+ 0.1.91
@@ -82,7 +82,7 @@ relationship. `identical` means `cw <cmd> --json` is equal to the `cw_<tool>`
82
82
  payload; `projected` means a declared divergence with a reason; `cli-only` marks
83
83
  a surface-specific capability with a recorded reason. The matrix is
84
84
  <!-- gen:parity:count -->
85
- machine-complete by design: 199 capabilities, 186 MCP tools.
85
+ machine-complete by design: 201 capabilities, 188 MCP tools.
86
86
  <!-- /gen:parity:count -->
87
87
 
88
88
  <!-- gen:parity:table -->
@@ -272,6 +272,8 @@ machine-complete by design: 199 capabilities, 186 MCP tools.
272
272
  | `gc.plan` | `cw gc plan` | `cw_gc_plan` | `gcPlan` | both | identical |
273
273
  | `gc.run` | `cw gc run` | `cw_gc_run` | `gcRun` | both | projected |
274
274
  | `gc.verify` | `cw gc verify` | `cw_gc_verify` | `gcVerify` | both | identical |
275
+ | `clones.list` | `cw clones list` | `cw_clones_list` | `listClones` | both | identical |
276
+ | `clones.gc` | `cw clones gc` | `cw_clones_gc` | `gcClones` | both | projected |
275
277
  | `telemetry.verify` | `cw telemetry verify` | `cw_telemetry_verify` | `telemetryVerify` | both | identical |
276
278
  | `demo.tamper` | `cw demo tamper` | `—` | `demoTamper` | cli-only | cli-only |
277
279
  | `demo.bundle` | `cw demo bundle` | `—` | `demoBundle` | cli-only | cli-only |
@@ -319,12 +321,13 @@ carry a recorded reason in the registry.
319
321
  <!-- /gen:parity:cliOnly -->
320
322
 
321
323
  <!-- gen:parity:projected -->
322
- Five capabilities are payload-divergent on purpose (`projected`):
324
+ Six capabilities are payload-divergent on purpose (`projected`):
323
325
 
324
326
  - `commit` — Both surfaces route through the single core entry runner.commit. The CLI emits the raw StateCommitResult for scripting (commit.id, commit.evidence, commit.gate, commit.acceptanceRationale); cw_commit emits the operator commit envelope (commitId, verifierGated, checkpoint, evidenceCount, snapshotPath, nextActions, plus the raw result under `commit`). Declared projection via capability-core.commitEnvelope, not drift.
325
327
  - `backend.agent.config.set` — Mutating: persists $CW_HOME/agent-config.json (secret-stripped) before returning the effective config; both surfaces perform the same write — it is a surface-mutating verb, not a read probe.
326
328
  - `run.drive.step` — Mutating: advances the run by spawning the external agent per worker and recording attested output — not a read probe. CLI (--drive/--step) and MCP route through the same drive() core.
327
329
  - `gc.run` — Mutating: frees disk and appends a tombstone; both surfaces perform the identical transaction but the payload reports now-derived bytesFreed/tombstone.
330
+ - `clones.gc` — Mutating: removes cache directories and reports now-derived freedBytes/removed; both surfaces perform the identical reclamation.
328
331
  - `workbench.serve` — Both surfaces route through the single core entry buildWorkbenchServeDescriptor and return the IDENTICAL serve descriptor under `cw workbench serve --json`/`--once` and `cw_workbench_serve`. They diverge only in side effect, not payload: the CLI's default `cw workbench serve` (no --once) additionally STARTS the blocking localhost host (like `schedule daemon`), which an MCP stdio host cannot do, so cw_workbench_serve only ever returns the descriptor. Declared divergence, not drift.
329
332
  <!-- /gen:parity:projected -->
330
333
 
@@ -521,3 +524,7 @@ CLI surface simplified to 6 commands with agent stderr streaming on by default a
521
524
  ## 0.1.89 (v0.1.89)
522
525
 
523
526
  CLI golden-path fixes: `cw -q "…"` routes the question (was read as an app id → "Workflow app not found"), auto-detects the cwd as the repo (run anywhere, no `--repo`), and `cw help` wraps its command list with a trailing newline; the CLI↔MCP parity contract and the help-token parser are unchanged.
527
+
528
+ 0.1.90
529
+
530
+ 0.1.91
@@ -157,3 +157,7 @@ _No behavioral change in v0.1.88 (no schema-migration edge was added; the increm
157
157
  ## 0.1.89 (v0.1.89)
158
158
 
159
159
  _No behavioral change in v0.1.89 (CLI-surface golden-path + help-output fixes only; this subsystem is unchanged)._
160
+
161
+ 0.1.90
162
+
163
+ 0.1.91
@@ -141,3 +141,7 @@ _No behavioral change in v0.1.88 (the `sched` priority/readiness selection, conc
141
141
  ## 0.1.89 (v0.1.89)
142
142
 
143
143
  _No behavioral change in v0.1.89 (CLI-surface golden-path + help-output fixes only; this subsystem is unchanged)._
144
+
145
+ 0.1.90
146
+
147
+ 0.1.91
@@ -140,3 +140,7 @@ _No behavioral change in v0.1.88 (atomic writes, fsync-durability for audit-esse
140
140
  ## 0.1.89 (v0.1.89)
141
141
 
142
142
  _No behavioral change in v0.1.89 (CLI-surface golden-path + help-output fixes only; this subsystem is unchanged)._
143
+
144
+ 0.1.90
145
+
146
+ 0.1.91
@@ -301,3 +301,7 @@ _No behavioral change in v0.1.88 (the evidence adoption reasoning chain and its
301
301
  ## 0.1.89 (v0.1.89)
302
302
 
303
303
  _No behavioral change in v0.1.89 (CLI-surface golden-path + help-output fixes only; this subsystem is unchanged)._
304
+
305
+ 0.1.90
306
+
307
+ 0.1.91
@@ -331,3 +331,7 @@ Agent stderr live-streaming is now on by default when stderr is a TTY (CW_AGENT_
331
331
  ## 0.1.89 (v0.1.89)
332
332
 
333
333
  _No behavioral change in v0.1.89 (CLI-surface golden-path + help-output fixes only; this subsystem is unchanged)._
334
+
335
+ 0.1.90
336
+
337
+ 0.1.91
@@ -299,3 +299,7 @@ The host-facing surface tracks the CLI simplification to 6 commands (streaming o
299
299
  ## 0.1.89 (v0.1.89)
300
300
 
301
301
  The host-facing surface tracks the CLI golden-path fixes (`cw -q` routing + repo auto-detect + clean help); the multi-agent verbs and their MCP-tool mirrors are unchanged.
302
+
303
+ 0.1.90
304
+
305
+ 0.1.91
@@ -333,3 +333,7 @@ _No change in behavior in v0.1.88 (no harness code changed; the new `loop-contro
333
333
  ## 0.1.89 (v0.1.89)
334
334
 
335
335
  _No behavioral change in v0.1.89 (CLI-surface golden-path + help-output fixes only; this subsystem is unchanged)._
336
+
337
+ 0.1.90
338
+
339
+ 0.1.91
@@ -345,3 +345,7 @@ _No behavioral change in v0.1.88 (no operator-view code changed; the new sub-wor
345
345
  ## 0.1.89 (v0.1.89)
346
346
 
347
347
  _No behavioral change in v0.1.89 (CLI-surface golden-path + help-output fixes only; this subsystem is unchanged)._
348
+
349
+ 0.1.90
350
+
351
+ 0.1.91
@@ -166,3 +166,7 @@ A new `loop-control` StateNodeKind now flows through per-node snapshot/diff/repl
166
166
  ## 0.1.89 (v0.1.89)
167
167
 
168
168
  _No behavioral change in v0.1.89 (CLI-surface golden-path + help-output fixes only; this subsystem is unchanged)._
169
+
170
+ 0.1.90
171
+
172
+ 0.1.91
@@ -225,3 +225,7 @@ Attestation now signs the agent's RESULT, not just its usage: `TelemetryAttestat
225
225
  ## 0.1.89 (v0.1.89)
226
226
 
227
227
  _No behavioral change in v0.1.89 (CLI-surface golden-path + help-output fixes only; this subsystem is unchanged)._
228
+
229
+ 0.1.90
230
+
231
+ 0.1.91
@@ -5,11 +5,11 @@ Generated from the current repository code on 2026-06-21 by `npm run sync:projec
5
5
  ## Snapshot
6
6
 
7
7
  - Package: `cool-workflow`
8
- - Version: `0.1.89`
9
- - Source modules: `65`
8
+ - Version: `0.1.91`
9
+ - Source modules: `68`
10
10
  - Workflow apps: `7`
11
- - Docs: `52`
12
- - Smoke tests: `130`
11
+ - Docs: `53`
12
+ - Smoke tests: `137`
13
13
  - Repository: https://github.com/coo1white/cool-workflow
14
14
 
15
15
  ## Architecture
@@ -83,6 +83,7 @@ multi-agent host -> topology -> blackboard/coordinator
83
83
  - [agent-config.ts](../src/agent-config.ts)
84
84
  - [capability-core.ts](../src/capability-core.ts)
85
85
  - [capability-registry.ts](../src/capability-registry.ts)
86
+ - [clones.ts](../src/clones.ts)
86
87
  - [collaboration.ts](../src/collaboration.ts)
87
88
  - [compare.ts](../src/compare.ts)
88
89
  - [contract-migration.ts](../src/contract-migration.ts)
@@ -102,6 +103,8 @@ multi-agent host -> topology -> blackboard/coordinator
102
103
  - [observability.ts](../src/observability.ts)
103
104
  - [onramp.ts](../src/onramp.ts)
104
105
  - [reclamation.ts](../src/reclamation.ts)
106
+ - [remote-source.ts](../src/remote-source.ts)
107
+ - [reporter.ts](../src/reporter.ts)
105
108
  - [result-normalize.ts](../src/result-normalize.ts)
106
109
  - [run-export.ts](../src/run-export.ts)
107
110
  - [run-registry.ts](../src/run-registry.ts)
@@ -166,6 +169,7 @@ multi-agent host -> topology -> blackboard/coordinator
166
169
  - [Release And Migration Discipline](release-and-migration.7.md)
167
170
  - [Cool Workflow Release History](release-history.md)
168
171
  - [Release Tooling](release-tooling.7.md)
172
+ - [Remote-Source Review (`--link`)](remote-source-review.7.md)
169
173
  - [Verifiable Report Bundle](report-verifiable-bundle.7.md)
170
174
  - [Routines](routines.md)
171
175
  - [Run Registry / Control Plane](run-registry-control-plane.7.md)
@@ -203,9 +207,14 @@ Smoke tests mirror the public contracts. The high-signal suites are:
203
207
  - [candidate-scoring-smoke.js](../test/candidate-scoring-smoke.js)
204
208
  - [canonical-workflow-apps-smoke.js](../test/canonical-workflow-apps-smoke.js)
205
209
  - [claude-p-agent-wrapper-smoke.js](../test/claude-p-agent-wrapper-smoke.js)
210
+ - [cli-arg-parsing-smoke.js](../test/cli-arg-parsing-smoke.js)
206
211
  - [cli-command-surface-smoke.js](../test/cli-command-surface-smoke.js)
207
212
  - [cli-jsonmode-parity-smoke.js](../test/cli-jsonmode-parity-smoke.js)
208
213
  - [cli-mcp-parity-smoke.js](../test/cli-mcp-parity-smoke.js)
214
+ - [cli-progress-summary-smoke.js](../test/cli-progress-summary-smoke.js)
215
+ - [cli-recoverable-errors-smoke.js](../test/cli-recoverable-errors-smoke.js)
216
+ - [cli-render-smoke.js](../test/cli-render-smoke.js)
217
+ - [clones-gc-smoke.js](../test/clones-gc-smoke.js)
209
218
  - [codex-agent-wrapper-smoke.js](../test/codex-agent-wrapper-smoke.js)
210
219
  - [concurrency-default-smoke.js](../test/concurrency-default-smoke.js)
211
220
  - [concurrent-failure-semantics-smoke.js](../test/concurrent-failure-semantics-smoke.js)
@@ -272,6 +281,8 @@ Smoke tests mirror the public contracts. The high-signal suites are:
272
281
  - [release-flow-smoke.js](../test/release-flow-smoke.js)
273
282
  - [release-gate-smoke.js](../test/release-gate-smoke.js)
274
283
  - [release-tooling-smoke.js](../test/release-tooling-smoke.js)
284
+ - [remote-link-archive-smoke.js](../test/remote-link-archive-smoke.js)
285
+ - [remote-link-git-smoke.js](../test/remote-link-git-smoke.js)
275
286
  - [report-bundle-smoke.js](../test/report-bundle-smoke.js)
276
287
  - [report-verify-bundle-smoke.js](../test/report-verify-bundle-smoke.js)
277
288
  - [result-normalize-smoke.js](../test/result-normalize-smoke.js)
@@ -173,3 +173,7 @@ _No behavioral change in v0.1.88 (the container/remote/ci delegating integration
173
173
  ## 0.1.89 (v0.1.89)
174
174
 
175
175
  _No behavioral change in v0.1.89 (CLI-surface golden-path + help-output fixes only; this subsystem is unchanged)._
176
+
177
+ 0.1.90
178
+
179
+ 0.1.91
@@ -313,3 +313,7 @@ _No behavioral change in v0.1.88 (`release:check` and the durable run-state comp
313
313
  ## 0.1.89 (v0.1.89)
314
314
 
315
315
  _No behavioral change in v0.1.89 (CLI-surface golden-path + help-output fixes only; this subsystem is unchanged)._
316
+
317
+ 0.1.90
318
+
319
+ 0.1.91
@@ -251,3 +251,7 @@ The release flow now captures the reviewer's verdict from agent stdout (`release
251
251
  ## 0.1.89 (v0.1.89)
252
252
 
253
253
  _No behavioral change in v0.1.89 (CLI-surface golden-path + help-output fixes only; this subsystem is unchanged)._
254
+
255
+ 0.1.90
256
+
257
+ 0.1.91
@@ -0,0 +1,88 @@
1
+ # Remote-Source Review (`--link`)
2
+
3
+ CW v0.1.91 lets you point a review at **any repository on the internet** instead
4
+ of only a local path: `cw -q "what are the risks?" --link <url>`. CW materializes
5
+ the remote into a local checkout and runs the **existing** review pipeline against
6
+ it — identical downstream to reviewing a folder. A URL passed to `-dir`/`--repo`
7
+ is auto-detected, so `--link <url>` and `-dir <url>` are equivalent.
8
+
9
+ ```bash
10
+ cw -q "What are the risks?" --link https://github.com/owner/repo
11
+ cw -q "What are the risks?" --link git@gitlab.com:owner/repo.git --ref v1.2.0
12
+ cw -q "What are the risks?" --link https://github.com/owner/repo/archive/refs/heads/main.tar.gz
13
+ cw -q "..." --link <url> --check # validate the URL + tooling WITHOUT fetching
14
+ ```
15
+
16
+ ## Sources
17
+
18
+ - **Git repositories**, any host: `https://`, `http://`, `ssh://`, `git://`, the
19
+ scp-style `git@host:owner/repo`, and `file://`. Cloned shallow (`--depth 1
20
+ --single-branch`); `--ref <branch|tag>` selects a ref. `commit` is the resolved
21
+ `HEAD` SHA.
22
+ - **Downloadable archives**: `.tar.gz` / `.tgz` / `.tar` / `.zip` (e.g. a GitHub
23
+ "Download ZIP" / codeload tarball). Fetched, extracted, and `git init`-snapshotted
24
+ into a local repo so the git-tracked source-context reader works unchanged.
25
+ `commit` is the **sha256 of the downloaded bytes** (a content address — there is
26
+ no git SHA).
27
+
28
+ ## The red line — materialize source, do not internalize execution
29
+
30
+ `--link` only materializes the **source** to review. CW still **DELEGATES** worker
31
+ execution to the operator's configured agent backend (`claude -p`, `codex exec`, an
32
+ HTTP endpoint) exactly as a local review does; it never executes a model itself.
33
+ Cloning is non-deterministic network I/O, so it happens in the **capability layer**
34
+ (before `plan`), never in the replay-deterministic orchestrator core — which only
35
+ ever sees the resulting local path.
36
+
37
+ ## Provenance — where the code came from, tamper-evidently
38
+
39
+ The sanitized origin rides through three surfaces:
40
+
41
+ - `run.inputs` → a `- Source: <url>@<commit>` line in `report.md`.
42
+ - the `--json` result's `remote { url, commit, kind, ref, cached }`.
43
+ - a hash-chained `source.clone` / `source.download` **trust-audit event** that
44
+ `cw audit verify <run-id>` re-proves — editing the recorded origin is detectable.
45
+
46
+ Credentials in a URL (`https://user:token@host/…`) are stripped before the URL is
47
+ used as a cache key, printed, persisted, or recorded; the raw URL reaches only a
48
+ single `git` argv element. Git/download diagnostics are credential-redacted before
49
+ they are ever surfaced.
50
+
51
+ ## Fail closed
52
+
53
+ A bad URL, a blocked scheme, a network failure, or a credential-less private repo
54
+ produces an **explicit error and a non-zero exit** — never a fabricated review,
55
+ never a hang on an auth prompt (`GIT_TERMINAL_PROMPT=0`). Hardening:
56
+
57
+ - **Scheme allowlist** (https/http/ssh/git/file); `ext::`/`fd::` transport helpers
58
+ and `-`-leading option-injection are rejected; the URL is always a separate argv
59
+ element (never a shell string); repo hooks are disabled (`-c core.hooksPath=`).
60
+ - **Archive extraction** validates the entry listing for `..`/absolute traversal
61
+ BEFORE extracting, **rejects symlink/non-regular entries** (walked with `lstat`),
62
+ and bounds the decompression bomb by **declared** uncompressed size (gzip ISIZE /
63
+ `unzip -l`) before extracting and **actual** size (1 GiB) after.
64
+ - **SSRF**: http(s) redirects are followed manually and each hop is re-validated
65
+ (http(s) scheme + no private/loopback/link-local host) before connecting — a
66
+ public URL cannot redirect CW into an internal service.
67
+
68
+ ## Cache — `cw clones`
69
+
70
+ Checkouts are cached, content-addressed, under
71
+ `~/.local/state/cool-workflow/clones/<hash>/` (honoring `CW_HOME`/`XDG_STATE_HOME`)
72
+ and reused on the next question; `--refresh` re-fetches. Manage the cache:
73
+
74
+ ```bash
75
+ cw clones list # origin url, kind, commit, age, bytes
76
+ cw clones gc --older-than-days 30 # reclaim checkouts older than N days
77
+ cw clones gc --all # reclaim everything
78
+ ```
79
+
80
+ `cw clones gc` deletes only paths it has proven are inside the clones cache (fail
81
+ closed). Both verbs have MCP peers (`cw_clones_list`, `cw_clones_gc`) with
82
+ byte-identical payloads.
83
+
84
+ ## Determinism note
85
+
86
+ The cache is keyed on the URL (+ref), not on content: if a URL's content changes
87
+ upstream, the cached checkout is reused until `--refresh` (mirroring how a git
88
+ clone pins its resolved `HEAD`). Use `--refresh` to re-fetch the latest.
@@ -434,3 +434,7 @@ Security: archive import now refuses path-traversal run ids (`..`/absolute/separ
434
434
  ## 0.1.89 (v0.1.89)
435
435
 
436
436
  _No behavioral change in v0.1.89 (CLI-surface golden-path + help-output fixes only; this subsystem is unchanged)._
437
+
438
+ 0.1.90
439
+
440
+ 0.1.91
@@ -224,3 +224,7 @@ _No behavioral change in v0.1.88 (the tiered, append-only, cryptographically-ver
224
224
  ## 0.1.89 (v0.1.89)
225
225
 
226
226
  _No behavioral change in v0.1.89 (CLI-surface golden-path + help-output fixes only; this subsystem is unchanged)._
227
+
228
+ 0.1.90
229
+
230
+ 0.1.91
@@ -302,3 +302,7 @@ _No behavioral change in v0.1.88 (the summarization/compaction layer and its fai
302
302
  ## 0.1.89 (v0.1.89)
303
303
 
304
304
  _No behavioral change in v0.1.89 (CLI-surface golden-path + help-output fixes only; this subsystem is unchanged)._
305
+
306
+ 0.1.90
307
+
308
+ 0.1.91
@@ -238,3 +238,7 @@ _No behavioral change in v0.1.88 (the host-attested actor, append-only approvals
238
238
  ## 0.1.89 (v0.1.89)
239
239
 
240
240
  _No behavioral change in v0.1.89 (CLI-surface golden-path + help-output fixes only; this subsystem is unchanged)._
241
+
242
+ 0.1.90
243
+
244
+ 0.1.91
@@ -246,3 +246,7 @@ _No behavioral change in v0.1.88 (the five operator surfaces and the registry cr
246
246
  ## 0.1.89 (v0.1.89)
247
247
 
248
248
  _No behavioral change in v0.1.89 (CLI-surface golden-path + help-output fixes only; this subsystem is unchanged)._
249
+
250
+ 0.1.90
251
+
252
+ 0.1.91
@@ -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.89",
5
+ "version": "0.1.91",
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": 44000,
28
+ "maxLines": 48000,
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.89",
3
+ "version": "0.1.91",
4
4
  "bin": {
5
5
  "cool-workflow": "scripts/cw.js",
6
6
  "cw": "scripts/cw.js"