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
package/profile/SCHEMA.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # PIPELINE.md profile — field reference
2
2
 
3
- `/init-pipeline` fills the `yaml pipeline-profile` block in `PIPELINE.md` (from
3
+ `/cohorte-init-pipeline` fills the `yaml pipeline-profile` block in `PIPELINE.md` (from
4
4
  `PIPELINE.template.md`) plus the prose sections. This documents every field and how the
5
5
  generic pipeline uses it, so a stateless agent can read/regenerate the profile correctly.
6
6
 
@@ -29,12 +29,12 @@ generic pipeline uses it, so a stateless agent can read/regenerate the profile c
29
29
  | `surfaces[].*_cmd` | string | implementer | test/lint/format/typecheck/build commands. |
30
30
  | `surfaces[].test_quiet_cmd` `.lint_quiet_cmd` | string | implementer, preflight, workflows | Bridled variants agents actually run (dot reporter / `--quiet` / failures-only). `""` ⇒ `<cmd> 2>&1 \| tail -40`. See §Output discipline. |
31
31
  | `surfaces[].uses_design` | bool | build, frontend | Whether this surface consumes designs. |
32
- | `contract.enabled` | bool | build | `false` ⇒ skip contract authoring (§2 of /build). |
32
+ | `contract.enabled` | bool | build | `false` ⇒ skip contract authoring (§2 of /cohorte-build). |
33
33
  | `contract.mechanism` | enum | build, lead | `shared-types-zod`/`openapi`/`protobuf`/`json-schema`/`none`. |
34
34
  | `contract.path` `.ext` `.index` | string | build | Where `<feature_id>` contract is authored + barrel. |
35
35
  | `contract.authored_by` | const `lead` | build | Implementers import it read-only, never edit. |
36
36
  | `commands.*` | string | all | Repo-wide install/dev/lint/format/typecheck/test + migrate. |
37
- | `commands.test_quiet` `.lint_quiet` | string | review, audit, workflows | Repo-wide bridled variants — what the `/review` pre-flight runs. Same fallback as the per-surface ones. |
37
+ | `commands.test_quiet` `.lint_quiet` | string | review, audit, workflows | Repo-wide bridled variants — what the `/cohorte-review` pre-flight runs. Same fallback as the per-surface ones. |
38
38
  | `rbac.enabled` | bool | brainstorm, review | Toggle RBAC personas + authz audit. |
39
39
  | `rbac.hierarchy` | list | review | Highest→lowest role list. |
40
40
  | `design.enabled` | bool | build, frontend, align-ds | `false` ⇒ design steps are no-ops. |
@@ -60,14 +60,14 @@ generic pipeline uses it, so a stateless agent can read/regenerate the profile c
60
60
 
61
61
  - **Conventions** — per-surface rules the implementer follows and review audits.
62
62
  - **Testing** — the TDD contract per surface (what a test must cover, DB isolation).
63
- - **Design brief note** — feeds `/spec` §8 and the Claude Design step.
64
- - **Personas** — the `/brainstorm` panel; include one per RBAC role when `rbac.enabled`.
63
+ - **Design brief note** — feeds `/cohorte-spec` §8 and the Claude Design step.
64
+ - **Personas** — the `/cohorte-brainstorm` panel; include one per RBAC role when `rbac.enabled`.
65
65
 
66
66
  ## How the pieces reference this file
67
67
 
68
68
  - **Agents** (`implementer`, `review`, `release`) are told at dispatch: _read `PIPELINE.md`
69
69
  §Commands / §Conventions / §Surfaces first._ They have `Read`, so they load it live.
70
- - **Commands** (`/build`, `/review`, …) parse the `yaml pipeline-profile` block to know how
70
+ - **Commands** (`/cohorte-build`, `/cohorte-review`, …) parse the `yaml pipeline-profile` block to know how
71
71
  many surfaces to dispatch, the contract mechanism, the commands, and the capability flags.
72
72
  - **Hook** (`gate.py`) reads `gate.deny`/`gate.ask`/`gate.ask_on_default_branch`/`gate.default_branch`
73
73
  from a generated `.claude/gate-config.json`. The last two make git + docker free on feature branches
@@ -87,7 +87,7 @@ follow is provider-agnostic: _"prefer the retrieval MCP tools over Grep/Glob + w
87
87
  | `graphify` | persistent tree-sitter knowledge graph over code + docs | as fresh as the last rescan | index step + re-index discipline |
88
88
  | `none` | agents fall back to Grep/Glob/Read | — | — |
89
89
 
90
- **Wiring (done by `/init-pipeline`, or `/update-pipeline` retroactively):**
90
+ **Wiring (done by `/cohorte-init-pipeline`, or `/cohorte-update-pipeline` retroactively):**
91
91
 
92
92
  - `serena` — requires the `serena` CLI (`uv tool install -p 3.13 serena-agent`). For day-to-day CLI
93
93
  use it should also be on PATH (`uv tool update-shell`; uv installs to `~/.local/bin`). Register at
@@ -113,7 +113,7 @@ follow is provider-agnostic: _"prefer the retrieval MCP tools over Grep/Glob + w
113
113
  - Rendered agents get the provider's MCP tools appended to their `tools:` list (e.g. `mcp__serena`
114
114
  grants the whole server); `none` ⇒ nothing appended.
