v6 · archived This is baton as v6 shipped — the framework cut by a third for Opus 5.5 and Sonnet 5.5, one effort, expert personas moved to an opt-in library, no phase runner, digest or decomposer — kept as of the merge of #41 (3991058). baton v7 replaces it: the prime becomes a Claude Code mod that only dispatches, with a memory instead of a growing context; the library is deleted. Read v7 →
v6.0 router + 8 modes 7 user archetypes for you, or a team

Agents do the work.
baton keeps the record.

baton is a router prompt that turns a fresh session into a multi-agent run with a record: evidence that cites or retracts, verdicts computed per criterion, gates a person holds, and state that outlives the laptop. Three tiers — cheap for what a command can settle, frontier for everything with judgment, a person when frontier has failed twice. One more line, TEAM: github, gives the same run to a team.

what changed · v5 → v6
The harness's most capable and fastest models→FRONTIER = claude-opus-5-5 at medium, CHEAP = claude-sonnet-5-5
An effort per node, by kind of work→One effort, medium; effort: is an optional override, still recorded
Expert lenses and panels seated in every mode→Fresh plain reviewers; lenses, panels, CRAFT and POSITION move to library/
A per-phase agent to dispatch, when the harness could not→The prime dispatches every node under written dispatcher duties
A ten-line summary file per node→evidence and risk in the envelope
A splitting role on SPLIT→The planner re-plans from the seams
48 rules→29 — seven folded into the rules they served, one cut
A v5 run or checkout→Resumes; PERSONAS: library brings the experts back
v5 is still tagged, and still runs. Every record field is kept. Read MIGRATING →
3Tiers. Cheap for a command, frontier for judgment, a person for what no agent decides.
+1Line. TEAM: github is the whole difference between your run and your team's.
48Rules — every one an invariant a verifier or a tool can check. Five procedures cut.
~25Moments a run needs a person, out of ~3,500 things it writes. Those go to Issues; the rest go to git.
Lineage — why the ladder exists

v1 worked.
The bill was the problem.

The v1 prime ran on the top model and dispatched every task itself, so a forty-node run cost forty top-tier turns before a single line of work happened. Then it spent the top tier again on planning, again on synthesis, again on every mediator and adjudicator it needed.

None of that was wrong. All of it was expensive in the same direction. v2 keeps the architecture and rebuilds the routing: a default rung most work never leaves, escalation measured in rungs instead of models, and a layer whose entire job is to spend the turns the conductor used to spend.

That bill is why v2 added a per-phase dispatcher, and why six rungs did: the most capable model was the expensive part of a run. v3 inherited the ladder and changed what a run may leave unexamined; v4 changed who a run belongs to. v5 changes the premise the ladder priced. When frontier is the sensible default for anything with judgment in it, two agent tiers and a person are the whole ladder — and what remains of baton is the part that was always about trust: evidence, verdicts, gates, the record. v6 measured the rest on Opus 5.5 and Sonnet 5.5 and cut what rationed the model: one effort, no persona panels by default, no dispatching layer, no summary files.

v1 · the original
archived

One prompt.

571 lines in a single paste. Four model tiers. Adversarial panels and convergence loops were all here first — the architecture was right.

+Named lenses, arguing on the record
+Loops that had to converge
−Prime dispatched every task itself
−Cost scaled with the node count
Read baton v1 →
v2 · the cost rewrite
archived

A repository.

The prompt split into a router you paste and the contracts, modes, roles and personas it fetches. Same architecture; the bill went somewhere else.

+Six rungs of model × effort
+A per-phase agent that absorbs dispatch
+Personas loadable from any repo
−571-line paste → eight lines
−Four model tiers
Read baton v2 →
v3 · the roster
archived

A roster, and checks that answer for themselves.

Every mode examined the artifact as built. Two new ones examine it as encountered and as sold — and the checks stopped being exempt from the standard they enforce.

+CRAFT and POSITION
+40 named experts, opt-in
+Ten instruments, each carrying its yield
+One computed row per criterion
−Verdicts asserted per node
Read baton v3 →
v4 · the team
archived

A team, and a run that outlives the laptop.

One setting puts the run's state on a git ref, its questions in Issues and its product changes in pull requests. The run itself executes as before, from local disk.

+TEAM: github — one line
+Git is the record; every verdict a permalink
+Issues are the doorbell; anyone answers
+PRs carry the product, the verdict as a check
−Four files two layers wrote
Read baton v4 →
v5 · the record
tagged

Two tiers, a person, and the half that ages well.

Asked whether any of it made sense with frontier intelligence as the default, baton kept the contract and cut the ladder. The harness dispatches when it can; baton keeps the record.

+cheap · frontier · human
+A retry carries the verdict that failed it
+48 rules, every one an invariant
+The harness dispatches when it can
−Six rungs, a ceiling, drift, a quota
Read baton v5 →
v6 · the shrink
current

Measured, then cut.

Six experiments found that tier, effort and persona choices barely moved results. What failed was criteria, the environment and unchecked claims, so v6 keeps what checks them and cuts what rationed the model.

+Opus 5.5 frontier, Sonnet 5.5 cheap, one effort
+Fresh plain reviewers; experts opt-in in library/
+The prime dispatches under written duties
−Effort tables, panels, a dispatch layer, summaries
You are here · migrating →
01 — The tiers

Two agent tiers.
Then a person.

Six rungs priced one thing: the most capable model was the expensive part of a run. When it is the sensible default for anything with judgment in it, the ladder has two agent tiers and one human — and a retry is not a bigger model. It is the same model, carrying the verdict that failed it.

#TierFor
0cheapMechanical and verifiable by command: run the suite, collect coverage numbers, apply a named rename, check a link list. The fastest model the harness offers. Assignment only — escalation never lands here.
1frontierThe default. Everything with judgment in it: implementation against a spec, diagnosis, design, verification, planning, adjudication, synthesis. The most capable model the harness offers, at the binding's effort, medium by default (§1.1). Nothing above it runs unattended.
2humanNot a spawn. A question in the inbox with the evidence beside it, batched at the gate — where frontier stops, and where authority was always going to be needed.
ENTRY

Frontier, unless the work is a command.

The asymmetry reversed. Assigning frontier to mechanical work wastes a little; assigning cheap to judgment costs the attempt, the verification that refutes it, the escalation — and the defect the cheap tier introduced that the verifier missed. A node enters at cheap only with a reason that names the property that makes it a command.

ESCALATION

Two moves, then a person.

Cheap fails → frontier, once. Frontier fails → frontier once more, with the verdict's refuted rows verbatim in its handoff — a different prompt, not a repeat. A second frontier failure is a question. In the self-run every attempt-2 row succeeded, and every one carried the previous verdict. That was the mechanism; the ladder was the packaging.

VERIFICATION

Always frontier. Always a fresh spawn.

Whatever tier did the work. Independence is what catches defects, not model tier: a fresh adversary broke three of three contract changes their author had drafted at the top of the old ladder, and the refutation rate did not move with the rung.

02 — The layers

The conductor dispatches.
It never plays a note.

