← Host moves — the study

The orthogonal toolbox

The re-architecture ruling of 2026-07-21, reached after a week of live play (steps 1–7 built and tested) put stress on the six-move basis — and after the werewolf trace (§5) broke it in an honest place. The six moves remain the product's face; underneath them sits a smaller orthogonal engine. Owner-designed; this page is the record.

The whole page in one line: six moves were the product's face — underneath: six mechanisms, one structural scope (the room), and one law: the mechanism states facts; the room's contract owns meaning.

1 · The basis — mechanism vs. contract

Every tool splits into a mechanism (what the server guarantees, identically in every game forever) and a policy (what the room's agreed contract decides). A week of live failures traced to exactly this line being blurred — see §3.

toolthe mechanism — what the server guaranteesthe contract decides
🎲 The randomizera fair draw from a distribution — dice2d6, 5d7)· pick(with replacement — the spinner)· deck(without replacement — the deal, ruling ⑦)— witnessed, timestamped, on the record; delivery: onto the table(public)or into the safe(face-down, §5b)who may draw, when, and how many times (default = 1); where the result lands; what it means
📋 The state recorderone shared, persistent, always-visible state strip; consistent structure: Currently(比分、回合)+ Next step(该干什么) — the game's program counterthe schema; what advances the counter
✉ The safeanyone — persona or human — deposits sealed content; the deposit is visible, the content is server-held; opens at the agreed moment, timestamp-proven unchangedwho deposits; when it opens (a manual reveal, a checklist firing, the clock)
☑ The checklista condition over room events that triggers the next step when satisfied: all committed a secret · all drew · all spoke · at least N spoke("spoke" = any user message — ruling ②); any member can release a stuck onewhich condition; who counts; what firing does (wake the host, open the safe, post the facts)
🕐 The clockstandalone furniture — the meeting room's wall clock: set it, everyone watches it count, it rings on the record. Never folded into the checklist(ruling ④: facilitators don't record time on the flipboard)what the ring means; who acts on it (usually: the ring cues the host)
🎙 The floornew — found by the werewolf trace. Server-enforced speech permission: mute / unmute, visible and attributable(「你已出局 · 旁观中」). Session-scoped ONLY — muting exists solely inside a consented game contractwho holds the floor, when; what restores it

And one structural scope, not furniture: the room itself. The werewolf den is not a whisper channel — it is a temp room whose members are the wolves. Visibility by membership, on machinery that already exists and is battle-tested (rooms, DMs, history floors), replaces visibility by message-routing. The study's aside (step 10) is superseded: a whisper is a game-scoped DM — the same sub-room mechanism, pair-sized.

2 · The rulings

ruling ①User-initiated randomizer: contract-gated, budget default 1. A player (persona or human) may draw when the contract allows, as many times as it grants — default one. In the owner's words: otherwise it's not a randomizer, it's a cast-until-satisfied. This re-derives the v543 armed-single-cast from first principles: arming is the contract grant.
ruling ②"Spoke" = any user message. The checklist's speech conditions(all spoke · N spoke)count any message from a counted member; persona speech counts via the panel turn.
ruling ③The checklist is visual, beside the whiteboard. The dock is the room's live-state zone: the board keeps one consistent structure(Currently + Next step); the checklist changes shape per scenario step — this round「waiting for secret votes · 2/3」, next round「waiting for everyone to roll」. Where the game is, and what it waits on, side by side.
ruling ④The clock is standalone. A wall clock, not a checklist entry. Its ring is an event the host acts on.
ruling ⑤Persona as GM first; persona as player later. The one-brain limit means persona players in a hidden-info game are not blind to the GM (or each other) while one model drives all seats. Design order: the persona hosts — humans play. Persona players arrive with the future per-persona-LLM architecture.
ruling ⑥DeepSeek non-reasoning is the model. Cost ruling. All discipline must come from structure (this toolbox + cards), not model tier.
ruling ⑦The deck is a randomizer mode. Deal-without-replacement is too common to compose by hand — and simulating it with rolls leaks re-roll ceremony into the players' hands. The randomizer's distributions are a closed set of three: dice · pick · deck, matched to the physical objects on real game tables. Where the mode/composition line sits: §6.
ruling ⑧The tools are the room's, not the persona's. Mechanisms never cared who invokes them — trust never depended on the invoker. Access is governed by the contract(a session's grants; a free room defaults open); the interface differs by species — hosts operate by tag grammar, humans by touch(the zero-syntax law constrains interfaces, not access); every use is attributed on the record. Human-only rooms get the toolbox too: witnessed coin flips, votes, sealed predictions(「我早说了——上周封存的」with a server timestamp)— the proven bar holds(WhatsApp/Telegram ship polls; the timestamp-proven reveal is the differentiator). One carve-out: the floor stays session-only for everyone — mute is never a group-chat feature.
ruling ⑨Human-first completeness — the form is the tool's true spec. Build the whole dial surface for HUMANS first, then teach personas onto it. A form cannot be vague: it forces every parameter enumerated, typed, defaulted — whereas teaching a persona first lets parameters hide in prose(exactly how the poll's edges stayed fuzzy through T2). It also makes the mechanism deterministically testable before the stochastic model layer(the FP-probe madness was testing logic through a random gate). So: complete the human tool, then the persona grammar is a thin translator onto a proven surface. The symmetry ruling ⑧ demands is of scope and permission, not interface; permissions stay role-gated, never species-gated(a card may say「only the GM closes the vote」, never「only personas may」).
ruling ⑩Three tiers of configuration — natural language compiles INTO the form. Too many dials breeds fear of the tool. One surface, three depths: defaults(one tap — question + options, nothing else showing)→ the full form(behind an "advanced" fold)→ NL via @tool(「帮我开个匿名投票,5分钟后自动截止」). The law that makes tier 3 trustworthy: NL fills the SAME form a human would see and shows it as a one-tap-confirm preview — it compiles into the form, never past it. This keeps the two-layer law(the model translates, never constructs), hands the human a receipt of what their words became, and quietly teaches the form over time. @Assistant dispatch is the precedent; @tool sits beside it.
ruling ⑪Every tool has three presence properties; WhatsApp is the default. Blocking · sticky · unique — and the default for all three is the relaxed value: non-blocking, non-sticky, non-unique. A tool bubble is then just a message you may answer or ignore(the WhatsApp poll). Cards flip the dials only where a scenario earns strictness(a turn-based game). The tools were born from games and defaulted to sticky+unique; the product's daily life is chat, so they are re-centred as chat citizens. Detailed with the value ladders and mockups in §9.
ruling ⑫A persona is a human at the tool surface. Where tools and history are concerned, a persona sees exactly what a human in that seat would see — no more, no less: the same defaults, the same dials, the same ignorance. This is the EXPOSURE half of ruling ⑧(which settled ACCESS), and it is what makes the persona–human experience realistic rather than staged. The corollary that matters in practice: when a persona fails to operate a tool correctly(forgets a dial, denies the prop exists, mimes the furniture)that is a tool-call and harnessing problem — never a reason to bend the tool’s design. Fix it where it lives: the SP’s worked example(in-context shape moves compliance—v553), the card’s config(T5 — a scenario states what it needs so the model needs no memory), the floor producer’s brief(v560). Giving a persona a privileged default to compensate for unreliability buys a little reliability and spends the realism the whole product is built on.

