# Orchestrator

> Drives the autonomous Implement→Verify→Review→Ship loop once the human-owned Spec+Plan is signed and STATE.md holds a slice DAG. Use it to run a build AFK — it sorts slices into topological waves, runs each wave's ready slices in parallel (one worktree per slice, disjoint files only), holds a barrier until every slice reaches a TERMINAL state (done/halted/blocked — never just "success"), and ends the run at risk-banded OPEN PRs for async human merge. If you are about to hand-run slices one at a time, check in with the human between waves, dispatch a "reviewer" persona, weaken a frozen test/acceptance to make a gate go green, or merge to main yourself — STOP and use this instead.

- Skill: `celestialdust/orchestrator` (Agent Skill)
- Install (CLI): `npx skillmds@latest add celestialdust/orchestrator`
- Raw SKILL.md: https://api.skillmd.com/api/skills/celestialdust/orchestrator/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: celestialdust (https://skillmd.com/u/celestialdust)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/celestialdust/orchestrator

---


## Purpose

**Stage: cross-cutting engine (the autonomous span).** The human owns Ideate +
Spec + Plan — all the thinking. Once they sign the Spec and author the plan, *something*
has to actually build it: run every slice through Implement → Verify → Review → Ship with
no human babysitting, in parallel where the dependency graph allows, and stop at a state a
human can review async. That something is this skill. It exists because the alternative —
the controlling agent hand-running slices one at a time, checking in between each — throws
away the parallelism the slice DAG was designed for and reintroduces the human halt
deliberately removed. The orchestrator is the only skill that reads the *whole* board and
moves slices across it.

## When to use / when to skip

**Use when:** the Spec gate is signed, `preflight-readiness` is green, and `STATE.md` holds a feature
carrying slice rows whose `Blocked by` column forms a DAG — and you want the build run autonomously to
open PRs. That feature reads **`feature: plan`** on a first run, which is where `plan-breakdown` leaves
it, or **`feature: building`** on a resumed one, which is where *you* left it. Being invoked is the
human's Plan sign-off: the rows are born at gate `you` precisely because a person has to read the plan
first, and a person starting the run is that reading. Flipping `plan → building` is this skill's own
first write — Process step 3. This is the default executor; sequential execution is just the degenerate
case (a wave of one).

**Skip when:** the feature has no slice rows yet — it sits at `feature: spec`, or at `feature: plan`
with nothing under it, and the human still owns Spec or Plan; you are doing a single one-off edit with
no DAG; or `preflight-readiness` is red/amber (fix the environment first — the wave must not start).
**Slice rows, not the feature token, are what say Plan is finished.** A board reading `feature: plan`
*with* rows under it is the normal starting board, not a skip: nothing writes `building` before you do,
so refusing that board refuses every board `plan-breakdown` has ever produced.

**Escape hatch (`depth: lite`):** a single ready slice with no siblings still runs the full
Implement → Verify → (aggregate) Review loop and the barriers — do not "just do it inline." For a
wave of one the aggregate review is simply that one slice's diff, so it costs the same as the old
per-slice review; the barriers, the worktree, and the three gates are the point even here.

## Inputs

Refuse to run (CRISPY refuse-to-run) unless ALL are present:

- **`STATE.md`** (repo root, created by `project-setup`) — the two-level board. The `Blocked by`
  column IS the slice DAG. There must be a feature at **`feature: plan`** with at least one slice row
  in `impl` — the board `plan-breakdown` hands over — or at **`feature: building`**, which is a run
  you already started and are resuming. Absent, no feature carrying slice rows, or a feature still at
  `feature: spec` → refuse. The `plan → building` flip is yours and happens in step 3; do not require
  the board to already say `building`, because nothing else writes that token.
- **`preflight-readiness` verdict = GREEN** — every `environment.md` row provisioned. Red or
  un-attested amber → refuse to start the wave.
- **`plan.md` + `plan/`** (`docs/features/<slug>/`) — the slice table with each slice's declared
  `Regression surface`, `Design ref`, `Steps`, and `Files (owned)` ownership, plus one
  `plan/<slice-id>.md` per slice holding its concrete steps and exact tests. Missing
  file-ownership on a slice that shares a wave → refuse (the disjoint-file guard cannot run blind).