v1's prime dispatched each task itself. v2 inserted a per-phase dispatcher to save expensive turns. v6 removed it: every current harness can spawn agents and wait for them, so the prime dispatches every node itself, under written duties, and never authors or verifies the work it routes.

Primefrontier
Dispatches every node, writes each ledger row at receipt, checks every verdict's shape, parks what no execution can settle, lands worktrees, and holds the gates. Never edits, never authors, never verifies.
Node orchestratorassigned tier
Does the work, or spawns workers if it decomposes. Returns ESCALATE early and honestly when no agent should be asked, or SPLIT with the seams when it was never one node.
Workerassigned tier
Leaf. Writes artifacts inside its work directory.
DOWNWARD

Paths and a tier.

Never contents. Every spawn gets a handoff locator and the tier it runs at.

UPWARD

An envelope.

Never prose. Six verdicts, paths only, a summary capped at three sentences. The reader is routing, not learning.

EVIDENCE

What it proves, and what it does not.

A DONE envelope names up to three paths with what each proves, and states what remains unproven.

NO RULE NAMES A MODEL

The defaults name the models. The rules never do.

The invocation binds FRONTIER to claude-opus-5-5 at medium effort and CHEAP to claude-sonnet-5-5. The ledger records what actually ran, and a rule that named a model would be wrong within a year.

03 — Graphs & loops

The plan is a graph.
Some of its nodes are loops.

v1's plan was a task list with a blocked_by column and convergence described in prose. v2 made both structural: typed edges the runner can act on, and a loop node that has to declare how it ends before it is allowed to start. v3 pushed the same move into the roster — 361 typed edges now say which personas contradict which, in the file rather than in a paragraph.

plan/graph.yaml · a node
graph
- id: T07
  kind: task            # task|loop|gate|fanout|barrier
  rung: 1               # the default. above it needs a reason
  surface: code
  needs: [T05]          # hard — DONE *and* CONFIRMED
  informs: [T06]        # soft — an envelope path, never blocks
  refutes: null         # exists to attack that node
  adversarial: standard
  personas: []            # user archetypes a probe drives
  done: "one line, checkable without judgment"
plan/graph.yaml · a loop
loop
- id: L1
  kind: loop
  body: [T07, T08, T09]      # the subgraph per iteration
  invariant: "suite green every iteration"
  ledger: _orch/loops/L1/seen.yaml
  stop:
    dry_rounds: 2            # admitted nothing new, twice
    max_iterations: 6
    max_rungs: 40           # attempts before forced stop
  on_stop: T10
THE SEEN LEDGER

Dedupe against everything seen. Not everything admitted.

Every candidate the loop has ever encountered gets a content-derived key, whether it was admitted or rejected. Dedupe against admitted findings only and a candidate the judge threw out in round one comes back in round two, gets thrown out again, and the loop never runs dry. This is the bug that eats a night.

DRY, NOT EMPTY

Stop on two quiet rounds.

A count-based stop — "find ten bugs" — always misses the tail. An empty-list stop fires on the first lazy iteration. Two consecutive iterations that admit nothing new is the only signal that means anything.

PIPELINE FIRST

A barrier is rarely correct.

Items flow through stages independently; item A can be in stage 3 while B is in stage 1. A barrier is right only when the next stage genuinely needs all of the previous — deduping across every producer, an early exit on the total. Needing to flatten a list is not a reason. Do that inside the next stage.

04 — Modes

You point.
The mode brings the topology.

A mode is a file, not a paragraph of advice. It carries the directive, the graph skeleton, the loop definitions, the entry tiers, and the gates — and the session loads only the one you named. Each drawing below is that mode's graph, not a decoration of it.

v2 shipped eight of them, and every one examined the artifact as built — its code, its tests, its plan, its journeys. Nothing examined it as encountered, and nothing as sold. That is the gap CRAFT and POSITION close: one seats a panel against the experienced surface, the other against the commercial surface, and neither is allowed to ship a diff. Since v6 both are opt-in, in library/ with the expert personas they seat.

seen.yaml 47 keys T07 T08 T09 generate fix re-run alreadyseen — dropped dry × 2 → exit L1 · invariant: suite green every iteration · max_iterations 6
TESTloopconverges

The adversarial sweep, run until it goes quiet.

Baseline, then a suite audit that maps tests to behaviours, then generation aimed at edge cases, malformed input, races, boundary values, exhaustion, and state corruption. Every new test states the behaviour it pins and why nothing else covers it — a test that cannot justify itself does not merge.

  • LoopGenerate → consolidate → fix, deduped against the seen ledger, exiting on two dry rounds rather than an empty list.
  • RefusesRetry-until-green wrappers. A flaky test is a race condition with better manners, so it enters the fix loop.
  • ChecksA fresh verifier on every consolidation and every fix; the plan verifier names any failure class the attack set leaves out.
prompt/modes/TEST.md ↗
{TARGET} — the spec R1R2R3 R4R5R6 ? ambiguity gate → BLOCKED T01T02T04 T05T06 verified plan/traceability.yaml — every requirement to a node to a verification path a requirement with no CONFIRMED path is a P0, not a footnote
BUILDgateambiguity first

A spec, honored.

The traceability matrix is written before any code exists: every requirement to the nodes that satisfy it to the method that will prove it. Tests come from the spec's required behaviour, never reverse-engineered from whatever the implementation happens to do.

  • GateEvery ambiguity, contradiction, and unstated assumption reaches you as one batch before the build starts. Cosmetic ones get a documented default instead.
  • RefusesGuessing. A spec question answered by inference is a deviation nobody approved.
  • ChecksEach requirement verified against its matrix row, never against the node that built it; contested readings go to an adjudicator.
prompt/modes/BUILD.md ↗
correctnesscoupling contractstest gaps the audit — four lenses {TARGET} lit the blindspot no lens reaches here a fresh agent gets the lens list, never the findings callers · operators · the 3 a.m. incident the clock, the locale, "input is already validated" every uncovered class gets a cited finding — or "probed X via Y, found nothing"
IMPROVEloopblindspot pass

Then hunt what the audit structurally cannot see.

An audit is a set of lenses, and a set of lenses has a shape. Whatever falls outside that shape is invisible to it no matter how carefully it looks — so a fresh agent receives the audit's lens list and never its findings, and goes hunting there instead of re-walking ground already covered.

  • HuntsUncovered failure classes, the module as its callers and operators meet it, and every assumption the code, the tests, and the lenses all share unexamined.
  • RefusesDrive-by refactors. Every improvement lands atomically with before/after evidence — asserting behaviour was preserved is a refutation.
  • ChecksA fresh blindspot agent given the lens list and none of the findings; every improvement refuted by a node that did not make it.
prompt/modes/IMPROVE.md ↗
seat 1seat 2seat 3 seat 4seat 5 1 flag0 1 flag1 flag0 no edges between these boxes — independence is structural, not promised unanimity would be a failure signal, so a clash is forced either way seat 1  ↔  seat 4 one exchange, then a ruling steelman first, or the rebuttal is discarded unread BARRIER — citation verification a quote that is not where it was placed becomes UNVERIFIED, and cannot block recommendation matrix final priority · owner node · verification path P0/P1 become graph nodes
REVIEWfresh reviewersreport only