115
115
 
116
- **Serena health check** — run after wiring in `/init-pipeline` AND on every `/update-pipeline`
116
+ **Serena health check** — run after wiring in `/cohorte-init-pipeline` AND on every `/cohorte-update-pipeline`
117
117
  reconcile (wiring that worked once can rot: PATH changes, tool uninstalled, entry hand-edited):
118
118
 
119
119
  1. **CLI resolves:** `command -v serena`. Fails but `~/.local/bin/serena` exists ⇒ PATH repair
@@ -135,7 +135,7 @@ Grep/Read; the health check above is the diagnostic.
135
135
 
136
136
  ## Specialization — when to split one surface into more agents
137
137
 
138
- `/build` dispatches ONE agent per surface, in parallel, so build wall-clock ≈ the **slowest single
138
+ `/cohorte-build` dispatches ONE agent per surface, in parallel, so build wall-clock ≈ the **slowest single
139
139
  surface**. More agents only build faster when they let the *slowest* surface's work run concurrently —
140
140
  and only if the split is safe. The invariant that keeps parallelism safe is **one owner per tree, and
141
141
  the frozen contract as the only cross-surface channel**. So specialization means carving a surface into
@@ -161,8 +161,8 @@ the frozen contract as the only cross-surface channel**. So specialization means
161
161
  Coarse first, specialize on evidence: start with one `frontend` / `backend` surface each; split only a
162
162
  surface that's proven slow and cleanly separable. The evidence lives in
163
163
  the **main checkout's** `.claude/pipeline-metrics.jsonl` (gitignored) — one JSONL line per phase batch
164
- (`ts`/`feature`/`phase`/`seconds`/`surfaces:{key: result}`), appended by `/build`, `/review`
165
- and `/fix`.
164
+ (`ts`/`feature`/`phase`/`seconds`/`surfaces:{key: result}`), appended by `/cohorte-build`, `/cohorte-review`
165
+ and `/cohorte-fix`.
166
166
  **`surfaces` keys are surface keys, nothing else** — run-level facts go in their own top-level
167
167
  fields. Anything put inside `surfaces` is read
168
168
  as a surface: the dashboard renders it as a row in the per-surface table and scores a non-`ok`
@@ -178,8 +178,8 @@ what's SLOW. It deliberately does NOT record tokens: the lead can't reliably rea
178
178
  to log it. For what's EXPENSIVE, use Claude Code's own accounting:
179
179
 
180
180
  - **`/cost`** (built-in, zero setup) — reports per-**subagent** and per-**slash-command** share of your usage
