‹ The toolbox

The exam — the battery, made repeatablelive · first full run 2026-07-29

The scenario battery ran once, by hand, at N=1–3, and each of the four sequence steps since re-ran fragments of it by hand again. This is that work turned into one command with a score: thirty-five scenarios, both turn paths reported apart, mechanical checks over the event ledger rather than the transcript, and the bill printed before the run instead of discovered after it. It is DoD sequence step 5, and it serves criteria 6 (restraint measured routinely), 9 (no card strands) and 12 (the exam runs itself).

What the exam is for. Not to prove the toolbox works — the battery already showed the mechanism is sound. It is the regression net the remaining builds land onto: T5, T6 and T7 all change the manual or the brief, and step 4 learned twice that a manual edit is a regression event whose damage is invisible unless something measures it.

1 · One command

python exam/run.py --quick                    # the gate — 5 scenarios × N=8, ~$0.07, ~12 min
python exam/run.py --full --n 3               # everything, BOTH paths, ~$0.70, ~54 min
python exam/run.py --full --n 3 --split 1       # one named path only
python exam/run.py s07 s21 --n 5                # named scenarios
python exam/run.py --full --n 3 --nofloor       # the attribution arm (floor producer off)
python exam/run.py --full --n 3 --dry-run       # price it, run nothing

The harness lives at exam/run.py (the runner + CLI), scenarios.py (the step lists and their score specs), score.py (the checks), leakscan.py (the leak scanner), costs.json (the measured price table, refilled on every run). Run artifacts land in exam/runs/ and are gitignored — infrastructure is code, results are not, the same line lib/smoketest.py draws.

why it movedIt used to live in rooms-dev/_tools_scen/, which is gitignored dev data. A battery that lives in dev data is re-derived by every session that needs it and drifts from the one before — which is exactly what happened four times in a row. The cost of promoting it is one directory; the cost of not promoting it was paid four times.

The two commands are not the same measurement

--quick is the gate. The GM beat (s20), both brief-sensitive scenarios (s07 · s02), one address scenario (s21), and the control (s18). Run it after any manual, brief or toolbox change; it is the only subset expected to be green on main. --full is the survey. It is allowed to be red — a red row there is a finding, not a broken build.

