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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: <SURFACE_AGENT>
|
|
3
|
-
description: Implements the <SURFACE_LABEL> surface (<SURFACE_PATH>) for one feature, strictly from the frozen spec + contract, test-first TDD. Dispatched by /build. Touches only its own surface.
|
|
3
|
+
description: Implements the <SURFACE_LABEL> surface (<SURFACE_PATH>) for one feature, strictly from the frozen spec + contract, test-first TDD. Dispatched by /cohorte-build. Touches only its own surface.
|
|
4
4
|
tools: <SURFACE_TOOLS>
|
|
5
5
|
model: <SURFACE_MODEL>
|
|
6
6
|
---
|
|
@@ -14,7 +14,7 @@ shared surface is the frozen contract and the spec.
|
|
|
14
14
|
> (§Conventions/§Testing): your slice of them is baked into this file below (§Your conventions),
|
|
15
15
|
> rendered from the profile — re-reading the prose every dispatch is exactly the cost the bake
|
|
16
16
|
> removes. If the baked slice visibly contradicts `PIPELINE.md`, say so in your handoff: the profile
|
|
17
|
-
> wins, and this agent file needs a re-render (`/update-pipeline`).
|
|
17
|
+
> wins, and this agent file needs a re-render (`/cohorte-update-pipeline`).
|
|
18
18
|
|
|
19
19
|
## You own
|
|
20
20
|
|
|
@@ -22,7 +22,7 @@ shared surface is the frozen contract and the spec.
|
|
|
22
22
|
|
|
23
23
|
## Your conventions (baked from `PIPELINE.md` at render time)
|
|
24
24
|
|
|
25
|
-
<!-- Rendered by /init-pipeline (and refreshed by /update-pipeline's reconcile) from
|
|
25
|
+
<!-- Rendered by /cohorte-init-pipeline (and refreshed by /cohorte-update-pipeline's reconcile) from
|
|
26
26
|
§Conventions `### Shared` + `### Surface: <your key>` + your §Testing lines.
|
|
27
27
|
Edit conventions in PIPELINE.md, never here — this block is regenerated. -->
|
|
28
28
|
|
package/core/agents/release.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: release
|
|
3
|
-
description: Commits, pushes, and opens the PR for a SHIP-verified feature. Dispatched by /ship at the SHIP gate. Drafts the conventional commit + PR body from the spec and diff. Never edits source.
|
|
3
|
+
description: Commits, pushes, and opens the PR for a SHIP-verified feature. Dispatched by /cohorte-ship at the SHIP gate. Drafts the conventional commit + PR body from the spec and diff. Never edits source.
|
|
4
4
|
tools: Read, Grep, Glob, Bash
|
|
5
5
|
model: haiku
|
|
6
6
|
---
|
package/core/agents/review.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: review
|
|
3
|
-
description: Read-only reviewer. Compares the implementation against the frozen spec, then audits code quality, security, and (if the profile declares it) mobile-first. Emits the REVIEW REPORT. Dispatched by /review — one per touched surface on multi-surface diffs. Cannot modify anything.
|
|
3
|
+
description: Read-only reviewer. Compares the implementation against the frozen spec, then audits code quality, security, and (if the profile declares it) mobile-first. Emits the REVIEW REPORT. Dispatched by /cohorte-review — one per touched surface on multi-surface diffs. Cannot modify anything.
|
|
4
4
|
tools: Read, Grep, Glob, mcp__serena
|
|
5
5
|
model: sonnet
|
|
6
6
|
---
|
|
@@ -66,7 +66,7 @@ Concrete, high-signal traps to grep for per language. A surface's language comes
|
|
|
66
66
|
- **SQL / migrations** — `UPDATE`/`DELETE` with no `WHERE`; N+1 (a query inside a loop that a JOIN
|
|
67
67
|
would collapse); foreign-key columns joined/filtered without an index.
|
|
68
68
|
|
|
69
|
-
## Audit mode (no feature spec — codebase refactor, dispatched by `/audit`)
|
|
69
|
+
## Audit mode (no feature spec — codebase refactor, dispatched by `/cohorte-audit`)
|
|
70
70
|
|
|
71
71
|
When given a **path/domain instead of a feature spec**, skip step 1 and audit the target against
|
|
72
72
|
`PIPELINE.md` §Conventions as the rulebook: conventions per surface, TDD coverage (list every
|
|
@@ -81,6 +81,24 @@ domain** (same finding-line shape) instead of a SHIP/REVISE/BLOCK verdict.
|
|
|
81
81
|
- Any **security vulnerability** ⇒ verdict **BLOCK**.
|
|
82
82
|
- No CRITICAL and no security issue ⇒ verdict **SHIP**.
|
|
83
83
|
|
|
84
|
+
## Deferred — real, but not this feature's problem
|
|
85
|
+
|
|
86
|
+
A finding is **deferred** when it is genuinely true and genuinely **out of this feature's scope**:
|
|
87
|
+
pre-existing code the staged diff did not touch, adjacent debt the spec never claims to fix, a
|
|
88
|
+
convention violation that predates this work. Deferring is not softening — it is naming the right
|
|
89
|
+
owner. The lead routes deferred findings to `specs/refactor-backlog.md` (they feed `/cohorte-refactor`), so
|
|
90
|
+
they are **never lost and never cost a fix loop**.
|
|
91
|
+
|
|
92
|
+
- **Deferred findings are separate from your findings list** and count in **no** severity row: the
|
|
93
|
+
severity table drives the verdict, and a deferred item must never force one.
|
|
94
|
+
- **Deferrable:** a problem entirely in lines/files the diff did not change, whose fix is not required
|
|
95
|
+
by any acceptance criterion of this spec.
|
|
96
|
+
- **NOT deferrable, ever:** anything the diff touched or introduced; any spec violation; any
|
|
97
|
+
**security** issue on a path this feature adds, calls or modifies (a pre-existing hole this feature
|
|
98
|
+
now exposes to new traffic is this feature's problem). When in doubt, it is a finding, not a deferral.
|
|
99
|
+
- Cap the deferred list at **10 lines**, worst first; each carries its own out-of-scope reason so the
|
|
100
|
+
lead can route it without re-reading anything.
|
|
101
|
+
|
|
84
102
|
## Your return — the REVIEW REPORT, exactly this shape
|
|
85
103
|
|
|
86
104
|
Every finding must be **self-sufficient for a stateless agent**: `file:line` · severity ·
|
|
@@ -110,6 +128,11 @@ Verdict: <SHIP | REVISE | BLOCK>
|
|
|
110
128
|
- **[<SEVERITY>]** `<file>:<line>` · <spec-violation|quality|security> · <problem> → **Fix:** <concrete change>
|
|
111
129
|
(order by severity; "None." if none; max 20 lines, one per finding, no code excerpts)
|
|
112
130
|
|
|
131
|
+
## Deferred
|
|
132
|
+
|
|
133
|
+
- **[<SEVERITY>]** `<file>:<line>` · <quality|security> · <problem> → **Fix:** <concrete change> · out of scope: <why this feature does not own it>
|
|
134
|
+
(real but out of this feature's scope — see §Deferred; worst first; "None." if none; max 10 lines)
|
|
135
|
+
|
|
113
136
|
## Notes
|
|
114
137
|
(ONLY the RBAC / mobile-first assessment when the profile enables them; omit the section otherwise)
|
|
115
138
|
```
|
|
@@ -5,9 +5,11 @@ argument-hint: [path or domain, default = whole repo]
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
You are the **lead**. Audit **$ARGUMENTS** (default: whole repo) to drive it to a clean base. Read +
|
|
8
|
-
analyze only — no fixes (those go through `/refactor`).
|
|
8
|
+
analyze only — no fixes (those go through `/cohorte-refactor`).
|
|
9
9
|
|
|
10
|
-
> Read `PIPELINE.md` §`commands` (the mechanical gates), `surfaces`, and §Conventions
|
|
10
|
+
> Read `PIPELINE.md` §`commands` (the mechanical gates), `surfaces`, and §Conventions — plus
|
|
11
|
+
> `specs/_decisions.md` §Live if it exists (SCHEMA.md §Decisions): those standing decisions are part
|
|
12
|
+
> of the rulebook you audit against, and code that contradicts one is a finding like any other.
|
|
11
13
|
>
|
|
12
14
|
> **Workflow variant** (opt-in — SCHEMA.md §Workflows): on Claude Code ≥ 2.1.154 with workflows
|
|
13
15
|
> enabled, the human can ask to "run the audit workflow" (`<core>/workflows/audit.js` — one auditor
|
|
@@ -39,5 +41,11 @@ from your instructions), grouped by domain (one group per surface + shared). —
|
|
|
39
41
|
Merge mechanical + convention findings into one prioritized backlog and **write
|
|
40
42
|
`specs/refactor-backlog.md`**, grouped by domain, each item:
|
|
41
43
|
`- [ ] <SEVERITY> · <file:line> · <rule|tdd|lint|format|type|security> · <concrete fix>`
|
|
44
|
+
|
|
45
|
+
**Carry over the deferred items** before overwriting: `grep -n 'deferred:' specs/refactor-backlog.md`
|
|
46
|
+
and re-emit every **open** (`- [ ]`) match verbatim under its domain, tag included. Those lines were
|
|
47
|
+
put there by `/cohorte-review` §3.5 — a real finding a feature deliberately did not own — and an audit that
|
|
48
|
+
blindly overwrites the file is the one way they silently disappear. Already-ticked (`- [x]`) ones are
|
|
49
|
+
done: drop them.
|
|
42
50
|
Print a short summary (counts per domain + top items). Tell the human: refactor a domain with
|
|
43
|
-
`/refactor <domain>`.
|
|
51
|
+
`/cohorte-refactor <domain>`.
|
|
@@ -11,6 +11,12 @@ at Finish, when a board is configured.
|
|
|
11
11
|
> Read `PIPELINE.md` §Personas (the panel) and §`rbac` first. If `rbac.enabled`, the panel must
|
|
12
12
|
> pressure-test the idea so it serves **every** role, not just admins.
|
|
13
13
|
>
|
|
14
|
+
> Also read `specs/_decisions.md` §Live if it exists (SCHEMA.md §Decisions) — one line per standing
|
|
15
|
+
> decision. The panel argues about the idea, not about settled ground: a persona that proposes
|
|
16
|
+
> something a live line already decided must be told so by another persona, and an idea that genuinely
|
|
17
|
+
> needs to overturn one must say which line, out loud, so the human decides it here rather than
|
|
18
|
+
> discovering the contradiction at `/cohorte-spec`.
|
|
19
|
+
>
|
|
14
20
|
> Template paths below (`.claude/templates/…`) resolve to `~/.claude/templates/…` when the core is
|
|
15
21
|
> installed globally — read whichever exists.
|
|
16
22
|
>
|
|
@@ -41,8 +47,8 @@ screens, risks, and what's explicitly out.
|
|
|
41
47
|
|
|
42
48
|
When the human is satisfied, produce the **brainstorm return** by filling
|
|
43
49
|
`.claude/templates/brainstorm-return.md` and **staging it to
|
|
44
|
-
`specs/reports/<feature_id>-brainstorm.md`** (the gitignored buffer dir — `/spec` reads it from there
|
|
45
|
-
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`
|
|
46
52
|
— **recommend a `/clear` first**, the return is staged on disk (pasting it remains a fallback).
|
|
47
53
|
|
|
48
54
|
**Kanban:** settle the `feature_id` (kebab-case slug) the return carries — it is the card's join key
|
|
@@ -50,7 +56,7 @@ downstream. If a board is configured, **move** the card into the **Brainstorm**
|
|
|
50
56
|
`#<feature_id>` (per §Kanban): the picked Ideas card if the human chose one, else a new card. No-op if
|
|
51
57
|
no board.
|
|
52
58
|
|
|
53
|
-
**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,
|
|
54
60
|
`<phase>` = `brainstorm`, `<seconds>` = `0` (this phase is human thinking time, not pipeline
|
|
55
61
|
wall-clock — the funnel signal is the event, not its duration), `<results>` = `""`. No board ⇒ still
|
|
56
62
|
ping, in its own `|| true` call. Silent no-op without consent; never ask about consent here.
|
|
@@ -16,14 +16,17 @@ You are the **lead**. Build feature **$ARGUMENTS** from its frozen spec.
|
|
|
16
16
|
## 1. Load & check
|
|
17
17
|
|
|
18
18
|
- Check the spec front-matter FIRST — `grep '^status:' specs/$ARGUMENTS.md` (or Read with a ~15-line
|
|
19
|
-
limit) — before any full read.
|
|
20
|
-
|
|
19
|
+
limit) — before any full read. Buildable statuses are `frozen`, `in-review` and `in-progress` (the
|
|
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
|
+
continue this build. Anything else (`draft`, missing, `shipped`) ⇒ stop and tell the human to run
|
|
23
|
+
`/cohorte-spec` first. Only then read the body, selectively: front-matter, §5 contract, the surface
|
|
21
24
|
task sections, and `## Remediation` (fall back to a full read if the spec doesn't follow the
|
|
22
25
|
template's headings).
|
|
23
26
|
- **Route check** — if `## Remediation` has open `- [ ]` items and none requires a contract change,
|
|
24
|
-
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
|
|
25
28
|
findings. A full build with open items is only right when the contract change ripples into clean
|
|
26
|
-
surfaces (the case `/fix` §1 falls back here for).
|
|
29
|
+
surfaces (the case `/cohorte-fix` §1 falls back here for).
|
|
27
30
|
- **Design gate** — only if `design.enabled` and the feature has UI (some surface `uses_design`): if the
|
|
28
31
|
spec front-matter `design_files` is empty, ask the human for the feature's design **links** and store
|
|
29
32
|
them in `design_files`, then continue. Each entry is a full self-contained link of the form
|
|
@@ -53,9 +56,62 @@ For each surface to add: infer its `key`, `path`, `label`, `agent`, `tools`, `mo
|
|
|
53
56
|
SCHEMA.md §"Rendering / reconciling a surface agent" — write the `surfaces[]` entry + §Conventions/§Testing
|
|
54
57
|
stanza into `PIPELINE.md`, render `.claude/agents/<agent>.md` from the implementer template, applying the
|
|
55
58
|
shared-code rule (shared trees get a single-owner surface; cross-slice shapes go through the contract).
|
|
56
|
-
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,
|
|
57
60
|
say so and continue. Dispatch (§3) then covers the reconciled surface list.
|
|
58
61
|
|
|
62
|
+
**Adding or splitting a surface is an architectural decision** — append ONE line for it to
|
|
63
|
+
`specs/_decisions.md` §Live (SCHEMA.md §Decisions; create from `.claude/templates/decisions.template.md`
|
|
64
|
+
if absent), area `surfaces`, e.g.
|
|
65
|
+
`- <date> · surfaces · <key> owns <path>, single owner of <what> — because <the boundary reason> · $ARGUMENTS`.
|
|
66
|
+
One `>>` in the Bash call you're already making. Nothing added ⇒ nothing to append.
|
|
67
|
+
|
|
68
|
+
## 1.6 Readiness verdict — the gate before N dispatches
|
|
69
|
+
|
|
70
|
+
**Zero extra agents: you already hold the spec, the profile and the reconciled surface list.** The
|
|
71
|
+
whole point is that a bancal spec costs one verdict here instead of N implementers discovering it in
|
|
72
|
+
parallel. Judge the frozen contract on **implementability only** — never on whether the feature is a
|
|
73
|
+
good idea (that was `/cohorte-brainstorm`), never by re-reading files you don't already need:
|
|
74
|
+
|
|
75
|
+
1. **Contract completeness** (§5) — every endpoint/interface has method+path (or signature), auth,
|
|
76
|
+
request fields with types + validation, the success shape, and its error cases. A missing
|
|
77
|
+
**request or success shape** ⇒ `NOT-READY` (an implementer would invent it, and the other surface
|
|
78
|
+
would invent a different one). A missing **error case** ⇒ `RESERVATIONS`.
|
|
79
|
+
2. **Surface coverage** — every §6 task maps to a surface in the reconciled list, and every contract
|
|
80
|
+
entry has an owner **on each side it names** (producer and consumer). A contract entry no surface
|
|
81
|
+
owns ⇒ `NOT-READY`.
|
|
82
|
+
3. **Dependencies exist** — for the modules, packages, tables, env vars and shared helpers the spec
|
|
83
|
+
names as *pre-existing*: verify them in ONE Bash call (`test -f` / `grep -l` / a package-manifest
|
|
84
|
+
grep, output redirected — never a file read per name). Named as pre-existing but absent, and not
|
|
85
|
+
listed as created by this feature ⇒ `NOT-READY`.
|
|
86
|
+
4. **Residual ambiguity** (§10) — an open question a surface would have to *guess* at: blocks a
|
|
87
|
+
contract decision ⇒ `NOT-READY`; merely narrows an implementation choice ⇒ `RESERVATIONS`.
|
|
88
|
+
5. **Design gate** — a `uses_design` surface in scope with `design_files` still empty ⇒ `NOT-READY`
|
|
89
|
+
(this is §1's gate restated as a verdict, so an automated driver sees the same fact).
|
|
90
|
+
|
|
91
|
+
Write the machine-readable verdict to `specs/reports/$ARGUMENTS.readiness.json` (overwrite,
|
|
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
|
+
which parses no prose:
|
|
95
|
+
|
|
96
|
+
```json
|
|
97
|
+
{ "id": "$ARGUMENTS", "phase": "readiness", "ts": "<ISO>", "verdict": "RESERVATIONS",
|
|
98
|
+
"gaps": ["contract|POST /orders|no 409 case for a duplicate id"],
|
|
99
|
+
"surfaces": ["backend", "frontend"] }
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
- **`gaps`** — one normalized string per gap, `<check>|<where>|<what is missing>`: `<check>` is
|
|
103
|
+
`contract` · `coverage` · `dependency` · `ambiguity` · `design`; `<where>` is the contract entry,
|
|
104
|
+
surface key or dependency name (no `:line` — it shifts on every edit); `<what>` is the gap, not the
|
|
105
|
+
fix. `READY` ⇒ `[]`.
|
|
106
|
+
- **`NOT-READY` ⇒ STOP: author no contract and spawn NO agent.** Print the gaps and send the human to
|
|
107
|
+
`/cohorte-spec $ARGUMENTS` to patch the contract, then re-run `/cohorte-build`. This abort is the whole point of the
|
|
108
|
+
step — a spec that cannot be built does not get cheaper by being built N times in parallel.
|
|
109
|
+
- **`RESERVATIONS` ⇒ continue.** It never blocks (a gate that stalls a sound build on a missing error
|
|
110
|
+
case would cost more human round-trips than it saves): inline each gap verbatim into the dispatch of
|
|
111
|
+
the surface it affects, as an explicit assumption the agent must implement *and* flag in its handoff,
|
|
112
|
+
and relay the list to the human in one line each.
|
|
113
|
+
- **`READY` ⇒ continue silently** — one line, no restatement.
|
|
114
|
+
|
|
59
115
|
## 2. Author the contract (lead-only — the single sync channel)
|
|
60
116
|
|
|
61
117
|
_Only if `contract.enabled`._ From §5 of the spec, write/update the feature's contract file at
|
|
@@ -87,28 +143,57 @@ tree. For each surface in `surfaces`:
|
|
|
87
143
|
> via `DesignSync get_file`, build mobile-first · or `none` (non-design surface, or a fix loop whose
|
|
88
144
|
> open items are all non-visual)>. Open Remediation items for YOUR surface (self-contained — fix
|
|
89
145
|
> exactly these, reading only the files they name; `none` ⇒ first build, implement the spec's tasks
|
|
90
|
-
> for your surface): <the surface's open `- [ ]` lines verbatim, or `none`>.
|
|
146
|
+
> for your surface): <the surface's open `- [ ]` lines verbatim, or `none`>. Readiness gaps for YOUR
|
|
147
|
+
> surface (§1.6 `RESERVATIONS` — the spec is silent here: implement the stated assumption and flag what
|
|
148
|
+
> you assumed in your handoff): <that surface's `gaps` entries verbatim, or `none`>."
|
|
149
|
+
|
|
150
|
+
## 3.5 Roll call — account for EVERY dispatch before integrating
|
|
151
|
+
|
|
152
|
+
A subagent can die: a rate limit mid-run, a transport error after retries, its own context exhausted.
|
|
153
|
+
When it does, it returns **nothing** — and nothing is byte-identical to "a clean surface with nothing
|
|
154
|
+
to report". Silence is not a green light; treat it as the failure it is (SCHEMA.md §Dead agents).
|
|
155
|
+
|
|
156
|
+
- **Roll call.** Every surface you dispatched in §3 must come back with a handoff in the format its
|
|
157
|
+
agent instructions define. Missing, empty, or truncated mid-sentence ⇒ that surface is **dead**.
|
|
158
|
+
- **Never infer success from silence,** and never speak for a dead agent — you did not see its work.
|
|
159
|
+
- **Retry that surface ONCE, alone.** Re-dispatch it with the byte-identical §3 prompt. The other
|
|
160
|
+
surfaces' work is already on disk and untouched, so this costs one agent, not a rebuild — and most
|
|
161
|
+
deaths are transient. Never retry a surface that *did* answer.
|
|
162
|
+
- **Died twice ⇒ stop guessing and look.** Run that surface's own quiet commands
|
|
163
|
+
(`<surface>.typecheck_cmd`, `lint_quiet_cmd`, `test_quiet_cmd`) with output redirected to
|
|
164
|
+
`specs/reports/$ARGUMENTS.<key>.deadcheck.txt`, then grep it — never into your context. Report the
|
|
165
|
+
three results plus which of the spec's tasks for that surface actually landed, checked against the
|
|
166
|
+
tree, not against a handoff you never got. Say plainly that the surface is **unverified**.
|
|
91
167
|
|
|
92
168
|
## 4. Integrate
|
|
93
169
|
|
|
94
170
|
When all return, flag any contract mismatch or failing test from the handoffs; otherwise print one
|
|
95
171
|
status line per surface (`<key> · tests pass/fail · <n> TODOs`) — do not restate handoff content.
|
|
172
|
+
A dead surface (§3.5) prints `<key> · DEAD — unverified` and **the batch is never reported as ok**.
|
|
96
173
|
Append **ONE line for the batch** to the **main checkout's** `.claude/pipeline-metrics.jsonl` —
|
|
97
174
|
NOT the worktree's, which dies at teardown while metrics must accumulate across features. Resolve
|
|
98
175
|
it from anywhere: `$(dirname "$(git rev-parse --git-common-dir)")/.claude/pipeline-metrics.jsonl`
|
|
99
176
|
(in the main checkout this resolves to itself). Create it if absent; it must be gitignored.
|
|
100
177
|
Compute the elapsed time in the same Bash call
|
|
101
178
|
(`echo "{...\"seconds\":$(($(date +%s)-<start epoch from §2>)),...}" >> …`):
|
|
102
|
-
`{"ts":"<ISO date>","feature":"$ARGUMENTS","phase":"build","seconds":<wall-clock>,"surfaces":{"<key>":"ok|error",…}}`
|
|
179
|
+
`{"ts":"<ISO date>","feature":"$ARGUMENTS","phase":"build","seconds":<wall-clock>,"surfaces":{"<key>":"ok|error|dead",…}}`
|
|
180
|
+
— **write this line even when a surface died.** An incomplete batch is exactly the batch worth having
|
|
181
|
+
in the record; skipping the append to "wait until it's complete" silently deletes the evidence that
|
|
182
|
+
anything went wrong. In the same call write the machine-readable batch result to
|
|
183
|
+
`specs/reports/$ARGUMENTS.build.json` (overwrite) — the channel an automated driver reads, since it
|
|
184
|
+
never sees your chat:
|
|
185
|
+
`{"id":"$ARGUMENTS","phase":"build","ts":"<ISO>","surfaces":{"<key>":"ok|error|dead",…},"dead":["<key>",…]}`
|
|
103
186
|
— this is the evidence SCHEMA.md §Specialization asks for before splitting a surface. In the same
|
|
104
187
|
Bash call, chain the opt-in usage ping — **the shared form every phase command reuses**:
|
|
105
188
|
`<core>/pipeline/scripts/telemetry-send.sh <phase> "$ARGUMENTS" <seconds> "<results>" || true`
|
|
106
189
|
(`<core>` = `~/.claude` global / `.claude` bundled; here `<phase>` = `build`, `<results>` =
|
|
107
190
|
`<ok,ok|error,…>`) — a silent no-op unless the human explicitly consented (SCHEMA.md §Telemetry);
|
|
108
|
-
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
|
|
109
192
|
phase + results. The `|| true` swallows a **missing** script too, so a half-copied core goes
|
|
110
|
-
silent rather than loud — `/doctor` check 1 is what catches that.
|
|
111
|
-
Then tell the human: exercise the feature by hand if it's worth it, then run `/review $ARGUMENTS
|
|
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).
|
|
112
197
|
Do not run the app or migrations yourself here — building is not running.
|
|
113
198
|
**Recommend a `/clear` now** — the spec, contract and diff are all on
|
|
114
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:
|
|
@@ -84,11 +92,16 @@ fix only with the human's go-ahead (or hand them the command).
|
|
|
84
92
|
End the check with ONE summary line, e.g.
|
|
85
93
|
`workflows: available (opt-in — ask to "run the review workflow")` or
|
|
86
94
|
`workflows: unavailable (<first failing prerequisite>) — conversational commands (the default)`.
|
|
87
|
-
9. **Specs & metrics.** Every `specs/*.md` front-matter `status` is a valid stage —
|
|
88
|
-
`
|
|
89
|
-
|
|
95
|
+
9. **Specs & metrics.** Every `specs/*.md` front-matter `status` is a valid stage — one of
|
|
96
|
+
`draft · frozen · in-progress · in-review · shipped · blocked` (SCHEMA.md §Spec status; the last two
|
|
97
|
+
are written by the `/cohorte-loop` driver, so flagging them would report the pipeline's own state as a
|
|
98
|
+
defect) — excluding
|
|
99
|
+
`_`-prefixed files (the spec template and `specs/_decisions.md`, the decision journal) and
|
|
100
|
+
`specs/refactor-backlog.md`, which `/cohorte-audit` writes as a backlog, not a
|
|
101
|
+
spec, and which has no front-matter to check. A spec left `in-progress`/`blocked` with
|
|
102
|
+
`loop_pass` > 0 is a loop that never finished ⇒ say so and name `/cohorte-loop <id> --resume`. `shipped` specs
|
|
90
103
|
with a live worktree flagged (see 6). `.claude/pipeline-metrics.jsonl` and `specs/reports/` (the
|
|
91
|
-
`/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
|
|
92
105
|
belong to the **main checkout** — a `pipeline-metrics.jsonl` inside a live feature worktree is a
|
|
93
106
|
stale-core sign (its lines die at teardown) ⇒ suggest appending its lines to the main checkout's
|
|
94
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
|
|
@@ -50,11 +50,16 @@ that change the *contract*; `/fix` is for everything else.
|
|
|
50
50
|
|
|
51
51
|
When the agents return:
|
|
52
52
|
|
|
53
|
+
- **Roll call first (SCHEMA.md §Dead agents).** A re-dispatched agent that returns nothing has fixed
|
|
54
|
+
nothing you can verify. Retry that surface ONCE with the byte-identical dispatch; still silent ⇒ leave
|
|
55
|
+
**every one of its items `- [ ]`** (a dead agent never ticks a box — that would hide an open finding
|
|
56
|
+
from the next round and from the driver), print `<key> · DEAD — items untouched`, and say the surface
|
|
57
|
+
is unverified.
|
|
53
58
|
- **Tick the resolved items.** Each handoff's `## Remediation addressed` lists what that agent fixed
|
|
54
59
|
(by `file:line`). For every Remediation item an agent reports fixed, flip its `- [ ]` → `- [x]` in
|
|
55
60
|
`specs/<id>.md` and append a terse ` — fixed: <what/where>` note (the convention prior rounds already
|
|
56
61
|
use). Leave genuinely-unaddressed items `- [ ]` so the next loop still sees them. This keeps the
|
|
57
|
-
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
|
|
58
63
|
here is the lead's job — surface agents own only their tree, never the spec.
|
|
59
64
|
- **Collapse fully-resolved rounds (keep the spec bounded).** When a whole dated Remediation round is now
|
|
60
65
|
entirely `- [x]`, replace its item lines with a single summary line (`- <date> — <N> findings, all
|
|
@@ -62,10 +67,12 @@ When the agents return:
|
|
|
62
67
|
re-reads each loop. Keep any round with ≥1 still-open `- [ ]` item fully expanded (§2's skip logic
|
|
63
68
|
needs those checkboxes).
|
|
64
69
|
- Print one status line per surface (`<key> · items fixed <n>/<m> · tests pass/fail`) — do not restate
|
|
65
|
-
handoff content — and append ONE metrics line for the batch to
|
|
66
|
-
(
|
|
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
|
|
67
74
|
(results = items fixed over items found across surfaces, e.g. `"5/6"`).
|
|
68
|
-
- 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
|
|
69
76
|
re-verdict — the re-review is what *verifies* the ticked items actually hold (a regression simply
|
|
70
77
|
reappears as a new finding in the next round). **Recommend a `/clear`** — all state (spec,
|
|
71
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.
|