181
- over the last 24 h / 7 d (e.g. _"Top subagents: frontend 7 %, backend 4 % · Top skills: /build 1 %,
182
- /review 1 %"_). That IS the per-phase ledger — approximate (share-of-total, machine-local, not exact
181
+ over the last 24 h / 7 d (e.g. _"Top subagents: frontend 7 %, backend 4 % · Top skills: /cohorte-build 1 %,
182
+ /cohorte-review 1 %"_). That IS the per-phase ledger — approximate (share-of-total, machine-local, not exact
183
183
  tokens). Read it to see which surface/command actually dominates the bill before you tune a `model` tier.
184
184
  - **OpenTelemetry** (exact numbers + dashboards) — add an `env` block to `~/.claude/settings.json`:
185
185
  `{"env":{"CLAUDE_CODE_ENABLE_TELEMETRY":"1","OTEL_METRICS_EXPORTER":"otlp","OTEL_EXPORTER_OTLP_PROTOCOL":"http/protobuf","OTEL_EXPORTER_OTLP_ENDPOINT":"http://localhost:4318"}}`
@@ -207,31 +207,158 @@ context. The profile therefore stores **two forms of each noisy command**:
207
207
  (`--reporter=dot`, `--quiet`, `-q`, `--silent`, framework equivalent) so a green run costs lines,
208
208
  not pages, and a red run prints only the failures.
209
209
 
210
- Rules for every consumer (implementers, preflight, `/audit` gates, workflow agents):
210
+ Rules for every consumer (implementers, preflight, `/cohorte-audit` gates, workflow agents):
211
211
 
212
212
  1. Run the quiet variant when set.
213
213
  2. Quiet variant empty/absent (older profile) ⇒ run `<full cmd> 2>&1 | tail -40` — never the bare
214
214
  command into your context.
215
215
  3. Need the full log? Redirect it to a file and grep it; never print it.
216
216
 
217
- `/init-pipeline` **asks** for these variants (detected defaults offered first) instead of silently
218
- storing a bare `pnpm test` as the thing agents execute; `/update-pipeline` tops up older profiles.
217
+ `/cohorte-init-pipeline` **asks** for these variants (detected defaults offered first) instead of silently
218
+ storing a bare `pnpm test` as the thing agents execute; `/cohorte-update-pipeline` tops up older profiles.
219
+
220
+ ## Spec status — the lifecycle state machine (and the loop's resume state)
221
+
222
+ A spec's front-matter `status` is not a label, it is the pipeline's **state**: every command routes on
223
+ it, the dashboard boards on it, the kanban backfill maps it to a column, and `/cohorte-loop --resume` reads it
224
+ back to continue an interrupted autonomous run. Six states, and exactly one writer each:
225
+
226
+ | status | meaning | written by | who may build it |
227
+ | --- | --- | --- | --- |
228
+ | `draft` | the interview is open, nothing is frozen | `/cohorte-spec` Mode A | no |
229
+ | `frozen` | the contract is frozen — the handoff to `/cohorte-build` | `/cohorte-spec` Mode A freeze | yes |
230
+ | `in-progress` | a `/cohorte-loop` is driving this spec right now (or died doing it) | `scripts/loop.sh`, before each phase | yes |
231
+ | `in-review` | reviewed / awaiting the next round or `/cohorte-ship` | `/cohorte-spec` Mode B, `/cohorte-fix`, `loop.sh` on a clean exit | yes |
232
+ | `blocked` | a loop gave up here (ceiling, non-convergent, no verdict, not implementable) | `loop.sh` on any non-zero exit | yes, with the reason named |
233
+ | `shipped` | the PR is open; the status flip is part of the release commit | `/cohorte-ship` | no |
234
+
235
+ **The resume contract.** Before every phase, `loop.sh` stamps `status: in-progress` plus `loop_pass`
236
+ (the review pass it is on) and `loop_phase` (`build`/`review`/`fix`) into the spec — deterministically,
237
+ with `awk`, spending **no tokens** on state it will need later. On exit it stamps a terminal status:
238
+ `in-review` + `loop_phase: done` when clean, `blocked` otherwise. `/cohorte-loop <id> --resume` then continues
239
+ at the recorded pass instead of pass 1, so a session killed at pass 3 of 5 does not re-pay passes 1–2.
240
+ The build is still skipped or redone by the build stamp alone (`specs/reports/<id>.built`, written only
241
+ after a build that finished), so an interrupted *build* correctly rebuilds.
242
+
243
+ Corollaries worth knowing:
244
+
245
+ - A spec with no front-matter makes every stamp a **silent no-op** — the state is bookkeeping, and the
246
+ loop must never die over a status line.
247
+ - Child commands write `status` too (`/cohorte-fix` sets `in-review`); re-stamping before each phase is what
248
+ keeps `in-progress` true for the duration of the run rather than for its first phase.
249
+ - `blocked` is not a failure to hide: it is the resumable state. `/cohorte-build` accepts it, names it, and
250
+ routes by the spec's `## Remediation` (open items ⇒ `/cohorte-fix`).
251
+
252
+ ## Dead agents — silence is not a green light
253
+
254
+ A subagent can die mid-run: a rate limit, a transport error that outlived its retries, its own context
255
+ exhausted on a big surface. When it does it returns **nothing** — and nothing is byte-identical to
256
+ "finished, nothing to report". Every phase that fans out therefore does a **roll call** before it
257
+ integrates anything, because the default reading of silence is the most dangerous one available:
258
+
259
+ | phase | what a dead agent looks like | what the phase must do |
260
+ | --- | --- | --- |
261
+ | `/cohorte-build` | a surface with no handoff | retry it **once** alone (byte-identical prompt), then mark it `dead`, verify the tree with that surface's own quiet commands, never call the batch ok |
262
+ | `/cohorte-review` | a reviewer with no report ⇒ **zero findings** | retry once, then list the surface in `unreviewed` and refuse to score `SHIP` |
263
+ | `/cohorte-fix` | a re-dispatched agent with no handoff | retry once, then leave **every** one of its items `- [ ]` — a dead agent never ticks a box |
264
+ | workflows | `agent()` resolves to `null` | already enforced (`review.js` `unreviewedSurfaces`) — the doctrine started here |
265
+
266
+ Non-negotiables, in every phase:
267
+
268
+ - **Retry once, alone, byte-identical.** Most deaths are transient, and the other surfaces' work is
269
+ already on disk — so recovery costs one agent, never a rebuild. Never retry an agent that answered.
270
+ - **Never speak for a dead agent.** You did not see its work: report what the *tree* says (quiet
271
+ commands, redirected to a file, grepped), not what a handoff would have said.
272
+ - **Never let it reach a driver as clean.** `/cohorte-build` writes `dead[]` into
273
+ `specs/reports/<id>.build.json`, `/cohorte-review` writes `unreviewed[]` into the verdict; `scripts/loop.sh`
274
+ aborts on either with **exit 2** *before* it reads `blocking`, since a dead reviewer makes
275
+ `blocking == 0` a statement about code nobody read.
276
+ - **`unreviewed` is separate from `blocking` on purpose.** Faking a count in `blocking` to force a
277
+ driver's hand would corrupt the one field the whole contract rests on; a driver reads them as two
278
+ different facts — "what was found" and "what was covered".
279
+ - **Write the metrics line anyway** (`"<key>":"dead"`). An incomplete batch is exactly the batch worth
280
+ recording; holding the append back "until it's complete" deletes the evidence that anything failed.
281
+
282
+ ## Readiness — the gate between a frozen spec and N implementers
283
+
284
+ `/cohorte-build` §1.6 scores the frozen spec on **implementability** before authoring the contract and before
285
+ dispatching anything, and writes `specs/reports/<id>.readiness.json`
286
+ (`verdict`: `READY` · `RESERVATIONS` · `NOT-READY`, plus `gaps[]`). It costs **zero extra agents** — the
287
+ lead already holds the spec, the profile and the reconciled surface list — which is the whole economics
288
+ of the step: a spec that cannot be built does not get cheaper by being built on N surfaces in parallel.
289
+
290
+ - Five checks: contract completeness · surface coverage · dependencies exist · residual ambiguity ·
291
+ the design gate. Each maps to `NOT-READY` (a surface would have to invent the answer) or
292
+ `RESERVATIONS` (a surface can proceed on a stated assumption).
293
+ - **`NOT-READY` aborts the build with no agent spawned** and sends the human to `/cohorte-spec`.
294
+ `scripts/loop.sh` reads the same file and exits **4** (`not implementable`) — the one loop outcome
295
+ that more passes cannot fix.
296
+ - **`RESERVATIONS` never blocks.** Each gap is inlined verbatim into the dispatch of the surface it
297
+ affects, as an assumption the implementer must apply *and* flag in its handoff. A gate that stalled a
298
+ sound build on a missing error case would cost more human round-trips than it saves.
299
+
300
+ ## Deferred findings — real, but not this feature's problem
301
+
302
+ `/cohorte-review` ends on "zero blocking findings", so everything non-blocking used to be discarded with the
303
+ report. A **deferred** finding is one the reviewer judges true and **out of this feature's scope**
304
+ (pre-existing code the staged diff never touched, adjacent debt the spec never claims to fix). The
305
+ review agent returns them in their own `## Deferred` section — never in `findings` — each carrying its
306
+ own out-of-scope reason.
307
+
308
+ - They count in **no** severity row, enter **no** verdict, and are **never** cross-checked: a deferred
309
+ item cannot cost a fix loop an iteration, and refuting one would spend an agent arguing about
310
+ something that cannot change the outcome.
311
+ - **Not deferrable, ever:** anything the diff touched or introduced, any spec violation, any security
312
+ issue on a path this feature adds, calls or modifies.
313
+ - `/cohorte-review` §3.5 routes them, **on every verdict**, into `specs/refactor-backlog.md` under the
314
+ `## <domain>` heading of the owning surface, tagged `deferred:<feature_id>` — the same grouping
315
+ `/cohorte-audit` writes, so `/cohorte-refactor <domain>` picks them up with no extra plumbing. Never into the spec's
316
+ `## Remediation`, which is what `/cohorte-fix` re-dispatches.
317
+ - `/cohorte-audit` **carries open `deferred:` items over** when it rewrites the backlog; overwriting them away
318
+ is the one way they silently vanish.
319
+ - The verdict JSON carries `deferred: <n>` (informational, outside `blocking`), so `/cohorte-loop` can name
320
+ them in its closing line without reading a report.
321
+
322
+ ## Decisions — the transverse decision journal
323
+
324
+ `PIPELINE.md` is a **stack profile** (surfaces, commands, conventions); it says nothing about what this
325
+ project has *decided*. Without somewhere for those, every `/cohorte-spec` re-discovers or contradicts them.
326
+ `specs/_decisions.md` (from `core/templates/decisions.template.md`) is that place, deliberately small:
327
+
328
+ - **Append-only, one line per decision, ≤ ~160 chars:**
329
+ `- <YYYY-MM-DD> · <area> · <decision> — because <reason> · <feature_id>`. Reversal never edits a line:
330
+ append a superseding one (`· supersedes <date> <area>`) and move the old one to `## Superseded`. When
331
+ `## Live` passes ~100 lines, sweep the superseded ones down.
332
+ - **Written by** `/cohorte-spec` at freeze (the decisions that outlive the feature — typically 0–3 lines, and
333
+ zero is a normal outcome) and `/cohorte-build` §1.5 when it adds or splits a surface.
334
+ - **Read by the deciding stages only** — `/cohorte-brainstorm` (so the panel argues about the idea, not about
335
+ settled ground), `/cohorte-spec` (so a new spec does not silently un-decide something), `/cohorte-audit` (standing
336
+ decisions are part of the rulebook it audits against).
337
+ - **Never read by implementers or reviewers.** They work from the frozen contract, which already tells
338
+ them what to do; shipping them the rationale would cost `surfaces × dispatches` tokens per feature
339
+ for a fact they cannot act on. This is what keeps the journal cheap enough to be worth having.
340
+ - The `_` prefix is load-bearing: `/cohorte-doctor`, the dashboard spec scanner and the kanban backfill all skip
341
+ `specs/_*.md`, so the journal is never mistaken for a spec (no phantom card, no bogus stage).
219
342
 
220
343
  ## Preflight — the deterministic phase gate
221
344
 
222
- `/review` starts by running `pipeline/scripts/preflight.sh` — a plain shell script (no
345
+ `/cohorte-review` starts by running `pipeline/scripts/preflight.sh` — a plain shell script (no
223
346
  agent) that executes the profile's mechanical checks in order (typecheck → lint → tests, quiet
224
347
  variants) with all output redirected to `specs/reports/<id>.preflight.txt`:
225
348
 
226
349
  - **Any check red** ⇒ the script prints the last 40 lines raw and exits 1. The command **aborts
227
350
  there: zero agents are spawned.** A reviewer dispatched onto code that doesn't compile burns its
228
351
  whole run rediscovering what `tsc` already printed for free — the failure goes straight to the
229
- human (or `/fix`) instead.
230
- - **All green** ⇒ the script stamps `.claude/preflight.ok` (`<epoch> <HEAD sha>`).
352
+ human (or `/cohorte-fix`) instead.
353
+ - **All green** ⇒ the script stamps `.claude/preflight.ok` (`<epoch> <HEAD sha> <tree digest>`
354
+ local and **gitignored**; a versioned stamp describes the tree *before* its own commit and rides
355
+ into every clone and worktree, which breaks the gate both ways).
231
356
 
232
357
  `hooks/gate.py` enforces the stamp as a **phase gate** (the `preflight` block of `gate-config.json`,
233
358
  generated from `gate.preflight`): a Task dispatch of a listed `subagent_type` (default
234
- `review`) with a missing/stale stamp — older than `max_age_minutes`, or HEAD moved gets an
359
+ `review`) with a missing/stale stamp — older than `max_age_minutes`, or the digest no longer
360
+ matches the working tree (`.claude` and `specs` excluded, so the pipeline's own writes and a
361
+ commit of already-verified code do not invalidate it) — gets an
235
362
  "ask", so a lead can't accidentally skip the gate but a human can consciously override it. The gate
