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

+14 -16
View File
@@ -6,26 +6,24 @@ gated.** Prototypes do not open completion or publication gates.
## Current checkpoint and work
Latest delivered checkpoint: `66c41b2`, [Kwisatz Haderach inspection](KWISATZ_INSPECTION.md).
Types, lint, **4,950 offline tests** and production build passed. All 1,373 rooms,
Latest delivered checkpoint: `b2fcef8`, [Storm and Spice Blow practice](INTERACTIVE_INTRODUCTION.md).
Types, lint, **4,954 offline tests** and production build passed. All 1,373 rooms,
2,883 seats and existing auxiliary rows stayed unchanged. The running server was
reused. Earlier checkpoints include `ed53eb7` for Storm Cards, `67e429e` for
Charity/Revival practice, `c4ff75a` for alliances, `b7ec940` for bidding,
`b9718ac` for lobby AI configuration and `b21b2bc` for one-use AI permission.
reused. Earlier checkpoints include `66c41b2` for Kwisatz Haderach inspection,
`ed53eb7` for Storm Cards and `67e429e` for Charity/Revival practice.
The `8f7a62c` policy checkpoint removed the usage cutoff and deferred AI refinement
until feature completion, with three adjacent 75% targets. See the
[implementation history](IMPLEMENTATION_STATUS.md).
Current work: [Storm and Spice Blow practice](INTERACTIVE_INTRODUCTION.md) expands
the introduction to thirteen lessons and eleven independent Basic examples.
Sealed dials, reveal, sector traversal, shelter, spice accumulation/storm loss,
first-turn worm return and later-worm Nexus timing reuse shared live calculations.
Version 6 preserves old lesson identities and outcomes. Full faction, Fremen-ride,
Advanced and expansion teaching remain unfinished. Source-bound checks, review,
browser and preservation/Git evidence belong to the private checkpoint.
A bounded Duke review confirmed revival/loan paths still cross recorded custody,
return and cycle questions; no duplicate ruling or invented outcome was added.
Broader multiplayer and component acceptance remain unfinished.
Current work: [table discussion](TABLE_DISCUSSION.md) adds public conversation and
private human-seat messages, separate from game state and decision continuation.
Durable history, audience-filtered pagination, exact retries and active-session
fences support communication through refresh and seat recovery. AI conversation
and prose-deal enforcement remain unfinished. Source-bound checks, independent
review, browser and preservation/Git evidence belong to the private checkpoint.
A fresh bounded Terror/Kull audit confirmed existing pending rulings; independent
multiplayer communication proceeds without inventing their outcomes. The full
rules, multiplayer and component acceptance gates remain open.
A bounded remaining-effect audit found that the reviewed faction/Nexus candidates
still cross recorded pending rulings. Continue independent features rather than
@@ -95,7 +93,7 @@ These links define bounded working behavior, not complete module certification.
| Nexus/Homeworlds | [Decision index](RULE_DECISIONS.md) links each integrated faction family, native/borrowed effects, physical custody, private choices, payments and transport. [CHOAM Collection trade](NEXUS_CHOAM_SECRET_ALLY.md) and [Emperor extra revival](NEXUS_EMPEROR_SECRET_ALLY_RUNTIME.md) are connected; CHOAM inspection and Emperor purchase remain pending. A source audit or helper alone is not a completed effect. |
| Truthtrance | [Spice facts](TRUTHTRANCE_SPICE_FACTS.md), [card counts](TRUTHTRANCE_CARD_COUNT.md), [hand inventory](TRUTHTRANCE_HAND_INVENTORY.md), [recorded knowledge](TRUTHTRANCE_KNOWLEDGE.md), and [Basic/no-Guild Advanced reserve-shipment promises](TRUTHTRANCE_SHIPMENT_PROMISES.md) use authoritative private state. Earlier readiness audits do not supersede these follow-ups. |
| Other cards | [Sapho runtime](JUICE_OF_SAPHO_RUNTIME.md) includes first among remaining unstarted movement turns after Advanced Guild has finished. [Recruits](RECRUITS_RUNTIME.md) connects clean Revival play; [Harass & Withdraw](HARASS_WITHDRAW_RUNTIME.md) connects the bounded battle return in the same independent three-card preview. Richese card contracts and the checklist identify other connected effects and explicit gaps. |
| Multiplayer | Saved rooms/seats, [recovery](../README.md#saved-seats-and-reconnecting), uncertain-request retry, [own-seat AI](AUTOPILOT.md), [named-player AI permission](SEAT_AI_PERMISSION.md) and [voluntary seat handover](SEAT_HANDOVER.md) have connected controls and recovery evidence. |
| Multiplayer | [Public and private discussion](TABLE_DISCUSSION.md), saved rooms/seats, [recovery](../README.md#saved-seats-and-reconnecting), uncertain-request retry, [own-seat AI](AUTOPILOT.md), [named-player AI permission](SEAT_AI_PERMISSION.md) and [voluntary seat handover](SEAT_HANDOVER.md) have connected controls and recovery evidence. |
## Remaining readiness
+14
View File
@@ -1,5 +1,19 @@
# Dune implementation status
## 21 September 2026 — durable table discussion prototype
Public table conversation and direct human-seat messages now have usable controls,
plain-text rendering, durable history and exact retries. Message SQL independently
fences current credentials and membership, filters private channels before paging,
and leaves game JSON/version, sealed choices and bot continuation unchanged.
Recovery/handover transfers access to the seat's history; old credentials stop
working. Independent review found and fixed committed-write/rotation and late
unmounted-response retry races, with regressions. See [table discussion](TABLE_DISCUSSION.md)
for the complete boundary. Final source-bound checks, browser observations,
preservation and delivery records belong to the private checkpoint. AI messaging,
prose-contract enforcement and full acceptance remain open; no mode gate changes.
## 21 September 2026 — Storm and Spice Blow practice
The [interactive introduction](INTERACTIVE_INTRODUCTION.md) now has thirteen
+71
View File
@@ -0,0 +1,71 @@
# Table discussion and private seat messages
The table now has an expandable **Table discussion** panel beneath the game.
Humans can speak publicly or choose a named human seat for a private conversation,
in the lobby, during any pending decision and after the game. A human using AI
control can still talk. Permanent AI opponents do not read or answer messages;
AI negotiation remains deferred until non-AI feature completion.
## Message delivery and audience
Each message is plain text, limited to 1,000 characters. HTML and URLs remain
literal text, with no executable markup or external links. The server supplies
the sender's identity. A public message is visible to all present and future
seats in that room; a direct message is visible only to its sender and recipient.
Private messages belong to those game seats: recovery or voluntary handover gives
the new controller access to their history, and revokes the old credential's
access. The panel explains that boundary before sending.
Discussion does not spend spice, change alliances, seal a plan, evaluate prose
promises or execute game actions. Use the existing authoritative game controls
to carry out an agreement. This is communication infrastructure, not a new ruling
about binding deals or a completed negotiation/AI strategy system.
The latest 50 messages in the selected conversation load on opening and refresh
serially every five seconds, with bounded requests. **Load older messages** pauses
live replacement while browsing saved history; **Return to latest messages**
resumes updates. Channel changes discard obsolete read results. There are no
public direct-message counts, typing indicators or global sequence numbers.
Messages are stored durably; pagination does not delete old history.
## Saved retries and state isolation
The browser saves an exact message UUID, recipient and body in tab storage before
sending. An uncertain response keeps the input locked for **Retry exact message**;
refresh restores that same request. Exact repeats save once, and conflicting
UUID reuse never returns another message's body. An already uncertain retry is
not discarded just because a later request fails. Explicitly discarding retry
details cannot undo an already committed send. Unsent drafts are local inputs;
only pending sends have refresh recovery. No credentials enter this storage.
A late response from an unmounted panel cannot erase a newer pending send.
Successful writes return their own receipt even if the seat subsequently rotates.
Replaying under a different seat session cannot reactivate the earlier operation;
the current owner can inspect the conversation and discard obsolete retry details.
Additive migration `0007_clammy_sprite.sql` creates `room_messages` and its indexes.
Every SQL read and insert checks the exact active seat token, room membership and
human status; inserts check recipient membership at commit. The internal sequence
is used only for ordering. Cursor lookups apply the same audience filter as the
message page, so an unknown or hidden UUID does not expose message metadata.
One new message per sender per second bounds accidental rapid submission; exact
retries do not consume another slot. There is no game-version conflict to refresh:
message operations never write game JSON, reset readiness, advance bots or enter
a gameplay continuation. Existing saved games and schema history are preserved.
## Evidence and remaining work
`table-talk-recovery.test.ts` exercises production SQL against the real migrations:
private/public projection, hidden cursors, pagination, exact concurrent retries,
changed payloads, active-token and membership fences, rotation during a write,
store recreation, human AI control and unchanged game rows. The HTTP tests use
real authenticated rooms and sealed setup choices, verify origin/error handling,
exact retries and actual saved-kit recovery. Client tests cover input/receipt
validation, identity-scoped storage and late-completion cleanup.
Independent review found two retry races during implementation; both have been
fixed and regression tested. Browser observations, the final check/build/HTTP
report and saved-row comparison are source-bound private checkpoint artifacts.
This prototype does not certify complete network-failure browser behavior,
notification/unread design, full accessibility/visual acceptance, complete
negotiation rules or any AI strength target. Existing release gates remain closed.