One spec's slices, driven as one run. A mixed-origin queue — several tickets
from different specs — is burndown's job.
The loop is not here
Picking the next clump, starting it, waiting, refilling as slots free, the
box reading before each dispatch, clumping, the frontier and the run file:
all of that is burndown/SKILL.md § The loop, which
is its single home (#779). Read it there and run it as written. This file is
policy over that loop, and states only the four things a spec run does
differently: the nesting, the exploration pass, the closing ticket, and the
spec-level review. Anything it does not override, the loop decides.
The nesting
A spec run is a worker to the burn that dispatched it and a controller
to its own slices. Both at once, and neither half is metaphorical: it
reports to the burn's controller the way any worker does, escalates and parks
by that controller's rules, and it dispatches, rules on and merges its slices
the way any controller does. What a controller rules on is
implement/SKILL.md § Control, and the merge is that file's § The merge.
Its slots are debited from the dispatching burn's budget, not added beside it. One budget, one box: a nested run that counted its own slots separately would double-spend the machine the box reading is there to protect, and the burn holding the budget is the one that can see both halves. A spec run that wants more slots asks the burn for them.
The exploration pass
One pass over the spec, before any slice is dispatched: what the spec's decisions say, and what the code already does about each one. Its output is a summary — one line per decision — plus whatever must reach Chris.
What reaches him is read by
contradictions.py, not by eye:
python3 implement-spec/contradictions.py <exploration.json>
The check compares a decision the code does not implement against the spec's own ticket list first. A decision a ticket of this spec builds is not yet built — a summary line naming that ticket, never a ruling for Chris. Only "the code does this, differently" escalates as a contradiction. A decision the code has never heard of, that no slice builds, is a summary line too: a gap in the slicing, for the controller to close by filing, not drift for Chris to rule on.
Which of those two a decision is — the code has not got there yet, or the code does it another way — is the pass's own reading, and the line between them is drawn in the reference. Where both readings honestly fit, it is the first: the channel that reaches Chris is the one that has to stay clean.
The three verdicts, that boundary, the input the reader takes, and the run
this rule came from: references/exploration.md.
The closing ticket
The spec's last slice, blocked by every other one. Its body is generated by
closing_ticket.py, because the two things the closing
worker was left to invent last time are exactly the two the generator
refuses to omit:
python3 implement-spec/closing_ticket.py <repo-root> <spec> --shas <sha>,<sha> [--surface <what>]...
- It names the repo's end-to-end seam and what that seam is blind
to — from the repo's
## End-to-end seamdeclaration, which outranks the exploration pass; the pass fills only what the declaration omits, and where both are present and differ the generator refuses and names both. A seam with no stated blind spot is refused too: a green run at a seam that has drifted from the shipping surface is the failure this names. - Where the spec has a user-visible surface the seam cannot reach, the ticket says so, and its acceptance carries one open of the real thing for each — checked in the shipping surface, not in the seam.
The declaration grammar and the evidence:
references/closing-ticket.md.
The spec-level review
The closing ticket hands the review the list of merge shas — this run's landings, read off the run file — and never a git range. On a shared default branch the obvious range holds every other session's work: the #781 spec run's three squash commits sat in a range with ~17 commits nobody in that spec wrote.
/multi-axis-code-review pins one fixed point, so the list alone is not a
procedure it can run. The generated ticket carries the one that builds the
comparison out of those commits — a detached worktree, the rest cherry-picked
on, the review against the first sha's parent — so that the worker is never
left inventing the range this replaces.