Go to file
type-two 83c30bf344 [lane E] The instrument exists: a HUD, and a surgical team who talk to you
#ui had been an empty div since round 0 — E never ran. It has an owner now.

HUD (charter #1): coat/hull, heat, torpedo pips, speed/flow/throttle, boost,
score, combo, biome + segment name, and a 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, so the HUD 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 — on nobody's list. Argued for, then 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 turned out to be more than flavour: it is 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 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 rather than guessed — all three L2 kinds get bespoke lines,
zero generic fallbacks. A level's worth of dialogue is now a data edit in LINES.

Three defects, all mine, all found by the stepped sim, none visible to the eye:
- The progress rail was dead. I read `level.length` — a field that does not
  exist. The level carries segments, not a total. It now uses the runtime
  world.length that B already divides into p.progress.
- My clock was fiction. Comms counted `+= 0.1` per timer tick and called it
  seconds; a backgrounded tab throttles setTimeout to ~1s, so lines held ~10x too
  long. It now reads performance.now().
- Every hazard warning had the LOWEST priority in the game. PRI has a key `warn`,
  but say() is called with `warn_reflux_surge`, so PRI[key] was undefined and
  fell through to the default of 1 — the surge screaming "GO. GO." could be
  talked over by park admiring a specimen. Keys now resolve exact-then-family.
  The evidence shot IS the fix: same seed, same frame, the warning now sits where
  the checkpoint line used to be.

### -> Lane B — player:state stops emitting the moment you die

player.js:103 early-returns before the emit when !st.alive. So `alive` is
unobservable (E can only ever read true — the field is currently decorative), and
E cannot use player:state as a clock, because it stops exactly when the death UI
needs to run and through boot's whole 2.0s respawn window. Comms works around it
with its own wall-clock. The death/respawn feed-drop (charter #4) will not be
able to. Ask is in NOTES; not patching your file.

### -> Lane F — two contract items

I edited boot.js (~10 lines mirroring your own dynamic-import/try-catch/
console.info fallback) because #ui needed an owner and two modules nothing
constructs aren't worth much. Ratify or move it. Second: shot_sink.py cannot
photograph Lane E — it POSTs renderer.domElement.toDataURL(), and the HUD is a
DOM overlay, so the house evidence tool renders it invisible. This shot is a
composite (canvas -> 2D canvas, then #ui via an SVG foreignObject). Offer to lift
it into pipeline/ as DBG.shotUI() stands.

qa GREEN. Evidence: docs/shots/laneE/round2_hud_aortic.webp (s=1111, seed 7, live
hazard warn + x6 chain). Dev server guts-e on 8146.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 23:01:40 +10:00
.claude [lane E] The instrument exists: a HUD, and a surgical team who talk to you 2026-07-17 23:01:40 +10:00
docs [lane E] The instrument exists: a HUD, and a surgical team who talk to you 2026-07-17 23:01:40 +10:00
pipeline [lane A] MODELBEAST dresses the molecules: 5 matcaps, and the canal picks space-filling 2026-07-16 21:31:24 +10:00
tools [lane A] Complete the biome texture set (oral + colon) + a provenance gate 2026-07-16 17:44:58 +10:00
web [lane E] The instrument exists: a HUD, and a surgical team who talk to you 2026-07-17 23:01:40 +10:00
.gitignore [lane A] The swept room + the acid sea, built — and it corrected me four times 2026-07-16 18:04:16 +10:00
README.md [lane F] Round 0 scaffold: docs, contracts, lane charters, bootable stub world 2026-07-16 01:28:35 +10:00

GUTS — a fantastic voyage through the alimentary canal

Browser flight-combat game (three.js, zero build step). You pilot ENDO-1, a microscopic probe, mouth → rectum through five anatomically-grounded biomes: ride peristalsis down the esophagus, cross the acid sea of the stomach, thread the villi forest of the small intestine, survive the gas swamps of the colon. Fantastic Voyage × Star Fox × Descent.

Run it

cd web && python3 -m http.server 8140
# http://localhost:8140            — the game
# http://localhost:8140/?stub=1&dbg=1  — stub world + debug HUD (works from day 0)

No bundler, no npm, no build. ES modules + import map; three.js r175 vendored in web/vendor/ (never CDN — the game must run offline). Before you finish a session: bash tools/qa.sh.

The one-paragraph tech pitch

The whole canal is a spline. World position is (s, θ, ρ) — distance along the canal, angle and radius in the cross-section. Tube walls are chunked extrusions along parallel-transport frames; peristalsis and breathing are vertex-shader displacement (cheap, squishy, everywhere); collision is an analytic radius test (no physics engine). Caverns (mouth, stomach) switch the same controller to free 6DOF. Look is synthetic scanner — dark endoscope void, SEM-style monochrome walls with FLUX-generated detail textures, emissive-coded enemies. Everything is seeded + deterministic, and every asset is optional at runtime — the game boots and plays asset-free with procedural fallbacks.

Hard laws (all lanes)

  1. Determinism. No Math.random outside js/core/rng.js. Seeded RNG only. qa.sh greps.
  2. Assets are optional. Missing texture/model/audio ⇒ procedural fallback, never a crash.
  3. Eyeball everything. Visual work isn't done until a screenshot is in docs/shots/laneX/.
  4. Perf budget: ≤300 draw calls, 60 fps on M-series / mid laptop. Measure via window.DBG.
  5. Free-first. Local MODELBEAST generation before any paid API; fal.ai is a gated fallback (John's go). See PIPELINE.md.
  6. Git: stage only your exact paths, commit + push each session, never git add ..

Deploy

Target: partly.party (static). Not wired yet — when it's time, consult the deploy-map skill and run ship-check first. Origin: ssh://git@100.71.119.27:222/monster/guts.git.