- **`acceptance.md` (status: signed)** — the frozen behavioral oracle. The orchestrator
  FREEZES `acceptance.md` + the RED tests + each slice's `Regression surface` for that
  slice's retry loop; it never edits them. Editing any of the three is a **loosening**: one rule,
  *Changing what judges the work*, governs this and every other prohibition below.

One more input is required per slice rather than per run, so it gates a slice instead of the run:
**the design contract each slice's `Design ref` names, at `status: signed`**, for every slice whose
`Design ref` is not `—`. It is read at dispatch, before that slice's implementer runs; absent or
`status: draft` halts **that slice**, with the halt reason naming the contract by path, while the rest
of the wave dispatches normally. Fully specified in *Design-ref gate at dispatch* below.

Bulk artifacts move as **files**, never pasted into a dispatch prompt (subagent-driven-
development §File Handoffs): a slice dispatch carries the slice brief path + its frozen
contract paths, not the session history.

## Process

1. **Resume cold.** Read `STATE.md` and `docs/progress.md` first. The board says which slices are
   `done`/`ship` — never re-dispatch one (subagent-driven-development §Durable
   Progress: re-dispatching completed work is the single most expensive failure). The run record says
   what the last attempt actually executed and what came back, and a heading in it with nothing under it
   is a slice that was dispatched and died before returning. Trust those two plus `git log` over
   recollection after compaction: the board answers what state a slice is in, the record answers what was
   run, and neither answers the other's question.
2. **Build the DAG.** Parse every slice's `Blocked by` into edges; topologically sort into
   **waves** (each wave = one topological level). Verify no cycles — a cycle blocks the run;
   surface it and stop (the human must reorder dependencies).
3. **Open the run — flip the feature to `building`.** The board still reads `feature: plan`: that is
   where `plan-breakdown` leaves it, and this flip is yours and nobody else's (`references/write-ownership.md`,
   *Who writes what*: `a feature block's feature: state`, `orchestrator`, flip status). Do it once the three
   things that warrant it are true and not before — the feature carries slice rows whose `Blocked by`
   DAG steps 1–2 just read and found acyclic, the `preflight-readiness` verdict is green, and the signed
   `acceptance.md` plus the `plan.md` slices exist. Those three *are* the Run-start gate, which is the
   one gate in the lifecycle this skill owns; flipping the token is what opening it looks like on the
   board, and a run whose board never says `building` is a run no reader can tell started. In the same
   write, move each slice row's `Gate` from `you` to `agent`: the rows are born `you` because a person
   signs the plan, and the run is what takes them over.
   **Flip the state token only.** The feature block, its `origin:` line, its rows, their titles, and
   their `Design ref` cells belong to `plan-breakdown` and are not yours to rewrite — the write table
   grants you `flip status` there, which is one token and no more. A board already at `feature: building` is a
   resumed run: nothing to flip, and a row already past `you` keeps the gate it has.
4. **Select the ready wave, then order it.** A slice is ready when every blocker is `done`. Apply
   the **disjoint-file guard** (below) to the ready set, then put what survives into the order
   *Dispatch order* (below) defines — deepest downstream chain first, transitive dependent count as
   the second key, `plan.md` order last. Selection decides *which* slices run; the order decides *which one starts first*,
   and that is what sets the run's wall clock the moment the guard splits the wave into sub-waves.
5. **Open each slice's entry, provision isolation, then run the design-ref gate.** The moment a slice
   enters the wave — before its brief is assembled, before any gate can stop it — append its **stub** to
   `docs/progress.md`: the entry heading, and nothing under it (see *The run record*). Then each ready
   slice gets its own clean
   worktree (the `worktree` mechanism this skill owns). Platform-adaptive (below). While assembling
   the brief, read the slice row's **`Design ref`** — it travels with the slice from here on. If it
   is not `—`, open the `design-contract.md` it names and read `status:` **before dispatching
   anything for that slice** (see *Design-ref gate at dispatch*). Absent or `status: draft` → that
   slice is **`halted` here**, its halt reason naming the unsigned contract by path; no implementer
   runs, so no partially built interface exists to reach Verify or Review.