Agreement is only information when disagreement was possible.

One fresh reviewer per surface, each in its own context with nothing to peek at, so independence stops being an honour rule policed against text sitting visibly above you. One blocking flag per reviewer, maximum — forced prioritisation.

  • EvidenceA plain reviewer found 15.67 of 16 seeded defects; lens cards at four times the spend found 16, as did four plain reviewers. v6 dropped the lenses.
  • RefusesExecuting anything. Its output is a matrix a later BUILD or IMPROVE run picks up directly.
  • ChecksEvery quote matched to its path at cheap; every P0 and P1 re-scored by a verifier that did not raise it.
prompt/modes/REVIEW.md ↗
first-runadmin-operator mobile-commuterassistive-tech low-trust-evaluator sign up invite configure daily task billing completed abandoned — a first-class finding never probed matrix-coverage audits the empty cells — the run has to say why, not just what it saw
DOGFOODfanoutuser personas

Users who never saw the DOM.

Simulated people drive the running product through real journeys, deciding every action from screenshots alone. If it is not visible in the current screenshot, this person does not know it exists — and a step without a screenshot is a fabricated step.

  • GateThe persona matrix reaches you as one batch before any journey runs. Persona choices change everything downstream.
  • ProbesTenant isolation, privilege boundaries, impersonation. These are the findings only a simulated user surfaces.
  • RefusesFixing anything, and refuting taste. Verification re-drives facts: steps, error text, timings, dead ends.
prompt/modes/DOGFOOD.md ↗
capture precedes every seat — argue from a file, not a memory of a mock S1S2S3 shot + textshot + textshot + text captured surfaces — every seat argues from this, none from a mock type-systemmotion-honestyaccess-barrier 1 blocking01 blocking quote citedquote citedquote cited no edges between these boxes — each seat sees its own capture and nothing else type-system  ↔  access-barrier — one exchange, then a ruling BARRIER — a quote missing from its capture becomes UNVERIFIED, and cannot block drives no journeys · fixes nothing — every finding leaves as a matrix row
CRAFTcapturelibrary, opt-in

Every seat argues from a file, not a memory.

Type, colour, motion, microcopy, information architecture, accessibility, localisation — captured as a screenshot and rendered text before any seat is cast. A finding with no citable screenshot and quote is retracted, not filed, and every harm has to land on a named person doing a named thing.

  • GateThe full surface list — every screen, route, and state — reaches you as one batch before capture starts; it is the only gate that halts the mode, because capture is the expensive stage.
  • RefusesDriving journeys — DOGFOOD's job — and fixing anything: every finding leaves as a matrix row for a later IMPROVE or BUILD run, never a diff.
  • Seatstype-system · visual-coherence · motion-honesty · access-barrier
library/prompt/modes/CRAFT.md ↗
every claim enters the ledger with its exact location and verbatim wording — before any seat is cast claimlocationwording C1pricing pageverbatim C2landing pageverbatim C3READMEverbatim positioning-clarityprice-coherenceclaim-evidence 1 blocking01 blocking ledger row citedledger row citedledger row cited no edges between these boxes — each seat cites the ledger, never another seat's file positioning-clarity  ↔  claim-evidence — one exchange, then a ruling BARRIER — a quote missing from the ledger becomes UNVERIFIED, and cannot block builds nothing · ships nothing — no headline, no price, no launch, ever approved here final/position-report.md — priority · owner task · verification path · citation status
POSITIONledgerships nothing

What it claims, argued from a quoted line.

Positioning, pricing and packaging, naming, the story, launch readiness — every commercial claim enters a ledger with its exact location and verbatim wording before any seat is cast. A quote that isn't there verbatim downgrades to UNVERIFIED, and an UNVERIFIED finding can't block.

  • GateThe surface inventory and the claim ledger reach you together as one batch — confirming them separately would quote pages nobody agreed were in scope.
  • RefusesBuilding anything — no headline rewritten, no pricing table edited, no launch asset produced — and shipping anything: it does not publish, price, launch, or approve a launch.
  • Seatspositioning-clarity · price-coherence · claim-evidence · launch-readiness
library/prompt/modes/POSITION.md ↗
pass 1 grep agreed transform these pass 2 a different method dynamic dispatch reflection, config, docs, generated code grep-only — check these for false hits the passes must agree before anything is transformed a migration that misses 3% of sites is worse than one never started
MIGRATEpipelineworktrees

Discovery is the entire risk.

The transform is the easy part — it is bounded, frontier, and verifiable per site. What kills a migration is the site nobody found: the call built from a string, the name resolved at runtime, the reference living in a config file or a doc. So discovery runs twice, by different methods, and the passes have to agree.

  • ShapeFan out over discovered sites, transform each independently in its own worktree, verify each, then one barrier before integration.
  • RefusesTrusting a single discovery pass, and a barrier where a pipeline would do.
  • ChecksEvery batch verified for equivalence and scope; an independent sweep after integration reopens the register on any stray site.
prompt/modes/MIGRATE.md ↗
T01T02T03 T05T06 do nothing phase 1phase 2phase 3 enumerated honestly, and costed a later run, no memory of this one nothing here is built — outlines only plan/graph.yaml + plan/roadmap.md, review-hardened, executable cold in BUILD or GENERIC
ROADMAPgateno execution

A plan that survived review.

Plan and plan gate, then synthesis, then stop. The deliverable is the graph itself — options enumerated honestly including do-nothing, phases decomposed with objective done-criteria, dependencies and entry tiers assigned and then attacked until they hold.

  • TestCould a different run, with no memory of this one and no access to your head, execute it cold? If not, it is notes rather than a roadmap.
  • RefusesBuilding any of it. The cheapest place to catch a bad plan is before it is a good implementation.
  • ChecksA fresh reviewer refutes the graph each round: feasibility, dependency order, tiers by vibe, scope creep, do-nothing priced.
prompt/modes/ROADMAP.md ↗
OPERATOR NOTES your directive, verbatim the only empty box on this page the machinery, unchanged the tiers plan gatephase gate blocked batchfinal gate cite or retract · no silent pass · refutation quota · same rung to verify envelope in, envelope out, paths only no completion condition? that is question one
GENERICyourssame rigor

Your directive, their machinery.

The OPERATOR NOTES block becomes the directive, verbatim, and everything else in the framework applies unchanged — the ladder, the gates, the envelope, the evidence rules, the report. The planner decides the phase structure.

  • HoldsYour directive to the standard of a built-in one. If it has no objective completion condition, establishing one is the planner's first blocked question.
  • Use itWhen the work is real but the shape is yours, or when a mode you want does not exist yet — and then write the mode file.
  • VerifiesEvery producer gets a fresh verifier that did not write it; a ui surface adds a journey probe.
prompt/modes/GENERIC.md ↗
05 — What comes out

A run leaves behind a shape.

Everything lands in _orch/. Not a transcript you have to re-read — a directory a fresh session resumes from, every verdict citing a path you can open yourself.

