PROCITY/docs/LANES
m3ultra 488067004c Lane C R28: audioEmitter — the till rings from the counter; the panner was inert
R28 ledger #3. My own idea, parked since R7. Brief stated acceptance only, so I scoped it.

THE TRAP MY OWN v3.0 NOTE SET: it said "userData.audioEmitter = musicKey so Lane B can
position/spatialise the bed". Both halves wrong. (1) Shape: the engine holds no reference to
the room group and would traverse a scene it cannot reach — emitters belong on room.audio as
data, riding the EXISTING playInterior() call (no lifecycle, no traverse, no dispose hook).
(2) Method: "spatialise" invites a PannerNode. NOTHING in this tree sets ctx.listener (zero
hits), so a panner resolves against a listener frozen at (0,0,0) — which, because rooms are
built room-local at the origin, is the room's own CENTRE, forever. Measured, OfflineAudioContext,
real pub stage bed:
    panner, listener never set (the engine as it SHIPS): RMS 0.106905 door / 0.106905 stage
                                                          -> ratio 1.0000, bit-identical
    panner + listener tracking the player:                RMS 0.055665 / 0.500000 -> 8.98x
It plays, throws nothing, warns nothing, and never changes by one sample as you cross the room
— while failing at the only thing it exists to do. "Routed through a panner?" yes. "Audible in
a venue?" yes. "In a shop?" yes. All green, all worthless.
-> ASSERT THE DELTA (gain at door != gain at stage), NEVER THE PRESENCE. Vacuous-gate law, 4th
application — and this one had no author to blame but me.
The house idiom was already right: tram/spill/gig-spill are all hand-rolled distance-gains vs
PROCITY.camera.position. No listener, no panner.