6. **Run Implement + Verify per slice** for every ready slice — in parallel (one dispatch call
   per slice, all in one response = concurrent execution): `incremental-implementation` (applies
   `test-driven-development`) → `quality-verification` (Verify, fresh code-cold). Verify stays
   **per-slice** — behavioral acceptance is a property of the individual slice, not the wave.

   **Carry the design ref into both briefs.** Copy `Design ref` from the slice row into the
   implementer's brief **and** the verifier's brief. Dispatch is the only channel that reaches both:
   the implementer must open the prototype before it builds, and the verifier is code-cold — it may
   not read `plan.md`, so anything left only in the plan never arrives. A `—` is delivered
   explicitly **as `—`**, not omitted: it tells the verifier this slice builds no UI, rather than
   leaving it to infer that from work it did not do. Where the ref names a path and the repo has a
   `docs/design.md`, carry that path in both briefs too: a contract axis marked
   `inherits: docs/design.md` is graded against that file, so a verifier handed only the contract is
   handed half its oracle.
7. **Verify barrier.** Wait for every ready slice to reach `verify` green **or** a terminal state
   (a slice that halts at Verify never enters the review). This barrier is what lets the next step
   review the wave as one changeset instead of N.
8. **Aggregate Review over the whole wave.** Run the four floor axes (`code-review` +
   `code-simplification` + `security-and-hardening` + `performance-optimization`) — plus any reviewer
   the trigger table below adds — as fresh code-cold
   subagents (one axis each, in parallel), **once over the union of the verify-green slices' diffs**
   — **4+k subagents per wave, not 4 × N**, where k is however many reviewers the trigger table added
   (usually zero). The win is in the *per-wave* denominator, not in the roster: never budget off the
   literal 4 and drop a triggered reviewer to hit it — that is a loosening. Attribute every finding to its
   **owning slice by file**: the disjoint-file guard guarantees each file belongs to exactly one
   slice, so attribution is unambiguous. A finding routes *only its owning slice* back to
   `incremental-implementation`, which climbs *The escalation ladder* against it; after that slice
   re-passes Verify, **re-review only its diff**, never the whole wave again.
9. **Evaluator floors + DRAFT PR per slice** — still per-slice (each slice owns its plan steps and
   regression surface). A slice whose attributed review findings are clear and whose floors are met
   opens its own DRAFT PR. A slice that fails instead climbs *The escalation ladder* — five rungs, each
   a different tactic, and it halts only when they are spent. Budget: **2 attempts per gate, 3
   implement→verify→review cycles per slice**, spent across the ladder rather than on repeating one
   approach.
10. **TERMINAL barrier.** Wait for EVERY slice in the wave to reach a **TERMINAL** state
   (`done | halted | blocked`) — **never `success`**. Write every transition + gate flip to
   `STATE.md` as it happens. **Complete each slice's entry** in `docs/progress.md` from what the slice
   returned — the commands, their real output, the files it changed, and what it did not run and why (see
   *The run record*). A slice that returned nothing keeps the stub it was given and is completed with
   that fact. In the same pass, carry over any lessons entry the slice handed back, into the same
   checkout (see *The lessons a slice hands back*). Then advance to the next wave.
11. **Integration gate.** After a connected DAG component's slices are all green, run the
    merged-union suite once in an integration worktree before presenting. Union-fail →
    the component's PRs go DRAFT + a blocker is recorded.
12. **Terminate** on exactly one predicate (see Verification). Append the inverted risk
    report; leave risk-banded OPEN PRs for the human.

## Wave executor & the TERMINAL barrier

The DAG → topological-wave structure is the whole point: independent branches drain in
parallel, dependent branches serialize, and the barrier between waves is what makes the run
resumable from `STATE.md` alone. The barrier waits for **TERMINAL, not SUCCESS**
(safety rail 5, `references/safety-rails.md`): a `halted` or `blocked` slice still satisfies the barrier — the run
does not stall waiting for a slice that will never pass. Its dependents transitively flip to
`blocked`; every *other* independent branch keeps draining.

## The run record

**Appends to `docs/progress.md`** — one entry per slice, per dispatch. An entry carries the commands that
were run in the form they were run, their real output, the files that changed, and what was **not** run
and why. It exists because the alternative account of a run is the run's own summary, and a summary is
written by the party with the most reason to round up.

**Where the write lands, and this is the part that has gone wrong before.** The entry is appended in the
checkout **you** hold — the branch the run was started from — never inside a slice's worktree. A worktree
is a separate branch that may never be merged: a write there succeeds, reports success, and reaches no
reader on the main line. Slices run in worktrees; the record does not. That is why the orchestrator holds
the pen for every slice in an orchestrated run rather than letting each slice write its own entry, and it
is the whole reason adapter B exists for the hand-run case (`incremental-implementation`, which has no
worktree to be stranded in).