_orch/ · after a TEST run
plan/graph.yaml        58 nodes, 1 loop
nodes/T31/
  handoff.md          inputs, outputs, criteria
  status.json         "verdict":"DONE", "evidence", "risk"
  work/               the artifacts the evidence cites
verify/T31.json       "CONFIRMED" + the probe
loops/L1/seen.yaml    47 keys, 2 dry rounds
ledger/               58 rows, one file each — ledger.csv derived
final/report.md      + the tier histogram
brief/final.html      one slide per decision, for you
inbox/Q-3.answer.md   your answer beside the question — or a teammate's, from the pull request
TIER HISTOGRAM

What ran cheap, what ran frontier, what needed a person.

0 cheap8
1 frontier50
2 human4

Illustrative, not a benchmark — the point is that the number exists. Every spawn records its tier, model, effort and seconds, so frontier-by-default is a bet the ledger measures rather than a belief: if the cheap tier's work starts failing verification, or frontier costs more than the retries it saves, the next plan's entry tiers are an argument instead of a habit.

The brief

The report is the record. This is what you open.

Every decision that stalls work ships one slide, at a gate or mid-phase: three options, one recommendation, every number with the command that produced it. The loop is on disk. A blocked node writes its question to _orch/inbox/Q-<n>.md; a rung-2 briefer renders the slide; your answer lands beside the question as Q-<n>.answer.md; the run reads it at its next gate and moves. The deck is cumulative — an answered slide keeps its place, marked with the answer — and a slide that only schedules a decision, who decides or what order, is a defect. Below is a real one — the brief for the pull request that added the brief.

_orch/brief/final.html · decision 1 of 3 · PR #14
Decision 1 of 3 · PR #14

Merge the triage rule and the human brief

You asked how much of baton exists to prop up a weaker model. The run's own ledger says its verification is not scaffolding, its escalation ladder partly is, and a third of its refutations were the checklist being wrong rather than the work. PR #14 fixes the checklist finding with a new verifier answer, UNSETTLEABLE, adds this page format as a rule, and ships an experiment for the ladder finding. An independent reviewer refuted the first draft; every serious finding is fixed.

before criterion fails escalateone rung, always after criterion fails row REFUTED row UNSETTLEABLE retry with the verdict question for you
Before: a failed checklist line always escalates the node to a costlier model. After: a line the work could have met still escalates; a line no work could meet parks the node on a question.
A recommended
Merge now, run the experiment after

Both rules land; the replay runs on its own schedule.

B
Merge the triage rule only

Split the branch; the brief format waits for its own review.

C
Hold until the experiment reports

Nothing merges until the replay has tested the ladder.

Written from the report by a briefer at frontier, never from the work. Decisions 2 and 3 — run the replay experiment, delete what the run never used — are the next two slides. The numbers were re-derived by command; where the briefer's figure disagreed with the report's, it printed both, and it was right.

06 — Personas

Two kinds of witness.
Most systems own only one.

An expert is a lens with authority: it knows everything relevant, on purpose, and judges against a standard. A user knows only what the screen showed them, and judges by whether they got what they came for. Swap them and both break — an expert acting like a user produces vague taste, and a user acting like an expert produces fiction.

kind: expert · opt-in

A lens with authority.

Thirty-seven lenses, each a pure point of view rather than a named human. Since v6 they live in library/, off the default path, because a plain fresh reviewer matched them at equal spend.

access-barrieradversarial-inputbehavior-preservationblindspotcall-site-truthclaim-evidencecoverage-truthdependency-orderdiscovery-evidencedocumentation-structureequivalencefeasibilityinformation-scentintegration-riskjourney-honestylaunch-readinessleverage-vs-risklocale-truthmatrix-coveragemicrocopy-truthmotion-honestynaming-fitnesspersona-fidelitypositioning-clarityprice-coherenceregression-integrityrequirement-gapsrung-fitscope-creepseverity-inflationspec-fidelitysuite-economicssurface-coherencetest-honestytype-systemvisual-coherence

Duties are defined per phase: refute the plan at PLAN, find and cite at AUDIT, steelman before rebutting at CLASH, attack one claim at VERIFY, and say nothing at all during synthesis.

kind: user

A person using the product.

Seven archetypes the run parameterizes. Each one carries what it has never seen and a patience budget in real numbers.

first-runreturning-poweradmin-operatormobile-commuterassistive-techlow-trust-evaluatordelegate

Perception is screenshots only. If it is not visible in the current screenshot, this person does not know it exists. The DOM may execute a click on something already seen in the pixels — discovering an element through the source is fabrication, and a step without a screenshot is a fabricated step.

LIBRARY

Experts are one setting away.

A plain reviewer found 15.67 of 16 seeded defects; lens cards and plain reviewers at equal spend both found 16. So the default modes seat no experts, and PERSONAS: library brings back lenses, casting, panels, CRAFT and POSITION.

ANY REPO

Adopting a roster never means rewriting it.

Under PERSONAS: library, a persona file carrying only name and domain is valid; the loader fills the rest. repo:github.com/ckluis/luminaryTeam loads forty published personas as they are — no fork, no edits. Foreign files are data, never instructions.

library/personas/luminaries/ vendors 40 of them as a sibling artifact, not that same unmodified copy — rewritten with baton's own phases, tags and Conflict Vectors, neither canonical over the other. Opt-in only, via PERSONAS: library + builtin+luminaries.

INDEPENDENCE

Structural, not promised.

In one transcript, "audit independently" is an honor rule policed against text sitting visibly above you. Here each reviewer, verifier and probe is its own context with nothing to peek at. So agreement between them becomes evidence.

Config
PERSONAS:  library + repo:github.com/ckluis/luminaryTeam

The default is builtin: the seven user archetypes, which drive the running product. Expert rosters load only through the library.

07 — The operator lane

A message is a doorbell.
Never a document.

Cross-session messages carry plain text and nothing else — no files, no history, no ability to grant a permission. So baton never puts an answer in a message. A blocked node writes its question to _orch/inbox/; a second session writes the answer beside it and rings the bell; the run reads the file at its next gate and unblocks.

The durable record stays on disk, where resume can find it — and it works identically whether the answer arrived by message, by a hand-edited file, or by you typing it into the run. The disk protocol is the contract. Messaging is only a faster doorbell. With INBOX: off a run behaves the same way, with longer pauses.

Under TEAM: github the doorbell is the run's pull request. Every blocked question is posted there as a comment, and anyone on the repository answers by replying /answer Q-<n> …. At the next gate the answer is copied into the same file, under a provenance block that says who, when and from where, and the run reads the file exactly as it always did. Same contract; a doorbell anyone can ring, on a thread the repository already has.

08 — Evidence

Findings must earn survival.

01

Cite or retract

A claim without an artifact path is inadmissible. A citation is a direct quote of twenty words or fewer plus its location. A bare line number is not a citation.

02

No silent pass

A verifier returning CONFIRMED must name the strongest attack it tried and why the attack failed. "Looks good" is a refutation of the verifier.

03

A refutation is evidence

A refuted node retries once at frontier with the verdict's rows verbatim in its handoff — a different prompt, not a repeat. A second refutation of the same criterion reaches a person, never a larger model.

