cohorte 1.2.5 → 1.3.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 CHANGED
@@ -3,6 +3,64 @@
3
3
  Entries are shown by `/update-pipeline` ("What's new") after a core refresh. Keep them short,
4
4
  user-facing, most recent first. One `## <version> — <YYYY-MM-DD>` section per release.
5
5
 
6
+ ## 1.3.0 — 2026-07-30
7
+
8
+ **Token economy — immediate wins, no workflow needed:**
9
+
10
+ - **Deterministic pre-flight before `/review` and `/smoke`.** A shipped script
11
+ (`pipeline/scripts/preflight.sh`) runs typecheck + lint + tests first; red ⇒ the command
12
+ aborts with the raw last-40 lines and **spawns zero agents** — a reviewer no longer burns
13
+ its whole run rediscovering what `tsc` printed for free. Green runs stamp
14
+ `.claude/preflight.ok`, and `gate.py` enforces it as a **phase gate**: a review/smoke
15
+ dispatch with a missing/stale stamp gets a confirm (`gate.preflight` in the profile).
16
+ - **Quiet commands.** New profile fields (`test_quiet_cmd`/`lint_quiet_cmd` per surface,
17
+ `commands.test_quiet`/`lint_quiet` repo-wide) hold the bridled forms agents actually run
18
+ (`--reporter=dot`, `--quiet`, failures-only); absent ⇒ `<cmd> 2>&1 | tail -40`.
19
+ `/init-pipeline` now asks for them instead of storing a bare `pnpm test`;
20
+ `/update-pipeline` tops up older profiles.
21
+ - **`/review` computes the diff once.** One `git diff --stat`, then full patches staged to
22
+ disk only for the touched surfaces — reviewers read the artifact instead of each
23
+ re-running git.
24
+ - **Conventions baked into rendered agents.** The implementer template gets a
25
+ `<SURFACE_CONVENTIONS>` slice rendered at init; at runtime agents read only the profile's
26
+ machine block. Edit conventions in `PIPELINE.md`, then `/update-pipeline` re-renders.
27
+ - **Capped reports.** Review reports: max 20 findings, one line each, zero code excerpts;
28
+ smoke returns: max 10 ❌ lines. Dispatch prompts now keep every volatile slot (feature id,
29
+ paths, file lists) at the END so repeats hit the prompt-cache prefix.
30
+ - `gate.py` also escalates every `ask` to a hard deny in unattended runs
31
+ (`bypassPermissions`) — nobody is there to answer a prompt.
32
+
33
+ **Workflows (opt-in — conversational commands stay the default and the fallback):**
34
+
35
+ - Four deterministic multi-agent scripts for the Claude Code Workflow runtime
36
+ (≥ 2.1.154, workflows enabled): **`workflows/cycle.js` — the full dev cycle on a frozen
37
+ spec** (contract → parallel build → smoke ∥ review(+cross-check) → fix, looping until
38
+ zero findings + PASS; contract changes handled in-loop by a lead-equivalent agent, human
39
+ decisions returned in a `questions` array at the end; a clean exit ticks the DoD and
40
+ stamps the freshness gate so `/ship` follows directly), `workflows/review.js` (preflight
41
+ gate → one reviewer per touched surface → adversarial cross-check of CRITICAL/security
42
+ findings → verdict only), `workflows/audit.js` (one auditor per domain, concurrent,
43
+ prioritized backlog), `workflows/refactor.js` (big domains only: shared first, parallel
44
+ implementers, per-domain verify + one retry). Mechanical phases route to haiku.
45
+ - New `profile-reader` agent (haiku) — phase 0 of every workflow: returns the
46
+ `PIPELINE.md` machine block as JSON, since workflow scripts have no filesystem access.
47
+ - `/doctor` check 8 reports the workflow prerequisites and which path a session will take;
48
+ the generated `settings.json` allow-list now covers what workflow agents need (quiet
49
+ commands, shipped scripts, `git rev-parse`, retrieval MCP tools) so runs don't stall on
50
+ prompts nobody is watching.
51
+ - Installers (npx CLI, install.sh, install.ps1) ship `core/workflows/` + `preflight.sh` +
52
+ the `profile-reader` agent in both global and bundled modes; CI dry-runs assert it.
53
+ - Dashboard: new headless **Audit** action (`claude -p "/audit"` — starts without a prompt,
54
+ no resume if the session dies) and the workflows state in the project drill-down.
55
+
56
+ ## 1.2.6 — 2026-07-30
57
+
58
+ - **`npx cohorte install` never installed the `smoke` agent.** It copied only `review.md` and
59
+ `release.md`, so `/smoke` was there but the agent it dispatches was not — the run failed
60
+ saying `/smoke` is not installed. The shell installers always copied it; only the npm port
61
+ drifted. It now copies every non-template agent in `core/agents/`, so nothing to keep in sync.
62
+ Fix an affected install by re-running `npx cohorte install --global` (or `install --repo`).
63
+
6
64
  ## 1.2.5 — 2026-07-29
7
65
 
8
66
  - **`.claude/pipeline.json`'s `core_version` never updated on global installs.** The installer