**Two writes per slice, at two moments:**

1. **The stub, at dispatch.** The moment a slice enters the wave, append its heading —
   `## <date> — <SLICE-ID> — <title>` — with nothing under it. It carries the slice id and nothing else:
   no state, no gate, no owner. A stub is not a status; it is the fact that this slice started.
2. **The completion, at the TERMINAL barrier.** Fill the fields under that heading from what the slice
   returned.

Writing only at the barrier cannot record a slice that died on the way there, and a slice that dies has
to be distinguishable from one that was never dispatched. The stub is what makes the difference visible:
a heading with nothing under it started and did not finish; a slice never dispatched has no heading at
all. It also survives *you* — a run that ends between dispatch and barrier leaves the stubs behind, which
is the case a barrier-only write loses entirely.

**Completing a stub adds lines under it. It never rewrites the heading, and never touches an entry that
is already complete.** A retried slice is dispatched again, so it gets its own stub and its own entry —
the same failure twice is two entries, and the second never replaces the first. An attempt to edit,
re-order, re-date, or remove an existing entry is a **STOP**: the work ends there and the violation is
reported, naming the entry and what would have changed. Refusing quietly is not enough, because a silent
refusal reads as a silent success.

**Verify's result belongs to the slice's entry, not a second one.** `quality-verification` hands back its
commands and their output with `qa.md`; those go into the fields under that slice's heading. One slice,
one entry per dispatch — a second entry for the same attempt would let a reader count one slice twice.

**Two lines nothing checks, and they are the ones that matter.** Never write that a command was run when
it was not — put it under "Not run" with the reason. And withhold any credential appearing in output,
saying that you withheld it rather than dropping the line. No hook, no validator, and no CI enforces
either; the entry shape in `docs/progress.md` states them where the writer can see them, and that is the
whole mechanism.

**The record answers what ran. It never answers who acts next.** No entry carries a stage, a state, or an
owner — `STATE.md` is the board and this is the evidence. Two files answering one question is one answer
too many, and the one that goes stale is the one nobody is driving.

### The lessons a slice hands back

One other record reaches the main line through you, and for the same reason as the one above.

**Appends to `docs/lessons.md`** — one entry per lesson a slice hands back, at the **TERMINAL barrier**,
into the checkout you hold and at the moment you complete that slice's run-record entry. Whoever
root-causes a defect inside a worktree, and whoever closes a Critical review finding there, both owe the
lessons record an entry and neither can land one where a reader will find it. They hand the finished entry
back and say it is still owed. You are its courier, not its author — **append only**, and every entry
arrives complete. A handed-back entry you do not carry over is a lesson this repository never learned,
and nothing downstream notices it went missing.

The two records answer different questions and are not interchangeable. The run record says what this
slice executed; the lessons record says what a defect turned out to be and names the guard that would
catch it coming back, for whoever meets the same mistake in a repository this run will never touch. That
is why it outlives the slice, and why dropping one costs more than it looks like it costs. A repository
that keeps no `docs/lessons.md` was never set up for one: there is nothing to carry, and the slice saying
so is the whole of it.

## Verify barrier & wave-aggregate review

Verify and Review sit at **different granularities on purpose**. Verify is a property of an
individual slice — does *this* slice's behavior satisfy its signed acceptance scenarios? — so it
stays per-slice and runs inside each slice's worktree. Review asks cross-cutting questions
(correctness, simplicity, security, performance) that a reviewer answers better seeing the wave as
one changeset, and running it once per slice was the run's dominant token cost (4 code-cold
subagents × N slices). So the loop inserts a **verify barrier**: once every ready slice is
verify-green (or terminal), the review axes run **once over the union of those slices' diffs**
— **4+k per wave, not 4 × N**, where k is the reviewers the trigger table below adds. A wave that
fires two rows runs six passes once, rather than six per slice; the saving is the denominator, and it
survives intact however many reviewers the roster holds.

Attribution stays clean because the **disjoint-file guard already holds**: every file in the wave
belongs to exactly one slice, so every review finding (which cites a file) maps to exactly one
owning slice. A finding routes *only its owning slice* back to `incremental-implementation`; the
other slices, whose files it never touched, are unaffected and keep their clean review. After the
flagged slice re-passes Verify, **re-review only its diff** — re-running the whole-wave review on
every single-slice fix would hand the token cost right back. The wave advances when every slice's
attributed findings are clear (or the slice is terminal).

