cohorte 2.1.0 → 2.2.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 +120 -0
- package/README.md +41 -32
- package/bin/cli.js +316 -26
- package/core/adapter/render.js +389 -0
- package/core/agents/implementer.template.md +3 -3
- package/core/agents/release.md +1 -4
- package/core/agents/review.md +10 -2
- package/core/commands/cohorte-audit.md +2 -0
- package/core/commands/cohorte-brainstorm.md +3 -6
- package/core/commands/cohorte-build.md +14 -17
- package/core/commands/cohorte-doctor.md +59 -28
- package/core/commands/cohorte-fix.md +2 -3
- package/core/commands/cohorte-init-pipeline.md +7 -8
- package/core/commands/cohorte-refactor.md +5 -2
- package/core/commands/cohorte-review.md +20 -16
- package/core/commands/cohorte-ship.md +5 -5
- package/core/commands/cohorte-spec.md +3 -7
- package/core/commands/cohorte-update-pipeline.md +8 -8
- package/core/hooks/gate.py +203 -16
- package/core/runtimes/claude.json +73 -0
- package/core/runtimes/codex.json +82 -0
- package/core/runtimes/cursor.json +75 -0
- package/core/runtimes/gemini.json +75 -0
- package/core/runtimes/opencode.json +72 -0
- package/core/templates/spec.template.md +1 -3
- package/core/templates/steps/init-pipeline/01-detect-stack.md +1 -1
- package/core/templates/steps/init-pipeline/02-interview-gaps.md +2 -2
- package/core/templates/steps/init-pipeline/04-write-render.md +23 -17
- package/core/templates/steps/init-pipeline/05-report.md +1 -1
- package/dashboard/dist/assets/{index-P1I1JGtj.js → index-D1rsbLat.js} +1 -1
- package/dashboard/dist/index.html +1 -1
- package/dashboard/server/doctor.js +156 -69
- package/dashboard/server/index.js +12 -2
- package/dashboard/server/metrics.js +13 -6
- package/dashboard/server/runtime.js +115 -0
- package/dashboard/server/versions.js +12 -1
- package/install.ps1 +23 -2
- package/install.sh +22 -4
- package/package.json +6 -2
- package/profile/PIPELINE.template.md +7 -6
- package/profile/SCHEMA.md +45 -48
- package/scripts/kanban-move.sh +11 -1
- package/scripts/metrics/collect.mjs +5 -3
- package/scripts/preflight.sh +27 -8
- package/scripts/telemetry-send.sh +10 -3
- package/scripts/test-adapter.mjs +368 -0
- package/scripts/test-dashboard.mjs +70 -0
- package/scripts/test-gate.mjs +62 -0
- package/scripts/validate-core.mjs +1 -1
- package/core/commands/cohorte-loop.md +0 -110
- package/scripts/loop-detach.sh +0 -153
- package/scripts/loop.sh +0 -399
- package/scripts/test-loop.mjs +0 -330
|
@@ -12,8 +12,17 @@ fix only with the human's go-ahead (or hand them the command).
|
|
|
12
12
|
|
|
13
13
|
## Checks, in order
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
0. **Runtime.** Say which coding agent you are running as and what it can enforce — every check
|
|
16
|
+
below is read through it. **You already know which one**: the Runtime preamble at the top of
|
|
17
|
+
this file names it. Read `<core>/pipeline/runtimes.json` for the details — a map of every
|
|
18
|
+
runtime installed against this core, since they share one core. Report one line:
|
|
19
|
+
`runtime: <label> · scope <global|project> · hooks <yes|no> · workflows <yes|no>`,
|
|
20
|
+
and name the other installed runtimes if there are any (they share `<state>` and `<config>`, so
|
|
21
|
+
a board or a gate config wired from one is seen by all — that is intended, and worth stating).
|
|
22
|
+
File absent ⇒ a core installed before the adapter existed ⇒ ⚠️, fix by re-running the installer.
|
|
23
|
+
A runtime without hooks makes check 3's gate **advisory** — say so there rather than
|
|
24
|
+
reporting a false ✅.
|
|
25
|
+
1. **Core & pointer.** A core exists (`<core>/pipeline/VERSION`); `<state>/pipeline.json` names a mode + `core_version`
|
|
17
26
|
coherent with the VERSION file. A **global**-mode pointer lagging the VERSION file is ⚠️, not ❌:
|
|
18
27
|
nothing bumped that field before 1.2.5, so the core itself is fine and only the pointer is stale
|
|
19
28
|
⇒ fix by running `/cohorte-update-pipeline` (§3 syncs it now), or by editing the one field. Compare
|
|
@@ -21,40 +30,57 @@ fix only with the human's go-ahead (or hand them the command).
|
|
|
21
30
|
commands' step files are present — `templates/steps/init-pipeline/` non-empty (a router whose
|
|
22
31
|
`templates/steps/<cmd>/` dir is missing is a partial/stale install ⇒
|
|
23
32
|
re-run install/update). **Shipped scripts present and executable** in `<core>/pipeline/scripts/`:
|
|
24
|
-
`kanban-move.sh`, `telemetry-send.sh`, `preflight.sh`,
|
|
33
|
+
`kanban-move.sh`, `telemetry-send.sh`, `preflight.sh`,
|
|
25
34
|
`new-feature.sh.template`, `remove-feature.sh.template` — ❌ any missing one.
|
|
26
|
-
|
|
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**
|
|
35
|
+
Every caller chains these with `|| true`, so an absent script is a **silent**
|
|
29
36
|
no-op (no kanban card moves, no telemetry ping, no error anywhere) — this check is the only thing
|
|
30
37
|
that sees it. Also flag ❌ a `VERSION` **newer than** the other `pipeline/` files (compare mtimes):
|
|
31
38
|
a version bumped without a full re-copy is a half-done update ⇒ re-run install/update.
|
|
32
39
|
2. **Profile.** `PIPELINE.md` exists and its `yaml pipeline-profile` block parses. Every
|
|
33
|
-
`surfaces[].agent` has its
|
|
40
|
+
`surfaces[].agent` has its `<agents>/<agent>.md` and every agent file has its `surfaces[]`
|
|
34
41
|
entry — **no orphans either way** (SCHEMA.md rule). Each rendered agent's frontmatter `tools`
|
|
35
42
|
matches its surface's `tools` (incl. `DesignSync` iff `uses_design`, retrieval MCP tools iff
|
|
36
43
|
`retrieval.provider` ≠ `none`). **Model pins:** each rendered agent's frontmatter `model` matches
|
|
37
44
|
its `surfaces[].model` — ❌ if missing, mismatched, or a literal `<SURFACE_MODEL>` placeholder
|
|
38
45
|
(all three silently fall back to inheriting the lead session's model — often Opus — on every
|
|
39
46
|
dispatch); ⚠️ any `inherit` with the note that it bills at the lead's tier. The generic agents
|
|
40
|
-
(`review.md`, `release.md`, `profile-reader.md`
|
|
41
|
-
each carry their `model:` line too (sonnet/haiku/haiku).
|
|
42
|
-
|
|
43
|
-
|
|
47
|
+
(`review.md`, `release.md`, `profile-reader.md` in `<agents>/`) must
|
|
48
|
+
each carry their `model:` line too (sonnet/haiku/haiku).
|
|
49
|
+
<!-- cohorte:if runtime:claude -->
|
|
50
|
+
**Command pins:** every mechanical command file
|
|
51
|
+
(`build`, `review`, `fix`, `ship`, `audit`, `refactor`, `doctor`, `align-ds`,
|
|
52
|
+
`update-pipeline` — in `<commands>/`) carries `model: sonnet` in
|
|
44
53
|
its frontmatter — ⚠️ if missing (the lead's orchestration turn then bills at the session model,
|
|
45
54
|
e.g. Opus/Fable). `brainstorm`, `spec`, and `init-pipeline` are intentionally unpinned
|
|
46
55
|
(interactive — they inherit the session model).
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
registered
|
|
56
|
+
<!-- cohorte:endif -->
|
|
57
|
+
|
|
58
|
+
3. **Hooks & gate.** `<state>/gate-config.json` exists and mirrors the profile's `gate` block
|
|
59
|
+
(regenerate if drifted).
|
|
60
|
+
<!-- cohorte:if hooks -->
|
|
61
|
+
The gate hook is registered **once** in the config file the Runtime preamble names — flag a
|
|
62
|
+
double registration, it double-prompts — and its `command` points at a `gate.py` that exists.
|
|
63
|
+
Check the **matcher** actually covers what it must: on Claude Code that means both `Bash` and
|
|
64
|
+
`Task`, since the preflight phase gate keys off `Task` dispatches and a `Bash`-only matcher
|
|
65
|
+
leaves it silently dead (the 1.3.0–1.3.1 regression). Prove the wiring end to end rather than
|
|
66
|
+
trusting the file: `python3 <core>/hooks/gate.py --check "<a pattern from the ask list>"` must
|
|
67
|
+
return a non-`allow` verdict. If the Runtime preamble said this runtime has **no confirmation
|
|
68
|
+
tier**, state it here too: every `ask` pattern behaves as a `deny`, which is safe but stricter
|
|
69
|
+
than the profile reads, and a human who expects a prompt will read the refusal as a bug.
|
|
70
|
+
<!-- cohorte:endif -->
|
|
71
|
+
<!-- cohorte:if !hooks -->
|
|
72
|
+
This runtime has **no blocking hook**, so the gate is **advisory**: it only fires when the agent
|
|
73
|
+
calls it. Say that in one line rather than reporting ✅ — the enforcement property genuinely is
|
|
74
|
+
weaker here, and a human who thinks otherwise will approve less carefully. Verify what CAN be
|
|
75
|
+
verified: `<core>/hooks/gate.py` exists and `python3 <core>/hooks/gate.py --check "git push"`
|
|
76
|
+
returns a verdict line (a non-`allow` on a gated pattern proves config + script are wired). ❌ if
|
|
77
|
+
the script is missing or errors; ℹ️ "advisory (this runtime has no hooks)" otherwise.
|
|
78
|
+
<!-- cohorte:endif -->
|
|
53
79
|
Then the **preflight stamp is local, never versioned**: `git ls-files --error-unmatch
|
|
54
|
-
|
|
80
|
+
<state>/preflight.ok` must miss, and `.gitignore` must cover it. A tracked stamp is a ❌ (not a
|
|
55
81
|
⚠️) — it records the tree it verified, the commit that carries it moves HEAD past that tree, and
|
|
56
82
|
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
|
|
83
|
+
greens unchecked ones. fix: `git rm --cached <state>/preflight.ok` + add it to `.gitignore`.
|
|
58
84
|
4. **Retrieval** (if `retrieval.provider` ≠ `none`). Run the SCHEMA.md §Code retrieval health
|
|
59
85
|
check: CLI resolvable from PATH, `.mcp.json` entry present in PATH-proof launcher form,
|
|
60
86
|
`.serena/` gitignored, server actually connects.
|
|
@@ -70,7 +96,7 @@ fix only with the human's go-ahead (or hand them the command).
|
|
|
70
96
|
When ≥2 slots are live, print the parallel-feature table (feature · worktree · ports · db ·
|
|
71
97
|
branch behind main by N commits) — a worktree far behind main means its next review will diff
|
|
72
98
|
against stale code ⇒ suggest rebasing it.
|
|
73
|
-
7. **Telemetry** (consent hygiene — read
|
|
99
|
+
7. **Telemetry** (consent hygiene — read `<config>` §`telemetry`). Report the
|
|
74
100
|
status in one line: `disabled` / `enabled since <consent_date> · install_id <id> · endpoint <url>`
|
|
75
101
|
(the install_id is the human's GDPR erasure key — see SCHEMA.md §Telemetry). Flag ❌ any
|
|
76
102
|
incoherent state: `enabled: true` with no `install_id` or no `consent_date` (sending without
|
|
@@ -85,6 +111,7 @@ fix only with the human's go-ahead (or hand them the command).
|
|
|
85
111
|
other key whose board file exists (a **rename** orphaned the link — re-key it via
|
|
86
112
|
`/cohorte-update-pipeline`), and an entry whose board file no longer exists at
|
|
87
113
|
`vault_path`-relative `board` (moved or renamed in the vault).
|
|
114
|
+
<!-- cohorte:if workflows -->
|
|
88
115
|
8. **Workflows** (the opt-in execution path — SCHEMA.md §Workflows; the conversational commands
|
|
89
116
|
stay the default, so failures here are ⚠️ at most, never ❌). Report which path this machine will
|
|
90
117
|
take and why:
|
|
@@ -92,8 +119,7 @@ fix only with the human's go-ahead (or hand them the command).
|
|
|
92
119
|
on PATH ⇒ conversational only.
|
|
93
120
|
- **Scripts present:** `<core>/workflows/review.js` + `audit.js` + `refactor.js` —
|
|
94
121
|
missing on a current core ⇒ half-done install, re-run install/update.
|
|
95
|
-
- **Phase-0 agent present:** `<agents
|
|
96
|
-
`~/.claude/agents/` global) — the workflows abort without it.
|
|
122
|
+
- **Phase-0 agent present:** `<agents>/profile-reader.md` — the workflows abort without it.
|
|
97
123
|
- **Workflows enabled in this session** — the `Workflow` tool is in your own toolset right now;
|
|
98
124
|
absent ⇒ disabled for this session (a setting or an old client), conversational path.
|
|
99
125
|
- **Preflight wiring** (used by both paths): `pipeline/scripts/preflight.sh` executable and
|
|
@@ -101,15 +127,20 @@ fix only with the human's go-ahead (or hand them the command).
|
|
|
101
127
|
End the check with ONE summary line, e.g.
|
|
102
128
|
`workflows: available (opt-in — ask to "run the review workflow")` or
|
|
103
129
|
`workflows: unavailable (<first failing prerequisite>) — conversational commands (the default)`.
|
|
130
|
+
<!-- cohorte:else -->
|
|
131
|
+
8. **Preflight wiring.** `<core>/pipeline/scripts/preflight.sh` is executable and
|
|
132
|
+
`gate-config.json` carries the `preflight` block — mismatch ⇒ regenerate from the profile.
|
|
133
|
+
(The workflow execution path does not exist on this runtime; the conversational commands are
|
|
134
|
+
the only path, which is also the default everywhere else. Not a defect — state it and move on.)
|
|
135
|
+
<!-- cohorte:endif -->
|
|
104
136
|
9. **Specs & metrics.** Every `specs/*.md` front-matter `status` is a valid stage — one of
|
|
105
|
-
`draft · frozen · in-progress · in-review · shipped · blocked` (SCHEMA.md §Spec status
|
|
106
|
-
are written by the `/cohorte-loop` driver, so flagging them would report the pipeline's own state as a
|
|
107
|
-
defect) — excluding
|
|
137
|
+
`draft · frozen · in-progress · in-review · shipped · blocked` (SCHEMA.md §Spec status) — excluding
|
|
108
138
|
`_`-prefixed files (the spec template and `specs/_decisions.md`, the decision journal) and
|
|
109
139
|
`specs/refactor-backlog.md`, which `/cohorte-audit` writes as a backlog, not a
|
|
110
|
-
spec, and which has no front-matter to check. A spec left `in-progress
|
|
111
|
-
|
|
112
|
-
|
|
140
|
+
spec, and which has no front-matter to check. A spec left `in-progress` or `blocked` is a round
|
|
141
|
+
that never finished ⇒ say so and route it: open `## Remediation` items ⇒ `/cohorte-fix`, none ⇒
|
|
142
|
+
`/cohorte-build`. `shipped` specs
|
|
143
|
+
with a live worktree flagged (see 6). `<state>/pipeline-metrics.jsonl` and `specs/reports/` (the
|
|
113
144
|
`/cohorte-review` report buffer that lets a `/cohorte-fix` survive a `/clear`) are gitignored. Metrics
|
|
114
145
|
belong to the **main checkout** — a `pipeline-metrics.jsonl` inside a live feature worktree is a
|
|
115
146
|
stale-core sign (its lines die at teardown) ⇒ suggest appending its lines to the main checkout's
|
|
@@ -12,8 +12,7 @@ that change the *contract*; `/cohorte-fix` is for everything else.
|
|
|
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): on ingest, run
|
|
15
|
-
> `<core>/pipeline/scripts/kanban-move.sh auto $ARGUMENTS fix
|
|
16
|
-
> `~/.claude` global — probe with `test -x`); the card returns to **Review** when `/cohorte-review`
|
|
15
|
+
> `<core>/pipeline/scripts/kanban-move.sh auto $ARGUMENTS fix`; the card returns to **Review** when `/cohorte-review`
|
|
17
16
|
> re-runs. `auto` resolves the board from the config itself and exits 0 with a `kanban: <reason>`
|
|
18
17
|
> line when there is none — so **never decide "no board is configured" without running it**.
|
|
19
18
|
|
|
@@ -71,7 +70,7 @@ When the agents return:
|
|
|
71
70
|
needs those checkboxes).
|
|
72
71
|
- Print one status line per surface (`<key> · items fixed <n>/<m> · tests pass/fail`) — do not restate
|
|
73
72
|
handoff content — and append ONE metrics line for the batch to the **main checkout's**
|
|
74
|
-
`$(dirname "$(git rev-parse --git-common-dir)")
|
|
73
|
+
`$(dirname "$(git rev-parse --git-common-dir)")/<state>/pipeline-metrics.jsonl` (never a bare
|
|
75
74
|
relative path: from a feature worktree that writes a stray sink whose lines die at teardown)
|
|
76
75
|
(rules in `/cohorte-build` §4, `phase: "fix"`), chaining the opt-in usage ping in the same Bash call
|
|
77
76
|
(results = items fixed over items found across surfaces, e.g. `"5/6"`).
|
|
@@ -9,13 +9,12 @@ agents. Interactive — confirm inferences with the human.
|
|
|
9
9
|
|
|
10
10
|
> **Bootstrap (applies to every step):**
|
|
11
11
|
>
|
|
12
|
-
> **Where the core lives (bundled vs global).**
|
|
13
|
-
>
|
|
14
|
-
> (
|
|
15
|
-
>
|
|
16
|
-
>
|
|
17
|
-
>
|
|
18
|
-
> root, agents/config under this repo's `.claude/`), never into `~/.claude/`.
|
|
12
|
+
> **Where the core lives (bundled vs global).** `<core>` above already names it — the adapter
|
|
13
|
+
> resolved the scope at install time, so nothing here probes. Read it once to learn WHICH mode you
|
|
14
|
+
> are in (`<core>` inside this repo ⇒ `bundled`; `<core>` under your home ⇒ `global`) and remember
|
|
15
|
+
> it — Phase 4 branches on it. **Everything you GENERATE is always written into THIS repo**
|
|
16
|
+
> (`PIPELINE.md` at the root, agents under `<agents>/`, config under `<state>/`), never into the
|
|
17
|
+
> global core.
|
|
19
18
|
>
|
|
20
19
|
> Work in phases. Do not write any file until Phase 4.
|
|
21
20
|
|
|
@@ -29,4 +28,4 @@ agents. Interactive — confirm inferences with the human.
|
|
|
29
28
|
| 04 | `04-write-render` | Write files & render surface agents | after go-ahead |
|
|
30
29
|
| 05 | `05-report` | Print install mode, files, mapping | always |
|
|
31
30
|
|
|
32
|
-
**Before running a step, read its file** in
|
|
31
|
+
**Before running a step, read its file** in `<core>/templates/steps/init-pipeline/`. This table is a map, not the instructions.
|
|
@@ -8,10 +8,12 @@ You are the **lead**. Refactor domain **$ARGUMENTS** to match `PIPELINE.md`, usi
|
|
|
8
8
|
|
|
9
9
|
> Read `PIPELINE.md` §`surfaces` (map the domain → a surface + its agent + commands) and §`contract`.
|
|
10
10
|
>
|
|
11
|
+
<!-- cohorte:if workflows -->
|
|
11
12
|
> **Workflow variant** (opt-in — SCHEMA.md §Workflows): for BIG domains (many open backlog items
|
|
12
13
|
> across several surfaces), on Claude Code ≥ 2.1.154 with workflows enabled, the human can ask to
|
|
13
14
|
> "run the refactor workflow" (`<core>/workflows/refactor.js`). For a handful of items this
|
|
14
15
|
> conversational path is cheaper — and it stays the default and the fallback.
|
|
16
|
+
<!-- cohorte:endif -->
|
|
15
17
|
|
|
16
18
|
## 1. Gather
|
|
17
19
|
|
|
@@ -22,11 +24,12 @@ You are the **lead**. Refactor domain **$ARGUMENTS** to match `PIPELINE.md`, usi
|
|
|
22
24
|
|
|
23
25
|
## 2. Dispatch the surface's implementer agent — TDD-first, stateless
|
|
24
26
|
|
|
25
|
-
Spawn the matching `<surface.agent>` with the template below
|
|
27
|
+
Spawn the matching `<surface.agent>` with the template below (as `subagent_type: <surface.agent>`).
|
|
28
|
+
Keep it **byte-identical across loop
|
|
26
29
|
rounds** (only the final items slot varies — it sits at the end so repeats hit the prompt cache), and
|
|
27
30
|
never paste a diff — the agent computes its own, scoped to its tree:
|
|
28
31
|
|
|
29
|
-
>
|
|
32
|
+
> "Refactor pass on your surface (no feature spec). Read
|
|
30
33
|
> `PIPELINE.md` first. **Add the missing tests FIRST** (pin current behavior / cover the entry
|
|
31
34
|
> points), watch them pass, **then** refactor to clear each item. Preserve current public behavior
|
|
32
35
|
> unless an item marks it a bug. Migrations stay additive. Need the current state of your tree?
|
|
@@ -10,20 +10,21 @@ You are the **lead**. Dispatch the review for feature **$ARGUMENTS**.
|
|
|
10
10
|
> _Skip the re-read if it's already in your context this session and unmodified since._
|
|
11
11
|
>
|
|
12
12
|
> **Kanban** (SCHEMA.md §Kanban): run
|
|
13
|
-
> `<core>/pipeline/scripts/kanban-move.sh auto $ARGUMENTS review`
|
|
14
|
-
> `~/.claude` global — probe with `test -x`). `auto` resolves the board from the config itself and
|
|
13
|
+
> `<core>/pipeline/scripts/kanban-move.sh auto $ARGUMENTS review`. `auto` resolves the board from the config itself and
|
|
15
14
|
> exits 0 with a `kanban: <reason>` line when there is none — so **never decide "no board is
|
|
16
15
|
> configured" without running it**.
|
|
17
16
|
>
|
|
17
|
+
<!-- cohorte:if workflows -->
|
|
18
18
|
> **Workflow variant** (opt-in — SCHEMA.md §Workflows): on Claude Code ≥ 2.1.154 with workflows
|
|
19
19
|
> enabled, the human can ask to "run the review workflow" (`<core>/workflows/review.js`) instead.
|
|
20
20
|
> This conversational path stays the default and the fallback; `/cohorte-doctor` shows which is available.
|
|
21
|
+
<!-- cohorte:endif -->
|
|
21
22
|
|
|
22
23
|
## 0. Deterministic pre-flight — no agents while red
|
|
23
24
|
|
|
24
25
|
Run the profile's mechanical gates in ONE Bash call via the shipped script
|
|
25
|
-
(`<core>/pipeline/scripts/preflight.sh
|
|
26
|
-
|
|
26
|
+
(`<core>/pipeline/scripts/preflight.sh`); note the epoch (`date +%s`) in the same call — §3's
|
|
27
|
+
metrics line needs it:
|
|
27
28
|
|
|
28
29
|
```
|
|
29
30
|
<core>/pipeline/scripts/preflight.sh specs/reports/$ARGUMENTS.preflight.txt \
|
|
@@ -37,8 +38,14 @@ with `test -x`); note the epoch (`date +%s`) in the same call — §3's metrics
|
|
|
37
38
|
rather than silence:
|
|
38
39
|
`{"id":"$ARGUMENTS","phase":"review","ts":"<ISO>","aborted":"preflight","verdict":"BLOCK","blocking":null}`
|
|
39
40
|
→ `specs/reports/$ARGUMENTS.verdict.json`. One `printf`, in the same Bash call.
|
|
40
|
-
|
|
41
|
+
<!-- cohorte:if hooks -->
|
|
42
|
+
- **Zero exit** ⇒ it stamped `<state>/preflight.ok`, which the gate hook checks before letting
|
|
41
43
|
`review` dispatches through (SCHEMA.md §Preflight). Continue.
|
|
44
|
+
<!-- cohorte:else -->
|
|
45
|
+
- **Zero exit** ⇒ it stamped `<state>/preflight.ok`. Nothing enforces that stamp on this runtime, so
|
|
46
|
+
§2 does not start until you have seen this line: a review of red code is the one failure mode this
|
|
47
|
+
step exists to prevent, and here only you can prevent it (SCHEMA.md §Preflight). Continue.
|
|
48
|
+
<!-- cohorte:endif -->
|
|
42
49
|
- Script absent (older core) ⇒ run the three commands yourself, each redirected into
|
|
43
50
|
`specs/reports/$ARGUMENTS.preflight.txt`, aborting on the first failure the same way.
|
|
44
51
|
|
|
@@ -61,7 +68,7 @@ with `test -x`); note the epoch (`date +%s`) in the same call — §3's metrics
|
|
|
61
68
|
|
|
62
69
|
## 2. Dispatch review agents — one per touched surface, IN PARALLEL
|
|
63
70
|
|
|
64
|
-
Spawn ONE `review` agent per surface that has changed files, in a **single message** (one
|
|
71
|
+
Spawn ONE `review` agent per surface that has changed files, in a **single message** (one dispatch
|
|
65
72
|
each, like `/cohorte-build`) so they run concurrently — NEVER serially: review wall-clock must be the
|
|
66
73
|
slowest surface, not the sum. A diff touching a single surface ⇒ a single reviewer.
|
|
67
74
|
|
|
@@ -70,12 +77,12 @@ changed lines), touches no contract file, and every open finding it addresses is
|
|
|
70
77
|
LOW/MEDIUM, skip the dispatch: verify the hunks yourself against the open Remediation items (did the
|
|
71
78
|
prescribed fixes land? — NOT a de-novo audit) and write the same REVIEW REPORT into the §3 flow.
|
|
72
79
|
First-round reviews, contract changes, and security findings always get a full reviewer. For each
|
|
73
|
-
|
|
80
|
+
reviewed surface:
|
|
74
81
|
|
|
75
82
|
Keep the dispatch prompt **byte-identical across features and rounds** except the variable block,
|
|
76
83
|
which sits at the END so every repeat hits the prompt-cache prefix:
|
|
77
84
|
|
|
78
|
-
> `subagent_type: review` — "Review one feature surface against its frozen spec. Read `PIPELINE.md`
|
|
85
|
+
> `subagent_type: review` (or this runtime's equivalent) — "Review one feature surface against its frozen spec. Read `PIPELINE.md`
|
|
79
86
|
> first (flags + the §Conventions/§Testing slice for your scope). Check spec conformance first, then
|
|
80
87
|
> correctness, security, conventions, RBAC/mobile-first _if the profile enables them_, and TDD
|
|
81
88
|
> coverage. Your dispatch names a staged diff file — read it FIRST; open a full source file only when
|
|
@@ -109,7 +116,7 @@ re-ordered by severity, counts summed, duplicates collapsed, verdict = the worst
|
|
|
109
116
|
(`BLOCK` > `REVISE` > `SHIP`). The `## Deferred` sections merge the same way (dedupe by
|
|
110
117
|
`file` + problem) and stay **out of the severity table and out of the verdict** — see §3.5, which
|
|
111
118
|
routes them. Append ONE metrics line for the batch to the **main checkout's**
|
|
112
|
-
`$(dirname "$(git rev-parse --git-common-dir)")
|
|
119
|
+
`$(dirname "$(git rev-parse --git-common-dir)")/<state>/pipeline-metrics.jsonl` (rules in
|
|
113
120
|
`/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>",…}}`.
|
|
114
121
|
In the same Bash call, chain the opt-in usage ping (`/cohorte-build` §4, `phase: "review"`, results = the
|
|
115
122
|
merged verdict + total finding count, e.g. `"REVISE:3"`).
|
|
@@ -118,7 +125,7 @@ merged verdict + total finding count, e.g. `"REVISE:3"`).
|
|
|
118
125
|
non-recursive `specs/*.md` glob, so it's never mistaken for a spec (no phantom card, no bogus stage).
|
|
119
126
|
**Write the machine-readable verdict** to `specs/reports/$ARGUMENTS.verdict.json` (overwrite) — on
|
|
120
127
|
**every** run, including the small-diff fast path of §2 and a `SHIP`. This file is the ONLY contract
|
|
121
|
-
between the pipeline and
|
|
128
|
+
between the pipeline and any automated driver, which parses no prose:
|
|
122
129
|
|
|
123
130
|
```json
|
|
124
131
|
{ "id": "$ARGUMENTS", "phase": "review", "ts": "<ISO>", "verdict": "REVISE",
|
|
@@ -163,8 +170,8 @@ exactly the leak this step closes. Append each merged `## Deferred` item to
|
|
|
163
170
|
- [ ] <SEVERITY> · <file:line> · <quality|security|rule> · <concrete fix> · deferred:$ARGUMENTS
|
|
164
171
|
```
|
|
165
172
|
|
|
166
|
-
- **Never into the spec's `## Remediation`** — that list is what `/cohorte-fix` re-dispatches
|
|
167
|
-
|
|
173
|
+
- **Never into the spec's `## Remediation`** — that list is what `/cohorte-fix` re-dispatches, so a
|
|
174
|
+
deferred item there would re-trigger the very fix round it was deferred out of.
|
|
168
175
|
- **Dedupe before appending:** `grep -F` the backlog for the item's `<file>` + the first words of its
|
|
169
176
|
problem; already there (from a prior round or an `/cohorte-audit`) ⇒ skip it, don't stack duplicates round
|
|
170
177
|
after round.
|
|
@@ -197,10 +204,7 @@ would sit in this session's history, re-sent every turn). Then:
|
|
|
197
204
|
re-trigger the fix loop), keep the SHIP verdict and the freshness stamp, and let the human ship.
|
|
198
205
|
- **REVISE / BLOCK**, or any CRITICAL/HIGH/security finding → tell the human to run
|
|
199
206
|
**`/cohorte-fix $ARGUMENTS`** — it appends the report to the spec's `## Remediation` and re-dispatches ONLY
|
|
200
|
-
the surfaces with findings. (
|
|
201
|
-
`disable-model-invocation: true` on purpose: **you cannot start it, they must type it**. Name the
|
|
202
|
-
exact line for them to type rather than attempting it — an attempt that silently fails reads as a
|
|
203
|
-
loop that is running when nothing is.) The full path (`/cohorte-spec` Mode B then `/cohorte-build`) remains for findings that
|
|
207
|
+
the surfaces with findings. The full path (`/cohorte-spec` Mode B then `/cohorte-build`) remains for findings that
|
|
204
208
|
change the contract in ways that ripple into clean surfaces. _The report is staged to
|
|
205
209
|
`specs/reports/$ARGUMENTS.md`, so you can `/clear` before `/cohorte-fix` — it reads the findings back from
|
|
206
210
|
disk._
|
|
@@ -12,8 +12,7 @@ You are the **lead**. Ship feature **$ARGUMENTS**. This is the outward-facing ga
|
|
|
12
12
|
>
|
|
13
13
|
> **Kanban** (SCHEMA.md §Kanban) is mirrored in **explicit steps** below, not as an afterthought:
|
|
14
14
|
> §1 moves the card → **Ship**; §4 moves it → **Shipped** and writes the PR number. Both are one
|
|
15
|
-
> call to `<core>/pipeline/scripts/kanban-move.sh auto
|
|
16
|
-
> global — probe with `test -x`), which resolves the board from the config itself and exits 0 with a
|
|
15
|
+
> call to `<core>/pipeline/scripts/kanban-move.sh auto …`, which resolves the board from the config itself and exits 0 with a
|
|
17
16
|
> `kanban: <reason>` line when there is none. **Never decide "no board is configured" without running
|
|
18
17
|
> it** — a ship session that inferred that, having opened neither the config nor `PIPELINE.md`, is
|
|
19
18
|
> exactly how a merged feature's card stayed in "Ready to build". Do not skip §4's move either.
|
|
@@ -65,17 +64,18 @@ See SCHEMA.md §Release notes.
|
|
|
65
64
|
- Then say in one line which level you chose and why — this is the human's last chance to correct it
|
|
66
65
|
before it is committed.
|
|
67
66
|
|
|
68
|
-
> **Why this is its own gate.** The requirement usually lives in the project's
|
|
67
|
+
> **Why this is its own gate.** The requirement usually lives in the project's `<memory>`, which this
|
|
69
68
|
> flow never reads. Skip it and everything below still "succeeds": commit, push, PR opened, kanban card
|
|
70
69
|
> moved to **Shipped** — and CI red on a job nobody watched. The feature reads as shipped while being
|
|
71
70
|
> unmergeable.
|
|
72
71
|
|
|
73
72
|
## 3. Dispatch the `release` agent
|
|
74
73
|
|
|
75
|
-
Spawn one agent (`subagent_type: release
|
|
74
|
+
Spawn one agent (`subagent_type: release`, or the equivalent dispatch for this runtime):
|
|
75
|
+
"Release feature `$ARGUMENTS` on branch
|
|
76
76
|
`<feature_branch_prefix>$ARGUMENTS`. Read `PIPELINE.md` §vcs first. Spec: `specs/$ARGUMENTS.md` (already
|
|
77
77
|
`status: shipped` — stage it). Write conventional commit(s), push (no force), open the PR (use `gh` if
|
|
78
|
-
`host: github` + available; else emit the compare URL + drafted PR body from
|
|
78
|
+
`host: github` + available; else emit the compare URL + drafted PR body from `<core>/templates/pr-body.md`).
|
|
79
79
|
Stage **all** the feature's changes including `specs/$ARGUMENTS.md` and, if `release_notes.enabled`, the
|
|
80
80
|
release note at `<release_notes.dir>/<release_notes.filename>` — it is already written, stage it as-is and
|
|
81
81
|
never author or edit one yourself. Never edit source, never force-push, never run migrations."
|
|
@@ -10,17 +10,13 @@ You run the **spec** step in the main thread — interactive, with the human. Pa
|
|
|
10
10
|
> Read `PIPELINE.md` first: `contract` (mechanism/path — so §5 names the right schema types),
|
|
11
11
|
> `design.enabled` (whether §8 matters), and §Conventions. Use `specs/_template.md` as the section list.
|
|
12
12
|
>
|
|
13
|
-
> Template paths below (`.claude/templates/…`) resolve to `~/.claude/templates/…` when the core is
|
|
14
|
-
> installed globally — read whichever exists.
|
|
15
|
-
>
|
|
16
13
|
> **Decision journal** (SCHEMA.md §Decisions): read `specs/_decisions.md` §Live if it exists — one
|
|
17
14
|
> line per standing decision, so it is cheap. It is the ONLY place the project's transverse rules
|
|
18
15
|
> live; a spec that contradicts one silently un-decides it. Absent ⇒ nothing to honour yet.
|
|
19
16
|
>
|
|
20
17
|
> **Kanban** (SCHEMA.md §Kanban): when the spec opens, run
|
|
21
18
|
> `<core>/pipeline/scripts/kanban-move.sh auto <feature_id> spec --title "<human title>"`; on freeze
|
|
22
|
-
> (`status: frozen`, Mode A), the same call with `ready`.
|
|
23
|
-
> global — probe with `test -x`. `auto` resolves the board from the config itself and exits 0 with a
|
|
19
|
+
> (`status: frozen`, Mode A), the same call with `ready`. `auto` resolves the board from the config itself and exits 0 with a
|
|
24
20
|
> `kanban: <reason>` line when there is none — so **never decide "no board is configured" without
|
|
25
21
|
> running it**.
|
|
26
22
|
|
|
@@ -67,7 +63,7 @@ Detect the mode from the pasted content:
|
|
|
67
63
|
convention, a deliberate non-goal that binds future features). Typical yield: **0–3 lines**; zero
|
|
68
64
|
is a normal, healthy outcome for a feature that decided nothing new — never invent lines to fill
|
|
69
65
|
the section. Append them to `specs/_decisions.md` §Live (create the file from
|
|
70
|
-
|
|
66
|
+
`<core>/templates/decisions.template.md` on first use), each exactly:
|
|
71
67
|
`- <YYYY-MM-DD> · <area> · <decision> — because <reason> · <feature_id>`
|
|
72
68
|
- **Never** duplicate what §5, `PIPELINE.md` §Conventions or the code already states — the journal
|
|
73
69
|
carries the *non-obvious rule*, not the feature's content. A line that restates a spec section is
|
|
@@ -78,7 +74,7 @@ Detect the mode from the pasted content:
|
|
|
78
74
|
- Append with one `>>` Bash call, not a full-file rewrite (the file is append-only, and reading it
|
|
79
75
|
back to re-write it is the one way to make a bounded file expensive).
|
|
80
76
|
6. Author the **design brief** — `specs/design/<id>.md`, rendered via
|
|
81
|
-
|
|
77
|
+
`<core>/templates/design-brief.md`.
|
|
82
78
|
_Only if `design.enabled` / the feature has UI; skip entirely for a backend-only feature._
|
|
83
79
|
- **Write it to `specs/design/<id>.md`** (the authored artifact, versioned with the spec; spec §8
|
|
84
80
|
holds the summary + pointer). Create the file — do not ask the human to. Keep it in the
|
|
@@ -6,14 +6,14 @@ argument-hint: [path-to-local-checkout]
|
|
|
6
6
|
|
|
7
7
|
You are the **pipeline updater**. Refresh the installed pipeline core to the latest version of the pipeline
|
|
8
8
|
repo. The installer's `--update` mode never touches generated files: `PIPELINE.md`, rendered surface agents,
|
|
9
|
-
`gate-config.json`, `settings.json`, and the filled
|
|
9
|
+
`gate-config.json`, `settings.json`, and the filled `<config>` are all preserved.
|
|
10
10
|
YOU then bring those generated files up to the new core yourself (§3.5) — additively, never clobbering
|
|
11
11
|
the human's choices — so `/cohorte-init-pipeline` never needs re-running for an upgrade.
|
|
12
12
|
|
|
13
13
|
## 1. Detect the install scope + current version
|
|
14
14
|
|
|
15
|
-
- **Global** install ⇒
|
|
16
|
-
|
|
15
|
+
- **Global** install ⇒ `<core>/pipeline/VERSION` exists. **Bundled** ⇒ this repo's
|
|
16
|
+
`<core>/pipeline/VERSION` exists. (Both can exist; prefer the bundled one when running inside such a
|
|
17
17
|
repo, and update both if the human wants.)
|
|
18
18
|
- **Never migrate a repo between bundled and global mode on your own.** Updating means refreshing the
|
|
19
19
|
core *in its current mode*. Only migrate (e.g. delete a bundled core in favor of the global one) if
|
|
@@ -52,7 +52,7 @@ the human's choices — so `/cohorte-init-pipeline` never needs re-running for a
|
|
|
52
52
|
|
|
53
53
|
Re-read the VERSION file(s) and print `old → new`. If unchanged, say the core was already up to date.
|
|
54
54
|
|
|
55
|
-
**Sync the pointer — in BOTH modes.** If this repo has a
|
|
55
|
+
**Sync the pointer — in BOTH modes.** If this repo has a `<state>/pipeline.json` whose `core_version`
|
|
56
56
|
differs from the core you just installed, rewrite that one field (leave every other field untouched)
|
|
57
57
|
and tell the human to commit it. In **bundled** mode the installer already did it; in **global** mode
|
|
58
58
|
**nothing does** — the installer refreshes one shared core and cannot know which repos point at it,
|
|
@@ -87,16 +87,16 @@ missing, say so. This is why `/cohorte-init-pipeline` never needs re-running for
|
|
|
87
87
|
Four of the §Reconcile steps matter specifically here:
|
|
88
88
|
|
|
89
89
|
- **Local-artifact hygiene** (§Reconcile step 8): gitignore + untrack the pipeline's runtime files
|
|
90
|
-
(
|
|
90
|
+
(`<state>/preflight.ok`, `<state>/pipeline-metrics.jsonl`, `specs/reports/`). A tracked
|
|
91
91
|
`preflight.ok` — what every pre-2.0.0 install ends up with once a release agent stages `.claude/` —
|
|
92
92
|
makes the phase gate ask on every single review dispatch, so fix it here and say so.
|
|
93
93
|
|
|
94
94
|
- **Spec-template top-up** (§Reconcile step 7): `specs/_template.md` was seeded at install and never
|
|
95
95
|
refreshed since, so add the front-matter fields the current `templates/spec.template.md` has and the
|
|
96
|
-
repo's copy lacks
|
|
96
|
+
repo's copy lacks — and drop `loop_pass`/`loop_phase`, retired with `/cohorte-loop` in 2.2.0 —
|
|
97
97
|
front-matter only, never the body.
|
|
98
98
|
|
|
99
|
-
- **Global config seed** (§Reconcile step 5): if
|
|
99
|
+
- **Global config seed** (§Reconcile step 5): if `<config>` is absent, seed it
|
|
100
100
|
from the template so the kanban + shared-vault config has a home. Never clobber an existing filled
|
|
101
101
|
file. Report what was seeded. If the existing file has NO `telemetry:` block with a `consent_date`
|
|
102
102
|
(pre-telemetry install), top up the block from the template and ask the ONE opt-in consent
|
|
@@ -125,5 +125,5 @@ Four of the §Reconcile steps matter specifically here:
|
|
|
125
125
|
`/cohorte-update-pipeline` inside each (it will skip the already-done core update and just reconcile).
|
|
126
126
|
- **Commit** the reconciled files (`PIPELINE.md`, `.claude/`, `.mcp.json` if added) so teammates get them.
|
|
127
127
|
- The kanban config is global and user-scoped
|
|
128
|
-
(
|
|
128
|
+
(`<config>`) — never committed. The core update never touches it; only the
|
|
129
129
|
reconcile above seeds the file and writes kanban board links (into that global file, not the repo).
|