package/README.md CHANGED
@@ -163,7 +163,7 @@ npx cohorte dashboard --port=4400 --open # custom port, open the browser
163
163
  ```
164
164
 
165
165
  **Bound to `127.0.0.1` by default** — the dashboard's actions execute code (install/update/reset,
166
- and `/init-pipeline`·`/update-pipeline` via headless Claude), so it must stay on loopback. Each user
166
+ and `/init-pipeline`·`/update-pipeline`·`/audit` via headless Claude), so it must stay on loopback. Each user
167
167
  runs their own agent and drives only their own machine. `--host=0.0.0.0` exposes it to the network
168
168
  (it prints a security warning) — only on a trusted network, since anyone who reaches the port can run
169
169
  those actions.
@@ -178,10 +178,13 @@ those actions.
178
178
  column, via `gh`), otherwise a **Specs board** from `specs/*.md` (by `draft · frozen · in-review ·
179
179
  shipped`). The Kanban supersedes the Specs board when both would apply.
180
180
  - **Actions** (stream their output live) — **Update / Install core** (the shared global core, or a
181
- repo's bundled core); **Init-pipeline / Update-pipeline**, which run those Claude Code commands
182
- **headless** (`claude -p`, autonomous — Init skips the interactive interview, so review the result);
183
- and **Reset pipeline**, which backs up then wipes a project's pipeline footprint and reinstalls a
184
- fresh core. Buttons render only when they apply (e.g. Init only when there's no profile).
181
+ repo's bundled core); **Init-pipeline / Update-pipeline / Audit**, which run those Claude Code
182
+ commands **headless** (`claude -p`, autonomous — Init skips the interactive interview, so review
183
+ the result; Audit writes `specs/refactor-backlog.md`; headless runs start without any prompt and
184
+ have **no resume** if the session dies); and **Reset pipeline**, which backs up then wipes a
185
+ project's pipeline footprint and reinstalls a fresh core. Buttons render only when they apply
186
+ (e.g. Init only when there's no profile). The drill-down's health checklist also shows the
187
+ **workflows** state (scripts + profile-reader installed, which path a session will take).
185
188
 
186
189
  Runtime is **dependency-free** — node's built-in `http` server serves a prebuilt React app (the app
187
190
  source lives in `dashboard/app/`, built to `dashboard/dist/` at publish time). The `/doctor` checks
@@ -269,6 +272,37 @@ Rules that make it safe:
269
272
  their eventual reviews diff against reality.
270
273
  - `/doctor` check 6 shows the live slot table (feature ↔ worktree ↔ ports) when you lose track.
271
274
 
275
+ ### Workflows — deterministic multi-agent runs (opt-in)
276
+
277
+ Three phases also ship as **workflow scripts** for the Claude Code Workflow runtime — the same
278
+ fan-out the commands orchestrate, but driven by a deterministic script instead of the lead reasoning
279
+ it out turn by turn:
280
+
281
+ | Script | What it runs |
282
+ | ----------------------- | ----------------------------------------------------------------------------------------- |
283
+ | `workflows/cycle.js` | **The full dev cycle on a frozen spec**: contract → parallel build → smoke ∥ review(+cross-check) → fix, looping until zero findings + PASS (contract changes handled in-loop by a lead-equivalent agent). Human decisions come back in a `questions` array at the END — empty when `/brainstorm`+`/spec` did their job. Exits SHIP-ready (DoD ticked, freshness stamped) so `/ship` is a straight shot. |
284
+ | `workflows/review.js` | Preflight gate (aborts while red — zero agents), one reviewer per touched surface, adversarial cross-check of CRITICAL/security findings, merged verdict only. |
285
+ | `workflows/audit.js` | One auditor per domain (every surface + shared) concurrently, prioritized `specs/refactor-backlog.md`. |
286
+ | `workflows/refactor.js` | Big domains only: `shared` first and alone, then parallel surface implementers, per-domain verify + one retry. |
287
+
288
+ The essentials:
289
+
290
+ - **The conversational commands stay the default path** — and the fallback when workflows are
291
+ disabled or the client is too old. A workflow runs only when you explicitly ask for it
292
+ ("run the review workflow").
293
+ - **Prerequisite: Claude Code ≥ 2.1.154** with workflows enabled. `/doctor` (check 8) tells you
294
+ which path your session will take and why.
295
+ - **No input mid-run — questions at the edges.** A workflow runs to completion without asking
296
+ anything. `cycle.js` moves the decisions to its boundaries: a readiness gate refuses a non-frozen
297
+ spec up front, and whatever would have been a mid-run question lands in the result's `questions`
298
+ array at the end (spec gaps, hit round-cap) — answer them, rerun the cycle. The destructive-
299
+ command gate still fires inside workflow subagents; in unattended runs its confirms become denies.
300
+ - Phase 0 of every script is the `profile-reader` agent (haiku) — it reads `PIPELINE.md` and hands
301
+ the script the profile as JSON, since workflow scripts have no filesystem access. Mechanical
302
+ phases run on haiku; judgment phases use the same pinned agents as the commands.
303
+
304
+ Details: `profile/SCHEMA.md` §Workflows.
305
+
272
306
  ## Privacy — opt-in telemetry
273
307
 
274
308
  Cohorte can send **anonymous** usage pings (core version, OS, phase name, duration, per-surface
@@ -296,15 +330,16 @@ bin/cli.js # the npm CLI: install / update / dashboard / version (c
296
330
  install.sh # script installer (fresh + --update) for no-Node environments
297
331
  install.ps1 # same installer for Windows PowerShell (fresh + -Update)
298
332
  core/ # copied verbatim into ~/.claude (global) or <project>/.claude (bundled)
299
- agents/ # implementer.template.md (rendered per surface) + review.md + release.md
300
- commands/ # init-pipeline + the workflow commands + /update-pipeline
301
- hooks/ # gate.py (destructive-command gate; branch-aware git/docker free off the default branch)
333
+ agents/ # implementer.template.md (rendered per surface) + review / release / smoke / profile-reader
334
+ commands/ # init-pipeline + the pipeline commands + /update-pipeline
335
+ hooks/ # gate.py (destructive-command gate; branch-aware; preflight phase gate)
302
336
  templates/ # handoff / brainstorm-return / design-brief / review-feedback / pr-body / spec
337
+ workflows/ # opt-in Workflow-runtime scripts: review.js / audit.js / refactor.js
303
338
  profile/
304
339
  PIPELINE.template.md # the profile skeleton /init-pipeline fills
305
340
  SCHEMA.md # field reference
306
341
  cohorte.config.template.yaml # seeds ~/.claude/cohorte.config.yaml (kanban)
307
- scripts/ # new-feature / remove-feature worktree-isolation templates
342
+ scripts/ # worktree-isolation templates + shipped preflight/kanban/telemetry scripts
308
343
  dashboard/ # local web cockpit (npx … dashboard) — see dashboard/README.md
309
344
  server/ # dependency-free node runtime (serves the built app + JSON/stream API)
310
345
  app/ # Vite + React source (built to dashboard/dist/ at publish time)
package/bin/cli.js CHANGED
@@ -92,7 +92,10 @@ fs.mkdirSync(dest, { recursive: true });
92
92
 
93
93
  // --- helpers (mirror install.sh) --------------------------------------------
94
94
  function copyCore() {
95
- for (const d of ['commands', 'hooks', 'templates']) {
95
+ // `workflows` = the deterministic orchestration scripts (review/audit/refactor) the
96
+ // Workflow runtime resolves from .claude/workflows (bundled) or ~/.claude/workflows
97
+ // (global) — same copy rule in both modes, like commands.
98
+ for (const d of ['commands', 'hooks', 'templates', 'workflows']) {
96
99
  fs.cpSync(path.join(src, 'core', d), path.join(dest, d), { recursive: true, force: true });
97
100
  }
98
101
  // 0.1.19 renamed questionnaire-domain-brief.md → research-brief.md; drop the stale copy.
@@ -156,8 +159,15 @@ function scrubTddGate() {
156
159
  // the fixed (non-rendered) agents: the dev review/release pipeline agents
157
160
  function copyFixedAgents() {
158
161
  fs.mkdirSync(path.join(dest, 'agents'), { recursive: true });
159
- for (const f of ['review.md', 'release.md']) {
160
- fs.copyFileSync(path.join(src, 'core', 'agents', f), path.join(dest, 'agents', f));
162
+ // Every agent in core/agents/ EXCEPT the *.template.md ones, which /init-pipeline renders
163
+ // per-surface. Until 1.2.6 this was a hardcoded ['review.md', 'release.md'] that never grew
164
+ // the `smoke.md` the shell installers copy, so `npx cohorte install` shipped the /smoke
165
+ // command with no `smoke` agent to dispatch — the run reported /smoke as not installed.
166
+ // Reading the directory needs no list to keep in sync with the shell installers.
167
+ const agentDir = path.join(src, 'core', 'agents');
168
+ for (const f of fs.readdirSync(agentDir)) {
169
+ if (!f.endsWith('.md') || f.endsWith('.template.md')) continue;
170
+ fs.copyFileSync(path.join(agentDir, f), path.join(dest, 'agents', f));
161
171
  }
162
172
  // 0.1.19 split the bi-mode questionnaire-researcher into research-agent + questionnaire-architect;
163
173
  // copy-over never deletes, so scrub the retired agent lest a dead subagent_type linger.
@@ -9,16 +9,25 @@ You are the **<SURFACE_AGENT>** engineer for one feature of **<PROJECT_NAME>**.
9
9
  statelessly, from the spec you are given. You cannot talk to the other surface agents — your only
10
10
  shared surface is the frozen contract and the spec.
11
11
 
12
- > **First action, always:** read `PIPELINE.md` the whole machine block (§`pipeline-profile`; it is the
13
- > shared contract: surfaces, contract, gate). Then in §Conventions read ONLY the `### Shared` stanza and
14
- > your own `### Surface: <your key>` stanza (Grep for your key; the other surfaces' stanzas are another
15
- > agent's rules skip them), plus §Testing. You have no memory; re-read your slice every dispatch —
16
- > but never load the other surfaces' convention prose.
12
+ > **First action, always:** read `PIPELINE.md`'s fenced `yaml pipeline-profile` block ONLY the
13
+ > machine contract (surfaces, contract, commands, gate). Do **not** read the prose sections
14
+ > (§Conventions/§Testing): your slice of them is baked into this file below (§Your conventions),
15
+ > rendered from the profile re-reading the prose every dispatch is exactly the cost the bake
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
18
 
18
19
  ## You own
19
20
 
20
21
  `<SURFACE_PATH>/**` only. Everything under it — and nothing outside it.
21
22
 
23
+ ## Your conventions (baked from `PIPELINE.md` at render time)
24
+
25
+ <!-- Rendered by /init-pipeline (and refreshed by /update-pipeline's reconcile) from
26
+ §Conventions `### Shared` + `### Surface: <your key>` + your §Testing lines.
27
+ Edit conventions in PIPELINE.md, never here — this block is regenerated. -->
28
+
29
+ <SURFACE_CONVENTIONS>
30
+
22
31
  ## You must NEVER
23
32
 
24
33
  - Touch any other surface's tree (see the `surfaces` list in `PIPELINE.md`). That's another agent's.
@@ -53,15 +62,19 @@ tools are unavailable or come up empty.
53
62
  ## How you work — strict TDD (red → green → refactor)
54
63
 
55
64
  1. <SURFACE_TDD_STEP1>
56
- 2. **Write the failing test(s) first** from the frozen contract (your surface's test runner is
57
- `surfaces[].test_cmd` in `PIPELINE.md`). Cover exactly what §Testing prescribes for your surface.
58
- Run the test command and watch it fail (red).
59
- 3. Implement until green, following §Conventions for your surface.
65
+ 2. **Write the failing test(s) first** from the frozen contract. Cover exactly what your baked
66
+ Testing rules (§Your conventions) prescribe. Run the test command and watch it fail (red).
67
+ 3. Implement until green, following your baked conventions.
60
68
  4. Refactor to the conventions. Keep tests green.
61
- 5. **Lint + format before handoff:** run your surface's `lint_cmd` from `PIPELINE.md` and fix every
62
- issue. If the project registers a PostToolUse format hook (see `.claude/settings.json`), your files
63
- are already formatted on every write — skip `format_cmd`; otherwise run it too. Code you hand off
64
- must be lint-clean and formatted.
69
+ 5. **Lint + format before handoff:** run your surface's lint and fix every issue. If the project
70
+ registers a PostToolUse format hook (see `.claude/settings.json`), your files are already
71
+ formatted on every write — skip `format_cmd`; otherwise run it too. Code you hand off must be
72
+ lint-clean and formatted.
73
+
74
+ **Run commands bridled — always.** Your surface's `test_quiet_cmd`/`lint_quiet_cmd` in `PIPELINE.md`
75
+ are the forms you execute (dot reporter / failures-only); when a quiet variant is empty or absent,
76
+ run `<full cmd> 2>&1 | tail -40`. Never print a full runner log into your context — redirect to a
77
+ file and grep it if you need more than the tail.
65
78
 
66
79
  ## Definition of done
67
80
 
@@ -72,7 +85,7 @@ of the contract your surface implements matches the spec exactly. User-facing co
72
85
 
73
86
  Your final message **is** the handoff (read by the lead, not a human chat). Keep it tight — the lead
74
87
  only acts on mismatches, test failures, remediation ticks, and TODOs; never list files one by one
75
- (the lead has `git diff --stat`):
88
+ (the lead has `git diff --stat`), never paste code excerpts (the code is on disk):
76
89
 
77
90
  ```
78
91
  # HANDOFF — <surface> · <feature_id>
@@ -0,0 +1,28 @@
1
+ ---
2
+ name: profile-reader
3
+ description: Reads PIPELINE.md and returns its `yaml pipeline-profile` block as compact JSON. Phase 0 of every cohorte workflow — workflow scripts have no filesystem or shell access, so this agent is how a script learns the profile (surfaces, commands, flags). Mechanical, read-only, no judgment.
4
+ tools: Read, Grep, Glob
5
+ model: haiku
6
+ ---
7
+
8
+ You are the **profile-reader**. One job, purely mechanical: load this project's `PIPELINE.md` and
9
+ return the machine block as JSON. A workflow script (which cannot read files itself) parses your
10
+ return and parameterizes every later phase from it — so fidelity beats brevity, and prose beats
11
+ nothing only when something is wrong.
12
+
13
+ ## How
14
+
15
+ 1. Read `PIPELINE.md` at the repo root — specifically the fenced ` ```yaml pipeline-profile ` block.
16
+ It can be long; read the whole block, nothing after it (the prose sections are not your job).
17
+ 2. Convert the YAML to JSON **faithfully**: every key and value as written, comments dropped,
18
+ nothing invented, nothing "fixed". Keep types honest (`true`/`false` booleans, numbers as
19
+ numbers, `""` stays an empty string). Unfilled template placeholders (values still wrapped in
20
+ `<…>`) pass through as the literal string — the caller decides what to do with them.
21
+ 3. Return **only** the JSON object — no fences, no commentary, no markdown. Your final message is
22
+ parsed by a script.
23
+
24
+ ## Failure shape
25
+
26
+ If `PIPELINE.md` is missing, or the `yaml pipeline-profile` fence is absent or unparseable, return
27
+ exactly one JSON object instead: `{"error": "<one line: what is missing or broken>"}` — never a
28
+ partial profile, never prose.
@@ -85,8 +85,12 @@ domain** (same finding-line shape) instead of a SHIP/REVISE/BLOCK verdict.
85
85
 
86
86
  Every finding must be **self-sufficient for a stateless agent**: `file:line` · severity ·
87
87
  `spec-violation | quality | security` · one concrete suggested fix — it gets appended verbatim to the
88
- spec's `## Remediation`. Your final message **is** the report. Emit nothing outside this shape — no
89
- restated rules, no "verified clean" lists:
88
+ spec's `## Remediation`. Your final message **is** the report. **The shape is capped:** at most
89
+ **20 findings**, ONE line each, **zero code excerpts** (the diff and the source are on disk — a
90
+ `file:line` is enough for a stateless fixer). More than 20? Keep every CRITICAL/HIGH/security
91
+ finding, fill the rest by severity, and close the list with one line:
92
+ `+<n> more MEDIUM/LOW — re-run after the fix loop`. Emit nothing outside this shape — no restated
93
+ rules, no "verified clean" lists:
90
94
 
91
95
  ```
92
96
  # REVIEW REPORT
@@ -104,7 +108,7 @@ Verdict: <SHIP | REVISE | BLOCK>
104
108
  ## Findings
105
109
 
106
110
  - **[<SEVERITY>]** `<file>:<line>` · <spec-violation|quality|security> · <problem> → **Fix:** <concrete change>
107
- (order by severity; "None." if none)
111
+ (order by severity; "None." if none; max 20 lines, one per finding, no code excerpts)
108
112
 
109
113
  ## Notes
110
114
  (ONLY the RBAC / mobile-first assessment when the profile enables them; omit the section otherwise)
@@ -57,5 +57,7 @@ assert on the pieces you need.
57
57
  - **Write the full report to `specs/reports/<id>.md`** (overwrite) — the same gitignored buffer
58
58
  `/review` uses, so a `/fix` after a `/clear` still has the failures.
59
59
  - Tear down what you started (kill the dev server); leave shared infra as you found it.
60
- - **Your return to the lead is ONLY:** the verdict line (`PASS` / `FAIL`), the lines verbatim (if
61
- any), and `Full report: specs/reports/<id>.md`. No logs, no bodies, no screenshots.
60
+ - **Your return to the lead is ONLY:** the verdict line (`PASS` / `FAIL:<n>`), **at most 10
61
+ lines** one line each (`❌ <flow/endpoint> · expected <x> got <y>`), no command output, no code
62
+ or body excerpts; more than 10 ⇒ keep the 10 most severe and add `+<n> more — see the report` —
63
+ and `Full report: specs/reports/<id>.md`. No logs, no bodies, no screenshots.
@@ -8,23 +8,31 @@ You are the **lead**. Audit **$ARGUMENTS** (default: whole repo) to drive it to
8
8
  analyze only — no fixes (those go through `/refactor`).
9
9
 
10
10
  > Read `PIPELINE.md` §`commands` (the mechanical gates), `surfaces`, and §Conventions.
11
+ >
12
+ > **Workflow variant** (opt-in — SCHEMA.md §Workflows): on Claude Code ≥ 2.1.154 with workflows
13
+ > enabled, the human can ask to "run the audit workflow" (`<core>/workflows/audit.js` — one auditor
14
+ > per domain, concurrent). This conversational path stays the default and the fallback.
11
15
 
12
16
  ## 1. Mechanical gates (you run these — Bash)
13
17
 
14
18
  Run the profile's checks **scoped to `$ARGUMENTS`** when a path/domain is given (lint/format/typecheck
15
19
  on that path, tests via that surface's `test_cmd`); repo-wide only for the default whole-repo audit.
16
- Redirect each command's output into `specs/reports/audit-gates.txt` in the same call
17
- (`cmd > specs/reports/audit-gates.txt 2>&1`) so the bulk never sits in your history, then grep it for
18
- the `file:line` of every failure: `commands.format` in check mode (e.g. `prettier --check .` /
19
- `ruff format --check`), `commands.lint`, `commands.typecheck`, `commands.test`.
20
+ Use the quiet variants (`commands.lint_quiet`/`test_quiet`, else the `2>&1 | tail -40` fallback —
21
+ SCHEMA.md §Output discipline) and redirect each command's output into
22
+ `specs/reports/audit-gates.txt` in the same call (`cmd > specs/reports/audit-gates.txt 2>&1`) so the
23
+ bulk never sits in your history, then grep it for the `file:line` of every failure:
24
+ `commands.format` in check mode (e.g. `prettier --check .` / `ruff format --check`),
25
+ `commands.lint`, `commands.typecheck`, `commands.test`.
20
26
 
21
27
  ## 2. Convention + TDD audit (dispatch `review` in audit mode)
22
28
 
23
- Dispatch `review` (read-only): "Audit `$ARGUMENTS` against `PIPELINE.md` (no spec**audit mode**).
24
- Check conventions (§Conventions per surface), TDD coverage (untested entry points / modules per surface),
25
- and if the profile enables them mobile-first + design-system usage. Mechanical findings from the
26
- gates: read `specs/reports/audit-gates.txt`. Emit a prioritized refactor backlog (finding-line format
27
- from your instructions), grouped by domain (one group per surface + shared)."
29
+ Dispatch `review` (read-only; static prompt first, variable slot lastprompt-cache prefix):
30
+ "Audit a target against `PIPELINE.md` (no spec **audit mode**). Check conventions (§Conventions
31
+ per surface), TDD coverage (untested entry points / modules per surface), and if the profile
32
+ enables them — mobile-first + design-system usage. Mechanical findings from the gates: read
33
+ `specs/reports/audit-gates.txt`. Emit a prioritized refactor backlog (capped finding-line format
34
+ from your instructions), grouped by domain (one group per surface + shared). — Target: `$ARGUMENTS`
35
+ (default: whole repo)."
28
36
 
29
37
  ## 3. Write the backlog
30
38
 
@@ -21,8 +21,8 @@ fix only with the human's go-ahead (or hand them the command).
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`, `new-feature.sh.template`, `remove-feature.sh.template`
25
- — ❌ any missing one. Every caller chains these with `|| true`, so an absent script is a **silent**
24
+ `kanban-move.sh`, `telemetry-send.sh`, `preflight.sh`, `new-feature.sh.template`,
25
+ `remove-feature.sh.template` — ❌ any missing one. Every caller chains these with `|| true`, so an absent script is a **silent**
26
26
  no-op (no kanban card moves, no telemetry ping, no error anywhere) — this check is the only thing
27
27
  that sees it. Also flag ❌ a `VERSION` **newer than** the other `pipeline/` files (compare mtimes):
28
28
  a version bumped without a full re-copy is a half-done update ⇒ re-run install/update.
@@ -34,8 +34,8 @@ fix only with the human's go-ahead (or hand them the command).
34
34
  its `surfaces[].model` — ❌ if missing, mismatched, or a literal `<SURFACE_MODEL>` placeholder
35
35
  (all three silently fall back to inheriting the lead session's model — often Opus — on every
36
36
  dispatch); ⚠️ any `inherit` with the note that it bills at the lead's tier. The generic agents
37
- (`review.md`, `release.md`, `smoke.md` — repo or `~/.claude/agents/`) must each carry their
38
- `model:` line too (sonnet/haiku/sonnet). **Command pins:** every mechanical command file
37
+ (`review.md`, `release.md`, `smoke.md`, `profile-reader.md` — repo or `~/.claude/agents/`) must
38
+ each carry their `model:` line too (sonnet/haiku/sonnet/haiku). **Command pins:** every mechanical command file
39
39
  (`build`, `review`, `fix`, `smoke`, `ship`, `audit`, `refactor`, `doctor`, `align-ds`,
40
40
  `update-pipeline` — in `.claude/commands/` or `~/.claude/commands/`) carries `model: sonnet` in
41
41
  its frontmatter — ⚠️ if missing (the lead's orchestration turn then bills at the session model,
@@ -66,7 +66,23 @@ fix only with the human's go-ahead (or hand them the command).
66
66
  incoherent state: `enabled: true` with no `install_id` or no `consent_date` (sending without
67
67
  recorded consent — fix: set `enabled: false` until the consent question is re-run), or a
68
68
  `telemetry:` block missing entirely on a current core (top up via `/update-pipeline`).
69
- 8. **Specs & metrics.** Every `specs/*.md` front-matter `status` is a valid stage; `shipped` specs
69
+ 8. **Workflows** (the opt-in execution path SCHEMA.md §Workflows; the conversational commands
70
+ stay the default, so failures here are ⚠️ at most, never ❌). Report which path this machine will
71
+ take and why:
72
+ - **Claude Code version** ≥ 2.1.154 (`claude --version 2>/dev/null | head -1`) — older or no CLI
73
+ on PATH ⇒ conversational only.
74
+ - **Scripts present:** `<core>/workflows/review.js` + `audit.js` + `refactor.js` + `cycle.js` —
75
+ missing on a current core ⇒ half-done install, re-run install/update.
76
+ - **Phase-0 agent present:** `<agents dir>/profile-reader.md` (repo `.claude/agents/` bundled or
77
+ `~/.claude/agents/` global) — the workflows abort without it.
78
+ - **Workflows enabled in this session** — the `Workflow` tool is in your own toolset right now;
79
+ absent ⇒ disabled for this session (a setting or an old client), conversational path.
80
+ - **Preflight wiring** (used by both paths): `pipeline/scripts/preflight.sh` executable and
81
+ `gate-config.json` carries the `preflight` block — mismatch ⇒ regenerate from the profile.
82
+ End the check with ONE summary line, e.g.
83
+ `workflows: available (opt-in — ask to "run the review workflow")` or
84
+ `workflows: unavailable (<first failing prerequisite>) — conversational commands (the default)`.
85
+ 9. **Specs & metrics.** Every `specs/*.md` front-matter `status` is a valid stage; `shipped` specs
70
86
  with a live worktree flagged (see 6). `.claude/pipeline-metrics.jsonl` and `specs/reports/` (the
71
87
  `/review`·`/smoke` report buffer that lets a `/fix` survive a `/clear`) are gitignored. Metrics
72
88
  belong to the **main checkout** — a `pipeline-metrics.jsonl` inside a live feature worktree is a
@@ -7,6 +7,11 @@ argument-hint: <domain…> (one or more surface keys, "shared", or "all")
7
7
  You are the **lead**. Refactor domain **$ARGUMENTS** to match `PIPELINE.md`, using the `/audit` backlog.
8
8
 
9
9
  > Read `PIPELINE.md` §`surfaces` (map the domain → a surface + its agent + commands) and §`contract`.
10
+ >
11
+ > **Workflow variant** (opt-in — SCHEMA.md §Workflows): for BIG domains (many open backlog items
12
+ > across several surfaces), on Claude Code ≥ 2.1.154 with workflows enabled, the human can ask to
13
+ > "run the refactor workflow" (`<core>/workflows/refactor.js`). For a handful of items this
14
+ > conversational path is cheaper — and it stays the default and the fallback.
10
15
 
11
16
  ## 1. Gather
12
17
 
@@ -42,9 +47,9 @@ slices import it, so refactor it alone, first.
42
47
 
43
48
  ## 3. Verify & loop
44
49
 
45
- After each agent returns: its surface's `test_cmd`/`lint_cmd`, `commands.typecheck`,
46
- `commands.format --check` (redirect output to a file and grep it — don't print gate output into your
47
- context). Then verify each backlog item cleared by checking its `file:line` directly — do NOT re-run
50
+ After each agent returns: its surface's `test_quiet_cmd`/`lint_quiet_cmd` (else the `tail -40`
51
+ fallback — SCHEMA.md §Output discipline), `commands.typecheck`, `commands.format --check` (redirect
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
48
53
  `/audit` per round (that repeats the repo-wide gates + a review dispatch you don't need); one optional
49
54
  final `/audit` once ALL dispatched domains are clean is enough. Check cleared items off in
50
55
  `specs/refactor-backlog.md`. Loop until each dispatched domain is clean. Verification is per-domain
@@ -6,22 +6,46 @@ argument-hint: <feature_id>
6
6
 
7
7
  You are the **lead**. Dispatch the review for feature **$ARGUMENTS**.
8
8
 
9
- > Read `PIPELINE.md` §`vcs.default_branch` (diff base) and the `surfaces`/`contract` fields.
9
+ > Read `PIPELINE.md` §`vcs.default_branch` (diff base) and the `surfaces`/`contract`/`commands` fields.
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): move card `#$ARGUMENTS` → **Review**. No-op silently if no board.
13
+ >
14
+ > **Workflow variant** (opt-in — SCHEMA.md §Workflows): on Claude Code ≥ 2.1.154 with workflows
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.
17
+
18
+ ## 0. Deterministic pre-flight — no agents while red
19
+
20
+ Run the profile's mechanical gates in ONE Bash call via the shipped script
21
+ (`<core>/pipeline/scripts/preflight.sh`, `<core>` = `.claude` bundled / `~/.claude` global — probe
22
+ with `test -x`); note the epoch (`date +%s`) in the same call — §3's metrics line needs it:
23
+
24
+ ```
25
+ <core>/pipeline/scripts/preflight.sh specs/reports/$ARGUMENTS.preflight.txt \
26
+ "<commands.typecheck>" "<commands.lint_quiet, else lint>" "<commands.test_quiet, else test>"
27
+ ```
28
+
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
31
+ rediscovers it at agent prices. This abort is the whole point of the step.
32
+ - **Zero exit** ⇒ it stamped `.claude/preflight.ok`, which the gate hook checks before letting
33
+ `review`/`smoke` dispatches through (SCHEMA.md §Preflight). Continue.
34
+ - Script absent (older core) ⇒ run the three commands yourself, each redirected into
35
+ `specs/reports/$ARGUMENTS.preflight.txt`, aborting on the first failure the same way.
13
36
 
14
37
  ## 1. Gather the inputs for stateless reviewers
15
38
 
16
39
  - Confirm `specs/$ARGUMENTS.md` exists.
17
- - Compute the diff, and let **git do the grouping** (deterministic don't reason it out file by file):
18
- per surface, `git diff <default_branch> --name-only -- <surface.path>` is exactly that surface's changed
19
- files; the **`shared` remainder** (contract file + anything outside every surface) is
20
- `git diff <default_branch> --name-only -- . $(for p in <each surface.path>; do printf ':(exclude)%s ' "$p"; done)`.
21
- Attach the remainder to the most relevant surface's reviewer and say so in its dispatch. A surface whose
22
- `git diff` comes back empty gets no reviewer.
23
- - **Stage the hunks** (reviewers are read-only — no Bash — so a staged diff file is the ONLY way they
24
- can review hunks instead of re-reading whole files). Per touched surface, regenerated every round:
40
+ - **Compute the diff ONCE `--stat` first, patches only for retained surfaces.** One call:
41
+ `git diff <default_branch> --stat > specs/reports/$ARGUMENTS.stat.txt`, then grep that file to
42
+ group the changed paths by `surfaces[].path` prefix (deterministic don't reason it out file by
43
+ file). Paths under no surface (contract file, root config) are the **`shared` remainder**: attach
44
+ them to the most relevant surface's reviewer and say so in its dispatch. A surface with no changed
45
+ paths gets no reviewer — and no `.diff` is ever generated for it.
46
+ - **Stage the hunks once per touched surface** (reviewers are read-only — no Bash — so the staged
47
+ diff file is the ONLY way they can review hunks instead of re-reading whole files, and staging it
48
+ here means N reviewers never re-run git N times). Regenerated every round:
25
49
  `git diff <default_branch> -- <surface.path> > specs/reports/$ARGUMENTS.<surface.key>.diff`
26
50
  (same gitignored buffer dir as the reports). For the surface that carries the shared remainder,
27
51
  append the remainder pathspecs to its command so its `.diff` includes them. Never print a diff into
@@ -40,16 +64,20 @@ prescribed fixes land? — NOT a de-novo audit) and write the same REVIEW REPORT
40
64
  First-round reviews, contract changes, and security findings always get a full reviewer. For each
41
65
  dispatched surface:
42
66
 
43
- > `subagent_type: review` "Review feature `$ARGUMENTS` **scope: the `<surface.key>` surface
44
- > only**. Read `PIPELINE.md` first (its flags + §Conventions/§Testing for `<surface.key>`). Spec:
45
- > `specs/$ARGUMENTS.md` (source of truth). Contract: `<contract.path>/$ARGUMENTS.<ext>`. Diff to
46
- > review: `specs/reports/$ARGUMENTS.<surface.key>.diff` (staged hunks read it FIRST; open a full
47
- > source file only when a finding demands it). Check spec conformance first, then correctness,
48
- > security, conventions, RBAC/mobile-first _if the profile enables them_, and TDD coverage. Emit
49
- > the REVIEW REPORT in the format your agent instructions define every finding self-sufficient
50
- > (`file:line` · severity · type · concrete fix). Changed files (`--stat`): <list>."
67
+ Keep the dispatch prompt **byte-identical across features and rounds** except the variable block,
68
+ which sits at the END so every repeat hits the prompt-cache prefix:
69
+
70
+ > `subagent_type: review` "Review one feature surface against its frozen spec. Read `PIPELINE.md`
71
+ > first (flags + the §Conventions/§Testing slice for your scope). Check spec conformance first, then
72
+ > correctness, security, conventions, RBAC/mobile-first _if the profile enables them_, and TDD
73
+ > coverage. Your dispatch names a staged diff file read it FIRST; open a full source file only when
74
+ > a finding demands it. Emit the REVIEW REPORT in the capped format your agent instructions define —
75
+ > every finding self-sufficient (`file:line` · severity · type · one-line concrete fix), no code
76
+ > excerpts. — Variable slots: feature `$ARGUMENTS` · scope: the `<surface.key>` surface only · spec:
77
+ > `specs/$ARGUMENTS.md` (source of truth) · contract: `<contract.path>/$ARGUMENTS.<ext>` · staged
78
+ > diff: `specs/reports/$ARGUMENTS.<surface.key>.diff` · changed files (`--stat`): <list>."
51
79
 
52
- The staging command in §1 already gave you the wall-clock start (`date +%s` in the same call) — §3's
80
+ §0's preflight call already gave you the wall-clock start (`date +%s` in the same call) — §3's
53
81
  metrics line needs it.
54
82
 
55
83
  ## 3. Merge & relay the verdict
@@ -8,24 +8,38 @@ You are the **lead**. Dispatch the smoke run for feature **$ARGUMENTS** — the
8
8
  runs it so the bulky output (curl bodies, server logs, screenshots, design payloads) never enters
9
9
  your own context, which is re-sent every turn.
10
10
 
11
- > Read `PIPELINE.md` §`pipeline-profile`: `isolation` (worktree, slot ports, db) and `contract.path`.
12
- > _Skip the re-read if it's already in your context this session and unmodified since._
11
+ > Read `PIPELINE.md` §`pipeline-profile`: `isolation` (worktree, slot ports, db), `contract.path`
12
+ > and `commands`. _Skip the re-read if it's already in your context this session and unmodified since._
13
13
  >
14
14
  > **Kanban:** none here — `/review` owns the → **Review** move (running both duplicated it).
15
15
 
16
+ ## 0. Deterministic pre-flight — no agents while red
17
+
18
+ Same gate as `/review` §0, run **in the feature's checkout** (§1 resolves it — resolve first, then
19
+ preflight): `<core>/pipeline/scripts/preflight.sh specs/reports/$ARGUMENTS.preflight.txt
20
+ "<commands.typecheck>" "<commands.lint_quiet, else lint>" "<commands.test_quiet, else test>"`.
21
+ Non-zero exit ⇒ the raw last-40 lines were already printed — **STOP, relay them verbatim, spawn NO
22
+ agent**: booting infra to smoke-test code that doesn't compile wastes the whole run. Zero exit ⇒
23
+ the `.claude/preflight.ok` stamp lets the gate hook pass your `smoke` dispatch. Script absent
24
+ (older core) ⇒ run the commands yourself redirected to the same file, aborting on the first failure.
25
+ Note the epoch (`date +%s`) in the same call — §3's metrics line needs it.
26
+
16
27
  ## 1. Resolve the checkout
17
28
 
18
29
  With `isolation.enabled`: the sibling worktree (`../<slug>-$ARGUMENTS`, its slot's ports + db from
19
- `.worktrees/slots.tsv`); otherwise the main checkout on the feature branch. Note the epoch
20
- (`date +%s`) in the same Bash call that reads the slot — §3's metrics line needs it.
30
+ `.worktrees/slots.tsv`); otherwise the main checkout on the feature branch.
21
31
 
22
32
  ## 2. Dispatch ONE `smoke` agent
23
33
 
24
- > `subagent_type: smoke` — "Smoke-test feature `$ARGUMENTS`. Read `PIPELINE.md` first. Spec:
25
- > `specs/$ARGUMENTS.md`. Contract: `<contract.path>/$ARGUMENTS.<ext>`. Checkout: `<worktree path or
26
- > main checkout>` · ports/db: `<slot info, or defaults>`. Bring it up, exercise the contract and the
27
- > §8 UI flows, stage the full SMOKE REPORT to `specs/reports/$ARGUMENTS.md`, tear down, and return
28
- > only the verdict + failure lines."
34
+ Keep the prompt byte-identical across features except the variable block at the END (prompt-cache
35
+ prefix):
36
+
37
+ > `subagent_type: smoke` "Smoke-test one feature. Read `PIPELINE.md` first. Bring it up, exercise
38
+ > the contract and the §8 UI flows, stage the full SMOKE REPORT to the report buffer, tear down, and
39
+ > return only the capped verdict your agent instructions define (verdict + ❌ lines, no logs). —
40
+ > Variable slots: feature `$ARGUMENTS` · spec: `specs/$ARGUMENTS.md` · contract:
41
+ > `<contract.path>/$ARGUMENTS.<ext>` · report: `specs/reports/$ARGUMENTS.md` · checkout: `<worktree
42
+ > path or main checkout>` · ports/db: `<slot info, or defaults>`."
29
43
 
30
44
  The gate hooks fire on the agent's Bash calls too — compose/migrate confirmations still reach the
31
45
  human; that's expected.
@@ -68,10 +68,16 @@ skip silently.
68
68
 
69
69
  Only when the current repo has a `PIPELINE.md`: run the **Reconcile procedure** from the installed
70
70
  `pipeline/SCHEMA.md` §Reconcile — top up the profile's machine block with new fields at their defaults
71
- (one batched question set for any genuinely new human decision, e.g. choosing a `retrieval` provider),
72
- re-render the surface agents from the current `implementer.template.md`, additively patch
73
- `settings.json`/`gate-config.json`, and run any newly-added capability's wiring (e.g. Serena's
74
- project-scope `claude mcp add`). Even when no capability is new, **re-run the retrieval provider's
71
+ (one batched question set for any genuinely new human decision e.g. choosing a `retrieval` provider,
72
+ or the **quiet command variants**: `test_quiet_cmd`/`lint_quiet_cmd` + `commands.test_quiet`/
73
+ `lint_quiet`, proposing the detected bridled forms per §Output discipline; `gate.preflight` tops up
74
+ silently at its defaults), re-render the surface agents from the current `implementer.template.md`
75
+ (this refreshes each agent's **baked §Conventions slice** — required after any hand-edit of the
76
+ profile's prose), additively patch `settings.json`/`gate-config.json` (including the `preflight`
77
+ block and the workflow-agent `allow` entries from init step 5), and run any newly-added capability's
78
+ wiring (e.g. Serena's project-scope `claude mcp add`). Verify the refreshed core actually carries
79
+ `<core>/workflows/` + `agents/profile-reader.md` — missing means the update half-ran: re-run the
80
+ installer. Even when no capability is new, **re-run the retrieval provider's
75
81
  health check** (SCHEMA.md §Code retrieval: CLI resolvable from PATH, `.mcp.json` entry present —
76
82
  upgrading a bare `serena` entry to the PATH-proof launcher form, `.serena/` gitignored, server
77
83
  actually connected) and repair whatever fails — wiring that worked at