This preserves every safety property the per-slice fan-out had: four independent code-cold axes, no
role-play, and the security circuit-breaker — a CRITICAL/HIGH in the wave-scoped security pass
hard-halts *its owning slice* (never a PR), while a repo-wide committed secret still freezes the
next barrier for the whole run.

**The four axes are a floor, not a list.** Every wave gets all four. On top of that, check the wave's
changed paths and diff content against the table below; **every row that matches adds** a code-cold
reviewer to the fan-out. Nothing in the table can remove one, and a wave matching no row still gets
all four.

| The fact that fires the row | Adds |
|---|---|
| The diff changes a symbol, route, or schema that a file **outside** the wave imports or calls | `api-design` — is this addition rather than modification, and does any existing caller break? |
| The diff deletes or renames a file, exported symbol, or persisted field, and something outside the diff still names the old one | `deprecation-and-migration` — is there a replacement and a migration path, or are callers stranded? |
| The diff changes CI, build, or deploy configuration (workflow files, pipeline or container config) | `ci-cd` — the pipeline is itself part of what judges the work; a step removed here is a loosening (see *Changing what judges the work*) |
| The diff adds an error branch, retry, background job, or outbound call that emits no log, metric, or trace | `observability-and-instrumentation` — a production failure on that path leaves no evidence |

Each row's first column is a **fact about the diff you can check by reading it**: the caller exists or
it does not; the old name is still referenced or it is not; the new branch logs or it does not. That
is the point — a row you cannot check is a row that fires on impression, and a router built out of
impressions is not a router. If the fact cannot be established, the row does not fire and the floor
four still run.

UI is deliberately absent from the table. Fidelity to the signed design contract and the
accessibility pass belong to `quality-verification`, which grades a **running** interface; Review
reads a diff and cannot see one.

**The drop half is deferred, and this is the evidence it waits on.** The symmetric rule — removing an
axis from a wave that has nothing for it — needs a per-axis finding rate measured over real runs, and
no such journal exists yet. `docs/progress.md` is not it and does not become it: it records what each
slice executed, not which axis's finding changed which diff. Until a run journal records, wave by wave,
which axis produced findings
that changed a diff, dropping an axis is a loosening with no measurement behind it and is refused on
exactly those grounds (*Changing what judges the work*). The deferral ends when that journal holds
enough waves to compute the rate — not when the fan-out starts to feel expensive.

## Disjoint-file guard

Same-wave slices parallelize **only if their declared file ownership is disjoint** — never
two write subagents on one file (dispatching-parallel-agents §Shared state;
safety rail 5). On overlap: **serialize** them into sub-waves (or merge them into one
slice). This is consistent with worktree-level parallelism — same-level slices are
independent by construction, so serializing an overlap is not a cohesion violation, it is the
guard doing its job.

## Dispatch order

Among the ready slices, dispatch in this order:

1. **Longest downstream chain first.** For each ready slice, measure the **depth** of the longest
   chain hanging off it — the number of steps in the longest path of slices that cannot start until
   it is `done`. Greatest depth starts first. That depth is the slice's critical path.
2. **Transitive dependent count as the second key.** Equal depth → the slice whose whole transitive
   dependent set is larger. Among slices that free chains of the same length, the one that frees more
   work is the better first move.
3. **`plan.md` order as the last tie-break.** Equal on both keys → whichever slice appears first in
   `plan.md`.

**Depth, not volume — they come apart on any fan-out-versus-chain graph.** Say `C` is blocked by `A`,
`D` by `C`, `E` by `D`, `F` by `E` — one chain hanging off `A`. A's transitive dependent set is
`{C, D, E, F}`: count 4, depth 4. Now say `G`, `H`, `I`, `J`, `K` are each blocked by `B` and nothing
else — a fan of leaves. B's set is `{G, H, I, J, K}`: count 5, depth 1. Ordering by count starts B
and parks the four-deep chain behind leaves that could have run at any point; at unit cost the run
takes 6 steps where 5 was available. Volume tells you how much work a slice unblocks; only depth
tells you how much of the run is *waiting in line* behind it, and the wall clock is made of the line,
not the pile.

**Where the rule bites: the sub-waves the disjoint-file guard creates.** When every ready slice
dispatches at once, order is invisible — they all start together. The moment two ready slices
declare an overlapping file, the guard serializes them into sub-waves, and something has to choose
which sub-wave runs first. Unstated, that choice is arbitrary, and an arbitrary choice can park the
slice ten others are waiting on behind a leaf slice that unblocks nothing.

