Dialogue · The toolbox · The game device
← The sim loop — the evidence this design answers

The game device — the flow the server runs, the voice the persona keeps

D1 + D2 LIVE · 2026-08-02. The owner's frame, arrived at together after two sim cycles: the GM holds a「谁是卧底」app on a handheld device and hosts THROUGH it — like every real-world party app in the genre. The device deals, tracks the living, runs the ballot, buzzes the end; the human reads its screen aloud and keeps the table alive. Nobody calls that host incompetent for not counting votes in their head.

1 · The lesson this answers

Two sim cycles (20Q closed; 卧底 at 16 sweeps) taught one asymmetry, measured over and over:

where code executes and the mind narrateswhere the mind performs the process live
the living default · close_sec · the replace law · the masks · auto-load · the draw pools — zero flaps, ever, by constructionread the tally(5f8f: 4-0 announced as「3-1」)· check the END(189c: cards at three living)· wait for the result(ad8c: a result invented BEFORE the ballot closed)· reveal at the end(c356: read「ALL IDENTICAL」and asserted the opposite)

Every prompt-side lever was tried in escalation — the check moved to the front of the settle block, then carried the dealer's map inline, then stated the string-equality itself — and each step lowered the flap rate without ever reaching zero. A game has 5–10 critical moments; even 95% per moment compounds into a broken game every few runs. A stochastic sampler cannot be prompted into an invariant — the prop-master study said it first;「the dependent variable is not an invariant」.

The PUBG asymmetry. The same model family builds whole games as a coding agent — because that loop has compilers, tests, private retries and one-job-per-call decomposition. The hosting GM gets six jobs in one live forward pass with zero retries. The answer is not a stronger GM; it is giving the GM the same deterministic scaffolding the coding agent already enjoys. Don't pay a stochastic sampler to do deterministic bookkeeping.

2 · The division of labor

THE DEVICE(world-run flow) THE GM(persona moments) deal(draw=pair · visibility=own) board + counters pinned await: every living player spoke completeness tracked, never guessed ballot(who=THE LIVING · close 90s) settles all-in or on the clock eliminate top → END check faces-identical · two-left · else loop reveal ALL · winner computed the pile publishes, always next round narrate the deal · set the mood rules speech, table talk call on people · judge descriptions 自爆 · too-specific · banter sell the vote moment read the tally OFF THE SCREEN the counts arrive as facts to voice perform the reveal · explain the why invite the next game the device prompts each moment with its facts · the persona's speech colors the game and never steers the flow
the lawProcess is never sampled. The device advances on world events(completeness, settles, timers)— every step carries its own dead-man timer, so a silent persona can slow a game's color but can never hang its process. The persona's speech is the game's voice; the firewall already guarantees it arms nothing.

3 · The kit becomes a cartridge

One file, three layers. The prose brief stays(the persona's understanding — tone, judgment rules, the spirit of the game). A fenced flow block joins it(the device's program — validated against a closed schema whose only verbs are the eight instruments and four control forms). The dials stay declarable.

== FLOW ==                                  # the device runs this; the persona never reads it
lobby:                                      # OWNER 2026-08-02: every cartridge gets this free
  join:   {ask: 这局谁玩?, min: 3, max: 9, close: 30s}
  #       roster ≤4 → OPT-OUT(all pre-joined, tap to sit out)· bigger rooms → opt-in taps
  #       under the floor → say so and fold back to chat; never deal a broken game
setup:
  deal:   {draw: pair, who: JOINERS, per: 1, visibility: own, dealer_sees: true, label: 谁是卧底}
  board:  {title: 谁是卧底, columns: 玩家|状态, counters: 轮次=1}
  moment: opening                           # persona: rules speech, in its own voice

round:
  await:  spoken_by_living                  # order-free; completeness is counted, not judged
  moment: recap                             # persona voices; the device supplies the verbatim list
  ballot: {who: living, options: living+弃权, close: 90s, blocking: host}
  on_tie: next_round                        # DIAL — declared, honored mechanically
  eliminate: top
  board:  update 状态                        # the row is the device's, not the persona's memory
  moment: result                            # facts handed over: the counts, the fallen
  end?:
    faces_identical → end(civilians)
    living <= 2     → end(spy)
    else            → round

