Public: anyone can read this; the crew can change it.
The table plays on the page: the charter, the standing offer, the log and the three acts — before the reveal exists #75
One measurement for the log, so the page does not inherit an unbounded read: with 300 acts in the ledger (a fortnight of 15-minute windows would be thousands), GET /api/tables/1 on main is 30 KB and 14 ms, against 2 KB and 6 ms for the same table empty. Every live refresh refetches the whole page, so an unbounded log is refetched with it. Show the latest acts with a count and a way back through the older ones, and keep what src/round.ts reads for its arithmetic separate from what the view hands out — the turn is derived from the act count, so bounding the wrong one changes the game.
The bound on the act log now has its own issue — #79, with the measurement (30 KB and 14 ms at 300 acts, against 2 KB and 6 ms empty) and the rule that matters: bound what the view hands out, never what the arithmetic reads. This page issue can show the latest acts and defer the paging to it; if #79 lands first, take the slice it gives you.
Intent. Let a person play a turn from a phone with what is already built, instead of waiting for the binding.
The split. #12 is "the whole game server-rendered, live, playable with a thumb" and waits on #10, the binding and the reveal — which is right for the reveal and wrong for everything else. Measured on
maintoday (948abc0): a table can be started, offered on, accepted and passed entirely over HTTP, and/tables/1shows the title, the seats and "The seats are fixed: this table has started." No charter, no charge, no offer, no log, no buttons, and itsdata-livedoes not even listact.made, so an act does not refresh it. The parts to draw all of it already exist insrc/pages/table.tsand are shown at/style. This issue is the pre-reveal half; #12 keeps the reveal, the settlement and the polish that needs them.Done looks like
/tables/:idrenders, for aplayingtable: the charter grid with the standing offer marked, the viewer's own charge (theirs alone), whose turn it is with the seat named, the act log newest-last with each acceptance's sworn aim, and what the standing offer would pay the viewer (your_payoff).maysays so and never otherwise, and a refusal comes back as the notice, in the action's own words.canStart.act.madeandturn.changedas well as the seat events, so an act made at another door appears without a reload.src/pages/table.tsalready has; anything new goes there and is shown at/stylefrom a fixture.Files I expect to change.
src/pages/tableview.ts,src/pages/table.ts,src/routes.ts(the form posts for offer, accept, pass and start),src/pages/style.ts,static/app.css,src/server.test.ts,src/pages/style.test.ts.Risks. An offer is irreversible and an acceptance spends a truth forever: the page says so before it posts. Do not let the page compute a rule — everything it draws comes from the state. Keep the log bounded once it is long (that is its own issue).
Who. @mason, reviewed by @juniper. Waits on the
may/your_payoffstate issue below it.