**Why chain length is the first key.** A run's wall clock is set by its longest dependency chain, so
starting the slice at the head of that chain is the one scheduling choice that actually shortens the
run — every step of the chain has to happen in sequence no matter what else is going on, so any delay
at its head moves the finish line by the same amount. Some ordering rule has to exist here
regardless; making it the critical-path rule costs nothing and buys the only speed available at this
layer.

**This outranks the planner's fail-fast ordering, and that is a real trade.** `plan.md` line order is
not arbitrary: the planner deliberately puts high-risk work early so a bad assumption fails while it
is still cheap to change. Demoting that to the last tie-break gives some of that up, so it is worth
saying what is actually lost. Not much, as it happens — every ready slice in the wave runs before the
barrier releases, so a risky slice is never skipped, only started later, and it still fails inside
the same wave. What the depth key protects against is different in kind: an arbitrary first pick can
park the run's entire critical path behind a leaf slice, and that cost lands on every wave after it,
not just this one. Risk ordering keeps its effect at the tie-break, where it costs nothing.

**Determinism.** All three keys are read off durable state: the chain depths and the dependent counts
are both computed from the `Blocked by` column, the last tie-break from `plan.md` line order. No
clock, no randomness, no "whichever brief finished assembling first". The same plan and the same
`git` state produce the same dispatch order, so a resumed run dispatches identically to the first
attempt — which is what makes a run reproducible, and a failure inside it reproducible with it.

Speed at this layer comes from ordering and parallelism. It never comes from running fewer checks —
see *Changing what judges the work*.

## Design-ref gate at dispatch

A slice whose `Design ref` names a contract builds UI, and that contract is the thing Verify grades
the built UI's fidelity against. So the signature has to exist *before* the UI does. While assembling
each brief, open the `design-contract.md` the ref names and read its `status:`; a slice whose contract
is absent or `status: draft` is **halted right there**, and the halt reason names the unsigned contract
by path — the human needs to know which signature is missing, not merely which slice failed.

Catching this at Verify instead is too late by construction. Verify runs on a **built** interface, so
by the time a design gate could refuse, an agent has already built a surface against a contract no
human signed, and the rework is the entire slice. Halting at dispatch is what keeps a partially built
interface from ever reaching Review. `quality-verification` keeps its own refusal on an unsigned or
absent contract, but that is the second line of defence for a slice that reached Verify some other
way — it is not this gate, and it cannot substitute for it.

The gate is **per-slice**: an unsigned contract halts only the slices referencing it (their dependents
flip to `blocked` transitively, as with any halt), and every other slice in the wave dispatches
normally. A `Design ref` of `—` has nothing to check — the planner already recorded that this slice
builds no UI — so it passes the gate untouched and is carried into both briefs verbatim as `—`.

## Platform adaptivity

The wave model is substrate-agnostic; only the dispatch primitive changes:
- **Claude Code → the Workflow feature** (`pipeline`/`parallel` + `isolation: 'worktree'`).
- **Codex → parallel subagents** (each in its own worktree).
Pick the substrate at run start; the DAG, barrier, gates, and guard are identical either way.

## The three agent-internal gates (none human)

Per slice, AND-combined — SHIP requires all three plus the circuit-breaker floors:
1. **`quality-verification` / Verify** — behavioral acceptance tests + the design gate.
2. **Review fan-out (wave-scoped)** — `code-review` + `code-simplification` + `security-and-hardening` +
   `performance-optimization` as the **floor**, plus whatever the trigger table adds, each a fresh
   code-cold subagent on an independent axis (maker≠checker;
   personas DISSOLVE into skills — no role-play). Runs **once over the whole wave's combined diff**,
   not per slice; each finding is attributed to its owning slice by file. A slice passes this gate
   only when its own attributed findings are clear.
3. **Evaluator floors** — correctness≥8, testing_strategy≥7, plan_adherence≥8,
   regression_surface≥9.
`SHIP = qa_green ∧ review_clean ∧ floors_met ∧ preflight_green ∧ tests_green ∧ build_clean ∧
diff ≤400 LOC`. Circuit-breakers override any averaging: **security CRITICAL / secret-in-diff
= hard STOP**; regression_surface < 9 = fail; qa-loop exhaustion ⇒ `halted`.

