cohorte 1.5.0 → 1.6.0

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/CHANGELOG.md CHANGED
@@ -3,13 +3,97 @@
3
3
  Entries are shown by `/update-pipeline` ("What's new") after a core refresh. Keep them short,
4
4
  user-facing, most recent first. One `## <version> — <YYYY-MM-DD>` section per release.
5
5
 
6
+ ## 1.6.0 — 2026-08-01
7
+
8
+ > **Re-run `npx cohorte@latest update --global` (or `update`)** to pick up the readiness gate, the
9
+ > deferred-findings route, the resumable driver and the decision journal — the update *deletes* the
10
+ > shadowed `/loop` command and the long-dead `/cycle` from your install, it does not just stop
11
+ > shipping them. Existing specs keep working: the new front-matter fields are written on demand, and a
12
+ > spec without them simply isn't resumable yet. **`/loop <id>` is now `/drive <id>`.**
13
+
14
+ - **New — the readiness gate between `/spec` and `/build`.** `/build` §1.6 now scores the frozen spec
15
+ on **implementability** before authoring the contract and before dispatching anything: contract
16
+ shapes complete · every area owned by a surface · named dependencies actually exist · no ambiguity a
17
+ surface would have to guess at · design links present. The verdict goes to
18
+ `specs/reports/<id>.readiness.json` (`READY` · `RESERVATIONS` · `NOT-READY` + `gaps[]`).
19
+ **`NOT-READY` stops the build with zero agents spawned** — a spec that can't be built doesn't get
20
+ cheaper by being built on N surfaces in parallel — and sends you to `/spec`. `RESERVATIONS` never
21
+ blocks: each gap is inlined into the affected surface's dispatch as an assumption the implementer
22
+ applies *and* flags in its handoff. It costs **no extra agent**: the lead already holds the spec,
23
+ the profile and the reconciled surface list.
24
+ - **New — deferred findings: `/review` stops throwing away what isn't blocking.** The review agent
25
+ now returns a separate `## Deferred` section (max 10) for what is real but **out of this feature's
26
+ scope** — pre-existing code the diff never touched, adjacent debt the spec never claims to fix —
27
+ each line carrying its own out-of-scope reason. Deferred items count in no severity row, move no
28
+ verdict, are never cross-checked, and on **every** verdict get routed into
29
+ `specs/refactor-backlog.md` under the owning surface's `## <domain>` heading, tagged
30
+ `deferred:<id>`. So `/review` feeds `/refactor` for free instead of dropping everything
31
+ non-blocking on the floor. Never into `## Remediation`, which is what `/fix` re-dispatches. Not
32
+ deferrable, ever: anything the diff touched, any spec violation, any security issue on a path this
33
+ feature adds or calls. `/audit` now **carries open `deferred:` items over** when it rewrites the
34
+ backlog. The verdict JSON gains `deferred: <n>` (informational, outside `blocking`).
35
+ - **BREAKING — `/loop` is renamed `/drive`, because Claude Code shadowed it.** Claude Code ships its
36
+ own built-in `/loop` (run a prompt on a recurring interval), which won the name: typing
37
+ `/loop <id>` started the *interval runner* with the feature id as its prompt, so cohorte's driver
38
+ never ran — and the session, having never seen `loop.md`, reported a loop that did not exist. Same
39
+ command, same flags, same script (`pipeline/scripts/loop.sh` keeps its name — nothing about your
40
+ install paths changes): type **`/drive <id>`**. The update scrubs the old `commands/loop.md`, so a
41
+ stale shadowed copy can't linger.
42
+ - **`/drive` is resumable — the spec's status is the state machine.** The lifecycle is now
43
+ `draft → frozen → in-progress → in-review → shipped` plus `blocked`. Before every phase the driver
44
+ stamps `status: in-progress` + `loop_pass` + `loop_phase` into the spec's front-matter — plain
45
+ `awk`, a temp file and `mv`, **zero tokens** — and on exit a terminal `in-review` (clean) or
46
+ `blocked`. **`/drive <id> --resume`** then continues at the pass it reached instead of re-paying the
47
+ ones already made, whether the session died, the ceiling hit, or the fix stopped converging.
48
+ `--max` stays a ceiling on the *total* passes. New **exit 4** (`not implementable`) relays the
49
+ readiness gate's `NOT-READY`: the one loop outcome more passes cannot fix. The dashboard's specs
50
+ board gains In-progress and Blocked columns and shows `↻ pass 3 · /review` on the card; `/doctor`
51
+ names any spec left mid-loop.
52
+ - **Fixed — a dead subagent no longer reads as a clean one on the conversational path.** The
53
+ "a dead agent is never a clean result" doctrine existed since 1.3.4 — but only inside the
54
+ **workflows**. `/build`, `/review` and `/fix` had nothing: a subagent that dies (rate limit,
55
+ transport error, exhausted context) returns *nothing*, and nothing was indistinguishable from
56
+ "finished, nothing to report". Concretely, a dead **reviewer** produced zero findings ⇒
57
+ `blocking: 0` ⇒ verdict `SHIP` ⇒ `/drive` exit 0 ⇒ the human sent to `/ship` — a clean bill of
58
+ health on code no agent ever read. Now every fan-out phase does a **roll call** before integrating:
59
+ a silent surface is retried **once** alone (byte-identical prompt, so recovery costs one agent, not
60
+ a rebuild), then `/build` marks it `dead` and verifies the tree with that surface's own quiet
61
+ commands instead of speaking for the agent, `/review` lists it in the verdict's new `unreviewed[]`
62
+ and **refuses to score `SHIP`**, and `/fix` leaves every one of its items `- [ ]` (a dead agent
63
+ never ticks a box). `/build` also writes `specs/reports/<id>.build.json` with `dead[]`, and
64
+ `loop.sh` aborts on either signal with **exit 2** *before* reading `blocking` — because a dead
65
+ reviewer makes `blocking == 0` a statement about unread code. `unreviewed` is deliberately kept
66
+ out of `blocking`: faking a count there would corrupt the one field the driver contract rests on.
67
+ The metrics line is now written even when a surface died (`"<key>":"dead"`) — an incomplete batch
68
+ is exactly the batch worth recording.
69
+ - **Fixed — `/cycle` and its workflow were removed in 1.4.0 but no installer ever scrubbed them.**
70
+ Every install since has kept `commands/cycle.md` + `workflows/cycle.js` on disk, so a dead command
71
+ stayed listed and invokable — dispatching a workflow whose phases 1.5.0 then deleted. All three
72
+ installers now remove them (as they already did for `/smoke`), and CI **plants the orphans before
73
+ re-installing** instead of asserting their absence on a fresh scratch home, which is exactly the
74
+ blind spot that let this survive four releases.
75
+ - **Reconcile now tops up `specs/_template.md`.** It was seeded once at install and never refreshed,
76
+ so every repo kept the front-matter its core shipped with. `/update-pipeline` adds the missing
77
+ front-matter fields (never the body — the section list is yours).
78
+ - **New — `specs/_decisions.md`, the transverse decision journal.** `PIPELINE.md` is a *stack* profile;
79
+ it says nothing about what the project has **decided**, so every `/spec` re-discovered or
80
+ contradicted the same choices. The journal is deliberately tiny: **append-only, one line per
81
+ decision** (`- <date> · <area> · <decision> — because <reason> · <feature_id>`), reversal by a
82
+ superseding line rather than an edit. Written by `/spec` at freeze (typically 0–3 lines; zero is
83
+ normal) and by `/build` when it adds or splits a surface. Read by the **deciding** stages only —
84
+ `/brainstorm`, `/spec`, `/audit`. **Implementers and reviewers never load it:** they have the frozen
85
+ contract, and shipping them the rationale would cost `surfaces × dispatches` tokens per feature for
86
+ a fact they can't act on. That exclusion is what keeps it cheap enough to be worth having. The `_`
87
+ prefix means `/doctor`, the dashboard scanner and the kanban backfill already skip it.
88
+
6
89
  ## 1.5.0 — 2026-08-01