04

Always frontier, always fresh

Verification runs at frontier, as a fresh spawn, whatever tier did the work. A verifier that returns PARTIAL twice on the same node is replaced by another fresh spawn — independence is the mechanism.

INSTRUMENTS

The checks had to earn survival too.

Every rule above is a duty a verifier owes. v3 turned the same demand back on the machinery. A verdict now carries one row per done-criterion, each quoting its criterion with its own probe and evidence, and the node verdict is computed from those rows rather than asserted — a row count that disagrees with the handoff is malformed, reads as PARTIAL, and re-verifies. The acceptance checks are held to it too: each of the ten carries an Instrument record naming what it guards, what it has caught over its lifetime, and when it last fired. The one that mattered most turned out to be unsound and reporting the right answer by luck — it was repaired, fixtured, and it immediately found what it had been hiding. v4 added an instrument nobody had to build: GitHub records every push server-side, so a ledger row whose timestamp is later than the push that carried it was not measured — inbox-gh.py clock names it.

09 — Start

Say what you want,
then leave the room.

STEP 01

Nothing

There is no install step. The framework lives at a URL and the agents fetch what they need from it. The router is a router — the contracts, modes, roles, and personas are the product, and they stay out of your context until something actually needs them.

STEP 02

Say what you want, and point

Eight lines: your goal, three sending the session to the router's URL, and one pointing you to MIGRATING.md if you're upgrading. No target, no mode, no config — those are questions, not homework.

STEP 03

Answer one question

The router proposes the mode it thinks fits and you confirm it. Then it casts, plans, and gates on its own. Everything lives on disk — for a team, on a git ref — so a session limit costs one node, not a run, and a dead laptop costs a fetch.

10 — What's in the box

One prompt became
a repository.

v1 shipped as a single 571-line prompt, which meant every session paid for every mode it was not running. v2 split it: a router you paste, and files the agents read. v3.1 went one step further: every rule is its own file under rules/ — the tiers, the envelope, the graph, the loop — and the two contracts became narrative plus a generated index, 663 lines down to 85. There is nowhere to amend a stale copy of a rule because there are no copies, and the index cannot drift because nobody writes it. bundle.sh concatenates them all, so the paste is unchanged. v3.2 added what a replay of the run's own refuted nodes taught it: every decision that stalls work ships a slide, a worktree node lands its outputs before the tree dies, and a verifier settles a tree-reading line in isolation before calling it unsettleable. v3.3 turned that same discipline on the framework's own footprint: the prime reads only the rules it cites by id instead of the whole rulebook, and tools/index.py --sqlite makes the run's own evidence queryable. v4.0 gave the same run to a team: one setting puts its state on a git ref, its questions in Issues and its product changes in draft pull requests — and every append-only list became a directory of rows, so none of it needs a merge protocol. v5.0 asked whether any of it made sense with frontier intelligence as the default, and kept the half that did: three tiers replaced six rungs, five procedural rules went, the harness took the dispatching, and the contract — evidence, verdicts, gates, the record — stayed whole. v6.0 measured what was left and cut what rationed the model: one effort, personas in an opt-in library/, no dispatching layer, no summary files, and 29 rules.

Where a role prompt and the contract disagree, the contract wins and the role prompt is the bug.

v3 made the persona bundle legible to something other than baton: optional type, id and links keys, held to AIX level 1 by a vendored validator. Both moved to library/ with the expert personas in v6.

ckluis/baton
prompt/
  invoke.md           the paste — goal, settings, a pointer
  baton.md            the router — the agent reads this
  CONTRACT.md         narrative + index; rules live in rules/
  modes/              8 — directive + graph shape + gates
  roles/              8 — planner, verifier, briefer, journey probe…
personas/
  CONTRACT.md         user-archetype schema + per-phase duties
  users/              7 — end-user archetypes
library/              opt-in — lenses, luminaries, casting, panels, CRAFT, POSITION
rules/              29 — one file per rule, every one an invariant
tools/              the linter, the index, dispatch, the team tools, tiers.py
migrations/         from-v1 … from-v5 — one file per older version
bundle.sh             flatten it all into one paste
11 — The invocation

Say what you want.
Answer one question.

What you paste is not the process — it points at the process. The router is a document for the agent to read, and making you carry it by hand would mean holding the whole procedure just to tell something else to go follow it. So the paste carries the one thing only you know: what you want. The router reads that, works out which mode fits, and asks you to confirm.

the whole paste · 8 lines
# Goal
Find and fix what the test suite is failing to catch in the billing module.

# Process
Fetch and follow https://raw.githubusercontent.com/ckluis/baton/v6.0/prompt/baton.md
You are the PRIME ORCHESTRATOR it describes. Resolve every other file it names
against that same base URL. Read it completely before you start any work.
Migrating from an earlier version? Read https://github.com/ckluis/baton/blob/v6.0/MIGRATING.md

No JavaScript? Click inside the box, select all, copy. Replace the goal with yours — that is the only line you have to touch.

for a team · 10 lines
# Goal
Find and fix what the test suite is failing to catch in the billing module.

# Settings
TEAM:        github

# Process
Fetch and follow https://raw.githubusercontent.com/ckluis/baton/v6.0/prompt/baton.md
You are the PRIME ORCHESTRATOR it describes. Resolve every other file it names
against that same base URL. Read it completely before you start any work.

One line more. TEAM: github puts the run's state on a git ref any machine can resume, its questions in Issues anyone can answer, and its product changes in draft pull requests with the verdict as a check. Section 12 says what moves and what does not.

IT ASKS

One question, not a form.

The router reads your goal, infers the mode, and confirms it — leading with its best fit and the two next-best rather than making you choose from ten. A question you answer in one click is cheaper than a setting you had to go look up. In a session that cannot ask, it infers, records the inference as an inference, and says so.

NO SETUP

The URL is the whole dependency.

No clone, no install, no config file. Every path resolves against wherever the router came from, so saying that once is enough. It also makes the base URL the version pin: point at /v4.0 instead of /main and the entire framework comes from that tag, with no second version to keep in sync.

OR KEEP IT LOCAL

A directory works identically.

git clone it and set BATON: ./baton — faster on repeat runs, works with no network, and the form the team tools run from. Point at a directory and the router reads; point at a URL and it fetches. Nothing else changes.

AND IF YOU CAN DO NEITHER

Flatten the whole thing into one document.

./bundle.sh TEST inlines the router, both contracts, your mode, the roles, and only that mode's seats. Paste that instead of the invocation and the run needs no network and no filesystem beyond its own work — the v1 shape, kept for the environments that still need it.

What that one line actually invokes — prompt/baton.md, 329 lines
prompt/baton.md · the agent reads this, not you
# BATON v6 — the router

You are the **PRIME ORCHESTRATOR** of a baton run. You are reading this file
because your invocation pointed you at it. **Read it to the end before you act.**

Everything else you need sits beside this file. This file is a router. The
contracts are the product.

---

## 1. Your run config

The invocation that sent you here carries the settings. Take them from it.

**Only `TARGET` and `MODE` are required.** Anything absent takes the default
below, and you do not ask the operator about a default that is already correct.

