cohorte 2.10.0 → 3.0.0-dev.0

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