cohorte 1.5.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +169 -3
- package/README.md +65 -57
- package/bin/cli.js +31 -15
- package/core/agents/implementer.template.md +3 -3
- package/core/agents/release.md +1 -1
- package/core/agents/review.md +25 -2
- package/core/commands/{audit.md → cohorte-audit.md} +11 -3
- package/core/commands/{brainstorm.md → cohorte-brainstorm.md} +9 -3
- package/core/commands/{build.md → cohorte-build.md} +95 -10
- package/core/commands/{doctor.md → cohorte-doctor.md} +22 -9
- package/core/commands/{fix.md → cohorte-fix.md} +20 -13
- package/core/commands/{init-pipeline.md → cohorte-init-pipeline.md} +1 -1
- package/core/commands/cohorte-loop.md +110 -0
- package/core/commands/{refactor.md → cohorte-refactor.md} +3 -3
- package/core/commands/{review.md → cohorte-review.md} +70 -20
- package/core/commands/{ship.md → cohorte-ship.md} +5 -5
- package/core/commands/{spec.md → cohorte-spec.md} +32 -12
- package/core/commands/{update-pipeline.md → cohorte-update-pipeline.md} +16 -6
- package/core/hooks/gate.py +101 -6
- package/core/templates/brainstorm-return.md +4 -4
- package/core/templates/decisions.template.md +42 -0
- package/core/templates/design-brief.md +1 -1
- package/core/templates/spec.template.md +8 -6
- package/core/templates/steps/init-pipeline/01-detect-stack.md +1 -1
- package/core/templates/steps/init-pipeline/02-interview-gaps.md +6 -6
- package/core/templates/steps/init-pipeline/03-draft-profile.md +1 -1
- package/core/templates/steps/init-pipeline/04-write-render.md +16 -12
- package/core/templates/steps/init-pipeline/05-report.md +5 -5
- package/core/workflows/audit.js +6 -6
- package/core/workflows/refactor.js +14 -14
- package/core/workflows/review.js +62 -20
- package/dashboard/README.md +2 -2
- package/dashboard/dist/assets/{index-dkO8UUVl.css → index-BZ_LQlEj.css} +1 -1
- package/dashboard/dist/assets/{index-8owBnqyv.js → index-P1I1JGtj.js} +11 -11
- package/dashboard/dist/index.html +2 -2
- package/dashboard/server/doctor.js +75 -18
- package/dashboard/server/index.js +5 -5
- package/dashboard/server/metrics.js +1 -1
- package/install.ps1 +31 -14
- package/install.sh +31 -14
- package/package.json +2 -2
- package/profile/PIPELINE.template.md +17 -16
- package/profile/SCHEMA.md +199 -48
- package/profile/cohorte.config.template.yaml +8 -8
- package/scripts/loop-detach.sh +153 -0
- package/scripts/loop.sh +202 -25
- package/scripts/metrics/collect.mjs +17 -8
- package/scripts/new-feature.sh.template +3 -3
- package/scripts/preflight.sh +40 -4
- package/scripts/remove-feature.sh.template +2 -2
- package/scripts/test-dashboard.mjs +34 -7
- package/scripts/test-gate.mjs +58 -0
- package/scripts/test-loop.mjs +269 -0
- package/scripts/test-metrics.mjs +23 -11
- package/scripts/test-workflows.mjs +33 -5
- package/scripts/validate-core.mjs +46 -9
- package/core/commands/loop.md +0 -61
- /package/core/commands/{align-ds.md → cohorte-align-ds.md} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,7 +1,172 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
Entries are shown by `/update-pipeline` ("What's new") after a core refresh. Keep them
|
|
4
|
-
user-facing, most recent first. One `## <version> — <YYYY-MM-DD>` section per release.
|
|
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.0.0 — 2026-08-03
|
|
11
|
+
|
|
12
|
+
> **Breaking: every command is renamed.** `/build` → `/cohorte-build`, `/review` →
|
|
13
|
+
> `/cohorte-review`, and so on for all 13. The driver, `/loop` → `/drive` in 1.6.0, is now
|
|
14
|
+
> **`/cohorte-loop`**. Re-run `npx cohorte@latest update --global` (or `update`): the update
|
|
15
|
+
> **deletes** the 13 unprefixed command files from your install rather than leaving them as
|
|
16
|
+
> decoys. Nothing inside your repo needs editing — `/build` in a spec or PIPELINE.md is prose,
|
|
17
|
+
> not a call site. Muscle memory is the only migration cost.
|
|
18
|
+
|
|
19
|
+
- **Every command now carries a `cohorte-` prefix, ending command shadowing for good.** A command
|
|
20
|
+
whose name collides with a Claude Code built-in is not overridden, it is **shadowed**: the
|
|
21
|
+
built-in answers the slash, our file is never read, and the session confidently reports on a run
|
|
22
|
+
that never happened. `/loop` did exactly that and went unnoticed until a user found the driver had
|
|
23
|
+
never started; `/doctor` was sitting on a watchlist waiting to do the same. 1.6.0 renamed one
|
|
24
|
+
name; this replaces the whole approach. `validate-core` now enforces the prefix structurally
|
|
25
|
+
instead of maintaining a blocklist that could only ever forbid the collisions we already knew
|
|
26
|
+
about. Telemetry **phase** names (`build`, `review`, `fix`, …) stay unprefixed — they are a wire
|
|
27
|
+
contract with the collector, and the retired bare command names are kept in the metrics
|
|
28
|
+
collector's retired list so months of existing transcripts stay attributed instead of silently
|
|
29
|
+
reclassifying to `(chat)`.
|
|
30
|
+
|
|
31
|
+
- **`/cohorte-loop` can now run for hours.** It previously ran the driver as one foreground Bash
|
|
32
|
+
call, which cannot work: a single call is capped at **600 s** and a build is 25–40 min, so it was
|
|
33
|
+
killed mid-`/cohorte-build`. Backgrounding it was worse — a backgrounded Bash call is **not
|
|
34
|
+
detached**, so the driver stayed in the calling session's process group and every Claude Code
|
|
35
|
+
restart, crash or laptop sleep took `loop.sh` and its `claude -p` children down with it, mid-write.
|
|
36
|
+
Observed on a real run: four teardowns in 45 minutes, each aborting both surface implementers and
|
|
37
|
+
leaving a half-built tree that read as `dead`. New `loop-detach.sh` puts the driver in its own
|
|
38
|
+
`screen` session so it outlives the launching process entirely, and `/cohorte-loop` polls a small
|
|
39
|
+
status file in ~9-minute waits. The driver's exit code — which the report table is keyed on —
|
|
40
|
+
survives as `__EXIT__ <code>` in that file.
|
|
41
|
+
|
|
42
|
+
- **`loop.sh` holds the machine awake for its whole run.** It re-execs itself under
|
|
43
|
+
`caffeinate -ims` on macOS, `systemd-inhibit` on Linux, because system sleep aborts every
|
|
44
|
+
in-flight `claude -p` request and the abort is byte-identical to "the agent returned nothing" —
|
|
45
|
+
the `dead` family the driver exists to catch. The inhibitor is **probed before the `exec`**, since
|
|
46
|
+
`exec` replaces the shell: one that exists but is refused (`systemd-inhibit` answers `Failed to
|
|
47
|
+
inhibit: Access denied` in a container, in CI, or in any seatless session) would otherwise make its
|
|
48
|
+
own failure the driver's exit code and the run would never start — GitHub's Linux runners turned
|
|
49
|
+
all 24 loop tests red exactly that way. Absent or refused both fall through to a no-op; an unheld
|
|
50
|
+
power assertion is a degraded run, not a failed one, and `test-loop.mjs` now pins both directions.
|
|
51
|
+
**This cannot prevent lid-close sleep** — no userspace assertion can on any platform; keep the
|
|
52
|
+
lid open or use clamshell mode.
|
|
53
|
+
|
|
54
|
+
- **Platform tiers, stated rather than assumed.** Detaching uses `screen` (macOS + Linux), else
|
|
55
|
+
`setsid` (Linux) — both escape the caller's process group, which is what actually matters. Git
|
|
56
|
+
Bash on Windows has neither, so it falls back to `nohup`, which ignores `SIGHUP` but does **not**
|
|
57
|
+
survive a teardown; `loop-detach.sh` prints that warning rather than degrading silently, and
|
|
58
|
+
points at running `loop.sh` from your own terminal instead. See the platform table in
|
|
59
|
+
`docs/reference/scripts.md`.
|
|
60
|
+
|
|
61
|
+
- **Fixed — the preflight stamp is keyed on the code, not on HEAD, and is never versioned.** The
|
|
62
|
+
stamp recorded the HEAD sha, which is the wrong key in both directions: the reviewed tree is
|
|
63
|
+
normally *dirty*, so committing the very code the preflight verified made the gate ask on a clean
|
|
64
|
+
tree, while an implementer editing files between preflight and dispatch invalidated nothing. Worse,
|
|
65
|
+
`.claude/preflight.ok` was never gitignored — once a release agent staged `.claude/`, the stamp
|
|
66
|
+
went into git describing the tree *before* its own commit, so it could never match again: every
|
|
67
|
+
review dispatch in that repo asked "HEAD moved" forever, and every new clone or worktree inherited
|
|
68
|
+
a green it never earned. The stamp is now `<epoch> <sha> <tree digest>`, where the digest is the
|
|
69
|
+
git tree id of the working tree (`.claude` and `specs` excluded, so the pipeline's own report,
|
|
70
|
+
metrics and DoD writes don't invalidate it), computed in a throwaway index that never touches
|
|
71
|
+
yours. Pre-2.0.0 two-field stamps still fall back to the HEAD comparison. `/cohorte-doctor` check 3
|
|
72
|
+
now fails hard on a tracked stamp, `/cohorte-update-pipeline` untracks it and fixes `.gitignore`
|
|
73
|
+
(§Reconcile step 8), and `test-gate.mjs` pins all of it — including "commit the verified code ⇒
|
|
74
|
+
still green" and "one edit ⇒ red".
|
|
75
|
+
|
|
76
|
+
- **`/cohorte-review` and `/cohorte-fix` now spell out the metrics path instead of delegating it.**
|
|
77
|
+
Both said "append a line to `pipeline-metrics.jsonl`" and pointed at `/cohorte-build` §4 for where
|
|
78
|
+
that file lives — a lead running from a feature worktree resolves the bare name against its own
|
|
79
|
+
cwd and strands the batch in a sink that dies at teardown. Both now carry the resolved
|
|
80
|
+
`$(dirname "$(git rev-parse --git-common-dir)")` form inline.
|
|
81
|
+
|
|
82
|
+
- **Fixed — the dashboard's command allowlist had drifted from its own error message.** The
|
|
83
|
+
server accepted the bare `/audit`/`/init-pipeline`/`/update-pipeline` while the UI sent (and the
|
|
84
|
+
error text advertised) the prefixed names, so the run button would have 400'd on the only
|
|
85
|
+
commands that exist. The test suite checked *rejection* only, which is why it passed; it now pins
|
|
86
|
+
both directions.
|
|
87
|
+
|
|
88
|
+
## 1.6.0 — 2026-08-01
|
|
89
|
+
|
|
90
|
+
> **Re-run `npx cohorte@latest update --global` (or `update`)** to pick up the readiness gate, the
|
|
91
|
+
> deferred-findings route, the resumable driver and the decision journal — the update *deletes* the
|
|
92
|
+
> shadowed `/loop` command and the long-dead `/cycle` from your install, it does not just stop
|
|
93
|
+
> shipping them. Existing specs keep working: the new front-matter fields are written on demand, and a
|
|
94
|
+
> spec without them simply isn't resumable yet. **`/loop <id>` is now `/drive <id>`.**
|
|
95
|
+
|
|
96
|
+
- **New — the readiness gate between `/spec` and `/build`.** `/build` §1.6 now scores the frozen spec
|
|
97
|
+
on **implementability** before authoring the contract and before dispatching anything: contract
|
|
98
|
+
shapes complete · every area owned by a surface · named dependencies actually exist · no ambiguity a
|
|
99
|
+
surface would have to guess at · design links present. The verdict goes to
|
|
100
|
+
`specs/reports/<id>.readiness.json` (`READY` · `RESERVATIONS` · `NOT-READY` + `gaps[]`).
|
|
101
|
+
**`NOT-READY` stops the build with zero agents spawned** — a spec that can't be built doesn't get
|
|
102
|
+
cheaper by being built on N surfaces in parallel — and sends you to `/spec`. `RESERVATIONS` never
|
|
103
|
+
blocks: each gap is inlined into the affected surface's dispatch as an assumption the implementer
|
|
104
|
+
applies *and* flags in its handoff. It costs **no extra agent**: the lead already holds the spec,
|
|
105
|
+
the profile and the reconciled surface list.
|
|
106
|
+
- **New — deferred findings: `/review` stops throwing away what isn't blocking.** The review agent
|
|
107
|
+
now returns a separate `## Deferred` section (max 10) for what is real but **out of this feature's
|
|
108
|
+
scope** — pre-existing code the diff never touched, adjacent debt the spec never claims to fix —
|
|
109
|
+
each line carrying its own out-of-scope reason. Deferred items count in no severity row, move no
|
|
110
|
+
verdict, are never cross-checked, and on **every** verdict get routed into
|
|
111
|
+
`specs/refactor-backlog.md` under the owning surface's `## <domain>` heading, tagged
|
|
112
|
+
`deferred:<id>`. So `/review` feeds `/refactor` for free instead of dropping everything
|
|
113
|
+
non-blocking on the floor. Never into `## Remediation`, which is what `/fix` re-dispatches. Not
|
|
114
|
+
deferrable, ever: anything the diff touched, any spec violation, any security issue on a path this
|
|
115
|
+
feature adds or calls. `/audit` now **carries open `deferred:` items over** when it rewrites the
|
|
116
|
+
backlog. The verdict JSON gains `deferred: <n>` (informational, outside `blocking`).
|
|
117
|
+
- **BREAKING — `/loop` is renamed `/drive`, because Claude Code shadowed it.** Claude Code ships its
|
|
118
|
+
own built-in `/loop` (run a prompt on a recurring interval), which won the name: typing
|
|
119
|
+
`/loop <id>` started the *interval runner* with the feature id as its prompt, so cohorte's driver
|
|
120
|
+
never ran — and the session, having never seen `loop.md`, reported a loop that did not exist. Same
|
|
121
|
+
command, same flags, same script (`pipeline/scripts/loop.sh` keeps its name — nothing about your
|
|
122
|
+
install paths changes): type **`/drive <id>`**. The update scrubs the old `commands/loop.md`, so a
|
|
123
|
+
stale shadowed copy can't linger.
|
|
124
|
+
- **`/drive` is resumable — the spec's status is the state machine.** The lifecycle is now
|
|
125
|
+
`draft → frozen → in-progress → in-review → shipped` plus `blocked`. Before every phase the driver
|
|
126
|
+
stamps `status: in-progress` + `loop_pass` + `loop_phase` into the spec's front-matter — plain
|
|
127
|
+
`awk`, a temp file and `mv`, **zero tokens** — and on exit a terminal `in-review` (clean) or
|
|
128
|
+
`blocked`. **`/drive <id> --resume`** then continues at the pass it reached instead of re-paying the
|
|
129
|
+
ones already made, whether the session died, the ceiling hit, or the fix stopped converging.
|
|
130
|
+
`--max` stays a ceiling on the *total* passes. New **exit 4** (`not implementable`) relays the
|
|
131
|
+
readiness gate's `NOT-READY`: the one loop outcome more passes cannot fix. The dashboard's specs
|
|
132
|
+
board gains In-progress and Blocked columns and shows `↻ pass 3 · /review` on the card; `/doctor`
|
|
133
|
+
names any spec left mid-loop.
|
|
134
|
+
- **Fixed — a dead subagent no longer reads as a clean one on the conversational path.** The
|
|
135
|
+
"a dead agent is never a clean result" doctrine existed since 1.3.4 — but only inside the
|
|
136
|
+
**workflows**. `/build`, `/review` and `/fix` had nothing: a subagent that dies (rate limit,
|
|
137
|
+
transport error, exhausted context) returns *nothing*, and nothing was indistinguishable from
|
|
138
|
+
"finished, nothing to report". Concretely, a dead **reviewer** produced zero findings ⇒
|
|
139
|
+
`blocking: 0` ⇒ verdict `SHIP` ⇒ `/drive` exit 0 ⇒ the human sent to `/ship` — a clean bill of
|
|
140
|
+
health on code no agent ever read. Now every fan-out phase does a **roll call** before integrating:
|
|
141
|
+
a silent surface is retried **once** alone (byte-identical prompt, so recovery costs one agent, not
|
|
142
|
+
a rebuild), then `/build` marks it `dead` and verifies the tree with that surface's own quiet
|
|
143
|
+
commands instead of speaking for the agent, `/review` lists it in the verdict's new `unreviewed[]`
|
|
144
|
+
and **refuses to score `SHIP`**, and `/fix` leaves every one of its items `- [ ]` (a dead agent
|
|
145
|
+
never ticks a box). `/build` also writes `specs/reports/<id>.build.json` with `dead[]`, and
|
|
146
|
+
`loop.sh` aborts on either signal with **exit 2** *before* reading `blocking` — because a dead
|
|
147
|
+
reviewer makes `blocking == 0` a statement about unread code. `unreviewed` is deliberately kept
|
|
148
|
+
out of `blocking`: faking a count there would corrupt the one field the driver contract rests on.
|
|
149
|
+
The metrics line is now written even when a surface died (`"<key>":"dead"`) — an incomplete batch
|
|
150
|
+
is exactly the batch worth recording.
|
|
151
|
+
- **Fixed — `/cycle` and its workflow were removed in 1.4.0 but no installer ever scrubbed them.**
|
|
152
|
+
Every install since has kept `commands/cycle.md` + `workflows/cycle.js` on disk, so a dead command
|
|
153
|
+
stayed listed and invokable — dispatching a workflow whose phases 1.5.0 then deleted. All three
|
|
154
|
+
installers now remove them (as they already did for `/smoke`), and CI **plants the orphans before
|
|
155
|
+
re-installing** instead of asserting their absence on a fresh scratch home, which is exactly the
|
|
156
|
+
blind spot that let this survive four releases.
|
|
157
|
+
- **Reconcile now tops up `specs/_template.md`.** It was seeded once at install and never refreshed,
|
|
158
|
+
so every repo kept the front-matter its core shipped with. `/update-pipeline` adds the missing
|
|
159
|
+
front-matter fields (never the body — the section list is yours).
|
|
160
|
+
- **New — `specs/_decisions.md`, the transverse decision journal.** `PIPELINE.md` is a *stack* profile;
|
|
161
|
+
it says nothing about what the project has **decided**, so every `/spec` re-discovered or
|
|
162
|
+
contradicted the same choices. The journal is deliberately tiny: **append-only, one line per
|
|
163
|
+
decision** (`- <date> · <area> · <decision> — because <reason> · <feature_id>`), reversal by a
|
|
164
|
+
superseding line rather than an edit. Written by `/spec` at freeze (typically 0–3 lines; zero is
|
|
165
|
+
normal) and by `/build` when it adds or splits a surface. Read by the **deciding** stages only —
|
|
166
|
+
`/brainstorm`, `/spec`, `/audit`. **Implementers and reviewers never load it:** they have the frozen
|
|
167
|
+
contract, and shipping them the rationale would cost `surfaces × dispatches` tokens per feature for
|
|
168
|
+
a fact they can't act on. That exclusion is what keeps it cheap enough to be worth having. The `_`
|
|
169
|
+
prefix means `/doctor`, the dashboard scanner and the kanban backfill already skip it.
|
|
5
170
|
|
|
6
171
|
## 1.5.0 — 2026-08-01
|
|
7
172
|
|
|
@@ -9,7 +174,8 @@ user-facing, most recent first. One `## <version> — <YYYY-MM-DD>` section per
|
|
|
9
174
|
> `/smoke` removal — the update *deletes* the command and its agent from your install, it does not
|
|
10
175
|
> just stop shipping them. The new dashboard panel comes with `npx cohorte dashboard`.
|
|
11
176
|
|
|
12
|
-
- **New — `/loop <id>`: the review ⇄ fix cycle, run for you.** `/
|
|
177
|
+
- **New — `/loop <id>`: the review ⇄ fix cycle, run for you.** _(renamed `/drive` in 1.6.0 — see
|
|
178
|
+
there.)_ `/build` → `/review` → `/fix` →
|
|
13
179
|
`/review` … until a review reports **zero blocking findings** (a CRITICAL or a security issue —
|
|
14
180
|
a LOW nit never costs a pass), or the pass ceiling (`--max=N`, default 5), or two consecutive
|
|
15
181
|
reviews returning the *same* blocking findings, which means the fix is treading water and more
|
package/README.md
CHANGED
|
@@ -14,13 +14,13 @@
|
|
|
14
14
|
</div>
|
|
15
15
|
|
|
16
16
|
A **portable, stack-agnostic multi-agent pipeline** for Claude Code. Install it once globally,
|
|
17
|
-
then one command per project (`/init-pipeline`) adapts it to that project's stack.
|
|
17
|
+
then one command per project (`/cohorte-init-pipeline`) adapts it to that project's stack.
|
|
18
18
|
|
|
19
19
|
- **The dev pipeline** — a human **lead** drives feature work through gated commands, dispatching
|
|
20
20
|
**stateless agents** that only communicate through a frozen contract:
|
|
21
21
|
|
|
22
22
|
```
|
|
23
|
-
/brainstorm → /spec → (design) → /build <id> → /review → (/fix) → /ship
|
|
23
|
+
/cohorte-brainstorm → /cohorte-spec → (design) → /cohorte-build <id> → /cohorte-review → (/cohorte-fix) → /cohorte-ship
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
## How it works — three layers
|
|
@@ -28,7 +28,7 @@ then one command per project (`/init-pipeline`) adapts it to that project's stac
|
|
|
28
28
|
| Layer | What it holds | Lives in | Scope |
|
|
29
29
|
| --- | --- | --- | --- |
|
|
30
30
|
| **Generic core** | the workflow doctrine: commands, fixed agents, templates, hooks — zero project facts | `~/.claude` (global) — or vendored in a repo's `.claude/` (bundled) | identical everywhere, installed once |
|
|
31
|
-
| **Project profile** | stack, surfaces, commands, conventions, gates | `PIPELINE.md` + rendered surface agents + `gate-config.json`, **committed in each repo** | generated per project by `/init-pipeline` |
|
|
31
|
+
| **Project profile** | stack, surfaces, commands, conventions, gates | `PIPELINE.md` + rendered surface agents + `gate-config.json`, **committed in each repo** | generated per project by `/cohorte-init-pipeline` |
|
|
32
32
|
| **User config** | kanban board links + shared Obsidian vault path | `~/.claude/cohorte.config.yaml` | personal, project-independent |
|
|
33
33
|
|
|
34
34
|
The core never hardcodes stack facts. Two mechanisms keep it generic:
|
|
@@ -37,7 +37,7 @@ The core never hardcodes stack facts. Two mechanisms keep it generic:
|
|
|
37
37
|
`~/.claude/cohorte.config.yaml` (kanban board links + shared vault) at run time — an agent's
|
|
38
38
|
_first action_ is to read its config.
|
|
39
39
|
2. **Render-at-init** — things that must be in agent frontmatter (name, `tools:`, surface ownership)
|
|
40
|
-
are rendered per **surface** by `/init-pipeline` from `implementer.template.md`.
|
|
40
|
+
are rendered per **surface** by `/cohorte-init-pipeline` from `implementer.template.md`.
|
|
41
41
|
|
|
42
42
|
## Prerequisites
|
|
43
43
|
|
|
@@ -48,10 +48,10 @@ Only one hard requirement — the rest is optional and independent:
|
|
|
48
48
|
provider. Install it separately (`uv tool install -p 3.13 serena-agent && uv tool update-shell`); the
|
|
49
49
|
`npx` install neither needs nor touches it, so the order between the two is irrelevant. Without Serena
|
|
50
50
|
the pipeline still runs — agents just fall back to Grep/Read. Having it installed **before**
|
|
51
|
-
`/init-pipeline` lets init wire it in one pass (otherwise `/update-pipeline` wires it later).
|
|
51
|
+
`/cohorte-init-pipeline` lets init wire it in one pass (otherwise `/cohorte-update-pipeline` wires it later).
|
|
52
52
|
- **On a new machine cloning a repo that's already pipeline-ised:** the Serena registration is committed
|
|
53
53
|
in the repo's `.mcp.json` (project scope, portable) — you don't re-wire. Just install the Serena CLI,
|
|
54
|
-
restart the session, and run `/doctor` to confirm it connects.
|
|
54
|
+
restart the session, and run `/cohorte-doctor` to confirm it connects.
|
|
55
55
|
|
|
56
56
|
## Install
|
|
57
57
|
|
|
@@ -66,11 +66,11 @@ own `gate-config.json`:
|
|
|
66
66
|
npx cohorte install --global
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
-
The per-project part is NOT the core — it's the **profile** `/init-pipeline` generates and you
|
|
69
|
+
The per-project part is NOT the core — it's the **profile** `/cohorte-init-pipeline` generates and you
|
|
70
70
|
commit: `PIPELINE.md`, the rendered surface agents, `gate-config.json`, `settings.json`, `specs/`.
|
|
71
71
|
**That's what makes team work possible in global mode**: everything project-specific travels with the
|
|
72
72
|
repo; each teammate just runs the same global one-liner once, guided by the committed
|
|
73
|
-
`.claude/pipeline.json` pointer (core version + install command) that `/init-pipeline` writes.
|
|
73
|
+
`.claude/pipeline.json` pointer (core version + install command) that `/cohorte-init-pipeline` writes.
|
|
74
74
|
|
|
75
75
|
<details>
|
|
76
76
|
<summary><strong>Alternative: per-project (bundled)</strong> — vendor the core into the repo itself.</summary>
|
|
@@ -109,13 +109,13 @@ published semver. Both land in `.claude/pipeline/VERSION` and the `pipeline.json
|
|
|
109
109
|
</details>
|
|
110
110
|
|
|
111
111
|
> **After installing (or updating): restart Claude Code / start a new session.** Slash commands and
|
|
112
|
-
> agents are scanned at session start — in an already-open session the new `/init-pipeline`,
|
|
113
|
-
> `/build`, etc. won't appear until you reload. This is the #1 "the install didn't work" trap.
|
|
112
|
+
> agents are scanned at session start — in an already-open session the new `/cohorte-init-pipeline`,
|
|
113
|
+
> `/cohorte-build`, etc. won't appear until you reload. This is the #1 "the install didn't work" trap.
|
|
114
114
|
|
|
115
115
|
Then, in Claude Code (from any repo, once the core is installed either way):
|
|
116
116
|
|
|
117
117
|
```
|
|
118
|
-
/init-pipeline
|
|
118
|
+
/cohorte-init-pipeline
|
|
119
119
|
```
|
|
120
120
|
|
|
121
121
|
It **detects** your stack (package manager, workspaces, frameworks, test runners, linters, git remote,
|
|
@@ -131,9 +131,10 @@ design system), **interviews** you for the gaps, and **generates**:
|
|
|
131
131
|
symbols instead of grep-and-reading whole files; `graphify` or `none` also available via the
|
|
132
132
|
profile's `retrieval.provider`)
|
|
133
133
|
- `scripts/new-feature.sh` + `remove-feature.sh` — parallel worktree isolation (if you enable it)
|
|
134
|
-
- `specs/_template.md`
|
|
134
|
+
- `specs/_template.md` (and, on first decision, `specs/_decisions.md` — the project's one-line-per-decision
|
|
135
|
+
journal, read by `/cohorte-brainstorm`, `/cohorte-spec` and `/cohorte-audit` so features stop re-litigating settled ground)
|
|
135
136
|
|
|
136
|
-
Sanity-check `PIPELINE.md`, commit it, and run `/brainstorm`.
|
|
137
|
+
Sanity-check `PIPELINE.md`, commit it, and run `/cohorte-brainstorm`.
|
|
137
138
|
|
|
138
139
|
## Update
|
|
139
140
|
|
|
@@ -148,12 +149,12 @@ The installer refreshes the generic core (commands, hook, templates) **without**
|
|
|
148
149
|
`PIPELINE.md`, rendered agents, `gate-config.json`, `settings.json`, or your filled
|
|
149
150
|
`~/.claude/cohorte.config.yaml`.
|
|
150
151
|
|
|
151
|
-
From inside Claude Code, prefer **`/update-pipeline`**: it runs the right update invocation for your
|
|
152
|
+
From inside Claude Code, prefer **`/cohorte-update-pipeline`**: it runs the right update invocation for your
|
|
152
153
|
install scope, reports `old → new` — and then **reconciles the repo's generated files to the new
|
|
153
154
|
core**: new profile fields are added at their defaults (you're only asked for genuinely new
|
|
154
155
|
decisions), surface agents are re-rendered, settings are patched additively, new capabilities get
|
|
155
|
-
wired. **`/init-pipeline` is one-time per project** — after init, `/update-pipeline` is the only
|
|
156
|
-
maintenance command you ever run (`/build` auto-grows surfaces as specs need them).
|
|
156
|
+
wired. **`/cohorte-init-pipeline` is one-time per project** — after init, `/cohorte-update-pipeline` is the only
|
|
157
|
+
maintenance command you ever run (`/cohorte-build` auto-grows surfaces as specs need them).
|
|
157
158
|
|
|
158
159
|
## Dashboard — a local web cockpit
|
|
159
160
|
|
|
@@ -166,7 +167,7 @@ npx cohorte dashboard --port=4400 --open # custom port, open the browser
|
|
|
166
167
|
```
|
|
167
168
|
|
|
168
169
|
**Bound to `127.0.0.1` by default** — the dashboard's actions execute code (install/update/reset,
|
|
169
|
-
and `/init-pipeline`·`/update-pipeline`·`/audit` via headless Claude), so it must stay on loopback. Each user
|
|
170
|
+
and `/cohorte-init-pipeline`·`/cohorte-update-pipeline`·`/cohorte-audit` via headless Claude), so it must stay on loopback. Each user
|
|
170
171
|
runs their own agent and drives only their own machine. `--host=0.0.0.0` exposes it to the network
|
|
171
172
|
(it prints a security warning) — only on a trusted network, since anyone who reaches the port can run
|
|
172
173
|
those actions.
|
|
@@ -174,7 +175,7 @@ those actions.
|
|
|
174
175
|
- **Fleet overview** — the global core version vs npm latest, plus every tracked project's freshness
|
|
175
176
|
and health at a glance. Add a project by absolute path or with the **folder picker** (Browse…); the
|
|
176
177
|
set is remembered in `~/.claude/cohorte-dashboard.json`.
|
|
177
|
-
- **Per-project drill-down** — Freshness (installed core vs npm), `/doctor` rendered as a live
|
|
178
|
+
- **Per-project drill-down** — Freshness (installed core vs npm), `/cohorte-doctor` rendered as a live
|
|
178
179
|
✅/⚠️/❌ checklist (each failure with its fix), the **Surfaces ↔ agents** map from `PIPELINE.md`,
|
|
179
180
|
and one board: a **Kanban** if the project has a linked Obsidian board (columns + cards from the
|
|
180
181
|
vault, with clickable PR links + live open/merged/closed status and a ship-date-sorted Shipped
|
|
@@ -190,7 +191,7 @@ those actions.
|
|
|
190
191
|
**workflows** state (scripts + profile-reader installed, which path a session will take).
|
|
191
192
|
|
|
192
193
|
Runtime is **dependency-free** — node's built-in `http` server serves a prebuilt React app (the app
|
|
193
|
-
source lives in `dashboard/app/`, built to `dashboard/dist/` at publish time). The `/doctor` checks
|
|
194
|
+
source lives in `dashboard/app/`, built to `dashboard/dist/` at publish time). The `/cohorte-doctor` checks
|
|
194
195
|
are reimplemented in JS, so the dashboard needs no Claude session to compute state. See
|
|
195
196
|
[`dashboard/README.md`](dashboard/README.md) for the architecture.
|
|
196
197
|
|
|
@@ -213,29 +214,29 @@ it in `.claude/pipeline/VERSION` and bundled repos in their committed `pipeline.
|
|
|
213
214
|
|
|
214
215
|
| Command | Role |
|
|
215
216
|
| -------------------- | ------------------------------------------------------------------------------------- |
|
|
216
|
-
| `/init-pipeline` | Detect stack → interview → generate the profile + agents. Run once per project. |
|
|
217
|
-
| `/brainstorm` | Interactive persona panel that pressure-tests a feature idea. |
|
|
218
|
-
| `/spec` | Freeze the feature spec + contract into `specs/<id>.md` (UI features also get a standalone design brief at `specs/design/<id>.md`). Also applies review returns. |
|
|
219
|
-
| `/build <id>` |
|
|
220
|
-
| `/review <id>` | Read-only review agents (one per touched surface, parallel) audit the diff vs the spec. |
|
|
221
|
-
| `/fix <id>` | Apply a review report: remediation into the spec, re-dispatch only the surfaces with findings. |
|
|
222
|
-
| `/loop <id>` | Autonomous `/build → /review → /fix → /review …` until no blocking finding is left (see below). |
|
|
223
|
-
| `/ship <id>` | Release agent commits, pushes, opens the PR; watches CI; proposes worktree teardown. |
|
|
224
|
-
| `/audit [path]` | Prioritized refactor backlog for existing code. |
|
|
225
|
-
| `/refactor <domain>` | Apply the backlog for one surface, TDD-first. |
|
|
226
|
-
| `/align-ds` | Align the code UI kit to the design system (no-op if none configured). |
|
|
227
|
-
| `/update-pipeline` | Refresh the installed core (global or bundled) to the latest published version. |
|
|
228
|
-
| `/doctor` | Diagnose the installation (core, agents↔surfaces, hooks, gate, retrieval, worktrees). |
|
|
217
|
+
| `/cohorte-init-pipeline` | Detect stack → interview → generate the profile + agents. Run once per project. |
|
|
218
|
+
| `/cohorte-brainstorm` | Interactive persona panel that pressure-tests a feature idea. |
|
|
219
|
+
| `/cohorte-spec` | Freeze the feature spec + contract into `specs/<id>.md` (UI features also get a standalone design brief at `specs/design/<id>.md`). Also applies review returns. |
|
|
220
|
+
| `/cohorte-build <id>` | Readiness gate on the frozen spec, then the lead authors the contract and dispatches one implementer per surface in parallel. |
|
|
221
|
+
| `/cohorte-review <id>` | Read-only review agents (one per touched surface, parallel) audit the diff vs the spec; out-of-scope findings go to the refactor backlog. |
|
|
222
|
+
| `/cohorte-fix <id>` | Apply a review report: remediation into the spec, re-dispatch only the surfaces with findings. |
|
|
223
|
+
| `/cohorte-loop <id>` | Autonomous `/cohorte-build → /cohorte-review → /cohorte-fix → /cohorte-review …` until no blocking finding is left (see below). |
|
|
224
|
+
| `/cohorte-ship <id>` | Release agent commits, pushes, opens the PR; watches CI; proposes worktree teardown. |
|
|
225
|
+
| `/cohorte-audit [path]` | Prioritized refactor backlog for existing code. |
|
|
226
|
+
| `/cohorte-refactor <domain>` | Apply the backlog for one surface, TDD-first. |
|
|
227
|
+
| `/cohorte-align-ds` | Align the code UI kit to the design system (no-op if none configured). |
|
|
228
|
+
| `/cohorte-update-pipeline` | Refresh the installed core (global or bundled) to the latest published version. |
|
|
229
|
+
| `/cohorte-doctor` | Diagnose the installation (core, agents↔surfaces, hooks, gate, retrieval, worktrees). |
|
|
229
230
|
|
|
230
231
|
### Run the loop cheaply — `/clear` between stages
|
|
231
232
|
|
|
232
233
|
Every command reloads all the state it needs **from disk** — the frozen spec, the contract, the diff, the
|
|
233
|
-
Remediation checkboxes, the freshness stamp, and the last `/review` report (staged to a gitignored
|
|
234
|
+
Remediation checkboxes, the freshness stamp, and the last `/cohorte-review` report (staged to a gitignored
|
|
234
235
|
`specs/reports/<id>.md`). Nothing essential lives in the conversation. So the loop is **`/clear`-safe at
|
|
235
236
|
every boundary**:
|
|
236
237
|
|
|
237
238
|
```
|
|
238
|
-
/spec → /clear → /build → /clear → /review → /clear → /fix → /clear → /review → /ship
|
|
239
|
+
/cohorte-spec → /clear → /cohorte-build → /clear → /cohorte-review → /clear → /cohorte-fix → /clear → /cohorte-review → /cohorte-ship
|
|
239
240
|
```
|
|
240
241
|
|
|
241
242
|
`/clear`-ing between stages sheds the accumulated main-thread context, which is the single biggest token
|
|
@@ -243,19 +244,26 @@ lever: long sessions (>150k) are expensive even when cached. Each command tells
|
|
|
243
244
|
safe to clear. If you'd rather stay in one session, `/compact` mid-task does the lighter version. (Claude
|
|
244
245
|
can't fire `/clear` itself — it's a client-side command; the pipeline just makes it always safe to type.)
|
|
245
246
|
|
|
246
|
-
### Let it run itself — `/loop`
|
|
247
|
+
### Let it run itself — `/cohorte-loop`
|
|
247
248
|
|
|
248
249
|
```
|
|
249
|
-
/loop feat-x # /build, then /review ⇄ /fix until clean (max 5 passes)
|
|
250
|
-
/loop feat-x --no-build # already built — just re-run the /review ⇄ /fix loop
|
|
251
|
-
/loop feat-x --max=8
|
|
250
|
+
/cohorte-loop feat-x # /cohorte-build, then /cohorte-review ⇄ /cohorte-fix until clean (max 5 passes)
|
|
251
|
+
/cohorte-loop feat-x --no-build # already built — just re-run the /cohorte-review ⇄ /cohorte-fix loop
|
|
252
|
+
/cohorte-loop feat-x --max=8
|
|
253
|
+
/cohorte-loop feat-x --resume # continue a run that died / hit the ceiling, at the pass it reached
|
|
252
254
|
```
|
|
253
255
|
|
|
254
|
-
It stops when `/review` reports **zero blocking findings** (a CRITICAL or a security issue — a LOW
|
|
255
|
-
nit never costs a pass), at the pass ceiling,
|
|
256
|
-
blocking findings
|
|
257
|
-
|
|
258
|
-
|
|
256
|
+
It stops when `/cohorte-review` reports **zero blocking findings** (a CRITICAL or a security issue — a LOW
|
|
257
|
+
nit never costs a pass), at the pass ceiling, as soon as two consecutive reviews return the same
|
|
258
|
+
blocking findings (the fix is treading water and more passes won't help), or immediately if `/cohorte-build`'s
|
|
259
|
+
readiness gate says the frozen spec **cannot be built** — that one needs `/cohorte-spec`, not passes. **Each
|
|
260
|
+
fix pass is committed** (`loop(<id>): fix pass <i>`) — that's your way back after N autonomous passes —
|
|
261
|
+
and **no fix runs on the last pass**, since fixing without a review behind it leaves unaudited code.
|
|
262
|
+
|
|
263
|
+
**It's resumable.** Before each phase the driver stamps `status: in-progress` + `loop_pass` +
|
|
264
|
+
`loop_phase` into the spec's front-matter (plain `awk`, zero tokens), and a terminal `in-review` or
|
|
265
|
+
`blocked` on exit. So `--resume` continues at pass 3 instead of re-paying passes 1 and 2 — and the spec
|
|
266
|
+
itself tells you, `/cohorte-doctor` and the dashboard where the loop got to.
|
|
259
267
|
|
|
260
268
|
**The loop does not run in your session.** Each phase is a separate `claude -p` child with its own
|
|
261
269
|
fresh context, driven by `pipeline/scripts/loop.sh`; all of their output goes to
|
|
@@ -263,7 +271,7 @@ fresh context, driven by `pipeline/scripts/loop.sh`; all of their output goes to
|
|
|
263
271
|
line per phase and a three-line summary. That's the whole design: a slash command can't `/clear`
|
|
264
272
|
itself, so a conversational loop would pile the diff plus N review reports plus N contracts into a
|
|
265
273
|
history that is re-sent at input price every turn — it would cost more than the loop saves. The
|
|
266
|
-
machine contract is `specs/reports/<id>.verdict.json`, which `/review` now writes on every run; no
|
|
274
|
+
machine contract is `specs/reports/<id>.verdict.json`, which `/cohorte-review` now writes on every run; no
|
|
267
275
|
prose is ever parsed.
|
|
268
276
|
|
|
269
277
|
### Run features in parallel — one session per feature
|
|
@@ -271,16 +279,16 @@ prose is ever parsed.
|
|
|
271
279
|
With `isolation.enabled`, every feature already gets its own worktree, ports, and database
|
|
272
280
|
(`scripts/new-feature.sh <id>` — slots tracked in `.worktrees/slots.tsv`). That isolation is exactly
|
|
273
281
|
what makes **parallel features** safe, and it's the real throughput multiplier when you're rate-limited:
|
|
274
|
-
while feature A's `/build` runs its agents (minutes of wall-clock you'd otherwise spend waiting), a
|
|
275
|
-
second Claude Code session can `/spec` or `/review` feature B.
|
|
282
|
+
while feature A's `/cohorte-build` runs its agents (minutes of wall-clock you'd otherwise spend waiting), a
|
|
283
|
+
second Claude Code session can `/cohorte-spec` or `/cohorte-review` feature B.
|
|
276
284
|
|
|
277
285
|
The pattern:
|
|
278
286
|
|
|
279
287
|
```
|
|
280
|
-
session 1 (main checkout): /spec feat-a → /build feat-a (agents run…)
|
|
281
|
-
session 2 (main checkout): /spec feat-b → /build feat-b (agents run…)
|
|
282
|
-
session 1: /review feat-a → /ship feat-a
|
|
283
|
-
session 2: /review feat-b → …
|
|
288
|
+
session 1 (main checkout): /cohorte-spec feat-a → /cohorte-build feat-a (agents run…)
|
|
289
|
+
session 2 (main checkout): /cohorte-spec feat-b → /cohorte-build feat-b (agents run…)
|
|
290
|
+
session 1: /cohorte-review feat-a → /cohorte-ship feat-a
|
|
291
|
+
session 2: /cohorte-review feat-b → …
|
|
284
292
|
```
|
|
285
293
|
|
|
286
294
|
Rules that make it safe:
|
|
@@ -293,10 +301,10 @@ Rules that make it safe:
|
|
|
293
301
|
- **The contract package is the one shared tree.** Two features editing
|
|
294
302
|
`<contract.path>/<their-own-id>.<ext>` never conflict (one file per feature); merge order only
|
|
295
303
|
matters if a later feature *imports* an earlier one's contract — ship the dependency first.
|
|
296
|
-
- `/ship` one at a time: it commits from the feature's branch and the freshness gate keeps a stale
|
|
304
|
+
- `/cohorte-ship` one at a time: it commits from the feature's branch and the freshness gate keeps a stale
|
|
297
305
|
verdict from shipping; after each merge, rebase the other live worktrees (`git rebase main`) so
|
|
298
306
|
their eventual reviews diff against reality.
|
|
299
|
-
- `/doctor` check 6 shows the live slot table (feature ↔ worktree ↔ ports) when you lose track.
|
|
307
|
+
- `/cohorte-doctor` check 6 shows the live slot table (feature ↔ worktree ↔ ports) when you lose track.
|
|
300
308
|
|
|
301
309
|
### Workflows — deterministic multi-agent runs (opt-in)
|
|
302
310
|
|
|
@@ -315,7 +323,7 @@ The essentials:
|
|
|
315
323
|
- **The conversational commands stay the default path** — and the fallback when workflows are
|
|
316
324
|
disabled or the client is too old. A workflow runs only when you explicitly ask for it
|
|
317
325
|
("run the review workflow").
|
|
318
|
-
- **Prerequisite: Claude Code ≥ 2.1.154** with workflows enabled. `/doctor` (check 8) tells you
|
|
326
|
+
- **Prerequisite: Claude Code ≥ 2.1.154** with workflows enabled. `/cohorte-doctor` (check 8) tells you
|
|
319
327
|
which path your session will take and why.
|
|
320
328
|
- **No input mid-run — questions at the edges.** A workflow runs to completion without asking
|
|
321
329
|
anything: whatever would have been a mid-run question lands in the result at the end. The
|
|
@@ -331,9 +339,9 @@ Details: `profile/SCHEMA.md` §Workflows.
|
|
|
331
339
|
|
|
332
340
|
Cohorte can send **anonymous** usage pings (core version, OS, phase name, duration, per-surface
|
|
333
341
|
result counts, and a *hash* of the feature id — never repo names, paths, code, or IPs). It is
|
|
334
|
-
**strictly opt-in**: `/init-pipeline` asks once per machine, the default is No, and both answers are
|
|
342
|
+
**strictly opt-in**: `/cohorte-init-pipeline` asks once per machine, the default is No, and both answers are
|
|
335
343
|
recorded so you're never re-asked. Withdraw anytime (`telemetry.enabled: false` in
|
|
336
|
-
`~/.claude/cohorte.config.yaml`); erase your history anytime (`/doctor` prints your `install_id`,
|
|
344
|
+
`~/.claude/cohorte.config.yaml`); erase your history anytime (`/cohorte-doctor` prints your `install_id`,
|
|
337
345
|
the collector's `DELETE /v1/install/<id>` drops it). Full spec + GDPR details:
|
|
338
346
|
`profile/SCHEMA.md` §Telemetry (including the collector API contract).
|
|
339
347
|
|
|
@@ -355,12 +363,12 @@ install.sh # script installer (fresh + --update) for no-Node enviro
|
|
|
355
363
|
install.ps1 # same installer for Windows PowerShell (fresh + -Update)
|
|
356
364
|
core/ # copied verbatim into ~/.claude (global) or <project>/.claude (bundled)
|
|
357
365
|
agents/ # implementer.template.md (rendered per surface) + review / release / profile-reader
|
|
358
|
-
commands/ # init-pipeline + the pipeline commands + /update-pipeline
|
|
366
|
+
commands/ # init-pipeline + the pipeline commands + /cohorte-update-pipeline
|
|
359
367
|
hooks/ # gate.py (destructive-command gate; branch-aware; preflight phase gate)
|
|
360
368
|
templates/ # handoff / brainstorm-return / design-brief / review-feedback / pr-body / spec
|
|
361
369
|
workflows/ # opt-in Workflow-runtime scripts: review.js / audit.js / refactor.js
|
|
362
370
|
profile/
|
|
363
|
-
PIPELINE.template.md # the profile skeleton /init-pipeline fills
|
|
371
|
+
PIPELINE.template.md # the profile skeleton /cohorte-init-pipeline fills
|
|
364
372
|
SCHEMA.md # field reference
|
|
365
373
|
cohorte.config.template.yaml # seeds ~/.claude/cohorte.config.yaml (kanban)
|
|
366
374
|
scripts/ # worktree-isolation templates + shipped preflight/kanban/telemetry scripts
|
package/bin/cli.js
CHANGED
|
@@ -45,7 +45,7 @@ Commands:
|
|
|
45
45
|
update Refresh the stack-agnostic core only. PIPELINE.md, rendered surface
|
|
46
46
|
agents, gate-config.json, settings.json and your filled
|
|
47
47
|
~/.claude/cohorte.config.yaml are never touched.
|
|
48
|
-
dashboard Serve a local web cockpit for the pipeline (freshness, /doctor
|
|
48
|
+
dashboard Serve a local web cockpit for the pipeline (freshness, /cohorte-doctor
|
|
49
49
|
health, specs board, install/update actions). Binds 127.0.0.1:4317
|
|
50
50
|
by default (loopback only — its actions execute code). --host=ADDR
|
|
51
51
|
to expose (e.g. --host=0.0.0.0, prints a security warning). --open
|
|
@@ -163,7 +163,7 @@ function copyCore() {
|
|
|
163
163
|
// every caller chains them with `|| true`, the result was silent: no kanban card
|
|
164
164
|
// moves, no telemetry pings, no error. The shell installers named them explicitly
|
|
165
165
|
// and this port drifted. The rule below needs no list to keep in sync: a `<x>.sh`
|
|
166
|
-
// with an `<x>.sh.template` sibling is rendered per-project by /init-pipeline, so
|
|
166
|
+
// with an `<x>.sh.template` sibling is rendered per-project by /cohorte-init-pipeline, so
|
|
167
167
|
// only the template ships; every other `.sh` is a shipped executable.
|
|
168
168
|
const scriptFiles = fs.readdirSync(path.join(src, 'scripts'));
|
|
169
169
|
for (const f of scriptFiles) {
|
|
@@ -178,7 +178,7 @@ function copyCore() {
|
|
|
178
178
|
}
|
|
179
179
|
fs.copyFileSync(path.join(src, 'core', 'agents', 'implementer.template.md'),
|
|
180
180
|
path.join(pipelineDir, 'implementer.template.md'));
|
|
181
|
-
// /doctor reads this to tell the human what they're missing; the shell installers
|
|
181
|
+
// /cohorte-doctor reads this to tell the human what they're missing; the shell installers
|
|
182
182
|
// have always copied it, this port never did.
|
|
183
183
|
const changelog = path.join(src, 'CHANGELOG.md');
|
|
184
184
|
if (fs.existsSync(changelog)) fs.copyFileSync(changelog, path.join(pipelineDir, 'CHANGELOG.md'));
|
|
@@ -211,7 +211,7 @@ function scrubTddGate() {
|
|
|
211
211
|
// the fixed (non-rendered) agents: the dev review/release pipeline agents
|
|
212
212
|
function copyFixedAgents() {
|
|
213
213
|
fs.mkdirSync(path.join(dest, 'agents'), { recursive: true });
|
|
214
|
-
// Every agent in core/agents/ EXCEPT the *.template.md ones, which /init-pipeline renders
|
|
214
|
+
// Every agent in core/agents/ EXCEPT the *.template.md ones, which /cohorte-init-pipeline renders
|
|
215
215
|
// per-surface. Until 1.2.6 this was a hardcoded ['review.md', 'release.md'] that never grew
|
|
216
216
|
// the agents the shell installers copy, so `npx cohorte install` shipped a command with no
|
|
217
217
|
// agent to dispatch — the run reported the command as not installed.
|
|
@@ -227,6 +227,22 @@ function copyFixedAgents() {
|
|
|
227
227
|
// 1.5.0 removed the /smoke phase; copy-over never deletes, so scrub the orphan agent+command.
|
|
228
228
|
fs.rmSync(path.join(dest, 'agents', 'smoke.md'), { force: true });
|
|
229
229
|
fs.rmSync(path.join(dest, 'commands', 'smoke.md'), { force: true });
|
|
230
|
+
// 1.4.0 removed /cycle and its workflow — and no installer ever scrubbed them, so every
|
|
231
|
+
// install since has kept offering a command that dispatches a workflow whose phases were
|
|
232
|
+
// later deleted. A dead command is worse than a missing one: the model can still fire it.
|
|
233
|
+
fs.rmSync(path.join(dest, 'commands', 'cycle.md'), { force: true });
|
|
234
|
+
fs.rmSync(path.join(dest, 'workflows', 'cycle.js'), { force: true });
|
|
235
|
+
// 1.6.0 renamed /loop → /drive: Claude Code's own built-in /loop shadowed ours, so a leftover
|
|
236
|
+
// commands/loop.md is a command the user can never reach — scrub it rather than leave a decoy.
|
|
237
|
+
fs.rmSync(path.join(dest, 'commands', 'loop.md'), { force: true });
|
|
238
|
+
// 2.0.0 prefixed every command with `cohorte-`, which ends the shadowing problem for good.
|
|
239
|
+
// Copy-over never deletes, so all 13 bare names would survive an upgrade as decoys — and a
|
|
240
|
+
// stale /build is the worst kind: it still dispatches implementers, from a 1.x command file
|
|
241
|
+
// that knows nothing of this core's contract. /drive goes too (it became /cohorte-loop).
|
|
242
|
+
for (const c of ['align-ds', 'audit', 'brainstorm', 'build', 'doctor', 'drive', 'fix',
|
|
243
|
+
'init-pipeline', 'refactor', 'review', 'ship', 'spec', 'update-pipeline']) {
|
|
244
|
+
fs.rmSync(path.join(dest, 'commands', `${c}.md`), { force: true });
|
|
245
|
+
}
|
|
230
246
|
scrubResearchQuestionnaire();
|
|
231
247
|
}
|
|
232
248
|
|
|
@@ -271,10 +287,10 @@ function setCfg(text, cfgKey, value) {
|
|
|
271
287
|
}
|
|
272
288
|
|
|
273
289
|
// Fill the seeded config from a short TTY interview (shared Obsidian vault for the kanban mirror).
|
|
274
|
-
// Kanban is per-project, so it is wired later by /init-pipeline — not asked here.
|
|
290
|
+
// Kanban is per-project, so it is wired later by /cohorte-init-pipeline — not asked here.
|
|
275
291
|
async function promptConfig(text) {
|
|
276
292
|
console.log('\n Quick setup (Enter to skip — you can also wire this later via');
|
|
277
|
-
console.log(' /init-pipeline or /update-pipeline):');
|
|
293
|
+
console.log(' /cohorte-init-pipeline or /cohorte-update-pipeline):');
|
|
278
294
|
const vault = await ask(' · absolute path to your shared Obsidian vault (for the kanban mirror): ');
|
|
279
295
|
if (vault) text = setCfg(text, 'vault_path', `"${vault}"`);
|
|
280
296
|
return text;
|
|
@@ -291,7 +307,7 @@ async function seedConfig() {
|
|
|
291
307
|
if (fs.existsSync(cfg)) { console.log(` · kept your existing ${cfg}`); return; }
|
|
292
308
|
if (legacy) {
|
|
293
309
|
console.log(` · found legacy ${legacy} — kept as-is (still read as a fallback).`);
|
|
294
|
-
console.log(' Run /update-pipeline to migrate it into cohorte.config.yaml + wire the kanban.');
|
|
310
|
+
console.log(' Run /cohorte-update-pipeline to migrate it into cohorte.config.yaml + wire the kanban.');
|
|
295
311
|
return;
|
|
296
312
|
}
|
|
297
313
|
fs.mkdirSync(path.dirname(cfg), { recursive: true });
|
|
@@ -302,7 +318,7 @@ async function seedConfig() {
|
|
|
302
318
|
console.log(` · seeded ${cfg} from your answers`);
|
|
303
319
|
} else {
|
|
304
320
|
fs.writeFileSync(cfg, text);
|
|
305
|
-
console.log(` · seeded ${cfg} (disabled defaults — enable via /init-pipeline or /update-pipeline)`);
|
|
321
|
+
console.log(` · seeded ${cfg} (disabled defaults — enable via /cohorte-init-pipeline or /cohorte-update-pipeline)`);
|
|
306
322
|
}
|
|
307
323
|
}
|
|
308
324
|
|
|
@@ -383,21 +399,21 @@ if (scope === 'global') {
|
|
|
383
399
|
✓ pipeline core installed globally into ${dest} (version ${VERSION})
|
|
384
400
|
gate hook: ${hookState} (reads each repo's .claude/gate-config.json; silent where absent)
|
|
385
401
|
|
|
386
|
-
The commands (/init-pipeline, /brainstorm, /build …) and the review/release agents are now
|
|
402
|
+
The commands (/cohorte-init-pipeline, /cohorte-brainstorm, /cohorte-build …) and the review/release agents are now
|
|
387
403
|
available in EVERY project on this machine — nothing is copied per repo.
|
|
388
404
|
|
|
389
405
|
Per repo:
|
|
390
406
|
1. Open the project in Claude Code.
|
|
391
|
-
2. Run /init-pipeline — it generates PIPELINE.md, renders the surface agents, writes
|
|
407
|
+
2. Run /cohorte-init-pipeline — it generates PIPELINE.md, renders the surface agents, writes
|
|
392
408
|
.claude/gate-config.json, and drops a committed .claude/pipeline.json pointer so
|
|
393
409
|
teammates know to install the global core (${REPO_URL}).
|
|
394
|
-
3. Commit PIPELINE.md + .claude/, then /brainstorm to start a feature.
|
|
410
|
+
3. Commit PIPELINE.md + .claude/, then /cohorte-brainstorm to start a feature.
|
|
395
411
|
|
|
396
412
|
Update later with: npx cohorte@latest update --global
|
|
397
413
|
|
|
398
414
|
Global kanban config, user-scoped — optional:
|
|
399
415
|
· One consolidated file: ${path.join(globalDir, 'cohorte.config.yaml')}
|
|
400
|
-
· Don't hand-edit it — /init-pipeline (new project) and /update-pipeline (existing) wire it
|
|
416
|
+
· Don't hand-edit it — /cohorte-init-pipeline (new project) and /cohorte-update-pipeline (existing) wire it
|
|
401
417
|
for you: creating + syncing an Obsidian kanban board of the pipeline in your shared vault.`);
|
|
402
418
|
} else if (mode === 'install') {
|
|
403
419
|
console.log(`→ installing pipeline core into ${dest}`);
|
|
@@ -414,9 +430,9 @@ Global kanban config, user-scoped — optional:
|
|
|
414
430
|
|
|
415
431
|
Next:
|
|
416
432
|
1. Open the project in Claude Code.
|
|
417
|
-
2. Run /init-pipeline — it detects your stack, asks the gaps, and generates
|
|
433
|
+
2. Run /cohorte-init-pipeline — it detects your stack, asks the gaps, and generates
|
|
418
434
|
PIPELINE.md + renders one implementer agent per surface.
|
|
419
|
-
3. Commit PIPELINE.md, then /brainstorm to start a feature.
|
|
435
|
+
3. Commit PIPELINE.md, then /cohorte-brainstorm to start a feature.
|
|
420
436
|
|
|
421
437
|
Update later with: npx cohorte@latest update
|
|
422
438
|
Prefer one shared core across all your repos? Re-run with --global.`);
|
|
@@ -428,6 +444,6 @@ Prefer one shared core across all your repos? Re-run with --global.`);
|
|
|
428
444
|
bumpPointerVersion(path.join(dest, 'pipeline.json'));
|
|
429
445
|
console.log(`
|
|
430
446
|
✓ core refreshed to ${VERSION}. Your PIPELINE.md, rendered surface agents, gate-config.json and
|
|
431
|
-
settings.json were left as-is. Re-run /init-pipeline if your stack changed.`);
|
|
447
|
+
settings.json were left as-is. Re-run /cohorte-init-pipeline if your stack changed.`);
|
|
432
448
|
}
|
|
433
449
|
})();
|