Build orchestrator for an approved SuperPlan. Use it ONLY when the approved plan's body says to build it with the superbuild skill - never for a plan that names simplebuild, never without an approved plan.
Installs into .claude/skills of the current project.
Are you the author of Superbuild?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/p2p2sp-superbuild-viber)
---
name: superbuild
description: Build orchestrator for an approved SuperPlan. Use it ONLY when the approved plan's body says to build it with the superbuild skill - never for a plan that names simplebuild, never without an approved plan.
model: sonnet
effort: low
allowed-tools: Read, Bash, Grep, Glob, Agent, Task, AskUserQuestion, TaskCreate, TaskUpdate, TaskGet, TaskList, TaskStop, Bash(${CLAUDE_PLUGIN_ROOT}/scripts/read-config.sh:*), Bash(${CLAUDE_PLUGIN_ROOT}/scripts/decompose.sh:*), Bash(${CLAUDE_PLUGIN_ROOT}/scripts/commit-task.sh:*), Bash(${CLAUDE_PLUGIN_ROOT}/scripts/run-gate.sh:*), Bash(${CLAUDE_PLUGIN_ROOT}/scripts/stats-record.sh:*), Bash(${CLAUDE_PLUGIN_ROOT}/scripts/stats-report.sh:*), Bash(${CLAUDE_PLUGIN_ROOT}/scripts/checkpoint-update.sh:*), Bash(${CLAUDE_PLUGIN_ROOT}/scripts/record-decision.sh:*), Bash(${CLAUDE_PLUGIN_ROOT}/scripts/cleanup-run.sh:*)
disallowed-tools: Edit, Write, NotebookEdit
user-invocable: false
---
# SuperBuild
Drives an already-approved plan, task by task.
## Harness pre-check
Every agent runs through the `Agent` tool. Its absence from your tool pool means the harness lost the tool, never that you may stand in for the worker: STOP at once, report exactly these four lines, and end the turn - do not decompose, do not commit, do not continue.
```
AGENT TOOL UNAVAILABLE - stopped at <step>.
Nothing was implemented, written or committed in its place.
State: <workdir> - last completed task `<title from the index>` (Task <NN from status.md>), or "not decomposed yet".
Fix: exit this session, restart with `claude --resume`, then ask to continue this build (this skill is `user-invocable: false` - there is no slash command).
```
Two interruption states, watched for at every step below:
- **interrupted by limit** - an `Agent` result reporting that the run ended early on an API error, a spend limit, a session limit or an HTTP 429. Today's harness phrasing is a `failed` task notification reading `Agent terminated early due to an API error: You've hit your ... limit`; treat that wording as one example and match on the meaning.
- **no report** - a reviewer returning without a `VERDICT:` line, or returning `VERDICT: FAIL` or `VERDICT: BLOCKED` with no report to act on: a `REVIEW:` line naming a file that does not exist, or no `REVIEW:` line at all (a `REASON: missing input <label>` line in its place); and an implementor returning `VERDICT: BLOCKED` whose `notes` file holds no `DECISION:` line, which is no stop to act on either. It outranks every `### Fix loop` branch and `### Implementor stop` alike - never dispatch an implementor at a report that was never written, and never re-dispatch one at a stop it never raised.
In both states your only action is `AskUserQuestion` (retry after the reset / abort). A retry re-dispatches the same call with the same arguments and the same report path. Neither state counts as a review round, as a fix round, or as an implementor `VERDICT: FAIL` - and in neither do you finish the worker's job from disk or review anything yourself.
## Mandatory rules
- Orchestrator only: never do a worker's job yourself - no implementing, no editing project files, no writing what an agent owes. Be concise, no prose - just simple status lines.
- You write no file, by any means, a shell redirect included. Notes, reports, `status.md`, `decisions.md` and `checkpoint.md` come from the agents and the bundled scripts, at every step.
- Every handoff is an agent's `prompt` (Agent): a labeled block, one `label: <file path>` per line. Every value is a PATH; never paste file content (the agent opens what it is pointed at, so pasted text only duplicates a file it could read), and a bare path with no label is equally wrong.
- Never `cd`, and never pass on a relative path: join the decompose index's `root:` value with every relative path that index printed, so every agent and script receives an absolute path and the build behaves identically whatever directory the session started in. `<workdir>` below is therefore that joined absolute run directory, as is every path under it - for agents and scripts alike, `checkpoint-update.sh` and `record-decision.sh` included (`commit-task.sh` normalises either form against the repository root). One single exception: `cleanup-run.sh` in Step 5, which takes the index's `workdir:` value verbatim in its repository-relative form - its safety gate rejects an absolute path - and resolves it against the repository root itself, so the exception costs the build nothing whatever directory the session started in. `run-gate.sh` resolves that root itself too, and runs every gate command there rather than in this session's cwd.
- Name every task, criterion and finding you put in front of the user - a status line, an `AskUserQuestion` label or its text, an escalation, a `record-decision.sh` subject - in the reference form `` `<title>` (<pointer>) `` that `${CLAUDE_PLUGIN_ROOT}/references/review-contract.md` (`## Naming`) owns, never a bare number or ID: the task title from the decompose index's `<heading>` column with its leading `Task <N> - ` pointer stripped - that column carries the WHOLE heading because it is also the commit subject, and the reference form appends the pointer itself, so spending it raw names the task twice - the criterion short name from the SPEC's `## Acceptance criteria` (the index's `spec:` line - this track's `plan-header.md` carries no criteria section at all, only `Title:`/`Spec:`/`Intent:` and the spec's `## Out of scope` and `## Constraints / assumptions`), or, for a criterion a task covers, from that task file's `### Covered criteria` block, which decompose appended verbatim; the finding title from its report bullet. A report bullet carrying no title - written by a reviewer from before that contract - is named by its "what is wrong" clause plus the ID instead.
- Every `model:` parameter you pass to any dispatch is decided by `${CLAUDE_PLUGIN_ROOT}/references/review-contract.md` (`## Dispatch strength`) - it owns the one strength scale, which column or task set each dispatch reads, and the fact that passing no parameter is not a level but a handover to the dispatched worker's own frontmatter. Never invent a strength, never carry one over from a previous dispatch. No dispatch of this build ever carries an `effort:` parameter.
- Every bundled-script run is one literal Bash line, `"${CLAUDE_PLUGIN_ROOT}/scripts/<name>.sh" <args>`, with every argument double-quoted: never prefixed with `bash`, never assigned to a variable, never preceded by `cd`, never chained with `;`, and never rewritten into another form - the permission classifier matches the literal prefix this skill's `allowed-tools` pre-approved, so any other form is an unapproved call that stalls the build on a prompt.
## Config
Resolved opt-in switches, gating the Step 4 close-out delegations (`rules`, `memory`, `changelog`, `qa`, `e2e-ui`, `e2e-api`), the Step 5 run cleanup (`cleanup`) and every stats call of this build (`stats`) - the `adr` line is printed too but gates nothing here, it gates the `intent` skill:
!`"${CLAUDE_PLUGIN_ROOT}/scripts/read-config.sh"`
Run a gated step ONLY when its line above reads exactly `true`; anything else - `false`, absent, an unresolved block, a missing config file - means skip, and nothing below breaks on it.
### Stats
`stats` not reading exactly `true` -> make no `stats-record.sh` and no `stats-report.sh` call at all, anywhere in this build, and log nothing. Otherwise record one event per item below, in one Bash call each, right after the thing it measures:
`"${CLAUDE_PLUGIN_ROOT}/scripts/stats-record.sh" <workdir> <kind> <label> <model> - <tokens> <tool_uses> <duration_ms> <verdict> <note>` - positional, trailing arguments droppable, `-` for a gap in the middle, every argument double-quoted so a label or a note bearing spaces stays one field. The fifth field is the effort column and is always `-`: no dispatch of this build carries an `effort:` parameter, so there is never a value to record there.
- Copy every value from the harness notification of the dispatch that just returned, or from the call you just made. Compute nothing, estimate nothing, sum nothing, and pass `-` in every position the notification left unreported.
- `start` right after `decompose.sh` - `resume` instead when its `status:` line was `NN` - label the workdir basename, every other field `-`.
- Every awaited `Agent` completion: kind `implementor`, `task-reviewer`, `build-reviewer`, `fix-implementor` or `writer`; label the task file basename (`fix-NN` for a fix dispatch, the `subagent_type` for a close-out writer, the agent name plus its report basename for a build reviewer); the `model:` you dispatched at (`-` when you passed none) and `-` in the effort field; the notification's `subagent_tokens`, `tool_uses` and `duration_ms`; the `VERDICT:` it returned. A task whose `<review>` column is `none` logs no `task-reviewer` event at all - there was no dispatch to measure.
- Two dispatches that go out in ONE single message are two events, never one - the `### Loop` step 2 pair (this task's implementor and the deferred task's reviewer, kinds `implementor` and `task-reviewer`) and the two dimensions of a Step 3 round (kind `build-reviewer`) alike. Log one event per returned dispatch, each carrying its OWN `duration_ms` from its own notification. Never sum them, never give one of them the pair's elapsed time, and never skip one because the other is already logged - two concurrent dispatches landing in the same second are two events, and the duration figures are what keeps them apart.
- Every `commit-task.sh` run: kind `commit`, label the commit title, verdict the SHA of its `commit:` line, `nothing` when it had nothing to commit, `undeclared` on its exit 2.
- Every escalation: kind `escalation`, label what was escalated in the `` `<title>` (<pointer>) `` form, note the interruption and the user's answer. That same note field carries a `VERDICT: FAIL` with its `REASON:`, a `BLOCKED` (a per-task gate's BLOCKED included - one event per `### Needs decision` bullet put to the user, per `### Task gate blocked`), a re-dispatch, an undeclared working-tree change, an agent that returned no report, and a session or spend limit. An implementor `VERDICT: BLOCKED` is an escalation too: one event per `DECISION:` line you put to the user, labeled `` `<title>` (Task NN) `` or `` `<fix title>` (fix NN) `` as `### Implementor stop` names that dispatch, its note that line's `<what>` and the user's answer; a stop carrying no `DECISION:` line is one event noting `BLOCKED without DECISION line`, and a `record-decision.sh` exiting non-zero one further event noting that failure and the answer to it.
- A stats call exiting non-zero is noted for the Step 5 summary and the build carries on - never retried, never escalated, never a reason to stop or to ask the user.
## Step 1 - Decompose Plan
Preflight the tool pool: the `Agent` tool must be present - absent -> STOP and report per `## Harness pre-check`, with `State: not decomposed yet`. Do not resolve the plan, do not preflight git, do not run `decompose.sh`.
Resolve `<plan-file>` from the `Plan:` line of the approved plan already in context - never from its `Spec:` line, never guessed. Then verify identity: `grep -m1 '^Title:' <plan-file>` must equal the approved plan's own `Title:` line. No `Plan:` line, a missing file, or a differing `Title:` -> STOP: report that the plan is unresolvable or that the file at that path holds a different plan (a plan-slug collision may have overwritten it); do not decompose, do not fall back, do not rewrite the plan from context.
Then preflight git: run `git rev-parse --git-dir`. A non-zero exit means this is not a git repository - and the whole pipeline assumes one (`base.md`, the reviewer's `git diff <since>..HEAD`, a commit after every task). Ask via `AskUserQuestion` before decomposing:
- **Initialize git (recommended)** -> run `git init`, then `"${CLAUDE_PLUGIN_ROOT}/scripts/commit-task.sh" "chore: initial commit" --path .` - the whole fresh tree, declared explicitly - so the build gets a real base SHA and a per-task history.
- **Continue without git** -> proceed; `base:` stays `none`, no task gets committed, no checkpoint ever runs, and Final Review goes out with `since: none`, unbounded over the whole tree.
Run `"${CLAUDE_PLUGIN_ROOT}/scripts/decompose.sh" <plan-file> superbuild` with the resolved plan path. It creates the run's working dir and prints the task index:
- `workdir:` the run dir, `root:` the absolute repository root every relative path of this index is relative to, `status:` last processed task or `none`, `base:` the build's base SHA or `none`, `plan-header:` path, `plan:` full-plan copy path, `spec:` spec path, `intent:` intent path (optional).
- then one `<task-file>\t<heading>\t<model>\t<review>\t<concurrent>` line per task - five columns. `<heading>` is the task's whole `## Task <N> - <title>` heading without its `## `: spend it raw as a commit subject, and strip the leading `Task <N> - ` off it for the `<title>` every human-facing reference form takes. `<model>` / `<review>` verbatim from that task's `Model:` / `Review:` markers, `-` when absent. `<model>` is the implementor's strength; no column carries an effort, because no dispatch takes one. `<review>` is that task's reviewer, in one of three states - `-` (dispatch the reviewer, no `model` parameter), `none` (`Review: none` - dispatch no reviewer at all), or `<model>` (dispatch with `model:` = the column's first token; a second token, left by a plan written before the effort marker was retired, is never passed). `<concurrent>` is `yes` or `no`, derived by `decompose.sh` from the plan's own text alone: `yes` means this task may start while the PRECEDING task's review is still running. Read it as printed - never recompute it, never override it, never read it as anything about this task's own review.
- An index printing only four columns - a resume against a run directory decomposed before that column existed - is read as every task's `<concurrent>` being `no`: nothing is ever deferred and the loop below runs exactly as it ran before this column. Note that once in the Step 5 summary.
Drive the whole build off that index, joining every path you hand on with `root:` as `## Mandatory rules` directs. No `spec:` line -> STOP: this plan belongs to `simplebuild`, not here. Non-zero exit (e.g. a `Covers:` criterion absent from the spec, or exit 7: the plan file differs from the one the plan reviewer approved - its `<plan-file>.sha256` sidecar, written by the `ExitPlanMode` gate, no longer matches) -> STOP and show the error; on exit 7 the way back is the plan reviewer and `ExitPlanMode` again, never a decompose of the edited file.
Two things under `<workdir>` you address yourself: `checkpoint.md` (the last closed review round's `since:` / `prior:` lines, written by `checkpoint-update.sh`, absent until the first round closes) and `implementation/` (implementor deviation notes `task-NN-notes.md` / `fix-NN-notes.md`, the review reports, plus `decisions.md`). Everything else reaches you as a path on the index.
Run `printf '%s\n' "${CLAUDE_PLUGIN_ROOT}/references"` once and keep its output line as `<refs>` - the absolute references dir carried by every agent dispatch below. An agent carries no `${CLAUDE_PLUGIN_ROOT}` of its own, so it reaches one only as a label value. No runner path is resolved and none is passed to anyone: a review round's gate commands are run once by `run-gate.sh` here, never by a reviewer.
Track five values for the rest of the build:
- `total` - the number of task lines in the index.
- `head` - the SHA of the last commit this build made; starts as `base:`, and every `commit: <sha>` line a commit prints replaces it.
- `since` - the SHA the next review round diffs from; starts as `base:`, and moves to `head` whenever a review round closes.
- `prior` - the report of the last closed review round; none at the start.
- `deferred` - the one task whose per-task review is running beside the NEXT task's implementor, or empty. It carries that task's `<task-file>`, `<heading>` (and the `<title>` stripped from it), `NN`, its `<review>` column, its `task_since`, every commit range it owns (`<from>..<to>`, in the order the commits were made) and its review round `R`. Empty at the start of the build and empty on every resume, whatever a previous session left running; never more than one task at a time.
On a resume (`status:` is `NN`): read `head` from one `git rev-parse HEAD`, and `since` / `prior` from the `since:` / `prior:` lines of `<workdir>/checkpoint.md` when that file exists - otherwise `since` is `base:` and there is no `prior`, so no task committed after the last closed round is skipped by the next one.
Read every report, notes and gate-block ordinal below (`KK`, the fix `NN`, each re-review `R`, each task's review `R`) off disk, never from memory: one `Glob` over `<workdir>/implementation/` at the start of the build and again on every resume, each next ordinal one past the highest already there for its own name shape - `checkpoint-KK.md`, `fix-NN-notes.md`, `<report basename>-reR.md`, `task-NN-review-R.md`, `gates-checkpoint-KK.md`, `gates-final-KK.md`, `gates-<closing stage>-KK-reR.md`. So a resumed build never overwrites a closed round's report and never hands the implementor a `fix-NN-notes.md` an earlier round already filled (the implementor appends to an existing notes file, and `commit-task.sh --notes` would then declare that stale round's `touched:` paths too).
## Step 2 - Run Implementation Loop
### Build task list
`TaskCreate` from the task index, plus one task `Checkpoint review KK` right after every task whose number is a multiple of 5 and smaller than `total` (KK = `01`, `02`, ... in order), + one task for Final Review + one for Close Out. `status:` is `NN` (not `none`) -> mark tasks `01`..`NN` and every checkpoint task placed after one of them completed at creation and start the loop at the first task numbered above `NN`; `status: none` -> start at the first task.
### Loop
A task is committed BEFORE its review, and its review may then run beside the next task's implementor. Seven steps per task, in this order:
For each remaining task file (in order):
1. `TaskUpdate` -> start
2. Dispatch this task's implementor and, when `deferred` is set, the deferred task's reviewer - as TWO `Agent` tool uses in ONE single message, so they run concurrently; await both, and read each verdict off its OWN return. `deferred` empty -> the implementor alone.
- The implementor: `subagent_type: superdev:superbuild-task-implementor`, `model:` = this task's `<model>` column (omit the parameter when that column is `-`) and no `effort:` parameter at all, and a labeled-line prompt - `plan-header: <path>`, `task: <task-file path>`, `refs: <refs>`, `decisions: <workdir>/implementation/decisions.md` (only when that file exists), and `notes: <workdir>/implementation/task-NN-notes.md` on separate lines (paths from the decompose index).
- The deferred reviewer: exactly the dispatch the **decide** step of step 6 specifies, built from `deferred`'s own values - that task's `<review>` column, its task file, its `task-NN-notes.md`, its `R`, its `report:` - plus one `range: <from>..<to>` line per commit range that task owns, in the order the commits were made. It reads no `since`: the ranges are the whole of what it judges, so it never sees this task's work.
3. The implementor's verdict:
- `VERDICT: PASS` -> continue to the commit at step 4. No reviewer is dispatched here; this task's own review is decided at step 6, after the commit.
- `VERDICT: FAIL` + `REASON: <line>` -> escalate via `AskUserQuestion` naming the task `` `<title>` (Task NN) `` (retry / skip / abort); act on the answer (abort ends the loop). `retry` re-dispatches the implementor alone.
- `VERDICT: BLOCKED` + `REASON: <line>` -> run `### Implementor stop` with `<subject>` = `` `<title>` (Task NN) `` and `<notes>` = this dispatch's `notes:` path; its re-dispatch is this same step 2 call with the implementor alone - a deferred reviewer that already returned is never dispatched a second time - and its verdict is read here again.
- A `deferred` review came back at step 2 and this branch is about to `skip` the task or `abort` the loop -> run step 6's **close** step on that deferred review FIRST, whatever step the loop has reached, and only then skip or end: a verdict that came back is never dropped. Log one further `escalation` stats event naming the deferred task `` `<title>` (Task NN) `` and the user's answer.
4. Commit the task: keep the current `head` as this task's `task_since`, then run `"${CLAUDE_PLUGIN_ROOT}/scripts/commit-task.sh" "<heading>" <task-file> --notes <workdir>/implementation/task-NN-notes.md` - it records the task number in `status.md` and stages only the declared set (the task's `### Files`, the notes' `touched:` lines, the run dir).
- `commit: <sha>` -> `head` := that SHA, and this task's first review range is `<task_since>..<that SHA>`.
- exit 2 -> `AskUserQuestion` quoting BOTH kinds of line the refusal printed, each under its own word: every `undeclared: <path>` (a working-tree change nobody declared) and every `dropped: <path>` (a DECLARED path that matched no file - a wrong `### Files` entry or a wrong `touched:` line, so the declaration is malformed rather than the change missing). A refusal may carry only the first kind; quote whichever it printed. The answers: **remove or stash them** (the user clears the undeclared changes, then re-run the same command), **include named ones** (re-run it with one `--path <path>` per path the user named), or **abort**. Never stage anything yourself, and never re-run with a `dropped:` path as a `--path` - it names nothing on disk.
- `Nothing to commit.` or `Not a git repository - skipping commit.` -> `head` is unchanged and this task owns no range.
5. `TaskStop` -> completed
6. Close the deferred review, then decide this task's own - in that order, both before the next task starts.
- **Close** - only when a `deferred` review returned at step 2 (or is the review this step just dispatched itself). `<report>` is its `REVIEW:` path, `NN` / `<title>` / `<model>` / `task-NN-notes.md` / `R` are the deferred task's, not this one's.
- `VERDICT: PASS` -> `deferred` := empty. Done.
- `VERDICT: BLOCKED` + `REVIEW: <path>` -> run `### Task gate blocked` with `<report>` = that path; it ends either with that review closed (`deferred` := empty) or in an abort, and its dispatches are never review rounds.
- `VERDICT: FAIL` + `REVIEW: <path>` -> dispatch `superbuild-task-implementor` (`Agent`; a fix after a task review runs at THAT task's own `<model>` column, exactly as step 2 dispatched it - no `model:` parameter when that column is `-`, and no `effort:` parameter in any case) with `plan-header: <path>`, `plan: <plan-copy path>`, `refs: <refs>`, `task: <REVIEW path>`, `decisions: <workdir>/implementation/decisions.md` (only when that file exists), and `notes: <workdir>/implementation/task-NN-notes.md` on separate lines (`plan` lets it source the real `### Task Checks` lines). That fix returning `VERDICT: BLOCKED` + `REASON: <line>` -> run `### Implementor stop` with `<subject>` = `` `<title>` (Task NN) `` (this fix carries no fix ordinal of its own - it is the same task, writing that same notes file) and `<notes>` = that same `task-NN-notes.md`, and read the re-dispatched fix's verdict here in its place. Then, on its `VERDICT: PASS`: keep the current `head` as `fix_since`, commit the fix as its own commit - `"${CLAUDE_PLUGIN_ROOT}/scripts/commit-task.sh" "fix: <heading>" --notes <workdir>/implementation/task-NN-notes.md`, the title distinct from the task's own so the fix is its own findable commit in history and the task file NOT passed a second time (the notes' `touched:` lines are the declared set; its exit 2 is the same `AskUserQuestion` step 4 uses - **remove or stash them** / **include named ones** / **abort** - answered before the re-review goes out, and logged as one `commit` stats event with verdict `undeclared`) - then `head` := the SHA of its `commit:` line and `<fix_since>..<that SHA>` joins this task's ranges. Then dispatch the reviewer again the same way with the next `R`, carrying every `range:` line it carried before plus that new one, and await it here: the review never spans a commit of another task. Max 3 review rounds per task - a FAIL still standing after the third -> escalate via `AskUserQuestion` naming the task `` `<title>` (Task NN) `` (retry / accept / abort); act on the answer, and `accept` clears `deferred`.
- `VERDICT: FAIL` + `REASON: <line>` (no `REVIEW:` line) -> a missing reviewer input is an orchestration fault, not the implementor's: escalate via `AskUserQuestion` naming the task `` `<title>` (Task NN) `` (retry / abort) and never dispatch the implementor for it; `retry` re-dispatches the reviewer the same way with the same `R` and the same `range:` lines (no report was written) and does not count as a review round.
- **Decide** - this task's own review, `deferred` now empty:
- `<review>` column `none` (`Review: none`) -> dispatch no reviewer at all, write no report, log no `task-reviewer` stats event, consume no review round and defer nothing - the implementor's `VERDICT: PASS` is what closes the task, with no substitute check of your own standing in for the review.
- `<review>` column whose first token is neither a `Model:` value nor `none` -> dispatch nothing and escalate via `AskUserQuestion` naming the task `` `<title>` (Task NN) `` (skip reviewer / abort), logging one `escalation` stats event whose note carries that value and the user's answer; `skip reviewer` ends the task exactly as `none` does, deferring nothing.
- The index printed `base: none`, or step 4 printed `Nothing to commit.` -> no commit exists to review: defer nothing, dispatch the reviewer here with no `range:` line at all, await it, and run the **close** step above on what it returns.
- A next task exists, this task's number `N` is NOT a multiple of 5, and the NEXT task's `<concurrent>` column reads `yes` -> `deferred` := this task, carrying its `task_since`, its ranges and its review round `R`. Dispatch nothing here; step 2 of the next task sends the reviewer out beside that task's implementor. Anything less than all three conditions is not a deferral.
- Every other case -> dispatch this task's reviewer alone, await it here, and run the **close** step above on what it returns.
- The reviewer dispatch, wherever it goes out: `Agent` with `subagent_type: superdev:superbuild-task-reviewer`, `model:` = the column's first token (no `model:` parameter at all when the column is `-`) and no `effort:` parameter in either case, and a labeled-line prompt - `plan-header: <path>`, `task: <task-file path>`, `refs: <refs>`, `notes: <workdir>/implementation/task-NN-notes.md`, `decisions: <workdir>/implementation/decisions.md` (only when that file exists - it is how the reviewer tells a `DECISION:` line the user already answered from one still open, the notes file keeping both), `prior: <workdir>/implementation/task-NN-review-<R-1>.md` (only when R is above `1` and that file exists - the previous round's report, read for finding-ID continuity alone), `report: <workdir>/implementation/task-NN-review-R.md` (R = review round for this task, starting `1`, +1 on each reviewer dispatch), and one `range: <from>..<to>` line per commit range this task owns, on separate lines.
- Because a deferral needs a next task that is not across a checkpoint boundary, `deferred` is always empty when a checkpoint round actually runs at step 7, and always empty when the last task of the build closes: every task of a checkpoint's window carries its verdict, or was never subject to review, before that checkpoint starts.
7. This task's number `N` is a multiple of 5 and `N` is smaller than `total` -> `head` moved in step 4: run `### Checkpoint` before starting the next task; `head` did not move: `TaskStop` -> completed on that checkpoint task, no round runs and `since` stays.
### Task gate blocked
`${CLAUDE_PLUGIN_ROOT}/references/review-contract.md` (`## Per-task gate`) owns this protocol; these are its steps as you run them. The task is already committed - step 4 of `### Loop` commits it before its review ever returns - and no implementor runs before the user has answered. You never settle the matter yourself.
1. One `AskUserQuestion` per bullet under `<report>`'s `### Needs decision`, in report order, skipping a bullet whose criterion `<workdir>/implementation/decisions.md` already covers, naming the finding `` `<title>` (<ID>) `` and the criterion `` `<title>` (criterion N) `` off the bullet and carrying its reason: **accept as is** / **fix the plan** (the user dictates the rule this task follows instead) / **abort** (ends the loop as every other abort does).
2. Per non-abort answer run `"${CLAUDE_PLUGIN_ROOT}/scripts/record-decision.sh" <workdir> "<ID>" "<criterion in the reference form>" "<the user's words>"`. The plan file is never edited. A non-zero exit -> `AskUserQuestion` (retry the script / abort), and no dispatch until it succeeds.
3. Every answer **accept as is** -> the reviewer again exactly as `### Loop` dispatched it for this task - at step 2 when it was deferred, at the **decide** step of step 6 otherwise - same `R`, same `report:`, same `range:` lines, plus `decisions: <workdir>/implementation/decisions.md`; await it and read its verdict in the **close** step of step 6, exactly as that step reads a deferred reviewer's. Any answer **fix the plan** -> the implementor again as step 2 dispatched it, same `task:`, same `model:` (or absence), same `notes:`, plus that same `decisions:` line; its verdict is read as step 3 reads an implementor's. A `VERDICT: PASS` off it -> keep the current `head` as `fix_since`, commit its edits - `"${CLAUDE_PLUGIN_ROOT}/scripts/commit-task.sh" "fix: <heading>" --notes <workdir>/implementation/task-NN-notes.md` plus one `--path <path>` per line of that task's own `### Files` section, read off `<task-file>` the way `### Fix loop` step 1 reads a task's files. Those `--path` values are what the POSITIONAL task file would otherwise have declared - this re-dispatch is a TASK-mode implementor call, whose notes declare only what it touched OUTSIDE `### Files`, so without them the edits sit uncommitted and surface as `undeclared:` on the next task's commit. The task file is NOT passed positionally all the same: that form also runs `status-update.sh`, writing THIS task's number over the one the next task's commit already put in `status.md`, and a resume would then re-run that next task's implementor over work already committed. The `fix:` prefix is there for the same reason the deferred-FAIL commit carries one - the task's own commit is already in history and the two stay apart. Its exit 2 is handled as in step 4; then `head` := the SHA of its `commit:` line, `<fix_since>..<that SHA>` joins this task's ranges, and the reviewer goes out with the next `R`, every earlier `range:` line plus that new one, and `decisions:` set. Neither re-dispatch counts toward the task's 3 review rounds; a BLOCKED off either is a new matter and runs this subsection again.
Stats: one `escalation` event per bullet put to the user, labeled `` `<title>` (Task NN) ``, its note the bullet's criterion and the user's answer.
### Implementor stop
An implementor returning `VERDICT: BLOCKED` + `REASON: <line>` - from step 3 of the loop above, from the fix after a task review in its **close** step, or from a `### Fix loop` dispatch - is a matter only the user can close, per `${CLAUDE_PLUGIN_ROOT}/references/review-contract.md` (`## Implementor stop`), which owns this protocol. `<subject>` is the dispatch it came back from, in the reference form of `## Mandatory rules`; `<notes>` is that dispatch's own `notes:` path. Nothing of THIS dispatch was committed - a task step 4 already committed before its review returned stays committed, and its fix is committed only once that fix passes - and the working tree stays exactly as the implementor left it: revert nothing, stage nothing, and never settle the matter yourself.
1. Read `<notes>` and take every `DECISION: <what> - <why> - <options>` line off it, skipping each one `<workdir>/implementation/decisions.md` already answers - a notes file appended to across re-dispatches keeps the earlier stop's lines, and those are closed. Not one `DECISION:` line there -> this is the **no report** state of `## Harness pre-check`, not a stop: take that rule (retry / abort) and re-dispatch nothing on it.
2. One `AskUserQuestion` per remaining line, in the order `<notes>` carries them, naming `<subject>` and carrying that line's `<what>`, its `<why>` and its `<options>`: **answer** (the user's own wording, taken verbatim) or **abort**. Abort ends the loop exactly as every other abort of this build does - the working tree is left as it stands and the task or fix stays unclosed.
3. Per answer run `"${CLAUDE_PLUGIN_ROOT}/scripts/record-decision.sh" <workdir> "<ID>" "<subject>" "<the user's answer>"`, where `<ID>` is that line's `D<n>` per the review contract (`## Finding IDs`): the stop's first line takes the number after the highest `D<n>` already in `<workdir>/implementation/decisions.md`, `D1` when there is no such file or no such line in it, and the stop's further lines continue from there in the order `<notes>` carries them. A non-zero exit -> `AskUserQuestion` (retry the script / abort), and no re-dispatch until it succeeds.
4. Re-dispatch the dispatch that stopped - the same `subagent_type`, the same `model:` (or the same absence of one), the same labels - plus `decisions: <workdir>/implementation/decisions.md`. The re-dispatch is neither a review round nor a fix round: it consumes no round budget, moves no ordinal (the same `notes:` file, the same fix `NN`, the same reviewer `R`), and its verdict is read wherever the stopped dispatch's verdict is read. A second `VERDICT: BLOCKED` off it is a new matter and runs this whole subsection again.
### Checkpoint
`TaskUpdate` -> start on this checkpoint's task. `deferred` is empty here by construction, so every task of this window already carries its review verdict or was never subject to review.
1. Run this round's gate set once: `"${CLAUDE_PLUGIN_ROOT}/scripts/run-gate.sh" <workdir> checkpoint <workdir>/implementation/gates-checkpoint-KK.md` (KK = this checkpoint's ordinal, `01`, `02`, ...), giving that `Bash` call its maximum `timeout`, `600000` ms. The script budgets the whole gate set to come back inside that; the tool's own 120 s default would kill a suite the script was still running, and a killed run leaves no `GATES:` path and no `RED:` line at all. Keep its `GATES:` path as `<gates>` and read its `RED:` line - `yes` or `no`, always its last line.
- A non-zero exit -> `AskUserQuestion` (**retry the script** / **abort**), logging one `escalation` stats event carrying the exit code and the user's answer. There is no third answer that dispatches the reviewer without a block: `gates:` is a required label on every build reviewer, and an absent one returns `VERDICT: FAIL` + `REASON: missing input gates` and writes no report, so a round with no gate block cannot be reviewed at all. `abort` ends the loop as every other abort does. Every other `run-gate.sh` call of this build carries that same `timeout` and handles a non-zero exit exactly this way.
2. Dispatch the reviewer ONLY when at least one of these three holds - each read off persistent state rather than off this session's memory, so a build resumed inside the window decides exactly as an unbroken one:
- `RED: yes` - some gate command of this round came back anything other than a success;
- some task of this window returned `VERDICT: FAIL` or `VERDICT: BLOCKED` from its per-task review - one `Glob` over `<workdir>/implementation/` for a `task-NN-review-R.md` whose `NN` falls in this window: the per-task reviewer writes a report only on FAIL and on BLOCKED, so such a file existing IS this condition. One its own fix rounds later closed to `PASS` still counts: the condition is that the window held a task REPORTED as defective, not that one is still open;
- some task of this window ended unreviewed, read off that task's `<review>` column in the index alone: `none` (`Review: none`), or a first token that is neither a `Model:` value nor `none` - the invalid value the **decide** step escalates, whose `skip reviewer` answer ends the task exactly as `none` does and is read here as this same condition (the only other answer there, `abort`, ends the loop, so no live window carries one).
Nothing else is a reason: three conditions, and a round none of them holds for dispatches nothing.
The dispatch: `Agent` with `subagent_type: superdev:superbuild-reviewer-change`, no `model:` parameter and no `effort:` parameter - this reviewer's strength is its own frontmatter's - and a labeled-line prompt: `stage: checkpoint`, `since: <since>`, `prior: <prior>` (omit the line when there is none), `decisions: <workdir>/implementation/decisions.md` (only when that file exists), `plan: <plan-copy path>`, `spec: <spec path>`, `notes: <workdir>/implementation/`, `refs: <refs>`, `gates: <gates>`, and `report: <workdir>/implementation/checkpoint-KK.md` on separate lines. It runs no gate command of its own; `<gates>` is the block this round already produced. Await it, then run `### Fix loop` on what it returns.
3. None of the three holds -> dispatch nothing at all, and close the round here: `since` := `head`, `prior` UNCHANGED - the last report there was stays the one the next round reads, so that round's finding IDs keep continuing from it and its prior-findings table keeps its rows; a round that dispatched nobody wrote no report to put in its place, and its gate block would cost the chain both. Only when this build has produced no report at all yet is there nothing to keep, and `prior` := `<gates>` then, so `checkpoint-update.sh` has a value and the contract's `prior:` entry covers what the next round reads. Then `"${CLAUDE_PLUGIN_ROOT}/scripts/checkpoint-update.sh" <workdir> <since> <prior>` so a resume finds both.
`TaskStop` -> completed on the checkpoint task once the round has ended - closed without a dispatch, closed by `### Fix loop`, accepted or aborted alike.
### Fix loop
Shared by the checkpoint above (`stage: checkpoint`) and by each round of Step 3 (`stage: final`); `<closing stage>` is that stage, `checkpoint` or `final`, and never any other word. `<report>` is the report of the review that just returned and `<gates>` the gate block of that same round - the file its one `run-gate.sh` run wrote. The budget per review is one fix dispatch and one re-review, after which the user decides.
- `VERDICT: PASS` -> close the round: `since` := `head`, `prior` := `<report>`, then run `"${CLAUDE_PLUGIN_ROOT}/scripts/checkpoint-update.sh" <workdir> <since> <prior>` so a resume finds both. Continue.
- `VERDICT: BLOCKED` + `REVIEW: <report>` -> no implementor runs. The bullets under the report's `### Needs decision` come in two shapes and a bullet is never both; `${CLAUDE_PLUGIN_ROOT}/references/review-contract.md` (`## Gates`) owns the distinction. Split them by it, ask per bullet, and take **abort** on any bullet as every other abort is taken.
- A **finding bullet** carries a `C<n>`/`I<n>` ID and the criterion or task it belongs to. One `AskUserQuestion` per bullet, naming that bullet's finding `` `<title>` (<ID>) ``: **accept as changed** / **fix it** / **abort**. Per accepted bullet run `"${CLAUDE_PLUGIN_ROOT}/scripts/record-decision.sh" <workdir> "<ID>" "<criterion or task>" "<what the user accepted>"` - its `<criterion or task>` argument in the reference form too, `` `<title>` (criterion N) `` or `` `<title>` (Task N) ``, read off the same bullet. **fix it** on any bullet -> take the FAIL branch instead, for every bullet of this report at once.
- A **gate bullet** carries NO ID and names a gate command or a `## Gate commands` subsection the plan does not hold. It is raised against the plan, so no implementor can clear it and `record-decision.sh` has no ID to take from it; there is no **fix it** answer here. One `AskUserQuestion` per bullet, naming the command or the subsection as the bullet spells it: **retry the gate set** / **accept the gate hole** / **abort**. **retry the gate set** -> `"${CLAUDE_PLUGIN_ROOT}/scripts/run-gate.sh" <workdir> <closing stage> <workdir>/implementation/gates-<closing stage>-KK-retryT.md` (T = this round's retry ordinal, `1` first; `KK` does not advance, a retry being no more a round than the re-run below), with the same `timeout: 600000` and the same non-zero-exit handling as `### Checkpoint` step 1, and `<gates>` := its `GATES:` path. **accept the gate hole** -> `"${CLAUDE_PLUGIN_ROOT}/scripts/record-decision.sh" <workdir> "G<n>" "gate <command or subsection>" "<what the user accepted>"` (`G<n>` numbered per `## Finding IDs`, continuing from the decisions file), leaving `<gates>` as it stands - the block is the round's evidence and the decisions line is what closes the entry.
Then re-run the same reviewer call with the same `report:`, `gates: <gates>` - the retry's block where one was written, the round's own otherwise - and `decisions: <workdir>/implementation/decisions.md` added. That re-run is not a round: it runs no gate set of its own beyond a retry the user asked for above.
- `VERDICT: FAIL` + `REVIEW: <report>`:
1. Dispatch `superbuild-task-implementor` (`Agent`) at the highest `<model>` among the tasks whose `### Files` names a file some finding in `<report>` points at - one scale, `opus` over `sonnet`, and no `effort:` parameter: read the findings' `file:line` paths off `<report>`, then those tasks' `### Files` off the task files the index lists. No task matches -> pass no `model:` parameter either. Labels: `refs: <refs>`, `plan-header: <path>`, `plan: <plan-copy path>`, `spec: <spec path>`, `task: <report>`, `decisions: <workdir>/implementation/decisions.md` (only when that file exists), and `notes: <workdir>/implementation/fix-NN-notes.md` on separate lines (NN = the fix ordinal across the whole build, `01` upward). Await it.
- `VERDICT: FAIL` + `REASON:` -> escalate via `AskUserQuestion` (retry / accept / abort); act on the answer.
- `VERDICT: BLOCKED` + `REASON: <line>` -> run `### Implementor stop` with `<subject>` = `` `<fix title>` (fix NN) `` and `<notes>` = this dispatch's `fix-NN-notes.md`; its re-dispatch keeps this same fix `NN`, its verdict is read here again, and the round's one-fix budget is untouched by it.
2. `VERDICT: PASS` -> keep the current `head` as `fix_since`, then commit the fix: `"${CLAUDE_PLUGIN_ROOT}/scripts/commit-task.sh" "<fix title>" --notes <workdir>/implementation/fix-NN-notes.md` (exit 2 handled exactly as in the loop above), and `head` := the SHA of its `commit:` line.
3. Re-review: run this re-review's own gate set once first - `"${CLAUDE_PLUGIN_ROOT}/scripts/run-gate.sh" <workdir> re-review:<closing stage> <workdir>/implementation/gates-<closing stage>-KK-reR.md` (the stage argument carries the `re-review:` prefix, the file name never does - so no gate file name ever holds that colon), keeping its `GATES:` path as the round's new `<gates>`; a non-zero exit is handled exactly as `### Checkpoint` step 1 states. `KK` is the ordinal of the round this re-review closes, the same one that round's own `gates-<closing stage>-KK.md` carries, and it is in the name because `R` restarts at `1` for every round: without it checkpoint 02's first re-review would write over the block checkpoint 01's first re-review left as the evidence its report cites. Then the same reviewer with the same labels, except `stage: re-review`, `since: <fix_since>`, `prior: <report>`, `gates:` = that new path, and `report: <workdir>/implementation/<report basename>-reR.md` (R = this report's re-review ordinal, `1` first, and the same R names the gate file; `<report basename>` stays a basename, so the directory is spelled out here exactly as every other dispatch spells it - `## Mandatory rules` admits no relative path on a handoff).
- `PASS` -> close the round: `since` := `head`, `prior` := the re-review report, run `checkpoint-update.sh` as above. Continue.
- `FAIL` or `BLOCKED` -> `AskUserQuestion` listing each still-open finding as `` `<title>` (<ID>) ``: **another round** (repeat from 1 with the next fix `NN` and the next re-review `R`, then ask this same question again - after every further round, every time), **accept with open findings** (record each still-open Critical and Important the same way the BLOCKED branch does - one `record-decision.sh` run per ID, so every later round reads it as plan text instead of re-opening what the user closed - then close the round: `since` := `head`, `prior` := the last report, run `checkpoint-update.sh`, continue), or **abort**.
## Step 3 - Final Review
1. `TaskUpdate` -> start
2. Run this round's gate set once, before either dispatch: `"${CLAUDE_PLUGIN_ROOT}/scripts/run-gate.sh" <workdir> final <workdir>/implementation/gates-final-01.md`. Keep its `GATES:` path as `<gates>`; a non-zero exit is handled exactly as `### Checkpoint` step 1 states. Its `RED:` line gates nothing here - a final round always runs both reviewers - but a red one is what they read off the block.
Then dispatch both reviewers before any fix dispatch - the two dimensions are independent (neither reads the other's report and neither waits on it), so they go out with the `Agent` tool as TWO tool uses in ONE single message and run concurrently; await both. Neither carries a `model:` parameter and neither carries an `effort:` parameter - each reviewer's strength is its own frontmatter's. Both prompts are labeled-line blocks:
- `subagent_type: superdev:superbuild-reviewer-spec` with `stage: final`, `since: <since>`, `decisions: <workdir>/implementation/decisions.md` (only when that file exists), `plan: <plan-copy path>`, `spec: <spec path>`, `notes: <workdir>/implementation/`, `refs: <refs>`, `gates: <gates>`, and `report: <workdir>/implementation/review-01-spec.md` on separate lines; no `prior:` line - this dimension has no earlier report.
- `subagent_type: superdev:superbuild-reviewer-change` with `stage: final`, `since: <since>`, `prior: <prior>` (omit the line when there is none), the same `decisions:`, `plan:`, `spec:`, `notes:`, `refs:` and `gates:` lines, and `report: <workdir>/implementation/review-01-code.md`.
Neither runs a gate command of its own: both read the one block this round already wrote, so the stage's set runs once for the round instead of once per reviewer, and `${CLAUDE_PLUGIN_ROOT}/references/review-contract.md` (`## Gates`) owns that handoff. Read each dimension's verdict off its own return - never let one dimension's `VERDICT:` or `REVIEW:` line stand in for the other's, and never act on the first return before the second has come back.
3. Run `### Fix loop` on the two verdicts, with three adjustments for the two dimensions:
- a BLOCKED report takes the BLOCKED branch for that report first; its re-run is that reviewer's same `stage: final` call with the same `gates:` path and `decisions:` set, and both verdicts are read again afterwards.
- one single implementor dispatch carries every failed report: `task: <code report>` plus `more: <spec report>` when both failed, `task: <spec report>` alone when only the spec failed.
- after its one fix commit, `superbuild-reviewer-spec` runs its own re-review whenever the round dispatched a fix at all - whichever report failed, and whether or not it raised a Critical or an Important of its own: it is the only writer of `## Decisions taken`, and the fix just committed may have written `UNDERSPECIFIED:` lines no earlier report could list. `superbuild-reviewer-change` runs its own re-review when it raised a Critical or an Important. Each of them keeps its own `subagent_type` and its own `refs:` line, its own `stage: re-review`, `since: <fix_since>`, `prior: <its own report>`, `report: <workdir>/implementation/<its own report basename>-reR.md` - and both share the one `gates:` path of this re-review round: `### Fix loop`'s re-review step runs `run-gate.sh` once for the round, `gates-final-01-reR.md`, never once per dimension. Both due in the same round -> they go out exactly as item 2 dispatched them, as two `Agent` tool uses in ONE single message, awaited together; only one due -> that one alone.
Continue once the round closes - both dimensions `PASS`, or the user accepting open findings.
4. Run `"${CLAUDE_PLUGIN_ROOT}/scripts/commit-task.sh" "chore(superbuild): final review reports" --path <workdir>` - saves the review reports (also on an accepted FAIL); its exit 2 is handled as in Step 2.
5. `TaskStop` -> completed
## Step 4 - Close Out
1. `TaskUpdate` -> start
2. Wave 1 - gated by Config; dispatch only the enabled ones with the `Agent` tool - all of them as multiple tool uses in ONE single message so they run concurrently - and await all before moving on.
- `memory: true` -> `subagent_type: superdev:memory-writer`, labeled-line prompt: `capture: <plan-copy path>`, `notes: <workdir>/implementation/`, `refs: <refs>`, `spec: <spec path>`.
- `rules: true` -> `subagent_type: superdev:rules-writer`, labeled-line prompt: `capture: <plan-copy path>`, `notes: <workdir>/implementation/`, `refs: <refs>`.
- any of `qa`, `e2e-ui`, `e2e-api` reading `true` -> `subagent_type: superdev:qa-writer`, labeled-line prompt: `capture: <plan-copy path>`, `workdir: <workdir>`, `notes: <workdir>/implementation/`, `reports: <workdir>/implementation/`, `refs: <refs>`, `qa: <value>`, `e2e-ui: <value>`, `e2e-api: <value>` copied verbatim from the Config block, `spec: <spec path>`, plus `intent: <intent path>` only when the decompose index printed an `intent:` line.
3. Wave 2 - `changelog: true` -> after wave 1 completes, first collect the ADRs this build wrote: the index's `base:` is a SHA -> run `git diff --name-only --diff-filter=A <base>..HEAD -- <root>/docs/adr/` with the Bash tool - the pathspec joined with the index's `root:` because you never `cd` and the session may have started in a subdirectory, and `--diff-filter=A` so an older ADR this build only marked superseded stays off the list. Each path it prints is repository-root-relative like every other path of the index, so join it with `root:` and carry it as one `adr: <root>/<printed path>` line, in the printed order; nothing printed -> no `adr:` line. The index's `base:` is `none` -> run no `git diff` and pass no `adr:` line. The command exits non-zero -> pass no `adr:` line and note the failure in the Step 5 summary.
Then dispatch `subagent_type: superdev:changelog-writer`, labeled-line prompt: `capture: <plan-copy path>`, `workdir: <workdir>`, `notes: <workdir>/implementation/`, `refs: <refs>`, `spec: <spec path>`, plus `intent: <intent path>` only when the decompose index printed an `intent:` line, and the `adr:` lines collected above (repeatable, one per ADR).
Nothing enabled in either wave -> skip to the commit.
4. Keep each delegation's `NODE:` / `RULE:` / `CHANGELOG:` / `INDEX:` / `GAP:` / `QA:` / `E2E:` / `QA-INDEX:` lines verbatim for the Step 5 summary - and with them the two PLURAL forms a writer returns when it touched nothing at all, `NODES: none` from `memory-writer` and `RULES: none` from `rules-writer`. Those are ordinary PASS answers, not failures and not omissions: they say the change needed no node and no rule, and they are the commonest answer on a small build. Any delegation failing is non-fatal -> note it there too, do not block.
5. Run `"${CLAUDE_PLUGIN_ROOT}/scripts/commit-task.sh" "chore(superbuild): close out memory, rules, changelog and qa" --path <workdir>` with one further `--path <path>` per path the writers relayed on their `NODE:` / `RULE:` / `CHANGELOG:` / `INDEX:` / `QA:` / `E2E:` / `QA-INDEX:` lines (a line reading `none` or `skipped - <reason>` declares nothing, and neither does a plural `NODES: none` / `RULES: none`) - that is the whole declared set of this commit; its exit 2 is handled as in Step 2.
6. `TaskStop` -> completed
## Step 5 - Done
1. `stats: true` -> run `"${CLAUDE_PLUGIN_ROOT}/scripts/stats-report.sh" <workdir>` - before the cleanup below, which takes the run dir the report reads. Keep its `stats:` line for the summary; a non-zero exit is noted there instead.
2. `cleanup: true` -> run `"${CLAUDE_PLUGIN_ROOT}/scripts/cleanup-run.sh" <workdir> superbuild` - here alone `<workdir>` is the index's `workdir:` value verbatim, repository-relative and never joined with `root:`, because the script's safety gate rejects every path outside `docs/.workflows/`, an absolute one included, and silently skips it as not a run dir. Keep its `CLEANUP:` line; the script verifies completion itself - never re-check, never retry.
3. Cleanup the task list and display short summary of work. Max ~3-5 sentences plus the relayed lines. Include:
- Step 4's `NODE:` / `RULE:` / `CHANGELOG:` / `INDEX:` lines verbatim, a `NODES: none` / `RULES: none` included (or the noted failure / disabled), plus the noted `git diff` failure when Step 4 hit one
- the `QA:` / `E2E:` / `QA-INDEX:` lines verbatim, a `skipped - <reason>` line included, or "disabled" when `qa`, `e2e-ui` and `e2e-api` are all off
- the `stats:` line verbatim (or "disabled" when `stats` is off), plus every stats call noted as failing
- the `CLEANUP:` line verbatim (or "disabled" when `cleanup` is off)
- every `GAP:` line verbatim, each followed by `-> run superdev-memory`