236
363
  hook fires for **every** agent in the session, including subagents spawned by the Workflow runtime
237
364
  (they run in `acceptEdits` whatever the session mode — Write/Edit auto-approved — but Bash and Task
@@ -240,7 +367,7 @@ hard deny, because nobody is there to answer a prompt.
240
367
 
241
368
  ## Rendering / reconciling a surface agent (shared procedure)
242
369
 
243
- Both `/init-pipeline` (initial render) and `/build` (auto-reconcile when a spec needs a new agent) use
370
+ Both `/cohorte-init-pipeline` (initial render) and `/cohorte-build` (auto-reconcile when a spec needs a new agent) use
244
371
  this exact procedure so a surface is always defined the same way. To add surface `S`:
245
372
 
246
373
  1. **Add the `surfaces[]` entry** to `PIPELINE.md`: `key`, `path` (the disjoint tree it exclusively
@@ -259,7 +386,7 @@ this exact procedure so a surface is always defined the same way. To add surface
259
386
  **baked at render time**: `PIPELINE.md` §Conventions `### Shared` + this surface's
260
387
  `### Surface: <key>` stanza + its §Testing lines, verbatim. At runtime the agent then reads only
261
388
  the profile's machine block (the fenced `yaml pipeline-profile`) — never the prose sections. The
262
- bake stays honest because §Conventions edits go through `/update-pipeline`, whose reconcile
389
+ bake stays honest because §Conventions edits go through `/cohorte-update-pipeline`, whose reconcile
263
390
  re-renders every agent (step 2 below); hand-edit the prose without re-rendering and the baked
264
391
  slice goes stale — that's the trade for not re-reading the prose on every dispatch. For a `uses_design` surface, fill them **link-based** (never with a
265
392
  stored `design_project` id — that goes stale on a DS rebuild):
@@ -287,7 +414,7 @@ conventions. Never leave an agent file with no matching `surfaces[]` entry (orph
287
414
 
288
415
  ## Reconcile — bringing generated files up to the current core
289
416
 
290
- `/init-pipeline` is **one-time per project**. Afterwards, `/update-pipeline` runs this procedure so a
417
+ `/cohorte-init-pipeline` is **one-time per project**. Afterwards, `/cohorte-update-pipeline` runs this procedure so a
291
418
  core upgrade never requires re-running init — new pipeline features flow into the repo's generated
292
419
  files automatically. It works because every generated artifact is a **deterministic function of
293
420
  (current template × the profile's data)**; nothing needs re-detecting or re-interviewing.
@@ -305,7 +432,7 @@ files automatically. It works because every generated artifact is a **determinis
305
432
  init spec (missing `allow` entries, hooks per install mode) — add what's missing, never remove or
306
433
  rewrite existing/custom keys.
307
434
  4. **Capability wiring.** If a top-up added a capability needing external setup (e.g. a `retrieval`
308
- provider whose MCP server isn't registered yet), run its wiring step from `/init-pipeline` Phase 4.
435
+ provider whose MCP server isn't registered yet), run its wiring step from `/cohorte-init-pipeline` Phase 4.
309
436
  Even when nothing new was added, re-run the provider's health check (§Code retrieval) — wiring
310
437
  rots (PATH changes, uninstalls, hand-edits) — and repair whatever fails.
311
438
  5. **Global config seed.** If `~/.claude/cohorte.config.yaml` is absent, seed it from the template
@@ -313,21 +440,38 @@ files automatically. It works because every generated artifact is a **determinis
313
440
  clobber an existing filled file; report what was seeded.
314
441
  6. **Kanban sync.** Run the §Kanban reconcile: link/create the project's board if configured, verify
315
442
  its columns, and backfill/sync cards from `specs/*.md`. See §Kanban.
316
-
317
- Re-running `/init-pipeline` remains possible (it reconciles too) but is only *needed* when the stack
318
- itself changes in ways `/build` §1.5 can't auto-grow (e.g. package manager or contract mechanism swap).
443
+ 7. **Spec-template top-up.** `specs/_template.md` is seeded once at install and then **never**
444
+ refreshed, so a repo keeps whatever front-matter the core shipped the day it was installed (a
445
+ pre-1.6 copy has no `loop_pass`/`loop_phase`, and its `status` comment still lists four states).
446
+ Top it up the same way as the profile: add the **front-matter fields** the current
447
+ `templates/spec.template.md` has and the repo's copy lacks, with their documented defaults, and
448
+ refresh the `status:` comment. Never rewrite its body — the section list is the human's to shape,
449
+ and some repos have deliberately trimmed it. Nothing breaks without this (the fields are written on
450
+ demand when a driver needs them); it just keeps a new spec's front-matter honest about the states
451
+ the pipeline can put it in.
452
+
453
+ 8. **Local-artifact hygiene.** The pipeline's own runtime files must stay out of git:
454
+ `.claude/preflight.ok`, `.claude/pipeline-metrics.jsonl`, `specs/reports/`. Add any missing entry to
455
+ `.gitignore`, and **untrack** what a pre-2.0.0 install let slip in —
456
+ `git rm --cached --ignore-unmatch .claude/preflight.ok` (repeat per stray path). The stamp is the
457
+ one that actively breaks: it records the tree it verified, the commit carrying it moves HEAD past
458
+ that tree, and the committed copy lands in every clone and worktree — so the phase gate ends up
459
+ blocking clean trees and greening unchecked ones. Report what was untracked; the human commits it.
460
+
461
+ Re-running `/cohorte-init-pipeline` remains possible (it reconciles too) but is only *needed* when the stack
462
+ itself changes in ways `/cohorte-build` §1.5 can't auto-grow (e.g. package manager or contract mechanism swap).
319
463
 
320
464
  ## Workflows — deterministic multi-agent runs (opt-in)
321
465
 
322
466
  Three phases have a **workflow variant** — a deterministic orchestration script the Claude Code
323
467
  Workflow runtime executes instead of the lead reasoning out the fan-out turn by turn:
324
468
  `<core>/workflows/review.js`, `audit.js`, `refactor.js` (installed to `.claude/workflows/` bundled or
325
- `~/.claude/workflows/` global). The conversational commands (`/review`, `/audit`, `/refactor`)
469
+ `~/.claude/workflows/` global). The conversational commands (`/cohorte-review`, `/cohorte-audit`, `/cohorte-refactor`)
326
470
  **remain the default path and the fallback** — a workflow runs only when the human explicitly asks
327
471
  for it ("run the review workflow"), and requires Claude Code ≥ **2.1.154** with workflows
328
472
  enabled.
329
- `/doctor` reports which path a session will take. The interactive commands (`/init-pipeline`,
330
- `/brainstorm`, `/spec`) and the dispatch-only ones (`/build`, `/ship`) have **no** workflow variant on
473
+ `/cohorte-doctor` reports which path a session will take. The interactive commands (`/cohorte-init-pipeline`,
474
+ `/cohorte-brainstorm`, `/cohorte-spec`) and the dispatch-only ones (`/cohorte-build`, `/cohorte-ship`) have **no** workflow variant on
331
475
  purpose: they're interviews or already a single parallel dispatch — a script adds nothing.
332
476
 
333
477
  Shared design, all four scripts:
@@ -347,19 +491,22 @@ Shared design, all four scripts:
347
491
  that never answered: `review.js` names them in `unreviewedSurfaces` and refuses to score
348
492
  `SHIP`. `scripts/test-workflows.mjs`
349
493
  pins this — it is the one invariant the structural checks in `validate-core.mjs` cannot see.
494
+ The conversational commands enforce the same rule by roll call (§Dead agents); it was the workflows
495
+ that had it first, and for three releases they had it **alone** — the same crash on the
496
+ conversational path went unreported.
350
497
  - **`review.js`** — preflight gate (aborts red, zero agents), one `git diff --stat` staged per
351
498
  touched surface, one reviewer per surface in parallel, then an **adversarial cross-check** phase
352
499
  that tries to refute each CRITICAL/security finding before it can trigger a fix loop.
353
500
  - **`audit.js`** — one auditor per domain (each surface + `shared`), concurrency capped by the
354
501
  runtime (~16), merged into the prioritized `specs/refactor-backlog.md`.
355
502
  - **`refactor.js`** — big domains only (it skips domains with a handful of open items — the
356
- conversational `/refactor` is cheaper there): `shared` first and alone, then the other domains'
503
+ conversational `/cohorte-refactor` is cheaper there): `shared` first and alone, then the other domains'
357
504
  implementers in parallel, each verified per-domain.
358
505
  - **No input mid-run.** A workflow runs to completion without questions; anything interactive
359
506
  (contract changes, human decisions) belongs to the conversational path. The gate hook still
360
507
  fires on workflow subagents (see
361
508
  §Preflight) — in unattended runs its asks become denies.
362
- - **Permissions:** `/init-pipeline` and `/update-pipeline` extend the generated `settings.json`
509
+ - **Permissions:** `/cohorte-init-pipeline` and `/cohorte-update-pipeline` extend the generated `settings.json`
363
510
  `allow` list with what workflow agents need (the quiet commands, the shipped
364
511
  `pipeline/scripts/*.sh`, read-only git incl. `git rev-parse`, and the retrieval provider's MCP
365
512
  tools) so a run never stalls mid-workflow on a permission prompt nobody is watching.
@@ -382,11 +529,11 @@ present else `kanban.columns`. Not found ⇒ kanban off for this project.
382
529
  **Card format.** A card is a Kanban list item under a `## <column>` heading:
383
530
  `- [ ] <human title> #<feature_id>`. The `#<feature_id>` tag is the join key between a card and its
384
531
  `specs/<feature_id>.md`; it is how every stage finds *its* card (Grep the board for `#<id>`). Free-text
385
- notes a human writes as sub-bullets under an Ideas card are seed context for `/brainstorm`. Never touch
532
+ notes a human writes as sub-bullets under an Ideas card are seed context for `/cohorte-brainstorm`. Never touch
386
533
  the trailing `%% kanban:settings … %%` block or the `kanban-plugin: board` front-matter.
387
534
 
388
- Once shipped, `/ship` appends the **PR number** to the card — `- [ ] <title> #<feature_id> — PR #<num>`.
389
- The bare `#<num>` is what the dashboard renders as a clickable link to the GitHub PR, so `/ship` always
535
+ Once shipped, `/cohorte-ship` appends the **PR number** to the card — `- [ ] <title> #<feature_id> — PR #<num>`.
536
+ The bare `#<num>` is what the dashboard renders as a clickable link to the GitHub PR, so `/cohorte-ship` always
390
537
  writes it when a PR was actually created.
391
538
 
392
539
  **Move a card (the core op).** Use the shipped script — it does the whole op outside the agent's
@@ -405,18 +552,22 @@ card created in the target column if missing.
405
552
  | Pipeline moment | Column |
406
553
  | --------------------------------------- | --------------- |
407
554
  | human drops a raw idea (manual) | `ideas` |
408
- | `/brainstorm` picks it up | `brainstorm` |
409
- | `/spec` opens (draft) | `spec` |
410
- | `/spec` freezes (`status: frozen`) | `ready` |
411
- | `/build` | `building` |
412
- | `/review` | `review` |
413
- | `/fix` | `fix` |
414
- | `/ship` starts | `ship` |
555
+ | `/cohorte-brainstorm` picks it up | `brainstorm` |
556
+ | `/cohorte-spec` opens (draft) | `spec` |
557
+ | `/cohorte-spec` freezes (`status: frozen`) | `ready` |
558
+ | `/cohorte-build` | `building` |
559
+ | `/cohorte-review` | `review` |
560
+ | `/cohorte-fix` | `fix` |
561
+ | a `/cohorte-loop` is driving it (`in-progress`) | the current phase's column |
562
+ | a `/cohorte-loop` gave up (`blocked`) | `fix` |
563
+ | `/cohorte-ship` starts | `ship` |
415
564
  | PR opened (`status: shipped`) | `shipped` (+ `PR #<num>` on the card) |
416
565
 
417
566
  **Backfill / sync from specs (reconcile).** `specs/*.md` is the source of truth. For each spec, read its
418
567
  `feature_id` (front-matter or filename) and `status`, map `status`→column — `frozen`→`ready`,
419
- `in-review`→`review`, `shipped`→`shipped`, anything else / a spec with no status→`spec` then **full
568
+ `in-progress`→the `loop_phase`'s column (`build`→`building`, `review`→`review`, `fix`→`fix`; unset
569
+ `building`), `in-review`→`review`, `blocked`→`fix`, `shipped`→`shipped`, anything else / a spec with no
570
+ status→`spec` — then **full
420
571
  sync**: card absent ⇒ add it in that column; card present ⇒ **move it** to that column so the board
421
572
  always reflects the specs (this repositions cards the human may have moved by hand). Report cards
422
573
  added vs. moved vs. already-correct.
@@ -429,12 +580,12 @@ per configured column in pipeline order, and the closing `%% kanban:settings %%`
429
580
  ## Telemetry — anonymous usage stats, strictly opt-in (GDPR-first)
430
581
 
431
582
  Cohorte can send the maintainers anonymous usage pings so the pipeline improves where it's actually
432
- slow. **Nothing is ever sent without explicit consent**: `/init-pipeline` (and `/update-pipeline` on
583
+ slow. **Nothing is ever sent without explicit consent**: `/cohorte-init-pipeline` (and `/cohorte-update-pipeline` on
433
584
  pre-telemetry installs) ask ONE question, once per machine, default **No**, and record the answer in
434
585
  `~/.claude/cohorte.config.yaml` §`telemetry` (`enabled`, `install_id`, `consent_date`). The sender —
435
586
  `pipeline/scripts/telemetry-send.sh` — is a silent no-op unless `enabled: true` AND `install_id` AND
436
587
  `endpoint` are all set, times out at 2s, and never fails the pipeline. Callers chain it with
437
- `|| true`, so a **missing** script is equally silent: `/doctor` check 1 verifies `pipeline/scripts/`
588
+ `|| true`, so a **missing** script is equally silent: `/cohorte-doctor` check 1 verifies `pipeline/scripts/`
438
589
  is fully populated.
439
590
 
440
591
  **Which commands ping** — the six that make up the feature funnel, and only those. The point is to
@@ -454,8 +605,8 @@ see where features stall, so every stage of `idea → PR` reports and nothing el
454
605
  > forms are valid — but read the `fix` column knowing which path produced it.
455
606
 
456
607
  `seconds: 0` marks a phase whose duration is human thinking time, not pipeline wall-clock — the
457
- funnel signal there is the event, not how long it took. `/doctor`, `/audit`, `/refactor`,
458
- `/align-ds`, `/init-pipeline` and `/update-pipeline` **never** ping: they sit outside the funnel, and
608
+ funnel signal there is the event, not how long it took. `/cohorte-doctor`, `/cohorte-audit`, `/cohorte-refactor`,
609
+ `/cohorte-align-ds`, `/cohorte-init-pipeline` and `/cohorte-update-pipeline` **never** ping: they sit outside the funnel, and
459
610
  keeping them out is what holds the collected set to what the consent text describes.
460
611
 
461
612
  **What one event contains** (strict allowlist, ~200 bytes):
@@ -475,7 +626,7 @@ work without revealing what is being built.
475
626
  - **Consent** — opt-in only, recorded with a date; "No" is also recorded so nothing re-asks.
476
627
  - **Withdrawal** — set `telemetry.enabled: false` in `~/.claude/cohorte.config.yaml`; effective on
477
628
  the next phase, no restart.
478
- - **Erasure** — `/doctor` prints your `install_id`; send
629
+ - **Erasure** — `/cohorte-doctor` prints your `install_id`; send
479
630
  `curl -X DELETE <endpoint-origin>/v1/install/<install_id>` and the collector drops every event
480
631
  for that id (the deployed collector implements this and stores no IPs).
481
632
  - **Access/portability** — events are keyed by your `install_id`; ask the operator for an export.
@@ -2,7 +2,7 @@
2
2
  # pipeline capabilities. One machine, every project. NOT tied to any project's PIPELINE.md.
3
3
  #
4
4
  # Seeded once by the installer (npx cohorte install) and never clobbered on update. Wired
5
- # interactively by /init-pipeline (new project) and /update-pipeline (existing project) —
5
+ # interactively by /cohorte-init-pipeline (new project) and /cohorte-update-pipeline (existing project) —
6
6
  # you should never need to hand-edit it.
7
7
  #
8
8
  # The `# cfg:<key>` markers below are anchors the installer's interactive prompts write to;
@@ -12,12 +12,12 @@ enabled: true # cfg:enabled — master switch; false disables ev
12
12
 
13
13
  # ── telemetry (anonymous usage stats — OPT-IN, GDPR-first) ──────────────────
14
14
  # Strictly opt-in: nothing is ever sent unless YOU said yes to the consent question
15
- # (/init-pipeline or /update-pipeline ask once per machine; they record your answer here).
15
+ # (/cohorte-init-pipeline or /cohorte-update-pipeline ask once per machine; they record your answer here).
16
16
  # What is sent when enabled: core version, OS, phase name, wall-clock seconds, per-surface
17
17
  # result counts, and a SHA-256 HASH of the feature id — never repo names, paths, code, spec
18
- # content, emails, or IPs. One ping per pipeline phase, /brainstorm through /ship; setup and
19
- # maintenance commands (/doctor, /init-pipeline, /update-pipeline, /audit, /refactor,
20
- # /align-ds) never ping. Sent fire-and-forget (2s timeout, silent on failure) by
18
+ # content, emails, or IPs. One ping per pipeline phase, /cohorte-brainstorm through /cohorte-ship; setup and
19
+ # maintenance commands (/cohorte-doctor, /cohorte-init-pipeline, /cohorte-update-pipeline, /cohorte-audit, /cohorte-refactor,
20
+ # /cohorte-align-ds) never ping. Sent fire-and-forget (2s timeout, silent on failure) by
21
21
  # pipeline/scripts/telemetry-send.sh. Withdraw anytime: set enabled: false. Erase your history:
22
22
  # see SCHEMA.md §Telemetry (DELETE by install_id).
23
23
  telemetry:
@@ -33,9 +33,9 @@ obsidian:
33
33
  vault_path: "" # cfg:vault_path
34
34
 
35
35
  # ── kanban (dev pipeline mirror) ─────────────────────────────────────────────
36
- # Mirrors /brainstorm…/ship onto an Obsidian Kanban board — one board per project. The
36
+ # Mirrors /cohorte-brainstorm…/cohorte-ship onto an Obsidian Kanban board — one board per project. The
37
37
  # board path points at your PERSONAL vault, so it is machine-specific and lives here (never
38
- # committed in a repo's PIPELINE.md). /init-pipeline + /update-pipeline write `boards` for you.
38
+ # committed in a repo's PIPELINE.md). /cohorte-init-pipeline + /cohorte-update-pipeline write `boards` for you.
39
39
  # See SCHEMA.md §Kanban.
40
40
  kanban:
41
41
  enabled: false # cfg:kanban_enabled — master switch for the kanban mirror
@@ -52,7 +52,7 @@ kanban:
52
52
  ship: "Ship"
53
53
  shipped: "Shipped"
54
54
  # One entry per project, keyed by the project's PIPELINE.md `name` (e.g. SAMO). `board` is a
55
- # path RELATIVE to obsidian.vault_path. Written by /init-pipeline + /update-pipeline.
55
+ # path RELATIVE to obsidian.vault_path. Written by /cohorte-init-pipeline + /cohorte-update-pipeline.
56
56
  boards: {}
57
57
  # SAMO:
58
58
  # board: "Samo/Tasks.md"