3 · The boundary law — and the week it was learned

The mechanism states facts; the contract owns meaning. Every violation of this line produced a live bug within days:

4 · Composition proofs — the built tools re-derived

Evidence the basis is right: everything built in steps 3–7 is a composition of it — including two machines that were built separately and turn out to be the same shape with a different payload.

what we built / deferredits decomposition
the circle(sealed collect, 7a/7c)safe × checklist(all-committed)— deposits visible as sealed bubbles, firing opens the safe + cues the host once
the collect-roll(7b)randomizer × checklist(all-drew)— same composition, different payload
a votesafe × checklist — everyone puts a name in; reveal together(already works; never needed naming)
the open go-around(deferred in 7a as "open collect")checklist alone(all-spoke)— nothing sealed, just the barrier
the wake(step 9)the clock — its ring is the host's cue; consent + rate caps unchanged
the aside / whisper(step 10)room scope — a game-scoped DM; the per-viewer message-routing design is superseded
a timed phase("5 minutes, then vote")clock → safe × checklist — checklists chain, each firing advances the board's Next step
the role deal(werewolf, face-down — §5b)randomizer × safe — a deck dealt into the safe: fair by shuffle-at-arm, private by delivery
a dot-vote / rating(the tally — §8 candidate)safe × server count — structured deposits; the COUNT posts as a fact, arithmetic leaves the model's hands

The chain is the session runtime. A card(step 8)is the program text · the board is the program counter · checklists are the barriers · the randomizer, safe, clock, and floor are the instructions. Step 8 doesn't need to invent a runtime — it composes this one. The owner's two game traces make the point visually — every round game is the same loop; only the payload changes:

EVERY ROUND GAME IS THE SAME LOOP — ONLY THE PAYLOAD CHANGES RPS plugs in ✉ THE SAFE human choices anchor → sealed until all in 比大小 plugs in 🎲 THE RANDOMIZER server facts don't anchor → public as they land 1 · GM arms the round the barrier + the payload 2 · players act each at their own moment 3 · ☑ fires one cue, all the facts 4 · the GM's ONE turn apply the contract · board · re-arm the next round the loop — until the board's finish line The board's Next step field(「第3轮 · 该掷骰」)is what keeps the model from losing the loop; the agreed finish line(先到3分)ends it — declare · ✉ stays shut · 🎲 away · 📋 away. Everything that failed in live play(Lee's mis-scores, the non-ending)lives in box 4 — the one contract step. That slot is the card's.
RPS never touches the randomizer; 比大小 never touches the safe. Same skeleton — the payload differs by one question: does showing it early change what people do?

5 · The werewolf trace — the probe that found the gaps

The test case(owner, 2026-07-21): the wolves' night discussion and kill vote, persona as GM. Decomposed:

VILLAGE room GM + everyone the door THE DEN · temp room members: wolves + GM 🕐 clock 5:00 · free discussion ring → vote: ✉ safe × ☑ all wolves discussion never leaves this room outcome bridge VILLAGE · the reveal GM announces the kill 🎙 floor mutes the room ☑ victim's last words → 🎙 mute EVERY PIECE, NAMED: the door(GM opens a scoped room + seats members)· the clock(timed phase)· the safe × checklist(the vote)· the outcome bridge(ONLY the checklist's result crosses back — the discussion is sealed by construction)· the floor(dead men tell no tales)· the board in both rooms(Currently: night 2 · Next: village debate) One-brain caveat: persona WOLVES in the den are not blind to the village GM while one model drives all seats — hence ruling ⑤: the persona hosts, humans play; persona players arrive with per-persona LLMs.
The night step, fully decomposed. Nothing here is a new kind of thing — every piece is a toolbox mechanism or the room scope; the only novel plumbing is the outcome bridge.

5b · The face-down deal — how roles are dealt

The game's opening move: each player learns only their own role, the GM knows all, the room knows nothing. Randomizer × safe — the deck dealt into the safe:

GM arms the deck 狼人×2 · 预言家×1 · 平民×3 server shuffles ONCE at arm time · timestamped GM's copy → his notes 🂠 in every hand the room sees only 「已看牌 · 3/6」 tap = the pickup flips for YOUR eyes only · you choose when ☑ fires at 6/6 night falls · the den opens death / game end → the card reveals FROM THE SAFE dealt before round one, unchanged — server-witnessed(「我一直是平民」becomes a fact) Why shuffle at ARM, not at tap: the complete assignment exists — timestamped — before anyone touches a card, so tap order is irrelevant BY CONSTRUCTION(the safe's commitment trick applied to chance). The tap is kept because choosing WHEN to peek is real privacy on a shared screen — the physical gesture of lifting your card's corner.
Net new machinery: the deck mode(ruling ⑦), the into-the-safe delivery, the private flip. All policy and plumbing on existing mechanisms — the basis held, and grew one knob.

