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

A word with your act: one public line of table talk, on your turn only #22

open not picked up yet opened this
opened this

Intent. A negotiation that runs for hours needs somewhere to persuade, so every act may carry one short public line — unaudited, never scored, and only on your turn, so the rhythm of the game is unchanged and the said register keeps its meaning.

Done looks like

  • [ ] RULES.md gains a short section after §7 naming it: talk is free text carried by an act, at most 280 characters, public forever, never verified, never scored, and never a substitute for a said claim — if you want a claim about your charge audited at the reveal, you say it, and saying it is what gets a verdict. §12's table of what each rule reads gains its row.
  • [ ] Migration appended to migrations in src/db.ts (never editing one that has run): act.talk TEXT NULL.
  • [ ] makeOffer, acceptOffer and passTurn take an optional talk, validated at the boundary in the action: trimmed, 1–280 characters after trimming, no newline and no control character, absent or empty means none. One named failure per rule, with a sentence a player can act on.
  • [ ] Talk appears in tableState's act log for everyone, guests included, and in the MCP table_state payload — it is public by construction, so there is nothing here to redact.
  • [ ] No new spam surface: one act is one turn, so the turn rule already caps talk. A test proves a second line out of turn is refused by the turn rule and not by a new one.
  • [ ] Tests: 280 characters accepted and 281 refused; a newline and a control character refused; <script> in talk comes back escaped from the page and from the terminal; a guest reading a playing table sees the talk and no charge.
  • [ ] The page shows the line under its act in the log, wrapping, never truncated silently; the terminal shows it the same way.

Files RULES.md, src/db.ts, src/actions.ts, src/actions.test.ts, src/routes.ts, src/mcp.ts, src/server.test.ts, and the table page (in src/pages/ if #12 has landed, otherwise that row lands with #12).

Risks This is the app's only unstructured input: escape it at every door — page, terminal and MCP text — and keep it out of the score and out of the reveal's verdicts, or the said register stops being the thing you are audited on. Resist making it a chat room: talk rides an act, and there is no endpoint that posts talk alone.

Brief that fits @vesper — the rules engine of a game, with the boundary written first. (A person assigns.)

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs