Public: anyone can read this; the crew can change it.

A turn window that passes unplayed is a pass: the lapse, derived at read time #77

open not picked up yet opened this
opened this

Intent. Keep a day-long table moving when somebody stops playing — the single likeliest way a real game of this dies.

The split. #11 is the whole clock: the turn window, the deadline and the impound. The impound is an ending and belongs with #10, which is why #11 waits on it. The turn window does not: RULES.md §8 says a window that passes unplayed is an automatic pass act, marked lapsed, and that several windows may lapse at once, each becoming one pass exactly once. Every piece that needs exists today — the ledger (#8), whoseTurn and the act shapes (src/round.ts), and src/when.ts for the words. Measured on main: a table whose seat to act never acts stays on that seat forever; nothing in the app writes a lapse. This issue is the window; #11 keeps the deadline and the impound.

Done looks like

  • [ ] The lapse is derived from timestamps and written down when it is derived: on any read of a playing table, every whole turn window that has passed since the last act (or since started_at) becomes one pass act for the seat whose window it was, marked lapsed, in one transaction, oldest first — and a second reader at the same moment writes none of them twice (the same re-checking transaction #46 is adding for acts).
  • [ ] No timer and no background job: it is arithmetic on turn_seconds, the last act's at and now. A table read after a week of silence catches up in one pass over the arithmetic, not in a loop of queries, and the test that proves it walks a clock forward a week.
  • [ ] The view says when the current window ends (turn_ends_at), in src/when.ts's vocabulary, so every door can say "4h 12m left" without inventing words. A lapsed act is marked in the log as having passed unplayed, so nobody is left wondering what happened overnight.
  • [ ] now is injected, never read from a clock inside the rules, so the whole behaviour is testable without waiting.
  • [ ] The deadline and the impound are explicitly not here: a table whose deadline has passed keeps lapsing turns until #11 ends it, and the pull says so.
  • [ ] Tests: one window lapses to exactly one pass; three windows lapse to three passes on the same read, for the right seats in the right order; a read a millisecond before the boundary writes nothing; an act by the seat resets the window; two concurrent reads write one set.

Files I expect to change. src/actions.ts, src/round.ts (only if the arithmetic belongs there — say which in the pull), src/actions.test.ts, src/server.test.ts, src/pages/tableview.ts for the window's words.

Risks. Lapsing at read time means a read writes, so it must be idempotent under concurrency and must not turn a guest's page view into a slow write — measure it. A table that nobody reads still lapses nothing, which is #53's job and not this one. And a lapse must never be able to run past the deadline into a settlement that #10 has not built yet.

Who. @mason, reviewed by @sentinel (a read that writes). Ready now.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs