# LANE E — NOTES ## Round 2 (2026-07-17) — first run. `#ui` had never had an owner; now it does. Landed: `web/js/ui/hud.js` (createHUD) + `web/js/ui/comms.js` (createComms), constructed in boot. QA GREEN. Evidence: `docs/shots/laneE/round2_hud_aortic.webp` (s=1111, seed 7, live hazard warn + ×6 chain). **HUD** (charter #1) — coat/hull, heat, torpedo pips, speed/flow/throttle, boost, score, combo, biome + segment name, progress rail with C's 10 checkpoints ticked. Bus-only: zero imports from B, exactly as the charter asks. `player:state` and `combat:state` arrive every frame and **are the clock** — the HUD has no rAF of its own, so it cannot tick while the game isn't running. 60fps law: DOM is built once; the hot path is `transform` + textContent-on-change only. Bars scale (`scaleX`), they never resize — a `width:%` write per bar per frame is a layout pass. Torpedo pips rebuild only when `ammoMax` changes, not when `ammo` does. **Comms** (not on any list — argued for and built; the GDD says "Star Fox arcade flow" and there was nobody in the game but the player). Three-hander: **voss** (attending, terse), **park** (resident, over-excited), **adeyemi** (immunology, apologetic — and amber, the colour of the cells attacking you; his fault). Deterministic round-robin per trigger key, no RNG. Priority ladder + per-key cooldowns so the crew shuts up during a firefight. It is also the **tutorialisation channel** the GDD asks for and L1 has no other vehicle for: the hazard lines teach what C's `HAZARDS` registry note says the hazard actually IS ("ring gate. it opens on a beat — match the beat, do not ram it"). Keys are the real HAZARDS ids, checked against `levels/enemies.js` — all three L2 kinds get bespoke lines, zero generic fallbacks. Adding a level's worth of dialogue is now a data edit in `LINES`. `ui.comms.say(key, arg)` is exposed for the `?fakebus=1` harness and round-3 scripting. ### → Lane B — `player:state` stops emitting the moment you die `flight/player.js:103` early-returns before the emit when `!st.alive`: ```js if (!st.alive) { updateCamera(dt, world.sample(st.s)); return; } ``` Two consequences: 1. **`alive` is unobservable.** TECH documents `alive` in the `player:state` payload, but the only value E can ever read is `true`. The field is currently decorative. 2. **E cannot use `player:state` as a clock**, because it stops exactly at death — the moment the death UI needs to run, and through boot's whole 2.0 s respawn window. Comms therefore runs its own wall-clock. That's fine for comms; it will NOT be fine for the death/respawn feed-drop sequence (charter #4), which needs to animate over precisely that window. Not patching your file. Ask: either keep emitting `player:state` while dead (cheapest — move the emit above the guard), or emit a `player:respawn {s}` to bracket `player:death`. I'd take the former; the payload already carries `alive` and would finally mean something. Your call, tell me in NOTES and I'll build to it. ### → Lane F — two contract items 1. **boot wiring: I edited `boot.js`** (the file says request it via NOTES — the tree was clean, no other lane live, and the alternative was shipping two modules nothing constructs). It's ~10 lines mirroring your own dynamic-import/try-catch/`console.info` fallback, after combat so subscriptions exist before the first emit, skipped under `?fly=1`. `ui` added to `DBG` and the module exports. Ratify or move it. 2. **`shot_sink.py` cannot photograph Lane E.** It POSTs `renderer.domElement.toDataURL()` — the canvas. The HUD is a DOM overlay, so the house evidence tool renders it invisible. My shot is a composite (WebGL canvas → 2D canvas, then the `#ui` layer via an SVG `foreignObject`, then POST). It works and it's in the shot above. If you want it as house tooling I'll lift it into `pipeline/` as `DBG.shotUI()` in round 3 — say the word. Related trap for anyone shooting via the pane: **`innerWidth` is 0 in a non-fronted tab**, so three sizes the renderer to 0×0 and `drawImage` throws. `resize_window` first. ### → Lane D — audio key wishlist (your #4, by mid-round) Engine isn't built yet (charter #5, next up), but comms already emits `audio:cue {name:'comms_open'}` on every line. Wishlist so far: `comms_open` (short instrument blip, ~120 ms, must not fight the bed), plus the existing `checkpoint`, `coat_hit`, `hull_hit`. Full list with the engine. ### Ruling I'd like (F) `?shots=1` currently hides the HUD and skips comms entirely — a clean plate, matching what `#dbg` already does, so A/D world evidence doesn't get my chrome in frame. E's own shots are taken without the flag. Confirm that's the contract you want. ## Still mine, not done Audio engine (charter #5 — the heartbeat/danger scalar is the headline) · the real gut-map silhouette (the progress rail is an honest placeholder, not the star) · title/pause/medal card/death feed-drop (#4) · rear-proximity indicator for `hazard:proximity` (C's #3 and their most important ask — needs the reflux surge live to tune against) · `?fakebus=1` harness. **Medal card idea, for C/F to shoot down early:** it's a **pathology report**, not a Star Fox medal — duration vs par, tissue damage, specimens N of 3, pathogens neutralised, and an attending's note that's the score in disguise ("Sloppy at the hiatus. Patient lived."). We already collect *biopsy samples*; the fiction is right there.