6 · The line — when does a pattern become a mode?

The deck can be simulated by many rolls — so why mode it? Because reducibility can't be the criterion: everything reduces(a deck is many rolls, a pick is a labeled die, NdM is N×1dM), and by that logic the randomizer collapses to a coin. Three tests draw the real line, each from a principle already on this page:

The result is a randomizer whose whole surface is a cross product of short closed lists — never one feature per game:

axisvaluesclosed by
distributiondice(NdM)· pick(w/ replacement)· deck(w/o replacement)the physical objects on real tables(ruling ⑦)
budgetdefault 1 · or the contract's grantruling ①("otherwise it's a cast-until-satisfied")
deliverythe table(public)· the safe(face-down)§5b — does showing it early change what people do?
accessthe contract's grants(a card session)· default-open(a free room)ruling ⑧

7 · Two layers — precoded mechanisms, on-the-fly orchestration

Is delivery-to-safe something the LLM assembles at runtime? No — and that is a load-bearing choice. The one-brain law: a model-improvised delivery route cannot referee the model — if it「simulated」face-down by DMing roles in prose, it could misdeal, leak, or remember the deal differently in round five. The trust lives precisely in the fact that the model cannot touch the route.

ORCHESTRATION — the LLM, assembled on the fly, per game, per turn which tool when · the rules · what the numbers MEAN · the narration · the sequencing(= the card + the host's skill) the persona's door policy knobs on fixed tags the humans' door touch — tap · flip · vote · release INVOKE, NEVER CONSTRUCT MECHANISMS — precoded, server-guaranteed, identical in every game forever 🎲 randomizer · 📋 state recorder · ✉ safe · ☑ checklist · 🕐 clock · 🎙 floor + the ROOM as scope anything that carries a GUARANTEE — fairness · secrecy · counting · timing · permission — lives here, and only here The growth protocol: a game needs a missing knob → the model CANNOT fake it → it degrades visibly(the clunky fallback, or says so) → the bruise becomes a ruling → the knob ships. The toolbox grows the way furniture does — deliberately, after the room has bruised itself.
The boundary law in structural form: the model owns meaning, so meaning is assembled on the fly; the server owns facts, so fact-machinery is precoded. The LLM parameterizes; it never constructs.

8 · Is this all of it? — the completeness question

Are these all the essential tools for productive human interaction? For structure, nearly — with three named candidates; for content, that was never the toolbox's job. The test is the boundary law itself: a tool earns mechanism status only where conversation breaks without a server guarantee — chance, secrecy, simultaneity, arithmetic, time, permission, scope. Everything else productive humans do together(asking good questions, synthesizing, deciding)is orchestration. Walking the full range — interview, book club, dating, brainstorm, retro, negotiation, classroom, games — three compositions don't close cleanly:

candidatewhat breaks without itverdict
The tally — structured ballots(choose · distribute N dots · rate 1–5)with server-counted resultscounting is a FACT, and arithmetic is precisely where the model wobbles(Lee's meltdown was score arithmetic); dot-voting a brainstorm, ranking, any retrostrongest — cheap: the safe with structured deposits + aggregation at reveal; the count joins「who rolled what」as furniture-stated fact
Anonymous reveal — the safe opening content without authorspsychological safety(the study's social-safety leg): honest retro feedback, blind review, 匿名提问 — people won't deposit what will be attributedone policy knob: safe reveal ∈ {attributed · anonymous}. Completes a symmetry — the deal is author-visible-content-hidden; this is the inverse
The ledger — conserved tokens(chips · budgets · bids: can't spend what you don't hold)auctions, poker, budget exercises, staked negotiation — conservation is a guarantee the board can't give(board numbers are host-written arithmetic)parked — waits for the scenario that demands it
§8 answered, 2026-07-28A fourth thing was missing, and it was not on the list. The three candidates above are all about the ROOM. The pad(§13)is about one participant's own head — externalised memory that never becomes furniture — and it was invisible to this walk because every scenario was read for what the table needs. It shipped as the eighth tool(v636). The lesson for the next completeness pass: walk the scenarios once more asking what each PARTICIPANT needs to hold, not only what the table must guarantee. The tally and anonymous reveal both shipped too(T2 · the deposit's anon); the ledger is still parked.

Looks like a gap, isn't: the speaking queue(floor granted in sequence + the board's Next step)· breakout pairing(deck deal × room scope)· minutes and artifacts(the transcript is native memory; wildcard-pane artifacts exist)· cross-session continuity(the persistent-memory track, not table furniture)· documents-in(a chat-app capability, not toolbox).

And the deeper answer: completeness is not provable by enumeration, and doesn't need to be. Physical meeting rooms converged on roughly this same short list — whiteboard, flipchart + dots, timer, talking piece, dice, breakout rooms — over a century of nobody designing it. Completeness comes from convergent evolution, and the evolution mechanism is already running: every probe(RPS · 比大小 · the deal)either decomposed cleanly or surfaced exactly one honest knob, and the bruises get smaller and more peripheral each time. That is what a converging basis feels like. The library of games and scenarios is the measurement instrument; the basis is complete when scenarios stop bruising.

9 · The presence properties — how a tool behaves on screen

Shipped as the poll pilot(v577, owner combo pass v578) — the poll now carries all three dials with the WhatsApp defaults; the store became a LIST so polls coexist. ⚠ The owner's combo review renamed the middle axis: for the poll it is place ∈ {inline, pinned}, not sticky {none·follow·pin}follow confused users and pin covers its use, so it survives only as the text circle's legacy value. And blocking=all(the composer lock)is now in scope for the poll. The combo law that fell out: placement must match blocking(host⟹pinned, all⟹unique). The pattern is left reusable for a per-tool rollout on owner approval. Build notes: T8 in the build log.

Rulings ⑨–⑪ came out of the owner perfecting the poll. The load-bearing one is ⑪: the tools were born from games and quietly defaulted to sticky and unique(a fixed dock strip, one at a time)— but the product's daily life is chat, so the right default is the WhatsApp poll: a message you may answer or ignore. Three dials capture the whole space, and the default of each is the relaxed value.

axisvalues(default first)what it controls
blockingnone · host · allwhose actions wait for the tool to finish before they are unlocked
stickynone · follow · pinwhere the tool bubble lives — and whether other bubbles push it away
uniqueno · yeswhether a second same-tool can open before the first is closed

Each axis is a small ladder, not a switch — and the middle rungs are what our games actually use.

Blocking — say whom

valuehumans may chat?the panel(the AI)speaks?where it fits
noneyesyes — may even comment mid-votea casual poll, a cast die
hostyesno — the AI waits, then answers ONCE reading the whole roundthe sealed round · the collect-roll(the one-turn law)
allno — composer locked, with a visible reasonnoa werewolf final vote · the deal's pickup — the Among Us meeting; the floor(T6)applied room-wide; cards only

The circle today is host-blocking, not all — people were never silenced; the AI was. That distinction was implicit until now; a card will want to choose it deliberately.

Sticky — three values, not two

valuebehaviournatural home
nonescrolls away like any message; you answer it or you don'tthe poll's default · a cast die
followre-floats to the stream's bottom as new messages land — never lost, still in-stream(the DiscordDiceBot trick; the liveTool host, already builtthe active instrument of a turn-based game
pina status chip in the strip — you pin the number, not the card; tap the chip to expand or jump to it(WhatsApp's pinned-message banner)the board · the clock — whose essence already is a one-line number

This is why the field study's dock verdict was about defaults, not mechanism: a poll pinned as a HUD strip was a none-sticky tool forced to pin. The strip holds numbers(board, clock); furniture with buttons(a poll)belongs in the stream.

Unique — one cost, one prize

The cost: the server holds ONE gate slot today, so unique=no(plural polls)means instruments become a list with instance ids, and chips/cards render per instance — honest but bounded work. The prize: under non-blocking, non-unique defaults, a sealed round can no longer capture「your next message」(chat keeps flowing)— which forces the sealed answer to become an input on the card itself. That is strictly better than what we shipped: the gate-mode strip, the message-capture surprise, and the「why did my message disappear」confusion all evaporate. The properties framework didn't just classify the tools — it found the circle's UX bug.

DEFAULT · the chat citizen none · none · no room · 3 people let's decide dinner Tess · 茶还是咖啡 OPEN 咖啡 tap to vote · counts hidden until close waiting on 2 of 3 i'm easy either way Message… TURN-BASED · the instrument host · follow · unique 比大小 · round 3 my turn — here goes good luck! ⏳ the panel waits — one reply when all are in Tess · 谁先手 OPEN 🎲 cast your die 1 of 2 rolled · re-floats above the chat ↑ always just above the composer Message…(still free) TAKEOVER · the meeting all · pin · unique 狼人杀 · 投票 📊 2/5 GM · 投谁出局 OPEN 3号 5号 弃票 3 of 5 have voted · everyone must progress mirrored into the chat 🔒 投票中 · 完成后解锁
The same poll under the three presence settings. Default(left): a bubble in the stream — messages land above and below it, you answer or ignore. Turn-based(middle): the card re-floats above the composer(follow)while humans keep chatting and the panel stays silent(host-blocking). Takeover(right): a status chip pins the count, the card fills the screen, and the composer locks for everyone(all-blocking · card sessions only).
THE BID BOX — a sealed answer is an input ON THE CARD(unique=no · chat keeps flowing) 1 · the card in the stream Tess · 一个词形容“家” OPEN ✍️ 密封作答 who's in · 1 / 3 the composer stays pure chat 2 · tap → a sheet rises 你的密封答案 港湾▏ 密封提交 …only you see this field… 3 · sealed · yours to change Tess · 一个词形容“家” OPEN 🔒 你的密封答案:港湾 点击可修改 · 全员交齐后一起公布 who's in · 1 / 3 others see only the tick — never 港湾
The bid box, in the poll's own design language(opener face · OPEN pill · who's-in chips). A sealed answer is a slip into the box, not a captured message: tap 密封作答 → a sheet with one field → submit. Your card then shows your answer privately; everyone else sees only your chip tick. Button-→-sheet, not typing inside the bubble — the virtual-keyboard scars say never put a caret in the middle of a scrolling stream. ⚠ SHIPPED v590 with three owner amendments to this sketch: no revise(an answer is FINAL on submit — the poll's own v571 ruling)· no proof line(the band's 🔒 carries the sealed story)· + a CHOICE mode<gate options="石头, 剪刀, 布"> makes RPS one tap, revealed by person at close).
shipped · T10(v590)The bid box is live — the sealed collect remade as the poll/roll's sibling(kind="seal"). An answer is an input ON the card(a free-text sheet or a tapped option), never a captured message: the message-capturing circle — the gate-mode strip, held bubbles, sealed placeholders — is RETIRED(a pre-T10 open circle releases-with-what's-in on load). It withholds content from EVERYONE until close(no reveal-on-answer — there is no tally to anchor, only your own answer shown to you), reveals BY PERSON not by option, and keeps the 🔒(v585 in reverse — the most sealed tool in the room). Two doors(the drawer's「Sealed collect」dialog + the persona's <gate> + <seal>); FINAL on submit; the cue always on a close that mattered. Build notes: T10 in the build log.
survives the WhatsApp-ificationAnti-anchoring is orthogonal to all three properties(owner-confirmed). No live counts until close — the reveal gate that sends standings to nobody who has not voted — is a fairness guarantee and our differentiator, not a strictness setting. A poll can be fully casual(none · none · no)and still hide its running tally.
extended 2026-07-25The three presence properties are now six axes — the owner's state × trigger matrix found that every instrument has up to THREE phases(collecting → closed·sealed → revealed), so visibility · close trigger · reveal trigger join blocking · place · unique. The design record, the twelve rulings that came out of it, and the five-task work breakdown live on tool-lifecycle.html.
amended · the T8 combo pass(v578)The owner drew the allowed-combo matrix on the live pilot, and it re-shaped the dials.sticky is renamed place ∈ {inline, pinned} —「follow confuses; pin covers its use」; follow survives only as the text circle's legacy value. ② blocking=all is built, not cards-only: the composer locks for everyone until close(voting stays reachable — it is on the card), server-refused too. ③ Two coercions, enforced in _clean_props and mirrored as locked buttons in the form: blocking=host ⟹ place=pinned(an inline card is lost the moment chat keeps flowing past a silent AI)· blocking=all ⟹ unique=yes(a locked composer cannot open a second one). The load-bearing insight: a tool's placement must match its blocking. This is the as-shipped ruleset every tool in the rollout copies.
amended 2026-07-24That insight holds for host and not for all. Pinning exists because an inline card is lost when chat keeps flowing — and under all nothing flows, so an inline card holds the tail by construction. The poll's form had been forcing pinned for both(never the server's law: _clean_props only ever did host⟹pinned); inline + all is now open to people, and for a run of polls it reads better than a sheet floating over the closed ones. ⚠ The same host||all ⟹ pinned line still sits in the roll(T9) and sealed-collect(T10) dialogs — left untouched pending the owner's call on whether the same reasoning applies there.

