vestige/docs/MEMORY_CINEMA.md
Sam Valladares 9e92a5999a fix(cinema): back-pressure the frame loop — kill parallax lag
The loop fired requestAnimationFrame immediately and never awaited render(); with
150k particles + compute + bloom a frame can exceed 16ms, so rAF callbacks queued
faster than the GPU could drain them and the camera/parallax visibly lagged behind
the cursor. Now AWAIT sb.render(dt) before scheduling the next frame → the loop is
capped to real GPU throughput, every frame reflects the latest pointer position,
no backlog. Also snappier active-steer damping (lam 3.5→9, ~110ms converge) so
input feels immediate; idle glide-home unchanged. renderFailures resets on success.

Plus docs/MEMORY_CINEMA.md — complete feature reference for the cinema engine.

Gate: svelte-check 0/0, 937 tests, verified live (parallax tracks cursor, no lag).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 15:12:28 -05:00

172 lines
9.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Memory Cinema — Complete Feature Reference
Memory Cinema turns your real memory graph into a directed, narrated, infinitely-
diving cinematic experience rendered as a 150,000-particle WebGPU compute storm.
It is the dashboard's signature pillar.
The whole thing is **dynamically imported only on launch** — the heavy WebGPU/TSL
bundles never load for normal dashboard use. It boots a **separate WebGPU canvas**
so the underlying WebGL graph (every current user's experience) is never touched —
zero regression by construction.
## Architecture — the 8 modules
| Module | Role |
|---|---|
| `pathfinder.ts` | Plans the narrative path through the real graph (a story, not a BFS dump) |
| `topology.ts` | Extracts graph signals (betweenness, contradictions, surprise, decay) |
| `auteur.ts` | The director's brain — a typed cinematography grammar + shot-plan contract |
| `narrator.ts` | Captions — 3-tier narration (LLM / local / deterministic) |
| `director.ts` | The camera runtime — executes the shot plan frame-by-frame |
| `sandbox.ts` | The isolated WebGPU stage — renderer, camera, selective bloom |
| `storm.ts` | The 150k-particle GPU compute storm — physics, geometry, color, immersion |
| `components/MemoryCinema.svelte` | The orchestration overlay — input, dream mode, UI |
## Tier 1 — the narrative path (`pathfinder.ts`)
The bulletproof core that always runs, using only the nodes + edges the backend
returns. It plans a story: start at the origin (focused memory) → visit its
strongest-weighted connections → detour to a contradiction edge if one exists
(tension = interesting) → end on a recently-created node ("where the mind is now").
Each stop is a beat with a `kind` (origin/connection/contradiction/recent/bridge/
surprise). Falls back to weighted BFS. No LLM, no WebGPU, no network — if
everything else fails this alone produces a coherent, watchable flythrough.
## Tier 2 — graph signal extraction (`topology.ts`)
Pure statistics over the real `/api/graph` data, computed once per launch:
- **Brandes betweenness centrality** — the most load-bearing memory (graph keystone)
- **Connected-component clustering**
- **Contradiction detection** + **merge/supersede detection**
- **Surprise score** (shared neighbors yet low edge weight = non-obvious link)
- **Recency rank**, **FSRS retention**, **suppression pressure**
## The Auteur — the director's brain (`auteur.ts`)
A real cinematography grammar applied to your memories. The director (LLM Tier-1 or
a deterministic rule table Tier-2) produces a `DirectorPlan`: typed `Shot`s, each
grounded in a real node and justified by a real metric.
- **Moves:** push_in, pull_back, orbit, crane, whip_pan, rack_focus, hold
- **Angles:** low = look up (power), high = look down (decay), eye
- **Cuts:** fly, hard_cut, match_cut
- **Per shot:** dutch roll, standoff, flight/dwell seconds, spring half-life,
intensity, tension (01)
- **Three acts** (I/II/III), an **emotional arc** (man_in_hole, rags_to_riches,
icarus, cinderella, oedipus, flat), a **caption tone**, a **score cue**
- A **required `why`** per shot citing the real graph metric
- **Carry-forward semantics:** sparse/half-hallucinated plans always resolve to a
coherent film.
## Narration (`narrator.ts`)
- **Tier 1:** backend LLM (`/api/narrative`) or opt-in on-device model (lazy-loaded
only when "Local AI" enabled; never downloads weights unprompted).
- **Tier 2:** deterministic structured captions from real data — instant, no network.
- **Tier 3:** can't fail — falls back to Tier 2.
- Optional voice via `speechSynthesis`; typewriter caption stream (instant under
reduced-motion).
## The 150k-particle storm (`storm.ts`)
150,000 particles whose physics run entirely on the GPU via Three Shading Language
compute nodes. One particle pool, one compute kernel, ~32 uniforms.
### The 7-beat world journey
Each beat is a unique world — particles aren't swapped, only the forces (uWorld
selects; uBlend crossfades over ~1s):
0 nebula mist (curl-noise flow) · 1 orbital anchor (cross-product spin) · 2 strange
attractor (Thomas) · 3 detonation void · 4 crystal lattice (voxel snap) · 5 fluid
galaxy (curl + swirl) · 6 phyllotaxis bloom (Vogel sunflower).
### The impossible-geometry form pack (dream worlds 711)
Forms nobody renders as living particles, mapped over a (u,v) manifold grid (387²)
so they read as a sculpted skin, not spaghetti:
7 supershape (3D superformula) · 8 CalabiYau (6D string-theory manifold, 4D→3D
projection; α rotates through the 4th dimension) · 9 Boy's surface (non-orientable
minimal immersion) · 10 Aizawa attractor shell · 11 gyroid↔Schwarz-D (triply-
periodic minimal surface morph). Inline complex-math + hyperbolics (sinh/cosh
expanded via exp; absent in three@0.172).
### Color
- Full-spectrum iridescent palette (per-particle phase + radial shells + spatial
bands + time + global drift).
- Per-world cosine (IQ) palettes — each world a distinct identity.
- **The Color Blast:** a long-lived uBlast envelope (~2.8s, decoupled from the fast
physics burst so color outlives the shockwave) drives an outward spectral-
dispersion wave (uBlastTime; prism order) over a blackbody ember core. Spectrum
dominates (reads rainbow, not white); capped at 0.6 mix.
- **Jarring inner/outer clash:** the nested figure and shell use opposing color
universes (ice↔fire, acid↔blood, gold↔violet, mint↔crimson, electric↔gold);
uClash cycles the pair every beat.
### 3D-within-3D nesting
~34% of particles form a second, smaller, counter-rotating figure (a different
world, ~52% scale) inside the outer shell — a figure within a figure.
### Anti-white-out / "solid" systems
- Rim glow (Fresnel): bright edges, dim readable center.
- Emissive routing: the rainbow goes to BOTH colorNode and emissiveNode (the
selective bloom reads emissive — the original white-out was an unset emissive).
- Hollow-shell spawn (the old tiny dense ball flashed white on frame 0).
- Act/beat-aware brightness (uActDim): beats 0/1 fade in soft, Acts II/III blaze.
### The immersion stack
- **Infinite Droste zoom** (uZoomPeriod/uLambda/uZoomOn): the cloud dives inward
forever. Two layers ride offset phases of fract(uTime/T); the outer grows
pow(λ, phase) then snaps back invisibly (λ=1.923=1/0.52 makes inner→outer exact);
the inner promotes by λ to become the next shell; a fresh inner spawns inside. A
sin(phase·π) seam cross-fade in rimFactor makes each layer transparent at its
snap → zero pop, seamless loop. Particle-space, not a camera dolly.
- **Velocity-stretch flythrough** (uCamVelView/uStreak/uMaxStretch): sprites stretch
along screen-space camera velocity into warp streaks; the camera clamp floor
relaxes (30→6) so it plunges inside the shell.
- **DOF + volumetric fog** (uFocus/uFocusRange/uDofDim/uFogDensity): off-focus
particles dim (bokeh under bloom) + exp-falloff fog tints the far field → 3D
atmospheric depth; rack-focus tracks the dive. All folded into a single depthFade
Fn (three@0.172 constraint: positionView may be read from only ONE Fn per
material output or the node-builder stack-overflows).
- **Interactive parallax** (overlay): pointer orbits, scroll/pinch zooms, damped;
composed onto the director's base pose; idle eases back to 0; the sandbox re-clamp
means framing can't break.
### Physics safety
Hard velocity clamp, strong damping, boundary snap, dt clamp, serialized compute
dispatches.
## Endless dream mode
When the 7-beat tour ends, instead of freezing it drops into an infinite generative
loop (`dreamBeat()` every ~5.5s): a fresh random procedural figure (worlds 711, new
uMorphSeed → never the same twice), uChaos ramps up so each is wilder than the last,
a random clash pair, full color blast, infinite zoom + flythrough on. Overlay shows
"∞ Dreaming." Never idle.
## The stage (`sandbox.ts`)
- Separate WebGPU renderer + scene + PerspectiveCamera (clamped to a safe distance
band, always lookAt(origin) → the storm can never leave frame).
- Selective MRT bloom — blooms only the emissive channel against a clean void; falls
back to a plain pass if MRT is unavailable on a driver.
- Per-frame camera-velocity tracking (one Vector3, zero compute) feeding the streak.
- Pass-throughs: setZoom, setStreak, setFlythrough, setCameraVel, setContainRadius.
## Overlay & UX (`MemoryCinema.svelte`)
- Fullscreen launch, staged status (idle → planning → playing → done).
- Pre-roll "Director's Plan" card (logline + arc).
- Live captions, beat chips, director's-note ("why," citing a real metric), act
indicator, tension sparkline, progress bar.
- WebGPU / Auteur / Live-captions badges; Voice + Local AI toggles.
- `H` hides all chrome for clean demo capture (faint restore hint; `body.cinema-open`
hides the graph page's stats pill; overlay z-index 200).
- Replay on completion.
- Graceful degradation: if WebGPU is unavailable or render fails 3× consecutively,
drops to camera-only (captions still play) — never stalls.
- Reduced-motion fully honored: no parallax listeners, zoom/flythrough/streak gated
off, jump-cuts instead of flights, instant captions.
## Protection contract
On the shared graph page, `<MemoryCinema>` is wrapped in a clearly-commented
`PROTECTED MEMORY CINEMA — DO NOT MODIFY` boundary so the graph-control overhaul and
the cinema engine stay visibly distinct.