Two clocks: real time, not turns
Characters act on their own clocks. Each one wakes when its cadence comes round, makes its call, and moves the instant the answer lands, while the slow physics and the room's decisions run on beat boundaries.
- Per-character cadence
- ~5 s for the impulsive, ~11 s for the patient
- Loop
- 200 ms
- A party
- 20 beats over five minutes; 24 over six in the crew room
- Room decisions
- on beat boundaries only
The fast clock belongs to the characters
runtime.ts wakes each person when their nextDecisionAt arrives, makes their evaluation call, and applies the move the moment it returns. The next look is booked cadenceMs later, stretched by patience and shortened by nerve, so the tempo of the room is itself a personality output and not a scheduler setting.
Nobody waits for a turn. You watch somebody cross the roof to the host while two other people are mid-conversation, which is the difference between a party and a board game.
The slow clock belongs to the room
advanceClock moves the party clock and runs the slow physics on beat boundaries: heat cooling, energy returning, trust drifting between people standing together. It also fires the tap, the ballot or the count on the beats the room decides on. A beat is fifteen seconds, and a party is twenty of them, or twenty-four in the crew room, which needs the extra night to grow a crew and lose it. The room's pause when it decides is the only beat a watcher ever sees, and it is deliberately visible.
Real time means staggered, not per-frame
This is the distinction that keeps getting lost. "Real time" here means characters are staggered: each acts when their own read returns. It does not mean the physics runs every frame. Every tuned number in the engine (decay, regen, trust drift) is per beat, and moving any of them onto a frame clock would retune the whole simulation without telling you.
Why the headless path still exists
resolveTick, where everybody decides and one beat passes, is kept for the tests and the terminal dry-run, and is built on the same two primitives. A rule that works headless works live, which is the only reason it is safe to tune the simulation without a browser open.
Read next
What a beat is
A beat is the simulation's unit of slow time, fifteen seconds of wall clock and twenty or twenty-four to a party. It is the only moment at which heat cools, energy returns, trust drifts and a room makes a decision.
One party in memory, streamed to everyone
A room is a single party held in server memory and streamed to every watcher, so everybody sees the same betrayal at the same moment and the model is paid for once per beat however many people are looking.
Playing a whole world in the terminal
A party plays in the terminal with no browser and no server, and a village year plays in under a second. Both run on the same primitives as the live simulation, so a rule that works headless works live.
coerce(): when the code overrules the model
coerce() is the last word on every decision. It drops forbidden actions, enforces gates and confidence floors, refuses moves the character cannot afford, and puts every override on screen in amber.