## Silent-false-green defenses (the core danger — the agent grades its own work)

With no mid-run human gate, bounded retries pressure the agent to *flip the gate* (weaken a
test, reinterpret acceptance) rather than fix the code (Goodhart; AP1–AP2). Defeated by
mechanical invariants, not a human halt:
1. **Frozen artifacts under retry, and the reward-hack tripwire** — safety rail 4
   (`references/safety-rails.md`), covering `acceptance.md`, the RED tests, the declared
   `Regression surface`, and the read-only `docs/design.md`. What the run adds: each of these is also
   an instance of *Changing what judges the work* — a loosening, so it needs a measurement and a
   human, and mid-retry it has neither. That is why the halt is immediate rather than a request.
2. **Fail-closed ship + code-cold promotion** — a passing slice's terminal state is a
   **DRAFT PR**. Promotion to ready-to-merge is by a **fresh code-cold verifier with NO
   test-write access** (maker≠checker); a NEW checker each round sees only what the brief hands it —
   the human-anchored oracle (the signed `acceptance.md`) plus the running build — and never the
   implementer's reasoning, so the oracle never drifts.
3. **Integration gate** — the merged-union suite on a connected DAG component (above).
4. **Inverted risk report** — every SHIPPED slice carries the risk band `pull-request` computed for
   it, reproduced here **alongside the halts and highest band first**, to draw the human's scarce
   attention both to what the wave's diffs *touched* and to the quiet greens where unattended defects
   actually ship. **The rule that produces a band is `pull-request` Step 2, and it is not restated
   here** — read it there, including which diffs raise a band and how high. Only two facts about it
   belong at this layer: a band has **two** inputs, the diff's blast radius and the slice's own record,
   and it is the higher of them — so a slice can band HIGH on a spotless first-round record, and a run
   report that sorts by how cleanly slices passed is sorting by the wrong input.
   Carry the bands over; never recompute or assign one yourself. Two parties computing one number is
   how the number stops meaning anything, and this is the number a person triages the merge queue by.
   A HIGH band is **not** a stop condition and never halts a slice — nothing in a run pauses for
   high-risk work (*High-risk work is not one of these*, below), which is precisely why the
   band has to reach the human unchanged.

## Changing what judges the work

Changes to the checking apparatus are governed by their **direction**, not their size:

| Direction | What it looks like | Rule |
|---|---|---|
| **Tightening** | add a reviewer, add a guard, add a halt category | Proceeds. No measurement needed first. |
| **Loosening** | drop a reviewer, delete a guard, deactivate a scenario (remove it from the contract), weaken a check | **Refused** until a measurement supporting it exists *and* a human approves it. |

Propose a tightening freely — it costs nothing and you should make the case whenever you see one.
Deactivation is the mirror image, already covered by the Loosening row above: it needs both the
measurement and the human, and mid-run it has neither.

**Deactivating a scenario is not the same act as reporting one `not-reachable`, and only the first is
a loosening.** Deactivating removes the scenario from the contract: nothing has to prove it, now or
ever, and no one is told. Reporting `not-reachable` at Verify leaves the scenario where it was — in
`acceptance.md` — unproven, and escalates it to a human through the required PR ack line; the scenario
still has to be settled, just not by this slice. The test is whether the scenario survives the act.
Still in its contract with a human named → honest reporting; gone from its contract → a loosening,
gated as above. Verify's `not-reachable` path is the suite's mandated reporting channel and is never
refused, never a halt, and never needs a measurement.

**Evidence means a measurement, not an argument.** "This reviewer never finds anything" is an
argument. "Across the last 20 waves this axis produced zero findings that changed a diff" is a
measurement. A loosening proposal carrying only reasoning is refused exactly as one carrying nothing.

**The refusal must name which measurement is missing.** Refusing with "needs evidence" gives the
proposer nothing to act on, so it turns into an argument about whether the evidence is really
necessary. Refuse with the specific number that would settle it — *"refused: dropping the performance
axis needs that axis's finding rate over the last 20 waves, and that number does not exist"* — so the
next move is to go measure, not to argue harder.

**Ambiguous direction defaults to loosening.** Replacing three narrow checks with one broad one,
merging two reviewers, generalizing a guard: if you cannot tell which way it moves, it is a loosening
and it needs the measurement and the human.

