Add web game (plan2.md) on the independent runtime, merge-blocking gates
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>
This commit is contained in:
@@ -0,0 +1,262 @@
|
||||
|
||||
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.
|
||||
Reference in New Issue
Block a user