docs · waypoint · 2026-10-03, updated 2026-10-06

Where the machine stands

Where Maschinenraum stands on 2026-10-03: what exists, how solid it is, where it bites, what is missing, what is stale or dead, and what to do next. It is about the result, not the history; git log has that. The HTML version is docs/html/waypoint.html, served at /docs/waypoint.html.

The snapshot was HEAD ce468a7 with the skate park uncommitted. Since then (update, later on 2026-10-03): the skate park and this file are committed; the Docker image builds and serves /docs; sound plays over plain http; the client reconnects; the sound engine computes the same samples on every OS; and every script and tool was run on Linux (Debian, in a container). Items done since are marked done below. (Everything has been pushed since.)

Update, 2026-10-06 (HEAD 751ed87, pushed): the numbers below are refreshed, and what was built since is listed under What exists as fresh: games on the city's floor (football, light cycles, breakout, Scramble cabinets, Spindizzy, Bomberman, Commando), the tower with its lift and paternoster, the lexicon, 52 looks with line weights and three new themes, run mode, photo mode at its best and the whole world, and two sound sources in code (a SID, the disco's machine with a DJ mixer). The audits in §5 to §9 are as of 2026-10-03 and were not re-run, except §7: every stale doc it lists (CLAUDE.md, the md design docs, the handbook and the technical design) was brought in line with the code on 2026-10-06.

Older audits stay where they are and are not repeated here: FINDINGS.md (121 findings at 33c1894), PERF_01.md (the measured performance pass), SECURITY.md (keys and the audit), PERF_IMPROVEMENTS.md, PLATFORM.md and IDEAS.md. This file tracks their status.

1. In numbers

Rustabout 49.6k lines of source and 2.7k of tests and benches (2026-10-06): client 32.7k (app.rs 4.5k, scene.rs 3.8k, gfx.rs 2.2k, sfx 4.9k), server 9.0k, protocol 5.8k, race 1.4k, props 0.7k, loadgen 0.2k
Content23 rooms (15 on the world grid: lobby, street, atrium, geode, central, skatepark, stadium, grid, court, spindizzy, bomber, tower, deck, skybar, roof; 8 behind portals: llm, lexicon, prairie, market, lab, bazaar, disco, basement), 48 object kinds, 52 looks, 59 sounds plus the SID and the disco's machine, 5 race tracks, 10 sceneries (Off included), 3 race themes, 16 bar menu items
Testsabout 215 #[test]s: client 84, server 66, protocol 47, race 9, props 9, loadgen 0. Also 3 benches, roomcheck, log_growth and two ignored tests that render the SID and the disco to WAV
History91 commits since 2026-09-30

2. What exists

Each line: what it does and where it lives. Solid means tested and used for a while. Working means it runs and was checked by hand or in a headless browser, but has thin tests. Fresh means built in the last day or two.

World and people

  • Rooms as actors solid. One tokio task per room, a bounded inbox, an allocation-free move broadcast, a token bucket that also charges for path search, and A* with a budget. server/src/room.rs, tests/alloc.rs.
  • World grid, seams and neighbours working. You see and walk across seams, with hand-offs, neighbour bands and light that reaches into neighbours. server/src/world.rs, rooms/world.ron. No tests at all.
  • Floors, stairs, raised and sunken areas solid. protocol::FloorPlan is shared by server and client. server/tests/floors.rs has 16 tests.
  • Residents and the bartender working. NPCs that wander and sit, and a bartender with a menu, servings and buzz effects. room/residents.rs, room/bartender.rs, client/src/buzz.rs.
  • Props and balls solid. Deterministic shared physics, golden-hashed for native and wasm. props/.
  • Builder editing and access keys working. An HMAC session cookie, a same-origin check, and edits gated per connection. server/src/auth.rs.
  • Event log solid. DuckDB on a single writer thread, a separate loader, snapshots, and a Parquet archive. server/src/eventlog.rs.

