cohorte 2.10.0 → 3.0.0-dev.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 (211) hide show
  1. package/README.md +7 -0
  2. package/assets/manifest.json +193 -0
  3. package/assets/migrations/config/README.md +12 -0
  4. package/assets/migrations/state/0001_init.sql +154 -0
  5. package/assets/prompts/README.md +11 -0
  6. package/assets/prompts/agents/fixer.md +7 -0
  7. package/assets/prompts/agents/implementer.md +12 -0
  8. package/assets/prompts/agents/reviewer.md +8 -0
  9. package/assets/prompts/agents/security-reviewer.md +7 -0
  10. package/assets/prompts/phases/build.md +5 -0
  11. package/assets/prompts/phases/review.md +5 -0
  12. package/assets/prompts/phases/test.md +5 -0
  13. package/assets/prompts/system.md +11 -0
  14. package/assets/schemas/agent-output.schema.json +225 -0
  15. package/assets/schemas/auth-status.schema.json +87 -0
  16. package/assets/schemas/command-result.schema.json +192 -0
  17. package/assets/schemas/commands.schema.json +952 -0
  18. package/assets/schemas/config.schema.json +2259 -0
  19. package/assets/schemas/doctor-report.schema.json +104 -0
  20. package/assets/schemas/events.schema.json +8514 -0
  21. package/assets/schemas/fake-script.schema.json +549 -0
  22. package/assets/schemas/inspect.schema.json +3133 -0
  23. package/assets/schemas/manifest.schema.json +79 -0
  24. package/assets/schemas/ownership.schema.json +52 -0
  25. package/assets/schemas/policy-verdict.schema.json +282 -0
  26. package/assets/schemas/project-model.schema.json +783 -0
  27. package/assets/schemas/project-status.schema.json +217 -0
  28. package/assets/schemas/reconcile-plan.schema.json +155 -0
  29. package/assets/schemas/run-diff.schema.json +177 -0
  30. package/assets/schemas/run-snapshot-manifest.schema.json +2104 -0
  31. package/assets/schemas/run-state.schema.json +1755 -0
  32. package/assets/schemas/runtime-capabilities.schema.json +1545 -0
  33. package/assets/schemas/sandbox-capabilities.schema.json +116 -0
  34. package/assets/schemas/skill.schema.json +87 -0
  35. package/assets/schemas/spec.schema.json +202 -0
  36. package/assets/schemas/tool-catalogue.schema.json +655 -0
  37. package/assets/schemas/trust-record.schema.json +38 -0
  38. package/assets/skills/README.md +9 -0
  39. package/assets/skills/inspect-surface.md +4 -0
  40. package/dist/agent-host.mjs +50 -0
  41. package/dist/agent-host.mjs.map +1 -0
  42. package/dist/bundle-manifest.json +102 -0
  43. package/dist/chunks/__host-DgGPyco9.mjs +18 -0
  44. package/dist/chunks/__host-DgGPyco9.mjs.map +1 -0
  45. package/dist/chunks/approve-Cv135UqI.mjs +19 -0
  46. package/dist/chunks/approve-Cv135UqI.mjs.map +1 -0
  47. package/dist/chunks/auth-BT5oVp76.mjs +132 -0
  48. package/dist/chunks/auth-BT5oVp76.mjs.map +1 -0
  49. package/dist/chunks/auth-D8rCVY33.mjs +84 -0
  50. package/dist/chunks/auth-D8rCVY33.mjs.map +1 -0
  51. package/dist/chunks/brainstorm-CU10T1tm.mjs +7 -0
  52. package/dist/chunks/brainstorm-CU10T1tm.mjs.map +1 -0
  53. package/dist/chunks/cancel-KV_cpsqS.mjs +15 -0
  54. package/dist/chunks/cancel-KV_cpsqS.mjs.map +1 -0
  55. package/dist/chunks/canonical-C8UxeEmB.mjs +57 -0
  56. package/dist/chunks/canonical-C8UxeEmB.mjs.map +1 -0
  57. package/dist/chunks/catalogue-BvwSrM_j.mjs +1549 -0
  58. package/dist/chunks/catalogue-BvwSrM_j.mjs.map +1 -0
  59. package/dist/chunks/compose-Cr0hP0qm.mjs +7303 -0
  60. package/dist/chunks/compose-Cr0hP0qm.mjs.map +1 -0
  61. package/dist/chunks/config-DefHA2Lw.mjs +96 -0
  62. package/dist/chunks/config-DefHA2Lw.mjs.map +1 -0
  63. package/dist/chunks/contract-B0ra2-bm.mjs +295 -0
  64. package/dist/chunks/contract-B0ra2-bm.mjs.map +1 -0
  65. package/dist/chunks/contract-vYbwYr0Y.mjs +123 -0
  66. package/dist/chunks/contract-vYbwYr0Y.mjs.map +1 -0
  67. package/dist/chunks/deny-ClTxSvHJ.mjs +15 -0
  68. package/dist/chunks/deny-ClTxSvHJ.mjs.map +1 -0
  69. package/dist/chunks/diff-Qw0II0sj.mjs +101 -0
  70. package/dist/chunks/diff-Qw0II0sj.mjs.map +1 -0
  71. package/dist/chunks/discover-30Ciya_0.mjs +20 -0
  72. package/dist/chunks/discover-30Ciya_0.mjs.map +1 -0
  73. package/dist/chunks/doctor-DfCrKpfT.mjs +222 -0
  74. package/dist/chunks/doctor-DfCrKpfT.mjs.map +1 -0
  75. package/dist/chunks/fix-D4Tj8RVA.mjs +18 -0
  76. package/dist/chunks/fix-D4Tj8RVA.mjs.map +1 -0
  77. package/dist/chunks/gc-BBXlBF5w.mjs +161 -0
  78. package/dist/chunks/gc-BBXlBF5w.mjs.map +1 -0
  79. package/dist/chunks/init-Okz4mlhW.mjs +30 -0
  80. package/dist/chunks/init-Okz4mlhW.mjs.map +1 -0
  81. package/dist/chunks/inspect-Buby4cQD.mjs +22 -0
  82. package/dist/chunks/inspect-Buby4cQD.mjs.map +1 -0
  83. package/dist/chunks/logs-Giq5sUau.mjs +25 -0
  84. package/dist/chunks/logs-Giq5sUau.mjs.map +1 -0
  85. package/dist/chunks/migrate-DRoFUg53.mjs +19 -0
  86. package/dist/chunks/migrate-DRoFUg53.mjs.map +1 -0
  87. package/dist/chunks/models-Btp6X2YZ.mjs +24 -0
  88. package/dist/chunks/models-Btp6X2YZ.mjs.map +1 -0
  89. package/dist/chunks/pause-BASBfKLO.mjs +16 -0
  90. package/dist/chunks/pause-BASBfKLO.mjs.map +1 -0
  91. package/dist/chunks/policy-DUIgzF3W.mjs +139 -0
  92. package/dist/chunks/policy-DUIgzF3W.mjs.map +1 -0
  93. package/dist/chunks/providers-Dx78imKj.mjs +19 -0
  94. package/dist/chunks/providers-Dx78imKj.mjs.map +1 -0
  95. package/dist/chunks/reconcile-BfD785gd.mjs +26 -0
  96. package/dist/chunks/reconcile-BfD785gd.mjs.map +1 -0
  97. package/dist/chunks/render-DyZr5Lgi.mjs +53 -0
  98. package/dist/chunks/render-DyZr5Lgi.mjs.map +1 -0
  99. package/dist/chunks/resume-GJQRb2Eb.mjs +15 -0
  100. package/dist/chunks/resume-GJQRb2Eb.mjs.map +1 -0
  101. package/dist/chunks/retry-CLrUem1H.mjs +15 -0
  102. package/dist/chunks/retry-CLrUem1H.mjs.map +1 -0
  103. package/dist/chunks/review-BDdjb6kB.mjs +17 -0
  104. package/dist/chunks/review-BDdjb6kB.mjs.map +1 -0
  105. package/dist/chunks/run-CgTWYlcd.mjs +82 -0
  106. package/dist/chunks/run-CgTWYlcd.mjs.map +1 -0
  107. package/dist/chunks/run-tool-C3rAv4XF.mjs +26 -0
  108. package/dist/chunks/run-tool-C3rAv4XF.mjs.map +1 -0
  109. package/dist/chunks/schema-C9QbUW4H.mjs +578 -0
  110. package/dist/chunks/schema-C9QbUW4H.mjs.map +1 -0
  111. package/dist/chunks/send-BdnJ85Nz.mjs +19 -0
  112. package/dist/chunks/send-BdnJ85Nz.mjs.map +1 -0
  113. package/dist/chunks/ship-DTuLGoaJ.mjs +19 -0
  114. package/dist/chunks/ship-DTuLGoaJ.mjs.map +1 -0
  115. package/dist/chunks/shutdown-BM92Iyv2.mjs +15 -0
  116. package/dist/chunks/shutdown-BM92Iyv2.mjs.map +1 -0
  117. package/dist/chunks/skip-DZG5kpcH.mjs +18 -0
  118. package/dist/chunks/skip-DZG5kpcH.mjs.map +1 -0
  119. package/dist/chunks/spec-Bq0P3jVh.mjs +20 -0
  120. package/dist/chunks/spec-Bq0P3jVh.mjs.map +1 -0
  121. package/dist/chunks/src-CId6kMsY.mjs +1689 -0
  122. package/dist/chunks/src-CId6kMsY.mjs.map +1 -0
  123. package/dist/chunks/src-CfAOde7C.mjs +5403 -0
  124. package/dist/chunks/src-CfAOde7C.mjs.map +1 -0
  125. package/dist/chunks/src-Cu3TxNob.mjs +783 -0
  126. package/dist/chunks/src-Cu3TxNob.mjs.map +1 -0
  127. package/dist/chunks/src-DcU4IXMe.mjs +117 -0
  128. package/dist/chunks/src-DcU4IXMe.mjs.map +1 -0
  129. package/dist/chunks/src-JxawBQBn.mjs +446 -0
  130. package/dist/chunks/src-JxawBQBn.mjs.map +1 -0
  131. package/dist/chunks/src-s7YRvk0t.mjs +2116 -0
  132. package/dist/chunks/src-s7YRvk0t.mjs.map +1 -0
  133. package/dist/chunks/status-SMjiOMYy.mjs +29 -0
  134. package/dist/chunks/status-SMjiOMYy.mjs.map +1 -0
  135. package/dist/chunks/tail-BuhT-2PH.mjs +25 -0
  136. package/dist/chunks/tail-BuhT-2PH.mjs.map +1 -0
  137. package/dist/chunks/update-BXIppsbi.mjs +16 -0
  138. package/dist/chunks/update-BXIppsbi.mjs.map +1 -0
  139. package/dist/cli.mjs +175 -0
  140. package/dist/cli.mjs.map +1 -0
  141. package/package.json +17 -32
  142. package/CHANGELOG.md +0 -1453
  143. package/bin/cli.js +0 -812
  144. package/bin/report.js +0 -141
  145. package/core/adapter/render.js +0 -389
  146. package/core/agents/implementer.template.md +0 -142
  147. package/core/agents/profile-reader.md +0 -50
  148. package/core/agents/release.md +0 -58
  149. package/core/agents/review.md +0 -179
  150. package/core/commands/cohorte-align-ds.md +0 -33
  151. package/core/commands/cohorte-audit.md +0 -58
  152. package/core/commands/cohorte-brainstorm.md +0 -70
  153. package/core/commands/cohorte-build.md +0 -219
  154. package/core/commands/cohorte-doctor.md +0 -170
  155. package/core/commands/cohorte-fix.md +0 -80
  156. package/core/commands/cohorte-fleet.md +0 -103
  157. package/core/commands/cohorte-init-pipeline.md +0 -31
  158. package/core/commands/cohorte-intake.md +0 -92
  159. package/core/commands/cohorte-patch.md +0 -118
  160. package/core/commands/cohorte-refactor.md +0 -59
  161. package/core/commands/cohorte-retro.md +0 -85
  162. package/core/commands/cohorte-review.md +0 -270
  163. package/core/commands/cohorte-ship.md +0 -122
  164. package/core/commands/cohorte-spec.md +0 -101
  165. package/core/commands/cohorte-update-pipeline.md +0 -134
  166. package/core/hooks/gate.py +0 -580
  167. package/core/runtimes/claude.json +0 -74
  168. package/core/runtimes/codex.json +0 -83
  169. package/core/runtimes/cursor.json +0 -76
  170. package/core/runtimes/gemini.json +0 -76
  171. package/core/runtimes/opencode.json +0 -73
  172. package/core/templates/agent-handoff.md +0 -34
  173. package/core/templates/brainstorm-return.md +0 -36
  174. package/core/templates/decisions.template.md +0 -42
  175. package/core/templates/design-brief.md +0 -44
  176. package/core/templates/patch.template.md +0 -86
  177. package/core/templates/pr-body.md +0 -25
  178. package/core/templates/review-feedback.md +0 -38
  179. package/core/templates/spec.template.md +0 -87
  180. package/core/templates/steps/init-pipeline/01-detect-stack.md +0 -44
  181. package/core/templates/steps/init-pipeline/02-interview-gaps.md +0 -55
  182. package/core/templates/steps/init-pipeline/03-draft-profile.md +0 -10
  183. package/core/templates/steps/init-pipeline/04-write-render.md +0 -115
  184. package/core/templates/steps/init-pipeline/05-report.md +0 -12
  185. package/core/workflows/audit.js +0 -240
  186. package/core/workflows/loop.js +0 -641
  187. package/core/workflows/refactor.js +0 -276
  188. package/core/workflows/review.js +0 -456
  189. package/install.ps1 +0 -103
  190. package/install.sh +0 -114
  191. package/lib/doctor.js +0 -504
  192. package/lib/runtime.js +0 -134
  193. package/lib/versions.js +0 -149
  194. package/lib/yaml.js +0 -129
  195. package/profile/PIPELINE.template.md +0 -251
  196. package/profile/SCHEMA.md +0 -698
  197. package/profile/cohorte.config.template.yaml +0 -43
  198. package/scripts/assert-gate-hook.mjs +0 -75
  199. package/scripts/kanban-move.sh +0 -313
  200. package/scripts/metrics/collect.mjs +0 -531
  201. package/scripts/metrics/prices.json +0 -42
  202. package/scripts/new-feature.sh.template +0 -98
  203. package/scripts/preflight.sh +0 -124
  204. package/scripts/remove-feature.sh.template +0 -56
  205. package/scripts/test-adapter.mjs +0 -368
  206. package/scripts/test-gate.mjs +0 -428
  207. package/scripts/test-kanban.mjs +0 -304
  208. package/scripts/test-lib.mjs +0 -310
  209. package/scripts/test-metrics.mjs +0 -156
  210. package/scripts/test-workflows.mjs +0 -758
  211. package/scripts/validate-core.mjs +0 -320
