cohorte 1.5.0 → 2.0.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.
Files changed (58) hide show
  1. package/CHANGELOG.md +169 -3
  2. package/README.md +65 -57
  3. package/bin/cli.js +31 -15
  4. package/core/agents/implementer.template.md +3 -3
  5. package/core/agents/release.md +1 -1
  6. package/core/agents/review.md +25 -2
  7. package/core/commands/{audit.md → cohorte-audit.md} +11 -3
  8. package/core/commands/{brainstorm.md → cohorte-brainstorm.md} +9 -3
  9. package/core/commands/{build.md → cohorte-build.md} +95 -10
  10. package/core/commands/{doctor.md → cohorte-doctor.md} +22 -9
  11. package/core/commands/{fix.md → cohorte-fix.md} +20 -13
  12. package/core/commands/{init-pipeline.md → cohorte-init-pipeline.md} +1 -1
  13. package/core/commands/cohorte-loop.md +110 -0
  14. package/core/commands/{refactor.md → cohorte-refactor.md} +3 -3
  15. package/core/commands/{review.md → cohorte-review.md} +70 -20
  16. package/core/commands/{ship.md → cohorte-ship.md} +5 -5
  17. package/core/commands/{spec.md → cohorte-spec.md} +32 -12
  18. package/core/commands/{update-pipeline.md → cohorte-update-pipeline.md} +16 -6
  19. package/core/hooks/gate.py +101 -6
  20. package/core/templates/brainstorm-return.md +4 -4
  21. package/core/templates/decisions.template.md +42 -0
  22. package/core/templates/design-brief.md +1 -1
  23. package/core/templates/spec.template.md +8 -6
  24. package/core/templates/steps/init-pipeline/01-detect-stack.md +1 -1
  25. package/core/templates/steps/init-pipeline/02-interview-gaps.md +6 -6
  26. package/core/templates/steps/init-pipeline/03-draft-profile.md +1 -1
  27. package/core/templates/steps/init-pipeline/04-write-render.md +16 -12
  28. package/core/templates/steps/init-pipeline/05-report.md +5 -5
  29. package/core/workflows/audit.js +6 -6
  30. package/core/workflows/refactor.js +14 -14
  31. package/core/workflows/review.js +62 -20
  32. package/dashboard/README.md +2 -2
  33. package/dashboard/dist/assets/{index-dkO8UUVl.css → index-BZ_LQlEj.css} +1 -1
  34. package/dashboard/dist/assets/{index-8owBnqyv.js → index-P1I1JGtj.js} +11 -11
  35. package/dashboard/dist/index.html +2 -2
  36. package/dashboard/server/doctor.js +75 -18
  37. package/dashboard/server/index.js +5 -5
  38. package/dashboard/server/metrics.js +1 -1
  39. package/install.ps1 +31 -14
  40. package/install.sh +31 -14
  41. package/package.json +2 -2
  42. package/profile/PIPELINE.template.md +17 -16
  43. package/profile/SCHEMA.md +199 -48
  44. package/profile/cohorte.config.template.yaml +8 -8
  45. package/scripts/loop-detach.sh +153 -0
  46. package/scripts/loop.sh +202 -25
  47. package/scripts/metrics/collect.mjs +17 -8
  48. package/scripts/new-feature.sh.template +3 -3
  49. package/scripts/preflight.sh +40 -4
  50. package/scripts/remove-feature.sh.template +2 -2
  51. package/scripts/test-dashboard.mjs +34 -7
  52. package/scripts/test-gate.mjs +58 -0
  53. package/scripts/test-loop.mjs +269 -0
  54. package/scripts/test-metrics.mjs +23 -11
  55. package/scripts/test-workflows.mjs +33 -5
  56. package/scripts/validate-core.mjs +46 -9
  57. package/core/commands/loop.md +0 -61
  58. /package/core/commands/{align-ds.md → cohorte-align-ds.md} +0 -0
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: <SURFACE_AGENT>
3
- description: Implements the <SURFACE_LABEL> surface (<SURFACE_PATH>) for one feature, strictly from the frozen spec + contract, test-first TDD. Dispatched by /build. Touches only its own surface.
3
+ description: Implements the <SURFACE_LABEL> surface (<SURFACE_PATH>) for one feature, strictly from the frozen spec + contract, test-first TDD. Dispatched by /cohorte-build. Touches only its own surface.
4
4
  tools: <SURFACE_TOOLS>
