The Phase-1 debt was 'verified by ear: NOTHING'. I still can't hear, so this
lane builds the instrument that lets someone who can tell me what's wrong, and
makes their answer a diff instead of a conversation.
- TechnoEngine drives every voice from the live TrackMix and the arc, instead of
module consts. Behaviour-identical at DEFAULT_MIX (verified constant by
constant). Voices whose effective gain rounds to silence are skipped, not
clamped — at 9PM the bass builds zero nodes rather than ~8/sec of silence.
setMixValue quantises integer paths, so what formatMix dumps is what played.
- MixDeskScene: solo/mute per voice with a per-voice listening prompt, every
mix param on log-mapped sliders, an arc scrubber (audition 1AM at 9PM), and
DUMP MIX -> a pasteable TrackMix literal. Restores the arc pin and solo state
it found on close, rather than forcing a default — the demo deliberately pins
PEAK and the desk was silently un-tuning it.
- Ambience: rain outside, crowd murmur inside, kebab-shop fluoro hum. On the SFX
bus, not the music lowpass — that filter models the PA being behind a wall,
and rain is not behind anything. Headcount comes off door:verdict admits and
floor:ejection, NOT door:clicker: the clicker is the player's claimed count and
its divergence from reality is the mechanic, so the room would sound like the
lie. Verified live: 120 + 2 admits - 1 ejection = 121, clicker ignored.
- JuiceDemoScene pins the arc at PEAK on entry. GameClock runs 360 game-min in
13 real min, so an unpinned demo opens on kick+hat and anyone judging the bass
would conclude it's broken.
- Phone thread scrolls with visible-window culling and a binary-searched range,
a history cap, and a 'new below' cue when a text lands off-screen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Audio (src/audio/), raw WebAudio, no samples or libraries:
- TechnoEngine: 128 BPM four-on-the-floor kick, off-beat hats, 2-bar 16th
bassline, 8-bar pad. Look-ahead scheduler (25ms timer, 100ms horizon) is the
beat authority — emits beat:tick with the SCHEDULED audio time, so consumers
can compare honestly. Replaces core/StubBeatClock at integration; same event.
Stale beats are resynced to the next downbeat rather than caught up: a
throttled/hidden tab otherwise dumps a 64-beat backlog onto one sample.
Music runs through the location lowpass; SFX bypass it and stay crisp.
- Sfx: 10 procedural one-shots + rain bed, one shared noise buffer, voices
self-disconnect on ended so a six-hour night doesn't accumulate nodes.
UI (src/ui/), reusable Phaser containers, no door/floor imports:
- Stamp (the signature interaction), Phone (Dazza thread + phoneTheatre),
DialogueBox (typed-out, drunk-typo render), Clicker (digit roll),
MeterHud (neon vibe / crowd-temp aggro / hype badge / 3 heat slots).
- JuiceDemoScene exercises every widget and SFX, with a log-mapped cutoff
slider and a DOOR/FLOOR toggle that routes through the bus.
Verified in-browser: the door->floor sweep ramps 250Hz->18kHz over 600ms,
monotonic and exponential (halfway lands ~2.1kHz, not the ~9kHz a linear ramp
would give) — that late bloom is what sells the door opening. Under a real
hidden tab, 52 consecutive beats scheduled with zero in the past, 75-98ms lead,
max one beat per wake.
main.ts touched to route J / #juice to the demo — outside lane ownership,
flagged for sign-off in LANEHANDOVER.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Testable-in-node math extracted ahead of the WebAudio/Phaser layers:
- audio/scheduling.ts: look-ahead beat grid (dueBeats never repeats or skips a
beat however ragged the timer wakes; burst-capped for suspended tabs)
- audio/filterCurve.ts: the location filter's exponential cutoff ramp — the
door-opening sweep, in frequency-space so it blooms late like a real door
- ui/style.ts: chunky pixel widget kit sharing the doll PALETTE
- ui/typo.ts: deterministic drunk-typo/typing/wobble renderer (seeded, no
Math.random)
- ui/juiceEvents.ts: EventMap extensions via declaration merging, so
door:phoneTheatre types correctly without editing frozen data/types.ts.
TODO(contract) — CONTRACT CHANGE REQUEST filed in LANEHANDOVER.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>