@@ -1,92 +0,0 @@
1
- ---
2
- description: Triage anything that arrives — a ticket, a client email, a stack trace, a Slack thread — into the pipeline's entry point: a patch handoff or a brainstorm seed.
3
- argument-hint: [paste the raw material — ticket, email, trace, thread — or empty to be asked]
4
- ---
5
-
6
- You are the **intake triager**. Work is arriving from OUTSIDE the pipeline — a bug report, a
7
- client email, a support thread, a stack trace, a half-idea — and today a human distills it by
8
- hand before anything can start. Your job is that distillation: read the raw material, decide
9
- which door it enters through, and stage a handoff the next command can consume verbatim.
10
-
11
- > Read `PIPELINE.md` §`pipeline-profile` first — `name`, `one_liner`, `surfaces` (to guess which
12
- > surface a symptom lives in) and `ui_language`. _Skip the re-read if it's already in your
13
- > context this session and unmodified since._ Read `specs/_decisions.md` §Live if it exists —
14
- > an incoming request that contradicts a settled decision must be flagged as such, not triaged
15
- > as a fresh idea.
16
-
17
- ## 1. Ingest & triage
18
-
19
- The material is pasted after the command; nothing pasted ⇒ ask for it and wait (paste, file
20
- path, or a `gh issue view <n>` you run yourself when they name an issue number). Then decide —
21
- and say which signals decided it:
22
-
23
- - **Bug** — existing behavior misbehaving: a repro or trace, "used to work", an error message,
24
- a version where it broke. → §2.
25
- - **Feature** — behavior that does not exist yet: "could we", "it should also", a workflow the
26
- product doesn't cover. → §3.
27
- - **Both tangled together** (a bug report whose fix half describes a new feature): split it —
28
- §2 for the defect, §3 for the rest — and say you split it.
29
- - **Neither** (a question, a config issue on their side, praise, noise): say so in one line and
30
- stop. Not everything that arrives is work; inventing a spec from noise costs a whole pipeline
31
- run downstream.
32
-
33
- Pick a short kebab-case **slug** from the content (`checkout-double-charge`, `csv-export`) —
34
- it becomes the join key for the file, the kanban card and the follow-up command.
35
-
36
- ## 2. Bug → a `/cohorte-patch` handoff
37
-
38
- Distill the raw material into exactly the structure `/cohorte-patch` §1 interviews for — so the
39
- patch triage starts loaded instead of re-asking:
40
-
41
- - **Symptom** — one sentence, observed behavior vs expected.
42
- - **Repro** — numbered steps as far as the material supports them; mark every step you inferred
43
- (`(inferred)`) rather than silently guessing. A trace with no steps ⇒ the trace IS the repro
44
- material, say so.
45
- - **Environment** — version/browser/OS/role if present; `unknown` where absent.
46
- - **Suspected surface(s)** — map the symptom onto `surfaces[]` by what the paths/stack frames
47
- name; a guess is fine, label it one.
48
- - **Severity signal** — who is blocked and how hard, in the reporter's own words.
49
-
50
- **Stage it** to `specs/reports/intake-<slug>.md` (overwrite; `mkdir -p specs/reports` first —
51
- the gitignored buffer dir, so the handoff survives a `/clear`). Then:
52
-
53
- > **Kanban** (SCHEMA.md §Kanban): run
54
- > `<core>/pipeline/scripts/kanban-move.sh auto patch-<slug> ideas --title "[patch] <one-line title>"`.
55
- > The id is **`patch-<slug>`, prefix included, and the title prefix is `[patch]`** — that is the
56
- > exact join key and the exact title `/cohorte-patch` §1 looks for, so its later move finds THIS
57
- > card instead of creating a duplicate and stranding this one in Ideas (the failure SCHEMA
58
- > §Kanban's "tag before you move" exists to prevent). `auto` resolves the board from the config
59
- > itself and exits 0 with a `kanban: <reason>` line when there is none — so **never decide "no
60
- > board is configured" without running it**.
61
-
62
- Close with: `→ /cohorte-patch <slug>` — `/cohorte-patch` reads the staged
63
- `specs/reports/intake-<slug>.md` when it exists, so the triage starts loaded. Do **not** run it
64
- yourself — freezing a spec is a decision the human confirms, and intake's job ends at the door.
65
-
66
- ## 3. Feature → a `/cohorte-brainstorm` seed
67
-
68
- Distill into the seed the panel argues best about:
69
-
70
- - **Title + one-liner** — in the product's language (`ui_language` for user-facing wording).
71
- - **Who is asking & why now** — verbatim quotes where the material has them; the panel argues
72
- better against a real voice than a paraphrase.
73
- - **Goals / explicit non-goals** — only what the material actually states; never pad.
74
- - **Open questions** — every ambiguity you'd otherwise have guessed at, as questions. This list
75
- is the seed's real value: it is the brainstorm's agenda.
76
- - **Prior art in this repo** — one grep pass: existing specs/decisions touching the same area
77
- (`grep -l` over `specs/*.md`, redirected — never a file read per name). Contradicts a
78
- `_decisions.md` line ⇒ name the line verbatim; the panel must argue against it knowingly.
79
-
80
- **Stage it** to `specs/reports/intake-<slug>.md` (overwrite), then the kanban call with the
81
- bare id: `<core>/pipeline/scripts/kanban-move.sh auto <slug> ideas --title "<title>"` (same
82
- "never decide without running it" rule as §2). The card is the board's join key; **the seed
83
- itself travels in the staged file** — `/cohorte-brainstorm <slug>` reads
84
- `specs/reports/intake-<slug>.md` when it exists, so the panel argues against the distillate,
85
- not against a bare slug.
86
-
87
- Close with: `→ /cohorte-brainstorm <slug>` — the seed is on disk and on the board;
88
- **recommend a `/clear` first**, the handoff is complete.
89
-
90
- In chat print ONLY: the triage verdict + its signals (one line), the staged file path, the
91
- kanban result line, and the follow-up command. Never echo the full distillate into chat — it
92
- is on disk, and this session's history is re-sent at input price on every turn.
@@ -1,118 +0,0 @@
1
- ---
2
- description: Triage a bug and freeze a minimal patch spec — the cheap entry into the pipeline for a fix, no brainstorm, no contract.
3
- argument-hint: [bug description / stack trace / issue text — or empty to pick from the kanban]
4
- ---
5
-
6
- You run the **patch triage** in the main thread — interactive, with the human. This is the bug-fix
7
- entry point: it produces `specs/patch-<slug>.md` and stops. Everything after it is the normal
8
- pipeline (`/cohorte-build` → `/cohorte-review` → `/cohorte-fix`* → `/cohorte-ship`), unchanged — the
9
- patch spec is a spec, so those commands consume it as-is. Splitting it this way is the point: each
10
- phase is a fresh session with the artifact on disk, instead of one long thread paying for the whole
11
- cycle at input price on every turn.
12
-
13
- Bug (may be empty): **$ARGUMENTS**
14
-
15
- > Read `PIPELINE.md` §`pipeline-profile` first: `surfaces` (paths — this is what you map the bug onto)
16
- > and `vcs`. _Skip the re-read if it's already in your context this session and unmodified since._
17
- > Do NOT read `specs/_decisions.md`: a bug fix decides nothing transverse, and the journal is for
18
- > decisions that outlive a feature.
19
- >
20
- > **Kanban** (SCHEMA.md §Kanban): two moves, and their **order is load-bearing** — §1 settles the
21
- > slug and moves the card to `spec`, §4 moves it to `ready` at freeze. Both are one call to
22
- > `<core>/pipeline/scripts/kanban-move.sh auto patch-<slug> <stage> [--title "[patch] <human title>"]`.
23
- > The slug is settled first precisely because the move needs it: a card cannot be joined on an id
24
- > that doesn't exist yet. `auto` resolves the board from the config itself and exits 0
25
- > with a `kanban: <reason>` line when there is none — so **never decide "no board is configured"
26
- > without running it**. Reading the Ideas column at §1 still needs the board path: get it from a
27
- > `kanban-move.sh` run, or grep the config for `boards[<PIPELINE name>]`.
28
-
29
- ## 1. Get the bug
30
-
31
- If `$ARGUMENTS` is non-empty, restate it in one line and confirm you've got it — and if it is
32
- (or names) a slug with a staged `specs/reports/intake-<slug>.md`, **read that file first**: it is
33
- `/cohorte-intake`'s distillate (symptom, repro with inferred steps labeled, environment, suspected
34
- surfaces, severity signal), so this triage starts loaded instead of re-asking. Keep intake's slug —
35
- its kanban card is already tagged `#patch-<slug>` and titled `[patch] …`, exactly what the move
36
- below joins on.
37
-
38
- If it is empty: when a board is configured and its **Ideas** column has cards, list them (with any
39
- sub-bullet notes as context) — **cards titled `[patch]` first**, since those are the ones a human
40
- filed as bugs — and let the human pick one. Otherwise ask **"What's broken?"**. Either way, wait.
41
-
42
- Then **settle the id, before anything moves.** Derive `<slug>` (kebab-case, from the symptom —
43
- `500-on-empty-cart`, not `bug-42`) and confirm it. The `feature_id` is **`patch-<slug>`**, prefix
44
- included: it is the join key for the kanban card, the spec filename, the branch and every later
45
- command, so the prefix is part of the id itself, not decoration on the card.
46
-
47
- **Kanban, in this order:**
48
-
49
- 1. **If the human picked an Ideas card, tag it FIRST.** Ideas cards are free text with no
50
- `#<feature_id>`, and the move script joins on that tag: move before tagging and it finds nothing,
51
- creates a second card, and strands the untagged original in Ideas forever. One targeted Edit
52
- appending ` #patch-<slug>` to that line, located by `grep -n` — never a full board read.
53
- 2. `<core>/pipeline/scripts/kanban-move.sh auto patch-<slug> spec --title "[patch] <human title>"` —
54
- which moves the (now tagged) card, or creates one under `--title` if the human typed a fresh bug.
55
- Report what it printed — `moved #…` or `kanban: <reason>` — never a guess about which happened.
56
-
57
- ## 2. Triage — three questions, not an interview
58
-
59
- `/cohorte-spec` walks a template section by section because a feature has to be *designed*. A bug is
60
- already specified by reality; your job is to pin it down, not to explore it. Ask only what you
61
- genuinely cannot infer from the input, batched into ONE message:
62
-
63
- 1. **Repro** — the shortest deterministic path to the symptom. No repro ⇒ ask whether they want you
64
- to go find one first (a diagnosis session, no spec) or to freeze it as a hypothesis and let the
65
- implementer confirm. Never invent a repro to fill the section.
66
- 2. **Expected behaviour** — often the whole spec. "It should 404, not 500" is a complete contract.
67
- 3. **Blast radius** — what must NOT change. This becomes §7 Out of scope, and it is what stops a fix
68
- from becoming a refactor.
69
-
70
- Then locate it yourself — do not make the human do it. Use the retrieval provider if one is wired,
71
- else grep for the symptom's strings/identifiers. Read only the files the trail actually names.
72
- Report the suspected `file:line` in one line and let them confirm or correct it.
73
-
74
- ## 3. Map it onto surfaces — as many as it takes
75
-
76
- Match the suspected cause and the fix's blast radius against `surfaces[].path`. **A patch is not
77
- capped at one surface**: a bug that spans an API validator and the form feeding it is one bug with
78
- one repro, and splitting it into two specs would give each half a contract it doesn't have. List the
79
- surfaces you're claiming, one line each, with why.
80
-
81
- **The one escalation that is not a judgment call:** if the fix needs **new** contract surface area —
82
- a new endpoint, a new shared type, a new field crossing surfaces — stop. That is a feature wearing a
83
- bug's clothes, and §5 is the only channel that keeps two surfaces in agreement about a shape that
84
- doesn't exist yet. Say so plainly and send the human to `/cohorte-spec`. Changing an **existing**
85
- contract entry is fine: describe the delta in §5 and continue.
86
-
87
- ## 4. Freeze the patch spec
88
-
89
- Write `specs/patch-<slug>.md` from `<core>/templates/patch.template.md` with `status: frozen`, filled
90
- from §§1–3. **Create the file — do not ask the human to.** Budget: **~60 lines**. A patch spec that
91
- wants 200 is a feature or a refactor — say which and route it (`/cohorte-spec`, or an item on
92
- `specs/refactor-backlog.md`).
93
-
94
- Two sections carry the weight, and both are cheap to get wrong:
95
-
96
- - **§4 Regression test** — name the test file and what it asserts. It replaces §5 as the thing the
97
- reviewer checks the diff against, so "add a test" is not enough: say what fails today and why. A
98
- patch whose test can only be written after the cause is found says exactly that.
99
- - **§5/§9 keep the feature spec's numbers** (contract delta, acceptance). `review.md` and
100
- `implementer.template.md` name "contract §5, acceptance §9" verbatim — renumbering them here would
101
- silently point both agents at the wrong section. The template already does this; don't "fix" it.
102
-
103
- **Postcondition:** `grep -q '^status: frozen' specs/patch-<slug>.md` — if it fails the freeze didn't
104
- land; fix it before pointing the human at `/cohorte-build`. Chain the second kanban move onto that
105
- same Bash call — `kanban-move.sh auto patch-<slug> ready` (the card is already tagged and on the
106
- board from §1, so this one needs no `--title`) — and report what it printed: `moved #…` or
107
- `kanban: <reason>`, never a guess.
108
-
109
- ## 5. Hand off
110
-
111
- Print the spec path, the surfaces, and the branch to cut: `<prefix>patch-<slug>`, where `<prefix>` is
112
- `vcs.patch_branch_prefix` — falling back to `fix/` on a profile that predates the key. If `isolation.enabled`
113
- and the fix is big enough to want its own worktree, mention `scripts/new-feature.sh patch-<slug>`;
114
- most patches don't need it.
115
-
116
- Then: `/cohorte-build patch-<slug>` — and **recommend a `/clear` first**. The spec is on disk; the
117
- lead's triage history is re-sent at input price on every turn it survives, and `/cohorte-build`
118
- re-reads everything it needs.
@@ -1,59 +0,0 @@
1
- ---
2
- model: sonnet
3
- description: Apply the refactor backlog for one or more domains via the surface implementer agents (TDD-first, parallel across independent surfaces), then re-verify.
4
- argument-hint: <domain…> (one or more surface keys, "shared", or "all")
5
- ---
6
-
7
- You are the **lead**. Refactor domain **$ARGUMENTS** to match `PIPELINE.md`, using the `/cohorte-audit` backlog.
8
-
9
- > Read `PIPELINE.md` §`surfaces` (map the domain → a surface + its agent + commands) and §`contract`.
10
- >
11
- <!-- cohorte:if workflows -->
12
- > **Workflow variant** (opt-in — SCHEMA.md §Workflows): for BIG domains (many open backlog items
13
- > across several surfaces), on Claude Code ≥ 2.1.154 with workflows enabled, the human can ask to
14
- > "run the refactor workflow" (`<core>/workflows/refactor.js`). For a handful of items this
15
- > conversational path is cheaper — and it stays the default and the fallback.
16
- <!-- cohorte:endif -->
17
-
18
- ## 1. Gather
19
-
20
- - Read `specs/refactor-backlog.md`; select the items for `$ARGUMENTS` (`all` = every domain with
21
- open items).
22
- - Map each domain to a surface. `shared` = the contract package (`contract.path`), owned by you/lead —
23
- refactor it directly, don't dispatch.
24
-
25
- ## 2. Dispatch the surface's implementer agent — TDD-first, stateless
26
-
27
- Spawn the matching `<surface.agent>` with the template below (as `subagent_type: <surface.agent>`).
28
- Keep it **byte-identical across loop
29
- rounds** (only the final items slot varies — it sits at the end so repeats hit the prompt cache), and
30
- never paste a diff — the agent computes its own, scoped to its tree:
31
-
32
- > "Refactor pass on your surface (no feature spec). Read
33
- > `PIPELINE.md` first. **Add the missing tests FIRST** (pin current behavior / cover the entry
34
- > points), watch them pass, **then** refactor to clear each item. Preserve current public behavior
35
- > unless an item marks it a bug. Migrations stay additive. Need the current state of your tree?
36
- > Compute it yourself: `git diff <default_branch> -- <surface.path>`. Lint + format before handoff;
37
- > return the handoff in the format your agent instructions define. Backlog items for YOUR surface
38
- > (self-contained — clear exactly these, reading only the files they name): <the domain's open
39
- > `- [ ]` lines verbatim, with exact file paths>."
40
-
41
- **Parallel when domains are independent:** if the human passed several domains (or `all`), dispatch
42
- their implementers **concurrently in a single message** — surface trees are disjoint by construction,
43
- so parallel is safe. Exception: `shared` (the contract package) never joins a parallel batch — the
44
- slices import it, so refactor it alone, first.
45
-
46
- - **Preserve current public behavior** unless a finding marks it a bug/convention violation — existing
47
- code has no contract spec, so don't silently change shapes.
48
- - Migrations stay **additive**; never `PIPELINE.md` §`gate.deny` commands.
49
- - Touch only its surface; lint + format before handoff.
50
-
51
- ## 3. Verify & loop
52
-
53
- After each agent returns: its surface's `test_quiet_cmd`/`lint_quiet_cmd` (else the `tail -40`
54
- fallback — SCHEMA.md §Output discipline), `commands.typecheck`, `commands.format --check` (redirect
55
- 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
56
- `/cohorte-audit` per round (that repeats the repo-wide gates + a review dispatch you don't need); one optional
57
- final `/cohorte-audit` once ALL dispatched domains are clean is enough. Check cleared items off in
58
- `specs/refactor-backlog.md`. Loop until each dispatched domain is clean. Verification is per-domain
59
- even when the dispatch was parallel — one failing surface loops alone, the others don't redo work.
@@ -1,85 +0,0 @@
1
- ---
2
- description: Mine the accumulated review findings across features for repeating patterns, and turn the ones the human ratifies into PIPELINE.md §Conventions rules the next build already follows.
3
- argument-hint: [last <n> | all] (default: every feature with a report on disk)
4
- ---
5
-
6
- You are running the **retrospective**. Every review this pipeline has run left structured
7
- residue on disk — verdicts, Remediation rounds, deferred backlog items. A finding that shows up
8
- once is a bug; the same finding shape across features is a **missing rule**, and the pipeline
9
- has a place for rules the implementers actually read: `PIPELINE.md` §Conventions, baked into
10
- each surface agent at render time. This command closes that loop: findings → patterns →
11
- ratified rules → re-rendered agents. The next build then never produces the finding again —
12
- which is cheaper than any number of review rounds catching it.
13
-
14
- > Read `PIPELINE.md` §`pipeline-profile` (`surfaces`, and skim the existing §Conventions
15
- > stanzas — a rule that already exists is a finding about *enforcement*, not a missing rule)
16
- > and `specs/_decisions.md` §Live. _Skip the re-read if already in context and unmodified._
17
-
18
- ## 1. Collect — mechanical, redirected, no judgment yet
19
-
20
- Scope: `all` (default), or `last <n>` features by spec mtime. In as few Bash calls as possible,
21
- **always redirected to `specs/reports/retro-scan.txt` and grepped — never into your context**:
22
-
23
- - `specs/reports/*.verdict.json` — per feature: `blocking_items` (normalized identities),
24
- `severity`, per-surface counts. The freshest machine record, one per feature.
25
- - Every non-`_` spec's `## Remediation` section — the **persistent** history (verdict.json is
26
- overwritten per round; Remediation accumulates, and collapsed rounds still carry their
27
- count line). Grep the item lines: `- [x?] <SEVERITY> · <file:line> · <kind> · <fix>`.
28
- - `specs/refactor-backlog.md` — the `deferred:<id>` tagged items: debt reviews kept finding
29
- but no feature owned.
30
-
31
- A repo with fewer than two features' worth of residue ⇒ say the retro has nothing statistical
32
- to stand on yet, name what exists, and stop — one feature's findings are that feature's story,
33
- not a pattern.
34
-
35
- ## 2. Patterns — what repeats, with the evidence attached
36
-
37
- A **pattern** is a finding shape that recurs where recurrence means something:
38
-
39
- - same `kind` × same surface across **≥ 2 features** (e.g. `security` findings on `backend`
40
- twice running — the strongest signal there is);
41
- - the same file/module named by findings from **≥ 2 features** (a hotspot no single fix loop
42
- owns);
43
- - the same *fix wording* family recurring (e.g. three "add the authz check" fixes = one
44
- missing authorization convention);
45
- - a `deferred:` cluster in one domain — debt the reviews keep re-discovering because no rule
46
- makes the implementers avoid adding to it.
47
-
48
- For each pattern, produce: the evidence lines **verbatim** (`<feature> · <severity> · <file> ·
49
- <problem/fix>`), the count, and ONE drafted convention rule — **rule-shaped**: a sentence an
50
- implementer can follow and a reviewer can test a diff against, placed under `### Shared` or the
51
- owning `### Surface: <key>`. Not advice ("be careful with auth") — a rule ("every route under
52
- `apps/api/src/routes/` calls `authorize()` before its handler; no exceptions without a spec
53
- §5 note"). Skip any pattern the existing §Conventions already covers — report those separately
54
- as **enforcement gaps** (the rule exists and reviews keep finding violations: that is input for
55
- the human, not a new rule).
56
-
57
- ## 3. Ratify — the human picks; nothing lands without them
58
-
59
- Present a compact table: pattern → evidence count → drafted rule → target stanza. Then **stop
60
- and ask** which to adopt (all / some / none — none is a fine outcome and says the rulebook fits
61
- the codebase). Rules are standing law every future dispatch pays tokens to carry: the human
62
- decides what becomes law, exactly as they freeze specs.
63
-
64
- ## 4. Apply — and keep the baked slices honest
65
-
66
- For each adopted rule, in this order:
67
-
68
- 1. Append it to `PIPELINE.md` §Conventions under its stanza (create the `### Surface: <key>`
69
- stanza if absent; keep it rule-shaped, one line each).
70
- 2. **Re-render every affected surface agent** per SCHEMA.md §Rendering step 2 — the
71
- `<SURFACE_CONVENTIONS>` slice is **baked at render time**, so a §Conventions edit without a
72
- re-render produces the worst outcome available: reviewers (who read the prose live) enforce
73
- a rule implementers (who carry the stale bake) have never seen, and every future review
74
- round re-finds the pattern this retro just paid to close. If you cannot re-render on this
75
- runtime, say so and route to `/cohorte-update-pipeline` (its reconcile step 2 re-renders) —
76
- but then the rule is **pending**, and you say that too.
77
- 3. Append ONE line per adopted rule to `specs/_decisions.md` §Live (SCHEMA.md §Decisions):
78
- `- <date> · conventions · <rule, compressed> — because <kind>×<n> across <features> · retro`.
79
- A retro rule is a standing decision; the journal is where the next `/cohorte-spec` learns it
80
- without re-mining the reports.
81
-
82
- In chat print ONLY: patterns found / adopted / skipped (one line each), enforcement gaps, which
83
- agents were re-rendered (or the pending route), and the decisions lines appended. The evidence
84
- stays in `specs/reports/retro-scan.txt`. **Recommend a `/clear`** — everything that matters is
85
- now in `PIPELINE.md`, the rendered agents, and the journal.
@@ -1,270 +0,0 @@
1
- ---
2
- model: sonnet
3
- description: Dispatch the read-only review agent to audit the feature against its frozen spec.
4
- argument-hint: <feature_id>
5
- ---
6
-
7
- You are the **lead**. Dispatch the review for feature **$ARGUMENTS**.
8
-
9
- > Read `PIPELINE.md` §`vcs.default_branch` (diff base) and the `surfaces`/`contract`/`commands` fields.
10
- > _Skip the re-read if it's already in your context this session and unmodified since._
11
- >
12
- > **Kanban** (SCHEMA.md §Kanban): run
13
- > `<core>/pipeline/scripts/kanban-move.sh auto $ARGUMENTS review`. `auto` resolves the board from the config itself and
14
- > exits 0 with a `kanban: <reason>` line when there is none — so **never decide "no board is
15
- > configured" without running it**. _(PR mode — `--pr` below — skips this entirely: an incoming
16
- > PR is not a pipeline feature and has no card.)_
17
- >
18
- <!-- cohorte:if workflows -->
19
- > **Workflow variant** (opt-in — SCHEMA.md §Workflows): on Claude Code ≥ 2.1.154 with workflows
20
- > enabled, the human can ask to "run the review workflow" (`<core>/workflows/review.js`) instead.
21
- > This conversational path stays the default and the fallback; `/cohorte-doctor` shows which is available.
22
- <!-- cohorte:endif -->
23
-
24
- ## PR mode — review an INCOMING pull request (`--pr <num>` or a PR URL)
25
-
26
- If `$ARGUMENTS` contains `--pr <num>` (or a GitHub PR URL — extract the number), this is not a
27
- pipeline feature: it is **someone else's work arriving**, reviewed with the same reviewers and the
28
- same report format, without pretending it went through the pipeline. What that changes, explicitly:
29
- **no spec** (nothing to check conformance against — reviewers run in audit mode: conventions +
30
- correctness + security + TDD coverage only), **no kanban move**, **no verdict.json**, **no DoD
31
- tick, no freshness stamp, no metrics line** — those certify pipeline features, and this is not one.
32
- Requires `vcs.host: github` + `gh`; otherwise say so and stop.
33
-
34
- 1. **Fetch into a throwaway worktree — never touch the current checkout.** One Bash call:
35
- `gh pr view <num> --json title,baseRefName,headRefName,author` (relay the one-line summary), then
36
- `git fetch -f origin pull/<num>/head:cohorte-pr-<num> <baseRefName> && git worktree add ../<repo>-pr-<num> cohorte-pr-<num>`
37
- — `-f` so a branch left behind by a crashed earlier run updates instead of failing, and the
38
- **base ref is fetched too**: the diff below is against `origin/<baseRefName>`, and a stale
39
- local base blames the PR for every commit it merely hasn't rebased onto yet.
40
- The human's tree, branch and stamps stay untouched; every later step runs `-C` that worktree.
41
- 2. **Mechanical checks inside the worktree — the commands directly, NEVER `preflight.sh`.** The
42
- script's whole point is stamping `<state>/preflight.ok` in the MAIN checkout (it resolves
43
- through `git-common-dir` on purpose), so running it here would overwrite the human's stamp
44
- with the PR tree's digest — greening pipeline review dispatches of a tree nobody preflighted,
45
- then blocking them once the worktree is gone. Instead: install dependencies first
46
- (`commands.install` — a bare `worktree add` has no `node_modules`), then run the profile's
47
- typecheck/lint-quiet/test-quiet yourself, each appended to the worktree's
48
- `specs/reports/pr-<num>.preflight.txt`, stopping at the first failure. **Red does NOT get
49
- reviewers** — same economics as §0 (a reviewer on code that doesn't compile rediscovers what
50
- `tsc` printed for free) — but unlike §0 it is not an abort: the mechanical failures ARE the
51
- review (severity CRITICAL, kind `quality`, the failing command + last lines) — jump to
52
- step 4. An *environmental* failure (install itself failed, a missing service) is reported as
53
- "not verifiable here", never as a finding against the PR.
54
- 3. **Stage + dispatch — §1's staging procedure and §2's dispatch, minus everything spec-shaped**
55
- (there is no `specs/<id>.md` to confirm and no small-diff fast path — an unknown author's
56
- diff always gets a full reviewer), with three substitutions: the diff is
57
- `git diff origin/<baseRefName>...HEAD` (**three-dot** — only the PR's own commits, not the
58
- base's drift), staged diffs and file paths are **absolute paths into the worktree**
59
- (reviewers are stateless — they must not read the main checkout), and the dispatch template's
60
- spec/contract slots read
61
- `spec: none (incoming PR — audit mode: PIPELINE.md conventions + quality/security/TDD only,
62
- skip spec conformance)` · `contract: none`. Roll call + merge per §3 (retry once, `unreviewed`
63
- forbids a clean verdict), same capped REVIEW REPORT.
64
- 4. **Stage the report to the MAIN checkout's `specs/reports/pr-<num>.md`** (it must outlive the
65
- worktree), print the verdict + severity table + CRITICAL/security digests in chat. Then —
66
- **always ask the human first, posting is outward-facing** — offer:
67
- `gh pr comment <num> --body-file specs/reports/pr-<num>.md` (prefix the body with one line:
68
- `Automated review — cohorte pipeline (advisory)`). Never post without the explicit go-ahead;
69
- "no" leaves the report on disk and that is a complete outcome.
70
- 5. **Teardown, always** (also after a red preflight or a dead reviewer):
71
- `git worktree remove --force ../<repo>-pr-<num> && git branch -D cohorte-pr-<num>`.
72
-
73
- Everything below this line is the normal pipeline-feature flow.
74
-
75
- ## 0. Deterministic pre-flight — no agents while red
76
-
77
- Run the profile's mechanical gates in ONE Bash call via the shipped script
78
- (`<core>/pipeline/scripts/preflight.sh`); note the epoch (`date +%s`) in the same call — §3's
79
- metrics line needs it:
80
-
81
- ```
82
- <core>/pipeline/scripts/preflight.sh specs/reports/$ARGUMENTS.preflight.txt \
83
- "<commands.typecheck>" "<commands.lint_quiet, else lint>" "<commands.test_quiet, else test>"
84
- ```
85
-
86
- - **Non-zero exit** ⇒ the script already printed the raw last-40 lines. **STOP: relay them verbatim
87
- and spawn NO agent** — a compiler/test failure needs `/cohorte-fix` (or the human), not a review that
88
- rediscovers it at agent prices. This abort is the whole point of the step. Before stopping, write
89
- the **aborted verdict** (§3's contract, degraded form) so an automated driver gets a diagnosis
90
- rather than silence:
91
- `{"id":"$ARGUMENTS","phase":"review","ts":"<ISO>","aborted":"preflight","verdict":"BLOCK","blocking":null}`
92
- → `specs/reports/$ARGUMENTS.verdict.json`. One `printf`, in the same Bash call.
93
- <!-- cohorte:if hooks -->
94
- - **Zero exit** ⇒ it stamped `<state>/preflight.ok`, which the gate hook checks before letting
95
- `review` dispatches through (SCHEMA.md §Preflight). Continue.
96
- <!-- cohorte:else -->
97
- - **Zero exit** ⇒ it stamped `<state>/preflight.ok`. Nothing enforces that stamp on this runtime, so
98
- §2 does not start until you have seen this line: a review of red code is the one failure mode this
99
- step exists to prevent, and here only you can prevent it (SCHEMA.md §Preflight). Continue.
100
- <!-- cohorte:endif -->
101
- - Script absent (older core) ⇒ run the three commands yourself, each redirected into
102
- `specs/reports/$ARGUMENTS.preflight.txt`, aborting on the first failure the same way.
103
-
104
- ## 1. Gather the inputs for stateless reviewers
105
-
106
- - Confirm `specs/$ARGUMENTS.md` exists.
107
- - **Compute the diff ONCE — `--stat` first, patches only for retained surfaces.** One call:
108
- `git diff <default_branch> --stat > specs/reports/$ARGUMENTS.stat.txt`, then grep that file to
109
- group the changed paths by `surfaces[].path` prefix (deterministic — don't reason it out file by
110
- file). Paths under no surface (contract file, root config) are the **`shared` remainder**: attach
111
- them to the most relevant surface's reviewer and say so in its dispatch. A surface with no changed
112
- paths gets no reviewer — and no `.diff` is ever generated for it.
113
- - **Stage the hunks once per touched surface** (reviewers are read-only — no Bash — so the staged
114
- diff file is the ONLY way they can review hunks instead of re-reading whole files, and staging it
115
- here means N reviewers never re-run git N times). Regenerated every round:
116
- `git diff <default_branch> -- <surface.path> > specs/reports/$ARGUMENTS.<surface.key>.diff`
117
- (same gitignored buffer dir as the reports). For the surface that carries the shared remainder,
118
- append the remainder pathspecs to its command so its `.diff` includes them. Never print a diff into
119
- your own context — redirect straight to the file.
120
-
121
- ## 2. Dispatch review agents — one per touched surface, IN PARALLEL
122
-
123
- Spawn ONE `review` agent per surface that has changed files, in a **single message** (one dispatch
124
- each, like `/cohorte-build`) so they run concurrently — NEVER serially: review wall-clock must be the
125
- slowest surface, not the sum. A diff touching a single surface ⇒ a single reviewer.
126
-
127
- **Small-diff fast path (re-reviews only):** if a surface's staged diff is tiny (≤2 files and ≤~40
128
- changed lines), touches no contract file, and every open finding it addresses is non-security
129
- LOW/MEDIUM, skip the dispatch: verify the hunks yourself against the open Remediation items (did the
130
- prescribed fixes land? — NOT a de-novo audit) and write the same REVIEW REPORT into the §3 flow.
131
- First-round reviews, contract changes, and security findings always get a full reviewer. For each
132
- reviewed surface:
133
-
134
- Keep the dispatch prompt **byte-identical across features and rounds** except the variable block,
135
- which sits at the END so every repeat hits the prompt-cache prefix:
136
-
137
- > `subagent_type: review` (or this runtime's equivalent) — "Review one feature surface against its frozen spec. Read `PIPELINE.md`
138
- > first (flags + the §Conventions/§Testing slice for your scope). Check spec conformance first, then
139
- > correctness, security, conventions, RBAC/mobile-first _if the profile enables them_, and TDD
140
- > coverage. Your dispatch names a staged diff file — read it FIRST; open a full source file only when
141
- > a finding demands it. Emit the REVIEW REPORT in the capped format your agent instructions define —
142
- > every finding self-sufficient (`file:line` · severity · type · one-line concrete fix), no code
143
- > excerpts. — Variable slots: feature `$ARGUMENTS` · scope: the `<surface.key>` surface only · spec:
144
- > `specs/$ARGUMENTS.md` (source of truth) · contract: `<contract.path>/$ARGUMENTS.<ext>` · staged
145
- > diff: `specs/reports/$ARGUMENTS.<surface.key>.diff` · changed files (`--stat`): <list>."
146
-
147
- §0's preflight call already gave you the wall-clock start (`date +%s` in the same call) — §3's
148
- metrics line needs it.
149
-
150
- ## 3. Merge & relay the verdict
151
-
152
- **Roll call FIRST — a dead reviewer is not a clean surface.** Every surface you dispatched in §2 must
153
- come back with a REVIEW REPORT. A reviewer that died (rate limit, transport error, exhausted context)
154
- returns **nothing**, and zero findings from a dead reviewer is byte-identical to zero findings from a
155
- genuinely clean one — which is how "every reviewer crashed" reads as the strongest possible verdict
156
- from no evidence at all (SCHEMA.md §Dead agents). So:
157
-
158
- - **Retry a silent surface ONCE**, byte-identical dispatch. Most deaths are transient, and the staged
159
- diff is already on disk — the retry costs one agent, not a re-review.
160
- - **Silent twice ⇒ that surface is `unreviewed`.** Name it in the report under
161
- `## NOT reviewed (no verdict on these)`, list it in the verdict JSON's `unreviewed`, and **refuse to
162
- score `SHIP`** — the merged verdict is at least `REVISE`. Absence of evidence is not evidence of
163
- absence, and it must never reach `/cohorte-ship` or tick a DoD box.
164
- - **Never re-review the other surfaces** to compensate: their reports are valid and already on disk.
165
-
166
- Then merge the returned reports into **one** REVIEW REPORT (same template): findings concatenated and
167
- re-ordered by severity, counts summed, duplicates collapsed, verdict = the worst returned
168
- (`BLOCK` > `REVISE` > `SHIP`). The `## Deferred` sections merge the same way (dedupe by
169
- `file` + problem) and stay **out of the severity table and out of the verdict** — see §3.5, which
170
- routes them. Append ONE metrics line for the batch to the **main checkout's**
171
- `$(dirname "$(git rev-parse --git-common-dir)")/<state>/pipeline-metrics.jsonl` (rules in
172
- `/cohorte-build` §4; never a bare relative path — from a worktree that strands the lines): `{"ts":"<ISO>","feature":"$ARGUMENTS","phase":"review","seconds":<wall-clock>,"surfaces":{"<key>":"<verdict>:<finding count>",…}}`.
173
- **Stage the full report to `specs/reports/$ARGUMENTS.md`** (overwrite) — a gitignored buffer so a
174
- `/cohorte-fix` after a `/clear` can still read the findings; the `specs/reports/` subfolder is skipped by the
175
- non-recursive `specs/*.md` glob, so it's never mistaken for a spec (no phantom card, no bogus stage).
176
- **Write the machine-readable verdict** to `specs/reports/$ARGUMENTS.verdict.json` (overwrite) — on
177
- **every** run, including the small-diff fast path of §2 and a `SHIP`. This file is the ONLY contract
178
- between the pipeline and any automated driver, which parses no prose:
179
-
180
- ```json
181
- { "id": "$ARGUMENTS", "phase": "review", "ts": "<ISO>", "verdict": "REVISE",
182
- "findings": 7, "blocking": 2, "security": 1, "deferred": 3, "unreviewed": [],
183
- "severity": {"CRITICAL": 1, "HIGH": 2, "MEDIUM": 3, "LOW": 1},
184
- "surfaces": {"backend": {"verdict":"BLOCK","findings":4,"blocking":2}},
185
- "blocking_items": ["backend|apps/api/src/routes/order.ts|missing authz on post"],
186
- "fingerprint": "b3f1c2a90d4e5f67" }
187
- ```
188
-
189
- - **`blocking` = CRITICAL findings + `security` findings, deduplicated** (a finding that is both
190
- counts once). That is exactly the agent's existing verdict rule restated as a number, so
191
- `blocking == 0` ⟺ `verdict == SHIP`. HIGH/MEDIUM/LOW quality findings are **not** blocking and
192
- must never cost a driver an iteration — a *human* routes them in the verdict branch below
193
- (a `/cohorte-fix` pass, or a deliberate park in the backlog); a driver ignores them.
194
- - **`blocking_items`** — one normalized string per **distinct** blocking finding (deduplicated —
195
- two findings sharing surface, file and problem head are one identity), `<surface>|<file>|<problem>`:
196
- the file path **without the `:line`** (a fix that inserts lines shifts every line below it — a
197
- line-bearing identity would change every pass and the drift detection would never fire), and the
198
- **problem**, not the fix, cut to its first 8 words, lowercased, every run of non-alphanumerics
199
- collapsed to one space. Identity of a finding, not its wording.
200
- - **`fingerprint`** — computed in the same Bash call, never by hand:
201
- `printf '%s\n' "<item>" … | LC_ALL=C sort | sha256sum | cut -c1-16` (`shasum -a 256` where there
202
- is no `sha256sum`). Empty list ⇒ `""`. A driver comparing two consecutive fingerprints detects a
203
- fix loop that is treading water.
204
- - **`deferred`** — the count of merged `## Deferred` items §3.5 parked in the backlog. Informational:
205
- it never enters `blocking`, so it can never cost a driver an iteration.
206
- - **`unreviewed`** — the surface keys whose reviewer died twice, `[]` on a complete run. It is
207
- **separate from `blocking` on purpose**: `blocking` counts real findings (CRITICAL + security), and
208
- faking a number there to force a driver's hand would corrupt the one field the whole contract rests
209
- on. A non-empty `unreviewed` means "this run does not cover everything" — a driver treats it as no
210
- usable verdict, never as clean, whatever `blocking` says.
211
-
212
- ## 3.5 Route the deferred findings — the backlog, not the fix loop
213
-
214
- Do this on **every** run, before the verdict branch below, and whatever the verdict — a deferred
215
- finding that is only routed on a `SHIP` is a deferred finding lost on every other verdict, which is
216
- exactly the leak this step closes. Append each merged `## Deferred` item to
217
- **`specs/refactor-backlog.md`**, under the `## <domain>` heading of the surface that owns its
218
- `file:line` (create the file and/or heading if absent — same grouping `/cohorte-audit` writes, so
219
- `/cohorte-refactor <domain>` picks them up with no extra plumbing):
220
-
221
- ```
222
- - [ ] <SEVERITY> · <file:line> · <quality|security|rule|complexity> · <concrete fix> · deferred:$ARGUMENTS
223
- ```
224
-
225
- - **Never into the spec's `## Remediation`** — that list is what `/cohorte-fix` re-dispatches, so a
226
- deferred item there would re-trigger the very fix round it was deferred out of.
227
- - **Dedupe before appending:** `grep -F` the backlog for the item's `<file>` + the first words of its
228
- problem; already there (from a prior round or an `/cohorte-audit`) ⇒ skip it, don't stack duplicates round
229
- after round.
230
- - Append with `>>` in ONE Bash call; never read the whole backlog into context to rewrite it (it grows
231
- with every audit the repo has ever run).
232
- - Report it as **one line** in chat: `deferred: <n> parked in specs/refactor-backlog.md (<domains>)`.
233
-
234
- In chat print ONLY: the verdict, the severity-count table, a one-line digest of each CRITICAL/security
235
- finding, and `Full report: specs/reports/$ARGUMENTS.md` — never echo the findings body into chat (it
236
- would sit in this session's history, re-sent every turn). Then:
237
-
238
- - **SHIP** → only reachable with `unreviewed` empty (the roll call above forbids it otherwise).
239
- **Split on what survived — the DoD tick and the freshness stamp are earned by a clean bill, not
240
- by the verdict alone** (the workflow variant enforces the same rule; certifying surviving
241
- HIGH/MEDIUM findings for `/cohorte-ship` would ship known defects):
242
- - **Nothing above LOW survived** — the clean bill. **Tick the DoD**: in `specs/$ARGUMENTS.md`
243
- §`Acceptance criteria / DoD`, flip each `- [ ]` → `- [x]` for the criteria the pipeline has
244
- actually verified — spec conformance + `ui_language` copy (this review), tests · lint ·
245
- typecheck (a green `/cohorte-build`), mobile-first as far as the code shows it (this review).
246
- **Leave `- [ ]` (and say which) any item no stage actually verified** — nothing in the pipeline
247
- *runs* the feature, so any criterion that needs the app up (runtime flows, a visual check
248
- against the design) stays open unless the human says they exercised it by hand and it held.
249
- Ticking is the lead's job (the reviewer is read-only). **Then stamp the freshness gate** so
250
- `/cohorte-ship` can refuse to ship code edited after this verdict: compute
251
- `BASE=$(git merge-base <default_branch> HEAD)` and write into the spec front-matter
252
- `reviewed_base: $BASE` plus `reviewed_digest: $(git diff $BASE -- . ':(exclude)specs/' | sha256sum | cut -c1-16)`
253
- (`shasum -a 256` then the first 16 hex chars where there is no `sha256sum` — macOS) — the
254
- fingerprint of exactly the source you just reviewed (specs excluded, so DoD ticks + the ship
255
- status flip don't trip it). Park the leftover LOWs through §3.5's exact route (the backlog,
256
- under their surface's domain heading, tagged `deferred:$ARGUMENTS` — never as open
257
- `## Remediation` items, which would re-trigger the fix loop). Then tell the human they can
258
- `/cohorte-ship` — **recommend a `/clear` first**, the handoff is fully on disk.
259
- - **HIGH or MEDIUM findings survived** — the verdict stays SHIP (they are not blocking), but
260
- **no DoD tick and no freshness stamp**. Route them: `/cohorte-fix $ARGUMENTS` for what should
261
- be fixed now; MEDIUMs the human *explicitly* chooses to live with go through §3.5's park
262
- instead — and once everything left is LOW, apply the clean-bill branch above (tick, stamp,
263
- ship). The stamp is the pipeline certifying what ships; it is never written over known
264
- HIGH/MEDIUM defects.
265
- - **REVISE / BLOCK**, or any CRITICAL/HIGH/security finding → tell the human to run
266
- **`/cohorte-fix $ARGUMENTS`** — it appends the report to the spec's `## Remediation` and re-dispatches ONLY
267
- the surfaces with findings. The full path (`/cohorte-spec` Mode B then `/cohorte-build`) remains for findings that
268
- change the contract in ways that ripple into clean surfaces. _The report is staged to
269
- `specs/reports/$ARGUMENTS.md`, so you can `/clear` before `/cohorte-fix` — it reads the findings back from
270
- disk._