5
5
  model: <SURFACE_MODEL>
6
6
  ---
@@ -14,7 +14,7 @@ shared surface is the frozen contract and the spec.
14
14
  > (§Conventions/§Testing): your slice of them is baked into this file below (§Your conventions),
15
15
  > rendered from the profile — re-reading the prose every dispatch is exactly the cost the bake
16
16
  > removes. If the baked slice visibly contradicts `PIPELINE.md`, say so in your handoff: the profile
17
- > wins, and this agent file needs a re-render (`/update-pipeline`).
17
+ > wins, and this agent file needs a re-render (`/cohorte-update-pipeline`).
18
18
 
19
19
  ## You own
20
20
 
@@ -22,7 +22,7 @@ shared surface is the frozen contract and the spec.
22
22
 
23
23
  ## Your conventions (baked from `PIPELINE.md` at render time)
24
24
 
25
- <!-- Rendered by /init-pipeline (and refreshed by /update-pipeline's reconcile) from
25
+ <!-- Rendered by /cohorte-init-pipeline (and refreshed by /cohorte-update-pipeline's reconcile) from
26
26
  §Conventions `### Shared` + `### Surface: <your key>` + your §Testing lines.
27
27
  Edit conventions in PIPELINE.md, never here — this block is regenerated. -->
28
28
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: release
3
- description: Commits, pushes, and opens the PR for a SHIP-verified feature. Dispatched by /ship at the SHIP gate. Drafts the conventional commit + PR body from the spec and diff. Never edits source.
3
+ description: Commits, pushes, and opens the PR for a SHIP-verified feature. Dispatched by /cohorte-ship at the SHIP gate. Drafts the conventional commit + PR body from the spec and diff. Never edits source.
4
4
  tools: Read, Grep, Glob, Bash
5
5
  model: haiku
6
6
  ---
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: review
3
- description: Read-only reviewer. Compares the implementation against the frozen spec, then audits code quality, security, and (if the profile declares it) mobile-first. Emits the REVIEW REPORT. Dispatched by /review — one per touched surface on multi-surface diffs. Cannot modify anything.
3
+ description: Read-only reviewer. Compares the implementation against the frozen spec, then audits code quality, security, and (if the profile declares it) mobile-first. Emits the REVIEW REPORT. Dispatched by /cohorte-review — one per touched surface on multi-surface diffs. Cannot modify anything.
4
4
  tools: Read, Grep, Glob, mcp__serena
5
5
  model: sonnet
6
6
  ---
@@ -66,7 +66,7 @@ Concrete, high-signal traps to grep for per language. A surface's language comes
66
66
  - **SQL / migrations** — `UPDATE`/`DELETE` with no `WHERE`; N+1 (a query inside a loop that a JOIN
67
67
  would collapse); foreign-key columns joined/filtered without an index.
68
68
 
69
- ## Audit mode (no feature spec — codebase refactor, dispatched by `/audit`)
69
+ ## Audit mode (no feature spec — codebase refactor, dispatched by `/cohorte-audit`)
70
70
 
71
71
  When given a **path/domain instead of a feature spec**, skip step 1 and audit the target against
72
72
  `PIPELINE.md` §Conventions as the rulebook: conventions per surface, TDD coverage (list every
@@ -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 `/cohorte-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
  ```
@@ -5,9 +5,11 @@ argument-hint: [path or domain, default = whole repo]
5
5
  ---
6
6
 
7
7
  You are the **lead**. Audit **$ARGUMENTS** (default: whole repo) to drive it to a clean base. Read +
8
- analyze only — no fixes (those go through `/refactor`).
8
+ analyze only — no fixes (those go through `/cohorte-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 `/cohorte-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
- `/refactor <domain>`.
51
+ `/cohorte-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 `/cohorte-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
  >
@@ -41,8 +47,8 @@ screens, risks, and what's explicitly out.
41
47
 
42
48
  When the human is satisfied, produce the **brainstorm return** by filling
43
49
  `.claude/templates/brainstorm-return.md` and **staging it to
44
- `specs/reports/<feature_id>-brainstorm.md`** (the gitignored buffer dir — `/spec` reads it from there
45
- when invoked with no paste). In chat print only a 3-line summary + the path. Tell them to run `/spec`
50
+ `specs/reports/<feature_id>-brainstorm.md`** (the gitignored buffer dir — `/cohorte-spec` reads it from there
51
+ when invoked with no paste). In chat print only a 3-line summary + the path. Tell them to run `/cohorte-spec`
46
52
  — **recommend a `/clear` first**, the return is staged on disk (pasting it remains a fallback).
47
53
 
48
54
  **Kanban:** settle the `feature_id` (kebab-case slug) the return carries — it is the card's join key
@@ -50,7 +56,7 @@ downstream. If a board is configured, **move** the card into the **Brainstorm**
50
56
  `#<feature_id>` (per §Kanban): the picked Ideas card if the human chose one, else a new card. No-op if
51
57
  no board.
52
58
 
53
- **Telemetry:** chain the opt-in usage ping onto that same Bash call — `/build` §4's shared form,
59
+ **Telemetry:** chain the opt-in usage ping onto that same Bash call — `/cohorte-build` §4's shared form,
54
60
  `<phase>` = `brainstorm`, `<seconds>` = `0` (this phase is human thinking time, not pipeline
55
61
  wall-clock — the funnel signal is the event, not its duration), `<results>` = `""`. No board ⇒ still
56
62
  ping, in its own `|| true` call. Silent no-op without consent; never ask about consent here.
@@ -16,14 +16,17 @@ 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 `/cohorte-loop` 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 ⇒ `/cohorte-fix`, none ⇒
22
+ continue this build. Anything else (`draft`, missing, `shipped`) ⇒ stop and tell the human to run
23
+ `/cohorte-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,
24
- stop and tell the human to run `/fix $ARGUMENTS` instead: it re-dispatches only the surfaces with
27
+ stop and tell the human to run `/cohorte-fix $ARGUMENTS` instead: it re-dispatches only the surfaces with
25
28
  findings. A full build with open items is only right when the contract change ripples into clean
26
- surfaces (the case `/fix` §1 falls back here for).
29
+ surfaces (the case `/cohorte-fix` §1 falls back here for).
27
30
  - **Design gate** — only if `design.enabled` and the feature has UI (some surface `uses_design`): if the
28
31
  spec front-matter `design_files` is empty, ask the human for the feature's design **links** and store
29
32
  them in `design_files`, then continue. Each entry is a full self-contained link of the form
@@ -53,9 +56,62 @@ For each surface to add: infer its `key`, `path`, `label`, `agent`, `tools`, `mo
53
56
  SCHEMA.md §"Rendering / reconciling a surface agent" — write the `surfaces[]` entry + §Conventions/§Testing
54
57
  stanza into `PIPELINE.md`, render `.claude/agents/<agent>.md` from the implementer template, applying the
55
58
  shared-code rule (shared trees get a single-owner surface; cross-slice shapes go through the contract).
56
- This is the automatic path: you don't send the human back to `/init-pipeline`. If nothing new is needed,
59
+ This is the automatic path: you don't send the human back to `/cohorte-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 `/cohorte-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 `/cohorte-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 (`/cohorte-loop`),
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
+ `/cohorte-spec $ARGUMENTS` to patch the contract, then re-run `/cohorte-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,28 +143,57 @@ 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`
106
189
  (`<core>` = `~/.claude` global / `.claude` bundled; here `<phase>` = `build`, `<results>` =
107
190
  `<ok,ok|error,…>`) — a silent no-op unless the human explicitly consented (SCHEMA.md §Telemetry);
108
- never ask about consent here. `/review` and `/fix` chain the same line with their own
191
+ never ask about consent here. `/cohorte-review` and `/cohorte-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
- 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`.
193
+ silent rather than loud — `/cohorte-doctor` check 1 is what catches that.
194
+ Then tell the human: exercise the feature by hand if it's worth it, then run `/cohorte-review $ARGUMENTS` —
195
+ unless a surface is dead, in which case say so first and let them decide whether to re-run `/cohorte-build`
196
+ (a dead surface has no findings, so `/cohorte-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.
@@ -16,13 +16,16 @@ fix only with the human's go-ahead (or hand them the command).
16
16
  `.claude/pipeline/VERSION` bundled); `.claude/pipeline.json` names a mode + `core_version`
17
17
  coherent with the VERSION file. A **global**-mode pointer lagging the VERSION file is ⚠️, not ❌:
18
18
  nothing bumped that field before 1.2.5, so the core itself is fine and only the pointer is stale
19
- ⇒ fix by running `/update-pipeline` (§3 syncs it now), or by editing the one field. Compare
20
- against `npm view cohorte version` — behind ⇒ suggest `/update-pipeline`. Read `pipeline/CHANGELOG.md` for what they're missing. The router
19
+ ⇒ fix by running `/cohorte-update-pipeline` (§3 syncs it now), or by editing the one field. Compare
20
+ against `npm view cohorte version` — behind ⇒ suggest `/cohorte-update-pipeline`. Read `pipeline/CHANGELOG.md` for what they're missing. The router
21
21
  commands' step files are present — `templates/steps/init-pipeline/` non-empty (a router whose
22
22
  `templates/steps/<cmd>/` dir is missing is a partial/stale install ⇒
23
23
  re-run install/update). **Shipped scripts present and executable** in `<core>/pipeline/scripts/`:
24
- `kanban-move.sh`, `telemetry-send.sh`, `preflight.sh`, `loop.sh`, `new-feature.sh.template`,
25
- `remove-feature.sh.template` — ❌ any missing one. Every caller chains these with `|| true`, so an absent script is a **silent**
24
+ `kanban-move.sh`, `telemetry-send.sh`, `preflight.sh`, `loop.sh`, `loop-detach.sh`,
25
+ `new-feature.sh.template`, `remove-feature.sh.template` — ❌ any missing one.
26
+ `loop-detach.sh` absent is what silently turns `/cohorte-loop` back into a foreground run
27
+ that dies at the 600 s tool ceiling, so name it explicitly rather than folding it into
28
+ "some script is missing". Every caller chains these with `|| true`, so an absent script is a **silent**
26
29
  no-op (no kanban card moves, no telemetry ping, no error anywhere) — this check is the only thing
27
30
  that sees it. Also flag ❌ a `VERSION` **newer than** the other `pipeline/` files (compare mtimes):
28
31
  a version bumped without a full re-copy is a half-done update ⇒ re-run install/update.
@@ -47,6 +50,11 @@ fix only with the human's go-ahead (or hand them the command).
47
50
  it double-prompts) **with a matcher covering both `Bash` and `Task`** — a `Bash`-only matcher
48
51
  leaves the preflight phase gate dead (the 1.3.0–1.3.1 regression). Hook files exist at the
49
52
  registered paths.
53
+ Then the **preflight stamp is local, never versioned**: `git ls-files --error-unmatch
54
+ .claude/preflight.ok` must miss, and `.gitignore` must cover it. A tracked stamp is a ❌ (not a
55
+ ⚠️) — it records the tree it verified, the commit that carries it moves HEAD past that tree, and
56
+ the committed copy lands in every clone and new worktree; the gate then blocks clean trees and
57
+ greens unchecked ones. fix: `git rm --cached .claude/preflight.ok` + add it to `.gitignore`.
50
58
  4. **Retrieval** (if `retrieval.provider` ≠ `none`). Run the SCHEMA.md §Code retrieval health
51
59
  check: CLI resolvable from PATH, `.mcp.json` entry present in PATH-proof launcher form,
52
60
  `.serena/` gitignored, server actually connects.
@@ -67,7 +75,7 @@ fix only with the human's go-ahead (or hand them the command).
67
75
  (the install_id is the human's GDPR erasure key — see SCHEMA.md §Telemetry). Flag ❌ any
68
76
  incoherent state: `enabled: true` with no `install_id` or no `consent_date` (sending without
69
77
  recorded consent — fix: set `enabled: false` until the consent question is re-run), or a
70
- `telemetry:` block missing entirely on a current core (top up via `/update-pipeline`).
78
+ `telemetry:` block missing entirely on a current core (top up via `/cohorte-update-pipeline`).
71
79
  8. **Workflows** (the opt-in execution path — SCHEMA.md §Workflows; the conversational commands
72
80
  stay the default, so failures here are ⚠️ at most, never ❌). Report which path this machine will
73
81
  take and why:
@@ -84,11 +92,16 @@ fix only with the human's go-ahead (or hand them the command).
84
92
  End the check with ONE summary line, e.g.
85
93
  `workflows: available (opt-in — ask to "run the review workflow")` or
86
94
  `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
95
+ 9. **Specs & metrics.** Every `specs/*.md` front-matter `status` is a valid stage — one of
96
+ `draft · frozen · in-progress · in-review · shipped · blocked` (SCHEMA.md §Spec status; the last two
97
+ are written by the `/cohorte-loop` driver, so flagging them would report the pipeline's own state as a
98
+ defect) — excluding
99
+ `_`-prefixed files (the spec template and `specs/_decisions.md`, the decision journal) and
100
+ `specs/refactor-backlog.md`, which `/cohorte-audit` writes as a backlog, not a
101
+ spec, and which has no front-matter to check. A spec left `in-progress`/`blocked` with
102
+ `loop_pass` > 0 is a loop that never finished ⇒ say so and name `/cohorte-loop <id> --resume`. `shipped` specs
90
103
  with a live worktree flagged (see 6). `.claude/pipeline-metrics.jsonl` and `specs/reports/` (the
91
- `/review` report buffer that lets a `/fix` survive a `/clear`) are gitignored. Metrics
104
+ `/cohorte-review` report buffer that lets a `/cohorte-fix` survive a `/clear`) are gitignored. Metrics
92
105
  belong to the **main checkout** — a `pipeline-metrics.jsonl` inside a live feature worktree is a
93
106
  stale-core sign (its lines die at teardown) ⇒ suggest appending its lines to the main checkout's
94
107
  file and deleting the stray.
@@ -5,29 +5,29 @@ argument-hint: <feature_id> [paste REVIEW REPORT]
5
5
  ---
6
6
 
7
7
  You are the **lead**. Run the fix loop for feature **$ARGUMENTS** — the scoped, cheap path after a
8
- `REVISE`/`BLOCK` verdict. The full `/spec` (Mode B) + `/build` path still exists for review returns
9
- that change the *contract*; `/fix` is for everything else.
8
+ `REVISE`/`BLOCK` verdict. The full `/cohorte-spec` (Mode B) + `/cohorte-build` path still exists for review returns
9
+ that change the *contract*; `/cohorte-fix` is for everything else.
10
10
 
11
11
  > Read `PIPELINE.md` §`pipeline-profile` first: `surfaces` (paths + agent names) and `contract`.
12
12
  > _Skip the re-read if it's already in your context this session and unmodified since._
13
13
  >
14
14
  > **Kanban** (SCHEMA.md §Kanban): move card `#$ARGUMENTS` → **Fix** on ingest (it returns to **Review**
15
- > when `/review` re-runs). No-op silently if no board.
15
+ > when `/cohorte-review` re-runs). No-op silently if no board.
16
16
 
17
17
  ## 1. Ingest the report
18
18
 
19
19
  - The report is either pasted after the feature id (a REVIEW REPORT, or failures the human hit by
20
- hand), this session's last `/review` REVIEW REPORT, or — if the context was cleared — read from
21
- `specs/reports/<id>.md`, where `/review` stages its last report for exactly this reason.
20
+ hand), this session's last `/cohorte-review` REVIEW REPORT, or — if the context was cleared — read from
21
+ `specs/reports/<id>.md`, where `/cohorte-review` stages its last report for exactly this reason.
22
22
  If you have none of these, ask for it and wait.
23
- - Append each finding to `specs/<id>.md` **`## Remediation`** (same format as `/spec` Mode B, under a
23
+ - Append each finding to `specs/<id>.md` **`## Remediation`** (same format as `/cohorte-spec` Mode B, under a
24
24
  dated/numbered subheading): `- [ ] <severity> · <file:line> · <type> · <concrete fix>`. Set
25
25
  `status: in-review`. Don't pull the whole spec into context for this: grep the line numbers of the
26
26
  front-matter `status:` and the `## Remediation` heading, then Read only those regions (offset/limit)
27
27
  before editing.
28
28
  - **Contract check:** if any finding implies the frozen contract must change, update spec §5 and
29
- re-author the contract file yourself now (lead-only, per `/build` §2) — agents never edit it. If
30
- the contract change ripples into surfaces *without* findings, fall back to full `/build` instead
29
+ re-author the contract file yourself now (lead-only, per `/cohorte-build` §2) — agents never edit it. If
30
+ the contract change ripples into surfaces *without* findings, fall back to full `/cohorte-build` instead
31
31
  and say so.
32
32
  - **Note the epoch** (`date +%s`) in the first Bash call you make here — §3's metrics line and usage
33
33
  ping both carry `seconds`, and there is no separate timing call.
@@ -39,7 +39,7 @@ that change the *contract*; `/fix` is for everything else.
39
39
  re-dispatch them. Items outside every surface path (contract file, root config) are yours or go
40
40
  to the most relevant surface — say which.
41
41
  - Re-dispatch **ONLY the surfaces owning ≥1 item**, in parallel, in a **single message** — the exact
42
- dispatch template from `/build` §3 (one byte-stable template for builds and fix loops; you do NOT
42
+ dispatch template from `/cohorte-build` §3 (one byte-stable template for builds and fix loops; you do NOT
43
43
  paste a diff — the agent computes its own, scoped to its tree). Fill the template's final variable
44
44
  slot with that surface's open `- [ ]` item lines **verbatim**, so the agent needs no spec re-read to
45
45
  find its work; fill the design slot with `none` when a `uses_design` surface's open items are all
@@ -50,11 +50,16 @@ 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
56
61
  use). Leave genuinely-unaddressed items `- [ ]` so the next loop still sees them. This keeps the
57
- checkbox state honest and stops a later `/fix` from re-dispatching already-fixed items (§2). Ticking
62
+ checkbox state honest and stops a later `/cohorte-fix` from re-dispatching already-fixed items (§2). Ticking
58
63
  here is the lead's job — surface agents own only their tree, never the spec.
59
64
  - **Collapse fully-resolved rounds (keep the spec bounded).** When a whole dated Remediation round is now
60
65
  entirely `- [x]`, replace its item lines with a single summary line (`- <date> — <N> findings, all
@@ -62,10 +67,12 @@ When the agents return:
62
67
  re-reads each loop. Keep any round with ≥1 still-open `- [ ]` item fully expanded (§2's skip logic
63
68
  needs those checkboxes).
64
69
  - Print one status line per surface (`<key> · items fixed <n>/<m> · tests pass/fail`) — do not restate
65
- handoff content — and append ONE metrics line for the batch to `pipeline-metrics.jsonl`
66
- (see `/build` §4, `phase: "fix"`), chaining the opt-in usage ping in the same Bash call
70
+ handoff content — and append ONE metrics line for the batch to the **main checkout's**
71
+ `$(dirname "$(git rev-parse --git-common-dir)")/.claude/pipeline-metrics.jsonl` (never a bare
72
+ relative path: from a feature worktree that writes a stray sink whose lines die at teardown)
73
+ (rules in `/cohorte-build` §4, `phase: "fix"`), chaining the opt-in usage ping in the same Bash call
67
74
  (results = items fixed over items found across surfaces, e.g. `"5/6"`).
68
- - Tell the human: re-test by hand if the failures were runtime ones, and `/review $ARGUMENTS` for the
75
+ - Tell the human: re-test by hand if the failures were runtime ones, and `/cohorte-review $ARGUMENTS` for the
69
76
  re-verdict — the re-review is what *verifies* the ticked items actually hold (a regression simply
70
77
  reappears as a new finding in the next round). **Recommend a `/clear`** — all state (spec,
71
78
  checkboxes, staged report) is on disk, and the lead's history is re-sent at input price every turn.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: Detect this project's stack, interview the gaps, and generate PIPELINE.md + render the agents so the portable pipeline fits this repo.
3
- argument-hint: (none) — one-time per project; afterwards /update-pipeline keeps everything current
3
+ argument-hint: (none) — one-time per project; afterwards /cohorte-update-pipeline keeps everything current
4
4
  ---
5
5
 
6
6
  You are the **pipeline installer**. Your job: turn the generic pipeline into one tailored to **this**
@@ -0,0 +1,110 @@
1
+ ---
2
+ model: sonnet
3
+ description: Autonomous /cohorte-build → /cohorte-review → /cohorte-fix → /cohorte-review loop for one feature, until no blocking finding remains.
4
+ argument-hint: <feature_id> [--max=N] [--no-build] [--rebuild] [--resume]
5
+ allowed-tools: Bash(bash ~/.claude/pipeline/scripts/loop-detach.sh:*), Bash(bash .claude/pipeline/scripts/loop-detach.sh:*), Bash(test:*), Read(specs/reports/**)
6
+ disable-model-invocation: true
7
+ ---
8
+
9
+ You are the **launcher**, not the loop. Run the driver for **$ARGUMENTS** and relay three lines.
10
+
11
+ > **The driver's name has moved twice.** It was `/loop`, which Claude Code's own built-in `/loop`
12
+ > (run a prompt on a recurring interval) silently **shadowed** — typing `/loop <id>` started the
13
+ > interval runner with the feature id as its prompt, so the driver never ran and the session
14
+ > reported a loop that did not exist. 1.6.0 renamed it `/drive` to escape that. 2.0.0 prefixed
15
+ > every command with `cohorte-`, which makes shadowing impossible by construction, so the accurate
16
+ > name is back: **`/cohorte-loop`**. The shipped script keeps its `loop.sh` name throughout.
17
+ >
18
+ > This command exists because a slash command cannot `/clear` itself. Every phase of the loop runs
19
+ > as a **separate `claude -p` child session** with its own fresh context, driven by a bash script —
20
+ > so the diff, the N review reports and the N contracts never accumulate in YOUR history, which is
21
+ > re-sent at input price on every turn. Running the loop conversationally here would cost more than
22
+ > the loop saves.
23
+
24
+ ## 1. Launch — detached, then poll
25
+
26
+ The driver runs for **hours**, which rules out running it as one foreground Bash call: a single
27
+ call is capped at 600 s, and a backgrounded one is not detached — the child stays in this session's
28
+ process group, so a Claude Code restart, crash or laptop sleep kills `loop.sh` and every `claude -p`
29
+ child with it, mid-write. `loop-detach.sh` puts the driver in its own `screen` session so it
30
+ survives all of that, and `loop.sh` re-execs itself under `caffeinate` so idle sleep cannot abort
31
+ its in-flight requests either.
32
+
33
+ Launch — returns immediately:
34
+
35
+ ```
36
+ test -f .claude/pipeline/scripts/loop-detach.sh \
37
+ && bash .claude/pipeline/scripts/loop-detach.sh start $ARGUMENTS \
38
+ || bash ~/.claude/pipeline/scripts/loop-detach.sh start $ARGUMENTS
39
+ ```
40
+
41
+ Then poll. Each call blocks up to ~9 min (inside the tool ceiling) and prints the **status file** —
42
+ one line per phase, plus `__EXIT__ <code>` when the run is over:
43
+
44
+ ```
45
+ bash ~/.claude/pipeline/scripts/loop-detach.sh wait <feature_id>
46
+ ```
47
+
48
+ **Repeat `wait` until you see `__EXIT__ <code>`.** A `__RUNNING__` line means the driver is still
49
+ working and nothing is wrong — call `wait` again. Never conclude anything from a `__RUNNING__`;
50
+ the run has not finished and you have no verdict to report. If the human says to stop waiting,
51
+ tell them the run continues detached and how to follow it (`screen -r cohorte-<id>`) — do not
52
+ kill it unless they ask.
53
+
54
+ Pass `$ARGUMENTS` through untouched — `loop.sh` owns its own flag parsing (`--max=N`,
55
+ `--no-build`, `--rebuild`, `--resume`) and exits 64 on anything it doesn't know. Don't validate flags
56
+ yourself, don't rewrite them, don't add any.
57
+
58
+ **One lid-close caveat to pass on** if the human is walking away from a laptop: `caffeinate` holds
59
+ off *idle* sleep, but no userspace assertion can prevent lid-close sleep. Lid open, or clamshell
60
+ mode (AC + external display + external input).
61
+
62
+ **Resume is the human's call, not yours.** The loop records its position in the spec's front-matter
63
+ (`status: in-progress` · `loop_pass` · `loop_phase` — SCHEMA.md §Spec status), so a run killed by a
64
+ dead session, a ceiling or a `blocked` exit can continue with `--resume` instead of re-paying the
65
+ passes it already made. If the human types `/cohorte-loop <id>` on a spec whose front-matter says
66
+ `status: in-progress` or `blocked` with `loop_pass` > 1, say so in one line and ask whether to resume
67
+ or restart — never silently add the flag, and never silently restart from pass 1.
68
+
69
+ **Never read `specs/reports/<id>.loop.log`.** It holds the full transcript of every child session —
70
+ the entire diff, every review report, every fix handoff. Pulling it into this session re-imports
71
+ exactly the context the loop was built to keep out, and it is the one mistake that turns this
72
+ command into the most expensive one in the pipeline. Point the human at the path instead; they can
73
+ open it in an editor for free. The same goes for the per-surface `.diff` and `.preflight.txt` files.
74
+
75
+ `<id>.loop.status` is the **other** file and is safe: it is the driver's stdout, one line per phase.
76
+ `wait` already prints it, so you never need to Read it yourself. Two files, one letter apart —
77
+ `.log` is the expensive one.
78
+
79
+ ## 2. Report — three lines, from the exit code
80
+
81
+ `wait` prints one line per phase, one closing line, and `__EXIT__ <code>`; that is your raw
82
+ material, and that code is the exit code the table below is keyed on. For exit
83
+ **1** or **3** only, also Read `specs/reports/<id>.verdict.json` (small, structured, safe) to name
84
+ the remaining findings — never the markdown report, which is the findings body in full. For exit
85
+ **4**, Read `specs/reports/<id>.readiness.json` instead (also small) and relay its `gaps`. On any
86
+ other exit the closing line already carries the deferred count, so read nothing.
87
+
88
+ | exit | meaning | what to say |
89
+ | ---- | ------- | ----------- |
90
+ | `0` | clean | no blocking findings left; the human can `/cohorte-ship <id>` |
91
+ | `1` | ceiling hit | the fix was progressing but ran out of passes ⇒ re-run with a higher `--max` |
92
+ | `2` | no usable verdict | `/cohorte-review` produced nothing, or aborted on a red preflight — the closing line says which; point at `specs/reports/<id>.preflight.txt` |
93
+ | `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) |
94
+ | `4` | not implementable | `/cohorte-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 `/cohorte-spec <id>`. More passes cannot fix this |
95
+ | `64` | usage | relay the script's own message verbatim |
96
+
97
+ Then print exactly three lines and nothing else — plus a fourth **only when the verdict carries
98
+ `deferred` > 0** (findings that were real but out of this feature's scope, parked in the backlog by
99
+ `/cohorte-review` §3.5; they are not blocking and never cost a pass, but they are not nothing either):
100
+
101
+ ```
102
+ outcome: <one clause — clean / ceiling / no verdict / non-convergent / not implementable / usage>
103
+ iterations: <n> review pass(es)<, m fix pass(es) committed>
104
+ remaining: <blocking count + one short phrase per blocking item, or "none">
105
+ deferred: <n> parked in specs/refactor-backlog.md — /cohorte-refactor <domain> when you want them
106
+ ```
107
+
108
+ Add at most one follow-up sentence: the next command to run. Never restate a finding's fix, never
109
+ summarize the log, never open the diff. Each fix pass is already committed
110
+ (`loop(<id>): fix pass <i>`) — say so on a non-zero exit, since those commits are the way back.
@@ -4,7 +4,7 @@ description: Apply the refactor backlog for one or more domains via the surface
4
4
  argument-hint: <domain…> (one or more surface keys, "shared", or "all")
5
5
  ---
6
6
 
7
- You are the **lead**. Refactor domain **$ARGUMENTS** to match `PIPELINE.md`, using the `/audit` backlog.
7
+ You are the **lead**. Refactor domain **$ARGUMENTS** to match `PIPELINE.md`, using the `/cohorte-audit` backlog.
8
8
 
9
9
  > Read `PIPELINE.md` §`surfaces` (map the domain → a surface + its agent + commands) and §`contract`.
10
10
  >
@@ -50,7 +50,7 @@ slices import it, so refactor it alone, first.
50
50
  After each agent returns: its surface's `test_quiet_cmd`/`lint_quiet_cmd` (else the `tail -40`
51
51
  fallback — SCHEMA.md §Output discipline), `commands.typecheck`, `commands.format --check` (redirect
52
52
  output to a file and grep it — don't print gate output into your context). Then verify each backlog item cleared by checking its `file:line` directly — do NOT re-run
53
- `/audit` per round (that repeats the repo-wide gates + a review dispatch you don't need); one optional
54
- final `/audit` once ALL dispatched domains are clean is enough. Check cleared items off in
53
+ `/cohorte-audit` per round (that repeats the repo-wide gates + a review dispatch you don't need); one optional
54
+ final `/cohorte-audit` once ALL dispatched domains are clean is enough. Check cleared items off in
55
55
  `specs/refactor-backlog.md`. Loop until each dispatched domain is clean. Verification is per-domain
56
56
  even when the dispatch was parallel — one failing surface loops alone, the others don't redo work.