# Lane C (Levels & Encounters) — progress ## 2026-07-16 — Round 1: the data spine + the vertical slice Landed: - **Schema v1 ratified** (TECH.md §Level data schema, C-owned from here). Additive over F's v0: `schema`, `par`, `next`, segment `name`, cross-section placement (`theta`/`rho`, rho as a *fraction* of the safe radius), group `spread`, zone `span`, `pickup`/`gate` event types, hazard params. STUB_LEVEL synced to v1 (only that const in F's file, per ROUND1 §Lane C.1). - **`levels/index.js`** — registry + loader (node + browser, no THREE), **schema selfcheck** (real; qa.sh's `--selfcheck` hook is now live) and a **pacing simulator** (`--sim`). The selfcheck consumes the other lanes' contracts live: A's `world/biomes.js` for biome ids and `wave.amp + wave.breathe`, A's `SKIN`, B's `flight/tuning.js` hull radius, B's `combat/balance.js` for scores. C's registry owns composition and mirrors nothing. - **`levels/enemies.js`** — enemy catalogue (fiction id → archetype) + pickup/hazard vocab. - **`levels/difficulty.js`** — the single difficulty table + `applyDifficulty()` (authored, not yet validated against play). - **`L2_esophagus.json`** — the vertical slice, complete: 3600 units, 7 beats, 47 events, 65 enemies, 10 checkpoints, 3 samples, reflux-surge finale. `L1_mouth` / `L3_stomach` skeletons (shape only, flagged SKELETON — the selfcheck downgrades content laws for them). - **GDD refined in place** (bannered): per-level time targets replacing a flat "6–10 min", esophagus roster, L2's three real constrictions as its setpieces. - **Boss specs** (Guardian / Tapeworm / Blockage) as one-pagers in NOTES — phases, telegraphs, windows, failure pressure. Deliberately three *different* pressures: coat race, distance race, hull attrition + doom timer. Verification (measured, `node web/js/levels/index.js --selfcheck|--sim`; qa.sh GREEN): - selfcheck **3/3 valid, exit 0**; 6 warnings, all expected (skeletons undesigned, L4 not yet registered). - L2 pressure curve **0.27 → 2.14 → 4.35 → 0.69 → 4.53 → 6.35 → 4.40** (breather → pressure → spike → breather → pressure → peak → finale). - L2 par 3:30 against a measured **2:47 speedrun / 3:19 par-pace / 4:22 timid** run; par.score 9000 of a 9400 kill budget (95%), computed from B's scores. - All 10 checkpoint gaps within the ≤30 s death-cost law (max 28.8 s). Min clearance 2.73 at the hiatus, against C's 2.5 floor. - Booted `?stub=1&dbg=1` after the STUB_LEVEL edit: tube renders, zero console errors, and the v1 module builds a valid world (`length 400`, `wallRho(0,0) = 8.5`, centre-line collide `null`). **`world.hash()` is byte-identical before and after my edit (`1bdf001`)** — the sync adds data fields only and provably does not move the geometry, so F's round-0 shot still stands. No screenshot committed: it would be pixel-identical to round 0's, and per charter a data lane's evidence is the pacing report, not a picture of an unchanged tube. (No fps claim: the preview pane throttles rAF in the background — `rafTicks: 0` — so framerate is unmeasurable here. Not a code fault; the render path is fine.) Two contract collisions found and resolved (detail in NOTES): - **Biome ids** — I had authored `mouth`/`pharynx`/`cardia`/`pylorus`; A's registry has six canonical ids and rejected all four. A is right: biome = look, `segments[].name` = anatomy. Conformed, and the constraint paid for itself (the cardia keeping the esophagus palette is why the acid sea reveals itself in colour). - **Balance ownership** — my first `enemies.js` restated hp/size/speed/score that B already owns in `combat/balance.js`. Cut to a join table; `index.js` reads B's scores instead. Caught live: A raised esophagus `wave.amp` 0.9 → 1.4 mid-session, which made the diaphragmatic hiatus unflyable (2.33 free radius vs the 2.5 floor). Widened 6.5 → 6.8. The invariant did its job on my own level twice — the aortic constriction also failed its first draft (radius 7, symmetric squeeze) and became radius 9 with a *directional* squeeze. Not done / next round: no in-engine flythrough — `?stub=1&lvl=` does not compose yet (snippet offered to F) and the stub is single-segment, so it could only ever render beat 1. L2's pacing evidence is a kinematic **model**, not a playtest: it proves the level is flyable, paced and survivable; it cannot prove the hiatus *feels* good. That needs A's world + B's controller in round 2 — and if one thing gets playtested, it should be s 2600–3000.