end:
  reveal: all                               # the pile publishes — always, by the device
  moment: verdict                           # persona: who won and why, the goodbye, 再来一局?

abort:                                      # OWNER 2026-08-02: reachable from EVERY phase
  by:     player→table-vote(收/继续, 30s) | founder outright | idle 10m(the device folds itself)
  then:   reveal all → board wraps 中止 → back to chat
  #       the audit law holds even here: cards were dealt, so cards are shown; winner = none.
  #       the door is a UI TAP on the game's card — speech never steers, the persona RELAYS

dials:                                      # OWNER 2026-08-02: user flexibility, validated
  spies:            {by-players: 4-7→1 · 8-9→2}        # NOT dialable — rule integrity
  tie_rule:         {enum: no-elimination|revote, default: no-elimination}
  reveal_on_death:  {enum: never|role-only|full-card, default: never}   # the players' amendment
  #  set through TWO doors: ① chat —「这局死了要亮牌」— the PERSONA parses(a real use of
  #  the mind)and the setup moment returns dials as schema-forced fields; the device
  #  validates, out-of-range gets the default said aloud. ② UI — the lobby card shows
  #  declared dials as tappable settings. Undeclared = FIXED. Where nobody asks, the
  #  persona picks in character(the liveliness law). A variant no cartridge declares →
  #  v1 says so honestly; D5 lets a user FORK the cartridge(edit → revalidate → their
  #  own shelf copy — the persona-clone pattern). 20Q's sibling dial: questions 5..30.

The judgment moments carry the facts pre-chewed(the counts, the faces, the verbatim descriptions)— the persona reads its handheld's screen, exactly the settle-cue pattern that already works, minus every chance to act on the process.