Games and things to do

  • Race working. Server-authoritative ships with the same code predicting on the client, rivals drawn in the present, an adaptive input queue, weapons, AI, 5 tracks and 3 themes (press T). race/, server/src/racing.rs, client/src/race_view.rs.
  • Disco working. Three stations each held by a player, notes made from the knobs on every client, dancing, speakers and eyes blown out by the kick. Since 2026-10-05/06: eight editable drum patterns, a bar, lights on the beat, and the music synthesised by the engine's machine with a DJ mixer and an 80s chain (fresh). client/src/disco.rs, app/disco.rs, server/tests/deck.rs.
  • Book box working. Durable LIFO links, by drag and drop or /drop. app/books.rs, server/tests/books.rs.
  • Half pipe fresh. A pad in front of a sunken pit, presses judged on the client and scored on the server, run after run with a durable board. protocol/src/skate.rs, server/src/room/skate.rs, client/src/app/skate.rs, rooms/skatepark.ron.
  • Transfer game (fresh, 2026-10-04). Paradroid's transfer on Deck 1's floor, player against player: wiring from a seed, shots checked and the match settled on the server, the board drawn from seed and shots on every client, a durable winners' board and droid badges. Against residents, and transfers as a way to take things over (IDEAS.md), are not built. protocol/src/transfer.rs, server/src/room/transfer.rs, client/src/app/transfer.rs, rooms/deck.ron.
  • Games on the floor fresh (2026-10-05/06). Football in the stadium, light cycles on the grid, breakout on the court (one player or two taking turns), Scramble on every arcade cabinet, Spindizzy's marble, Bomberman for one to four with predicted walking. Each one's rules in protocol, played by its room, with a board. protocol/src/{football,cycles,court,dizzy,bomber}.rs, server/src/room/*.rs, client/src/app/*.rs, client/src/scramble.rs.
  • Commando fresh (2026-10-06). An endless lockstep battlefield on a sunken sand table in the basement: the room steps the same deterministic game from the runner's inputs, so it keeps the score; onlookers watch live; the table plays itself when idle. protocol/src/commando.rs, server/src/room/commando.rs, client/src/commando_view.rs, scene/commando.rs. No server-side integration test yet.
  • Kobold fresh (2026-10-06). A coding game after EXAPUNKS in the boiler room under the basement: up to four at terminals write kobolds that walk a network of hosts on a sunken machine floor; eight jobs, a submission scored over 100 cases off the room task, the best cycles, size and activity on a #kobold board. Duels (Study B) in three arenas, RING, CROSS and LINE: spar against the house kobold, save a champion, challenge another nick's champion, or play a live duel after five minutes of writing; challenges and live duels are rated, Elo per nick and arena, on a #duel board. Relay (Study C) on four production lines, from BAR TAB to THE POST: a station per seat, Save swaps a station in a few cycles ahead, three-minute shifts scored right minus wrong, each crew's best per line on a #relay board. Live wire (Study D): a rig of 32 lamps over the floor that lights the room, beating to the disco's tempo; in free play each queued show plays a minute for everyone and the last runs on; three set pieces, PATTERN, CHASE and BINARY, tried in your own view only and checked by the room, the smallest solutions on a #show board. All four studies are built. protocol/src/kobold.rs, server/src/room/kobold.rs, client/src/kobold_view.rs, scene/kobold.rs.
  • The lexicon fresh (2026-10-06). Every word said there that GloVe knows grows a tree, folded by the room's own principal axes. server/src/words.rs, room/lexicon.rs, client/src/lexicon_view.rs.
  • The tower working (2026-10-04). A landmark skyscraper, a plaza, a lift corkscrewing up to the sky bar and the roof, a paternoster. protocol/src/{tower,lift,paternoster}.rs.
  • Run mode fresh. Shift+click or a double click runs; every walk carries its pace. protocol/src/walk.rs.
  • Model room working. A tiny transformer trained on the docs' trigrams, streaming tokens and its attention onto the wall. server/src/llm.rs, client/src/llm_view.rs.
  • Keyword billboards working. #latency, #server, #clients, #departures, #skate, #transfer, and since then #score, #cycles, #breakout, #dizzy, #bomber, #commando, #kobold, #duel, #relay and #show. latency_view.rs, server_view.rs.
  • Pings, emotes, a peer latency mesh and touch controls working.
  • Usability pass (fresh, 2026-10-04):
    • Settings as key=value (client/src/saved.rs), which fixes FINDINGS APP-1 to APP-4. New settings: Text size, High contrast, Reduce motion.
    • A key cheat-sheet (?); edit keys only in edit mode; Ctrl+Z undo; hover hints; a people menu and following; reading things up close.
    • Echoes, quiet rooms, groups, letters, paper planes, the world map (N), teleporters and tubes, proximity voice (client/voice.js).
    • Touch context buttons; a shared status-line column; a fault banner with reload and copy; mentions; refusals and rate limits said out loud.
    • The transfer opponent's cursor and spectator line; half pipe sounds of its own.
    • Code: server/src/room/social.rs, client/src/app/social.rs, app/voice.rs, app/undo.rs.

Look and sound

  • Renderer solid core, many options. wgpu on WebGPU or WebGL2: beams and fills, six shader looks and 52 profiles in all, vertex, edge and face themes (10, 11, 12), line weights, a light volume, GI traced on WebGPU, shadows, reflections, phosphor, shafts, photo mode (lighter while moving, at its best when still, the whole world on request), boss mode, an Auto quality governor and ten sceneries. Dynamic fills since 2026-10-06, for the Commando battlefield and the Kobold floor. client/src/scene.rs, gfx.rs, light.rs, look.rs, *.wgsl.
  • Characters working. Rigged templates with gestures and quirky parts (bobblehead, googly eyes, mittens).
  • Sound working. The client's own wasm instantiated a second time inside an AudioWorklet, patches as .snd text, held voices, buses and ambience beds. client/src/sfx/, sfx-worklet.js. Pinned by voice goldens. Since 2026-10-06 two sources in code: a SID (sfx/sid.rs) and the disco's machine (sfx/machine.rs), each with its own tests (fresh).

Transport and operations

  • WebSocket, then WebRTC data channels working. A reliable channel for the room and an unreliable one for the race, with barrier messages. server/src/rtc.rs, client/src/app/rtc.rs.
  • Docs served at /docs working. The handbook, technical design, platform page, engine log and this waypoint.
  • Deploy configs working. Docker (built and smoke-tested), compose with Caddy TLS, helm and kustomize. The configs still carry no secrets; see §4.
  • Linux working. .gitattributes keeps every text file LF. check.sh, dev.sh, shellcheck, the CDP scripts (Chromium, SwiftShader without a GPU) and the Python skill tools pass in a rust:1.99-bookworm container.
  • Tooling working. scripts/check.sh (clippy for both targets, every test suite, every room through roomcheck), scripts/dev.sh, loadgen, roomcheck, and the room-from-image and look-from-image skills.

3. Pitfalls: things that bite, and how

These are traps for whoever works on the code next, not bugs.

  • Hand-mirrored layouts. CameraUniform (304 bytes since the line weights), Line (64), Instance (80), anim codes, rig consts, GiParams, Photo and Grade lanes are all mirrored by hand between Rust and WGSL. Get one wrong and the geometry comes out scrambled with no error. Nothing asserts the sizes, and the comments disagree with each other (gfx.rs:10 and scene.wgsl:4 say 240, the HTML docs 272, CLAUDE.md both 48 and 64 for Line). Add const _: () = assert!(size_of::<…>() == …) as sfx/parse.rs does.
  • Lists of the same thing in several places. Object kinds live in ObjectKind::ALL, props::height, light.rs (emits and solid), affects_light in app.rs (drifted), sight.rs lights (drifted), scene.rs dispatch, roomgen.py KINDS (missing HalfPipe), preview.py COLOURS (missing 10 kinds) and the handbook's KINDS (missing 6). Every new kind touches about 15 files: the book box took 15 and the half pipe about 25.
  • Event kinds in SQL strings. EDIT_KINDS and HISTORY_KINDS are hand-written, and no test ties them to Event. skate is in neither, on purpose (the board reads it), so it is never archived and grows forever.
  • Shared timing needs both sides rebuilt together. Props, race physics, skate timing and disco notes change for everyone only once server and clients run the same build. Clients do not reconnect on their own (app.rs:1019, "reload to rejoin"), so a deploy strands everyone until they reload.
  • Secure context. AudioWorklet, WebGPU and crossOriginIsolated need https or localhost. Over http://<LAN IP>:8080 WebGPU is gone, so WebGL2 runs without traced GI, and the sound engine runs on the page behind a ScriptProcessorNode (done: it used to be silent), where a long frame can stutter it. docs/deployment.md now says so.
  • Autoplay. Joining from a ?nick= link keeps audio suspended until the first click or key. The #sound-hint now says so.
  • Windows builds. A running server.exe locks the release binary: stop it before cargo build/test --release. target/debug got corrupted twice in one day ("can't find crate", "found staticlib std") when a disk filled and, it seems, when the IDE built into the same target directory at the same time. Give the IDE its own CARGO_TARGET_DIR.
  • Disk. D: was at 100% today (22 GB free, target/ 31 GB) and C: at 6.6 GB. A full disk truncates build artefacts, and on the server a failed DuckDB write exits the process, which then crash-loops (SEC-7). Update: C: hit 0 bytes again during the xtask work, from Docker's growth inside WSL and leaked temp files. The WSL distro now lives in D:\wsl\Ubuntu, which freed 35 GB on C:, and the tests and browser tools delete their temp files.
  • wasm-only code is invisible to host checks. app.rs and gfx.rs compile only for wasm32, so cargo check on the host never warns about their dead code. Run clippy with --target wasm32-unknown-unknown, as check.sh does.
  • The steady-state move path must not allocate. Re-run cargo test -p server --release --test alloc after touching room.rs or the protocol. The skate hooks in walk() were checked and pass.
  • Headless verification needs a real click. A form submitted by script is not a user gesture, so audio stays suspended (scripts/smoke.mjs clicks through CDP's input events for that reason). The other CDP scripts used this session (shot.mjs, audio.mjs, prof.mjs, a frame tap) live in a scratch directory, not in the repo.

4. Gaps

Functional

  • Reconnect (done). The client rejoins its room with backoff after a drop or a restart, and reloads into it when a deploy changed the client bundle. A run on the half pipe or a race in progress is lost.
  • Sound without a secure context (done). The page-thread fallback plays; latency is about 21 ms higher.
  • Unused protocol surface. NeighborEvent::Gone is never sent; Target::Player, Verb::Use and several Act combinations are never built. Interact and Act{Use} behave differently: only Interact cancels a pending walk or a skate run (SRV-12).
  • Over-budget commands vanish silently (PERF_01 #10, done): the sender is told, at most every three seconds.
  • Turntables placed at runtime create a deck nobody is told about (FINDINGS #9, not re-checked).
  • Half pipe: no sound of its own beyond reused clicks, thuds and chimes. Spectators see a dropped air count as a clean landing until the count arrives. A run in progress is lost on leaving. The #skate billboard in the park faces away from the default camera.

Tests

None at all for world.rs (seams, hand-offs, caps), racing.rs (session lifecycle, retirement), rtc.rs, main.rs (auth endpoints, origin check, routing; no end-to-end WebSocket test), load.rs, protocol's codec and sanitisers, every client/src/app/*, gfx.rs, or sfx engine, bus, voice and parse beyond sfx/mod.rs. cargo xtask golden checks the wasm builds against the native hashes and cargo xtask smoke drives the real client in a browser; still, no unit tests run inside wasm.

Operations

  • Docker image (done, BLD-1). It builds (the parallel stages also raced on a shared cargo cache, now locked), serves / and /docs, 208 MB.
  • No TLS in the binary. That is fine behind Caddy or an ingress, but the cookie's Secure flag trusts X-Forwarded-Proto from any peer, and nothing refuses keys without TLS (SEC-9).
  • Deploy configs carry no secrets wiring (MR_ACCESS_KEY, MR_BUILDER_KEY, MR_SESSION_SECRET), so a deployment is open and editable by default.
  • No health endpoint, no metrics, logs to stdout only, and no bare-metal or systemd guidance.
  • Unbounded growth. Archive Parquet files are never pruned (41 in two days), every snapshot is kept, edits are never deleted after a snapshot, and skate rows are never archived. The k8s PVC is 5 Gi.
  • Backups: "copy the file while stopped" only.
  • Single replica. One DuckDB writer, so a rollout means downtime and a manual reload for everyone.
  • loadgen cannot log in, so it gets a 401 against a server with an access key.

5. Status of the earlier audits

FINDINGS.md top 10

#FindingStatus
1The settings string garbles looks 10–12open (app.rs:2043)
2Docker build broken by .dockerignoreopen
3affects_light drifted from the light tablesopen (app.rs:224)
4Neighbour SPIN/WAVE centres absolutenot re-checked
5Held RTC frames had no capfixed (MAX_HELD 256)
6A race session without a Join never retiresnot re-checked
7Held voices lost before the worklet runsfixed in ce468a7
8GPU struct sizes documented three ways, unassertedopen
9Runtime turntables and the decknot re-checked
10Event kinds in hand-written SQL listsopen

Also re-checked and still open: SRV-2, SRV-3, SRV-4, SRV-6, SRV-12, KIND-0, KIND-9, GFX-1, GFX-2, GFX-15 (Mesh::new unused), RACE-4, REPO-2. Its header says "nothing has been fixed", which is no longer true. Line numbers have drifted by 7–20 lines.

PERF_01.md top 12

#7 (race input two ticks late) is fixed: the queue target is adaptive, 1 to MAX_TARGET 4. The first-join freeze, measured separately, is fixed too: 61 ms instead of 2 s plus 1.7 s (a throwaway RTCPeerConnection and a warm-up frame, ce468a7). Everything else is open, the biggest first:

  1. A neighbour's edit rebakes the whole patch (21–25 ms frames).
  2. Joining and crossing a seam are one long frame.
  3. Every seat or door change rebuilds the static scene.
  4. The WebRTC driver costs about 10× the CPU of the WebSocket.
  5. DOM work dominates with crowds.
  6. GI is traced over every cell every frame.

SECURITY.md

The criticals are fixed. Still open: SEC-7 disk fill, SEC-8 fan-out amplification, SEC-9 TLS, SEC-10 book box abuse and sessions that cannot be revoked, SEC-13 to SEC-17 and the script CSP. SEC-16 says the Mermaid CDN page "is not served by the game", but /docs now serves it.

PERF_IMPROVEMENTS.md

None of it has been done yet: a SIMD light bake, sound voices without a per-sample match, the resident spot search, picking. Worth folding into PERF_01's list rather than keeping two.

6. Dead, obsolete and duplicated code

Superseded but still present

  • The old 2D per-tile lamp bake (sight::lights and bake_light, app.rs:3070) is now only a fallback for Classic and before the volume bakes. Its light table (sight.rs:140) lacks 9 emitting kinds and its colours differ from light.rs.
  • The look byte in the settings string (byte 5) is written and read but always overwritten by the profile index. The doc comment at app.rs:1358 ("the look as a or c") is stale.
  • settings.v1–v3 are never removed from localStorage.
  • auth_status's fallback for "an old server without /auth" (app.rs:685) has no purpose: client and server ship together.
  • custom_look: Option<usize> is always Some after start-up; its None branches are dead.
  • Style::Corporate and Style::Temple are used by no room since the atrium became Chinatown, yet they still carry palette, dressing and ambience code. ObjectKind::Pillar is in no room.

Dead or test-only

  • Mesh::new (scene.rs:174), LOOK_GRAPHIC (gfx.rs:264, allow(dead_code)), ST_HOLD (sfx/voice.rs:23, allow(dead_code)), and the rig consts UARM_R, LARM_R, THIGH_R, SHIN_R (mirrors only).
  • NeighborEvent::Gone (handled, never sent) and Target::Player (never built).
  • POST /logout is never called by the client.
  • Test hooks, intentional: LogMsg::Archive, Room::step_props_now, Room::unthrottled.
  • race::TICK_HZ duplicates protocol::TICK_HZ with no assert; sfx::TICK_HZ means something else under the same name.

Duplicated and drifting

  • splitmix64 twice (disco.rs:92, scene.rs:141).
  • xorshift four times (scene.rs:632, loadgen, residents.rs:35, race/game.rs:216, the last with different shifts).
  • FNV-1a with two different bases (scene.rs:667, residents.rs:92), plus a fourth hash in race_view.rs:163.
  • HANDLES = 64 twice (app/sound.rs:25, sfx/engine.rs:178).
  • level_of inlined again at app.rs:1766, and a third version with a different tolerance in light.rs:187.
  • Three copies of "nearest object" for /portal, /board and /screen (APP-8).
  • Scenery ring placement copied (GFX-3).
  • The CDP harness copied (scripts/looks.mjs and the skill's snap.mjs).
  • Interactable and keyword lists kept separately on client and server (KIND-6, KIND-7).

Repo hygiene

  • .idea/ is tracked and dirty.
  • Five screenshots are referenced only by FINDINGS.md.
  • The README caption still says "the temple atrium".
  • Five working notes sit at the root (FINDINGS, PERF_01, PERF_IMPROVEMENTS, PLATFORM, IDEAS), and IDEAS.md is a compile input of the model room.
  • MR_LLM_URL, MR_LLM_KEY and MR_LLM_MODEL are documented in props-npcs-audio.md but never read.

7. Docs that disagree with the code

There are 46 places. The ones people actually read come first.

docs/html/handbook.html

  • The KINDS list lacks Speaker, Turntables, DrumMachine, BassSynth and BookBox, and marks Plant as blocking. (done 2026-10-06)
  • It gives CameraUniform as 272 bytes; it is 288 (now 304). (done 2026-10-06)
  • The replayed kinds leave out drop and take. (done 2026-10-06)
  • The key map has no B, K or T, and lists a / key that does not exist. (done 2026-10-06)
  • It says "anyone can edit any room". (done 2026-10-06)
  • The config table lacks MR_DOCS and the four auth variables. (done 2026-10-06)
  • The list of rooms that ship lacks disco. (done 2026-10-06)

docs/html/technical-design.html

  • It gives CameraUniform as 272 bytes and the object cap as 4096 (it is 32,768). (done 2026-10-06)
  • The byte-level wire examples predate look, level and at. (done 2026-10-06)

CLAUDE.md

  • Line is both 48 and 64 bytes. It is 64.
  • FLOOR_INDICES no longer exists; it is now ViewRanges.floor with STENCIL_FLOOR.
  • "Only place/remove/rotate/screen are replayed": portal, drop and take are too.
  • History also includes served.

docs/protocol.md

  • RaceInput is { seq, recent: [u8; 6] }, not controls.
  • The RTC barrier messages are missing.
  • RaceFrame's field order (ack last) and its rate (every tick) are wrong.
  • ObjectState lacks Shelf, and the list of walkable kinds is short by 8.
  • It says "all traffic is WebSocket".

docs/architecture.md

  • It says rooms live for the life of the process; they retire after 5 idle minutes.
  • It gives "4096 objects"; the cap is 32,768.
  • It says the directory lock is taken on join only and is the only lock.
  • It says the reader "does not decode"; it does.

docs/performance.md

  • It says chat is allocation-free; chat allocates for its log row.
  • It says loads run on the log thread; they run on a separate loader thread.
  • It says wasm-opt -Os; the build uses -O3.
  • It describes Diorama's cost as a 32-light loop, which is gone.
  • The loadgen flags lack --room.

docs/rendering.md

  • It says 16 avatar lights; up to 32 are kept.
  • It says lamps go into the light list; only avatars do.
  • The edit-rebuild timings are stale.
  • Sight is also blocked by Diagonal, Column and Billboard.

docs/rooms.md

  • The lava lamp has 7 blobs, not 10.
  • The lobby's "walled back room" is gone.
  • The Ball row is missing.
  • "Anyone can edit" is out of date.

docs/deployment.md and README.md

  • docker build is given as working; it is not.
  • "Anyone can edit" is out of date.
  • "Room creation capped at 64": rooms without a file are capped at 16.
  • The worst-case path search is 275 µs, not 75.
  • The "temple atrium" caption is stale.

docs/persistence.md

  • The schema comment leaves out skate.
  • It says a corrupt payload "panics the room"; it panics the loader thread.

FINDINGS.md and PERF_01.md

  • Both say "nothing fixed".
  • Their line references have drifted.

8. The speculative docs

IDEAS.md: built but not marked

  • The bartender (with the menu, servings and buzz).
  • First person when sitting (a setting).
  • A rewarding sound system (sfx).
  • Photo mode.
  • roomcheck (it lints but does not render top-down).
  • The /look and /room skills (as look-from-image and room-from-image).
  • docker-compose with Caddy, kustomize and Helm (all written, all blocked by the Docker build).

Built in part:

  • Race variants: three themes, but no time trial, ghosts or teams.
  • Music back in: the disco makes music from knobs, but there is no .kit or .mid player.
  • Achievements as neon: the #skate board is the first one.
  • Light cycles: the Tron light-racer theme exists, but not on the dance floor.

Marked built already: Pings, the LLM room.

IDEAS.md: sensible next, by what already exists

  1. A window onto the race (M). Race frames are already decoded on the client, and the race view draws on any surface.
  2. Time trial with ghosts (S–M). The client already re-runs ship::step, so a ghost is the same thing replayed.
  3. Footprints that fade, and dust in the light (S). The dynamic-line plumbing exists (pings, disco eyes, skateboards).
  4. A world clock or a build radiator (S–M). Keyword billboards are the pattern; one more keyword means one function in server_view.rs.
  5. Quiz night at the bar (M). There is a bartender NPC and a chat path.
  6. A Prometheus /metrics endpoint (S). load.rs already samples.
  7. CI (S). check.sh is already the whole pipeline.

The Lore quarter and proximity voice are large and have nothing underneath them yet. Paradroid's transfer game exists as a PvP match on Deck 1; taking things over with it does not.

PLATFORM.md

None of the platform layers is built. The skate park is one more data point for its §1.2. A new thing still costs code smeared across four crates:

  • protocol: a kind, messages and a shared module;
  • props: the ball height;
  • server: eventlog, layout, room, roomcheck and tests;
  • client: scene, app, latency, pings, server_view and index.html;
  • rooms, world, street;
  • six docs.

That is about 25 files against the book box's 15. The interesting logic, judging and scoring, is about 150 lines in protocol/src/skate.rs. The case for kits is stronger than when the page was written. The cheapest first step, deriving every per-kind table from one declaration, would have saved the drift listed in §3.

9. Clean-up, in order

Each step is small, independent and safe to do on its own.

  1. ~~Commit the skate park.~~ Done. Still to do: stop tracking .idea/.
  2. ~~Fix the Docker build.~~ Done. Still to do: wire the auth secrets into compose, helm and kustomize.
  3. Assert the GPU struct sizes with const _: () = assert!(…), and fix the 240/272/48 comments and docs in the same change.
  4. One per-kind table. Derive affects_light, the sight lights, the light emits and solids, and props::height from one place, or at least test that they agree. Regenerate roomgen.py's KINDS, preview.py's COLOURS and the handbook's KINDS from ObjectKind::ALL, or add a check.
  5. Fix the settings-string look bug (APP-1). Drop the dead look byte and clear settings.v1–v3.
  6. Remove the dead code:
    • Mesh::new, LOOK_GRAPHIC, ST_HOLD, NeighborEvent::Gone (or send it) and Target::Player;
    • the old /auth fallback, and the 2D lamp bake if Classic can use the volume;
    • Style::Corporate and Style::Temple, unless a room is coming for them.
  7. Make Act{Use} and Interact one path, or drop Verb::Use.
  8. One small rand and hash module shared by client, server, race and loadgen, keeping race's own shifts if its goldens depend on them.
  9. A test that ties EDIT_KINDS and HISTORY_KINDS to Event. Decide whether skate is pruned.
  10. Sweep the docs in §7. Two passes: the HTML pages people read, then the markdown. Rewrite the headers of FINDINGS.md and PERF_01.md with their fix status, or fold the still-open items into this file and archive them.
  11. Move the CDP scripts from the scratch directory into scripts/, as a smoke test: join, click, meter audio, ride the half pipe.

10. What to do next

Ordered by value for effort. S is an afternoon, M a few days.

  1. ~~Sound everywhere.~~ Done (page-thread fallback).
  2. ~~Reconnect.~~ Done.
  3. ~~CI.~~ Done, as steps by hand. cargo xtask (lint, test, rooms, client, server, golden, smoke, image, deploy-lint, bench) passes on Windows and, with cargo xtask linux, in Debian; see docs/deployment.md, "Checks". There is no CI server, by choice. Still open: the compose file is only checked where docker is on PATH, and deploy-lint on Windows needs helm and kubectl (or the linux form).
  4. Deploy (S). The image works; add the secrets wiring, a /healthz and archive pruning.
  5. The frame-time top three from PERF_01 (M):
    • rebake only the region of an edit;
    • bake over several frames, or in a worker, on join;
    • doors and seats in a dynamic layer instead of the static rebuild.
  6. Tests for world.rs and racing.rs lifecycles (S–M). These are the biggest untested server paths with state machines.
  7. Half pipe polish (S):
    • its own landing and bail sounds;
    • a spectator chase camera;
    • turn the billboard toward the camera;
    • a short trick name in chat ("540!");
    • time trial on the same board.
  8. First platform step (M). One per-kind declaration that the tables in §3 come from, before the next new object kind.