7
90
 
8
91
  > **Re-run `npx cohorte@latest update --global` (or `update`)** to pick up the collector and the
9
92
  > `/smoke` removal — the update *deletes* the command and its agent from your install, it does not
10
93
  > just stop shipping them. The new dashboard panel comes with `npx cohorte dashboard`.
11
94
 
12
- - **New — `/loop <id>`: the review ⇄ fix cycle, run for you.** `/build` `/review` `/fix` →
95
+ - **New — `/loop <id>`: the review ⇄ fix cycle, run for you.** _(renamed `/drive` in 1.6.0 see
96
+ there.)_ `/build` → `/review` → `/fix` →
13
97
  `/review` … until a review reports **zero blocking findings** (a CRITICAL or a security issue —
14
98
  a LOW nit never costs a pass), or the pass ceiling (`--max=N`, default 5), or two consecutive
15
99
  reviews returning the *same* blocking findings, which means the fix is treading water and more
package/README.md CHANGED
@@ -131,7 +131,8 @@ design system), **interviews** you for the gaps, and **generates**:
131
131
  symbols instead of grep-and-reading whole files; `graphify` or `none` also available via the
132
132
  profile's `retrieval.provider`)
133
133
  - `scripts/new-feature.sh` + `remove-feature.sh` — parallel worktree isolation (if you enable it)
134
- - `specs/_template.md`
134
+ - `specs/_template.md` (and, on first decision, `specs/_decisions.md` — the project's one-line-per-decision
135
+ journal, read by `/brainstorm`, `/spec` and `/audit` so features stop re-litigating settled ground)
135
136
 
136
137
  Sanity-check `PIPELINE.md`, commit it, and run `/brainstorm`.
137
138
 
@@ -216,10 +217,10 @@ it in `.claude/pipeline/VERSION` and bundled repos in their committed `pipeline.
216
217
  | `/init-pipeline` | Detect stack → interview → generate the profile + agents. Run once per project. |
217
218
  | `/brainstorm` | Interactive persona panel that pressure-tests a feature idea. |
218
219
  | `/spec` | Freeze the feature spec + contract into `specs/<id>.md` (UI features also get a standalone design brief at `specs/design/<id>.md`). Also applies review returns. |
219
- | `/build <id>` | Lead authors the contract, then dispatches one implementer per surface in parallel. |
220
- | `/review <id>` | Read-only review agents (one per touched surface, parallel) audit the diff vs the spec. |
220
+ | `/build <id>` | Readiness gate on the frozen spec, then the lead authors the contract and dispatches one implementer per surface in parallel. |
221
+ | `/review <id>` | Read-only review agents (one per touched surface, parallel) audit the diff vs the spec; out-of-scope findings go to the refactor backlog. |
221
222
  | `/fix <id>` | Apply a review report: remediation into the spec, re-dispatch only the surfaces with findings. |
222
- | `/loop <id>` | Autonomous `/build → /review → /fix → /review …` until no blocking finding is left (see below). |
223
+ | `/drive <id>` | Autonomous `/build → /review → /fix → /review …` until no blocking finding is left (see below). |
223
224
  | `/ship <id>` | Release agent commits, pushes, opens the PR; watches CI; proposes worktree teardown. |
224
225
  | `/audit [path]` | Prioritized refactor backlog for existing code. |
225
226
  | `/refactor <domain>` | Apply the backlog for one surface, TDD-first. |
@@ -243,19 +244,26 @@ lever: long sessions (>150k) are expensive even when cached. Each command tells
243
244
  safe to clear. If you'd rather stay in one session, `/compact` mid-task does the lighter version. (Claude
244
245
  can't fire `/clear` itself — it's a client-side command; the pipeline just makes it always safe to type.)
245
246
 
246
- ### Let it run itself — `/loop`
247
+ ### Let it run itself — `/drive`
247
248
 
248
249
  ```
