cohorte 2.10.1 → 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 -1461
  143. package/bin/cli.js +0 -817
  144. package/bin/report.js +0 -141
  145. package/core/adapter/render.js +0 -415
  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 -194
  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 -165
  166. package/core/hooks/gate.py +0 -588
  167. package/core/runtimes/claude.json +0 -74
  168. package/core/runtimes/codex.json +0 -85
  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 -145
  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 -534
  192. package/lib/runtime.js +0 -139
  193. package/lib/versions.js +0 -149
  194. package/lib/yaml.js +0 -129
  195. package/profile/PIPELINE.template.md +0 -259
  196. package/profile/SCHEMA.md +0 -735
  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 -437
  206. package/scripts/test-gate.mjs +0 -443
  207. package/scripts/test-kanban.mjs +0 -304
  208. package/scripts/test-lib.mjs +0 -356
  209. package/scripts/test-metrics.mjs +0 -156
  210. package/scripts/test-workflows.mjs +0 -758
  211. package/scripts/validate-core.mjs +0 -325
package/CHANGELOG.md DELETED
@@ -1,1461 +0,0 @@
1
- # Changelog
2
-
3
- Entries are shown by `/cohorte-update-pipeline` ("What's new") after a core refresh. Keep them
4
- short, user-facing, most recent first. One `## <version> — <YYYY-MM-DD>` section per release.
5
-
6
- > Sections below 2.0.0 name commands **as they were at the time** (`/build`, `/drive`, `/loop`).
7
- > They are history and are deliberately not rewritten — every command gained a `cohorte-` prefix
8
- > in 2.0.0.
9
-
10
- ## 2.10.1 — 2026-09-14
11
-
12
- - **Codex project isolation:** surface agents stay in each repository's `.codex/agents/*.toml`
13
- even with a global core; no `CODEX_HOME` launcher or auth symlink is required.
14
- - **Codex correctness:** init/update/doctor use native TOML agents and MCP settings, preflight
15
- covers `spawn_agent` dispatches, explicit Codex model choices survive, and implementer
16
- templates no longer accidentally force a read-only sandbox. Added regression coverage.
17
-
18
- ## 2.10.0 — 2026-08-24
19
-
20
- - **The dashboard is gone.** The local web cockpit — the `cohorte dashboard` verb, the
21
- dependency-free HTTP server, the Vite/React app and the prebuilt `dashboard/dist` that shipped
22
- in every tarball — is removed, along with the fleet registry, kanban and usage readers that
23
- only it consumed. It was a second surface for state the CLI already reports, with its own
24
- build step, its own security posture (loopback-bound because its action endpoints executed
25
- code: install, update, reset, and `/cohorte-init-pipeline`·`/cohorte-update-pipeline`·`/cohorte-audit`
26
- through headless Claude), and its own drift to police. `cohorte doctor`, `cohorte specs` and
27
- `cohorte metrics` answer the same questions from the shell, and `doctor` exits 1 on any bad
28
- check, which the browser never could.
29
-
30
- **What did not go with it:** the four modules those verbs actually run on — the JS port of
31
- `/cohorte-doctor`, the runtime-layout resolver, the version prober and the block-YAML parser —
32
- moved from `dashboard/server/` to **`lib/`**. `cohorte doctor` / `specs` / `version` behave
33
- exactly as before, and so do the Francois extension's `--panel` payloads. Their test suite
34
- moved with them (`scripts/test-dashboard.mjs` ⇒ `scripts/test-lib.mjs`, 54 assertions), minus
35
- the cases that covered deleted code.
36
-
37
- Fallout worth naming: the package no longer has a build step at all (`prepack` and
38
- `build:dashboard` are gone, npm and CI no longer build a React app to publish), the tarball
39
- drops from 88 files to 73, and `~/.claude/cohorte-dashboard.json` — the tracked-project list —
40
- is now dead; delete it. `--port` / `--host` / `--open` and `COHORTE_DASHBOARD_PORT` /
41
- `COHORTE_DASHBOARD_HOST` no longer exist; `cohorte dashboard` prints the usage and exits 2.
42
-
43
- ## 2.9.0 — 2026-08-22
44
-
45
- - **`/cohorte-intake` — the door before the doors.** Work has always entered the pipeline
46
- pre-distilled by a human: a ticket became a `/cohorte-patch` paste, an email became a
47
- brainstorm idea, by hand. Intake does the distillation: paste anything that arrives and it
48
- triages — bug ⇒ the exact structure patch interviews for (inferred repro steps labeled as
49
- such); feature ⇒ a brainstorm seed whose open-questions list is the panel's agenda, with any
50
- `_decisions.md` line it contradicts named; noise ⇒ says so and stops, because inventing a
51
- spec from noise costs a whole pipeline run downstream. The distillate lands on disk and on
52
- the kanban's Ideas column; freezing anything stays the human's move.
53
-
54
- - **`/cohorte-retro` — the pipeline learns from its own findings.** Every review leaves
55
- structured residue (verdict.json, the specs' Remediation history, the deferred backlog) that
56
- nothing ever read back. Retro mines it for patterns — the same finding kind on the same
57
- surface across features, a hotspot module, a recurring fix family — and turns each into ONE
58
- rule-shaped §Conventions line the human ratifies. Adopted rules re-render the affected
59
- surface agents (the conventions slice is baked at render time — a rule without a re-render
60
- is one reviewers enforce and implementers never saw) and land in the decisions journal.
61
- Findings → rules → the next build never produces the finding: cheaper than any number of
62
- review rounds catching it.
63
-
64
- - **`/cohorte-fleet` — parallel features get a flight controller.** The worktree isolation
65
- existed; the coordination lived in your head. `plan` builds the feature×surface overlap
66
- matrix from the specs themselves (contract dependencies ⇒ merge order; same-tree writes ⇒
67
- serialize or drop one), provisions the worktrees, and prints one launch line per feature.
68
- `status` is one row per feature ending in the single next action. `sync` does the post-merge
69
- sweep everyone forgets — rebase every survivor, report conflicts verbatim to their owner's
70
- session, and say out loud that a rebase invalidates the freshness stamp. What it will never
71
- do is spawn the work headless: that is the retired 2.2.0 driver's grave, and each feature's
72
- loop keeps running in its own supervised session.
73
-
74
- - **`/cohorte-review --pr <num>` — the pipeline reviews incoming work.** Same reviewers, same
75
- report, none of the pipeline's certifications: the PR is fetched into a throwaway worktree
76
- (your checkout untouched), reviewed in audit mode (no spec to conform to), and a red
77
- preflight makes the mechanical failures the review instead of wasting reviewers on code that
78
- doesn't compile. Posting the report as a PR comment always asks first — it is outward-facing
79
- — and declining leaves the report on disk as a complete outcome.
80
-
81
- - **What a feature costs, finally on the dashboard.** The workflow paths now stamp an
82
- approximate `tokens` field into their metrics lines from the runtime's own counter
83
- (`budget.spent()` deltas — the figure a conversational lead cannot read), the loop's history
84
- carries cost per round, and the dashboard shows `~Nk tok` per feature and per phase. Marks
85
- are placed around the review child so build/fix deltas never double-count it; token-less
86
- conversational lines aggregate as absent, never as "free".
87
-
88
-
89
-
90
- ## 2.8.0 — 2026-08-22
91
-
92
- - **`/cohorte-loop` is back — as a workflow, which is the whole point.** The 2.2.0 driver was
93
- retired because it spawned headless child processes it could not supervise: it stalled on a
94
- permission prompt it could not see, read a missing `build.json` as an empty one, and had a
95
- session killed mid-write with nothing noticing. `core/workflows/loop.js` runs
96
- build → review → [fix → review]* for one feature inside the Workflow runtime instead — the
97
- runtime holds control flow, a dead agent resolves to `null` rather than to silence, and there
98
- is no prompt to stall on.
99
-
100
- What it will not do is as designed as what it does: it *verifies* `/cohorte-build`'s outputs
101
- (frozen spec, fresh `readiness.json`, the lead-authored contract) as preconditions and aborts —
102
- naming the gap — on anything that is a human's call: a `NOT-READY` spec, a surface the profile
103
- doesn't own, a blocking finding on the contract file itself. A dead reviewer's zero findings
104
- can never read as ship (`unreviewed` is checked before `blocking`, in that order on purpose);
105
- identical blocking findings two rounds running abort as treading water instead of burning the
106
- remaining rounds; `maxRounds` (default 5) is the last net, never the first. State is four files
107
- in `specs/reports/` — re-invoking resumes, and every file older than the spec is treated as
108
- absent. There is **no** `core/commands/cohorte-loop.md` and `validate-core.mjs` now fails if
109
- one appears: without the Workflow runtime the loop refuses explicitly rather than degrading to
110
- a lead re-reasoning the fan-out every round at session prices. It stamps `in-progress` /
111
- `in-review` / `blocked` on the spec — the driver states SCHEMA.md kept alive since 2.2.0 have
112
- a producer again.
113
-
114
- To serve it, the review workflow now writes the same `specs/reports/<id>.verdict.json` the
115
- conversational `/cohorte-review` §3 guarantees (blocking count, normalized `blocking_items`,
116
- sha256 fingerprint, the degraded `aborted: "preflight"` form) — one machine contract, two
117
- producers.
118
-
119
- - **A deny behind an ask was reachable with one click.** `gate.py` scanned command segments in
120
- order and returned on the first match, so `git commit -m x && node ace migration:fresh`
121
- surfaced only the benign `git commit` confirm — and the human's single "yes" ran the
122
- hard-denied migration behind it. Deny patterns are now matched across the whole chain before
123
- any ask is offered. Global installs pick this up with `cohorte update`; bundled repos via
124
- `/cohorte-update-pipeline`.
125
-
126
- - **The SHIP stamp is now earned, not implied.** The conversational `/cohorte-review` ticked the
127
- DoD and wrote the freshness stamp on every SHIP — including one carrying HIGH findings, which
128
- `/cohorte-ship`'s gates then happily certified, while the workflow variant refused the same
129
- state. Both paths now agree: tick + stamp only when nothing above LOW survived; surviving
130
- HIGH/MEDIUM routes to `/cohorte-fix` (or an explicit park) first.
131
-
132
- - **A dozen bugs the release audit surfaced**, the sharper ones being: `cohorte install` seeded
133
- `cohorte.config.yaml` under `~/.claude` even when `CLAUDE_CONFIG_DIR` pointed elsewhere — a
134
- config no reader ever probed (CI now asserts the seed lands where the readers look);
135
- the refactor workflow's retry round discarded the items its first verify had already cleared,
136
- so the backlog re-dispatched finished work — and invoked with a bare `"backend"` it silently
137
- refactored *every* big domain; the dashboard trusted the absolute paths in a committed
138
- `runtimes.json`, going all-red on any cloned or moved checkout; `preflight.sh` fed a UTC
139
- timestamp to a local-time `touch -t`, future-dating the throwaway index west of UTC (and an
140
- all-empty command list stamped a green preflight that had verified nothing);
141
- `new-feature.sh` branched worktrees off the *local* default branch its own fetch never
142
- updated; a CRLF kanban board failed with "column not found" on a column that exists; and a
143
- dead mechanical-gates agent read as "0 failures" in the audit workflow. Plus a sweep of doc
144
- drift (the first-feature walkthrough skipped build *and* review; "Node-less" installers that
145
- require Node; stale counts of agents, scripts and board columns).
146
-
147
- - **The shell installers are now the thin delegators they already were.** Since 2.2.0 both
148
- scripts handed everything to `bin/cli.js` and then carried ~300 lines of unreachable legacy
149
- copy code below the hand-off — dead text that `validate-core`'s "does the installer copy X"
150
- checks were vacuously matching, which is worse than no check: it reads as coverage. The dead
151
- code is gone; the checks now assert CI's install dry-run postconditions — tests against the
152
- copy that actually runs. Along the way: `sh install.sh` from inside a checkout silently
153
- *cloned the remote* instead of installing the local tree (`$0` arrives with no slash and the
154
- self-locate case missed it); both installers now refuse a Node older than 18 up front instead
155
- of half-installing before `fs.cpSync` crashes; and the review agent's `tools:` names both
156
- retrieval providers (`mcp__serena`, `mcp__graphify`) — one fixed agent file, shared across
157
- projects, only the wired provider is live in a session, and graphify projects' reviewers were
158
- silently cut off from their own index.
159
-
160
-
161
- ## 2.7.0 — 2026-08-22
162
-
163
- - **The metrics panel billed Sonnet 5 fifty percent over.** `prices.json` carried $3/$15 because
164
- that was the rate scheduled to take effect on 2026-09-01. It never will: Anthropic made the
165
- $2/$10 introductory rate the standard one. Every run costed since the entry was written reads
166
- high, and the further back a run is, the more confidently wrong the number looks.
167
-
168
- Sonnet 5 is now $2/$10, and the file says in prose why the increase must not be reinstated —
169
- the next person to "correct" this back will at least have to argue with a comment first. Sonnet
170
- 4.6 and earlier stay at $3/$15: same tier, different price, and the longest-prefix lookup keeps
171
- them apart on its own.
172
-
173
- - **A concurrency ceiling that moved while the comments stood still.** `audit.js` described the
174
- runtime as capping concurrent agents at "~16". It is 20, it is named
175
- (`CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS`), and raising it raises the ceiling without changing this
176
- script — the queue belongs to the runtime, and a queued domain was never a lost one. Comments
177
- only; no dispatch logic moved.
178
-
179
- - **The design brief was the one step the pipeline handed back to you.** `/cohorte-spec` freezes a
180
- brief to `specs/design/<feature_id>.md` and then said, in effect, paste this somewhere else. With
181
- `design.inline: true` it can instead hand that file to `/design`, which reads the codebase,
182
- matches the existing UI style, and returns editable artboards without leaving the session.
183
-
184
- The flag is off by default and degrades rather than fails: an unmet floor falls back to the
185
- paste-it-yourself path with a note, never an error. It needs `provider: claude-design`, the new
186
- `inline_design` runtime capability (Claude Code only), and a CLI ≥ 2.1.234 — a **higher floor than
187
- workflows' 2.1.154**, which is why `/cohorte-doctor` grew a separate check `8b` instead of raising
188
- the existing one. Raising the shared floor would have made every install between the two versions
189
- read as broken while its workflows ran fine.
190
-
191
- Understand what inline does and does not change: it changes who does the pasting. The brief is
192
- still written to disk first and is still what `/cohorte-build` reads — artboards are an aid to the
193
- human, not an input to the pipeline. And `/design` is a research preview that **does not save them
194
- for you**, so check 8b says so on every run, including the runs where everything passes. An
195
- artboard nobody exported dies with the session, and there is no way to notice afterwards.
196
-
197
- - This release adds a runtime capability, a profile flag, and a command section: run
198
- `/cohorte-update-pipeline` after updating.
199
-
200
- ## 2.6.0 — 2026-08-14
201
-
202
- - **Two ways to type the same command, and one of them silently doesn't work.** The docs wrote
203
- `npx cohorte install`, the Francois extension's manifest names a bare `cohorte` binary, and
204
- nothing said why the two could not be the same string. They cannot: `npx` fetches a package
205
- into a cache and runs it once, leaving nothing on `PATH`, and a Francois panel may only spawn
206
- a **bare binary name resolved on `PATH`**. So the extension's requirement read like a
207
- preference the rest of the documentation contradicted.
208
-
209
- Every command is now written one way — `cohorte <verb>`, after `npm i -g cohorte` — across the
210
- README, the docs, both shell installers, the CLI's own banners, the `/cohorte-doctor` fix
211
- lines, and the `install` string `/cohorte-init-pipeline` writes into a repo's committed
212
- `pipeline.json`. `npx cohorte@latest <verb>` still works and is still the right call for a
213
- one-off on a machine you don't own; it is named once, as the escape hatch it is.
214
-
215
- - **The cost of pinning, removed before it could bite.** `install` and `update` lay down the core
216
- carried by the CLI that runs them. `npx cohorte@latest` made that self-correcting; a global
217
- install does not, so `cohorte update` on a CLI left at an old version would re-lay an old core
218
- and report success — an update that updates nothing.
219
-
220
- Both verbs now compare themselves against the registry when they finish and print exactly what
221
- to run (`npm i -g cohorte@latest`) when they are behind. It is never fatal, never blocks a
222
- successful install, costs a 2.5s fetch with no `npm view` fallback, and stays silent on any
223
- failure — an offline install pays 2.5 seconds and says nothing. `COHORTE_NO_VERSION_CHECK=1`
224
- opts out; `CI` opts out already.
225
-
226
- Nothing in the pipeline changed: no new agent, no gate, no template — this release needs no
227
- `/cohorte-update-pipeline`.
228
-
229
- ## 2.5.0 — 2026-08-14
230
-
231
- - **Everything the pipeline knew about your repo, it would only say to a coding agent.**
232
- `/cohorte-doctor` reads the health of an install and `specs/*.md` holds the board, but both
233
- answers cost a session: you opened Claude Code, ran a command, and read prose. There was no
234
- way to ask "is this repo's pipeline sound?" from a shell script, a CI job, or anything that
235
- isn't an LLM.
236
-
237
- Two read-only commands now answer without an agent in the loop:
238
-
239
- ```sh
240
- cohorte specs # the board: id · status · branch · title, from specs/*.md frontmatter
241
- cohorte doctor # the /cohorte-doctor checks — exits 1 when any check is bad
242
- ```
243
-
244
- `doctor` **exits 1 on any bad check**, so it drops into CI as-is. Both reuse the dashboard's
245
- own readers, so the board, the dashboard and the CLI can never give three answers about one
246
- repo. `--porcelain` gives one record per line with `U+001F` between fields — a spec title
247
- with a space in it never misaligns a column — and `--json` gives the native document.
248
-
249
- - **The pipeline, in Francois.** A third shape, `--panel` (on `specs`, `doctor` and `metrics`),
250
- emits the payload a [Francois](https://github.com/antoine-gmnz/francois) extension panel
251
- validates against. It exists for
252
- [**francois-plugin-cohorte**](https://github.com/TheBidouilleAgency/francois-plugin-cohorte):
253
- a manifest-only extension — no code, no binary — that renders the 30-day cost, the doctor
254
- report and the spec board as three panels beside your sessions, on any project with a
255
- `PIPELINE.md`.
256
-
257
- ```sh
258
- npm i -g cohorte # a Francois extension may only spawn a
259
- francois ext install TheBidouilleAgency/cohorte # bare binary on PATH — never npx, never a shell
260
- ```
261
-
262
- This is the only Francois-aware surface in the package, and it is one flag wide. Nothing in
263
- the pipeline itself changed: no new agent, no new gate, no template to re-render — this
264
- release needs no `/cohorte-update-pipeline`.
265
-
266
- ## 2.4.0 — 2026-08-13
267
-
268
- - **The pipeline froze *what* to build, never *how much*.** A spec pins the contract and the
269
- acceptance criteria, so the feature was right — but nothing ever asked an implementer whether the
270
- helper it was about to write already existed three files over, whether the stdlib shipped it, or
271
- whether the abstraction it was wrapping had exactly one caller. The diff came out correct and
272
- fatter than it needed to be, and every extra line was then paid twice: once at build, once again at
273
- `/cohorte-review`, whose cost is linear in the diff it reads.
274
-
275
- Implementers now walk a **minimality ladder** before inventing anything: does it need to exist at
276
- all → already in this repo → stdlib/framework → native platform feature → an already-installed
277
- dependency → a few inline lines → only then the minimum the contract requires. It governs the
278
- **how**, never the **what** — a contract field, an acceptance criterion, a test, a validation or an
279
- authz check is out of its reach, by construction. It is bounded to **one lookup per candidate**, so
280
- it costs a symbol search and not an exploration, and a shortcut kept on purpose surfaces in the
281
- handoff's `## TODO / not done` with its ceiling and its upgrade trigger, instead of rotting in a
282
- comment.
283
-
284
- The `review` agent gains the matching axis — over-engineering, tagged `delete:` / `stdlib:` /
285
- `native:` / `yagni:` / `shrink:`, always naming the cheaper replacement. It is deliberately the
286
- weakest thing in the report: **5 findings max, MEDIUM ceiling, never a CRITICAL, never a REVISE,
287
- never a BLOCK**. A diff whose only findings are `complexity` ships, and they park in the backlog
288
- like any other nit. Tests, fixtures and anything the contract mandates are out of bounds — coverage
289
- is not bloat. In audit mode the axis widens to the whole target (10 per domain, biggest cut first,
290
- closing with `net: -N lines, -M deps possible.`), and `/cohorte-audit` files them under a new
291
- `complexity` backlog tag: the cheapest wins in the file, since deleting code needs no new test.
292
-
293
- Doctrine adapted from [ponytail](https://github.com/dietrichgebert/ponytail) (MIT) — the decision
294
- ladder and the finding tags are theirs; the subordination to the frozen contract and the
295
- can't-block severity ceiling are what make them safe inside a gated pipeline.
296
-
297
- Run `/cohorte-update-pipeline` to re-render your surface agents — the ladder lives in the
298
- implementer template, so it only reaches your agents through a reconcile.
299
-
300
- ## 2.3.0 — 2026-08-12
301
-
302
- - **A bug fix had to pretend to be a feature.** The only way into the pipeline was
303
- `/cohorte-spec` — a section-by-section interview whose critical part is a frozen §5 contract, with
304
- a ~300-line budget. For a `500` on an empty cart that is more work than the fix, so in practice you
305
- left the pipeline and patched by hand: no frozen intent, no review, no trace.
306
-
307
- `/cohorte-patch` is the bug-fix entry point. A **triage, not an interview** — repro, expected
308
- behaviour, what must not change — it locates the cause itself and freezes
309
- `specs/patch-<slug>.md` (`kind: patch`, ~60 lines). The **§4 regression test replaces §5 CONTRACT**
310
- as the thing the diff is checked against.
311
-
312
- Then nothing downstream is special-cased: a patch spec *is* a spec, so `/cohorte-build` →
313
- `/cohorte-review` → `/cohorte-fix` → `/cohorte-ship` consume it unchanged, one `/clear` between
314
- each — four short sessions instead of one thread re-sending its own triage history at input price
315
- every turn. Only three places read `kind: patch`: build §1.6/§2 (judge the repro + test, author no
316
- contract when §5 is `none`), the `review` agent (scope creep becomes a first-class finding), and
317
- ship (branch off `vcs.patch_branch_prefix`, `patch` bump by default, `fix(<scope>)` commit).
318
-
319
- A patch may span **several surfaces** — one bug, one repro, one spec. The single hard escalation:
320
- a fix needing **new** contract surface area is a feature wearing a bug's clothes, and it is routed
321
- to `/cohorte-spec` rather than letting two surfaces invent a shape independently.
322
-
323
- - **Telemetry is gone — all of it.** The opt-in usage pings that shipped through 2.2.0 are removed
324
- wholesale: the `telemetry-send.sh` sender, the per-phase pings in the six funnel commands, the
325
- consent question in `/cohorte-init-pipeline`, the `telemetry:` block in the config template, the
326
- `/cohorte-doctor` consent check, the collector contract in `SCHEMA.md`. Cohorte now sends nothing,
327
- anywhere.
328
-
329
- **Upgrading removes what is already on disk.** Copy-over never deletes, so an existing install
330
- would otherwise keep an executable that still POSTs to the collector — all three installers
331
- (`install.sh`, `install.ps1`, `npx cohorte`) now scrub it, and CI asserts its absence. And
332
- `/cohorte-update-pipeline` deletes the leftover `telemetry:` block from
333
- `~/.claude/cohorte.config.yaml`: nothing reads it any more, and an `enabled: true` left sitting in
334
- a file you may open reads as though data were still leaving the machine.
335
-
336
- The OpenTelemetry tip (Claude Code's own metrics export, a collector you point at yourself) is
337
- gone from `SCHEMA.md` §Measuring cost and the token-economy guide too. `/cost` and
338
- `pipeline-metrics.jsonl` remain — both entirely local.
339
-
340
- `validate-core.mjs` gained a ratchet: any mention of telemetry or a usage ping under
341
- `core/{commands,agents,templates,workflows}` now fails CI, so it cannot creep back in by copying an
342
- old command file. The single exemption is `/cohorte-update-pipeline` — the command that *deletes*
343
- the leftovers has to name them — and it is itself checked for never naming a ping, a sender or a
344
- consent flow.
345
-
346
- - **Kanban:** `/cohorte-patch` with no argument offers the **Ideas** column, `[patch]`-titled cards
347
- first, and titles its own card `[patch] <title>` (join key `#patch-<slug>`). The `[<kind>]` prefix
348
- stays a human convention — nothing parses it.
349
-
350
- - **Profile:** new optional `vcs.patch_branch_prefix` (default `fix/`); `/cohorte-update-pipeline`
351
- tops it up, and a profile without it falls back to the same default.
352
-
353
- ## 2.2.0 — 2026-08-12
354
-
355
- - **The pipeline was Claude Code or nothing.** The doctrine — frozen spec, stateless surfaces, a
356
- gate you cannot talk your way past — is not Claude-specific, but every artefact that carried it
357
- was: `.claude/commands/*.md` with Claude frontmatter, `Task` dispatches, a PreToolUse hook. A
358
- Codex or Cursor user could read the ideas and reimplement nothing.
359
-
360
- `core/commands/` and `core/agents/` are now **runtime-neutral sources**, and the installer renders
361
- them per coding agent — as slash commands, TOML commands, or **Codex skills**
362
- (`.agents/skills/<name>/SKILL.md`, committed with the repo: custom prompts are deprecated *and*
363
- user-scoped, so a teammate cloning the repo would have got the profile and none of the commands) —
364
- for **Claude Code, Codex CLI, Cursor, Gemini CLI, OpenCode**
365
- (`npx cohorte install --runtime=codex,cursor`, or `--all-runtimes`, or nothing and it detects and
366
- asks). Rendering rewrites the surface — markdown + the frontmatter keys that runtime understands,
367
- or TOML for Gemini — resolves every path through the tokens `<core>` / `<state>` / `<agents>` /
368
- `<config>` / `<memory>`, and swaps the argument placeholder (`$ARGUMENTS`, `{{args}}`, or an
369
- explicit note where the runtime substitutes nothing, as Cursor does).
370
-
371
- The part that is not cosmetic: the prompts **branch on what the runtime can enforce**, and say so
372
- in their own text rather than pretending.
373
-
374
- **The gate really runs on four of the five.** `gate.py` is registered as a blocking hook in each
375
- runtime's own format — `PreToolUse` in `settings.json` (Claude) and `.codex/hooks.json` (Codex),
376
- `beforeShellExecution` in `.cursor/hooks.json`, `BeforeTool` in `.gemini/settings.json` — and
377
- emits that runtime's envelope, selected by `--runtime <id>`. A verdict in the wrong shape is read
378
- as *allow* by every one of them, so each dialect is covered by `scripts/test-gate.mjs` rather than
379
- trusted. **Codex and Gemini have no confirmation tier**, so an `ask` verdict is escalated to
380
- `deny` with the reason attached: the point of that tier is that a human sees the command first,
381
- and a runtime that cannot ask cannot deliver it — the same rule unattended headless runs already
382
- used. The phase gate also learned Gemini's shape, where a subagent arrives as a tool of its own
383
- name rather than as `Task` + `subagent_type`. OpenCode extends via plugins, not hooks, so there
384
- the commands call `gate.py --check` themselves: same verdicts, but advisory, and
385
- `/cohorte-doctor` says so instead of reporting ✅.
386
-
387
- **Subagents are real everywhere**, in four different file formats — markdown + frontmatter for
388
- Claude, Cursor, Gemini and OpenCode, TOML with the body under `developer_instructions` for Codex.
389
- Read-only enforcement for the reviewer is derived from the source agent's tool list and re-emitted
390
- as each runtime spells it (`readonly: true`, `sandbox_mode = "read-only"`); where there is no
391
- equivalent, the rendered reviewer carries an explicit instruction that read-only is on it, and
392
- why. Model pins do **not** travel: the profile names Anthropic aliases, which are meaningless
393
- elsewhere, so agents inherit the runtime's own model selection.
394
-
395
- **Real subagents are a requirement, not a capability to degrade around.** A sequential-persona
396
- fallback shipped mid-development and was removed before release: it asked the lead to simulate the
397
- isolation boundary by discipline — adopt one agent file, do that surface, drop it — which is not
398
- the same guarantee, and no supported runtime ever took the branch. A runtime declaring
399
- `subagents: false` is now refused at install with a named error rather than rendered into a
400
- pipeline whose central promise is silently absent.
401
-
402
- - **`/cohorte-loop` is removed, on every runtime including Claude Code.** The autonomous
403
- build→review→fix driver was the one part of the pipeline tied to a single vendor's headless CLI —
404
- it spawned `claude -p` children through two shell scripts, a detached `screen` session, a
405
- `caffeinate` assertion and a resume protocol stamped into spec front-matter. That is a lot of
406
- surface, on the platform-specific end of the codebase, for a phase the human-driven cycle already
407
- covers at a cost the loop was mostly there to hide.
408
-
409
- Gone with it: `scripts/loop.sh`, `scripts/loop-detach.sh`, their test suite, and the
410
- `loop_pass`/`loop_phase` front-matter fields (dropped from the spec template; still *read* by the
411
- dashboard so a spec left mid-flight by an older core still explains itself). The installer scrubs
412
- the command and both scripts on upgrade, in every runtime's layout — copy-over never deletes, and
413
- a surviving command file is a decoy the model can still fire against a core that no longer ships
414
- its driver.
415
-
416
- **The file contract stays.** `verdict.json`, `readiness.json` and `build.json` are still written
417
- on every run, and the `in-progress`/`blocked` spec statuses stay valid: they are what anything
418
- automating the cycle from outside reads and writes. Removing the built-in driver does not remove
419
- the ability to drive it — it removes cohorte's opinion about how.
420
-
421
- Layout: each runtime gets its own rendered core (`.cohorte/<id>/`), because the same template
422
- resolves differently per capability — but the **project state is shared** (`.cohorte/`:
423
- gate-config, preflight stamp, metrics), so a repo driven from two agents cannot disagree with
424
- itself about what is gated or what has been verified. The user config is shared too; the shipped
425
- scripts probe `~/.claude` then `~/.cohorte`, so one kanban board and one telemetry consent.
426
-
427
- **Claude Code is unchanged** — same paths, same frontmatter, same hook, and `scripts/test-adapter.mjs`
428
- asserts that as a regression test alongside the per-runtime output. `install.sh` / `install.ps1`
429
- now delegate to the Node CLI: there is no shell renderer, and a raw copy would install prompts
430
- full of unresolved markers that look installed and instruct the model wrongly.
431
-
432
- - **A config dir with a space in it broke every tool call in the session.** The gate-hook
433
- registration quoted the script path only on Windows, so a `CLAUDE_CONFIG_DIR` under
434
- `~/Library/Application Support/…` — where a desktop host naturally puts it — produced
435
- `python3 /Users/x/Library/Application Support/…/gate.py`. The shell split that, python reported
436
- `can't open file '/Users/x/Library/Application'`, and *every* Bash and Task call failed —
437
- including the ones needed to undo it. Quoted on every platform now, in both the global
438
- registration and the per-runtime one, with a test that installs into a path containing a space
439
- and asserts the quoting plus that a re-install still reconciles its own entry instead of
440
- stacking a second.
441
-
442
- - **`CLAUDE_CONFIG_DIR` was only half honoured.** The runtime registry declares Claude's paths as
443
- `~/.claude`, and the adapter resolved them from the homedir — so with the variable set, the core
444
- was written to the real `~/.claude` while the hook was registered in the overridden dir. A
445
- scratch or CI install silently wrote into the user's actual global core. `resolvePaths` now
446
- takes a re-rooting override, and the test asserts the core, the commands and the hook all land
447
- in the override with nothing written to the home default.
448
-
449
- - **The dashboard reported a healthy non-Claude install as broken.** Every path it checked was
450
- `.claude/…`, so a repo driven from Cursor came back "no pipeline core installed", "surface with
451
- no rendered agent", "artifacts not gitignored", "gate.py not registered" — four findings, all
452
- false. A false red is worse than no check: it sends someone fixing what is not broken. The
453
- server now resolves paths from `runtimes.json` (`dashboard/server/runtime.js`), reads the gate
454
- registration in each runtime's own envelope, names artifacts against the right state dir, reads
455
- the metrics sink from every state dir in play, skips workflows where there is no engine instead
456
- of reporting them missing, and the reset action backs up every runtime's directory rather than
457
- leaving the others behind for the fresh install to land beside.
458
-
459
- - **`SCHEMA.md` is the agents' rulebook, read at run time — and it still hardcoded `.claude`.**
460
- It ships to `<core>/pipeline/`, so on a non-Claude install it was telling agents to write
461
- rendered agents and read the gate config in a directory that runtime never looks at. It and
462
- `PIPELINE.template.md` now use the same `<core>`/`<state>`/`<agents>`/`<config>` tokens as the
463
- commands, and the installer resolves their capability conditionals like any other prompt.
464
-
465
- - **The preflight stamp could green code that had changed.** Both sides of the content digest seed
466
- a throwaway git index from the real one, for its stat cache — but the copy is stamped `now`, and
467
- git trusts an entry's cached stat data whenever the entry predates the index file. A file edited
468
- in the same second as the preflight, at an unchanged size, therefore read as clean: the gate let
469
- a `review` dispatch through onto code the preflight never verified. Both `gate.py` and
470
- `preflight.sh` now backdate the copy by 5 s, which forces a content check for anything touched
471
- inside that window and leaves the fast path intact for every older file.
472
-
473
- ## 2.1.0 — 2026-08-09
474
-
475
- - **A repo that gates merges on a per-feature release note shipped red PRs, and the flow reported
476
- success.** Changesets' `changeset` job fails any PR that touches product code without a
477
- `.changeset/*.md`, but that requirement lives in the project's `CLAUDE.md` — which the ship flow
478
- never reads. So `/cohorte-ship` committed, pushed, opened the PR and moved the kanban card to
479
- **Shipped** while the PR was unmergeable, red on a job nobody was watching.
480
-
481
- The profile gains a `release_notes` block (`enabled`, `tool`, `dir`/`filename`,
482
- `anchor_package`, `language`, `forbid_levels`, `empty_cmd`, `ci_job`, `guidance` — SCHEMA.md
483
- §Release notes), and `/cohorte-ship` gains **§2b**: the lead writes the note itself, next to the
484
- `status: shipped` flip, so it lands *inside* the release commit rather than in a second one after
485
- the PR is already open. The bump level is project policy, not a git ritual — the release agent is
486
- now explicitly forbidden from authoring or editing a note, and only stages the one it is handed.
487
- §4 verifies the note is in the commit; §5 routes a red `ci_job` back to §2b instead of through
488
- `/cohorte-fix`, which would treat a missing note as a code finding.
489
-
490
- Two things the block encodes that the tool itself does not: `forbid_levels`, for the `0.x` repo
491
- where a `major` changeset silently jumps to `1.0.0` with no human deciding it, and the rule to
492
- **ask** rather than guess between two defensible levels — a wrong bump is a published version
493
- number, not a fixable draft. `empty_cmd` covers the honest no-op, for a PR that must move no
494
- version at all.
495
-
496
- - **Existing projects are asked, not defaulted.** `/cohorte-init-pipeline` detects a versioning tool
497
- or note-enforcing CI job in Phase 1 and asks the anchor package, language and bump policy in Phase
498
- 2; `/cohorte-update-pipeline` treats `release_notes` as a genuine human decision during reconcile
499
- rather than topping it up blind. No tool found ⇒ `enabled: false`, and §2b is a silent no-op.
500
-
501
- ## 2.0.2 — 2026-08-08
502
-
503
- - **Kanban cards stopped moving mid-pipeline, and every stage still reported success.** The
504
- stages only *described* the move — "move card `#<id>` → Building, no-op silently if no board" —
505
- without saying where a board is even declared. Each phase runs in its own session after a
506
- `/clear`, so the cheapest reading consistent with that instruction is "I see no board, so there
507
- is none": a `/cohorte-ship` run announced "no kanban board configured", having opened neither
508
- `~/.claude/cohorte.config.yaml` nor `PIPELINE.md`, and a feature that shipped and merged left
509
- its card sitting in "Ready to build". Silence was indistinguishable from correctness, so this
510
- went unnoticed across several features.
511
-
512
- Resolution is not a judgment call, so it is no longer made by a judge. `kanban-move.sh auto <id>
513
- <stage>` now reads the profile `name`, the config's `kanban.enabled` / `obsidian.vault_path` /
514
- `boards[name]`, and maps the **stage key** (`ideas` … `shipped`) to that board's heading through
515
- `boards[name].columns` → `kanban.columns` → a built-in default. Every stage calls exactly that,
516
- and reports the line it printed: `moved #<id> -> <column>`, or `kanban: <reason>` naming the
517
- missing link. Both exit 0 and they are not interchangeable. A board that *is* configured but
518
- unmovable stays loud (exit 2 usage, exit 3 missing board / unknown column). Explicit board paths
519
- and literal headings still work.
520
-
521
- `validate-core` now fails any funnel command that moves a card without a literal
522
- `kanban-move.sh auto …` call, or that omits the instruction not to conclude "no board" without
523
- running it — the prose-only form is what regressed, so the prose-only form is what is banned.
524
- New `scripts/test-kanban.mjs` (29 checks) pins the resolution table and the move semantics.
525
-
526
- - **Renaming a project silently unlinks its board.** `kanban.boards` is keyed by the profile
527
- `name`, so editing `name:` orphans the old entry and no lookup matches the new one — a genuine
528
- "not configured", identical from the outside to never having had a board. `/cohorte-doctor`
529
- gains check **7b**, which reports the resolved board (or the exact missing link) and flags an
530
- orphaned entry as a rename; `/cohorte-update-pipeline` offers to re-key it instead of creating a
531
- second board. New `kanban-move.sh --check` does the resolution alone, for both.
532
-
533
- - **The gate judged `cd <other repo> && git commit` against the wrong checkout.** Branch-conditional
534
- patterns resolved the branch at the payload cwd, but the tool's shell keeps no cwd between calls,
535
- so agents write the `cd` into the command itself. A commit on a feature branch in another repo was
536
- therefore refused as if it were on the default branch — and the refusal named a branch the command
537
- was never going to run on, so no confirmation could lift it (in an unattended run, where `ask`
538
- escalates to `deny`, it was a hard wall). The branch is now resolved per segment at the cwd that
539
- segment actually runs in, cached so the common case is still one `git` call. Deliberately narrow:
540
- a plain absolute/relative/quoted `cd`, never `cd -`, `$(…)`, variables or globs — anything
541
- unresolvable keeps the previous cwd, which is the direction that keeps gating. `cd` never softens
542
- the unconditional `deny`/`ask` tiers; 10 new cases in `test-gate.mjs` pin all of it.
543
-
544
- - **`/cohorte-brainstorm` tags an Ideas card before moving it.** The join key is the `#<id>` tag,
545
- and an Ideas card a human typed by hand has none — so the move found nothing, created a second
546
- card, and stranded the original in Ideas. It now appends the tag first, located by `grep -n`,
547
- never a full board read.
548
-
549
- ## 2.0.1 — 2026-08-03
550
-
551
- Three fixes, one failure: an autonomous `/cohorte-loop` run that built 1 surface of 3, stamped
552
- itself green, and then hung asking a human to approve its own pre-flight. All in `loop.sh` — no
553
- repo files change, so `npx cohorte@latest update --global` (or `update`) is the whole migration.
554
-
555
- - **Child sessions now run in `bypassPermissions`, not `acceptEdits`.** `acceptEdits` auto-approves
556
- Write/Edit and *nothing else*, so the first `Bash` call no `allow` prefix in `settings.json`
557
- covers raises a permission prompt — and a `claude -p` child has nobody to answer it. It stalls,
558
- prints prose asking you to approve, and **exits 0**, which the driver scores as a clean phase.
559
- That is the whole content of one observed run: the review child blocked on invoking
560
- `preflight.sh` and the loop logged `▶ /cohorte-review … ok`. It is also backwards from what the
561
- gate is built for — `hooks/gate.py` escalates every `ask` match to a hard **deny** under
562
- `bypassPermissions` precisely because an unattended run cannot confirm. So the dangerous commands
563
- from PIPELINE.md `gate` stay blocked deterministically, while typecheck/lint/tests/`git diff` stop
564
- needing a human. `CLAUDE_FLAGS` still overrides it for a watched run.
565
-
566
- - **A build phase that reported nothing is no longer treated as a build that found nothing.** The
567
- driver checked `dead[]` in `specs/reports/<id>.build.json` but accepted the file being **absent** —
568
- and a phase cut short never reaches the step that writes it, so there was no file to grep and no
569
- surface to name while the child still exited 0. A 3-surface build that lost 2 of them mid-write
570
- stamped `<id>.built` and sent reviewers at the result. A missing `build.json` after a build now
571
- aborts as **exit 2**, naming the cause, and leaves no stamp so a re-run rebuilds.
572
-
573
- - **`CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS=0` is exported for every child.** Print mode otherwise
574
- *terminates* still-running background tasks at its ceiling ("Background tasks still running after
575
- 600s; terminating") — which is 25–40 min short of a real implementer batch, and killed the two
576
- surfaces above mid-write. The phase is bounded by its own completion (and by the `caffeinate`
577
- assertion the driver already holds), not by a stopwatch that fires inside the longest phase.
578
-
579
- `test-loop.mjs` pins all three, including the fixture bug that hid the second one: its `ready`
580
- build wrote no `build.json` either.
581
-
582
- ## 2.0.0 — 2026-08-03
583
-
584
- > **Breaking: every command is renamed.** `/build` → `/cohorte-build`, `/review` →
585
- > `/cohorte-review`, and so on for all 13. The driver, `/loop` → `/drive` in 1.6.0, is now
586
- > **`/cohorte-loop`**. Re-run `npx cohorte@latest update --global` (or `update`): the update
587
- > **deletes** the 13 unprefixed command files from your install rather than leaving them as
588
- > decoys. Nothing inside your repo needs editing — `/build` in a spec or PIPELINE.md is prose,
589
- > not a call site. Muscle memory is the only migration cost.
590
-
591
- - **Every command now carries a `cohorte-` prefix, ending command shadowing for good.** A command
592
- whose name collides with a Claude Code built-in is not overridden, it is **shadowed**: the
593
- built-in answers the slash, our file is never read, and the session confidently reports on a run
594
- that never happened. `/loop` did exactly that and went unnoticed until a user found the driver had
595
- never started; `/doctor` was sitting on a watchlist waiting to do the same. 1.6.0 renamed one
596
- name; this replaces the whole approach. `validate-core` now enforces the prefix structurally
597
- instead of maintaining a blocklist that could only ever forbid the collisions we already knew
598
- about. Telemetry **phase** names (`build`, `review`, `fix`, …) stay unprefixed — they are a wire
599
- contract with the collector, and the retired bare command names are kept in the metrics
600
- collector's retired list so months of existing transcripts stay attributed instead of silently
601
- reclassifying to `(chat)`.
602
-
603
- - **`/cohorte-loop` can now run for hours.** It previously ran the driver as one foreground Bash
604
- call, which cannot work: a single call is capped at **600 s** and a build is 25–40 min, so it was
605
- killed mid-`/cohorte-build`. Backgrounding it was worse — a backgrounded Bash call is **not
606
- detached**, so the driver stayed in the calling session's process group and every Claude Code
607
- restart, crash or laptop sleep took `loop.sh` and its `claude -p` children down with it, mid-write.
608
- Observed on a real run: four teardowns in 45 minutes, each aborting both surface implementers and
609
- leaving a half-built tree that read as `dead`. New `loop-detach.sh` puts the driver in its own
610
- `screen` session so it outlives the launching process entirely, and `/cohorte-loop` polls a small
611
- status file in ~9-minute waits. The driver's exit code — which the report table is keyed on —
612
- survives as `__EXIT__ <code>` in that file.
613
-
614
- - **`loop.sh` holds the machine awake for its whole run.** It re-execs itself under
615
- `caffeinate -ims` on macOS, `systemd-inhibit` on Linux, because system sleep aborts every
616
- in-flight `claude -p` request and the abort is byte-identical to "the agent returned nothing" —
617
- the `dead` family the driver exists to catch. The inhibitor is **probed before the `exec`**, since
618
- `exec` replaces the shell: one that exists but is refused (`systemd-inhibit` answers `Failed to
619
- inhibit: Access denied` in a container, in CI, or in any seatless session) would otherwise make its
620
- own failure the driver's exit code and the run would never start — GitHub's Linux runners turned
621
- all 24 loop tests red exactly that way. Absent or refused both fall through to a no-op; an unheld
622
- power assertion is a degraded run, not a failed one, and `test-loop.mjs` now pins both directions.
623
- **This cannot prevent lid-close sleep** — no userspace assertion can on any platform; keep the
624
- lid open or use clamshell mode.
625
-
626
- - **Platform tiers, stated rather than assumed.** Detaching uses `screen` (macOS + Linux), else
627
- `setsid` (Linux) — both escape the caller's process group, which is what actually matters. Git
628
- Bash on Windows has neither, so it falls back to `nohup`, which ignores `SIGHUP` but does **not**
629
- survive a teardown; `loop-detach.sh` prints that warning rather than degrading silently, and
630
- points at running `loop.sh` from your own terminal instead. See the platform table in
631
- `docs/reference/scripts.md`.
632
-
633
- - **Fixed — the preflight stamp is keyed on the code, not on HEAD, and is never versioned.** The
634
- stamp recorded the HEAD sha, which is the wrong key in both directions: the reviewed tree is
635
- normally *dirty*, so committing the very code the preflight verified made the gate ask on a clean
636
- tree, while an implementer editing files between preflight and dispatch invalidated nothing. Worse,
637
- `.claude/preflight.ok` was never gitignored — once a release agent staged `.claude/`, the stamp
638
- went into git describing the tree *before* its own commit, so it could never match again: every
639
- review dispatch in that repo asked "HEAD moved" forever, and every new clone or worktree inherited
640
- a green it never earned. The stamp is now `<epoch> <sha> <tree digest>`, where the digest is the
641
- git tree id of the working tree (`.claude` and `specs` excluded, so the pipeline's own report,
642
- metrics and DoD writes don't invalidate it), computed in a throwaway index that never touches
643
- yours. Pre-2.0.0 two-field stamps still fall back to the HEAD comparison. `/cohorte-doctor` check 3
644
- now fails hard on a tracked stamp, `/cohorte-update-pipeline` untracks it and fixes `.gitignore`
645
- (§Reconcile step 8), and `test-gate.mjs` pins all of it — including "commit the verified code ⇒
646
- still green" and "one edit ⇒ red".
647
-
648
- - **`/cohorte-review` and `/cohorte-fix` now spell out the metrics path instead of delegating it.**
649
- Both said "append a line to `pipeline-metrics.jsonl`" and pointed at `/cohorte-build` §4 for where
650
- that file lives — a lead running from a feature worktree resolves the bare name against its own
651
- cwd and strands the batch in a sink that dies at teardown. Both now carry the resolved
652
- `$(dirname "$(git rev-parse --git-common-dir)")` form inline.
653
-
654
- - **Fixed — the dashboard's command allowlist had drifted from its own error message.** The
655
- server accepted the bare `/audit`/`/init-pipeline`/`/update-pipeline` while the UI sent (and the
656
- error text advertised) the prefixed names, so the run button would have 400'd on the only
657
- commands that exist. The test suite checked *rejection* only, which is why it passed; it now pins
658
- both directions.
659
-
660
- ## 1.6.0 — 2026-08-01
661
-
662
- > **Re-run `npx cohorte@latest update --global` (or `update`)** to pick up the readiness gate, the
663
- > deferred-findings route, the resumable driver and the decision journal — the update *deletes* the
664
- > shadowed `/loop` command and the long-dead `/cycle` from your install, it does not just stop
665
- > shipping them. Existing specs keep working: the new front-matter fields are written on demand, and a
666
- > spec without them simply isn't resumable yet. **`/loop <id>` is now `/drive <id>`.**
667
-
668
- - **New — the readiness gate between `/spec` and `/build`.** `/build` §1.6 now scores the frozen spec
669
- on **implementability** before authoring the contract and before dispatching anything: contract
670
- shapes complete · every area owned by a surface · named dependencies actually exist · no ambiguity a
671
- surface would have to guess at · design links present. The verdict goes to
672
- `specs/reports/<id>.readiness.json` (`READY` · `RESERVATIONS` · `NOT-READY` + `gaps[]`).
673
- **`NOT-READY` stops the build with zero agents spawned** — a spec that can't be built doesn't get
674
- cheaper by being built on N surfaces in parallel — and sends you to `/spec`. `RESERVATIONS` never
675
- blocks: each gap is inlined into the affected surface's dispatch as an assumption the implementer
676
- applies *and* flags in its handoff. It costs **no extra agent**: the lead already holds the spec,
677
- the profile and the reconciled surface list.
678
- - **New — deferred findings: `/review` stops throwing away what isn't blocking.** The review agent
679
- now returns a separate `## Deferred` section (max 10) for what is real but **out of this feature's
680
- scope** — pre-existing code the diff never touched, adjacent debt the spec never claims to fix —
681
- each line carrying its own out-of-scope reason. Deferred items count in no severity row, move no
682
- verdict, are never cross-checked, and on **every** verdict get routed into
683
- `specs/refactor-backlog.md` under the owning surface's `## <domain>` heading, tagged
684
- `deferred:<id>`. So `/review` feeds `/refactor` for free instead of dropping everything
685
- non-blocking on the floor. Never into `## Remediation`, which is what `/fix` re-dispatches. Not
686
- deferrable, ever: anything the diff touched, any spec violation, any security issue on a path this
687
- feature adds or calls. `/audit` now **carries open `deferred:` items over** when it rewrites the
688
- backlog. The verdict JSON gains `deferred: <n>` (informational, outside `blocking`).
689
- - **BREAKING — `/loop` is renamed `/drive`, because Claude Code shadowed it.** Claude Code ships its
690
- own built-in `/loop` (run a prompt on a recurring interval), which won the name: typing
691
- `/loop <id>` started the *interval runner* with the feature id as its prompt, so cohorte's driver
692
- never ran — and the session, having never seen `loop.md`, reported a loop that did not exist. Same
693
- command, same flags, same script (`pipeline/scripts/loop.sh` keeps its name — nothing about your
694
- install paths changes): type **`/drive <id>`**. The update scrubs the old `commands/loop.md`, so a
695
- stale shadowed copy can't linger.
696
- - **`/drive` is resumable — the spec's status is the state machine.** The lifecycle is now
697
- `draft → frozen → in-progress → in-review → shipped` plus `blocked`. Before every phase the driver
698
- stamps `status: in-progress` + `loop_pass` + `loop_phase` into the spec's front-matter — plain
699
- `awk`, a temp file and `mv`, **zero tokens** — and on exit a terminal `in-review` (clean) or
700
- `blocked`. **`/drive <id> --resume`** then continues at the pass it reached instead of re-paying the
701
- ones already made, whether the session died, the ceiling hit, or the fix stopped converging.
702
- `--max` stays a ceiling on the *total* passes. New **exit 4** (`not implementable`) relays the
703
- readiness gate's `NOT-READY`: the one loop outcome more passes cannot fix. The dashboard's specs
704
- board gains In-progress and Blocked columns and shows `↻ pass 3 · /review` on the card; `/doctor`
705
- names any spec left mid-loop.
706
- - **Fixed — a dead subagent no longer reads as a clean one on the conversational path.** The
707
- "a dead agent is never a clean result" doctrine existed since 1.3.4 — but only inside the
708
- **workflows**. `/build`, `/review` and `/fix` had nothing: a subagent that dies (rate limit,
709
- transport error, exhausted context) returns *nothing*, and nothing was indistinguishable from
710
- "finished, nothing to report". Concretely, a dead **reviewer** produced zero findings ⇒
711
- `blocking: 0` ⇒ verdict `SHIP` ⇒ `/drive` exit 0 ⇒ the human sent to `/ship` — a clean bill of
712
- health on code no agent ever read. Now every fan-out phase does a **roll call** before integrating:
713
- a silent surface is retried **once** alone (byte-identical prompt, so recovery costs one agent, not
714
- a rebuild), then `/build` marks it `dead` and verifies the tree with that surface's own quiet
715
- commands instead of speaking for the agent, `/review` lists it in the verdict's new `unreviewed[]`
716
- and **refuses to score `SHIP`**, and `/fix` leaves every one of its items `- [ ]` (a dead agent
717
- never ticks a box). `/build` also writes `specs/reports/<id>.build.json` with `dead[]`, and
718
- `loop.sh` aborts on either signal with **exit 2** *before* reading `blocking` — because a dead
719
- reviewer makes `blocking == 0` a statement about unread code. `unreviewed` is deliberately kept
720
- out of `blocking`: faking a count there would corrupt the one field the driver contract rests on.
721
- The metrics line is now written even when a surface died (`"<key>":"dead"`) — an incomplete batch
722
- is exactly the batch worth recording.
723
- - **Fixed — `/cycle` and its workflow were removed in 1.4.0 but no installer ever scrubbed them.**
724
- Every install since has kept `commands/cycle.md` + `workflows/cycle.js` on disk, so a dead command
725
- stayed listed and invokable — dispatching a workflow whose phases 1.5.0 then deleted. All three
726
- installers now remove them (as they already did for `/smoke`), and CI **plants the orphans before
727
- re-installing** instead of asserting their absence on a fresh scratch home, which is exactly the
728
- blind spot that let this survive four releases.
729
- - **Reconcile now tops up `specs/_template.md`.** It was seeded once at install and never refreshed,
730
- so every repo kept the front-matter its core shipped with. `/update-pipeline` adds the missing
731
- front-matter fields (never the body — the section list is yours).
732
- - **New — `specs/_decisions.md`, the transverse decision journal.** `PIPELINE.md` is a *stack* profile;
733
- it says nothing about what the project has **decided**, so every `/spec` re-discovered or
734
- contradicted the same choices. The journal is deliberately tiny: **append-only, one line per
735
- decision** (`- <date> · <area> · <decision> — because <reason> · <feature_id>`), reversal by a
736
- superseding line rather than an edit. Written by `/spec` at freeze (typically 0–3 lines; zero is
737
- normal) and by `/build` when it adds or splits a surface. Read by the **deciding** stages only —
738
- `/brainstorm`, `/spec`, `/audit`. **Implementers and reviewers never load it:** they have the frozen
739
- contract, and shipping them the rationale would cost `surfaces × dispatches` tokens per feature for
740
- a fact they can't act on. That exclusion is what keeps it cheap enough to be worth having. The `_`
741
- prefix means `/doctor`, the dashboard scanner and the kanban backfill already skip it.
742
-
743
- ## 1.5.0 — 2026-08-01
744
-
745
- > **Re-run `npx cohorte@latest update --global` (or `update`)** to pick up the collector and the
746
- > `/smoke` removal — the update *deletes* the command and its agent from your install, it does not
747
- > just stop shipping them. The new dashboard panel comes with `npx cohorte dashboard`.
748
-
749
- - **New — `/loop <id>`: the review ⇄ fix cycle, run for you.** _(renamed `/drive` in 1.6.0 — see
750
- there.)_ `/build` → `/review` → `/fix` →
751
- `/review` … until a review reports **zero blocking findings** (a CRITICAL or a security issue —
752
- a LOW nit never costs a pass), or the pass ceiling (`--max=N`, default 5), or two consecutive
753
- reviews returning the *same* blocking findings, which means the fix is treading water and more
754
- passes won't help. `--no-build` re-runs the loop on an already-built feature; `--rebuild` forces
755
- a build. Every fix pass is committed (`loop(<id>): fix pass <i>`) — your way back after N
756
- autonomous passes — and **no fix runs on the last pass**, since fixing without a review behind
757
- it leaves unaudited code. Exit codes distinguish clean · ceiling · no verdict · non-convergent ·
758
- usage, so a wrapper can tell "needs more passes" from "needs a human".
759
- - **The loop does not run in your session — that's the whole design.** Each phase is a separate
760
- `claude -p` child with its own fresh context, driven by the new shipped `loop.sh`; all child
761
- output goes to `specs/reports/<id>.loop.log`, which the command is forbidden to read back. Your
762
- session sees one line per phase and a three-line summary. A slash command cannot `/clear` itself,
763
- so a conversational loop would pile the diff plus N review reports plus N contracts into a
764
- history re-sent at input price every turn — it would cost more than the loop saves.
765
- `disable-model-invocation: true`: an autonomous loop only ever starts because you asked.
766
- - **`/review` now writes a machine-readable verdict** to `specs/reports/<id>.verdict.json` on every
767
- run — verdict, finding counts by severity, per-surface breakdown, the normalized blocking items
768
- and a stable `fingerprint` over them. It is the only contract between the pipeline and any
769
- driver; no prose is parsed. `blocking` restates the reviewer's existing rule as a number
770
- (CRITICAL + security, deduplicated), so `blocking == 0` ⟺ `SHIP`. The fingerprint hashes
771
- *surface + file + problem* with the line number deliberately dropped — a fix that inserts lines
772
- would otherwise change it every pass and the drift detection would never fire. A red preflight
773
- writes a degraded `{"aborted":"preflight"}` verdict rather than nothing, so an abort is a
774
- diagnosis instead of a silence.
775
- - **BREAKING — `/smoke` and the `smoke` agent are removed.** The end-to-end run phase is gone:
776
- the command, the agent, its preflight wiring, its telemetry phase and its documentation. The
777
- loop is now `/brainstorm` → `/spec` → `/build` → `/review` → (`/fix` → `/review`)* → `/ship`,
778
- with `/clear` safe between each. Nothing else depended on it; a `/smoke` in an old habit will
779
- report an unknown command.
780
- - **Nothing in the pipeline runs your app any more — that part is yours.** `/build` now closes by
781
- telling you to exercise the feature by hand if it's worth it, and `/fix` says the same for
782
- runtime failures. `/review` follows suit at the SHIP verdict: it ticks only what a stage
783
- actually verified, and **leaves any DoD criterion that needs the app up open** (runtime flows,
784
- a visual check against the design) unless you say you exercised it yourself and it held.
785
- - **The preflight phase gate now gates `review` alone** (`gate.preflight.agents` defaults to
786
- `[review]`). Existing profiles that list `smoke` keep working — the hook just never sees that
787
- dispatch. `/doctor` compares against the new default, so re-run it after the update if it
788
- flags gate drift.
789
- - **Retired-phase data still renders.** Metrics files and dashboards carrying `phase: "smoke"`
790
- keep their column, the transcript collector keeps attributing past `/smoke` runs to `/smoke`
791
- instead of silently reclassifying them, and `telemetry-send.sh` still accepts the phase from a
792
- stale install. Same treatment `/cycle` got in 1.4.0.
793
- - **The cockpit now shows what a feature actually cost.** The dashboard's only metrics source
794
- was `pipeline-metrics.jsonl`, written by the model itself — so it misses any run that ended
795
- early and can never report tokens. On a real project it had captured 18 phase batches where
796
- the transcripts hold 53 runs. The new **Cost & runtime** panel reads
797
- `cohorte metrics` instead: per command, the number of runs, $ per run, $ total, tokens, wall
798
- and active time, and the median number of subagents dispatched. That last column is the one
799
- that makes a broken run obvious — a `/build` reporting 0 agents did no fan-out at all.
800
- - **Both metrics sources are kept, because they answer different questions.** `pipeline-metrics.jsonl`
801
- carries per-surface verdicts (`ok`, `REVISE:2`, `error`) that only the model knows and the
802
- transcripts never contain; the collector carries money and time, which the model cannot report
803
- and the transcripts record exactly. The two panels sit side by side and each says what it is
804
- for. Neither replaces the other.
805
- - **Fixed: discussing a command counted as running it.** An inline command mention was treated
806
- as an invocation regardless of context, so a long message *about* `/review` billed that whole
807
- conversation to `/review` — in cohorte's own repo it invented five `/cycle` runs out of a
808
- design discussion. Inline mentions are now length-gated (an instruction is short; a discussion
809
- is not); an explicit slash-command invocation is always counted.
810
-
811
- ## 1.4.0 — 2026-08-01
812
-
813
- > **Re-run `npx cohorte@latest update --global` (or `update`)** — the workflow fixes only apply
814
- > once the installed core is refreshed. Both the workflow scripts and the `profile-reader` agent
815
- > are replaced by the update.
816
-
817
- - **BREAKING — `/cycle` and `cycle.js` are removed.** The full-cycle workflow is gone: the command
818
- file, the script, its tests and its documentation. The conversational path it wrapped is
819
- unchanged and remains the way to run a feature — `/build` → `/smoke` → `/review` → `/fix` →
820
- `/ship`, with `/clear` safe between each. `review.js`, `audit.js` and `refactor.js` are
821
- untouched. Nothing else in the pipeline depended on it; a `/cycle` in an old habit will simply
822
- report an unknown command. Metrics files and dashboards that already carry `phase: "cycle"`
823
- lines keep rendering them.
824
- - **A workflow could dispatch zero agents and still report a verdict.** Phase 0's `profile-reader`
825
- (haiku) intermittently returned the profile as a JSON *string* nested under a wrapper field
826
- (`{"output": "{\"surfaces\": …}"}`) instead of at the top level. The schema was
827
- `{type: 'object', additionalProperties: true}` — no declared properties, no required keys — so
828
- the wrapper validated cleanly and every field then read as `undefined`: `surfaces` fell back to
829
- `[]`, `parallel([])` dispatched **nothing**, and because every later guard compares against
830
- `surfaces`, an empty list made them all vacuously pass. The run finished with a verdict, no code
831
- written, and no complaint — indistinguishable from a clean run with an empty diff. Fixed in three
832
- places: `profile-reader.md` now states that the profile's keys go at the top level of the
833
- structured-output tool (with the wrong shapes shown), the schema declares what it expects, and a
834
- profile with no surfaces **aborts loudly** instead of proceeding. All three workflows.
835
- - **`args` given as a JSON string became the feature id.** A caller that JSON-encoded its arguments
836
- got that whole blob used as the id — which is how a report was written to
837
- `specs/reports/{"feature": "x"}.md` — and the other options (`maxRounds`, `smoke`) silently read
838
- as `undefined` on the same run, so a run could skip smoke without saying so. `args` is now parsed
839
- back into an object (a bare slug is still valid shorthand), and a feature id that is not a slug
840
- throws with an actionable message **before** anything touches the filesystem — so no junk file
841
- can be written, and a path-shaped id is rejected.
842
- - **`/doctor` warned about a file cohorte itself had written.** `/audit` writes
843
- `specs/refactor-backlog.md` by design; the spec scanner globbed `specs/*.md` and flagged it for
844
- having no valid front-matter `status`. It fired in every project that had ever run `/audit`. Both
845
- the conversational `/doctor` and the dashboard port now exclude it.
846
- - **New: `cohorte metrics` — real cost and runtime per command.** Reconstructs tokens, USD,
847
- wall/active time and subagent counts from Claude Code's own transcripts, so it needs nothing
848
- enabled and works retroactively on runs that already happened. It is worktree-aware (a feature
849
- built across worktrees adds up instead of being dropped), attributes subagent spend back to the
850
- command that spawned it, and de-duplicates the repeated `usage` blocks a single API response
851
- writes across several transcript lines — summing those naively inflates tokens ~1.8×.
852
- `--json`, `--runs`, `--days=N`, `--since=ISO`. Prices live in `scripts/metrics/prices.json`.
853
-
854
- ## 1.3.4 — 2026-07-31
855
-
856
- > **Re-run `npx cohorte@latest update --global` (or `update`)** — the workflow and script
857
- > fixes only apply once the installed core is refreshed.
858
-
859
- - **The dashboard server now has tests.** `dashboard/server/*.js` is shipped runtime code — a
860
- hand-rolled YAML parser every `/doctor` check derives from, the metrics aggregator, the JS port
861
- of `/doctor`, the board parser, the fleet registry, and the HTTP guards — with no coverage at
862
- all. `scripts/test-dashboard.mjs` (83 assertions, in CI) pins each module, including every
863
- `/doctor` check both green and deliberately broken.
864
- - **The gate hook now has tests.** `hooks/gate.py` is the one component that can block a command,
865
- and CI only ever checked that it *parsed* — every one of its shipped regressions reached users
866
- first. `scripts/test-gate.mjs` drives its real stdin→stdout contract (42 assertions: deny/ask
867
- tiers, chained-command splitting, branch-conditional gating at the payload's cwd, the
868
- `bypassPermissions` ask⇒deny escalation, config robustness, the preflight phase gate, worktree
869
- HEAD matching) and runs in CI. No new defect was found in the gate itself — the behaviour is
870
- now pinned.
871
- - **A crashed reviewer scored as a clean surface.** `agent()` returns `null` when a subagent dies,
872
- and a dead reviewer returns zero findings — byte-identical to a surface with nothing wrong. Both
873
- `review.js` and `cycle.js` read that as `SHIP`: the review workflow answered "`/ship`" when
874
- *every* reviewer had crashed, and the cycle workflow exited **SHIP-READY**, ticked the DoD and
875
- stamped the freshness gate over code nobody had read. Unreviewed surfaces are now named in
876
- `unreviewedSurfaces` + `questions`, can never score `SHIP`, and the cycle re-reviews instead of
877
- dispatching an empty fix round. `scripts/test-workflows.mjs` (new, run in CI) pins this.
878
- - **Swept the whole "dead agent read as success" family across all four workflows** — the same
879
- root cause as the two above, found at eight more call sites by auditing every `agent()` result
880
- in `cycle.js` · `review.js` · `audit.js` · `refactor.js`. The worst: a dead **diff-staging**
881
- agent in `review.js` returned `verdict: SHIP` ("no diff — nothing to review") for a feature
882
- nobody had looked at; and a dead **close/staging** agent let both `/cycle` and the review
883
- workflow report `SHIP-READY` + a report path + "ship is a straight shot" when the report, the
884
- DoD ticks, the freshness stamp and the metrics had never been written (and `/ship`'s freshness
885
- gate skips silently when those fields are absent, so the human would have shipped on it). Also:
886
- a dead auditor made a domain look **clean** instead of unaudited; a dead backlog writer/reader
887
- and a dead item-ticker were each reported as success. Every one of these now distinguishes
888
- "died" from "succeeded with nothing to say", and `scripts/test-workflows.mjs` pins all of them.
889
- - **A dead contract agent was reported as a successful re-authoring.** Same failure shape as the
890
- crashed reviewer: when the lead-equivalent agent that re-authors spec §5 + the contract file
891
- died, `/cycle` still pushed a `contractChanges` entry and handed **every** consuming surface a
892
- CRITICAL "the contract was RE-AUTHORED — re-read it and realign" item, pointing at a file
893
- nobody had touched. It now reports the contract as UNCHANGED and ripples nothing.
894
- - **A red preflight nobody owns burned every remaining round.** When no surface path appeared in
895
- the failure tail and no implementer had survived the build, the fix round dispatched *zero*
896
- agents, the next round found the same red gates, and the loop spun to the cap doing literally
897
- nothing before reporting a stale verdict. It now stops immediately with the failure tail.
898
- - **Findings belonging to no surface were dropped silently.** A finding whose file sits outside
899
- every surface tree — reachable when the diff-staging agent names a key the profile lacks —
900
- stayed in the open set (so the loop could never exit clean) while nobody was ever dispatched to
901
- fix it. They are now named, with their `file:line`, in `questions`.
902
- - **`/cycle` build telemetry hid dead implementers**: results were mapped over the *survivors*, so
903
- two of three surfaces reported `ok,ok` and the dead one vanished from the funnel entirely.
904
- - **The review workflow sent HIGH findings straight to `/ship`.** A `SHIP` verdict can legitimately
905
- carry HIGH/MEDIUM findings (only CRITICAL and security force a fix), but the conversational
906
- `/review` routes any surviving HIGH to `/fix` — the workflow said `/ship`. It now only recommends
907
- shipping when nothing above LOW survived, and stamps the freshness gate on that same condition.
908
- - **Smoke is now opt-in in the cycle workflow** — `/cycle <id> smoke` (or `args.smoke: true`).
909
- Booting the app every round is expensive and a library project has nothing to smoke. Without it
910
- the run reports `smoke: "SKIPPED"`, leaves the runtime-flow DoD boxes unticked, and says so.
911
- - **The dashboard reset could move the shared global core.** Nothing stopped a project path of
912
- `~` — reset would then rename `~/.claude` into a backup dir and break every repo on the machine,
913
- while the UI promised the global core is never touched. It now refuses that path outright.
914
- - **The cycle workflow polluted the metrics with phantom surfaces.** It wrote `rounds` / `verdict` /
915
- `smoke` inside the metrics line's `surfaces` map, so the dashboard rendered them as three surface
916
- rows and scored `rounds: "1"` as a failing surface. Run-level facts now sit outside `surfaces`,
917
- and the dashboard knows the `cycle` phase.
918
- - **Telemetry from bundled installs reported no core version.** `telemetry-send.sh` read `VERSION`
919
- only from the *global* core; it now resolves the core that ships it. Payloads are also hardened —
920
- a quote or newline in the results string used to produce JSON the collector dropped.
921
- - **Every kanban card move added a blank line.** Ten moves of one card padded a board with fifteen
922
- of them, and every phase command moves cards. Runs of blank lines are now collapsed; a board is
923
- byte-stable across moves. Sub-notes of a duplicate card are no longer duplicated either.
924
- - **Python bytecode could reach the published package and users' `.claude`.** `.npmignore` is inert
925
- under an explicit `files` allowlist, so its `__pycache__/` rule never fired, and all three
926
- installers copied the directory verbatim. Excluded at both ends, asserted in CI.
927
- - **Every non-design surface agent rendered with a blank first TDD step.** `<SURFACE_TDD_STEP1>`
928
- sat as numbered item 1 of the TDD list but is filled only for `uses_design` surfaces, so every
929
- other agent got an empty "1." above its real first step. It is now a lead-in paragraph.
930
- - Doc/template corrections found by reading the whole core against the code: the spec template's
931
- `## 6+. Surface tasks` could collide with the `§8`/`§9` sections the pipeline references by
932
- number; `/init-pipeline` step 04 forgot `smoke.md` in its "leave the fixed agents as-is" list;
933
- the getting-started page placed `implementer.template.md` in `agents/` (it ships in `pipeline/`);
934
- the dashboard docs never documented the CSRF/DNS-rebinding guard; `dashboard/README.md` was
935
- missing `metrics.js`, `/api/metrics` and `/audit`; the two reference-only templates
936
- (`agent-handoff.md`, `review-feedback.md`) are unreferenced copies of shapes that live in the
937
- agents — `review-feedback.md` had drifted and is re-synced, and both now say so.
938
- - Smaller: the dashboard no longer stalls for 13 s per project when npm is unreachable (failed
939
- lookups are cached and de-duplicated); `--port=` rejects a non-numeric value instead of listening
940
- on a random port; a missing hashed asset 404s instead of being served `index.html`; a project
941
- card is now keyboard-activatable; long headless logs are trimmed instead of growing unbounded;
942
- `install.sh --help` exists; the preflight stamp is written once per distinct directory.
943
-
944
- ## 1.3.3 — 2026-07-30
945
-
946
- > **Re-run `npx cohorte@latest update --global` (or `update`)** — the gate fixes only apply once
947
- > the installed `hooks/gate.py` is refreshed.
948
-
949
- - **The cycle workflow could exit SHIP-READY with open findings.** A round with only HIGH/MEDIUM
950
- findings scored `SHIP`, broke the loop, ticked the DoD and stamped the freshness gate — making
951
- `/ship` a straight shot over unfixed findings, against the workflow's own "zero open findings"
952
- contract. The exit condition is now literally zero open findings + a smoke PASS.
953
- - **Dead implementers went undetected in the cycle workflow.** `agent()` returns `null` when a
954
- subagent dies, but the build fan-out wrapped every result in a truthy object before the check —
955
- so the "implementer(s) died" question never fired and build telemetry always said `ok`.
956
- - **`gate.py` gated worktree commands as if they ran on the default branch.** Branch and HEAD were
957
- resolved in `CLAUDE_PROJECT_DIR` (the main checkout, usually on `main`) instead of where the
958
- command actually runs — so in a feature worktree, every `ask_on_default_branch` pattern
959
- prompted, and the preflight HEAD-moved check compared against the wrong checkout. Git state now
960
- resolves at the hook payload's `cwd`.
961
- - **The preflight phase gate hung headless runs.** The bypassPermissions "nobody can answer an
962
- ask ⇒ deny" escalation only covered Bash patterns; a review/smoke Task dispatch with a stale
963
- stamp still emitted an unanswerable `ask`. The phase gate now escalates the same way.
964
- - **`/init-pipeline` bundled installs registered the gate with the dead `Bash`-only matcher** —
965
- the exact bug 1.3.2 fixed in the installers lived on in the template — and never dropped an
966
- existing registration, so a bundled repo later switched to global ran the gate twice per
967
- command. The template now mandates `Bash|Task` and a reconcile.
968
- - Smaller cycle-workflow fixes: smoke telemetry reports the real failure count (was always 0 —
969
- it filtered on a `kind` value that doesn't exist); a run whose last round ends on a red
970
- preflight now flags that the reported findings are from the previous round; a malformed
971
- preflight stamp says "unreadable" instead of "not found".
972
-
973
- ## 1.3.2 — 2026-07-30
974
-
975
- > **Re-run `npx cohorte@latest update --global` (or `update`).** This release repairs the gate
976
- > hook registration in place — updating is what applies it.
977
-
978
- - **1.3.0's preflight phase gate never fired on any install.** `gate.py` gates review/smoke
979
- dispatches on `tool_name == "Task"`, but all three installers registered the hook with
980
- `matcher: "Bash"` — a Task call never reached it. The `preflight` block in `gate-config.json`
981
- and `gate.preflight` in `PIPELINE.md` were both dead config. The matcher is now `Bash|Task`.
982
- - **Re-installing duplicated the hook, every time.** The "already registered?" test was
983
- `command.endswith("gate.py")`, which is false for the Windows form `py "C:\…\gate.py"` because
984
- of the trailing quote — so `install.sh` and `bin/cli.js` appended another copy on each run, and
985
- `gate.py` ran once per copy on every Bash call (four copies seen in the wild). Registration is
986
- now a **reconcile**: it drops every existing `gate.py` entry and writes exactly one. Idempotent,
987
- it collapses the duplicates you already have, and it upgrades the stale matcher — an
988
- append-if-absent would have found the stale entry and skipped, pinning the bug forever.
989
- Unrelated hooks and every other settings key are untouched.
990
- - **`npx cohorte update` never touched the hook at all**, so neither fix above could have reached
991
- you through the command you actually run to get fixes — only a full re-install rewrote it.
992
- `install.sh` and `install.ps1` always registered on update; this port had drifted (the same
993
- class of drift as 1.2.4 and 1.2.6). It now registers on both paths.
994
- - CI installs **twice** before asserting the hook, via a new `scripts/assert-gate-hook.mjs`:
995
- exactly one registration, matcher covering both Bash and Task. A single install could never
996
- surface the duplication — which is precisely why CI stayed green while it shipped.
997
-
998
- ## 1.3.1 — 2026-07-30
999
-
1000
- - **`/cycle <feature_id> [max_rounds]`** — a launcher command for the full dev-cycle workflow,
1001
- so you don't have to phrase the request in prose. It resolves `workflows/cycle.js`
1002
- (bundled or global), checks the runtime is available (missing ⇒ it hands you the
1003
- conversational `/build` → `/smoke` → `/review` path instead), sanity-checks the spec is
1004
- frozen, launches the workflow in the background, then relays the verdict: outcome,
1005
- contract re-authorings to eyeball, the `questions` array verbatim, and the next step
1006
- (`/ship` on SHIP-READY, rerun `/cycle` or `/fix` otherwise). Kanban card moves included.
1007
-
1008
- ## 1.3.0 — 2026-07-30
1009
-
1010
- **Token economy — immediate wins, no workflow needed:**
1011
-
1012
- - **Deterministic pre-flight before `/review` and `/smoke`.** A shipped script
1013
- (`pipeline/scripts/preflight.sh`) runs typecheck + lint + tests first; red ⇒ the command
1014
- aborts with the raw last-40 lines and **spawns zero agents** — a reviewer no longer burns
1015
- its whole run rediscovering what `tsc` printed for free. Green runs stamp
1016
- `.claude/preflight.ok`, and `gate.py` enforces it as a **phase gate**: a review/smoke
1017
- dispatch with a missing/stale stamp gets a confirm (`gate.preflight` in the profile).
1018
- - **Quiet commands.** New profile fields (`test_quiet_cmd`/`lint_quiet_cmd` per surface,
1019
- `commands.test_quiet`/`lint_quiet` repo-wide) hold the bridled forms agents actually run
1020
- (`--reporter=dot`, `--quiet`, failures-only); absent ⇒ `<cmd> 2>&1 | tail -40`.
1021
- `/init-pipeline` now asks for them instead of storing a bare `pnpm test`;
1022
- `/update-pipeline` tops up older profiles.
1023
- - **`/review` computes the diff once.** One `git diff --stat`, then full patches staged to
1024
- disk only for the touched surfaces — reviewers read the artifact instead of each
1025
- re-running git.
1026
- - **Conventions baked into rendered agents.** The implementer template gets a
1027
- `<SURFACE_CONVENTIONS>` slice rendered at init; at runtime agents read only the profile's
1028
- machine block. Edit conventions in `PIPELINE.md`, then `/update-pipeline` re-renders.
1029
- - **Capped reports.** Review reports: max 20 findings, one line each, zero code excerpts;
1030
- smoke returns: max 10 ❌ lines. Dispatch prompts now keep every volatile slot (feature id,
1031
- paths, file lists) at the END so repeats hit the prompt-cache prefix.
1032
- - `gate.py` also escalates every `ask` to a hard deny in unattended runs
1033
- (`bypassPermissions`) — nobody is there to answer a prompt.
1034
-
1035
- **Workflows (opt-in — conversational commands stay the default and the fallback):**
1036
-
1037
- - Four deterministic multi-agent scripts for the Claude Code Workflow runtime
1038
- (≥ 2.1.154, workflows enabled): **`workflows/cycle.js` — the full dev cycle on a frozen
1039
- spec** (contract → parallel build → smoke ∥ review(+cross-check) → fix, looping until
1040
- zero findings + PASS; contract changes handled in-loop by a lead-equivalent agent, human
1041
- decisions returned in a `questions` array at the end; a clean exit ticks the DoD and
1042
- stamps the freshness gate so `/ship` follows directly), `workflows/review.js` (preflight
1043
- gate → one reviewer per touched surface → adversarial cross-check of CRITICAL/security
1044
- findings → verdict only), `workflows/audit.js` (one auditor per domain, concurrent,
1045
- prioritized backlog), `workflows/refactor.js` (big domains only: shared first, parallel
1046
- implementers, per-domain verify + one retry). Mechanical phases route to haiku.
1047
- - New `profile-reader` agent (haiku) — phase 0 of every workflow: returns the
1048
- `PIPELINE.md` machine block as JSON, since workflow scripts have no filesystem access.
1049
- - `/doctor` check 8 reports the workflow prerequisites and which path a session will take;
1050
- the generated `settings.json` allow-list now covers what workflow agents need (quiet
1051
- commands, shipped scripts, `git rev-parse`, retrieval MCP tools) so runs don't stall on
1052
- prompts nobody is watching.
1053
- - Installers (npx CLI, install.sh, install.ps1) ship `core/workflows/` + `preflight.sh` +
1054
- the `profile-reader` agent in both global and bundled modes; CI dry-runs assert it.
1055
- - Dashboard: new headless **Audit** action (`claude -p "/audit"` — starts without a prompt,
1056
- no resume if the session dies) and the workflows state in the project drill-down.
1057
-
1058
- ## 1.2.6 — 2026-07-30
1059
-
1060
- - **`npx cohorte install` never installed the `smoke` agent.** It copied only `review.md` and
1061
- `release.md`, so `/smoke` was there but the agent it dispatches was not — the run failed
1062
- saying `/smoke` is not installed. The shell installers always copied it; only the npm port
1063
- drifted. It now copies every non-template agent in `core/agents/`, so nothing to keep in sync.
1064
- Fix an affected install by re-running `npx cohorte install --global` (or `install --repo`).
1065
-
1066
- ## 1.2.5 — 2026-07-29
1067
-
1068
- - **`.claude/pipeline.json`'s `core_version` never updated on global installs.** The installer
1069
- bumps it in bundled mode, but a global core is shared — it cannot know which repos point at
1070
- it, so nothing bumped the field and it drifted forever. Repos running a current core were
1071
- still claiming `1.0.0`. `/update-pipeline` now syncs the pointer in both modes.
1072
- - `/doctor` no longer reports that drift as a broken install: a global-mode pointer lagging the
1073
- VERSION file is ⚠️ with the one-command fix, not ❌. The core was never the problem.
1074
-
1075
- ## 1.2.4 — 2026-07-29
1076
-
1077
- > **If you installed with `npx cohorte`, this is the release that makes 1.2.3 actually
1078
- > reach you.** Re-run `npx cohorte@latest update --global` (or `update` for a bundled core).
1079
-
1080
- - **`npx cohorte install/update` shipped a core missing two scripts.** `bin/cli.js` — the
1081
- port of `install.sh` that `npx` actually runs — copied only `scripts/*.template`, never
1082
- `kanban-move.sh` or `telemetry-send.sh`. Since every caller chains them with `|| true`,
1083
- the result was silent on every npx-installed machine: no kanban card moves, no telemetry
1084
- pings, no error anywhere. The shell installers named both files explicitly and this port
1085
- drifted from them. It now copies by a rule that needs no list to keep in sync.
1086
- - The same port never copied `CHANGELOG.md` into the core either, so `/doctor` and
1087
- `/update-pipeline`'s "What's new" had nothing to read on npx installs. Fixed.
1088
- - CI now dry-runs `bin/cli.js` into a scratch dir and asserts the same postconditions as
1089
- the `install.sh` dry-run. 1.2.3's guard only grepped the two shell installers — it would
1090
- have passed this bug, because the port copies by rule rather than by name.
1091
-
1092
- ## 1.2.3 — 2026-07-29
1093
-
1094
- - **Telemetry now covers the whole funnel.** Only `/build` was actually pinging; `/smoke`,
1095
- `/review` and `/fix` wrote their metrics line but never sent one, so consenting installs
1096
- reported a quarter of their pipeline. Those three are fixed, and `/brainstorm`, `/spec`
1097
- (on a landed freeze) and `/ship` join them — the seven stages of `idea → PR` now report,
1098
- so it's finally possible to see *where* features stall. Setup and maintenance commands
1099
- (`/doctor`, `/init-pipeline`, `/update-pipeline`, `/audit`, `/refactor`, `/align-ds`)
1100
- deliberately never ping: the collected set stays inside what the consent text describes.
1101
- Same data categories as before, same purpose — nothing new about you is sent, so your
1102
- existing consent stands and nothing re-asks. The full table is in SCHEMA.md §Telemetry.
1103
- - `telemetry-send.sh` now allowlists the phase name client-side — a typo in a command file
1104
- used to sail through and land a phantom phase in the dataset.
1105
- - `/fix` never defined a wall-clock start, so the `seconds` in its metrics line was
1106
- undefined. It now notes the epoch like `/build` and `/review` do.
1107
- - **`/doctor` catches a half-copied core.** New check: `pipeline/scripts/` must hold every
1108
- shipped script, and `VERSION` must not be newer than its siblings. Callers chain these
1109
- scripts with `|| true`, so a missing one was invisible — no kanban move, no telemetry
1110
- ping, no error. If you saw either go quiet, this is why: re-run the installer.
1111
- - CI now fails if an installer forgets to copy a `scripts/*.sh`, and the dry-run install
1112
- asserts the scripts land executable — the root cause above, caught before release
1113
- rather than on someone's machine.
1114
- - The npm tarball no longer ships `scripts/new-feature.sh` + `scripts/remove-feature.sh`
1115
- — cohorte's *own* rendered isolation scripts, with this repo's ports and paths baked
1116
- in. They claimed in their header to be excluded but never were (an explicit `files`
1117
- whitelist wins over `.npmignore`). Only the `*.sh.template` files ship, as intended.
1118
- - Fixed `validate-core.mjs` crashing on Windows (`C:\C:\…` path), so the guard above
1119
- actually runs locally too.
1120
-
1121
- ## 1.2.2 — 2026-07-29
1122
-
1123
- - The reference collector moved to its own (private) deployment repo; the public repo keeps
1124
- the collector API contract in SCHEMA.md §Telemetry. No behavior change for users.
1125
-
1126
- ## 1.2.1 — 2026-07-29
1127
-
1128
- - Telemetry collector URL shipped as the config-template default
1129
- (`https://telemetry.cohorte.thebidouille.fr/v1/events`) — consenting installs start
1130
- reporting once the collector is live. Still strictly opt-in; nothing changes for anyone
1131
- who declined (or never answered) the consent question.
1132
-
1133
- ## 1.2.0 — 2026-07-29
1134
-
1135
- > **Opt-in anonymous telemetry, GDPR-first.** Nothing is sent unless you explicitly say yes.
1136
-
1137
- - `/init-pipeline` (and `/update-pipeline` on existing installs) ask ONE consent question, once per
1138
- machine, default **No** — both answers are recorded in `~/.claude/cohorte.config.yaml` §`telemetry`
1139
- so you're never re-asked.
1140
- - When enabled, each pipeline phase fires a ~200-byte ping (fire-and-forget, 2s timeout, never
1141
- blocks): core version, OS, phase, duration, per-surface result counts, and a **hash** of the
1142
- feature id. Never sent: repo names, paths, code, spec content, IPs.
1143
- - Withdraw anytime (`telemetry.enabled: false`); erase your history anytime (`/doctor` prints your
1144
- `install_id`; `DELETE /v1/install/<id>` on the collector drops it). Full spec: SCHEMA.md
1145
- §Telemetry; privacy summary in the README.
1146
- - Ships a zero-dependency reference collector (`telemetry/collector.mjs` — NDJSON storage, strict
1147
- field allowlist, erasure endpoint, stores no IPs) to self-host.
1148
- - `/doctor` reports telemetry consent state and flags incoherent configs (enabled without a
1149
- recorded consent).
1150
- - Note: the shipped default `endpoint` is empty — telemetry stays dormant even for consenting
1151
- installs until a collector URL ships in the config template.
1152
-
1153
- ## 1.1.1 — 2026-07-29
1154
-
1155
- - **Fix: pipeline metrics survive worktree teardown.** With `isolation.enabled` the lead session
1156
- runs inside the feature worktree, so metrics lines landed in the worktree's `.claude/` and were
1157
- deleted with it — defeating their purpose (cross-feature evidence for surface splits, dashboard
1158
- history). All phases now append to the **main checkout's** `.claude/pipeline-metrics.jsonl`,
1159
- resolved from anywhere via `git rev-parse --git-common-dir`; `/doctor` flags a stray metrics file
1160
- inside a worktree as a stale-core sign.
1161
-
1162
- ## 1.1.0 — 2026-07-29
1163
-
1164
- > **The token-economy release.** A full audit of the core (40 verified fixes) cuts the pipeline's
1165
- > consumption by an estimated 40–60% per feature, and the pipeline no longer inherits your session's
1166
- > model for orchestration. Plus: pipeline metrics in the dashboard, CI on the core, and a documented
1167
- > parallel-features workflow.
1168
-
1169
- - **Byte-stable dispatches.** One dispatch template for builds AND fix loops; variable parts
1170
- (design links, open Remediation items inlined verbatim) sit at the end so repeats hit the prompt
1171
- cache. The lead never pastes a diff — agents compute their own, scoped to their tree. On fix
1172
- loops, implementers no longer re-read the spec at all.
1173
- - **Reviewers read hunks, not whole files.** `/review` stages each surface's diff to
1174
- `specs/reports/<id>.<key>.diff`; tiny re-reviews skip the dispatch entirely (fast path); the
1175
- merged report is staged to disk with only a verdict summary printed; LOW-only findings defer to
1176
- the refactor backlog instead of forcing a fix cycle.
1177
- - **`/smoke` is now an agent.** A new pinned `smoke` agent runs infra/curl/UI checks so logs,
1178
- response bodies, and screenshots never enter (and re-bill in) your session's history.
1179
- - **Model pins everywhere.** The `review` agent and the 10 mechanical commands
1180
- (build/review/fix/smoke/ship/audit/refactor/doctor/align-ds/update-pipeline) are pinned
1181
- `model: sonnet` — orchestration runs on Sonnet even if your session runs Opus/Fable. `/doctor`
1182
- checks agent AND command pins; the profile template's frontend example no longer suggests
1183
- `inherit`.
1184
- - **Leaner outputs.** Handoff + review-report formats are inlined in the agent bodies (no template
1185
- probe), templates de-boilerplated, the design brief is authored once to `specs/design/<id>.md`,
1186
- metrics collapsed to one JSONL line per phase, and every command's closing now *recommends*
1187
- `/clear` (all state is on disk by design).
1188
- - **Pipeline metrics in the dashboard.** New per-project panel: wall-clock per phase, fix rounds,
1189
- and per-surface results from `.claude/pipeline-metrics.jsonl` — see which phase/surface dominates
1190
- before tuning anything.
1191
- - **`kanban-move.sh`.** Card moves (move/create/dedupe/`--pr`) now run as a script outside the
1192
- agent's context; installed to `<core>/pipeline/scripts/`, with the manual grep-based op as
1193
- fallback.
1194
- - **Spec size budget.** `/spec` targets ≤~300 lines and proposes a feature split beyond that —
1195
- every spec line is paid `surfaces × dispatches` times.
1196
- - **Parallel features documented.** README: one session per feature, worktree isolation as the
1197
- safety mechanism, ship-then-rebase rule; `/doctor` prints the live slot table when ≥2 features
1198
- run in parallel.
1199
- - **CI on the core.** `scripts/validate-core.mjs` + GitHub Actions: frontmatter/pin invariants,
1200
- render placeholders, cross-references, installer coverage (would have caught the smoke-agent
1201
- install gap this release also fixes), plus an end-to-end install dry-run.
1202
-
1203
- ## 1.0.0 — 2026-07-28
1204
-
1205
- > **Renamed `thebidouille-agents` → `cohorte`** and cut the first stable release. The npm package,
1206
- > the CLI (`npx cohorte …`), the repo, and the user config file are all renamed. The pre-rename
1207
- > `~/.claude/thebidouille.config.yaml` and `~/.claude/thebidouille-dashboard.json` are still read as a
1208
- > fallback, so existing installs keep working — `/update-pipeline` migrates them forward on next run.
1209
-
1210
- - **Repo moved to the `TheBidouilleAgency` org** (`github.com/TheBidouilleAgency/cohorte`), with a
1211
- proper logo/brand kit under `assets/` and a dashboard favicon set.
1212
-
1213
- - **The research + questionnaire capability was removed from the core.** `/research`,
1214
- `/questionnaire`, their agents, templates and step files are extracted to a separate private repo
1215
- and will return later as an installable Cohorte **plugin**. `update` scrubs the now-orphaned files
1216
- from existing installs. The global config keeps only the shared Obsidian vault + the kanban mirror;
1217
- the `research:`/`questionnaire:` config keys are gone.
1218
-
1219
- - **`/ship` now reliably moves the kanban card to Shipped and writes the PR number.** The
1220
- move-to-Shipped was a parenthetical in the command header, easy to skip — so shipped features could
1221
- leave their card stuck in an earlier column. It is now an explicit, verify-after step (§4): move
1222
- card `#<id>` → `shipped` **and append `PR #<num>`** (from the PR URL), then re-read the board to
1223
- confirm. The bare `#<num>` is what the dashboard renders as a clickable PR link. SCHEMA.md §Kanban
1224
- documents the shipped-card format. (`/ship` also moves the card → `ship` on confirm, in §1.)
1225
-
1226
- - **Branch-aware gate — git + docker run freely on feature branches, gated only on the default
1227
- branch.** The `gate` block gains two keys: `ask_on_default_branch` (patterns confirmed *only* when
1228
- the checked-out branch is `default_branch`) and `default_branch` (default `main`). `gate.py`
1229
- resolves the current branch at run time (`git rev-parse`); an unknown branch (no repo / detached)
1230
- is treated conservatively as gated. The default profile moves git (commit/push/merge/rebase/reset)
1231
- and `docker compose` into this tier, so agents move fast on feature branches while `main` stays
1232
- protected; DB commands (`migration:run`, `db:`, `psql`) remain always-`ask`, destructive migrations
1233
- always-`deny`. Existing gate-configs without the new keys keep working unchanged. Re-run
1234
- `/update-pipeline` to regenerate `gate-config.json` with the new tier.
1235
-
1236
- - **New `dashboard` subcommand — a local web cockpit for the pipeline.** Run
1237
- `npx cohorte dashboard` to open a browser view of pipeline state: a **Fleet**
1238
- overview (global core version vs npm latest + every tracked project's freshness and health
1239
- at a glance), a per-project drill-down that renders `/doctor` as a live checklist, the
1240
- **Surfaces ↔ agents** map from `PIPELINE.md`, and a **Specs board** (kanban by
1241
- `draft·frozen·in-review·shipped`). Install/update actions run the CLI and stream their output
1242
- live. Add projects by path — the set is remembered in `~/.claude/cohorte-dashboard.json`.
1243
- The runtime is dependency-free (node's built-in `http` serves a prebuilt React app); the
1244
- `/doctor` checks are reimplemented in JS so they run without a Claude session. Point it at any
1245
- pipeline-ised repo, or at nothing (it seeds the launch directory). A **folder picker** browses
1246
- the filesystem to add projects (dirs with a `PIPELINE.md` are flagged), and a **Reset pipeline**
1247
- action wipes a project's entire pipeline footprint (`.claude/`, `PIPELINE.md`, optionally
1248
- `specs/`) — backed up first to `.claude.bak-<ts>/`, the shared `~/.claude` core untouched — so a
1249
- project riddled with old-version relics can be brought back to a clean, pipeline-managed state
1250
- (then `/init-pipeline` regenerates the profile). **Init-pipeline / Update-pipeline** buttons run
1251
- those Claude Code commands headless (`claude -p … --dangerously-skip-permissions`) in the project
1252
- and stream the output. The server **binds `127.0.0.1` by default** (its actions execute code);
1253
- `--host=ADDR` exposes it with a printed security warning, `--open` launches the browser.
1254
- Projects with a linked **Obsidian Kanban board** (config `kanban.boards`) get it rendered inline —
1255
- columns + cards read straight from the vault markdown (local, no token; Notion is not a kanban
1256
- source in this pipeline, only /research archival). PR references become clickable links, enriched
1257
- with **live PR status** (open/merged/closed/draft) + date via the user's `gh` CLI (cached 60s), and
1258
- the **Shipped** column is sorted by ship date. Cards missing an explicit `#<num>` have their PR
1259
- **inferred from the branch** (`…/<feature_id>`), so historical boards light up too.
1260
-
1261
- ## 0.1.27 — 2026-07-28
1262
-
1263
- - **README gains a Prerequisites section.** Spells out what a new machine actually needs: Node ≥ 18 + npm
1264
- (the only hard requirement, for the `npx` installer) versus `uv` + the Serena CLI (optional, the default
1265
- retrieval provider — installed separately, independent of the `npx` core install, order irrelevant, and
1266
- the pipeline still runs without it by falling back to Grep/Read). Also documents the cloned-repo case
1267
- (Serena registration travels in the committed `.mcp.json`; just install the CLI + restart + `/doctor`).
1268
- The mechanics were already in `SCHEMA.md` §Code retrieval, but not in the human-facing onboarding doc.
1269
-
1270
- ## 0.1.26 — 2026-07-28
1271
-
1272
- - **The design step now references designs by full link, not a stored project id + bare filename.** A
1273
- `design_files` entry is a self-contained `https://claude.ai/design/p/<projectId>?file=<file>` link that
1274
- carries its own project (`/p/<projectId>`) and page (`?file=`); agents extract both and read it via
1275
- `DesignSync get_file(<projectId>, <file>)`. No stored `design_project` id means a design-system rebuild
1276
- (which mints a new project id) no longer breaks every spec — you just paste the new links. `design_project`
1277
- becomes an optional legacy fallback (default `none`) for old bare-filename specs. Updated across `/build`
1278
- (design gate + dispatch), `/smoke`, `/spec` + the spec template, `PIPELINE.md` (§design + conventions),
1279
- `SCHEMA.md`, and `/doctor`. Crucially, the surface-agent render step now specifies the link-based
1280
- `<SURFACE_DESIGN_INPUT>`/`<SURFACE_TDD_STEP1>` — so `/update-pipeline` re-renders design agents to resolve
1281
- from the link instead of the stale `get_file(design_project, <file>)`. Existing specs keep their bare
1282
- filenames until you replace them with links.
1283
-
1284
- ## 0.1.25 — 2026-07-27
1285
-
1286
- - **`research-agent` defaults to `sonnet`** instead of silently inheriting the session model (Opus). Its
1287
- work — MAP / ANALYSE / SYNTHESISE of pre-extracted text — is extraction-and-summary that Sonnet handles
1288
- well at a fraction of the cost, and `/cost` showed it was one of the two heaviest subagents. The fixed
1289
- agents were never tiered like the surfaces; this closes the biggest gap. If cross-cutting synthesis ever
1290
- needs more, the `/research` SYNTHESISE dispatch can override the model for just that pass.
1291
- - **README documents the `/clear`-safe loop** as the top token lever — since all pipeline state lives on
1292
- disk, `/clear`-ing between stages sheds the accumulated main-thread context (long >150k sessions are
1293
- expensive even cached), with the safe-to-clear boundary shown for the whole `/spec → … → /ship` loop.
1294
-
1295
- ## 0.1.24 — 2026-07-27
1296
-
1297
- - **The dev loop is now `/clear`-safe between every stage.** All pipeline state already lives on disk
1298
- (spec, contract, diff, Remediation checkboxes, freshness stamp), so you can `/clear` between commands
1299
- to shed the accumulated main-thread context and cut token cost — each command reloads everything from
1300
- disk. Every command now marks its handoff as safe to `/clear` before the next step.
1301
- - **`/review` and `/smoke` stage their report to `specs/reports/<id>.md`** (a gitignored buffer in its own
1302
- subfolder, like `specs/design/`) — the one context-coupling that a `/clear` used to break. `/fix` and
1303
- `/spec` Mode B read the report back from disk when the context was cleared. `/init-pipeline` gitignores
1304
- the buffer; `/doctor` reports it. The non-recursive `specs/*.md` glob skips the subfolder, so it never
1305
- shows up as a phantom kanban card or spec.
1306
-
1307
- ## 0.1.23 — 2026-07-26
1308
-
1309
- - **Cheaper dev loop by default — implementers now default to `sonnet`, not the Opus lead.** A surface
1310
- agent mostly applies a frozen contract, which Sonnet handles well at a fraction of the cost;
1311
- `/init-pipeline` and reconcile now default `surfaces[].model` to `sonnet`, keeping `haiku` for purely
1312
- mechanical scaffolding and `inherit` only for surfaces with real design decisions. The fixed `release`
1313
- and `questionnaire-validator` agents drop to `haiku`, `questionnaire-writer` to `sonnet`. Existing
1314
- projects pick this up on the next `/update-pipeline` (agents re-render; a `model` you set by hand is kept).
1315
- - **Stateless agents read a *slice* of `PIPELINE.md`, not the whole file.** The implementer and reviewer
1316
- now load the machine block + only the `### Shared` and their own `### Surface:` convention stanza
1317
- (+ §Testing), never the other surfaces' prose — less context re-read on every parallel dispatch.
1318
- - **Leaner fix loops.** On a `/fix` re-dispatch, a surface agent works from the self-contained open
1319
- Remediation items + the diff and reads only the files those findings name — no longer re-reading the
1320
- whole (growing) spec or re-exploring its tree.
1321
- - **Freshness gate at `/ship`.** `/review` now fingerprints the reviewed source (`reviewed_base` +
1322
- `reviewed_digest` in the spec front-matter) at a SHIP verdict, and `/ship` re-checks it — refusing to
1323
- ship if any source or contract file changed after the review, so a verdict can't go stale unnoticed.
1324
- Specs are excluded (DoD ticks + the ship status flip don't trip it); a spec predating the gate skips it.
1325
- - **Big commands lazy-load their steps (progressive disclosure).** `/init-pipeline`, `/research` and
1326
- `/questionnaire` are now thin routers (a bootstrap block + a steps table) that read each step from
1327
- `templates/steps/<command>/NN-*.md` as they reach it, instead of one monolithic body — the branchy
1328
- commands (esp. `/research`) no longer pull an unused branch into context. Pure re-partition, verified
1329
- token-for-token identical to the old bodies. No installer change (steps ride the existing `templates/` copy).
1330
- - **Machine-checkable postconditions on the two silent-failure gates** — `/spec` freeze asserts
1331
- `status: frozen` actually landed; `/build` asserts the contract file exists before dispatching agents.
1332
- - **`/review` lets git group the diff by surface** (`git diff --name-only -- <path>` + an `:(exclude)`
1333
- remainder) instead of the lead reasoning it out file by file — deterministic and cheaper.
1334
- - **`/fix` collapses fully-resolved Remediation rounds** to a one-line summary, so the spec every agent
1335
- re-reads stops growing unbounded across fix loops (rounds with any open item stay expanded).
1336
- - **New SCHEMA § "Measuring cost"** — documents `/cost` (built-in per-subagent + per-command usage share)
1337
- and the OTEL `settings.json` env block (`claude_code.token.usage` / `cost.usage`) for exact numbers.
1338
-
1339
- ## 0.1.22 — 2026-07-26
1340
-
1341
- - **`/spec` exports a standalone design brief** — for a UI feature, freezing the spec now also writes
1342
- §8 (the "spec return") to its own `specs/design/<id>.md`, in addition to printing the copy-paste
1343
- block. One `.md` you can open, share, or drop straight into the design tool instead of scrolling back
1344
- through the chat — regenerated on every freeze so it never drifts from the spec. Lives in the
1345
- `specs/design/` subfolder on purpose, so the non-recursive `specs/*.md` glob (kanban backfill,
1346
- `/doctor`) never mistakes it for a spec. Backend-only features are unaffected.
1347
-
1348
- ## 0.1.21 — 2026-07-24
1349
-
1350
- - **Reliable local-PDF reading for `/research`** — subagent nodes often lack a PDF renderer (no
1351
- poppler), which made research-agents silently fall back to a web copy of the document — fine for a
1352
- public PDF, a silent fabrication risk for a private one. `/research` now **extracts the PDF to
1353
- per-page text ONCE up front** (pure-Python `pypdf` in a throwaway venv — no system deps) and agents
1354
- read that text, never the binary PDF. A local read that fails now returns a loud `===READ-FAILED===`
1355
- instead of reconstructing from the web; the orchestrator re-extracts or surfaces it. Adds a
1356
- scanned-PDF guard (no text layer ⇒ stop, needs OCR).
1357
-
1358
- ## 0.1.20 — 2026-07-24
1359
-
1360
- - **`/fix` now checks off resolved Remediation items** — the lead flips `- [ ]` → `- [x]` (with a
1361
- short "fixed" note) for every item the surface agents report addressed in their handoff, and skips
1362
- already-`[x]` items when scoping the re-dispatch. Fixes two long-standing quirks: a spec whose
1363
- Remediation looked permanently open even after fixes landed, and a later `/fix` re-sending
1364
- already-fixed items from earlier rounds to the agents.
1365
- - **`/review` now ticks the §9 DoD at a SHIP verdict** — a SHIP verdict is the pipeline's statement
1366
- that the feature is done, so the lead checks off each Acceptance-criteria item its verifying stage
1367
- actually covered (conformance/copy = review, tests/lint/types = build, mobile-first/runtime = smoke),
1368
- leaving open any whose stage didn't run. `/ship` gains a matching gate: it lists any still-open DoD
1369
- item and asks before shipping (it never ticks — that's `/review`'s job).
1370
-
1371
- ## 0.1.19 — 2026-07-24
1372
-
1373
- - **Research decoupled from the questionnaire** — `/research` now dispatches a dedicated, standalone
1374
- **`research-agent`** (an autonomous research assistant that extracts everything important in the
1375
- source) instead of the old bi-mode `questionnaire-researcher`. The report no longer carries any
1376
- "future questionnaire" framing: the domain-brief `goal` is a research objective, and the brief
1377
- template is renamed `research-brief.md`. The blueprint step moves to its own **`questionnaire-architect`**
1378
- agent, dispatched by `/questionnaire`. New Notion archive databases are titled « Recherche ». Update
1379
- scrubs the retired `questionnaire-researcher` agent and old template automatically.
1380
- - **Multi-pass research for large sources** — `/research` now maps a big PDF into a reading plan, runs
1381
- one deep `research-agent` pass **per segment in parallel**, synthesises the cross-cutting sections,
1382
- and assembles a single report. Report length scales with the source (no fixed word-count cap), so a
1383
- dense thesis or state-of-the-art gets exhaustive coverage instead of being compressed into one pass.
1384
- Small sources and URLs still take the single-pass path.
1385
-
1386
- ## 0.1.18 — 2026-07-22
1387
-
1388
- - **Consolidated global config** — the research/questionnaire settings move from
1389
- `~/.claude/questionnaire.config.yaml` into one `~/.claude/cohorte.config.yaml` with
1390
- `obsidian` / `research` / `questionnaire` / `kanban` sections and a shared `obsidian.vault_path`.
1391
- The old file is still read as a fallback; `/update-pipeline` migrates it for you. The `npx`
1392
- installer now offers a quick interactive setup on a TTY.
1393
- - **Obsidian kanban mirror** — an optional per-project board mirrors the pipeline
1394
- (`/brainstorm`…`/ship`): each stage moves the feature's card across columns
1395
- (Ideas → Brainstorm → Spec → Ready to build → Building → Review → Fix → Ship → Shipped).
1396
- `/brainstorm` can pick an idea straight from the *Ideas* column; `/init-pipeline` creates + links
1397
- a board (keyed by the project's `PIPELINE.md` name); `/update-pipeline` links/repairs it and
1398
- **backfills existing `specs/` onto the board**, syncing each card to its spec's status. Enable it
1399
- via `/init-pipeline` (new project) or `/update-pipeline` (existing) — no hand-editing.
1400
-
1401
- ## 0.1.17 — 2026-07-22
1402
-
1403
- - **Serena dashboard no longer auto-opens** — the per-repo Serena launcher `/init-pipeline` wires now
1404
- passes `--open-web-dashboard False`. The dashboard stays available (`http://localhost:24282/dashboard/`)
1405
- but no longer pops a browser tab on every server start. The flag overrides each machine's
1406
- `serena_config.yml`, so behaviour is uniform across the team; `/update-pipeline`'s health check appends
1407
- the flag to launcher entries that predate it.
1408
-
1409
- ## 0.1.16 — 2026-07-22
1410
-
1411
- - **Obsidian store: research and questionnaires split** — research notes land in
1412
- `obsidian_research_folder` (default `Recherches/`, with `_sources/`), and a derived questionnaire
1413
- is now a **separate note** in `obsidian_questionnaire_folder` (default `Questionnaires/`),
1414
- wikilinked both ways with the research note. Statut lifecycle: the research note stays
1415
- `Recherche`; the questionnaire note carries `À relire` / `Bloqué` / `Approuvé`. (Replaces
1416
- 0.1.15's single `obsidian_folder` key.) Notion store unchanged — one page per run.
1417
-
1418
- ## 0.1.15 — 2026-07-22
1419
-
1420
- - **Obsidian store for research runs** — the research/questionnaire capability gains a `store:`
1421
- switch in `~/.claude/questionnaire.config.yaml`: `notion` (default, unchanged) or `obsidian` —
1422
- each run becomes a markdown note in `<vault>/<obsidian_folder>/` with frontmatter properties
1423
- (`run_id`, `sujet`, `cadre`, `statut`, `date`), source PDFs copied to `_sources/` for provenance.
1424
- No MCP needed; the vault path is asked once on first `/research`, then saved. Old Notion runs stay
1425
- readable — pass their URL to `/questionnaire`.
1426
-
1427
- ## 0.1.14 — 2026-07-22
1428
-
1429
- - **`/fix`** — scoped fix loop: appends a REVIEW REPORT (or `/smoke` failures) to the spec's
1430
- `## Remediation` and re-dispatches ONLY the surfaces with findings, instead of the full
1431
- paste-into-`/spec` + full `/build` round-trip.
1432
- - **`/smoke`** — end-to-end verification between `/build` and `/review`: infra up in the feature
1433
- worktree, migrations, real contract endpoints via curl (incl. RBAC denials), spec §8 UI flows
1434
- mobile-first, optional screenshot diff against the Claude Design pages.
1435
- - **`/doctor`** — installation diagnostic: core/pointer versions, agents↔surfaces orphans, hooks &
1436
- gate config, retrieval health, design wiring, stale worktree slots — each failure with its exact fix.
1437
- - **Dispatch metrics** — `/build`, `/review`, `/fix`, `/smoke` append per-agent JSONL evidence to
1438
- `.claude/pipeline-metrics.jsonl` (gitignored); SCHEMA §Specialization now points at it.
1439
- - **`/ship`** — watches the PR's CI checks (`gh pr checks --watch`) and, after the merge is
1440
- confirmed, proposes `scripts/remove-feature.sh` (worktree + slot teardown, db kept by default).
1441
- - **`/init-pipeline`** — generates `.github/workflows/pipeline-ci.yml` from the profile's commands
1442
- (with go-ahead) and gitignores the metrics sink.
1443
- - **CHANGELOG** — this file; shipped with the core, shown by `/update-pipeline` after an update.
1444
-
1445
- ## 0.1.13 — 2026-07-22
1446
-
1447
- - **`/review` is parallel** — one review agent per touched surface in a single dispatch (wall-clock =
1448
- slowest surface, not the sum); the lead merges the reports, worst verdict wins.
1449
- - **Review agent reads less** — `mcp__serena` in its toolset (harmlessly absent when a project has no
1450
- retrieval provider) and a diff-hunks-first reading rule instead of whole-file reads.
1451
-
1452
- ## 0.1.12 — 2026-07-22
1453
-
1454
- - **Per-feature design projects** — spec `design_files` now accepts full Claude Design links, each
1455
- carrying its own project id (extracted at `/build`'s design gate); the profile's `design_project`
1456
- becomes an optional fallback. Design each feature in a fresh project and just paste the link.
1457
-
1458
- ## 0.1.11 and earlier
1459
-
1460
- Pre-changelog releases: serena wiring made PATH-proof and health-checked (0.1.9–0.1.11), OIDC npm
1461
- trusted publishing (since 0.1.4). See `git log` for details.