The three moment kinds(owner, 2026-08-02 — improvised content is the persona's)

kindthe persona providesthe device doesexample
colorfree speechnothing — hands over facts, never waits beyond the step timerthe recap · the reveal speech · banter
rulinga forced choice + a free-text quip, one callwrites the row / ticks the score from the choice half20Q's 是/不是/说不清/不适用 · trivia's 对/错/算对
composeauthored content — structured fields in its own voice and domainroutes each field where the flow declares(seal · board · public)and enforces the ORDERtrivia:「{question → public, answer → SEAL}」— the answer seals BEFORE the question posts, so a host can never retrofit the answer to the funniest submission(the seal_traced law, applied at authoring)

Trivia is the proof case: the device ships NO question bank — Hadid's quiz asks about cantilevers, MrBeast's about view counts, and the same cartridge runs both. Content is the persona's craft; commitments are the device's honesty. Where a kit's content is the HOUSE's instead(卧底's word pairs — entropy the persona must not know how to leak), the flow says draw: pair and the device draws; the two sources are declared per slot, never mixed by accident.

# trivia(问答之夜)— the improvised-content shape
round:
  moment: compose {question → public, answer → seal}   # sealed first, posted second
  collect: {answers: all-players, close: 60s}           # the seal-collect the toolbox has
  moment: ruling per player {对/错/算对 + quip}          # judgment stays a mind's
  score:  board ++ from the ruling half
  end?:   rounds == N | score >= target → end

4 · The runner

5 · The liveliness law — MrBeast's game must not read like Hadid's

The owner's requirement, 2026-08-02: the flow is shared; the rhetoric must not be. The device's answer — it removes the parts where every host already sounded the same(the bookkeeping recitals, identical and error-prone)and returns the freed attention to the parts where they differ.

6 · What retires, what stays

retires on device-run gamesstays everywhere
the prop master on process turns · the promise check · the standing cues(row-lag, stillness, zero, stalled-ballot, end-owed)· the settle-affordance blocks — the runner makes each of these true by constructionthe split firewall · the masks(belt over suspenders)· the collection laws · the renderable-table law · the whole classic path for kit-less rooms and free-form play — dual-mode: a kit WITHOUT a flow block runs exactly as today

The three tiers, top to bottom(owner-confirmed 2026-08-02): ① a cartridge game — the device runs process, moments carry voice. ② a kit without a flow — today's classic path whole(prop → act ∥ speech, FP, wake, every cue and mask). ③ no kit at all, or a game the shelf never heard of —「我们玩狼人杀」matches nothing, nothing auto-loads, and the persona hosts from its own memory, assembling raw instruments through the classic loop, every guardrail underneath. Improvisation is the fallback, never the ceiling: D5's compiler is the long-term door for unlisted games —「tell me your rules」→ a drafted cartridge → validated → played.

Cost: a settle moment today = prop + act + FP + cue machinery(~4 calls); on the device it is one moment call — and most turns need none. The act-call cache lever precedent says measure it, not assume it.

7 · Authoring — where the stochastic step belongs

A user writes a rulebook in prose. A one-shot LLM call compiles it to the flow schema. The schema validator rejects anything outside the closed vocabulary; the sim harness dry-runs the cartridge; the auditor gates it. The sampling happens once, offline, where a human can review it — never on turn 47 of a live game. This is the user-generated-kits path the owner already named:「a kit is like pseudocode」— taken literally, compiled, not recited.

8 · Acceptance

9 · The build plan

#phasecontentstatus
D1the schema + the runner corelib/gameflow.py(nine verbs · six predicates · a fixed fact list · three lints with teeth)+ the runner in run_room.py: self.game IS the machine, plain JSON so a restart resumes mid-game · direct arming through the existing appliers · moments via the wake door · a dead man on every wait · one publish path for all five entry pointsSHIPPED 2026-08-02
D2the 卧底 cartridgethe flow block in who-is-spy.md(13 steps)· exam/device_dryrun.py 75 checks green · 8 live games at N=3/4, both END doors, and a two-game rematch · spy_audit.py clean on every post-fix room · the distinctness judge tells MrBeast from Hadid on the same cartridgeSHIPPED 2026-08-02
D3the 20Q cartridgea trivial flow(seal · Q&A rows · the two endgame doors)— proves the schema generalizes beyond ballotsqueued
D4the rest of the shelf + the retirement骰子 · quiz · 2T1F · 真心话 cartridges · retire the process cues on device rooms · the cost measurementqueued
D5the compilerprose rulebook → flow, one-shot, validated, dry-run — the Studio's user-kit doorqueued

10 · Ruled by the owner(2026-08-02)

11 · Ruled by the owner, round two(2026-08-02)

12 · The call economy — who arms, and what it costs

The code arms everything in the flow. The runner drives the same appliers the act call uses today — same events, same cards, the GM's name on each — and the per-game LLM bill collapses to voice alone:

per 卧底 gametoday(classic path)on the device
prop calls~12 — every turn pays the gatekeeper~0 — process needs no gate; off-flow requests fall through to the classic path
act calls~6–80 — the structured half of a ruling/compose moment rides the speech call itself, schema-forced
speech / moment calls~12~6–8 moments, all voice
cues · promise checks · verifyconstant machineryretired — true by construction

The pipeline, piece by piece: wake stays and is promoted — moments ARE wake turns with a directive and facts. prop effectively retires in device rooms. fp stays for staging(verdict-void in force; a slimming candidate, by measurement). act is gone as a phase. speech becomes the moment call — the turn split collapses back to ONE call on device rooms: the split existed because one pass could not be a form-filler and a conversationalist at once, and with process in code the only form left is a four-token choice riding along. The classic path stays whole for kit-less rooms — dual-mode, unchanged.

13 · What the build taught(2026-08-02, D1 + D2)

The design survived contact. Everything §2–§6 claims — process in code, moments for voice, dual mode — went in as written, and the two defects that got through were both the same shape: a gate placed where the game runs instead of where the cartridge sits.

found bythe defectthe fix, and why it is that one
the dry run
(no server, no API)
「all living faces identical」was read as「the civilians won」. At 8 seats with two minority cards the survivors CAN be the spies — the rule named the wrong winner at a whole class of table.the winner is read off the surviving FACE, mapped through the cartridge's sides. The predicate says when the game ends; the deal says who won. Two facts, never conflated.
the first live game
(console stream)
The persona's deal swept the device's off the table and dealt a different pair mid-game. The split's own act call was gated — and the turn armed anyway, through the DELIBERATE second phase, whose flag was computed one breath before the cartridge booted mid-turn.the door moved onto _act_call itself. A gate per caller is a gate you are one race away from; the one place an act is committed is where it belongs.
the same gameThe game ended, _flow_active went False, the manual came back — and the host cheerfully hosted a SECOND 卧底 from prose: dealing over the published pile, calling a dead player alive, tripping the standing end-owed cue on furniture it had invented._flow_kit() beside _flow_active(). The device does not hand the room back to improvisation because a game finished. While the cartridge is on the table, this game is the device's — and the REMATCH DOOR restarts it through the same prop-SETUP verdict that started it.
the same gameTwo rules speeches in a row — the auto-load turn's own, then the OPENING moment's.the boot happens BEFORE the prompt is assembled, so its moment belongs to that turn. The cue is taken off the queue and folded into the turn already running.
the harness dial
(MAD_GAME_TIME_SCALE)
TWO DEAD MEN RACING. Scaled to seconds, the RUNNER's wait for a vote result beat the BALLOT's own 90s close — so the program stepped over a live ballot carrying the previous round's tally: the round advanced, the pile published while the vote was still collecting(law C), and the ballot settled empty two minutes later into nothing. Latent at real time(90 < 420 always), and latent is what bites on turn 47.three layers, because it bit twice. The schema lints the ordering where the author writes the number; the arm clamps it at runtime, AFTER any scaling(the first clamp sat before the scale, so the dial broke the very invariant it was written to protect); and if it fires anyway it CLOSES the ballot instead of stepping over it — the settle then advances the program the ordinary way, with a real tally.
the bench
(that same fix)
The close-the-ballot fix deadlocked on its first run: it called gate_detach, the public door, from inside a locked block — and the room lock is a plain Lock.detached inline. Worth recording not for the fix but for where it was caught: a second on the bench, with no room, no persona and no bill.
the rematch sim
(the UX judge)
A host opened a free turn with「四个人都说完了」when three had spoken, and caught itself mid-sentence. The moments were right; the turns BETWEEN moments were blind.THE DEVICE'S SCREEN on every turn, not only on moments — and the owed list LEADS it. Position is the dose: with「still owed: Owen」at the tail of the clause the host read past it; at the front, the slip stopped.

The screen is the piece the design did not name. §2 gave the persona facts at each moment and left the rest to voice — but a host also takes ordinary turns, and on those it knew nothing. A real host holding a device never has that problem: the screen is always there. One block, facts only, above everything: what round, who is in, who still owes a line, what the device is waiting for.

The instruments this phase added

Acceptance, as measured

gateresult
the dry run(75 checks, every scenario)green, and repeatably — the deal is random, the checks are not
live games(N=3 · N=4 · N=8, two spies, nine options · door A · door B · a two-game rematch · an adversarial table · a silent player)13 games, every one reaching its own END door unaided
spy_audit.py — laws A–E over the whole ledgerclean on every post-fix room(13 rooms)
the adversarial table(spyadv)— open the cards early · skip the descriptions · re-deal over a live deal · a 2–2 tie · a voted-out player who plays on · the kit pulled off mid-gameall six held. The bar is not「the host says no」— it is that the WORLD does not move; and after three refusals the round still reached its own ballot
the dead man, live(spysilent)— one player never speaks176s of silence, then the ballot opened with NO request in flight; the silent player stayed ON it, and the recap named them
the UX judge(confusion candidates)「无」on every post-fix run
the distinctness judge(§5's FAIL condition)「不同的人」— MrBeast is punchy and totalising, Hadid is measured and spatial, on one flow
persona arms during a device gamezero — not walled attempts, zero attempts: with the manual off its prompt the host never reached for the pen

Open, and honest about it

Dialogue · the game device · drafted 2026-08-02 from the two sim cycles' evidence(the loop · ledger rows 41–50)· the constitution extended:「code=world」now includes the game's skeleton(world-events)· status: D1 + D2 SHIPPED 2026-08-02 · D3–D5 queued