249
- /loop feat-x # /build, then /review ⇄ /fix until clean (max 5 passes)
250
- /loop feat-x --no-build # already built — just re-run the /review ⇄ /fix loop
251
- /loop feat-x --max=8
250
+ /drive feat-x # /build, then /review ⇄ /fix until clean (max 5 passes)
251
+ /drive feat-x --no-build # already built — just re-run the /review ⇄ /fix loop
252
+ /drive feat-x --max=8
253
+ /drive feat-x --resume # continue a run that died / hit the ceiling, at the pass it reached
252
254
  ```
253
255
 
254
256
  It stops when `/review` reports **zero blocking findings** (a CRITICAL or a security issue — a LOW
255
- nit never costs a pass), at the pass ceiling, or as soon as two consecutive reviews return the same
256
- blocking findings, which means the fix is treading water and more passes won't help. **Each fix pass
257
- is committed** (`loop(<id>): fix pass <i>`) — that's your way back after N autonomous passes — and
258
- **no fix runs on the last pass**, since fixing without a review behind it leaves unaudited code.
257
+ nit never costs a pass), at the pass ceiling, as soon as two consecutive reviews return the same
258
+ blocking findings (the fix is treading water and more passes won't help), or immediately if `/build`'s
259
+ readiness gate says the frozen spec **cannot be built** — that one needs `/spec`, not passes. **Each
260
+ fix pass is committed** (`loop(<id>): fix pass <i>`) that's your way back after N autonomous passes —
261
+ and **no fix runs on the last pass**, since fixing without a review behind it leaves unaudited code.
262
+
263
+ **It's resumable.** Before each phase the driver stamps `status: in-progress` + `loop_pass` +
264
+ `loop_phase` into the spec's front-matter (plain `awk`, zero tokens), and a terminal `in-review` or
265
+ `blocked` on exit. So `--resume` continues at pass 3 instead of re-paying passes 1 and 2 — and the spec
266
+ itself tells you, `/doctor` and the dashboard where the loop got to.
259
267
 
260
268
  **The loop does not run in your session.** Each phase is a separate `claude -p` child with its own
261
269
  fresh context, driven by `pipeline/scripts/loop.sh`; all of their output goes to
package/bin/cli.js CHANGED
@@ -227,6 +227,14 @@ function copyFixedAgents() {
227
227
  // 1.5.0 removed the /smoke phase; copy-over never deletes, so scrub the orphan agent+command.
228
228
  fs.rmSync(path.join(dest, 'agents', 'smoke.md'), { force: true });
229
229
  fs.rmSync(path.join(dest, 'commands', 'smoke.md'), { force: true });
230
+ // 1.4.0 removed /cycle and its workflow — and no installer ever scrubbed them, so every
231
+ // install since has kept offering a command that dispatches a workflow whose phases were
232
+ // later deleted. A dead command is worse than a missing one: the model can still fire it.
233
+ fs.rmSync(path.join(dest, 'commands', 'cycle.md'), { force: true });
234
+ fs.rmSync(path.join(dest, 'workflows', 'cycle.js'), { force: true });
235
+ // 1.6.0 renamed /loop → /drive: Claude Code's own built-in /loop shadowed ours, so a leftover
236
+ // commands/loop.md is a command the user can never reach — scrub it rather than leave a decoy.
237
+ fs.rmSync(path.join(dest, 'commands', 'loop.md'), { force: true });
230
238
  scrubResearchQuestionnaire();
231
239
  }
232
240
 
@@ -81,6 +81,24 @@ domain** (same finding-line shape) instead of a SHIP/REVISE/BLOCK verdict.
81
81
  - Any **security vulnerability** ⇒ verdict **BLOCK**.
82
82
  - No CRITICAL and no security issue ⇒ verdict **SHIP**.
83
83
 
84
+ ## Deferred — real, but not this feature's problem
85
+
86
+ A finding is **deferred** when it is genuinely true and genuinely **out of this feature's scope**:
87
+ pre-existing code the staged diff did not touch, adjacent debt the spec never claims to fix, a
88
+ convention violation that predates this work. Deferring is not softening — it is naming the right
89
+ owner. The lead routes deferred findings to `specs/refactor-backlog.md` (they feed `/refactor`), so
90
+ they are **never lost and never cost a fix loop**.
91
+
92
+ - **Deferred findings are separate from your findings list** and count in **no** severity row: the
93
+ severity table drives the verdict, and a deferred item must never force one.
94
+ - **Deferrable:** a problem entirely in lines/files the diff did not change, whose fix is not required
95
+ by any acceptance criterion of this spec.
96
+ - **NOT deferrable, ever:** anything the diff touched or introduced; any spec violation; any
97
+ **security** issue on a path this feature adds, calls or modifies (a pre-existing hole this feature
98
+ now exposes to new traffic is this feature's problem). When in doubt, it is a finding, not a deferral.
99
+ - Cap the deferred list at **10 lines**, worst first; each carries its own out-of-scope reason so the
100
+ lead can route it without re-reading anything.
101
+
84
102
  ## Your return — the REVIEW REPORT, exactly this shape
85
103
 
86
104
  Every finding must be **self-sufficient for a stateless agent**: `file:line` · severity ·
@@ -110,6 +128,11 @@ Verdict: <SHIP | REVISE | BLOCK>
110
128
  - **[<SEVERITY>]** `<file>:<line>` · <spec-violation|quality|security> · <problem> → **Fix:** <concrete change>
111
129
  (order by severity; "None." if none; max 20 lines, one per finding, no code excerpts)
112
130
 
131
+ ## Deferred
132
+
133
+ - **[<SEVERITY>]** `<file>:<line>` · <quality|security> · <problem> → **Fix:** <concrete change> · out of scope: <why this feature does not own it>
134
+ (real but out of this feature's scope — see §Deferred; worst first; "None." if none; max 10 lines)
135
+
113
136
  ## Notes
114
137
  (ONLY the RBAC / mobile-first assessment when the profile enables them; omit the section otherwise)
115
138
  ```
@@ -7,7 +7,9 @@ argument-hint: [path or domain, default = whole repo]
7
7
  You are the **lead**. Audit **$ARGUMENTS** (default: whole repo) to drive it to a clean base. Read +
8
8
  analyze only — no fixes (those go through `/refactor`).
9
9
 
10
- > Read `PIPELINE.md` §`commands` (the mechanical gates), `surfaces`, and §Conventions.
10
+ > Read `PIPELINE.md` §`commands` (the mechanical gates), `surfaces`, and §Conventions — plus
11
+ > `specs/_decisions.md` §Live if it exists (SCHEMA.md §Decisions): those standing decisions are part
12
+ > of the rulebook you audit against, and code that contradicts one is a finding like any other.
11
13
  >