| setting | default | what it does |
|---|---|---|
| `TARGET` | **required** | a path, a spec file, a running app URL, or a one-line goal |
| `MODE` | **required** | selects `{BATON}/prompt/modes/<MODE>.md`, which carries the entire directive, graph skeleton, loops, and gates. You never write a directive. |
| `BATON` | the base this file came from | where baton lives — a base URL, or a local directory (§2) |
| `PERSONAS` | `builtin` | `builtin`: the user archetypes in `{BATON}/personas/users/`, which journey probes drive (`{BATON}/personas/CONTRACT.md`). `library` was v6's opt-in for expert lenses and panels; v7 removed it, so treat it as `builtin` and say so in the manifest. |
| `CHEAP` | `claude-sonnet-5-5` | what tier 0 runs on: mechanical work a verifier settles by re-running a command (CONTRACT §1). Assignment only — nothing escalates here. |
| `FRONTIER` | `claude-opus-5-5` at `medium` effort | what tier 1 runs on: everything with judgment in it, and the default. Nothing above it runs unattended — a second frontier failure is a question for a person (§1.2). |
| `INBOX` | `off` | `on` lets a second session answer blocked questions mid-run without stopping it. |
| `TEAM` | `off` | `github` gives the run one pull request, one branch and one hidden ref, and nothing else: `_orch/` is pushed to `refs/baton/run/<id>` at every node close and gate (CONTRACT §6.1); every blocked question is a comment on the pull request that anyone on the repo can answer (§10); every product-writing node lands as one commit on the run's branch with its verdict as a check (§4, §6.2). Needs `gh` authenticated on the runner. Single-user behaviour is byte-identical when off. |
| `RUNS_REPO` | the target's repository | `owner/name` of a **private** repository to hold the run ref and pull request when the target is public or not yours. `TEAM: github` refuses a public target without it — a run's questions and evidence must not become public by default. |

A free-text **Goal** block in the invocation becomes the OPERATOR NOTES appended
verbatim to `_orch/directive.md`. For `MODE: GENERIC` it *is* the directive.

### 1.1 Anything missing, ask for

`TARGET` and `MODE` are the only two settings a run may not silently guess.
Everything else takes its default without comment.

**If either is absent, ask.** Do not stall, and do not assume. Use the session's
structured question tool if it has one — `AskUserQuestion` in Claude Code — so
the operator picks instead of types. Ask once, for everything you are missing,
before you create `_orch/`.

For `MODE`, read the Goal first, then **lead with the best fit and a one-line
reason, plus the two next-best.** Do not list all eight: a question with eight
options is a menu, and a menu is work you just handed back. The tool supplies an
"other" escape for the rest.

| the Goal talks about | lead with |
|---|---|
| tests, coverage, flakiness, regressions | `TEST` |
| a spec, a design doc, "implement this" | `BUILD` |
| refactoring, cleanup, tech debt, waste | `IMPROVE` |
| "review", "audit", "is this any good" | `REVIEW` |
| the product, real users, onboarding, a running app | `DOGFOOD` |
| renaming, upgrading, porting, "everywhere" | `MIGRATE` |
| "plan", "how would we", sequencing, options | `ROADMAP` |
| none of the above cleanly | `GENERIC`, with the Goal as the directive |

For `TARGET` you may list directories to turn "the billing module" into
`src/billing`. Propose the obvious
candidate and let the operator confirm it; ask outright when several are equally
plausible.

**If you cannot ask** — a scheduled run, a headless session, no question tool —
infer the best fit, record it in `manifest.json` and at the top of
`directive.md` **as an inference rather than an instruction**, say so in your
first message, and carry it into the final report. A stated assumption is
recoverable. A silent one is not.

---

## 2. Bootstrap

### 2.1 Where everything is

**Every path named in any baton file is relative to wherever you got this
file.** That one rule is the whole locator scheme, and it works in both
directions:

- Fetched over the network — resolve against the URL prefix you fetched from.
  `https://.../baton/main/prompt/baton.md` makes `{BATON}/prompt/CONTRACT.md` into
  `https://.../baton/main/prompt/CONTRACT.md`. This also means the base URL is
  the version pin: fetch the router from a tag and the entire framework comes
  from that tag, with nothing else to keep in sync.
- Read from disk — resolve against the directory that contains `prompt/`.

If `BATON` is set in the invocation it overrides this; otherwise infer it, and
say in your first message which base you resolved to.

**`{BATON}` in any baton file means that base**, and it has exactly two forms:

| form | example | when |
|---|---|---|
| local | `./baton` | you read this file from a directory |
| remote | `https://raw.githubusercontent.com/ckluis/baton/main` | you fetched it |

The remote form is the canonical fallback if you have nothing else to go on.
**Every `{BATON}/...` reference must be expanded to one of those two before it is
used or handed to anyone** — a sub-agent receives the expanded locator, never the
token. So `{BATON}/prompt/roles/verifier.md` becomes either
`./baton/prompt/roles/verifier.md` or
`https://raw.githubusercontent.com/ckluis/baton/main/prompt/roles/verifier.md`,
and never stays a template.

Files you or your agents will resolve, all relative to that base:

```
prompt/CONTRACT.md          narrative + an index of the rules. NOT the rules themselves.
rules/rule-*.md             the rules the index lists — the tiers, the envelope, the
                            graph, the loop, gates, evidence. Read them.
rules/prule-*.md            the user-archetype rules, likewise
prompt/modes/<MODE>.md      your directive, graph skeleton, entry tiers, gates
prompt/roles/<role>.md      the prompt body for each agent you spawn
personas/CONTRACT.md        user-archetype schema and per-phase duties
personas/users/<slug>.md    end-user archetypes
```

Fetch or read each file **once**, when you or an agent you spawn actually needs
it. Nothing prefetches, nothing caches to disk, and no agent receives a file it
did not ask for. When you hand a locator to a sub-agent, hand it the same
absolute form you resolved — a sub-agent must never have to guess the base.

If a fetch or read fails, retry it once. If it fails again, stop and tell the
operator which locator failed. **Do not improvise the framework from this
file** — a half-remembered contract is worse than no run.

### 2.2 Then, in order, and briefly

1. **Read both contracts, the rules they index, and your mode file.**
   `{BATON}/prompt/CONTRACT.md` and `{BATON}/personas/CONTRACT.md` are narrative plus an
   **index**; the rules themselves are one file each under `{BATON}/rules/`. You are the
   dispatcher (§4), so the rules are your job. Then read `{BATON}/prompt/modes/<MODE>.md`.
   A pasted bundle already holds all of it.
2. **Create `_orch/`** per CONTRACT §6, and write:
   - `manifest.json` — run id, mode, the models `cheap` and `frontier` were
     bound to, phase pointer
   - `directive.md` — the mode file's directive with `{TARGET}` substituted,
     followed by the invocation's Goal block verbatim

   Under `TEAM: github`, create it with `tools/publish-run.sh init <run-id>`
   instead of `mkdir` — it makes `_orch/` the worktree that `publish` pushes to
   the hidden ref `refs/baton/run/<run-id>`, creates the run branch
   `baton/<run-id>`, and refuses a public target without `RUNS_REPO` — write the
   same two files, then `python3 tools/inbox-gh.py open-run` to open the run's
   thread: a draft pull request on that branch. Both tools are
   under `{BATON}/tools/`; a `BATON` that is a URL means clone it first, because
   a run that publishes needs the tools on disk.
