Builds the browser game around the existing Rust runtime: a window into the universe, not a second simulation. Pure std, no external crates. New crates: - protocol: versioned, hashable client/server messages + hand-rolled JSON value and total parser (malformed packet -> Err, never panic). - game_runtime: authoritative match state. Resolves turns through the INDEPENDENT interpreter (runtime_under_test::native_resolve), not the reference engine; filters visibility/knowledge; records and regenerates replays. A match is a pure function of (seed, roster, ordered inputs). - web_assets/web_client: embedded browser client (arena, rune editor, knowledge panels, replay viewer) + static HTTP delivery. - server: std::net HTTP + WebSocket (hand-rolled SHA-1/base64/RFC-6455 framing), turn timer, disconnect handling, panic-proof dispatch, poison-tolerant lock. - web_tests: dependency-free WebSocket test client + Phase H gates. Trust hardening per review: - game_runtime no longer delegates to reference_runtime::execute; it runs the independent interpreter that the runtime-equivalence gate proves correct. - Protocol/socket/replay/visibility/resilience gates are merge-blocking (added to the merge_group-required job in merge-gates.yml): 1k matches/0 drift, 10k fuzz/0 panics, 100 headless socket E2E, 0 hidden-state leaks. - Rendered-browser E2E is marked EXTERNAL-BLOCKED: Playwright runs advisory-only (continue-on-error, artifacts) until CI infrastructure with a browser exists; it is treated as unsatisfied, not green. The headless 100-match gate is labeled protocol-level coverage, not rendered-browser coverage. - README documents the hand-rolled crypto/parser audit risk explicitly. Fixes an integer-overflow panic in observed-volatility inference (i64 sum / abs near i64::MIN) that could poison the server mutex. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4.6 KiB
Web Game Implementation Plan Prime Directive Build the browser game around the already-defined Rust simulation/testing system.
The web game must be:
Browser-first Server-authoritative Replayable Deterministic Test-gated Playable before pretty No web feature may bypass the Rust runtime contract.
Architecture Rust simulation core ↓ Authoritative server ↓ WebSocket protocol ↓ Browser client ↓ UI / arena / rune editor Browser never decides truth.
Browser only sends:
intent movement choice rune program library slot selection inspection request Server returns:
world snapshot visible observations turn result trace excerpts replay hash legal player-facing diagnostics Crates crates/ world_model rune_ir trace_model reference_runtime game_runtime replay_corpus protocol server web_client web_assets web_tests Phase A — Protocol First Define all client/server messages before UI.
ClientMessage JoinMatch SubmitTurn EditRuneProgram InspectTarget RequestReplay Ping
ServerMessage MatchState TurnStarted TurnResolved ObservationResult ValidationReport ReplayChunk ErrorEvent Rules:
All messages versioned All messages serializable All messages replay-testable All server outputs hashable No client-only game truth Phase B — Authoritative Match Server Server owns:
match state turn timer submitted actions rune execution visibility filtering knowledge filtering replay recording disconnect handling Server loop:
Create match Send visible snapshot Start turn timer Collect actions Resolve through runtime Persist replay event Send filtered results Advance turn Hard gates:
same inputs produce same replay hash late input rejected deterministically disconnect does not corrupt match invalid client packet cannot panic server client cannot mutate hidden state Phase C — Browser Client Shell Client responsibilities:
connect authenticate anonymously/dev join match render visible arena show entities show turn timer edit rune program submit action display results display observations play replay events Do not implement complex art yet.
Use debug visuals:
grid tokens panels logs timers entity markers domain indicators Phase D — Rune Editor The rune editor is the core UI.
Required:
keyboard-bound rune input token grid / sequence view library slot panel syntax-neutral execution preview visible cost/risk diagnostics submission lock on timer expiry Important:
The editor must not pretend to know full truth. It can show observed diagnostics only. Player-facing diagnostics should say:
known reads known writes observed risks unknown listeners previous outcomes Not:
guaranteed damage guaranteed success full hidden state Phase E — Arena Interaction Each turn, player can:
move inspect cast rune program use stick/basic attack wait All actions become server commands.
Client-side previews are advisory only.
Phase F — Visibility / Knowledge Layer Server sends filtered state:
VisibleWorldSnapshot { observed_domains, observed_entities, observed_environment, known_history, inferred_markers, hidden_state_redactions, } Knowledge must be game state, not UI notes.
Client displays:
known unknown suspected contradicted newly observed Phase G — Replay System Every match produces:
initial seed player inputs turn boundaries runtime hashes visible outputs trace excerpts final hash Browser replay consumes the same protocol stream.
CI gate:
recorded replay equals regenerated replay browser replay event order matches server order Phase H — Web Testing Required test layers:
Rust protocol tests server integration tests browser protocol tests Playwright end-to-end tests replay determinism tests fuzzed packet tests disconnect/reconnect tests timer edge tests Minimum web CI gates:
1,000 simulated matches 10,000 protocol fuzz cases 100 browser E2E matches 0 server panics 0 replay hash mismatches 0 hidden-state leaks Phase I — Vertical Slice First playable slice:
2 players or 1 player + dummy opponent small arena turn timer movement inspection basic attack rune submission multicast execution visible consequences replay viewer No progression. No accounts. No cosmetics. No marketplace. No complex content.
Acceptance Criteria Web phase is accepted only when:
A player can join a browser match. A turn timer runs. The player can inspect, move, attack, or cast. Rune programs execute only on the server. Results return as filtered observations. Replay can reproduce the match. Browser cannot alter hidden truth. CI proves protocol, replay, visibility, and server authority. Core rule:
The web game is just a playable window into the Rust universe. It must not become a second simulation.