Public: anyone can read this; the crew can change it.
The clock: turn windows, the deadline, and the impound, all derived from timestamps #11
Split. RULES.md §8 is two clocks. The turn window — a window that passes unplayed becomes one pass act marked lapsed, several at once if several passed — needs only the ledger (#8, merged) and src/when.ts (#20, merged), and it is what keeps a real table moving when somebody goes quiet; it is now #77, ready.
This issue keeps the deadline and the impound, which are an ending and belong with #10 — the dependency is right and stays. #53 (a silent table still passes) sits on top of both.
Note for whoever takes the deadline and the impound: #83 changes the deadline's floor from 2 × turn window to the arithmetic of a binding (quorum + 1 windows, plus slack), because on today's defaults a 5- or 6-seat table cannot bind before its deadline if the seats use their windows. Read the deadline rule from the constants after that lands, not from the numbers written here.
Intent. Make the game asynchronous but not stalled — a turn that goes unplayed for its window becomes a pass, and a table that reaches its deadline without an accord is impounded — with no timers, no background job, nothing but arithmetic on rows at read time.
Done looks like
src/clock.ts: given a game, its acts and anow, it says whose turn it is, when that turn lapses, how many turns have lapsed unplayed, and whether the deadline has passed. Pure,nowinjected, fully tested.passacts by the engine (seat marked, reasonlapsed), and a passed deadline settles the table asimpoundedwith every seat scored zero and everything revealed exactly as a binding accord reveals it.turn_seconds(default 6h) anddeadline_seconds(default 24h) are set when the table opens, validated to a sane range, and shown on the page and in the API.tableStatecarriesturn_ends_atanddeadline_atas ISO strings; the page renders a countdown without layout shift, and without JavaScript still shows the absolute time.emit("table.impounded", …)fires once.Files
src/clock.ts(new),src/clock.test.ts(new),src/actions.ts,src/db.ts,src/page.ts,src/actions.test.ts.Risks Lazy catch-up is idempotent or it is a bug — two readers arriving at once must not each write the pass. Do the catch-up inside one transaction with a guard on the act count.
Brief that fits @hearth — honest about what really runs, with a recoverable state. (A person assigns.)