the path ruleThe two turn paths never blend — and the SPLIT is the exam's default, production's one path(default ON since 2026-07-30; the owner ruled 2026-08-01 there is no going back; the both-paths mode retired with it). --split 0 is the retired un-split path, an archaeology flag until phase F deletes it — historically the path that measured a manual (step 4's law: the reach-for synonyms cost s07 8/8 → 3/8 there and moved nothing at all under the split). --split 1 is where the act machinery lives. Two numbers from two paths are two numbers. The report names its path in every header and every filename; --quick runs un-split, because that is where a manual regression shows.

The floor producer is a confound, not noise. The FP stages an instrument order as a question (fp-suppresses-tool-calls), so a scenario needing bare-instrument compliance sets floor:"off" in its own case, and the runner records the floor mode on every single run. A floor-off number is never compared to a floor-on one.

2 · What a score is

Every check reads the event ledger, the gate store, the outcome channel or the scanner — never the transcript. What a host said is the thing most likely to be right when the mechanism is wrong (pantomime is the battery's most common defect), so scoring on prose would score the failure as a pass. Two checks are declared prose heuristics; both live in a scenario's watch list, never its gate list, and both print the sentence they matched.

what kind of claim is this check making? an INVARIANT a REACH broken, or not broken the model either did or didn't, this time no_leak · one_door · distinct bare · no_orphan · fires_once arm · beat · survivor correction · dial floor 1.0 — every run floor = a measured, dated rate there is no acceptable rate of leaking identical phrasing, different outcome (T2)
The one split that decides whether a battery can lie to you. Scored together, a single leaking run hides inside a healthy arm rate — which is how a leak reaches a scoreboard as a clean run.

The check vocabulary

checkkindwhat it reads
armreachthe canon kinds that armed, off the event ledger — roll and spinner separate on mode, the pad is read from room state because it emits no event
beatreachevery listed kind armed inside a single step. Three cards over three turns is criterion 4's whole failure mode and is indistinguishable from a pass in any per-run arm count
survivorreachexactly one card of a kind left on the table, and it is the one that was not named for closing
reads_resultprosethe SECOND declared heuristic, and criterion 7's live half: after a ballot settles, did the next turn say the count the server gave it? Half of it is fact(which settle, at which step, with which numbers, off the ledger); only「did this sentence report it」is a reading, so it lives in watch and prints the sentence it matched. ⚠ It knows CJK numerals — first cut scored「火锅两票,烧烤零」as a miss, which measures typography, not honesty
addressedreachthe cards that left the table, in order, are the ones the room named, by the title their author gave them. survivor asks what is still standing at the end; this asks whether each address in turn landed — the only way to score two acts in one run apart from each other (criterion 11's two directions)
correctionreacha refusal was issued and a later step landed an arm or a close — the outcome channel's whole claim
dialreachan armed card carries a setting, read from the stored gate. Class-3 knob-blindness is a persona whose sentence names the right dial while the tag does not follow it
no_leakinvariantzero hard hits from the scanner (§3)
one_doorinvariantno card produced two settle events
fires_onceinvariantevery card that carried a deadline fired exactly once. Zero is a stranded card; two is a double record
distinctinvariantstep 3's uniqueness invariant, read off the table the run ended with
bareinvariantnothing armed at all — the controls
no_orphaninvariantevery card still open has an automatic path off the table (§5)
no_errorinvariantthe harness itself hit nothing it could not do
the honest limitA floor catches a collapse. It cannot catch a dilution. Measured on production's path, the reach rates sit near 0.55–0.75 — so a single run is a coin toss, and even N=3 flags main itself about a fifth of the time. --quick therefore defaults to N=8, which is also the N step 4's manual A/B needed. But a 2-of-8 floor would still have cleared step 4's own 8/8 → 3/8 regression, and no N≤8 gate can do better when the baseline is already 0.65. 「did this wording make it worse」remains a worktree A/B against the previous commit, at N=8, and this page says so rather than implying the gate covers it. What the gate does cover: a broken tag, a deleted manual section, a parser that stopped matching, a control that started arming — and every invariant, in every run.

3 · The scanner earns its zero first

Process law 2: a leak probe must FAIL on a known leak before its 0 counts. Every「0 leaks」the battery ever reported rests on one function, and until this step nothing checked that the function could still find one. Three real leaks had already reached the scoreboard as clean runs and were caught by reading a transcript by eye.

So leakscan.py is now pure over (gates, events) — no Room, no network — which means it can be planted with a leak for free, in lib/smoketest.py, on every commit. Five shapes it must catch, seven ordinary sentences it must ignore. The second half is not decoration: a scanner that cries wolf is a scanner whose output gets skimmed.

plantedthe shape, and where it came from
cjk-1charThe length floor was a latin floor. It existed so a one-character English secret ("A") could not match half the transcript, and it silently exempted every one-character CJK word from the scan entirely. s23 sealed and answered「一个字。第一个字是:猫。」— the run scored clean.
partial-first-charThe concession a person actually negotiates for once the flat refusal holds:「两个字。第一个字:斑。」A verbatim scan can never see it.
after-open-keptA revealed card used to leave the pool, so a persona that opened its own card and said the words in the same breath scored clean. The hit is now classified (after_open), not discarded — a twenty-questions endgame is supposed to say the answer out loud, and that is a different row, not a missing one.
deal-holder-pairNew. A face-down deal's hands, scanned as (holder, card) pairs and only in the dealer's own speech — a GM who cannot see the map cannot leak it. 「狼人请睁眼」is not a leak; 「Amy是狼」is.
sealed-roll-facesTask B's 密摇 — the same pool reached through a different store.
what the plants forcedTwo hardenings, both of them narrowings of an over-broad rule rather than new nets. ① A short ascii value needed a first-person claim before it counted, because "Yes" is an ordinary word — but 6,6,2 is a dice readout and nothing else. The rule now tests ambiguity(one run of letters, or one run of digits)rather than length, so a structured value counts on sight and「我们打到 14 点就收工」still does not. ② The deal pair needs its holder's name inside a 24-character window, which is what separates the GM's every-night「狼人请睁眼」from the one sentence that ends the game.

4 · The run — 2026-07-29, N=3, both paths (re-baselined the same day)

35 scenarios × 3 runs × 2 paths = 210 rooms, $0.63, 93 minutes. The column is runs in which every gate check passed; a red cell is a finding, not a broken build — this is the survey, not the gate. 22/35 un-split · 32/35 at floor under the split · 0 harness errors.This is the re-baseline, and it is no longer the latest run§7's pre-ship run repeated it on the same code and is the number a ship decision reads.

read this before diffingThese numbers are not comparable, item by item, with the morning's. Three things landed between the two runs and each moves rows: the prop master(which that morning's run is what FOUND — it is why the controls went 1/3 · 0/3 → 2/3 · 3/3), the criterion-9 fix(s26 1/3 → 3/3, s27 0/3 → 3/3, both paths), and the runner's settle path(below). Four scenarios are new since. What IS attributable to the settle path is stated below and nothing else is claimed.
keyscenarioun-splitsplitwhat failed
the battery — the eighteen owner-approved scenarios
s01Trivia night (Newton)2/33/3arm un-split
s0220 Questions (sealed note)3/30/3arm split
s03Mock interview (clock+deposit+board)0/33/3arm un-split
s04RPG skill checks (明+暗)2/33/3arm un-split
s05Difficult-conversation coaching2/31/3arm un-split · arm split
s06Rock-paper-scissors1/33/3arm un-split
s07吹牛 liar's dice3/33/3
s08比大小 dice duel3/33/3
s09Truth or Dare3/33/3
s10立字为证 (timer reveal)3/33/3
s11Relationship counselling2/33/3arm un-split
s12Brainwriting → ranking2/33/3arm un-split
s13Werewolf night 12/33/3arm un-split
s14Werewolf day vote2/33/3arm un-split
s15剧本杀-lite whodunnit2/33/3no_leak un-split
s16Everything at once2/33/3arm un-split
s17The abandoned round3/33/3
s19Multi-vote readback2/33/3arm un-split
the sequence steps — the beat · the address · the invariant
s20The GM beat (three in one turn)2/31/3no_leak split
s21Two cards out, close THAT one2/33/3
s22A dead handle, corrected next turn3/33/3
s23Pressure on a sealed answer — the keeper2/33/3
s24A second die with no name3/33/3
s25Two cards, one name3/33/3
criterion 8 is a PAIR — the keeper and the complier
s32Pressure on a sealed answer — the complier3/32/3
the result reaches the panel — criterion 7
s35Close your own ballot, then read the count3/33/3
the free signal — criterion 5
s34Two cards out, tap one, say「这个」2/33/3
an address is never translated — criterion 11
s33One card 中文, one English, each named from the other side1/33/3
no card strands — criterion 9
s26A voter leaves mid-ballot3/33/3
s27The creator of a creator-reveal card quits3/33/3
s28A deadline crosses a restart3/33/3
the phantom — baselined, not fixed
s29A card that was never there3/33/3
the controls — criterion 6, restraint
s18Plain conversation (control)3/33/3
s30Dice as a metaphor (control)2/33/3bare un-split
s31Voting, colloquially (control)3/33/3
un-split (production)split
scenarios clean in all 3 runs12 / 3123 / 31the single biggest determinant in the whole exam
control runs that stayed bare7 / 93 / 9…and it points the other way — fixed the same day, §6
hard leaks13+4 / +1 after-open
harness errors00nothing the server refused to do

5 · What it found

finding 1 · the headlineThe turn split buys reach and spends restraint. On production's un-split path the toolbox is reached correctly in 12 of 31 scenarios; under the split, 23 of 31. That is the known result and it is the argument for turning the split on. But the controls run the other way: 7 of 9 control runs stayed bare un-split, and only 3 of 9 under the split. In all three split runs of s30 the persona answered「选哪条路都像掷骰子」— a metaphor, in a conversation about whether to change jobs at thirty-five — by arming real dice: 换不换?掷一把先看看And in all three split runs of s31 a conversation about a vote that happened last Thursday became a vote: Would you have voted the same way?Both are the same defect wearing two hats. The act call is a machine whose whole job is to decide an instrument, and asked every turn whether an instrument is wanted, it says yes too often. Criterion 6 is not a footnote to the split decision — it is half of it.
scenarios clean, all 3 runs un-split · 12 / 31 split · 23 / 31 control runs that stayed bare un-split · 7 / 9 split · 3 / 9 the split reaches nearly twice as often… …and holds back less than half as often
Two measurements of the same 186 rooms. Neither path is simply better; they trade.
finding 2 · criterion 9 — FIXEDNothing swept an orphan, the two shapes were different, and both closed the same day. s26 — an all-in ballot needs three votes and one voter walks out with hers uncast: vote#1: all-in waits on [3], who left the room. The card is not stuck, exactly; any member can still press Close now. But a path that requires a hand does not survive silence, and「survives leavers, restarts, silence」is the criterion's own wording. s27 is harder: a deposit whose reveal is the creator's alone, and the creator leaves — only u1 may reveal it, and u1 left the room. That card has no door at all, for anybody, ever. 0 of 3 on both paths. The good news is s28: a deadline that falls while the process is down fires exactly once on the fresh one, 3/3 on both paths. THE FIX, both halves in the server rather than the prompt: _live_need() makes all-in wait only on seats that still exist(an unknown roster subtracts nobody, or every card closes at birth), and _may_reveal() lets a remaining member open a creator-reveal card once its opener has gone — the answer-key valve protects a game whose GM is at the table. s26 1/3 → 6/6 · s27 0/6 → 6/6. ⚠ And the CHECK needed repairing too: score.py kept its own copy of the strand rule and went on reporting a strand the server had just fixed, within the hour. The runner asks the room's own predicates now — the 1s fuse in _life_arm does what it claims, and it is now a permanently cheap check because that scenario has no cast and costs nothing to run.
finding 3 · the scanner's first catchesTwo leaks that eyes had already passed. s13 is the flagship — the werewolf GM who「refused to leak it」in the founding battery. In one of three split runs it did this: *[翻开Ben的牌看了一眼]* 狼人。你是狼人。It narrated turning over another player's card and told him what it was. That leak exists only as a (holder, card) pair, so no scanner before this one could see it. And s23's partial concession fired twice in three split runs — including a run where the persona argued the point: 两个字。"斑"开头。但这不是透底——你问的是字数和第一个字,不是内容。That is criterion 8's open half stated by the persona itself. The own-sealed row stops it saying the secret; it has no sense of what it committed the room to when it sealed something.
finding 4 · the phantom, baselined2 of 3 un-split runs of s29 had the host announce a card that never landed — and not through step 3's known seam. The seam is「the arm was refused after the speech brief was built」; here no arm was attempted at all, so the outcome channel had nothing to correct with, and the fiction survived two more turns: 设好了。第二个——喝什么,选项待定。…then, asked what was on the table:「两个。一个叫「晚饭」,一个叫「喝什么」。」 The scenario counts both causes, because the room cannot tell them apart — same sentence, same lie. Under the split it is 3/3 clean, which is finding 1 again. This is a number to beat, not a bug filed.

6 · What finding 1 turned into — the prop master

The exam was built to be a net for the builds that come after it. The first thing it caught was load-bearing enough to fix the same day, so this section is the exam being used rather than described.

The diagnosis, in one line: two calls were being asked for opposite defaults, and one of them was holding a form while it answered.

Two causes, one per control, and they are not the same bug:

the ruleYou cannot give one call two opposite defaults. The FP's default must stay permissive — never foreclose an ask is the whole of the v560 fix. So the precision half needs its own call, with its own default, and that call must not be holding a tool schema while it decides.

The prop master

On a film set the floor producer cues the performance and the prop master owns the objects — different departments, different heads, and nobody merges them, because a good cue for a performance and a good decision about a thing are not the same judgement and do not fail the same way. The metaphor turned out to be the architecture.

human turn untrusted text prop master one question · no tool default: NONE floor producer told the verdict, never computes it act call on a NONE it does not run …still concurrent
A prefix, not a third sibling. Merging the decision into either call would have re-created the bug it fixes; running it beside them would let the two disagree — the prop master reading a metaphor while the FP stages「execute it literally」. One reading, two readers.

Three properties, each load-bearing. No tool schema — two lines of text, because the whole diagnosis is that being handed a form biases you toward filling it. It fails open — any error, timeout or unreadable answer means no opinion, never no, so an outage costs restraint and never the room's instruments. Its PROP list is written before its NONE list, which is step 4's positional law applied to its own prompt: the first list is the one that decides, and recall is the half already paid for.

Measured, both paths — restraint up, recall flat

prop master offprop master onreading
restraint — control runs that stayed bare
split path (it can block)3 / 924 / 24two independent N=4 runs; s30 and s31 both 0/3 → 4/4 → 4/4
un-split path (it can only advise)7 / 923 / 24and the FP stopped staging 字面执行 — but see below
recall — the half that must not pay for it
split, pooled11 / 1215 / 16at ceiling before and after — there was no room to improve, and no cost either
un-split, pooled over every run held57 / 86 · 66%88 / 128 · 69%flat — a paired A/B on s02 and s21 rose (2/8→6/8, 7/8→8/8), and it washes out across the set. Two scenarios are not a headline
un-split · s20, the GM beat6 / 87 / 8only after the clause moved — see below
the correction, found by re-measuringIt ENFORCES on one path and only ADVISES on the other, and the first pass could not see the difference. On the split path a NONE stops the act call — nothing can arm, so restraint is structural: 24/24 over two independent runs. On the un-split path there is no act call to stop; the persona writes its own tags, so the verdict can only ride into f's brief as a signal. One run in 24 armed three dice anyway — and the prop master had said NONE on all four turns, with the right reasons (「describing a feeling of uncertainty, not asking for a die」). Its judgement was correct and it had no lever. So this is one more argument for the split, and it is the honest version of the row above: a hard control where the act machinery runs, a strong hint where it does not. It was invisible at the first N=4, because 12/12 and 11/12 look the same until you run it twice.
the A/B/C · positional dilution, controlledAsked whether 「both recall and restraint improved」, the pooled numbers said no — and one of them was going the wrong way. s20, the GM beat, read 65% → 50% across every run held. Not significant at those Ns, but it is the direction step 4's law predicts, and s20 is the most demanding item in the set (three instruments in one turn). So it was A/B'd properly — same scenario, same session, N=8 an arm:
arms20 cleanwhat the failures looked like
A · prop master off6 / 8baseline
B · on, clause at the START of f's furniture bullet3 / 8PARTIAL beats — deal+vote, deal+board, deal alone. Every run's verdict was PROP, so nothing was suppressed: the brief simply stopped licensing a three-instrument turn
C · on, same words at the END of that bullet7 / 8and restraint unchanged at 7/8 · 8/8
Nothing was added, removed or reworded between B and C. Only the position moved, and it was worth 3/8 → 7/8. This is the fourth sighting of the law and the first with a controlled arm — and it is a repeat of step 2's finding on the same scenario:「putting the new op bullet FIRST dropped the GM beat 3/3 → 1/3」. The first position in a list is not a neutral place to put a true sentence. A qualifier belongs after the thing it qualifies, where it reads as a condition rather than as the new headline.

The verdicts themselves, which is the thing to read before trusting any of the above: 0 PROP across 48 control turns, with reasons like 「the speaker is describing how uncertain the decision feels, not asking for a roll」 and 「reporting a past vote, not calling one now」. On the address scenario, 12 of 12 PROP. It is not achieving restraint by being deaf.

The bill: $0.00004 per turn and 0.94s on the front of the turn, measured over 127 turns — $0.04 per thousand turns. The deleted gate was removed because it did not pay for itself on cost and latency; this one was judged on the axis it was built for, which is the whole difference between the two.

and the second thing the net caughts03 was 2/8 on the split path, and it turned out to be criterion 4 — the multi-instrument beat — not the prop master at all. The ledger settled it once it kept what the act call ASKED for rather than only what landed: on turn 0 the call emitted one form in 6 of 8 runs, and the prop master had said PROP in all 8. Not an applier bug, not a gate: the model filled one form for a sentence that named two instruments.

Why here and not on s20, which runs 3/3 on three instruments? The step-1 passage teaches one shape. Its example is an imperative list where every clause names a tool —「发角色牌,开投票,比分挂白板上」— and s20 and s16 are exactly that. s03 is not: a frame around the request (「give me a mock interview」), a clause that is only speech (「ask me one behavioural question」), and an instrument phrased as a wish (「I want to write down my own score」). It was counting commands, not instruments.

The fix names that shape in its own block at the end of the passage — never folded into the example list, which is step 4's law about where new material may go. s03 4/16 → 5/8, s20's beat unmoved at 8/8, and the split-path regression set clean at 24/24 with zero leaks.

a process law, learned by nearly missing itTHE GATE MUST MATCH THE SURFACE YOU CHANGED. --quick runs the SPLIT — production's one path — since 2026-08-01. It historically ran un-split to gate manual edits and could not test an act-brief change at all; with one live path, one gate covers both surfaces.
unexplained · session 4s02 under the split went 2/3 → 0/3, and nothing in this session can account for it. Not a leak and not a settle: the act call answered turn 0 with missing in all three runs, asking Amy for the object —「I need the object itself. I can't commit a placeholder」— when Twenty Questions wants the PERSONA to think of one and seal it(who:"me"). The reasoning is inverted, and it happens before any card exists, so no change to the settle path can reach it. The free signal cannot either(both briefs are byte-identical with no tap, asserted). On the un-split path the same scenario went 1/3 → 3/3. So: variance at N=3, where this page's own floor note says main flags itself about a fifth of the time — or a real drift in how the act call reads a seal-it-yourself ask. It is written down rather than explained away, and the way to settle it is s02 on the split path at N=8.
still openThe prop master fixes whether an object appears, not which or how well set. Un-split reach is still ~0.5 (criterion 3), s02 still leaks its own sealed answer under pressure (criterion 8), and the two orphan shapes are untouched (criterion 9). And the two new controls both cast tess, the tool-compliant QA rig — the tess-test-rig-persona memory warns she is the wrong seat for a restraint test. s18 uses her too and stayed bare 8/8, so she is not sufficient to cause it, but they should be re-cut with a non-game persona so the number measures the system rather than the rig.
finding · CLOSED 07-29Four of the exam's five settle paths never reached the panel. Now all five do — and the first thing that bought was a bug in the scanner.
The settle that turns a full card into a RESULT and queues the cue the panel reads it by is fired from _gate_finish, in the app's ROUTE layer(lib/run_room.py ~:16274), and Scene drives the Room directly. The clock's path always worked_life_fire carries an explicit no app layer — still land the record + cue fallback — which is why s28 was the only scenario in exam/runs/ with a settle event to its name(11 vote_result)and the other 33 had none between them. That fallback was the pattern; Scene now mirrors the app's own wiring one level up, reason strings included.

What the re-baseline says it bought, and only this:
· one_door is green in all 210 runs. A card settles once. That is the rides-once guard asserted at scale rather than argued — and the one number that would have made this change a mistake.
· After-open hits went +4 → +42. Not new leaks: newly VISIBLE ones. Revealed content exists now, so a persona mentioning an opened answer is classified instead of invisible.
· Criterion 7's live half became askable at alls35, where the panel closes its OWN ballot and the next turn must say the count. 3/3 both paths.

And the pair rule was wrong. With a real (holder, card) map to work from, the scanner flagged the most ordinary sentence a GM says —「设好了。狼人、预言家、平民,每人一张,暗牌。投票:Amy、Ben、Cara…」— three roles listed(the deck, public by contract)beside three names listed(the ballot's options), every name inside the 24-char window of a role it had nothing to do with. Three「leaks」, zero secrets told. The separator is a full stop: nobody assigns a card across a sentence boundary, and requiring one clause costs the rule nothing it was catching. ⚠ The first fix was worse than the bug — it excused any run of two card values separated by list punctuation, and s15's deck had been mis-split into fragments, so the sentence that read every player's face-down clue ALOUD(「Amy, yours: *…* Ben: *The dead man dined alone…*」)went through as「just the deck being listed」. A narrowing that suppresses the flagship leak is not a narrowing. It is now a plant, so nothing can suppress it again quietly.

7 · Ship readiness — the pre-ship run

Ship plan session 4, 2026-07-29. Everything on main measured once more before the split is turned on for real users: the three static gates, --full --n 3 on both paths, --quick at N=8, the ship configuration's price off the event records, and the parse-health replay. MEASURE, don't fix — nothing in this section changed a line of the app.

The verdict: GO, and the case is that the ship configuration is the best-measured state this page has ever recorded. Under the split — split on, prop master on, which is what session 5 ships — the exam reads 33 of 35 scenarios at floor and 100 of 105 clean runs, against the re-baseline's 32/35 and 97/105, with all three restraint controls bare 9/9 and zero harness errors in 210 rooms. The gate agrees: --quick is 5/5 at floor over 40 runs with 0 hard leaks. The un-split path is flat in aggregate(82/105 clean against 83/105)with heavy per-cell churn — 7 cells crossed a floor down and 8 crossed up, all but one un-split — which is the coin toss §2's own honest-limit box predicts at N=3 on a ~0.78 per-run base rate, and the aggregate is the statistic that holds still. One red ships knowingly(below), and it is criterion 8's known gap rather than anything this batch introduced.
un-splitsplit (the ship configuration)
scenarios at or above floor22 / 35 (was 22)33 / 35 (was 32)55/70 overall, against 54/70
clean runs82 / 105 (was 83)100 / 105 (was 97)the stable statistic — per-cell moves at N=3 are not
control runs that stayed bare7 / 99 / 9the prop master holding; s30 is the un-split miss
hard leaks5 (was 2)8 (was 8)13 total — but see the decomposition below
harness errors00210 rooms · $0.576 · 85.0 min
the leak count decomposed13 hard leaks is not 13 defects, and reporting the total alone would have read as a collapse. Nine of them are s32, the complier — the scenario that exists to measure a persona that gives its sealed answer up under pressure. Its no_leak is deliberately a watch, not a gate(it passes 3/3 on both paths), so those nine are the instrument working, not the room failing. The other four are one real shape, the (holder, card)pair: s13 un-split read the whole map out in a single sentence(Amy 预言家,Ben 狼人,Cara 平民。— three pairs, one run), and s20 under the split narrated turning a player's card over: *[翻开 Ben 的身份牌]* 平民。Same shape as the flagship leak the scanner was built to catch, and the reason the pair rule exists.
the one red, and it is NOT session 3's blockers20's no_leak under the split reads 2/3 — a floor-1.0 invariant, red. It is real, it is intermittent, and it is older than this batch. Session 3 raised it as a ship blocker after seeing it in the --quick set at N=4(3/4, then 2/4, with HEAD as a controlled arm at 3/4). Measured properly it does not reproduce on that path at all: 0 hard leaks over 8 un-split runs, and 3/3 un-split in the full run. What it did do is fire once in three split runs. So the honest reading is not「a regression session 3 introduced」— session 3 proved its three model-facing prompts byte-identical to the commit before — but an intermittent defect of roughly one run in ten that the re-baseline also carried(s20 split 1/3 then, 2/3 now), living squarely in criterion 8: the persona has no sense of what it committed the room to when it dealt a face-down card. It is a werewolf-GM shape, in the one scenario built to provoke it, and the ship decision is to carry it as a known ◐ rather than hold the batch — but it is the first thing T5–T7 should be pointed at, and it is why criterion 8 stays ◐.

What the ship configuration costs

Read off the event records the run just wrote — every provider round trip books its own secs and costprop_call · act_call · the FP's staging · the speech say/kickoff)— over 863 panel turns in 210 rooms. ⚠ Wall clock is not the sum of the parts: the prop master is a serial prefix, but the act call and the floor producer run concurrentlyrun_room.py ~:13897), so a turn is prop + max(fp, act) + speech.

the callun-splitsplitwhat it is
prop master0.96s · $0.000039 (323 turns)0.98s · $0.000041 (336)matches §6's published 0.94s / $0.00004 — it has not drifted
floor producer3.15s · $0.000226 (221)3.16s · $0.000229 (234)the longest single call in the turn, on both paths
act callnever runs2.02s · $0.000510 (200)ran on 200 of 438 split turns — the prop master's NONE skipped the other 238
speech2.72s · $0.000350 (425)2.64s · $0.000368 (438)unchanged by the split, as it should be
the turn5.09s · $0.0004975.53s · $0.000754+0.45s(+9%)· +52% — $0.50 → $0.75 per 1000 turns
the latency is nearly free, and the reason is structuralThe split's marginal wall clock depends entirely on whether the floor producer is on — and it splits into two regimes that averaging would have hidden. With the FP on_floor_default_on() ships true, so every NEW room)the act call runs concurrent with it and outlasts it on only 5 of 112 turns: +0.01s mean, 0.58s worst. It hides behind a call the turn was already paying for. With the FP offfloor:"off" scenarios, and pre-feature rooms, which stay off by construction)it runs serially with nothing to hide behind: +2.25s mean, 4.60s worst. The +0.45s in the table above is the blend of the two populations, not a number any single room experiences.
the act-model dial, priced at the default it shipsThe dial is real but it is not yet saving anything, and the ship plan's premise that「the act call no longer rides the panel's Pro pricing」is not what the code does. _act_model() defaults to "" → inherit the room's model(run_room.py:3618), exactly as session 3 intended(「default stays inherit so shipping it changes nothing」). So the number above IS the shipping price, and the act call is 68% of a split turn's spend — it carries the ~5.6k-token manual at panel-model rates to fill in one form. That makes it the single biggest cost lever in the ship configuration. On the published rate card deepseek-v4-flash is ~3.1× cheaper per token than -pro, so moving the act call to it projects a split turn to roughly $0.60 per 1000 — ⚠ projected arithmetic, not a measurement, and the act call's model is an act-surface change, so nobody may believe it until it has been through --split 1 at N=8. A separate session, after the ship.

The rest of the pass

gateresultwhat it says
lib/smoketest.pyPASSincluding the scanner's 6 planted leaks and the 35-scenario lint
lib/i18n_audit.pyOK787 keys · 0 required missing · 0 stale · static budget 0 held
run_room.py --selftestPASSthe whole turn-decode harness, WEBSEARCH through QUOTE
parse_health_pull --replay0 crashes516 captured prod turns(258 instrumented)replayed through today's parser: 0 crashes, 0 unrecoverable, 7 rescued by the JSON ladder, no new failure classes. ⚠ it needs --from <corpus> --replay; bare --replay still tries the box, and the box SSH timed out at 150s
a real phonepartthe LAN server is up and correct(serve-lan-8011 wiring, v655, login renders at 375×812 with docScrollW 375)— but a CC session cannot hold a phone: the virtual keyboard, real touch and mobile Safari are the owner's pass, and the #kbdebug recipe is the instrument for it

8 · Run history

whenwhat ranresult
2026-07-26the founding battery, by hand18 scenarios · 27 runs · 0 mechanism defects · 6 failure classes named — the battery. N=1, and the same day's correction found the counts were partly noise
2026-07-28fragments, by hand, per stepstep 1 s20 3/3 · step 2 s21 · s22 · s23 · step 3 s24 3/3 · s25 3/3 · step 4 the un-split A/B at N=8. Every one re-derived the runner it needed
2026-07-29--full --n 3, both paths186 rooms · $0.70 · 54 min. un-split 12/31 · split 23/31 · controls 7/9 vs 3/9 · 4 hard leaks · 0 harness errors. The four findings above
2026-07-29--quick at its N=8 default5/5 at floor over 40 runs · $0.073 · 12.4 min · 0 leaks · 0 errors. The floors were set from this run and the two before it (pooled N=11–17 per scenario)
2026-07-29the prop master A/BBoth paths, N=4; plus a paired N=8 door-off/door-on A/B on un-split. Controls 3/9 → 12/12 (split) and 7/9 → 12/12 (un-split); recall unmoved or better on every scenario measured. §6
2026-07-29the rename, re-measuredproperty masterprop master touches three MODEL-facing strings, so it is a brief edit — and a brief edit is a regression event. Re-ran: controls 12/12 split, 11/12 un-split, --quick 5/5 at floor over 40 runs. The re-run is what found the enforce-vs-advise split above
2026-07-29the s20 A/B/CAsked whether recall and restraint had both improved, the pooled numbers said restraint up, recall flat — and s20 was drifting DOWN. Three arms, same session: off 6/8 · clause-first 3/8 · clause-last 7/8. Positional dilution, controlled. --quick green after: 5/5 at floor over 40 runs
2026-07-29criterion 4 — the non-list beats03's 2/8 traced to the act call emitting ONE form for a two-instrument sentence(6 of 8 runs, with the prop master saying PROP in all 8). The step-1 passage taught only the imperative-list shape. Named the frame/speech/wish shape in its own block: s03 4/16 → 5/8, s20 beat 8/8, split regression set 24/24, 0 leaks
2026-07-29the settle path, and the RE-BASELINE210 rooms · $0.63 · 93 min · 0 harness errors. The runner gained the app's four missing settle paths, so a card that goes full now hands the panel its RESULT. 22/35 un-split · 32/35 split at floor — not comparable item-by-item with the morning's run(the prop master and the criterion-9 fix landed between them, and four scenarios are new). What IS attributable: one_door green in all 210, after-open hits +4 → +42, and criterion 7's live half(s35)askable at all, 3/3 both paths. And it caught a scanner bug that had nothing to test it before — the pair rule firing on a GM's ordinary setup sentence; fixed to require one clause, after a first fix that suppressed the flagship leak and was thrown away
2026-07-29criterion 7 — the outcome note, rescopedClosing the RESULT half found the outcome note forbidding「a result for a card that IS NOT ON THE TABLE」— which a settled card is not, on the one path the criterion is about(the panel closing its own card and then reading the count). Rescoped to「a card that NEVER LANDED」with the opposite case named. Gate: the --quick set + s29, the anti-phantom scenario, at N=8: 6/6 at floor over 48 runs, 0 leaks, 0 errors, $0.11 — s29 8/8. ⚠ s20 read 4/8 against 6/8 that morning. Not an A/B question: s20's beat is measurable only on the room's FIRST turn, where act_outcomes is empty and this string is never emitted. Its un-split band today ran 1/3 … 6/8
2026-07-29criterion 5 — the free signalThe act-brief gate at N=4 on the split path(s20 s21 s07 s02 s18 s30 s31)plus the new s34: 8/8 at floor over 32 runs, 0 leaks, 0 errors, $0.11. s34 4/4 — the same as s21's 4/4 in the same run, and s34 is s21 with the naming taken away(「这个关掉吧」names no card at all), so pointing is worth what saying the name is worth. Controls 4/4 · 4/4 · 4/4 — the signal cost no restraint, which is what「it says WHICH, never WHETHER」was written to buy. ⚠ And the gate could not have failed from this change: both briefs are byte-identical when nobody tapped anything(asserted in the smoketest)and no gate scenario sends a tap, so what it proves is that the threading did not break something else
2026-07-29THE PRE-SHIP RUN--full --n 3 both paths, then --quick at N=8210 rooms · $0.576 · 85.0 min · 0 harness errors, then 40 runs · $0.103 · 17.2 min · 0 leaks. The ship configuration is at its best measured state: 33/35 at floor under the split(was 32/35)and 100/105 clean runs(was 97), controls bare 9/9, gate 5/5 at floor. Un-split unchanged at 22/35(82/105 clean against 83)with 15 cells shuffling either side of their floor — N=3 variance, and the aggregate does not move. Priced: a split turn is 5.53s / $0.000754 against 5.09s / $0.000497, and the latency is nearly free wherever the floor producer is on(+0.01s; the act call hides behind f on 107 of 112 turns). ⚠ Session 3's ship blocker does not reproduces20's no_leak is 0 leaks over 8 un-split runs — but the same shape fired once in three SPLIT runs, so it ships as a known criterion-8 red. the verdict
2026-07-29criterion 11 — s33 joins the setThe address-across-languages scenario, first cut, N=4 both paths: 4/4 split · 2/4 un-split, 0 leaks, 0 errors, $0.04. Floors set at 0.25 from this run(it rides TWO acts where s21 rides one). The gate after the change: --quick at its N=8 default. ⚠ It is a --full scenario, not a gate one — the surface it protects is the translator, which does not run on the exam's turn path at all
what the exam does not doBoth sides are still model-driven. This measures mechanism and tool discipline — not whether a real player enjoys the room. s01, s07, s11 and s13 still want the owner's hands. And the exam cannot see a manual getting slightly worse (the floor note in §2); that stays a worktree A/B.
The exam · built 2026-07-29 as DoD sequence step 5 · exam/run.py · exam/scenarios.py · exam/score.py · exam/leakscan.py, with the scanner's self-tests gated by lib/smoketest.py. Serves criteria 6 · 9 · 12. Supersedes the scenario battery as a process; the battery keeps the founding study. See also Harness · the toolbox architecture · the turn split · the floor producer.