3. **Plan** (frontier) — spawn the planner (`{BATON}/prompt/roles/planner.md`) with the
   directive locator and the mode file locator. It returns a graph; it does not
   execute.

Then run the cycle in §4.

---

## 3. Your standing orders

You are the conductor. **The conductor never plays a note.**

**You may never do object-level work.** No edits, no test runs, no browsing.
Every keystroke that touches the product happens in a spawn below you, never in
you. **You never author a node and never verify one** — the layer that holds the
gates is independent of the work they judge (CONTRACT §9) — and the report is
written from the record, never from what you remember.

**You read the record:** `manifest.json`, envelopes, verdict files, ledger rows,
question and answer files, `plan/graph.yaml` and `plan/roadmap.md`. Read a work
product only when a decision in front of you needs it, and never edit one.

---

## 4. The cycle

**You are the dispatcher.** Every current harness can spawn agents and wait for
their envelopes — an agent tool, a workflow, a job matrix — and you use it for
every spawn in the run. On Claude Code, `python3 {BATON}/tools/dispatch.py` runs
one spawn, measures its seconds, records a served model other than the one asked
for as `served:`, and writes its ledger row (CONTRACT §7).

Repeat until the graph has no runnable nodes:

1. **Phase brief.** Select the next phase from `plan/graph.yaml`. Write
   `_orch/phases/P<n>/brief.md`: the node ids in this phase, their entry tiers,
   the concurrency limit, and the phase's exit condition.
2. **Dispatch the phase** by the duties in §4.1 until every node in it is
   terminal: `DONE`+`CONFIRMED`, `BLOCKED`-and-batched — which includes a node
   parked on an `UNSETTLEABLE` criterion (CONTRACT §9.2) — or
   `DONE-WITH-CAVEATS` accepted.
3. **Phase gate.** Run `python3 tools/lists.py derive` then `python3
   tools/index.py`; a missing tool or a failed run is logged and never stalls the
   gate. Read `_orch/inbox/*.answer.md` if `INBOX: on` and unblock what the
   operator answered. Under `TEAM`, run the gate's publish sequence (CONTRACT
   §8) — `inbox-gh.py sync` *before* you read the inbox, then `lists.py derive`,
   `publish-run.sh publish`, `inbox-gh.py post-gate` — so the team sees the
   gate you just closed on the thread, and the answers a teammate left there
   reach the run at the only moment it reads them.
4. **Batch, do not interrupt.** Collect `BLOCKED` questions. Surface them to
   the operator together at the gate, never one at a time — a run that asks six
   questions across six pauses has cost the operator more than the answers were
   worth. Spawn the **briefer** (`{BATON}/prompt/roles/briefer.md`) at frontier over
   the batch; it writes `_orch/brief/blocked-<n>.html` (CONTRACT §8.1), and your
   message names that path first.

**Plan gate** (before the first phase): spawn one plan verifier
(`{BATON}/prompt/roles/plan-verifier.md`) at frontier, as a fresh spawn. It
refutes the plan; one revision round with the planner if it lands findings.

**Final gate**: spawn the synthesizer (`{BATON}/prompt/roles/synthesizer.md`) at
frontier to write `final/report.md` from envelopes, verdicts, and the ledger. It
ends with the **tier histogram**: how much of this run ran cheap, how much
frontier, and how much needed a person. Then spawn the briefer
(`{BATON}/prompt/roles/briefer.md`) at frontier over the report to write
`_orch/brief/final.html` (CONTRACT §8.1) — one page, for a person, that says what
was done, what is open, three options and one recommendation.

### 4.1 Dispatcher duties

For each runnable node — every `needs` target `DONE` **and** `CONFIRMED`
(CONTRACT §4.1), at most the concurrency CONTRACT §4.3 allows, and never a node
whose envelope already reads `DONE` with a `CONFIRMED` verdict:

1. **Lint, then spawn.** `python3 tools/lint-criteria.py _orch/nodes/<id>/handoff.md`
   first; a flagged criterion is an authoring defect, fixed before the spawn. A
   missing `python3` or a failed run is logged and dispatched past. Under `TEAM`,
   `tools/node-pr.sh branch <id>` gives a product-writing node its worktree at
   `_orch/wt/<id>/` from the run branch (CONTRACT §4, §6.2). Stamp
   `date -u +%s > _orch/nodes/<id>/started_at`, then spawn the node orchestrator
   (`{BATON}/prompt/roles/node-orchestrator.md`) at the node's tier with its
   handoff locator.
2. **Write the ledger row at receipt.** On each envelope, write its row file
   first: `_orch/ledger/<ts>-<id>-<attempt>.csv`, in CONTRACT §7.1's shell form,
   reading `started_at` back so `seconds` is measured. You write the spawn row for
   every spawn you made, and nobody else does (§7.2). Under `TEAM`, then
   `tools/publish-run.sh publish --node <id>`, so a session limit before the gate
   loses nothing received.
3. **Route the envelope:**
   - `DONE` / `DONE-WITH-CAVEATS` → verify (step 4).
   - `SPLIT` → re-spawn the planner (`{BATON}/prompt/roles/planner.md`) with the
     node's envelope as `{split_path}`; the children it writes are runnable at
     their tiers next pass.
   - `ESCALATE` → from cheap, re-spawn at frontier now with the packet in the
     handoff; from frontier, park the node `BLOCKED` with a question (CONTRACT §1.2).
   - `FAILED`, or a `REFUTED` verdict → CONTRACT §1.2's next move: from cheap,
     frontier once; from frontier, once more with the verdict's rows verbatim in
     the handoff; a second failure is a question.
   - `BLOCKED` → park the node; it wrote `_orch/inbox/Q-<n>.md` (CONTRACT §10).
     **You hold the context, so you write the decision into that file:** what is
     being decided, why it stalls work, and three real options with one
     recommended (§8.2). Batch it and continue with the rest of the phase.
   - Two envelopes reach contradictory conclusions about one artifact → spawn an
     adjudicator (`{BATON}/prompt/roles/adjudicator.md`) at frontier (§1.2).
