M1-03C
zoen-zone part C: runnable zone binary with WebSocket endpoint (zoen-protocol/1), 20 Hz loop
Evidence
From logs/evidence/M1-03C/. Click a thumbnail for the full image.
Logs and data (2)
server-log.txt · 305 B · open
zone binary smoke run (task log M1-03C-05) $ cargo run -q --release -p zoen-zone --bin zone -- --port 0 --seconds 2 [zone] listening on ws://127.0.0.1:55172 (zoen-protocol/1, 20 Hz) [zone] stopped after 2.0s: ticks=41 p50=0.02 ms p99=0.15 ms max=0.14 ms joins=0 leaves=0 frames=0 skipped=0 threads_left=0
test-summary.txt · 2 kB · open
M1-03C cargo test -p zoen-zone -p zoen-protocol (task log M1-03C-04) New: tests/ws.rs (SHA-1, base64, RFC 6455 accept key, frame round-trip/refusals), tests/server.rs (6 clients move+see each other, refusals, ping/pong, idle timeout, disconnect cleanup, entity reuse, graceful shutdown), zoen-protocol schema close_codes_match. test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.18s test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.14s test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 2.87s test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 2.56s test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.45s test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 4.37s test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.47s test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 2.37s test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.04s test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.28s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
Tests
$ cargo test -q -p zoen-zone -p zoen-protocol$ cargo clippy -q -p zoen-zone -p zoen-protocol --all-targets -- -D warnings$ cargo clippy -q -p zoen-zone -p zoen-protocol --all-targets -- -D warnings$ cargo test -q -p zoen-zone -p zoen-protocol$ cargo run -q --release -p zoen-zone --bin zone -- --port 0 --seconds 2$ pnpm --filter @zoen/wiki exec playwright test --only-changedNotes
2026-10-10 21:12 UTC · Split: endpoint + tests done here; 200-socket load check (pnpm zone:loadcheck, loop p99 + bytes/client/s JSON) and the idle-machine snapbench re-run -> M1-03D (roadmap card added). Decision: std threads + hand-written RFC 6455 (no crates): the workspace has no crates cache and builds offline, the endpoint needs only binary frames/masking/ping/close (~300 lines, RFC-vector tested), and TLS comes from the gateway later; tungstenite would not be clearly better. Built services/zone/src/net: ws.rs (SHA-1, base64, accept key, upgrade parse/400/426, frame reader with continuation/control/size/mask checks), server.rs (acceptor; per connection reader thread = handshake, hello check, decode, idle timeout, and writer thread; one bounded sync_channel into the tick, readers wait when full, tick only try_recv; per-client pool of sendQueueFrames preallocated buffers out, skipped snapshot when none free; slots taken after hello and returned after Left so Left(slot) precedes the next Joined(slot); ClientReplica built on the network thread; client seq mapped onto the entity's server seq via ClientReplica::set_input_seq_base; leavers get a stop input, are parked (ZoneState::park/unpark) and reused; graceful 1001 shutdown waits for all threads), client.rs (blocking masked client + ClientView), bin/zone.rs (--port --bind --seconds --quiet; pnpm zone:run). zoen.schema.json: session + closeCodes (1001/1002/1003/1009, 4001 protocolMismatch, 4002 idleTimeout, 4003 serverFull, 4004 badMessage) checked by zoen-protocol schema test. Proposed netcode.json -> server: bindAddress 127.0.0.1, port 7310, handshakeTimeoutMs 5000, idleTimeoutMs 10000, inboundQueueEvents 4096, sendQueueFrames 4, maxClientMessageBytes 125, maxHandshakeBytes 4096, spawnSpreadM 10, statusEveryS 5; spawn centre = world.json start waypoint zone centre. Tick Hz stays sim.json (no CLI override: it is the shared sim contract). Tests: tests/ws.rs 5 (RFC vectors, round-trips, refusals), tests/server.rs 2 (6 clients move exactly speed*dt per tick by their inputs, stop, see each other with exact quantised positions; HTTP 400, 4001, 4004, ping/pong RTT, drop -> entity leaves others, reuse with seq restart, idle 4002, shutdown 1001, threads_left 0). Evidence logs/evidence/M1-03C/test-summary.txt, server-log.txt (binary smoke run). Docs: NETCODE_1000.md transport (run instructions), ADR-003 build status. No crates added, so LICENSES.md unchanged.