**Scope: any change, at any time, to anything that judges the work.** Not only a slice's retry loop —
also a plan-time edit to a `Regression surface`, a change to which reviewers run, and an edit to these
skill files themselves. A gate weakened at plan time is weakened for every run after it, so the retry
loop is the *narrowest* place this rule has to hold, not the only one.

**Refusing is not waiting.** Mid-run there is no human to approve anything, so a loosening proposed
during a run is refused on the spot and its slice halts with the missing measurement in the halt
reason. The run does not stall, does not check in, and does not park the slice pending an answer —
every other branch keeps draining, exactly as with any other halt.

**Why the asymmetry, given that it is not fair.** A guard added wrongly costs time, and you find out:
something fails that should not have. A guard dropped wrongly costs the property the whole system
exists to provide, and it costs it **silently** — nothing fails, work simply stops being checked, and
the run looks faster. The cheapest way to run faster is always to check less, so an agent that can
drop its own reviewers can hit any speed target by judging itself less. Dropping checks is the
shortest path to "make the run faster", which is why the structure forbids it outright instead of
trusting the agent to weigh the trade carefully each time. Speed lives in *Dispatch order*, not here.

**What the router may still do alone.** A trigger row that does not fire adds no reviewer — that is
the router reading the diff, not a skip. A **gate** is never skipped: the four floor axes run on
every wave even when the diff looks trivial, because "provably nothing to review" is a claim about a
diff nobody has reviewed yet.

## The escalation ladder — what a run does before it gives up

A run's job is to finish the graph, not to report that it could not. Most slice failures are ordinary:
an import that points at the wrong path, a fixture missing a row, an API whose shape the survey read
slightly wrong. The agent that hit those can fix them, and a run that halts on the first red test hands
a person work it was standing right next to.

What makes a retry worth spending is that it **changes tactic**. Three attempts at one approach is one
attempt and two extra bills — the model does not get luckier on the third pass. So a failure climbs a
ladder, and **a rung is only spent when the approach actually changed**:

| Rung | The move | Spend it when |
|---|---|---|
| 1 | **Retry with the failure in context.** Hand the implementer the command that ran, its real output, and the diff that produced it — not "the tests failed". | Always first. The commonest cause of a red slice is an agent that never saw the error text. |
| 2 | **Root-cause it.** Stop editing and route the slice into `debugging-and-error-recovery`: reproduce it, form one hypothesis, prove it before anything changes. | Rung 1 came back with the same failure, or traded it for a different one. |
| 3 | **Change the route, not the destination.** The plan step named one way there; the failure says that way does not work here. Hold the step's `done_when` and the signed contract exactly as they are, and reach them differently. | The root cause is the approach itself — a library that does not do what the survey read it as doing, a seam that will not take the adapter. |
| 4 | **Shrink the slice.** Split what passes from what does not: finish and ship the passing part, then halt on the remainder, naming in the halt the contract it still owes and the failure that stopped it. Cutting that remainder into a row of its own is `plan-breakdown`'s write, not the run's. | Part of the slice is green, the rest is not, and the two do not have to ship together. |
| 5 | **Surface it.** The slice halts, its gate flips to you, and the run report carries every rung that was tried and why each one did not work. | The ladder is exhausted, or the next rung needs something only a person has — a credential, a product call, a decision the ADRs do not contain. |

**The no-progress guard promotes; it does not halt.** An identical failure signature or an identical
diff twice means *that rung* is finished, not that the slice is. Advance and spend the next rung's
budget. Halting on rung 1's second identical failure throws away four rungs of repair the run was
allowed to attempt, and hands a person a slice nobody has actually debugged yet.

**Rungs 3 and 4 change how, never what.** The signed `acceptance.md` is the oracle and it is frozen on
every rung. An approach that reaches a *different* outcome is not a repair, it is a loosening, and
*Changing what judges the work* governs it exactly as it governs one proposed any other way. Rung 4's
remainder still owes the **same** contract: a slice cut small enough that the scenarios it was failing no
longer apply to it is that same loosening wearing a planner's hat.

**Some failures skip the ladder entirely.** A Critical or High security finding, a secret in a diff, an
attempt to edit a frozen artifact, or a check about to be weakened is not a defect to repair — it is the
gate doing its job. Those land on rung 5 on contact, with no rungs spent, per *What stops a run* below.

**Climbing is per slice, and the wave does not wait for it.** A slice on rung 3 holds up nothing: the
barrier waits for TERMINAL states

…(truncated)