12
14
  > **Workflow variant** (opt-in — SCHEMA.md §Workflows): on Claude Code ≥ 2.1.154 with workflows
13
15
  > enabled, the human can ask to "run the audit workflow" (`<core>/workflows/audit.js` — one auditor
@@ -39,5 +41,11 @@ from your instructions), grouped by domain (one group per surface + shared). —
39
41
  Merge mechanical + convention findings into one prioritized backlog and **write
40
42
  `specs/refactor-backlog.md`**, grouped by domain, each item:
41
43
  `- [ ] <SEVERITY> · <file:line> · <rule|tdd|lint|format|type|security> · <concrete fix>`
44
+
45
+ **Carry over the deferred items** before overwriting: `grep -n 'deferred:' specs/refactor-backlog.md`
46
+ and re-emit every **open** (`- [ ]`) match verbatim under its domain, tag included. Those lines were
47
+ put there by `/review` §3.5 — a real finding a feature deliberately did not own — and an audit that
48
+ blindly overwrites the file is the one way they silently disappear. Already-ticked (`- [x]`) ones are
49
+ done: drop them.
42
50
  Print a short summary (counts per domain + top items). Tell the human: refactor a domain with
43
51
  `/refactor <domain>`.
@@ -11,6 +11,12 @@ at Finish, when a board is configured.
11
11
  > Read `PIPELINE.md` §Personas (the panel) and §`rbac` first. If `rbac.enabled`, the panel must
12
12
  > pressure-test the idea so it serves **every** role, not just admins.
13
13
  >
14
+ > Also read `specs/_decisions.md` §Live if it exists (SCHEMA.md §Decisions) — one line per standing
15
+ > decision. The panel argues about the idea, not about settled ground: a persona that proposes
16
+ > something a live line already decided must be told so by another persona, and an idea that genuinely
17
+ > needs to overturn one must say which line, out loud, so the human decides it here rather than
18
+ > discovering the contradiction at `/spec`.
19
+ >
14
20
  > Template paths below (`.claude/templates/…`) resolve to `~/.claude/templates/…` when the core is
15
21
  > installed globally — read whichever exists.
16
22
  >
@@ -16,8 +16,11 @@ You are the **lead**. Build feature **$ARGUMENTS** from its frozen spec.
16
16
  ## 1. Load & check
17
17
 
