Add durable public and private table discussion

Humans can discuss plans publicly or message another human seat privately while
pending game decisions stay intact. The conversation panel provides plain text,
explicit recipient names and factions, saved history, private pagination and
exact retries through refresh. Human AI-control owners can still talk; bots do
not interpret messages or negotiate. Existing game actions execute agreements.

An additive indexed D1 message table stores discussion separately from game JSON,
versioning, readiness and bot continuation. Every read/insert checks active seat
credentials and membership; direct audiences and cursor lookups are filtered
before limiting. Public history has no private activity counts or sequential IDs.
Recovery/handover inherits seat history while fencing old credentials.

Independent review found two retry races: a rotation between a committed insert
and receipt read, and stale unmounted completion deleting a newer retry record.
Both are fixed with regressions. A prior uncertain retry stays pending on later
rejection. The nine focused offline cases and two HTTP cases cover production SQL,
concurrent/altered receipts, audience/cursor privacy, rotation/membership races,
actual saved-kit recovery and unchanged sealed setup state.

Types, lint, all 4963 offline tests, production build and 48 HTTP tests
pass on stable source. An initial check caught an invalid checklist status label;
that was corrected before the successful final2 verification.

Desktop browser checks send public/private messages, receive a peer reply, retain
private history after refresh and remove it on channel switch. Literal markup and
URLs remain text. Recipient and bystander API reads confirm the browser messages'
audiences. Screenshot capture was unavailable and the viewport override did not
take effect; mobile, full keyboard/visual and injected browser network-failure
acceptance remain open. No final rules, mode, AI or publication gate changes.

All 1373 pre-existing rooms, 2883 seats and auxiliary rows
are unchanged. SQLite integrity/foreign keys pass; migration 0007 adds messages
without replacing data. The healthy server was reused without restart.

Private evidence: 20260921-table-talk.
Verified source tree: 236dd55b6c15d55dbced735be67427e5fbd7fa348d583f119e67a03894ec21b0
This commit is contained in:
Quintine committed 2026-09-21 09:52:31 +10:00
1 parent b2fcef8d51
commit 7814f740ef
19 files changed
+2303 -17

No files matched your search

+24
View File
@@ -254,6 +254,30 @@ export const RULE_TOPICS: RuleTopic[] = [
{ area: 'Verification', status: 'Partial', detail: 'Focused checks compare all 24 offered storm dials and four spice scenarios with real engine actions, preserve v5 lesson identities, and compare resource payments, allowances and leader custody with engine actions, validate paid-save continuation and prior lesson migration, and cover alliance consent/break and later victory across 24 engine comparisons, bidding/re-entry against the live engine, full hands, payment/card custody, pricing, all offered plans, weapon survival, ties, losses, collection limits, 96 movement comparisons against the engine, single/mutual/declined Traitor calls and saved-choice migration/validation. This does not certify all rules or the complete learning journey.', evidence: ['tests/introduction.test.ts', 'tests/introduction-practice.test.ts', 'tests/introduction-bidding.test.ts', 'tests/introduction-alliance.test.ts', 'tests/nexus-alliance.test.ts', 'tests/introduction-resources.test.ts', 'tests/introduction-resources-migration.test.ts', 'tests/introduction-opening.test.ts'] },
],
},
{
id: 'table-discussion',
title: 'Table discussion and private messages',
category: 'Getting started',
coverage: 'Partial',
developmentStage: 'Prototyped',
summary: 'Discuss plans publicly or privately with another human seat, with saved history and exact message retries.',
steps: [
'Open Table discussion beneath the board. Choose Everyone at the table or a named human seat before sending. The server supplies your sender identity; messages are plain text, up to 1,000 characters.',
'Public messages can be read by everyone who joins this room. Private messages can be read only by the two addressed seats. Recovery or handover gives a seat’s next controller its message history and revokes the old credential.',
'Messages are available while game decisions are pending and do not change their state. Use the game controls to carry out agreed actions; typing a message does not transfer spice, form an alliance or make a Truthtrance commitment.',
'If sending is uncertain, Retry exact message confirms the original request without sending a duplicate. Refresh restores pending sends. Discarding retry details cannot undo a message already sent.',
'Load older messages to browse saved history. Return to latest messages resumes live updates. The panel shows no private-activity counts to other seats.',
'Human owners using AI control can still talk. Permanent AI opponents do not read or answer messages yet; AI negotiation waits until the game features are complete.',
],
related: ['privacy', 'alliance-funding', 'card-truthtrance', 'implementation-checklist'],
checklist: [
{ area: 'Implementation', status: 'Partial', detail: 'Separate durable message storage supports public/direct conversation, private pagination, session-fenced reads/writes and exact retries without changing game state.', evidence: ['db/table-talk.ts', 'lib/table-talk.ts'] },
{ area: 'Player controls', status: 'Partial', detail: 'Named conversation selection, plain-text messages, saved retries and older history are connected. Full notification, accessibility and visual acceptance remain open.', evidence: ['components/table-talk.tsx'] },
{ area: 'AI', status: 'Planned', detail: 'Human controllers can communicate while AI operates their seat. Automated message understanding and negotiation are deferred until non-AI feature completion.' },
{ area: 'Documentation', status: 'Implemented', detail: 'Audience, seat inheritance, saved retries and the distinction between discussion and game actions are explained.', evidence: ['docs/TABLE_DISCUSSION.md'] },
{ area: 'Verification', status: 'Partial', detail: 'Production SQL and HTTP cases cover audience, cursor privacy, exact retries, token rotation, saved-kit recovery and unchanged sealed setup. Full browser/network and multiplayer acceptance remain open.', evidence: ['tests/table-talk-recovery.test.ts', 'tests/table-talk-http.test.ts', 'tests/table-talk-client.test.ts'] },
],
},
{
id: 'table-sounds',
title: 'Sound effects',