cohorte 1.6.0 → 2.0.1
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 +117 -2
- package/README.md +57 -57
- package/bin/cli.js +23 -15
- package/core/agents/implementer.template.md +3 -3
- package/core/agents/release.md +1 -1
- package/core/agents/review.md +3 -3
- package/core/commands/{audit.md → cohorte-audit.md} +3 -3
- package/core/commands/{brainstorm.md → cohorte-brainstorm.md} +4 -4
- package/core/commands/{build.md → cohorte-build.md} +15 -15
- package/core/commands/{doctor.md → cohorte-doctor.md} +17 -9
- package/core/commands/{fix.md → cohorte-fix.md} +15 -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} +20 -19
- package/core/commands/{ship.md → cohorte-ship.md} +5 -5
- package/core/commands/{spec.md → cohorte-spec.md} +13 -13
- package/core/commands/{update-pipeline.md → cohorte-update-pipeline.md} +11 -6
- package/core/hooks/gate.py +101 -6
- package/core/templates/brainstorm-return.md +4 -4
- package/core/templates/decisions.template.md +1 -1
- package/core/templates/design-brief.md +1 -1
- package/core/templates/spec.template.md +7 -7
- 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 +22 -22
- package/dashboard/README.md +2 -2
- package/dashboard/dist/assets/{index-DYyn4p93.js → index-P1I1JGtj.js} +2 -2
- package/dashboard/dist/index.html +1 -1
- package/dashboard/server/doctor.js +69 -19
- package/dashboard/server/index.js +5 -5
- package/dashboard/server/metrics.js +1 -1
- package/install.ps1 +23 -14
- package/install.sh +24 -14
- package/package.json +2 -2
- package/profile/PIPELINE.template.md +17 -16
- package/profile/SCHEMA.md +89 -77
- package/profile/cohorte.config.template.yaml +8 -8
- package/scripts/loop-detach.sh +153 -0
- package/scripts/loop.sh +110 -29
- 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 +123 -20
- package/scripts/test-metrics.mjs +23 -11
- package/scripts/test-workflows.mjs +7 -7
- package/scripts/validate-core.mjs +45 -23
- package/core/commands/drive.md +0 -80
- /package/core/commands/{align-ds.md → cohorte-align-ds.md} +0 -0
|
@@ -15,7 +15,7 @@ at Finish, when a board is configured.
|
|
|
15
15
|
> decision. The panel argues about the idea, not about settled ground: a persona that proposes
|
|
16
16
|
> something a live line already decided must be told so by another persona, and an idea that genuinely
|
|
17
17
|
> needs to overturn one must say which line, out loud, so the human decides it here rather than
|
|
18
|
-
> discovering the contradiction at `/spec`.
|
|
18
|
+
> discovering the contradiction at `/cohorte-spec`.
|
|
19
19
|
>
|
|
20
20
|
> Template paths below (`.claude/templates/…`) resolve to `~/.claude/templates/…` when the core is
|
|
21
21
|
> installed globally — read whichever exists.
|
|
@@ -47,8 +47,8 @@ screens, risks, and what's explicitly out.
|
|
|
47
47
|
|
|
48
48
|
When the human is satisfied, produce the **brainstorm return** by filling
|
|
49
49
|
`.claude/templates/brainstorm-return.md` and **staging it to
|
|
50
|
-
`specs/reports/<feature_id>-brainstorm.md`** (the gitignored buffer dir — `/spec` reads it from there
|
|
51
|
-
when invoked with no paste). In chat print only a 3-line summary + the path. Tell them to run `/spec`
|
|
50
|
+
`specs/reports/<feature_id>-brainstorm.md`** (the gitignored buffer dir — `/cohorte-spec` reads it from there
|
|
51
|
+
when invoked with no paste). In chat print only a 3-line summary + the path. Tell them to run `/cohorte-spec`
|
|
52
52
|
— **recommend a `/clear` first**, the return is staged on disk (pasting it remains a fallback).
|
|
53
53
|
|
|
54
54
|
**Kanban:** settle the `feature_id` (kebab-case slug) the return carries — it is the card's join key
|
|
@@ -56,7 +56,7 @@ downstream. If a board is configured, **move** the card into the **Brainstorm**
|
|
|
56
56
|
`#<feature_id>` (per §Kanban): the picked Ideas card if the human chose one, else a new card. No-op if
|
|
57
57
|
no board.
|
|
58
58
|
|
|
59
|
-
**Telemetry:** chain the opt-in usage ping onto that same Bash call — `/build` §4's shared form,
|
|
59
|
+
**Telemetry:** chain the opt-in usage ping onto that same Bash call — `/cohorte-build` §4's shared form,
|
|
60
60
|
`<phase>` = `brainstorm`, `<seconds>` = `0` (this phase is human thinking time, not pipeline
|
|
61
61
|
wall-clock — the funnel signal is the event, not its duration), `<results>` = `""`. No board ⇒ still
|
|
62
62
|
ping, in its own `|| true` call. Silent no-op without consent; never ask about consent here.
|
|
@@ -17,16 +17,16 @@ You are the **lead**. Build feature **$ARGUMENTS** from its frozen spec.
|
|
|
17
17
|
|
|
18
18
|
- Check the spec front-matter FIRST — `grep '^status:' specs/$ARGUMENTS.md` (or Read with a ~15-line
|
|
19
19
|
limit) — before any full read. Buildable statuses are `frozen`, `in-review` and `in-progress` (the
|
|
20
|
-
last one means a `/
|
|
21
|
-
loop gave up here: say so, and route by the spec's `## Remediation` — open items ⇒ `/fix`, none ⇒
|
|
20
|
+
last one means a `/cohorte-loop` is or was driving this spec — SCHEMA.md §Spec status). `blocked` means a
|
|
21
|
+
loop gave up here: say so, and route by the spec's `## Remediation` — open items ⇒ `/cohorte-fix`, none ⇒
|
|
22
22
|
continue this build. Anything else (`draft`, missing, `shipped`) ⇒ stop and tell the human to run
|
|
23
|
-
`/spec` first. Only then read the body, selectively: front-matter, §5 contract, the surface
|
|
23
|
+
`/cohorte-spec` first. Only then read the body, selectively: front-matter, §5 contract, the surface
|
|
24
24
|
task sections, and `## Remediation` (fall back to a full read if the spec doesn't follow the
|
|
25
25
|
template's headings).
|
|
26
26
|
- **Route check** — if `## Remediation` has open `- [ ]` items and none requires a contract change,
|
|
27
|
-
stop and tell the human to run `/fix $ARGUMENTS` instead: it re-dispatches only the surfaces with
|
|
27
|
+
stop and tell the human to run `/cohorte-fix $ARGUMENTS` instead: it re-dispatches only the surfaces with
|
|
28
28
|
findings. A full build with open items is only right when the contract change ripples into clean
|
|
29
|
-
surfaces (the case `/fix` §1 falls back here for).
|
|
29
|
+
surfaces (the case `/cohorte-fix` §1 falls back here for).
|
|
30
30
|
- **Design gate** — only if `design.enabled` and the feature has UI (some surface `uses_design`): if the
|
|
31
31
|
spec front-matter `design_files` is empty, ask the human for the feature's design **links** and store
|
|
32
32
|
them in `design_files`, then continue. Each entry is a full self-contained link of the form
|
|
@@ -56,7 +56,7 @@ For each surface to add: infer its `key`, `path`, `label`, `agent`, `tools`, `mo
|
|
|
56
56
|
SCHEMA.md §"Rendering / reconciling a surface agent" — write the `surfaces[]` entry + §Conventions/§Testing
|
|
57
57
|
stanza into `PIPELINE.md`, render `.claude/agents/<agent>.md` from the implementer template, applying the
|
|
58
58
|
shared-code rule (shared trees get a single-owner surface; cross-slice shapes go through the contract).
|
|
59
|
-
This is the automatic path: you don't send the human back to `/init-pipeline`. If nothing new is needed,
|
|
59
|
+
This is the automatic path: you don't send the human back to `/cohorte-init-pipeline`. If nothing new is needed,
|
|
60
60
|
say so and continue. Dispatch (§3) then covers the reconciled surface list.
|
|
61
61
|
|
|
62
62
|
**Adding or splitting a surface is an architectural decision** — append ONE line for it to
|
|
@@ -70,7 +70,7 @@ One `>>` in the Bash call you're already making. Nothing added ⇒ nothing to ap
|
|
|
70
70
|
**Zero extra agents: you already hold the spec, the profile and the reconciled surface list.** The
|
|
71
71
|
whole point is that a bancal spec costs one verdict here instead of N implementers discovering it in
|
|
72
72
|
parallel. Judge the frozen contract on **implementability only** — never on whether the feature is a
|
|
73
|
-
good idea (that was `/brainstorm`), never by re-reading files you don't already need:
|
|
73
|
+
good idea (that was `/cohorte-brainstorm`), never by re-reading files you don't already need:
|
|
74
74
|
|
|
75
75
|
1. **Contract completeness** (§5) — every endpoint/interface has method+path (or signature), auth,
|
|
76
76
|
request fields with types + validation, the success shape, and its error cases. A missing
|
|
@@ -89,8 +89,8 @@ good idea (that was `/brainstorm`), never by re-reading files you don't already
|
|
|
89
89
|
(this is §1's gate restated as a verdict, so an automated driver sees the same fact).
|
|
90
90
|
|
|
91
91
|
Write the machine-readable verdict to `specs/reports/$ARGUMENTS.readiness.json` (overwrite,
|
|
92
|
-
`mkdir -p specs/reports` first — the same gitignored buffer dir `/review` stages into, which may not
|
|
93
|
-
exist yet on a first build) — on **every** build, including `READY`. It is the only channel between this gate and a driver (`/
|
|
92
|
+
`mkdir -p specs/reports` first — the same gitignored buffer dir `/cohorte-review` stages into, which may not
|
|
93
|
+
exist yet on a first build) — on **every** build, including `READY`. It is the only channel between this gate and a driver (`/cohorte-loop`),
|
|
94
94
|
which parses no prose:
|
|
95
95
|
|
|
96
96
|
```json
|
|
@@ -104,7 +104,7 @@ which parses no prose:
|
|
|
104
104
|
surface key or dependency name (no `:line` — it shifts on every edit); `<what>` is the gap, not the
|
|
105
105
|
fix. `READY` ⇒ `[]`.
|
|
106
106
|
- **`NOT-READY` ⇒ STOP: author no contract and spawn NO agent.** Print the gaps and send the human to
|
|
107
|
-
`/spec $ARGUMENTS` to patch the contract, then re-run `/build`. This abort is the whole point of the
|
|
107
|
+
`/cohorte-spec $ARGUMENTS` to patch the contract, then re-run `/cohorte-build`. This abort is the whole point of the
|
|
108
108
|
step — a spec that cannot be built does not get cheaper by being built N times in parallel.
|
|
109
109
|
- **`RESERVATIONS` ⇒ continue.** It never blocks (a gate that stalls a sound build on a missing error
|
|
110
110
|
case would cost more human round-trips than it saves): inline each gap verbatim into the dispatch of
|
|
@@ -188,12 +188,12 @@ Bash call, chain the opt-in usage ping — **the shared form every phase command
|
|
|
188
188
|
`<core>/pipeline/scripts/telemetry-send.sh <phase> "$ARGUMENTS" <seconds> "<results>" || true`
|
|
189
189
|
(`<core>` = `~/.claude` global / `.claude` bundled; here `<phase>` = `build`, `<results>` =
|
|
190
190
|
`<ok,ok|error,…>`) — a silent no-op unless the human explicitly consented (SCHEMA.md §Telemetry);
|
|
191
|
-
never ask about consent here. `/review` and `/fix` chain the same line with their own
|
|
191
|
+
never ask about consent here. `/cohorte-review` and `/cohorte-fix` chain the same line with their own
|
|
192
192
|
phase + results. The `|| true` swallows a **missing** script too, so a half-copied core goes
|
|
193
|
-
silent rather than loud — `/doctor` check 1 is what catches that.
|
|
194
|
-
Then tell the human: exercise the feature by hand if it's worth it, then run `/review $ARGUMENTS` —
|
|
195
|
-
unless a surface is dead, in which case say so first and let them decide whether to re-run `/build`
|
|
196
|
-
(a dead surface has no findings, so `/fix` has nothing to re-dispatch).
|
|
193
|
+
silent rather than loud — `/cohorte-doctor` check 1 is what catches that.
|
|
194
|
+
Then tell the human: exercise the feature by hand if it's worth it, then run `/cohorte-review $ARGUMENTS` —
|
|
195
|
+
unless a surface is dead, in which case say so first and let them decide whether to re-run `/cohorte-build`
|
|
196
|
+
(a dead surface has no findings, so `/cohorte-fix` has nothing to re-dispatch).
|
|
197
197
|
Do not run the app or migrations yourself here — building is not running.
|
|
198
198
|
**Recommend a `/clear` now** — the spec, contract and diff are all on
|
|
199
199
|
disk, and the lead's history is re-sent at input price on every turn it survives.
|
|
@@ -16,13 +16,16 @@ fix only with the human's go-ahead (or hand them the command).
|
|
|
16
16
|
`.claude/pipeline/VERSION` bundled); `.claude/pipeline.json` names a mode + `core_version`
|
|
17
17
|
coherent with the VERSION file. A **global**-mode pointer lagging the VERSION file is ⚠️, not ❌:
|
|
18
18
|
nothing bumped that field before 1.2.5, so the core itself is fine and only the pointer is stale
|
|
19
|
-
⇒ fix by running `/update-pipeline` (§3 syncs it now), or by editing the one field. Compare
|
|
20
|
-
against `npm view cohorte version` — behind ⇒ suggest `/update-pipeline`. Read `pipeline/CHANGELOG.md` for what they're missing. The router
|
|
19
|
+
⇒ fix by running `/cohorte-update-pipeline` (§3 syncs it now), or by editing the one field. Compare
|
|
20
|
+
against `npm view cohorte version` — behind ⇒ suggest `/cohorte-update-pipeline`. Read `pipeline/CHANGELOG.md` for what they're missing. The router
|
|
21
21
|
commands' step files are present — `templates/steps/init-pipeline/` non-empty (a router whose
|
|
22
22
|
`templates/steps/<cmd>/` dir is missing is a partial/stale install ⇒
|
|
23
23
|
re-run install/update). **Shipped scripts present and executable** in `<core>/pipeline/scripts/`:
|
|
24
|
-
`kanban-move.sh`, `telemetry-send.sh`, `preflight.sh`, `loop.sh`, `
|
|
25
|
-
`remove-feature.sh.template` — ❌ any missing one.
|
|
24
|
+
`kanban-move.sh`, `telemetry-send.sh`, `preflight.sh`, `loop.sh`, `loop-detach.sh`,
|
|
25
|
+
`new-feature.sh.template`, `remove-feature.sh.template` — ❌ any missing one.
|
|
26
|
+
`loop-detach.sh` absent is what silently turns `/cohorte-loop` back into a foreground run
|
|
27
|
+
that dies at the 600 s tool ceiling, so name it explicitly rather than folding it into
|
|
28
|
+
"some script is missing". Every caller chains these with `|| true`, so an absent script is a **silent**
|
|
26
29
|
no-op (no kanban card moves, no telemetry ping, no error anywhere) — this check is the only thing
|
|
27
30
|
that sees it. Also flag ❌ a `VERSION` **newer than** the other `pipeline/` files (compare mtimes):
|
|
28
31
|
a version bumped without a full re-copy is a half-done update ⇒ re-run install/update.
|
|
@@ -47,6 +50,11 @@ fix only with the human's go-ahead (or hand them the command).
|
|
|
47
50
|
it double-prompts) **with a matcher covering both `Bash` and `Task`** — a `Bash`-only matcher
|
|
48
51
|
leaves the preflight phase gate dead (the 1.3.0–1.3.1 regression). Hook files exist at the
|
|
49
52
|
registered paths.
|
|
53
|
+
Then the **preflight stamp is local, never versioned**: `git ls-files --error-unmatch
|
|
54
|
+
.claude/preflight.ok` must miss, and `.gitignore` must cover it. A tracked stamp is a ❌ (not a
|
|
55
|
+
⚠️) — it records the tree it verified, the commit that carries it moves HEAD past that tree, and
|
|
56
|
+
the committed copy lands in every clone and new worktree; the gate then blocks clean trees and
|
|
57
|
+
greens unchecked ones. fix: `git rm --cached .claude/preflight.ok` + add it to `.gitignore`.
|
|
50
58
|
4. **Retrieval** (if `retrieval.provider` ≠ `none`). Run the SCHEMA.md §Code retrieval health
|
|
51
59
|
check: CLI resolvable from PATH, `.mcp.json` entry present in PATH-proof launcher form,
|
|
52
60
|
`.serena/` gitignored, server actually connects.
|
|
@@ -67,7 +75,7 @@ fix only with the human's go-ahead (or hand them the command).
|
|
|
67
75
|
(the install_id is the human's GDPR erasure key — see SCHEMA.md §Telemetry). Flag ❌ any
|
|
68
76
|
incoherent state: `enabled: true` with no `install_id` or no `consent_date` (sending without
|
|
69
77
|
recorded consent — fix: set `enabled: false` until the consent question is re-run), or a
|
|
70
|
-
`telemetry:` block missing entirely on a current core (top up via `/update-pipeline`).
|
|
78
|
+
`telemetry:` block missing entirely on a current core (top up via `/cohorte-update-pipeline`).
|
|
71
79
|
8. **Workflows** (the opt-in execution path — SCHEMA.md §Workflows; the conversational commands
|
|
72
80
|
stay the default, so failures here are ⚠️ at most, never ❌). Report which path this machine will
|
|
73
81
|
take and why:
|
|
@@ -86,14 +94,14 @@ fix only with the human's go-ahead (or hand them the command).
|
|
|
86
94
|
`workflows: unavailable (<first failing prerequisite>) — conversational commands (the default)`.
|
|
87
95
|
9. **Specs & metrics.** Every `specs/*.md` front-matter `status` is a valid stage — one of
|
|
88
96
|
`draft · frozen · in-progress · in-review · shipped · blocked` (SCHEMA.md §Spec status; the last two
|
|
89
|
-
are written by the `/
|
|
97
|
+
are written by the `/cohorte-loop` driver, so flagging them would report the pipeline's own state as a
|
|
90
98
|
defect) — excluding
|
|
91
99
|
`_`-prefixed files (the spec template and `specs/_decisions.md`, the decision journal) and
|
|
92
|
-
`specs/refactor-backlog.md`, which `/audit` writes as a backlog, not a
|
|
100
|
+
`specs/refactor-backlog.md`, which `/cohorte-audit` writes as a backlog, not a
|
|
93
101
|
spec, and which has no front-matter to check. A spec left `in-progress`/`blocked` with
|
|
94
|
-
`loop_pass` > 0 is a loop that never finished ⇒ say so and name `/
|
|
102
|
+
`loop_pass` > 0 is a loop that never finished ⇒ say so and name `/cohorte-loop <id> --resume`. `shipped` specs
|
|
95
103
|
with a live worktree flagged (see 6). `.claude/pipeline-metrics.jsonl` and `specs/reports/` (the
|
|
96
|
-
`/review` report buffer that lets a `/fix` survive a `/clear`) are gitignored. Metrics
|
|
104
|
+
`/cohorte-review` report buffer that lets a `/cohorte-fix` survive a `/clear`) are gitignored. Metrics
|
|
97
105
|
belong to the **main checkout** — a `pipeline-metrics.jsonl` inside a live feature worktree is a
|
|
98
106
|
stale-core sign (its lines die at teardown) ⇒ suggest appending its lines to the main checkout's
|
|
99
107
|
file and deleting the stray.
|
|
@@ -5,29 +5,29 @@ argument-hint: <feature_id> [paste REVIEW REPORT]
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
You are the **lead**. Run the fix loop for feature **$ARGUMENTS** — the scoped, cheap path after a
|
|
8
|
-
`REVISE`/`BLOCK` verdict. The full `/spec` (Mode B) + `/build` path still exists for review returns
|
|
9
|
-
that change the *contract*; `/fix` is for everything else.
|
|
8
|
+
`REVISE`/`BLOCK` verdict. The full `/cohorte-spec` (Mode B) + `/cohorte-build` path still exists for review returns
|
|
9
|
+
that change the *contract*; `/cohorte-fix` is for everything else.
|
|
10
10
|
|
|
11
11
|
> Read `PIPELINE.md` §`pipeline-profile` first: `surfaces` (paths + agent names) and `contract`.
|
|
12
12
|
> _Skip the re-read if it's already in your context this session and unmodified since._
|
|
13
13
|
>
|
|
14
14
|
> **Kanban** (SCHEMA.md §Kanban): move card `#$ARGUMENTS` → **Fix** on ingest (it returns to **Review**
|
|
15
|
-
> when `/review` re-runs). No-op silently if no board.
|
|
15
|
+
> when `/cohorte-review` re-runs). No-op silently if no board.
|
|
16
16
|
|
|
17
17
|
## 1. Ingest the report
|
|
18
18
|
|
|
19
19
|
- The report is either pasted after the feature id (a REVIEW REPORT, or failures the human hit by
|
|
20
|
-
hand), this session's last `/review` REVIEW REPORT, or — if the context was cleared — read from
|
|
21
|
-
`specs/reports/<id>.md`, where `/review` stages its last report for exactly this reason.
|
|
20
|
+
hand), this session's last `/cohorte-review` REVIEW REPORT, or — if the context was cleared — read from
|
|
21
|
+
`specs/reports/<id>.md`, where `/cohorte-review` stages its last report for exactly this reason.
|
|
22
22
|
If you have none of these, ask for it and wait.
|
|
23
|
-
- Append each finding to `specs/<id>.md` **`## Remediation`** (same format as `/spec` Mode B, under a
|
|
23
|
+
- Append each finding to `specs/<id>.md` **`## Remediation`** (same format as `/cohorte-spec` Mode B, under a
|
|
24
24
|
dated/numbered subheading): `- [ ] <severity> · <file:line> · <type> · <concrete fix>`. Set
|
|
25
25
|
`status: in-review`. Don't pull the whole spec into context for this: grep the line numbers of the
|
|
26
26
|
front-matter `status:` and the `## Remediation` heading, then Read only those regions (offset/limit)
|
|
27
27
|
before editing.
|
|
28
28
|
- **Contract check:** if any finding implies the frozen contract must change, update spec §5 and
|
|
29
|
-
re-author the contract file yourself now (lead-only, per `/build` §2) — agents never edit it. If
|
|
30
|
-
the contract change ripples into surfaces *without* findings, fall back to full `/build` instead
|
|
29
|
+
re-author the contract file yourself now (lead-only, per `/cohorte-build` §2) — agents never edit it. If
|
|
30
|
+
the contract change ripples into surfaces *without* findings, fall back to full `/cohorte-build` instead
|
|
31
31
|
and say so.
|
|
32
32
|
- **Note the epoch** (`date +%s`) in the first Bash call you make here — §3's metrics line and usage
|
|
33
33
|
ping both carry `seconds`, and there is no separate timing call.
|
|
@@ -39,7 +39,7 @@ that change the *contract*; `/fix` is for everything else.
|
|
|
39
39
|
re-dispatch them. Items outside every surface path (contract file, root config) are yours or go
|
|
40
40
|
to the most relevant surface — say which.
|
|
41
41
|
- Re-dispatch **ONLY the surfaces owning ≥1 item**, in parallel, in a **single message** — the exact
|
|
42
|
-
dispatch template from `/build` §3 (one byte-stable template for builds and fix loops; you do NOT
|
|
42
|
+
dispatch template from `/cohorte-build` §3 (one byte-stable template for builds and fix loops; you do NOT
|
|
43
43
|
paste a diff — the agent computes its own, scoped to its tree). Fill the template's final variable
|
|
44
44
|
slot with that surface's open `- [ ]` item lines **verbatim**, so the agent needs no spec re-read to
|
|
45
45
|
find its work; fill the design slot with `none` when a `uses_design` surface's open items are all
|
|
@@ -59,7 +59,7 @@ When the agents return:
|
|
|
59
59
|
(by `file:line`). For every Remediation item an agent reports fixed, flip its `- [ ]` → `- [x]` in
|
|
60
60
|
`specs/<id>.md` and append a terse ` — fixed: <what/where>` note (the convention prior rounds already
|
|
61
61
|
use). Leave genuinely-unaddressed items `- [ ]` so the next loop still sees them. This keeps the
|
|
62
|
-
checkbox state honest and stops a later `/fix` from re-dispatching already-fixed items (§2). Ticking
|
|
62
|
+
checkbox state honest and stops a later `/cohorte-fix` from re-dispatching already-fixed items (§2). Ticking
|
|
63
63
|
here is the lead's job — surface agents own only their tree, never the spec.
|
|
64
64
|
- **Collapse fully-resolved rounds (keep the spec bounded).** When a whole dated Remediation round is now
|
|
65
65
|
entirely `- [x]`, replace its item lines with a single summary line (`- <date> — <N> findings, all
|
|
@@ -67,10 +67,12 @@ When the agents return:
|
|
|
67
67
|
re-reads each loop. Keep any round with ≥1 still-open `- [ ]` item fully expanded (§2's skip logic
|
|
68
68
|
needs those checkboxes).
|
|
69
69
|
- Print one status line per surface (`<key> · items fixed <n>/<m> · tests pass/fail`) — do not restate
|
|
70
|
-
handoff content — and append ONE metrics line for the batch to
|
|
71
|
-
(
|
|
70
|
+
handoff content — and append ONE metrics line for the batch to the **main checkout's**
|
|
71
|
+
`$(dirname "$(git rev-parse --git-common-dir)")/.claude/pipeline-metrics.jsonl` (never a bare
|
|
72
|
+
relative path: from a feature worktree that writes a stray sink whose lines die at teardown)
|
|
73
|
+
(rules in `/cohorte-build` §4, `phase: "fix"`), chaining the opt-in usage ping in the same Bash call
|
|
72
74
|
(results = items fixed over items found across surfaces, e.g. `"5/6"`).
|
|
73
|
-
- Tell the human: re-test by hand if the failures were runtime ones, and `/review $ARGUMENTS` for the
|
|
75
|
+
- Tell the human: re-test by hand if the failures were runtime ones, and `/cohorte-review $ARGUMENTS` for the
|
|
74
76
|
re-verdict — the re-review is what *verifies* the ticked items actually hold (a regression simply
|
|
75
77
|
reappears as a new finding in the next round). **Recommend a `/clear`** — all state (spec,
|
|
76
78
|
checkboxes, staged report) is on disk, and the lead's history is re-sent at input price every turn.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Detect this project's stack, interview the gaps, and generate PIPELINE.md + render the agents so the portable pipeline fits this repo.
|
|
3
|
-
argument-hint: (none) — one-time per project; afterwards /update-pipeline keeps everything current
|
|
3
|
+
argument-hint: (none) — one-time per project; afterwards /cohorte-update-pipeline keeps everything current
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
You are the **pipeline installer**. Your job: turn the generic pipeline into one tailored to **this**
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
---
|
|
2
|
+
model: sonnet
|
|
3
|
+
description: Autonomous /cohorte-build → /cohorte-review → /cohorte-fix → /cohorte-review loop for one feature, until no blocking finding remains.
|
|
4
|
+
argument-hint: <feature_id> [--max=N] [--no-build] [--rebuild] [--resume]
|
|
5
|
+
allowed-tools: Bash(bash ~/.claude/pipeline/scripts/loop-detach.sh:*), Bash(bash .claude/pipeline/scripts/loop-detach.sh:*), Bash(test:*), Read(specs/reports/**)
|
|
6
|
+
disable-model-invocation: true
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
You are the **launcher**, not the loop. Run the driver for **$ARGUMENTS** and relay three lines.
|
|
10
|
+
|
|
11
|
+
> **The driver's name has moved twice.** It was `/loop`, which Claude Code's own built-in `/loop`
|
|
12
|
+
> (run a prompt on a recurring interval) silently **shadowed** — typing `/loop <id>` started the
|
|
13
|
+
> interval runner with the feature id as its prompt, so the driver never ran and the session
|
|
14
|
+
> reported a loop that did not exist. 1.6.0 renamed it `/drive` to escape that. 2.0.0 prefixed
|
|
15
|
+
> every command with `cohorte-`, which makes shadowing impossible by construction, so the accurate
|
|
16
|
+
> name is back: **`/cohorte-loop`**. The shipped script keeps its `loop.sh` name throughout.
|
|
17
|
+
>
|
|
18
|
+
> This command exists because a slash command cannot `/clear` itself. Every phase of the loop runs
|
|
19
|
+
> as a **separate `claude -p` child session** with its own fresh context, driven by a bash script —
|
|
20
|
+
> so the diff, the N review reports and the N contracts never accumulate in YOUR history, which is
|
|
21
|
+
> re-sent at input price on every turn. Running the loop conversationally here would cost more than
|
|
22
|
+
> the loop saves.
|
|
23
|
+
|
|
24
|
+
## 1. Launch — detached, then poll
|
|
25
|
+
|
|
26
|
+
The driver runs for **hours**, which rules out running it as one foreground Bash call: a single
|
|
27
|
+
call is capped at 600 s, and a backgrounded one is not detached — the child stays in this session's
|
|
28
|
+
process group, so a Claude Code restart, crash or laptop sleep kills `loop.sh` and every `claude -p`
|
|
29
|
+
child with it, mid-write. `loop-detach.sh` puts the driver in its own `screen` session so it
|
|
30
|
+
survives all of that, and `loop.sh` re-execs itself under `caffeinate` so idle sleep cannot abort
|
|
31
|
+
its in-flight requests either.
|
|
32
|
+
|
|
33
|
+
Launch — returns immediately:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
test -f .claude/pipeline/scripts/loop-detach.sh \
|
|
37
|
+
&& bash .claude/pipeline/scripts/loop-detach.sh start $ARGUMENTS \
|
|
38
|
+
|| bash ~/.claude/pipeline/scripts/loop-detach.sh start $ARGUMENTS
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Then poll. Each call blocks up to ~9 min (inside the tool ceiling) and prints the **status file** —
|
|
42
|
+
one line per phase, plus `__EXIT__ <code>` when the run is over:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
bash ~/.claude/pipeline/scripts/loop-detach.sh wait <feature_id>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**Repeat `wait` until you see `__EXIT__ <code>`.** A `__RUNNING__` line means the driver is still
|
|
49
|
+
working and nothing is wrong — call `wait` again. Never conclude anything from a `__RUNNING__`;
|
|
50
|
+
the run has not finished and you have no verdict to report. If the human says to stop waiting,
|
|
51
|
+
tell them the run continues detached and how to follow it (`screen -r cohorte-<id>`) — do not
|
|
52
|
+
kill it unless they ask.
|
|
53
|
+
|
|
54
|
+
Pass `$ARGUMENTS` through untouched — `loop.sh` owns its own flag parsing (`--max=N`,
|
|
55
|
+
`--no-build`, `--rebuild`, `--resume`) and exits 64 on anything it doesn't know. Don't validate flags
|
|
56
|
+
yourself, don't rewrite them, don't add any.
|
|
57
|
+
|
|
58
|
+
**One lid-close caveat to pass on** if the human is walking away from a laptop: `caffeinate` holds
|
|
59
|
+
off *idle* sleep, but no userspace assertion can prevent lid-close sleep. Lid open, or clamshell
|
|
60
|
+
mode (AC + external display + external input).
|
|
61
|
+
|
|
62
|
+
**Resume is the human's call, not yours.** The loop records its position in the spec's front-matter
|
|
63
|
+
(`status: in-progress` · `loop_pass` · `loop_phase` — SCHEMA.md §Spec status), so a run killed by a
|
|
64
|
+
dead session, a ceiling or a `blocked` exit can continue with `--resume` instead of re-paying the
|
|
65
|
+
passes it already made. If the human types `/cohorte-loop <id>` on a spec whose front-matter says
|
|
66
|
+
`status: in-progress` or `blocked` with `loop_pass` > 1, say so in one line and ask whether to resume
|
|
67
|
+
or restart — never silently add the flag, and never silently restart from pass 1.
|
|
68
|
+
|
|
69
|
+
**Never read `specs/reports/<id>.loop.log`.** It holds the full transcript of every child session —
|
|
70
|
+
the entire diff, every review report, every fix handoff. Pulling it into this session re-imports
|
|
71
|
+
exactly the context the loop was built to keep out, and it is the one mistake that turns this
|
|
72
|
+
command into the most expensive one in the pipeline. Point the human at the path instead; they can
|
|
73
|
+
open it in an editor for free. The same goes for the per-surface `.diff` and `.preflight.txt` files.
|
|
74
|
+
|
|
75
|
+
`<id>.loop.status` is the **other** file and is safe: it is the driver's stdout, one line per phase.
|
|
76
|
+
`wait` already prints it, so you never need to Read it yourself. Two files, one letter apart —
|
|
77
|
+
`.log` is the expensive one.
|
|
78
|
+
|
|
79
|
+
## 2. Report — three lines, from the exit code
|
|
80
|
+
|
|
81
|
+
`wait` prints one line per phase, one closing line, and `__EXIT__ <code>`; that is your raw
|
|
82
|
+
material, and that code is the exit code the table below is keyed on. For exit
|
|
83
|
+
**1** or **3** only, also Read `specs/reports/<id>.verdict.json` (small, structured, safe) to name
|
|
84
|
+
the remaining findings — never the markdown report, which is the findings body in full. For exit
|
|
85
|
+
**4**, Read `specs/reports/<id>.readiness.json` instead (also small) and relay its `gaps`. On any
|
|
86
|
+
other exit the closing line already carries the deferred count, so read nothing.
|
|
87
|
+
|
|
88
|
+
| exit | meaning | what to say |
|
|
89
|
+
| ---- | ------- | ----------- |
|
|
90
|
+
| `0` | clean | no blocking findings left; the human can `/cohorte-ship <id>` |
|
|
91
|
+
| `1` | ceiling hit | the fix was progressing but ran out of passes ⇒ re-run with a higher `--max` |
|
|
92
|
+
| `2` | no usable verdict | `/cohorte-review` produced nothing, or aborted on a red preflight — the closing line says which; point at `specs/reports/<id>.preflight.txt` |
|
|
93
|
+
| `3` | non-convergent | the same blocking findings survived a fix pass; a higher `--max` will NOT help — the human needs to look at them (list them from the verdict) |
|
|
94
|
+
| `4` | not implementable | `/cohorte-build`'s readiness gate returned `NOT-READY` — the frozen spec cannot be built and **no agent ran**; Read `specs/reports/<id>.readiness.json` (small, structured) and relay its `gaps`, then point at `/cohorte-spec <id>`. More passes cannot fix this |
|
|
95
|
+
| `64` | usage | relay the script's own message verbatim |
|
|
96
|
+
|
|
97
|
+
Then print exactly three lines and nothing else — plus a fourth **only when the verdict carries
|
|
98
|
+
`deferred` > 0** (findings that were real but out of this feature's scope, parked in the backlog by
|
|
99
|
+
`/cohorte-review` §3.5; they are not blocking and never cost a pass, but they are not nothing either):
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
outcome: <one clause — clean / ceiling / no verdict / non-convergent / not implementable / usage>
|
|
103
|
+
iterations: <n> review pass(es)<, m fix pass(es) committed>
|
|
104
|
+
remaining: <blocking count + one short phrase per blocking item, or "none">
|
|
105
|
+
deferred: <n> parked in specs/refactor-backlog.md — /cohorte-refactor <domain> when you want them
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Add at most one follow-up sentence: the next command to run. Never restate a finding's fix, never
|
|
109
|
+
summarize the log, never open the diff. Each fix pass is already committed
|
|
110
|
+
(`loop(<id>): fix pass <i>`) — say so on a non-zero exit, since those commits are the way back.
|
|
@@ -4,7 +4,7 @@ description: Apply the refactor backlog for one or more domains via the surface
|
|
|
4
4
|
argument-hint: <domain…> (one or more surface keys, "shared", or "all")
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
You are the **lead**. Refactor domain **$ARGUMENTS** to match `PIPELINE.md`, using the `/audit` backlog.
|
|
7
|
+
You are the **lead**. Refactor domain **$ARGUMENTS** to match `PIPELINE.md`, using the `/cohorte-audit` backlog.
|
|
8
8
|
|
|
9
9
|
> Read `PIPELINE.md` §`surfaces` (map the domain → a surface + its agent + commands) and §`contract`.
|
|
10
10
|
>
|
|
@@ -50,7 +50,7 @@ slices import it, so refactor it alone, first.
|
|
|
50
50
|
After each agent returns: its surface's `test_quiet_cmd`/`lint_quiet_cmd` (else the `tail -40`
|
|
51
51
|
fallback — SCHEMA.md §Output discipline), `commands.typecheck`, `commands.format --check` (redirect
|
|
52
52
|
output to a file and grep it — don't print gate output into your context). Then verify each backlog item cleared by checking its `file:line` directly — do NOT re-run
|
|
53
|
-
`/audit` per round (that repeats the repo-wide gates + a review dispatch you don't need); one optional
|
|
54
|
-
final `/audit` once ALL dispatched domains are clean is enough. Check cleared items off in
|
|
53
|
+
`/cohorte-audit` per round (that repeats the repo-wide gates + a review dispatch you don't need); one optional
|
|
54
|
+
final `/cohorte-audit` once ALL dispatched domains are clean is enough. Check cleared items off in
|
|
55
55
|
`specs/refactor-backlog.md`. Loop until each dispatched domain is clean. Verification is per-domain
|
|
56
56
|
even when the dispatch was parallel — one failing surface loops alone, the others don't redo work.
|
|
@@ -13,7 +13,7 @@ You are the **lead**. Dispatch the review for feature **$ARGUMENTS**.
|
|
|
13
13
|
>
|
|
14
14
|
> **Workflow variant** (opt-in — SCHEMA.md §Workflows): on Claude Code ≥ 2.1.154 with workflows
|
|
15
15
|
> enabled, the human can ask to "run the review workflow" (`<core>/workflows/review.js`) instead.
|
|
16
|
-
> This conversational path stays the default and the fallback; `/doctor` shows which is available.
|
|
16
|
+
> This conversational path stays the default and the fallback; `/cohorte-doctor` shows which is available.
|
|
17
17
|
|
|
18
18
|
## 0. Deterministic pre-flight — no agents while red
|
|
19
19
|
|
|
@@ -27,7 +27,7 @@ with `test -x`); note the epoch (`date +%s`) in the same call — §3's metrics
|
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
- **Non-zero exit** ⇒ the script already printed the raw last-40 lines. **STOP: relay them verbatim
|
|
30
|
-
and spawn NO agent** — a compiler/test failure needs `/fix` (or the human), not a review that
|
|
30
|
+
and spawn NO agent** — a compiler/test failure needs `/cohorte-fix` (or the human), not a review that
|
|
31
31
|
rediscovers it at agent prices. This abort is the whole point of the step. Before stopping, write
|
|
32
32
|
the **aborted verdict** (§3's contract, degraded form) so an automated driver gets a diagnosis
|
|
33
33
|
rather than silence:
|
|
@@ -58,7 +58,7 @@ with `test -x`); note the epoch (`date +%s`) in the same call — §3's metrics
|
|
|
58
58
|
## 2. Dispatch review agents — one per touched surface, IN PARALLEL
|
|
59
59
|
|
|
60
60
|
Spawn ONE `review` agent per surface that has changed files, in a **single message** (one Task call
|
|
61
|
-
each, like `/build`) so they run concurrently — NEVER serially: review wall-clock must be the
|
|
61
|
+
each, like `/cohorte-build`) so they run concurrently — NEVER serially: review wall-clock must be the
|
|
62
62
|
slowest surface, not the sum. A diff touching a single surface ⇒ a single reviewer.
|
|
63
63
|
|
|
64
64
|
**Small-diff fast path (re-reviews only):** if a surface's staged diff is tiny (≤2 files and ≤~40
|
|
@@ -97,23 +97,24 @@ from no evidence at all (SCHEMA.md §Dead agents). So:
|
|
|
97
97
|
- **Silent twice ⇒ that surface is `unreviewed`.** Name it in the report under
|
|
98
98
|
`## NOT reviewed (no verdict on these)`, list it in the verdict JSON's `unreviewed`, and **refuse to
|
|
99
99
|
score `SHIP`** — the merged verdict is at least `REVISE`. Absence of evidence is not evidence of
|
|
100
|
-
absence, and it must never reach `/ship` or tick a DoD box.
|
|
100
|
+
absence, and it must never reach `/cohorte-ship` or tick a DoD box.
|
|
101
101
|
- **Never re-review the other surfaces** to compensate: their reports are valid and already on disk.
|
|
102
102
|
|
|
103
103
|
Then merge the returned reports into **one** REVIEW REPORT (same template): findings concatenated and
|
|
104
104
|
re-ordered by severity, counts summed, duplicates collapsed, verdict = the worst returned
|
|
105
105
|
(`BLOCK` > `REVISE` > `SHIP`). The `## Deferred` sections merge the same way (dedupe by
|
|
106
106
|
`file` + problem) and stay **out of the severity table and out of the verdict** — see §3.5, which
|
|
107
|
-
routes them. Append ONE metrics line for the batch to
|
|
108
|
-
(
|
|
109
|
-
|
|
107
|
+
routes them. Append ONE metrics line for the batch to the **main checkout's**
|
|
108
|
+
`$(dirname "$(git rev-parse --git-common-dir)")/.claude/pipeline-metrics.jsonl` (rules in
|
|
109
|
+
`/cohorte-build` §4; never a bare relative path — from a worktree that strands the lines): `{"ts":"<ISO>","feature":"$ARGUMENTS","phase":"review","seconds":<wall-clock>,"surfaces":{"<key>":"<verdict>:<finding count>",…}}`.
|
|
110
|
+
In the same Bash call, chain the opt-in usage ping (`/cohorte-build` §4, `phase: "review"`, results = the
|
|
110
111
|
merged verdict + total finding count, e.g. `"REVISE:3"`).
|
|
111
112
|
**Stage the full report to `specs/reports/$ARGUMENTS.md`** (overwrite) — a gitignored buffer so a
|
|
112
|
-
`/fix` after a `/clear` can still read the findings; the `specs/reports/` subfolder is skipped by the
|
|
113
|
+
`/cohorte-fix` after a `/clear` can still read the findings; the `specs/reports/` subfolder is skipped by the
|
|
113
114
|
non-recursive `specs/*.md` glob, so it's never mistaken for a spec (no phantom card, no bogus stage).
|
|
114
115
|
**Write the machine-readable verdict** to `specs/reports/$ARGUMENTS.verdict.json` (overwrite) — on
|
|
115
116
|
**every** run, including the small-diff fast path of §2 and a `SHIP`. This file is the ONLY contract
|
|
116
|
-
between the pipeline and an automated driver (`/
|
|
117
|
+
between the pipeline and an automated driver (`/cohorte-loop`), which parses no prose:
|
|
117
118
|
|
|
118
119
|
```json
|
|
119
120
|
{ "id": "$ARGUMENTS", "phase": "review", "ts": "<ISO>", "verdict": "REVISE",
|
|
@@ -151,17 +152,17 @@ Do this on **every** run, before the verdict branch below, and whatever the verd
|
|
|
151
152
|
finding that is only routed on a `SHIP` is a deferred finding lost on every other verdict, which is
|
|
152
153
|
exactly the leak this step closes. Append each merged `## Deferred` item to
|
|
153
154
|
**`specs/refactor-backlog.md`**, under the `## <domain>` heading of the surface that owns its
|
|
154
|
-
`file:line` (create the file and/or heading if absent — same grouping `/audit` writes, so
|
|
155
|
-
`/refactor <domain>` picks them up with no extra plumbing):
|
|
155
|
+
`file:line` (create the file and/or heading if absent — same grouping `/cohorte-audit` writes, so
|
|
156
|
+
`/cohorte-refactor <domain>` picks them up with no extra plumbing):
|
|
156
157
|
|
|
157
158
|
```
|
|
158
159
|
- [ ] <SEVERITY> · <file:line> · <quality|security|rule> · <concrete fix> · deferred:$ARGUMENTS
|
|
159
160
|
```
|
|
160
161
|
|
|
161
|
-
- **Never into the spec's `## Remediation`** — that list is what `/fix` re-dispatches and what `/
|
|
162
|
+
- **Never into the spec's `## Remediation`** — that list is what `/cohorte-fix` re-dispatches and what `/cohorte-loop`
|
|
162
163
|
waits on, so a deferred item there would re-trigger the very loop it was deferred out of.
|
|
163
164
|
- **Dedupe before appending:** `grep -F` the backlog for the item's `<file>` + the first words of its
|
|
164
|
-
problem; already there (from a prior round or an `/audit`) ⇒ skip it, don't stack duplicates round
|
|
165
|
+
problem; already there (from a prior round or an `/cohorte-audit`) ⇒ skip it, don't stack duplicates round
|
|
165
166
|
after round.
|
|
166
167
|
- Append with `>>` in ONE Bash call; never read the whole backlog into context to rewrite it (it grows
|
|
167
168
|
with every audit the repo has ever run).
|
|
@@ -175,27 +176,27 @@ would sit in this session's history, re-sent every turn). Then:
|
|
|
175
176
|
verdict *is* the pipeline's statement that the feature meets its Definition of
|
|
176
177
|
Done, so **tick the DoD**: in `specs/$ARGUMENTS.md` §`Acceptance criteria / DoD`, flip each `- [ ]`
|
|
177
178
|
→ `- [x]` for the criteria the pipeline has actually verified — spec conformance + `ui_language`
|
|
178
|
-
copy (this review), tests · lint · typecheck (a green `/build`), mobile-first as far as the code
|
|
179
|
+
copy (this review), tests · lint · typecheck (a green `/cohorte-build`), mobile-first as far as the code
|
|
179
180
|
shows it (this review). **Leave `- [ ]` (and say which) any item no stage actually verified** —
|
|
180
181
|
nothing in the pipeline *runs* the feature, so any criterion that needs the app up (runtime flows,
|
|
181
182
|
a visual check against the design) stays open unless the human says they exercised it by hand and
|
|
182
183
|
it held. Ticking is the lead's job
|
|
183
|
-
(the reviewer is read-only). **Then stamp the freshness gate** so `/ship` can refuse to ship code
|
|
184
|
+
(the reviewer is read-only). **Then stamp the freshness gate** so `/cohorte-ship` can refuse to ship code
|
|
184
185
|
edited after this verdict: compute `BASE=$(git merge-base <default_branch> HEAD)` and write into the
|
|
185
186
|
spec front-matter `reviewed_base: $BASE` plus
|
|
186
187
|
`reviewed_digest: $(git diff $BASE -- . ':(exclude)specs/' | sha256sum | cut -c1-16)` — the fingerprint
|
|
187
188
|
of exactly the source you just reviewed (specs excluded, so DoD ticks + the ship status flip don't
|
|
188
|
-
trip it). Then tell the human they can `/ship` — **recommend a `/clear` first**, the handoff is
|
|
189
|
+
trip it). Then tell the human they can `/cohorte-ship` — **recommend a `/clear` first**, the handoff is
|
|
189
190
|
fully on disk. **SHIP with leftover LOW findings** (or LOW+MEDIUM at the human's call) does NOT
|
|
190
191
|
force a fix cycle for nits: park them through §3.5's exact route (the backlog, under their surface's
|
|
191
192
|
domain heading, tagged `deferred:$ARGUMENTS` — never as open `## Remediation` items, which would
|
|
192
193
|
re-trigger the fix loop), keep the SHIP verdict and the freshness stamp, and let the human ship.
|
|
193
194
|
- **REVISE / BLOCK**, or any CRITICAL/HIGH/security finding → tell the human to run
|
|
194
|
-
**`/fix $ARGUMENTS`** — it appends the report to the spec's `## Remediation` and re-dispatches ONLY
|
|
195
|
+
**`/cohorte-fix $ARGUMENTS`** — it appends the report to the spec's `## Remediation` and re-dispatches ONLY
|
|
195
196
|
the surfaces with findings. (If they'd rather automate the rounds, the autonomous driver is
|
|
196
197
|
`disable-model-invocation: true` on purpose: **you cannot start it, they must type it**. Name the
|
|
197
198
|
exact line for them to type rather than attempting it — an attempt that silently fails reads as a
|
|
198
|
-
loop that is running when nothing is.) The full path (`/spec` Mode B then `/build`) remains for findings that
|
|
199
|
+
loop that is running when nothing is.) The full path (`/cohorte-spec` Mode B then `/cohorte-build`) remains for findings that
|
|
199
200
|
change the contract in ways that ripple into clean surfaces. _The report is staged to
|
|
200
|
-
`specs/reports/$ARGUMENTS.md`, so you can `/clear` before `/fix` — it reads the findings back from
|
|
201
|
+
`specs/reports/$ARGUMENTS.md`, so you can `/clear` before `/cohorte-fix` — it reads the findings back from
|
|
201
202
|
disk._
|
|
@@ -15,15 +15,15 @@ You are the **lead**. Ship feature **$ARGUMENTS**. This is the outward-facing ga
|
|
|
15
15
|
|
|
16
16
|
## 1. Pre-flight (confirm before doing anything irreversible)
|
|
17
17
|
|
|
18
|
-
- Confirm the latest `/review` returned **SHIP** (no CRITICAL, no security). If not reviewed, or the
|
|
18
|
+
- Confirm the latest `/cohorte-review` returned **SHIP** (no CRITICAL, no security). If not reviewed, or the
|
|
19
19
|
verdict was REVISE/BLOCK, stop and say so.
|
|
20
20
|
- **Freshness gate** — the reviewed code must be exactly what ships. If the spec front-matter carries
|
|
21
21
|
`reviewed_base` + `reviewed_digest`, recompute
|
|
22
22
|
`git diff <reviewed_base> -- . ':(exclude)specs/' | sha256sum | cut -c1-16` and compare to
|
|
23
23
|
`reviewed_digest`. **Match** ⇒ source unchanged since the SHIP verdict, proceed. **Mismatch** ⇒ source
|
|
24
24
|
(or the contract) was edited after review — the verdict is **stale**: stop and tell the human to re-run
|
|
25
|
-
`/review $ARGUMENTS` before shipping. Missing fields (spec predates the gate) ⇒ skip, don't block.
|
|
26
|
-
- **DoD gate (verify, don't tick — `/review` owns the ticking).** Read `specs/$ARGUMENTS.md`
|
|
25
|
+
`/cohorte-review $ARGUMENTS` before shipping. Missing fields (spec predates the gate) ⇒ skip, don't block.
|
|
26
|
+
- **DoD gate (verify, don't tick — `/cohorte-review` owns the ticking).** Read `specs/$ARGUMENTS.md`
|
|
27
27
|
§`Acceptance criteria / DoD`; if any item is still `- [ ]`, list the open ones and ask the human to
|
|
28
28
|
confirm shipping anyway (they may be deferred on purpose — e.g. a UI item on a backend-only feature).
|
|
29
29
|
All `- [x]` ⇒ proceed silently.
|
|
@@ -61,7 +61,7 @@ or an offset-limited Read around the match): exactly one card, under the `shippe
|
|
|
61
61
|
re-read the whole board into context. No board ⇒ skip silently.
|
|
62
62
|
|
|
63
63
|
**Telemetry — the usage ping that closes the funnel.** Chain it onto the verify call above
|
|
64
|
-
(`/build` §4's shared form, `<phase>` = `ship`, `<seconds>` = `0` — the release agent's duration is
|
|
64
|
+
(`/cohorte-build` §4's shared form, `<phase>` = `ship`, `<seconds>` = `0` — the release agent's duration is
|
|
65
65
|
not the pipeline's, `<results>` = `pr` when a PR was created / `compare` when only a compare URL was
|
|
66
66
|
emitted). Fire it **after** the release agent reports success, never on an aborted ship — a `ship`
|
|
67
67
|
event must mean the feature actually left the pipeline. No board ⇒ still ping, in its own `|| true`
|
|
@@ -70,7 +70,7 @@ call. Silent no-op without consent; never ask about consent here.
|
|
|
70
70
|
## 5. After the PR — CI gate + teardown
|
|
71
71
|
|
|
72
72
|
- If `host: github` and `gh` is available, watch the PR's checks (`gh pr checks <url> --watch`) and
|
|
73
|
-
report the result — the human merges only on green. A red check ⇒ back to `/fix $ARGUMENTS`.
|
|
73
|
+
report the result — the human merges only on green. A red check ⇒ back to `/cohorte-fix $ARGUMENTS`.
|
|
74
74
|
- Once the human confirms the PR is **merged**: if `isolation.enabled`, propose the teardown —
|
|
75
75
|
`scripts/remove-feature.sh $ARGUMENTS` (add `--drop-db` to also drop the feature db; kept by
|
|
76
76
|
default). It removes the worktree, deletes the merged branch, frees the slot. Never run it before
|
|
@@ -25,7 +25,7 @@ Detect the mode from the pasted content:
|
|
|
25
25
|
## Mode A — new spec (input is a brainstorm return, or empty)
|
|
26
26
|
|
|
27
27
|
1. If empty, look for a staged brainstorm return first — `specs/reports/*-brainstorm.md` (where
|
|
28
|
-
`/brainstorm` stages its output); one match ⇒ read it and confirm, several ⇒ ask which. None ⇒
|
|
28
|
+
`/cohorte-brainstorm` stages its output); one match ⇒ read it and confirm, several ⇒ ask which. None ⇒
|
|
29
29
|
ask the human to paste the return (or describe the feature) and wait.
|
|
30
30
|
2. Derive a `feature_id` (kebab-case slug). Confirm it.
|
|
31
31
|
2b. **Size budget — a spec is a contract, not a novel.** Target ≤ ~300 lines; hard-think at 500.
|
|
@@ -47,15 +47,15 @@ Detect the mode from the pasted content:
|
|
|
47
47
|
non-design surfaces never re-read the full brief on every dispatch).
|
|
48
48
|
4b. **New-surface heads-up.** If the feature clearly introduces an area no existing `surfaces[].path`
|
|
49
49
|
owns (a new service/app/top-level module), note it in the spec (a line in the relevant task section:
|
|
50
|
-
`> needs new surface: <proposed key/path>`). Don't render agents here — `/build` §1.5 auto-reconciles
|
|
51
|
-
it. This is just so the human isn't surprised when `/build` proposes a new agent.
|
|
50
|
+
`> needs new surface: <proposed key/path>`). Don't render agents here — `/cohorte-build` §1.5 auto-reconciles
|
|
51
|
+
it. This is just so the human isn't surprised when `/cohorte-build` proposes a new agent.
|
|
52
52
|
5. When the human validates, **freeze**: write `specs/<id>.md` (`status: frozen`, front-matter filled).
|
|
53
53
|
Create the file — do not ask the human to. **Postcondition:** `grep -q '^status: frozen' specs/<id>.md`
|
|
54
|
-
— if it fails the freeze didn't land; fix it before pointing the human at `/build`. Chain the
|
|
55
|
-
opt-in usage ping onto the postcondition's Bash call (`/build` §4's shared form, `<phase>` =
|
|
54
|
+
— if it fails the freeze didn't land; fix it before pointing the human at `/cohorte-build`. Chain the
|
|
55
|
+
opt-in usage ping onto the postcondition's Bash call (`/cohorte-build` §4's shared form, `<phase>` =
|
|
56
56
|
`spec`, `<seconds>` = `0` — interactive time, not pipeline wall-clock, `<results>` = `frozen`).
|
|
57
57
|
Ping only on a **landed** freeze, so the funnel counts specs that exist, not attempts. Mode B does
|
|
58
|
-
not ping — it re-enters an already-counted spec, and `/fix` covers that loop. Silent no-op without
|
|
58
|
+
not ping — it re-enters an already-counted spec, and `/cohorte-fix` covers that loop. Silent no-op without
|
|
59
59
|
consent; never ask about consent here.
|
|
60
60
|
5b. **Record the transverse decisions — the journal, not a summary.** Walk what the interview settled
|
|
61
61
|
and keep ONLY the decisions that **outlive this feature**: a rule the next spec would otherwise
|
|
@@ -67,7 +67,7 @@ Detect the mode from the pasted content:
|
|
|
67
67
|
`- <YYYY-MM-DD> · <area> · <decision> — because <reason> · <feature_id>`
|
|
68
68
|
- **Never** duplicate what §5, `PIPELINE.md` §Conventions or the code already states — the journal
|
|
69
69
|
carries the *non-obvious rule*, not the feature's content. A line that restates a spec section is
|
|
70
|
-
a line every future `/spec` pays for and learns nothing from.
|
|
70
|
+
a line every future `/cohorte-spec` pays for and learns nothing from.
|
|
71
71
|
- **Contradicting an existing line** is allowed but never silent: tell the human which line this
|
|
72
72
|
feature overrides, get their go-ahead, then append the new line with
|
|
73
73
|
`· supersedes <YYYY-MM-DD> <area>` and move the old one to `## Superseded`.
|
|
@@ -79,28 +79,28 @@ Detect the mode from the pasted content:
|
|
|
79
79
|
- **Write it to `specs/design/<id>.md`** (the authored artifact, versioned with the spec; spec §8
|
|
80
80
|
holds the summary + pointer). Create the file — do not ask the human to. Keep it in the
|
|
81
81
|
`specs/design/` subfolder, **not** `specs/<id>....md`: the `specs/*.md` glob that drives the
|
|
82
|
-
kanban backfill and `/doctor` is non-recursive, so a brief in the subfolder never gets mistaken
|
|
82
|
+
kanban backfill and `/cohorte-doctor` is non-recursive, so a brief in the subfolder never gets mistaken
|
|
83
83
|
for a spec (no phantom card, no bogus stage). Overwrite it on every freeze.
|
|
84
84
|
- Print ONLY the path + a one-line summary — never echo the brief into chat (it would sit in this
|
|
85
85
|
session's history; echo it only if the human asks). Tell the human: copy it from
|
|
86
86
|
`specs/design/<id>.md` into the design tool (if any — typically a fresh design project for this
|
|
87
|
-
feature), then run `/build <id>` and hand its design gate the resulting page link(s) — a full
|
|
87
|
+
feature), then run `/cohorte-build <id>` and hand its design gate the resulting page link(s) — a full
|
|
88
88
|
`https://claude.ai/design/p/<projectId>?file=<file>` link carries its own project + page, no
|
|
89
89
|
profile change needed. (They can also paste the links into the spec's `design_files` themselves.)
|
|
90
|
-
**Recommend a `/clear` before `/build`** — the frozen spec + `specs/design/<id>.md` are the whole
|
|
90
|
+
**Recommend a `/clear` before `/cohorte-build`** — the frozen spec + `specs/design/<id>.md` are the whole
|
|
91
91
|
handoff.
|
|
92
92
|
|
|
93
93
|
## Mode B — review return (input is a REVIEW REPORT)
|
|
94
94
|
|
|
95
95
|
1. Read the report — pasted as input, or (whenever nothing is pasted) read from
|
|
96
|
-
`specs/reports/<id>.md`, where `/review` stages its last report. Identify `feature_id` from its
|
|
96
|
+
`specs/reports/<id>.md`, where `/cohorte-review` stages its last report. Identify `feature_id` from its
|
|
97
97
|
header; open `specs/<id>.md`.
|
|
98
98
|
2. Append each finding to the spec's **`## Remediation`**, one per line:
|
|
99
99
|
`- [ ] <severity> · <file:line> · <spec-violation|quality|security> · <concrete fix>`
|
|
100
100
|
(Keep prior items; add the new round under a dated/numbered subheading.)
|
|
101
101
|
3. If a finding implies the **contract** must change, update §5 and flag it so the lead re-authors the
|
|
102
102
|
contract file.
|
|
103
|
-
4. Set `status: in-review`. Tell the human to run `/build <id>` to re-dispatch fresh agents.
|
|
104
|
-
**Recommend a `/clear` before `/build`** — the spec is the whole handoff.
|
|
103
|
+
4. Set `status: in-review`. Tell the human to run `/cohorte-build <id>` to re-dispatch fresh agents.
|
|
104
|
+
**Recommend a `/clear` before `/cohorte-build`** — the spec is the whole handoff.
|
|
105
105
|
|
|
106
106
|
In both modes the spec is the single source of truth; agents are stateless and read only it + the diff.
|