18
18
  - Check the spec front-matter FIRST — `grep '^status:' specs/$ARGUMENTS.md` (or Read with a ~15-line
19
- limit) — before any full read. If missing or `status` not `frozen`/`in-review`, stop tell the human
20
- to run `/spec` first. Only then read the body, selectively: front-matter, §5 contract, the surface
19
+ limit) — before any full read. Buildable statuses are `frozen`, `in-review` and `in-progress` (the
20
+ last one means a `/drive` is or was driving this spec SCHEMA.md §Spec status). `blocked` means a
21
+ loop gave up here: say so, and route by the spec's `## Remediation` — open items ⇒ `/fix`, none ⇒
22
+ continue this build. Anything else (`draft`, missing, `shipped`) ⇒ stop and tell the human to run
23
+ `/spec` first. Only then read the body, selectively: front-matter, §5 contract, the surface
21
24
  task sections, and `## Remediation` (fall back to a full read if the spec doesn't follow the
22
25
  template's headings).
23
26
  - **Route check** — if `## Remediation` has open `- [ ]` items and none requires a contract change,
@@ -56,6 +59,59 @@ shared-code rule (shared trees get a single-owner surface; cross-slice shapes go
56
59
  This is the automatic path: you don't send the human back to `/init-pipeline`. If nothing new is needed,
57
60
  say so and continue. Dispatch (§3) then covers the reconciled surface list.
58
61
 
62
+ **Adding or splitting a surface is an architectural decision** — append ONE line for it to
63
+ `specs/_decisions.md` §Live (SCHEMA.md §Decisions; create from `.claude/templates/decisions.template.md`
64
+ if absent), area `surfaces`, e.g.
65
+ `- <date> · surfaces · <key> owns <path>, single owner of <what> — because <the boundary reason> · $ARGUMENTS`.
66
+ One `>>` in the Bash call you're already making. Nothing added ⇒ nothing to append.
67
+
68
+ ## 1.6 Readiness verdict — the gate before N dispatches
69
+
70
+ **Zero extra agents: you already hold the spec, the profile and the reconciled surface list.** The
71
+ whole point is that a bancal spec costs one verdict here instead of N implementers discovering it in
72
+ parallel. Judge the frozen contract on **implementability only** — never on whether the feature is a
73
+ good idea (that was `/brainstorm`), never by re-reading files you don't already need:
74
+
75
+ 1. **Contract completeness** (§5) — every endpoint/interface has method+path (or signature), auth,
76
+ request fields with types + validation, the success shape, and its error cases. A missing
77
+ **request or success shape** ⇒ `NOT-READY` (an implementer would invent it, and the other surface
78
+ would invent a different one). A missing **error case** ⇒ `RESERVATIONS`.
79
+ 2. **Surface coverage** — every §6 task maps to a surface in the reconciled list, and every contract
80
+ entry has an owner **on each side it names** (producer and consumer). A contract entry no surface
81
+ owns ⇒ `NOT-READY`.
82
+ 3. **Dependencies exist** — for the modules, packages, tables, env vars and shared helpers the spec
83
+ names as *pre-existing*: verify them in ONE Bash call (`test -f` / `grep -l` / a package-manifest
84
+ grep, output redirected — never a file read per name). Named as pre-existing but absent, and not
85
+ listed as created by this feature ⇒ `NOT-READY`.
86
+ 4. **Residual ambiguity** (§10) — an open question a surface would have to *guess* at: blocks a
87
+ contract decision ⇒ `NOT-READY`; merely narrows an implementation choice ⇒ `RESERVATIONS`.
88
+ 5. **Design gate** — a `uses_design` surface in scope with `design_files` still empty ⇒ `NOT-READY`
89
+ (this is §1's gate restated as a verdict, so an automated driver sees the same fact).
90
+
91
+ Write the machine-readable verdict to `specs/reports/$ARGUMENTS.readiness.json` (overwrite,
92
+ `mkdir -p specs/reports` first — the same gitignored buffer dir `/review` stages into, which may not
93
+ exist yet on a first build) — on **every** build, including `READY`. It is the only channel between this gate and a driver (`/drive`),
94
+ which parses no prose:
95
+
96
+ ```json
97
+ { "id": "$ARGUMENTS", "phase": "readiness", "ts": "<ISO>", "verdict": "RESERVATIONS",
98
+ "gaps": ["contract|POST /orders|no 409 case for a duplicate id"],
99
+ "surfaces": ["backend", "frontend"] }
100
+ ```
101
+
102
+ - **`gaps`** — one normalized string per gap, `<check>|<where>|<what is missing>`: `<check>` is
103
+ `contract` · `coverage` · `dependency` · `ambiguity` · `design`; `<where>` is the contract entry,
104
+ surface key or dependency name (no `:line` — it shifts on every edit); `<what>` is the gap, not the
105
+ fix. `READY` ⇒ `[]`.
106
+ - **`NOT-READY` ⇒ STOP: author no contract and spawn NO agent.** Print the gaps and send the human to
107
+ `/spec $ARGUMENTS` to patch the contract, then re-run `/build`. This abort is the whole point of the
108
+ step — a spec that cannot be built does not get cheaper by being built N times in parallel.
109
+ - **`RESERVATIONS` ⇒ continue.** It never blocks (a gate that stalls a sound build on a missing error
110
+ case would cost more human round-trips than it saves): inline each gap verbatim into the dispatch of
111
+ the surface it affects, as an explicit assumption the agent must implement *and* flag in its handoff,
112
+ and relay the list to the human in one line each.
113
+ - **`READY` ⇒ continue silently** — one line, no restatement.
114
+
59
115
  ## 2. Author the contract (lead-only — the single sync channel)
60
116
 
61
117
  _Only if `contract.enabled`._ From §5 of the spec, write/update the feature's contract file at
@@ -87,19 +143,46 @@ tree. For each surface in `surfaces`:
87
143
  > via `DesignSync get_file`, build mobile-first · or `none` (non-design surface, or a fix loop whose
88
144
  > open items are all non-visual)>. Open Remediation items for YOUR surface (self-contained — fix
89
145
  > exactly these, reading only the files they name; `none` ⇒ first build, implement the spec's tasks
90
- > for your surface): <the surface's open `- [ ]` lines verbatim, or `none`>."
146
+ > for your surface): <the surface's open `- [ ]` lines verbatim, or `none`>. Readiness gaps for YOUR
147
+ > surface (§1.6 `RESERVATIONS` — the spec is silent here: implement the stated assumption and flag what
148
+ > you assumed in your handoff): <that surface's `gaps` entries verbatim, or `none`>."
149
+
150
+ ## 3.5 Roll call — account for EVERY dispatch before integrating
151
+
152
+ A subagent can die: a rate limit mid-run, a transport error after retries, its own context exhausted.
153
+ When it does, it returns **nothing** — and nothing is byte-identical to "a clean surface with nothing
154
+ to report". Silence is not a green light; treat it as the failure it is (SCHEMA.md §Dead agents).
155
+
156
+ - **Roll call.** Every surface you dispatched in §3 must come back with a handoff in the format its
157
+ agent instructions define. Missing, empty, or truncated mid-sentence ⇒ that surface is **dead**.
158
+ - **Never infer success from silence,** and never speak for a dead agent — you did not see its work.
159
+ - **Retry that surface ONCE, alone.** Re-dispatch it with the byte-identical §3 prompt. The other
160
+ surfaces' work is already on disk and untouched, so this costs one agent, not a rebuild — and most
161
+ deaths are transient. Never retry a surface that *did* answer.
162
+ - **Died twice ⇒ stop guessing and look.** Run that surface's own quiet commands
163
+ (`<surface>.typecheck_cmd`, `lint_quiet_cmd`, `test_quiet_cmd`) with output redirected to
164
+ `specs/reports/$ARGUMENTS.<key>.deadcheck.txt`, then grep it — never into your context. Report the
165
+ three results plus which of the spec's tasks for that surface actually landed, checked against the
166
+ tree, not against a handoff you never got. Say plainly that the surface is **unverified**.
91
167
 
92
168
  ## 4. Integrate
93
169
 
94
170
  When all return, flag any contract mismatch or failing test from the handoffs; otherwise print one
95
171
  status line per surface (`<key> · tests pass/fail · <n> TODOs`) — do not restate handoff content.
172
+ A dead surface (§3.5) prints `<key> · DEAD — unverified` and **the batch is never reported as ok**.
96
173
  Append **ONE line for the batch** to the **main checkout's** `.claude/pipeline-metrics.jsonl` —
97
174
  NOT the worktree's, which dies at teardown while metrics must accumulate across features. Resolve
98
175
  it from anywhere: `$(dirname "$(git rev-parse --git-common-dir)")/.claude/pipeline-metrics.jsonl`
99
176
  (in the main checkout this resolves to itself). Create it if absent; it must be gitignored.
100
177
  Compute the elapsed time in the same Bash call
101
178
  (`echo "{...\"seconds\":$(($(date +%s)-<start epoch from §2>)),...}" >> …`):
102
- `{"ts":"<ISO date>","feature":"$ARGUMENTS","phase":"build","seconds":<wall-clock>,"surfaces":{"<key>":"ok|error",…}}`
179
+ `{"ts":"<ISO date>","feature":"$ARGUMENTS","phase":"build","seconds":<wall-clock>,"surfaces":{"<key>":"ok|error|dead",…}}`
180
+ — **write this line even when a surface died.** An incomplete batch is exactly the batch worth having
181
+ in the record; skipping the append to "wait until it's complete" silently deletes the evidence that
182
+ anything went wrong. In the same call write the machine-readable batch result to
183
+ `specs/reports/$ARGUMENTS.build.json` (overwrite) — the channel an automated driver reads, since it
184
+ never sees your chat:
185
+ `{"id":"$ARGUMENTS","phase":"build","ts":"<ISO>","surfaces":{"<key>":"ok|error|dead",…},"dead":["<key>",…]}`
103
186
  — this is the evidence SCHEMA.md §Specialization asks for before splitting a surface. In the same
104
187
  Bash call, chain the opt-in usage ping — **the shared form every phase command reuses**:
105
188
  `<core>/pipeline/scripts/telemetry-send.sh <phase> "$ARGUMENTS" <seconds> "<results>" || true`
@@ -108,7 +191,9 @@ Bash call, chain the opt-in usage ping — **the shared form every phase command
108
191
  never ask about consent here. `/review` and `/fix` chain the same line with their own
109
192
  phase + results. The `|| true` swallows a **missing** script too, so a half-copied core goes
110
193
  silent rather than loud — `/doctor` check 1 is what catches that.
111
- Then tell the human: exercise the feature by hand if it's worth it, then run `/review $ARGUMENTS`.
194
+ Then tell the human: exercise the feature by hand if it's worth it, then run `/review $ARGUMENTS` —
195
+ unless a surface is dead, in which case say so first and let them decide whether to re-run `/build`
196
+ (a dead surface has no findings, so `/fix` has nothing to re-dispatch).
112
197
  Do not run the app or migrations yourself here — building is not running.
113
198
  **Recommend a `/clear` now** — the spec, contract and diff are all on
114
199
  disk, and the lead's history is re-sent at input price on every turn it survives.
@@ -84,9 +84,14 @@ fix only with the human's go-ahead (or hand them the command).
84
84
  End the check with ONE summary line, e.g.
85
85
  `workflows: available (opt-in — ask to "run the review workflow")` or
86
86
  `workflows: unavailable (<first failing prerequisite>) — conversational commands (the default)`.
87
- 9. **Specs & metrics.** Every `specs/*.md` front-matter `status` is a valid stage — excluding
88
- `_`-prefixed files and `specs/refactor-backlog.md`, which `/audit` writes as a backlog, not a
89
- spec, and which has no front-matter to check; `shipped` specs
87
+ 9. **Specs & metrics.** Every `specs/*.md` front-matter `status` is a valid stage — one of
88
+ `draft · frozen · in-progress · in-review · shipped · blocked` (SCHEMA.md §Spec status; the last two
89
+ are written by the `/drive` driver, so flagging them would report the pipeline's own state as a
90
+ defect) — excluding
91
+ `_`-prefixed files (the spec template and `specs/_decisions.md`, the decision journal) and
92
+ `specs/refactor-backlog.md`, which `/audit` writes as a backlog, not a
93
+ spec, and which has no front-matter to check. A spec left `in-progress`/`blocked` with
94
+ `loop_pass` > 0 is a loop that never finished ⇒ say so and name `/drive <id> --resume`. `shipped` specs
90
95
  with a live worktree flagged (see 6). `.claude/pipeline-metrics.jsonl` and `specs/reports/` (the
91
96
  `/review` report buffer that lets a `/fix` survive a `/clear`) are gitignored. Metrics
92
97
  belong to the **main checkout** — a `pipeline-metrics.jsonl` inside a live feature worktree is a
@@ -1,13 +1,19 @@
1
1
  ---
2
2
  model: sonnet
3
3
  description: Autonomous /build → /review → /fix → /review loop for one feature, until no blocking finding remains.
4
- argument-hint: <feature_id> [--max=N] [--no-build] [--rebuild]
4
+ argument-hint: <feature_id> [--max=N] [--no-build] [--rebuild] [--resume]
5
5
  allowed-tools: Bash(bash ~/.claude/pipeline/scripts/loop.sh:*), Bash(bash .claude/pipeline/scripts/loop.sh:*), Bash(test:*), Read(specs/reports/**)
6
6
  disable-model-invocation: true
7
7
  ---
8
8
 
9
9
  You are the **launcher**, not the loop. Run the driver for **$ARGUMENTS** and relay three lines.
10
10
 
11
+ > **This command was `/drive` until 1.6.0.** Claude Code ships its own built-in `/drive` (run a prompt on
12
+ > a recurring interval), which **shadowed** this one: typing `/drive <id>` started the interval runner
13
+ > with the feature id as its prompt, so the driver below never ran and the session reported a loop that
14
+ > did not exist. The shipped script keeps its `loop.sh` name — nothing about a user's install path
15
+ > changes, only what you type.
16
+ >
11
17
  > This command exists because a slash command cannot `/clear` itself. Every phase of the loop runs
12
18
  > as a **separate `claude -p` child session** with its own fresh context, driven by a bash script —
13
19
  > so the diff, the N review reports and the N contracts never accumulate in YOUR history, which is
@@ -25,8 +31,15 @@ test -f .claude/pipeline/scripts/loop.sh \
25
31
  ```
26
32
 
27
33
  Pass `$ARGUMENTS` through untouched — the script owns its own flag parsing (`--max=N`,
28
- `--no-build`, `--rebuild`) and exits 64 on anything it doesn't know. Don't validate flags yourself,
29
- don't rewrite them, don't add any.
34
+ `--no-build`, `--rebuild`, `--resume`) and exits 64 on anything it doesn't know. Don't validate flags
35
+ yourself, don't rewrite them, don't add any.
36
+
37
+ **Resume is the human's call, not yours.** The loop records its position in the spec's front-matter
38
+ (`status: in-progress` · `loop_pass` · `loop_phase` — SCHEMA.md §Spec status), so a run killed by a
39
+ dead session, a ceiling or a `blocked` exit can continue with `--resume` instead of re-paying the
40
+ passes it already made. If the human types `/drive <id>` on a spec whose front-matter says
41
+ `status: in-progress` or `blocked` with `loop_pass` > 1, say so in one line and ask whether to resume
42
+ or restart — never silently add the flag, and never silently restart from pass 1.
30
43
 
31
44
  **Never read `specs/reports/<id>.loop.log`.** It holds the full transcript of every child session —
32
45
  the entire diff, every review report, every fix handoff. Pulling it into this session re-imports
@@ -38,7 +51,9 @@ open it in an editor for free. The same goes for the per-surface `.diff` and `.p
38
51
 
39
52
  The script prints one line per phase and one closing line; that is your raw material. For exit
40
53
  **1** or **3** only, also Read `specs/reports/<id>.verdict.json` (small, structured, safe) to name
41
- the remaining findings — never the markdown report, which is the findings body in full.
54
+ the remaining findings — never the markdown report, which is the findings body in full. For exit
55
+ **4**, Read `specs/reports/<id>.readiness.json` instead (also small) and relay its `gaps`. On any
56
+ other exit the closing line already carries the deferred count, so read nothing.
42
57
 
43
58
  | exit | meaning | what to say |
44
59
  | ---- | ------- | ----------- |
@@ -46,14 +61,18 @@ the remaining findings — never the markdown report, which is the findings body
46
61
  | `1` | ceiling hit | the fix was progressing but ran out of passes ⇒ re-run with a higher `--max` |
47
62
  | `2` | no usable verdict | `/review` produced nothing, or aborted on a red preflight — the closing line says which; point at `specs/reports/<id>.preflight.txt` |
48
63
  | `3` | non-convergent | the same blocking findings survived a fix pass; a higher `--max` will NOT help — the human needs to look at them (list them from the verdict) |
64
+ | `4` | not implementable | `/build`'s readiness gate returned `NOT-READY` — the frozen spec cannot be built and **no agent ran**; Read `specs/reports/<id>.readiness.json` (small, structured) and relay its `gaps`, then point at `/spec <id>`. More passes cannot fix this |
49
65
  | `64` | usage | relay the script's own message verbatim |
50
66
 
51
- Then print exactly three lines and nothing else:
67
+ Then print exactly three lines and nothing else — plus a fourth **only when the verdict carries
68
+ `deferred` > 0** (findings that were real but out of this feature's scope, parked in the backlog by
69
+ `/review` §3.5; they are not blocking and never cost a pass, but they are not nothing either):
52
70
 
53
71
  ```
54
- outcome: <one clause — clean / ceiling / no verdict / non-convergent / usage>
72
+ outcome: <one clause — clean / ceiling / no verdict / non-convergent / not implementable / usage>
55
73
  iterations: <n> review pass(es)<, m fix pass(es) committed>
56
74
  remaining: <blocking count + one short phrase per blocking item, or "none">
75
+ deferred: <n> parked in specs/refactor-backlog.md — /refactor <domain> when you want them
57
76
  ```
58
77
 
59
78
  Add at most one follow-up sentence: the next command to run. Never restate a finding's fix, never
@@ -50,6 +50,11 @@ that change the *contract*; `/fix` is for everything else.
50
50
 
51
51
  When the agents return:
52
52
 
53
+ - **Roll call first (SCHEMA.md §Dead agents).** A re-dispatched agent that returns nothing has fixed
54
+ nothing you can verify. Retry that surface ONCE with the byte-identical dispatch; still silent ⇒ leave
55
+ **every one of its items `- [ ]`** (a dead agent never ticks a box — that would hide an open finding
56
+ from the next round and from the driver), print `<key> · DEAD — items untouched`, and say the surface
57
+ is unverified.
53
58
  - **Tick the resolved items.** Each handoff's `## Remediation addressed` lists what that agent fixed
54
59
  (by `file:line`). For every Remediation item an agent reports fixed, flip its `- [ ]` → `- [x]` in
55
60
  `specs/<id>.md` and append a terse ` — fixed: <what/where>` note (the convention prior rounds already
@@ -86,9 +86,25 @@ metrics line needs it.
86
86
 
87
87
  ## 3. Merge & relay the verdict
88
88
 
89
- Merge the returned reports into **one** REVIEW REPORT (same template): findings concatenated and
89
+ **Roll call FIRST a dead reviewer is not a clean surface.** Every surface you dispatched in §2 must
90
+ come back with a REVIEW REPORT. A reviewer that died (rate limit, transport error, exhausted context)
91
+ returns **nothing**, and zero findings from a dead reviewer is byte-identical to zero findings from a
92
+ genuinely clean one — which is how "every reviewer crashed" reads as the strongest possible verdict
93
+ from no evidence at all (SCHEMA.md §Dead agents). So:
94
+
95
+ - **Retry a silent surface ONCE**, byte-identical dispatch. Most deaths are transient, and the staged
96
+ diff is already on disk — the retry costs one agent, not a re-review.
97
+ - **Silent twice ⇒ that surface is `unreviewed`.** Name it in the report under
98
+ `## NOT reviewed (no verdict on these)`, list it in the verdict JSON's `unreviewed`, and **refuse to
99
+ score `SHIP`** — the merged verdict is at least `REVISE`. Absence of evidence is not evidence of
100
+ absence, and it must never reach `/ship` or tick a DoD box.
101
+ - **Never re-review the other surfaces** to compensate: their reports are valid and already on disk.
102
+
103
+ Then merge the returned reports into **one** REVIEW REPORT (same template): findings concatenated and
90
104
  re-ordered by severity, counts summed, duplicates collapsed, verdict = the worst returned
91
- (`BLOCK` > `REVISE` > `SHIP`). Append ONE metrics line for the batch to `pipeline-metrics.jsonl`
105
+ (`BLOCK` > `REVISE` > `SHIP`). The `## Deferred` sections merge the same way (dedupe by
106
+ `file` + problem) and stay **out of the severity table and out of the verdict** — see §3.5, which
107
+ routes them. Append ONE metrics line for the batch to `pipeline-metrics.jsonl`
92
108
  (main-checkout path + rules in `/build` §4): `{"ts":"<ISO>","feature":"$ARGUMENTS","phase":"review","seconds":<wall-clock>,"surfaces":{"<key>":"<verdict>:<finding count>",…}}`.
93
109
  In the same Bash call, chain the opt-in usage ping (`/build` §4, `phase: "review"`, results = the
94
110
  merged verdict + total finding count, e.g. `"REVISE:3"`).
@@ -97,11 +113,11 @@ merged verdict + total finding count, e.g. `"REVISE:3"`).
97
113
  non-recursive `specs/*.md` glob, so it's never mistaken for a spec (no phantom card, no bogus stage).
98
114
  **Write the machine-readable verdict** to `specs/reports/$ARGUMENTS.verdict.json` (overwrite) — on
99
115
  **every** run, including the small-diff fast path of §2 and a `SHIP`. This file is the ONLY contract
100
- between the pipeline and an automated driver (`/loop`), which parses no prose:
116
+ between the pipeline and an automated driver (`/drive`), which parses no prose:
101
117
 
102
118
  ```json
103
119
  { "id": "$ARGUMENTS", "phase": "review", "ts": "<ISO>", "verdict": "REVISE",
104
- "findings": 7, "blocking": 2, "security": 1,
120
+ "findings": 7, "blocking": 2, "security": 1, "deferred": 3, "unreviewed": [],
105
121
  "severity": {"CRITICAL": 1, "HIGH": 2, "MEDIUM": 3, "LOW": 1},
106
122
  "surfaces": {"backend": {"verdict":"BLOCK","findings":4,"blocking":2}},
107
123
  "blocking_items": ["backend|apps/api/src/routes/order.ts|missing authz on post"],
@@ -121,12 +137,42 @@ between the pipeline and an automated driver (`/loop`), which parses no prose:
121
137
  `printf '%s\n' "<item>" … | LC_ALL=C sort | sha256sum | cut -c1-16` (`shasum -a 256` where there
122
138
  is no `sha256sum`). Empty list ⇒ `""`. A driver comparing two consecutive fingerprints detects a
123
139
  fix loop that is treading water.
140
+ - **`deferred`** — the count of merged `## Deferred` items §3.5 parked in the backlog. Informational:
141
+ it never enters `blocking`, so it can never cost a driver an iteration.
142
+ - **`unreviewed`** — the surface keys whose reviewer died twice, `[]` on a complete run. It is
143
+ **separate from `blocking` on purpose**: `blocking` counts real findings (CRITICAL + security), and
144
+ faking a number there to force a driver's hand would corrupt the one field the whole contract rests
145
+ on. A non-empty `unreviewed` means "this run does not cover everything" — a driver treats it as no
146
+ usable verdict, never as clean, whatever `blocking` says.
147
+
148
+ ## 3.5 Route the deferred findings — the backlog, not the fix loop
149
+
150
+ Do this on **every** run, before the verdict branch below, and whatever the verdict — a deferred
151
+ finding that is only routed on a `SHIP` is a deferred finding lost on every other verdict, which is
152
+ exactly the leak this step closes. Append each merged `## Deferred` item to
153
+ **`specs/refactor-backlog.md`**, under the `## <domain>` heading of the surface that owns its
154
+ `file:line` (create the file and/or heading if absent — same grouping `/audit` writes, so
155
+ `/refactor <domain>` picks them up with no extra plumbing):
156
+
157
+ ```
158
+ - [ ] <SEVERITY> · <file:line> · <quality|security|rule> · <concrete fix> · deferred:$ARGUMENTS
159
+ ```
160
+
161
+ - **Never into the spec's `## Remediation`** — that list is what `/fix` re-dispatches and what `/drive`
162
+ waits on, so a deferred item there would re-trigger the very loop it was deferred out of.
163
+ - **Dedupe before appending:** `grep -F` the backlog for the item's `<file>` + the first words of its
164
+ problem; already there (from a prior round or an `/audit`) ⇒ skip it, don't stack duplicates round
165
+ after round.
166
+ - Append with `>>` in ONE Bash call; never read the whole backlog into context to rewrite it (it grows
167
+ with every audit the repo has ever run).
168
+ - Report it as **one line** in chat: `deferred: <n> parked in specs/refactor-backlog.md (<domains>)`.
124
169
 
125
170
  In chat print ONLY: the verdict, the severity-count table, a one-line digest of each CRITICAL/security
126
171
  finding, and `Full report: specs/reports/$ARGUMENTS.md` — never echo the findings body into chat (it
127
172
  would sit in this session's history, re-sent every turn). Then:
128
173
 
129
- - **SHIP** → a SHIP verdict *is* the pipeline's statement that the feature meets its Definition of
174
+ - **SHIP** → only reachable with `unreviewed` empty (the roll call above forbids it otherwise). A SHIP
175
+ verdict *is* the pipeline's statement that the feature meets its Definition of
130
176
  Done, so **tick the DoD**: in `specs/$ARGUMENTS.md` §`Acceptance criteria / DoD`, flip each `- [ ]`
131
177
  → `- [x]` for the criteria the pipeline has actually verified — spec conformance + `ui_language`
132
178
  copy (this review), tests · lint · typecheck (a green `/build`), mobile-first as far as the code
@@ -141,12 +187,15 @@ would sit in this session's history, re-sent every turn). Then:
141
187
  of exactly the source you just reviewed (specs excluded, so DoD ticks + the ship status flip don't
142
188
  trip it). Then tell the human they can `/ship` — **recommend a `/clear` first**, the handoff is
143
189
  fully on disk. **SHIP with leftover LOW findings** (or LOW+MEDIUM at the human's call) does NOT
144
- force a fix cycle for nits: park them in `specs/refactor-backlog.md` tagged `deferred:<id>` (NOT as
145
- open `## Remediation` items, which would re-trigger the fix loop), keep the SHIP verdict and the
146
- freshness stamp, and let the human ship.
190
+ force a fix cycle for nits: park them through §3.5's exact route (the backlog, under their surface's
191
+ domain heading, tagged `deferred:$ARGUMENTS` — never as open `## Remediation` items, which would
192
+ re-trigger the fix loop), keep the SHIP verdict and the freshness stamp, and let the human ship.
147
193
  - **REVISE / BLOCK**, or any CRITICAL/HIGH/security finding → tell the human to run
148
194
  **`/fix $ARGUMENTS`** — it appends the report to the spec's `## Remediation` and re-dispatches ONLY
149
- the surfaces with findings. The full path (`/spec` Mode B then `/build`) remains for findings that
195
+ the surfaces with findings. (If they'd rather automate the rounds, the autonomous driver is
196
+ `disable-model-invocation: true` on purpose: **you cannot start it, they must type it**. Name the
197
+ exact line for them to type rather than attempting it — an attempt that silently fails reads as a
198
+ loop that is running when nothing is.) The full path (`/spec` Mode B then `/build`) remains for findings that
150
199
  change the contract in ways that ripple into clean surfaces. _The report is staged to
151
200
  `specs/reports/$ARGUMENTS.md`, so you can `/clear` before `/fix` — it reads the findings back from
152
201
  disk._