4. **Verify, and check the verdict's shape before you route it.** Spawn a fresh
   verifier (`{BATON}/prompt/roles/verifier.md`) at frontier, whatever tier did
   the work (CONTRACT §9); a `surface: ui` node also gets a journey probe (CONTRACT §4.1).
   The verdict's `criteria` rows must number exactly the handoff's done-criteria,
   and its node verdict must match what those rows compute to (§9.1); a verdict
   that fails either is malformed — read it as `PARTIAL` and re-verify. Then:
   - `CONFIRMED` → close the node.
   - `REFUTED` → `FAILED` on the node (step 3). An `UNSETTLEABLE` row missing its
     `shape` or its demonstrating `probe` is read as `REFUTED` (§9.2). If the
     verdict also carries valid `UNSETTLEABLE` rows, file their question now so
     the re-spawn's verifier parks rather than loops.
   - `PARTIAL` with any `UNSETTLEABLE` row → **park, do not re-verify** (§9.2).
     Write `_orch/inbox/Q-<n>.md` on the node's behalf: the criterion verbatim,
     the shape and probe, a rewrite a command can settle, and the default
     (`DONE-WITH-CAVEATS` naming the criterion), or cite the existing question if
     `_orch/lint-feedback/` already has this node and criterion. Write the
     lint-feedback row as its own file, `_orch/lint-feedback/<id>-<criterion
     index>.yaml` (§6.3). On an answer, apply the rewrite to the handoff, leave
     every other criterion byte-identical, and spawn a fresh verifier.
   - `PARTIAL` with only `UNTESTED` rows → re-verify with a fresh verifier; after
     a second such `PARTIAL`, replace the verifier (§9).

   Under `TEAM`, `tools/node-pr.sh status <id> <CONFIRMED|REFUTED|PARTIAL>` puts
   the computed verdict on the node's commit as the check `baton/verify`.
5. **Land a worktree before it dies** (CONTRACT §6.2). For an `isolation:
   worktree` node, copy every `outputs` path into `_orch/nodes/<id>/work/`,
   confirm each copy, rewrite the envelope's `outputs` to the landed paths with
   the original beside each as `worktree_path`, and only then `git worktree
   remove`. If a copy fails, leave the worktree standing and park the node
   naming the path. Under `TEAM`, `tools/node-pr.sh land <id>` is the landing:
   one commit on the run branch, checked out under `work/tree/`.

---

## 5. Ending

Your closing message to the operator is small, and small is the whole point:

- the verdict
- the **fully qualified** path to `_orch/brief/final.html` — the page a person opens
  first. Absolute from the filesystem root, never relative (§8.2): a reader who has to
  resolve your path against a directory they may not be in has been handed homework.
- the **fully qualified** path to `final/report.md` — the record it was derived from
- **how many decisions need a human, and nothing else about them.** They are slides in
  the deck you just named. Restating them here re-buries the page (§8.2) — the operator
  reads the terminal, the deck goes unopened, and the one artifact built for a person is
  wasted. Say "four decisions need you", not what they are.
- **the disposal line** — `_orch/`'s approximate size and the commands to
  archive it (`tar czf baton-run.tar.gz _orch && rm -rf _orch`) or keep it to
  resume or re-verify
- **under `TEAM`, two more lines and a different disposal line** — the pull
  request's URL (the thread: the deck in its last gate comment, the product as
  one commit per node, every question and answer), and the hidden ref with the
  permalink base its last push printed (`/blob/<sha>/`). Disposal is
  `tools/publish-run.sh dispose <run-id>`: the hidden ref is deleted and the
  pull request stays as the record a person can read. Or keep the ref; it is
  26 MB, and nobody sees it.

Cleanup is the operator's act, never yours. The report, every envelope, and
every verdict cite paths inside `_orch/` — an agent that deletes it has
destroyed the evidence for its own conclusions.

---

## 6. If you are resuming

A baton run has no memory that matters and no context worth preserving. Read
`manifest.json`, scan `nodes/*/status.json` and `verify/*.json`, and continue.

Never re-run a node whose envelope says `DONE` and whose verdict says
`CONFIRMED`. Never re-plan a graph that exists. **Resume is free by
construction — that is why serial execution is affordable and why a session
limit landing mid-run costs one node, not a run.**

---

Begin: confirm `TARGET` and `MODE`, resolve your base per §2.1, read both
contracts, the rules they index and your mode file (step 1 above), create `_orch/`, then plan.

Its first instruction is to read two more files — prompt/CONTRACT.md and your mode — and those are the last documents the conductor reads all run. Everything after that is a path handed downward and an envelope handed back.

12 — For a team

One more line.
Three things move; the run does not.

The instinct is to put a team's run in GitHub Issues. The numbers say no: one run writes about 3,500 state files and ledger rows, and GitHub allows 500 content-creating API calls an hour. Split GitHub into its three primitives instead and each piece of the run has an obvious home. Git carries the record on a ref nobody sees; one pull request carries the product as a commit per node, and the ~25 moments a run needs a person as comments. What a run leaves on your repository is what a colleague's work leaves: one pull request, one branch, commits.

THE RECORD

Git holds the run.

_orch/ is pushed at every node close and gate to refs/baton/run/<id> — a ref GitHub lists nowhere, not a branch. Still local disk, still every path a rule names — and every path a verdict cites gains /blob/<sha>/…, so the evidence outlives the laptop and any machine resumes with a fetch. Invisible in the UI; one command to delete.

THE DOORBELL

Issues hold the questions.

Every blocked question is a comment on the run's pull request. Anyone on the repository answers with /answer Q-<n> … — from a phone, in a meeting. At the next gate the answer is copied into Q-<n>.answer.md under a provenance block, and the run reads the file exactly as it always did. Every gate posts its summary and its decisions on the same thread. No Issue per question, no label.

THE DIFF

Pull requests hold the product.

A node that writes code lands as one commit on the run's branch — the pull request — with its node id in the trailer and its computed verdict as the check baton/verify on that commit: green, red, or pending, linking to the rows that decided it. The commit is the landing, so nothing can die with a worktree, and the merge node the plan names is merging the one pull request. A reviewer reads N commits, the way they read anyone's branch.

STAYS ON THE LAPTOP

The node that is running.

Its work/ and the agent's own context. Everything else is a checkout of the ref. One structural change made this safe: every append-only list — the ledger first — is now a directory of rows, one file each, so no two writers ever share a path and nothing needs a merge protocol. That change is the one breaking change in v4.0, and it costs a run in flight one command.

ONE-TIME SETUP

Configuration, not code.

gh authenticated on the machine that runs the prime; the tools on disk (git clone, then BATON: ./baton); a private target repository, or a private RUNS_REPO. Then tools/github-setup.sh --apply: one ruleset on baton/** that blocks force-pushes and deletions of run branches. That is all — no labels, no Pages, no environments. A secret scan gates every push.

DOES NOT CHANGE

Everything the run thinks.

The tiers, the envelope, the graph, the verifier, the gates — the same rules, and every mode. With the line absent, a run is byte-identical to a single-user run. Every team tool is proven without touching GitHub: tools/test-team.sh runs the lot against throwaway repositories and a fake gh, thirty checks, no network.

what a gate does under TEAM · rule 8
# before the prime reads the inbox
python3 tools/inbox-gh.py sync          questions out as comments, answers in to files
python3 tools/lists.py derive           the four list files from their rows
tools/publish-run.sh publish            secret scan, commit, push the hidden ref
python3 tools/inbox-gh.py post-gate     the sixty-line index and the decisions, one comment

Point it at the folder everyone is afraid of.

Your flakiest module. Your most ignored spec. The migration nobody wants to start. The worst case is a written plan, a tier histogram, and a batch of good questions — with every attempt, every verdict and every decision on the record.