10 · What's missing — the capability roadmap

plan lockedThe execution plan is written: toolbox-build.html — seven step contracts(T1 clock · T2 tally · T3 deal · T4 touch drawer · T5 cards · T6 floor · T7 outcome bridge + the werewolf finale)for fresh Opus 4.8 sessions, one per step, owner-triggered. The table below remains the capability view; the build page is the tracker.
capabilitystatus / where it lands
persona creates a room + seats people(the den; the game-scoped DM)the door(step 11)widened: sub-rooms born from a parent, humans seatable — behind the §7 consent design
the outcome bridge(a sub-room's checklist result posts to its parent)new, small — the same by-construction leak control as the gate's held answers: only the firing's outcome crosses
the floor(mute / unmute)new, small — a policy on the say route + a visible composer state; session-scoped only
the clocknew furniture(standalone — ruling ④); its ring absorbs step 9's timing; consent + rate caps stay
the checklist as a first-class visualgeneralize the 7a gate card: one dock card rendering any condition(votes · rolls · spoke · N-of-M)
persona persistent memoryits own major track — needed for relationship continuity across unrelated chats; not a blocker for the den or the game-scoped whisper (the sub-room's brief carries the game context)
the deck mode + into-the-safe delivery + the private flip(§5b)new randomizer knobs(ruling ⑦ + the delivery axis)— unlocks the face-down deal, secret pairings, hidden prompts
the humans' touch drawer(ruling ⑧)the composer's second door: every mechanism the panel can arm — die · wheel · deck · sealed round · vote · note · board · clock, and the away that takes each down. Same mechanisms, same events, same capsules, attributed to a person. Owner ruling v565 — the parity law: whatever a persona can do, a human can do, and its acceptance is an ALL-HUMAN room running a whole game with no persona seated. Free rooms default-open; sessions defer to the card's grants(room_tool_access()
the tally · anonymous reveal(§8)ruling material — the strongest candidates; the ledger stays parked

Persona-initiated rooms and seat-dragging are the first tools whose misuse reaches outside a room(notification spam, unwanted inclusion). Principles, to be designed before the door ships:

12 · Migration — mostly a renaming, not a rebuild

The internals are already close: the gate object is a checklist instance(a need-list, a have-set, a trigger); its subs are safe deposits; the collect-roll is the same barrier over draws. The re-architecture extracts the checklist's condition types, unifies the safe under one store, and adds the three small mechanisms(clock · floor · bridge)— while the user-facing faces do not change: people play with 骰子, 白板, 信封, and「waiting on Dan」, never with a "condition-trigger primitive." The furniture principle survives by keeping familiar faces on an orthogonal engine. Cards(step 8)compose against the engine in plain language: a state schema, a safe policy, checklist conditions, randomizer grants, clock settings, floor rules.

13 · The pad — the private axis the basis was missing

Shipped v636 as the eighth tool. It is the only instrument that puts nothing in front of the room.

The test that separates a pad from a board with a visibility dial. Ask: does the audience change what the object IS, or only who can see it? A private board does not stop being seen — it stops being posted. It goes from furniture the room reads to memory the owner keeps. Different act, different tool. Contrast <note>, which was correctly merged INTO the deposit: who answers never changed what a deposit was.
boardpad
audiencethe roomyou alone
lifecycle · 参与者 · 可见性none · none · publicnone · none · private by definition
length rulescreen budget — glanceableneed budget — prune what stopped mattering(capped at 2 000 chars)
sheettitle · content · 谁能改 · 传笔(v642)content. That is the whole sheet.
the fieldplain textarea, markdown — rendered for readersplain textarea, plain text — there are no readers
result bubbleyesnone, ever
v641 · the sheet caught up with the table「content. That is the whole sheet」was the design from the start; until v641 the build still drew a 标题 above it. It is gone, and the argument is the audience argument said one step further: a label exists so that somebody looking for the thing can find it, and nobody else will ever look for this. The same sentence kills formatting — bold, lists and a table are things you do for readers, and this page has one reader who was there when it was written — so the field is plain text, no toolbar, where the board's is rich. ⚠ The persona grammar keeps <pad title="…">, and that is not an inconsistency: several seats' pads ride ONE panel prompt, so each has to say whose it is. Different problem, different answer. Titles a person had already stored are folded into the first line of their text at load rather than orphaned.
the consequenceThe board therefore has no visibility dial — and never had one. With the private case extracted there is no such thing as a private board. This is enforced rather than merely intended: the form↔grammar lint compiles a form that sets visibility, who, place, blocking, reveal and close on a board and on a pad, and fails unless both compile to a bare body tag. ⚠ v642 amends the second half of that sentence, not the first. The board's sheet is no longer two fields — it grew 谁能改 and 传笔§14)— and the guard was re-cut, not deleted: it now probes the parser against a DECLARED attribute set(board = title · edit · handover, pad = title)and still fails on any word nobody listed. The visibility half is untouched and load-bearing: 谁能改 says who holds the marker, never who may look. A board is always public; that is what makes it a board.

The storage shape IS the security

The pad is the only tool whose entire value is that nobody else sees it: a leak does not degrade it, it destroys it. So the design question was not「where do we filter it out」but「where can it be put such that no filter is needed」. Three guarantees, in descending order of how much work they save:

  1. It is never an event. self.pads lives in state.json only(the deal's idiom, taken further). replay(), transcript.md, the export and the Seen digest all walk events or the transcript — so a pad cannot reach any of them, and nobody has to remember to exclude it.
  2. There is no broadcast. Nothing here ever touches hub.publish(). A viewer-less SSE fan-out is the precise failure gate_payload(g, viewer_uid) exists to prevent, and the pad has no use for one: only the owner changes their own pad, so their own client already knows.
  3. Every read is keyed by owner. pad_payload(viewer) can only return that viewer's own and returns None for a viewer-less caller; user_pad() takes no owner argument, so the route has no parameter through which one person could name another. There is deliberately no method that returns「the room's pads」, because a caller that could ask for that would eventually ship one.

The leak test was written before the feature(the brief's instruction, and it earned itself immediately — it caught a real exposure on the first run). Two humans and two personas, each holding a pad with a unique string; every other party's payload, strip, replay, riding note and on-disk record is asserted to contain none of it. If that test is hard to write, the storage shape is wrong.

The one place it is not absolute, stated plainly

the seat wallBetween two PERSONAS, the wall is discipline, not structure. A turn is one panel call over the whole castself.system holds every seated profile — so there is no per-persona prompt to scope to. Each seat's pad therefore rides labelled with whose it is, and the block instructs a seat to read and write only its own: exactly the status quo of [Your sealed notes], which has always been cast-wide. The human wall is a different thing entirely and is structural — a u: key is unreachable from _pad_note, and the test asserts it. Making the seat wall structural too means splitting the panel call per persona; that is a turn-architecture change, not a pad change.

And one honest note about the record. A persona's <pad> was written by the model, so the verbatim reply survives server-side in the panel's own history and in the say event's forensic raw — the same two places a sealed <note>'s secret already lives(the v539 law: a persona keeps its own grammar). Neither is served to any participant. A human's pad reaches no model call and no reply, so it is in neither, and the test proves that separately.

The cost nobody can see

The pad rides every turn, which is what makes it useful and also makes it a compounding per-turn tax invisible to the person paying it. Hence a hard cap(2 000 chars ≈ 500–700 tokens)with a warning from 1 600, and a rule worth keeping: a write over the cap is REFUSED, never truncated. Trimming would delete the owner's words while reporting success.

Decisions taken, so they are not re-litigated

questionruling
one pad per owner, per room?yes — per-room matches every other instrument and keeps the leak test's assertions room-local. A second pad is a heading in the first.
more than one each?no.
the per-turn costa hard cap(2 000), warn at 1 600, refuse over — rather than trusting the manual's「prune」line alone.
does a human's pad survive them leaving?yes — it is their memory OF the room, not the room's furniture, so a rejoin finds it as they left it. It matches the room_members.status grain, where leaving destroys no content. Only deleting the room takes it.

14 · The board — markdown, the pen, and a face

Shipped v642, then v643 — ten owner reads on the built thing, two of which reversed a v642 ruling(§⑤). The board was the oldest tool in the box and the least finished: it worked, and three things settled in design had never been built.

THE PEN IS THE WRITE TOKEN. That one sentence is the whole permission model. Ownership never moves — the creator is whoever pinned the board, until it comes down — but the pen can be handed over, and whoever holds it is the one person the board takes a write from while 谁能改 is 仅创建者. So there is no second「may X edit」rule to keep in step with the pen: the predicate reads the pen and nothing else, and one predicate gates both doors(user_board and _apply_panel_board)— which is ruling ⑫ holding by construction rather than by care.

① The body is markdown

It renders through the app's one pipeline — renderRichmdToHtml → sanitize → mentions → house emoji), the same call a chat bubble makes. Bold, italic, strike, inline code, bullet and numbered lists, headings and a GFM pipe table all work; the grammar guard the study set(never raw HTML, never an iframe)is the sanitizer that pipeline already ends with, so it costs nothing to keep. A board-local renderer was the wrong answer: a second markdown implementation is how a table comes to work in the chat and not on the board, so the two things the board needed and the shared layer lacked — GFM tables, GFM strike — were added there, and every bubble in the app gained them too.

the exception, and why it is oneThe strip chip STRIPS markdown rather than rendering it. A 24-character preview is the one place the body must arrive as flat words:「**Dan** 3」with its stars showing is worse than either the markup working or the markup being absent, and a table row's pipes are pure noise at that width. One reader still decides what a board says(_md_gist, server-side, beside the rest of the strip)— it is just that this reader says it flat.
the cap, unifiedThree layers had three numbers. The tag's body read 1 200, the human door truncated at 400, and two docstrings claimed 600 — so a markdown table met whichever was smallest, and a body over the tag's own limit failed to match the regex at all: no board, no counter, no message, the v555 silent refusal exactly. Now BOARD_MAX = 1200 is one module constant read by all three, the grammar deliberately reads wider than the cap so an over-long tag is SEEN, and past the cap a write is refused rather than trimmed — with the reason, since「ask for the pen」and「write less」want opposite next moves.

② 谁能改 · 传笔 — and where each lives

dialdefaultwhat it means
谁能改仅创建者(was: anyone)who holds the marker — never who may look. A board is always public; that is what makes it a board.
传笔may others ASK you for the pen? Only meaningful under 仅创建者 — with 所有人 there is no marker to lend, so the row is not drawn(ruling ⑥'s treatment)rather than greyed.
sheet = policy · card = stateThe dials live in the sheet; who holds the pen — and the Edit door — live on the card. A dial is chosen once by the board's owner; the pen moves many times, in front of everyone, so the verbs that move it(要笔 · 给笔 · 收回 · 交回)sit beside the thing they change. A pen control in the sheet would have been a second place setting one value, and one of the two would have gone stale.
the legacy boardA board_set carrying no mode field at all projects as 所有人. Every board pinned before v642 was pinned under「anybody writes」, and silently locking one to whoever happened to touch it last would take the marker off a room mid-game. The test is the KEY's absence, not a falsy value — those are two different facts.
policy on a later writeHonoured only from the creator. A pen holder writes content, not rules: the marker was lent, not the board. Enforced on both sides — the applier declines to stamp the field, and the projection declines to read it — so the event log stays honest instead of leaving the projection the only thing that knows a value was ignored.

③ The pen's two events, and the trap they avoid

board_pen {to, by} and board_pen_ask {by} are their own stream, deliberately. Folding a hand-over onto a board_set would mean every 给笔 re-pins the board — a fresh timestamp, a fresh author, a fresh everything — and the projection could no longer tell「the creator handed the marker over」from「the creator wrote something」.

⚠ the per-viewer trapThe board's SSE has no viewer, so it publishes the FACT and never the obligation. The payload carries asks —「u:8 raised a hand」— and each client decides whether that is theirs to answer. A broadcast saying「you have a request」has no viewer to be「you」; that is a failure this codebase has already paid for twice. The per-viewer half lives in strip_payload(viewer_uid), which is scoped by construction, and the request surfaces as a 待办 pill in the top bar.
a pill must have a button(ruling ⑫)An ask is the PEN HOLDER's obligation — and a holder who is not the creator has no 给笔 door. That is the「settable, unusable」failure caught on the sealed roll, so a borrower gets 交回: send the marker home, whereupon the ask becomes the creator's to answer with a button that exists. Same event, one valve — the creator may hand it anywhere, the holder only homeward.
⚠ the same law, found LIVE, one seat overA PERSONA holding the pen had no door either — and the secretary case is precisely a persona holding the pen. The card's 给笔/收回/要笔 are buttons, and a persona has no card: so a seated host could pin a board it keeps, open 传笔, be asked for the pen, and have nothing to answer with. The fix is one more tag rather than a special case — <board pen="u3"/>(hand it over; a roster id or the person's name)· <board pen="back"/>(take it back)· <board pen="ask"/>(raise your own hand at somebody else's board)— carrying no body, split off in the applier so it never competes with「the last write wins」, and running the write FIRST so a reply that updates the board and then lends the pen did both with the pen it still held. It goes through the same valve as the human route(one lock-free core, two wrappers), so a persona cannot hand over what it does not hold. This is ruling ⑫ read as「same dials」, not merely「same access」, and the riding note now names the act in its own verb once(the v635 fix, applied here rather than rediscovered):「Ben asked for the pen. Hand it over with <board pen="u8"/> —「Ben, it's yours」with no tag hands over nothing」. An unreadable target moves NOTHING and is counted(the T1 units law: a word we cannot read must never become a hand-over to the wrong person).

A non-creator edit is not reversible — the board IS the state, so there is no undo and no revert-to-previous; the history is in the event log and the UI does not offer it.

④ The persona's side — the secretary case

The expected author of a board is often a persona. A room that wants a whiteboard kept will seat a secretary to keep it, and a persona can hold the pen — that is the point rather than a side effect. So board_note_sp lost its「short plain lines only; it is a scoreboard, not a document」half(wrong now)and kept the other(a panel, not a document); the tag grew edit="all" and the bare word handover.

the implementation shape of ⑫, againA persona has no wire payload, so「may I write this?」can only reach it as turn content. Told nothing, it writes the tag, is refused, and then narrates a board it never changed — the exact fiction the whose-board-is-this line was added to head off. So _board_note() carries the PERMISSION every turn, per seat: 「YOU HOLD THE PEN」or「⚠ ONLY X holds the pen — a <board> from you will be REFUSED」. And a refused write is never silentboard_bad + stderr + a persisted board_refused the next turn's note reports, with the reason): a model that is not told simply writes the same tag forever.

⑤ Owner reads on the built thing — v643’s ten, and v644’s three

reversed · the take-down撤下 IS A WRITE. v642 left it open to any member, reasoning by analogy with the clock(「a phase everybody has finished must not wait on one absent person」). The owner's reading is stronger and is what ships: deleting the whole thing is the largest edit there is, so it goes through the same predicate as one — both doors, the human route and the panel's <board away/>. And it needs no exception for the open case: with 谁能改 = 所有人 everybody may write, so everybody may clear, by construction.
reversed · the pill's zoneTHE BOARD'S CHIP DOES NOT MOVE. Every other obligation migrates into 待办, and for a card that is right: a card is transient, so its ZONE is what tells you it wants something. The board is the opposite — permanent furniture whose chip is a landmark — and sending it across the strip and back read as the chip teleporting. So a 状态 entry may now carry verb and wears the 待办 look in place: still exactly one chip, in one position, showing its verb instead of its value. The priority rule survives: THE FIT exempts an owed entry from the merge, so 状态 still yields width first — just never the one entry in it that is actually an obligation.
the readwhat shipped
the sheet, not yoursThe WHOLE sheet greys.bk-ro)with a banner that says why —「Ben has the pen — you cannot write on this board.」A dead commit over normal-looking fields makes a person type a paragraph before finding out, and a reason turns「it won't let me」into「Ben has the pen」. The banner itself stays at full strength: it is the one thing there you are meant to read.
传笔 under 所有人Greyed and struck, not removed — real but unavailable, the 全部 convention(v642 hid it per ruling ⑥; the owner's call is that a vanishing control reads as「this board has no such setting」). The hint swaps to say why. ⚠ And this fixed a real bug the owner photographed — see below.
an Edit doorOn the CARD, for whoever may actually write. The card is where you are looking when you decide to change the board, so the way in belongs there and not only in the ➕ drawer — and its presence IS the pen made visible.
the owner never asks要笔 is gone from the creator's card. Asking for your own board reads as though it had got away from you; 收回 is the creator's move and is always there.
who edited itShown in every mode and now said in words —「Amy · edited 10m ago」. A board is state somebody is accountable for, so「who touched this last」is never the part that drops out.
who holds the penShown whenever there is a pen to hold, never inferred from the presence of a button.
the fieldEight line-boxes(it was ~4½), derived from ONE --lh exactly as the pad's is, so the box and the text cannot disagree about what a line is. ⚠ Measured, not assumed: the first cut wrote the padding wrong and the field showed 7.4 lines.
linesSee below — the last one, and the most interesting.
⚠ the bug behind read ②hidden never worked on the segment at all. [hidden]'s display:none is a UA-stylesheet rule, and .pk-seg{display:flex} — an author rule — outranks it. So the 传笔 buttons stayed on screen while their LABEL and hint(plain <div>s with no display rule)vanished: exactly the owner's「the off/on's gap to 谁能改 disappeared」, and it also let an impossible 所有人 + 开 pair sit there looking settable. The general form is worth keeping: setting hidden on a node your own CSS gives a display to does nothing. Grey it, or write display:none yourself.
v644 · 「u:1 has the pen」An internal identifier reached a sentence a person reads, and it had two causes. ① /api/rooms/{id}/replay never populated name_map — and it is the one path a plain PAGE LOAD takes while rebuilding the whole room payload, every projection in it included. The fix is at the DOOR, one line, not per-projection. ② _actor_name degraded to the RAW KEY, which is worse than empty: a fallback that looks like data leaves the caller unable to tell it failed. It returns "" now, board_state() reads the name stamped on the event at write time, and the client re-resolves from its own roster as a last resort. Three layers, none depending on a per-request RAM field.
v644 · the owner’s own boardTHE CREATOR MAY ALWAYS TAKE IT DOWN. v643 made the take-down a write and stopped there — which locked the owner out of their own board the moment they lent the pen: they could only ask for it back first. Ownership never moves, so the one power an owner cannot lose is the power to END itboard_may_clear). A borrower still cannot delete somebody else’s board. And the live wash stopped reporting the pen:「Something is pinned right now — Dan has the pen」beside a button that takes it down is two unrelated facts in one sentence.
v644 · 传笔 greys as ONE sectionUnder 谁能改 = 所有人 there is no pen to pass, so it is the whole idea that does not apply — greying only the choice while its label and hint stayed bright said the wrong thing. One class over the group(.pk-grp.off). ⚠ And wrapping the field STOLE its gap.pk-lab:not(:first-child) is an ADJACENCY rule, so a label moved inside a wrapper becomes :first-child and its 22px silently goes to zero: the very symptom v643 fixed, re-created by the fix’s own wrapper. Two sightings of one shape in two versions: v643’s hidden lost to our own display rule, and this lost to our own new wrapper. Wrap a field, carry its spacing.
read ⑩ · a board IS linesA single newline is a line break on the board. Strict markdown folds consecutive lines into one paragraph — right for PROSE, wrong for a PANEL: four typed lines came back as one run-on sentence. mdToHtml/renderRich take {breaks:true} and the board passes it. An OPTION rather than a second renderer(a board-local markdown is how a table comes to work in the chat and not on the board)and rather than a global flip(a host bubble's wrapped prose should still reflow). The board declares its own paragraph semantics, which is the honest shape: prose reflows, a panel does not.

Noted, not built

out of scopewhy, and what mitigates it
row-level edits<board set="Dan" to="13"/>The drift risk from a persona rewriting the whole board every turn is real, but the tag grammar for incremental edits is its own build. The manual's「keep it short」is the mitigation for now.
the board's own history / undo UIThe board is the state(above). The event log holds the history; the UI does not offer it.
The orthogonal toolbox · owner-designed 2026-07-21, documented same day · supersedes the six-move basis as the internal architecture(the study keeps the product story; the build plan tracks execution). Steps 1–7 shipped on the old naming; §12 maps them. Werewolf is the standing stress test; the first target remains persona-as-GM. Extended from the design-check session: the shared round loop(§4)· the face-down deal(§5b)· the mode/composition line(§6)· the two layers(§7)· the completeness argument(§8)· rulings ⑦–⑧. Extended 2026-07-23 from perfecting the poll: the presence properties(§9)· rulings ⑨–⑪ — human-first, three configuration tiers, and blocking·sticky·unique with WhatsApp defaults. First played end to end 2026-07-26the scenario battery, 18 rooms over 27 runs: the mechanism took zero defects and every failure sat upstream of it, in the persona's reach for the tool(ruling ⑫'s exposure problem, now measured). Extended 2026-07-28: §13 — the pad, the eighth tool and the first with no audience at all; it answers a hole in §8 that the completeness walk could not see, because every scenario there was read for what the TABLE needs rather than what a PARTICIPANT must hold. And §14 — the board's upgrade(v642): the oldest tool in the box finally finished — markdown through the shared renderer, one cap instead of three, and a pen that can be lent without ownership moving.