SHIPPED (C's files only):
- room.audio.emitters {stage?, counter?} — room-local, 3dp, 18/18 same-seed deep-equal. `r`
  (reach) is the ROOM DIAGONAL, not a constant: measured diagonals 9.81-15.63m, and scaling to
  the room holds door->stage proximity in a 0.42-0.59 band from a pokey band_room to a hall pub.
  `floor` is the room-filling residue, never 0 — a PA fills a pub; what changes as you walk in
  is the BALANCE, not the presence. Swing 2.65-4.52 dB (John R20: subtle changes are great).
- THE TILL RINGS FROM THE COUNTER — audible positioning in a normal shop with NO ENGINE CHANGE,
  via B's already-public playSfx(key,{gain}): C does its own distance math, hands B a scalar.
  Measured through the real BUY button, real record shop: 0.9489 @0.60m vs 0.6436 @4.19m =
  3.37 dB; negative control (no emitters) fires at exactly 1.0. sfx-till.ogg has been on disk
  since 15 Jul and had NEVER ONCE PLAYED. Routing, not content — as the brief said.
- ?mute=1 now actually silences the crate riffle (below).

WHY THE VENUE HALF IS AN ASK: a one-shot resolves its gain once, at fire time, from a position C
already knows. A bed must be re-gained every frame inside the engine's update() loop — B's file.
Structural, not political. B has a ~12-line paste-ready diff in the house idiom; audio.js
untouched. The letter of "consulted not modified" could have been met by reaching through B's
exposed state.layers diag to rewire its graph from outside — that backdoor is strictly worse
than the edit it avoids. Refused.

TWO BUGS FOUND:
- F DROPS EMITTERS ON THE ONE NIGHT THEY MATTER. interior_mode.js:289 rebuilds the spec on a gig
  night ({musicKey: ra.gigKey, toneKey: WALLA_KEY}) and every unnamed field dies. Measured on a
  real gig-night pub: quietNight_emittersSurvive TRUE, gigNight_emittersSurvive FALSE. Silent,
  fail-soft, no error. -> F: don't just spread `ra`; pass emitters DELIBERATELY, gig-night only —
  on a quiet night the radio + room-tone genuinely ARE room-filling.
- ?mute=1 NEVER SILENCED THE RIFFLE (R5->R28). dig.js opened a SECOND, private AudioContext
  straight to destination, breaking both stated house laws (ONE AudioContext; mute forces
  silence). It survived three epochs because NO GATE ASSERTS MUTE => SILENCE: the engine returns
  its silent surface and looks honest from its own side, while the sound came from somewhere it
  never knew existed. A gate that asks the engine whether it is muted can only ever answer yes.
  Fixed via B's PUBLIC .muted getter (consulted, not modified), URL fallback when standalone.
  Measured with a positive control so the probe provably CAN see sound: live 1 ctx / 1 source;
  muted 0 / 0. Blips stay procedural on purpose — zero-fetch, deterministic, still work under
  ?noassets=1 where a sampled riffle cannot. Only mute was broken; only mute was fixed.
  -> F: assert SILENCE, not muted-state.

HARNESS HONESTY: the first till rig reported the same clean 3.37 dB — from a CONTAMINATED rig
(createDig appends a panel per call, close() doesn't remove it, so querySelector clicked trial
1's stale button every time). Tell: panelUp false on all three, and the NEGATIVE CONTROL
returning 0.6436 where it must return 1.0. The gains matched the formula exactly; I refused them
anyway and re-ran isolated (panelCount 1, panelUp true, control 1.0). Never report a number from
a rig you have watched lie — even when you like the number.

QA GREEN 6/0/0/0. Docs: LANE_C_AUDIO.md -> v3.1 (contract + both asks + every measurement).
2026-07-17 17:39:54 +10:00
..
FABLE_TO_LANE_G.md Fable (integrator): response to Lane G — Draco ruling (no-Draco depot), density ruling, bug triage, G2/G3 sequence 2026-07-16 20:34:30 +10:00
LANE_A_CITYGEN.md PROCITY scaffold: spec, research, 6 Opus lane prompts, core modules, vendored three r175, 69 inherited skins 2026-07-14 10:46:40 +10:00
LANE_A_NOTES.md Lane A R27 wave 5: THE FACADE FIX — it was every town, not just the real ones (the covenant amended) 2026-07-17 16:28:20 +10:00
LANE_B_NOTES.md Lane B R28 (v5.1): the awning fabric ripple — KILLED with the measurement 2026-07-17 17:29:39 +10:00
LANE_B_STREETSCAPE.md PROCITY scaffold: spec, research, 6 Opus lane prompts, core modules, vendored three r175, 69 inherited skins 2026-07-14 10:46:40 +10:00
LANE_C_AUDIO.md Lane C R28: audioEmitter — the till rings from the counter; the panner was inert 2026-07-17 17:39:54 +10:00
LANE_C_GLB_VALIDATION.md Lane C R5 C3: re-measure interiors after Lane E's hero-prop bake 2026-07-14 21:16:15 +10:00
LANE_C_INTERIORS.md PROCITY scaffold: spec, research, 6 Opus lane prompts, core modules, vendored three r175, 69 inherited skins 2026-07-14 10:46:40 +10:00
LANE_C_NOTES.md Lane C round-9: draw-headroom note for D's browser rigs (F1 handoff) 2026-07-15 09:57:55 +10:00
LANE_C_PUB.md Lane C R27 (v5.0): the tier-2 seam ruling + LANE_C_PUB v5-FROZEN (ledgers #2, #6) 2026-07-17 13:53:02 +10:00
LANE_D_CITIZENS.md PROCITY scaffold: spec, research, 6 Opus lane prompts, core modules, vendored three r175, 69 inherited skins 2026-07-14 10:46:40 +10:00
LANE_D_NOTES.md Lane D R28 (v5.1): instrument LOD — KILLED with the measurement (ledger #4) 2026-07-17 17:21:34 +10:00
LANE_E_ASSETS.md PROCITY scaffold: spec, research, 6 Opus lane prompts, core modules, vendored three r175, 69 inherited skins 2026-07-14 10:46:40 +10:00
LANE_E_NOTES.md Lane E R28 (v5.1): Spike 1 — look.glb shipped; lean does not exist (ledger #1) 2026-07-17 17:35:17 +10:00
LANE_F_INTEGRATION.md PROCITY scaffold: spec, research, 6 Opus lane prompts, core modules, vendored three r175, 69 inherited skins 2026-07-14 10:46:40 +10:00
LANE_F_NOTES.md Lane F R27 (v5.0): the covenant re-pinned, the frame that took five tries, QA GREEN 2026-07-17 16:48:22 +10:00
LANE_G_GODVERSE.md Lane G (GODVERSE, ultra) R1: real-shop census adapter — 18 real Newtown shops on the real road graph 2026-07-16 20:19:14 +10:00
ROUND3_INSTRUCTIONS.md Lane F R5 start: archive R3/R4 instruction claims + v2 flags table + v1.1 watch 2026-07-14 20:48:19 +10:00
ROUND4_INSTRUCTIONS.md Lane F R5 start: archive R3/R4 instruction claims + v2 flags table + v1.1 watch 2026-07-14 20:48:19 +10:00
ROUND5_INSTRUCTIONS.md Fable (integrator): round-6 lane instructions — finish v2 wiring + pay review debts (A plansrc carried, F enforcement harness, C draw batching, orphaned assets) 2026-07-14 22:21:31 +10:00
ROUND6_INSTRUCTIONS.md Fable (integrator): round-7 lane instructions — roster default-on flip + GODVERSE real stock + weather + strict harness 2026-07-14 23:53:54 +10:00
ROUND7_INSTRUCTIONS.md Fable (integrator): round-8 lane instructions — catch-up (A/B carried) + the town comes alive (patronage, buy loop, weather, pack breadth) 2026-07-15 02:06:34 +10:00
ROUND8_INSTRUCTIONS.md Fable (integrator): round-9 lane instructions — the v2.0 ship round (interior presence, buy-anywhere, tram, tour, docs freeze) 2026-07-15 09:16:59 +10:00
ROUND9_INSTRUCTIONS.md Fable (integrator): round-9 lane instructions — the v2.0 ship round (interior presence, buy-anywhere, tram, tour, docs freeze) 2026-07-15 09:16:59 +10:00
ROUND10_INSTRUCTIONS.md Fable (integrator): round-10 instructions — interior giant-rig blocker, v2.0 tag pulled 2026-07-15 12:12:55 +10:00
ROUND11_INSTRUCTIONS.md Fable (integrator): v2.0 shipped; round-11 instructions — the audio round 2026-07-15 14:08:32 +10:00
ROUND12_INSTRUCTIONS.md Fable (integrator): round-12 instructions — v3.0-alpha, one pub end-to-end 2026-07-15 17:32:34 +10:00
ROUND13_INSTRUCTIONS.md Fable (integrator): round-13 instructions — v3.0-beta, the district 2026-07-15 21:30:01 +10:00
ROUND14_INSTRUCTIONS.md Fable: R14 kickoff rulings recorded (push done, flag stays opt-in, genres final) + gitignore local session files 2026-07-16 00:59:42 +10:00
ROUND15_INSTRUCTIONS.md Fable (integrator): round-15 instructions — close the v3.0 release (F's carried brief + poster-face fix + amp fix) 2026-07-16 09:21:39 +10:00
ROUND16_INSTRUCTIONS.md Fable (integrator): round-16 instructions — v3.1 THE FLIP (defaults on, classic covenant, drummer sits, town-wide pools) 2026-07-16 12:01:26 +10:00
ROUND17_INSTRUCTIONS.md Fable: R17 kickoff rulings — v4 = THE REAL MAP (John), Overpass fetch authorized 2026-07-16 14:05:50 +10:00
ROUND18_INSTRUCTIONS.md Fable (integrator): v4 REAL MAP charter + round-18 instructions — v4.0-alpha REAL ROADS (katoomba_real) 2026-07-16 15:29:10 +10:00
ROUND19_INSTRUCTIONS.md Fable (integrator): round-19 instructions — the v4.0-alpha close (fragmentation ruling, BIG_CITY fix, the gate) 2026-07-16 17:06:18 +10:00
ROUND20_INSTRUCTIONS.md Fable: R20 kickoff ruling — density widening approved (John), directive: subtle, texture not takeover 2026-07-16 18:14:53 +10:00
ROUND21_INSTRUCTIONS.md Fable (integrator): round-21 instructions — the v4.0-beta close (venue cluster bias, selector index, density soak, the gate) 2026-07-16 20:14:39 +10:00
ROUND22_INSTRUCTIONS.md Fable (integrator): round-22 instructions — v4.0 THE EPOCH CLOSE (tri diet first, pack absorb, release tour, G items) 2026-07-16 21:44:03 +10:00
ROUND23_INSTRUCTIONS.md Fable (integrator): v5 THE REAL SHOP charter + round-23 instructions — v5.0-alpha THE FIRST REAL CRATE 2026-07-16 22:48:59 +10:00
ROUND24_INSTRUCTIONS.md Fable (integrator): round-24 instructions — the alpha completion (contract fix, identity field, redhill, honest gates) + two new laws 2026-07-17 00:21:51 +10:00
ROUND25_INSTRUCTIONS.md Fable (integrator): round-25 instructions — the tag, earned (sweep vs Ruling 2, licence line, sku ids, F closes) 2026-07-17 02:14:02 +10:00
ROUND26_INSTRUCTIONS.md Fable (integrator): R26 wave 4 — the mint-id ruling (prefixes are namespace fences); C one line, E one line, F tags 2026-07-17 11:49:38 +10:00
ROUND27_INSTRUCTIONS.md Fable (integrator): R27 wave-5 — THE SPEC RULING (facade = +Z, B's canon canonical); A one-commit fix+pins+cross-convention gate; F re-gates and tags 2026-07-17 16:01:31 +10:00
ROUND28_INSTRUCTIONS.md Fable (integrator): round-28 instructions — THE SPIKE AND THE SWEEP (spike 1 + parked polish, tag v5.1) 2026-07-17 17:07:52 +10:00