Memory Cinema storm color/shape overhaul (the crown-jewel pillar):
- Fix the white-out root cause: emissiveNode was NEVER set, so the selective
MRT bloom had no color to bloom and washed the frame white. Route the shared
iridescent rainbow to BOTH colorNode and emissiveNode.
- Rim glow (fresnel-style): bright glowing edges, dim readable center — the
shareable luminous-shell / hollow-torus look.
- Morphing geometry: the home target cycles sphere → torus → galaxy spiral →
cube lattice → wave sheet, drifting continuously and snapping per beat.
- Hyper-saturated full-spectrum palette (per-particle phase + radial shells +
spatial bands + time) so the whole rainbow is present at once.
- Spread the initial spawn across a wide hollow shell (was a tiny dense ball
that boot-flashed white).
- Act/beat-aware brightness: beats 0/1 fade in soft, Act I held calm, Acts
II/III blaze at full. No white-out regressions.
Gate: svelte-check 0/0, 937/937 tests pass (cinema auteur/pathfinder green),
verified live in browser.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Root cause: layoutPositions grew per beat (radius 22 + i*6), so each beat sat
farther out; the camera + storm marched off into space as the tour progressed.
Fix (centered-by-construction):
- layoutPositions: tight BOUNDED golden-angle shell (SHELL_RADIUS 14), no growth.
- sandbox: storm pinned to the WORLD ORIGIN permanently; camera hard-clamped to
an 18-46 unit distance band and always lookAt(origin); containment sphere
sized to the FOV at origin. A runaway move is corrected every frame.
- director: new centerOnOrigin mode (enabled when WebGPU active) — frames/orbits
the origin instead of flying to scattered nodes; variety from angle/standoff.
No path remains for the subject to leave frame. 937 tests + build green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
director.ts: optional shots:ResolvedShot[] in DirectorOptions; per-beat
flight/dwell timing; framePosition now reads move (push_in/pull_back/crane
scale standoff) + angle (low=look-up, high=look-down) + standoff; orbit shots
revolve the camera during dwell; Dutch roll via camera.up; hard/match cuts
snap (editorial cut). With NO shots the camera is byte-identical to before
(all values fall back to the existing constants + easeInOutCubic lerp).
MemoryCinema.svelte: build computeSignals + planShotsDeterministic + resolveShots
on launch, pass shots to the director; onBeat drives storm mode + director's
note + Act + tension from the shot. New UI: pre-roll DIRECTOR'S PLAN card
(logline naming real memories), per-beat 'why this shot' note, Act I/II/III
badge, tension-tinted progress bar, Auteur source badge.
The deterministic auteur ships the hero film with zero LLM. 937 tests + build green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
storm.ts (blockers): correct particle position wiring — positionNode now
instancePos.add(positionLocal) (bare storage element collapsed every quad to a
point); serialize GPU compute dispatches (computeInFlight) to stop queue
stalls; ignition floor so the storm never fades to black; null buffers on
dispose for GC (StorageBufferAttribute has no dispose()); typed computeNode +
InstancedMesh, removed unsafe casts.
narrator.ts: validate + filter backend beats, bounds-safe fallback merge,
KIND_CHIP satisfies (compile-time enum coverage), chip type guard, timer cleanup.
MemoryCinema.svelte: replace the null-returning Local AI stub with a real
on-device transformers.js text-generation pipeline (+ genuine fallback);
Escape-to-close + autofocus a11y; reset all run state on launch (no stale
Replay); fix render/close race; computed fallback camera aspect; typed state.
director.ts: NaN-guard progress on empty path; clamp dt >= 0.
sandbox.ts: guard three/webgpu exports + tsl pass() API shape; resize w/h floor.
926 tests + build green. Net: every audit blocker/high/medium fixed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>