# Handoff — 2026-05-02 (holo moonshot)

Long session. Built two plasma viewers from zero, plus the Tier 3 Rail-WASM substrate. Most work is uncommitted in `tools/plasma/`.

## Shipped this session

- **`tools/plasma/live4k.html`** (Tier 0) — WebGL2 viewer for the live beacon. Bicubic Catmull-Rom upsample (manual, Safari-safe via `texelFetch`), LIC strands over (Bx, By), vorticity-tinted hue, schlieren edges, magnetic glow, ACES tone-map + saturation stretch. Polls `https://ledatic.org/entropy/{pulse,frame/current}` every 2 s. Frame-pacing yield + DPR cap to prevent the GPU-queue-runaway lockup that bit us once mid-session.
- **`tools/plasma/holo.html`** (Moonshot) — WebGPU viewer with volumetric raymarched plasma in a real glass cylinder (Snell refraction, double Fresnel, static surface scratches), mirrored floor with reflection-raymarched second pass + caustic projection, engineering grid platform, MSAA 4× HDR pipeline, 96-tap golden-spiral bloom (gaussian-weighted, threshold-gated), live conservation diagnostics with sparklines + OK/WARN gates, audio synth from the 8 inline beacon metrics (drone + pad + sparkle + delay tail, bass-drop on t=π reset), camera presets (iso/front/side/top + 1-4 keys + double-click reset), auto-orbit when idle, picture-in-picture top-down 2D + B-field quiver overlay, 3D-anchored DOM annotations.
- **`tools/plasma/render.rail` + `render.wasm`** (Tier 3-A bootstrap) — Rail-WASM compute kernels: `vorticity`, `current_density`, `schlieren`, `total_kinetic_energy`, `total_magnetic_energy`, `max_divb`, `mean_vorticity`, `seed_ot`. Compiles native (`./rail_native run` produces correct OT IC metrics: KE=22755.56, ME=8192, |∇·B|=0, ⟨ω⟩≈machine-zero). Compiles to WASM (7818 bytes) via `tools/plasma/build_render_wasm.sh` which post-processes the WAT to add per-function exports — the Rail emitter only declares `memory` + `_start` by default, so the build script injects `(export "name" (func $name))` lines before `wat2wasm --enable-tail-call`. Installed `wabt` via brew during session.
- **`docs/plans/PLASMA_RAIL_WASM_RENDERER.md`** — full Tier 3 5-phase design doc (A bootstrap → B derived fields → C temporal LIC → D particles → E site integration).
- **Bench audit scripts** — `tools/train/honest_grade.sh` (triple-redundant compile-link grader closing the rail_native ld-exit-0 hole) + `tools/train/audit_dir.sh` (parallel batch grader). Drafted earlier in the session; not yet executed against any benched ckpt.
- **Site stage** — `holo.html` copied byte-identical to `~/projects/ledatic-site/holo.html` (66911 bytes), ready for `CF_TOKEN=$(cat ~/Desktop/rings) ./deploy.sh holo.html`.

## Findings

- **Safari WebGL2 won't filter float textures** without `OES_texture_float_linear`, and even with the extension, R32F on M-series silently nearest-samples. Workaround: manual bilinear / Catmull-Rom via `texelFetch` regardless of filter setting. Cost is small.
- **WebGPU r32float is `unfilterable-float`.** Linear sampler + r32float → silent black render (validation rejection invisible to user). r16float IS filterable; `Float16Array` does the f32→f16 conversion in JS with no manual bit math. Safari supports Float16Array on macOS Sequoia+.
- **`Math.pow` on certain Safari builds throws inside drawPiP** when fed our typed-array f32 values (silent) — replaced with `Math.sqrt` + binary tint. Always wrap per-pulse work in try/catch so a JS error can't kill the texture upload.
- **Volumetric MSAA**: `rgba16float` IS multisample-renderable on M-series. `resolveTarget` works fine with `storeOp: 'discard'` on the MS view.
- **Bloom artifacts come from sparse spiral kernels with low brightpass thresholds.** Each tap of a too-far-apart spiral produces a visible "ghost" of the bright source. Fix: high tap count (96+), tight radius (≤4% canvas), gaussian falloff, brightpass well above 1.0 so only HDR overshoot blooms.
- **Rail's WASM emitter declares ONLY memory + _start.** Per-function exports require WAT post-processing. mhd_wasm.rail's exports were added the same way — there's no first-class `@export` mechanism in compile.rail.
- **`fsqrt` (ARM64 native intrinsic) is NOT available in Rail's WASM target.** Use `sqrt` (which the WASM emitter routes to `f64.sqrt`).

## Blocked

- **#22 deploy holo to ledatic.org** — needs `CF_TOKEN=$(cat ~/Desktop/rings)`. The token file isn't on disk currently. Once user provides, run from `~/projects/ledatic-site`. Unblocks #8, #9, #11, #16, #23.
- **#13 Tier 3-B (JS glue for render.wasm)** — needs investigation of Rail's tagged-pointer i64 ABI. Specifically, how to construct a Rail-tagged i64 from JS that the kernel functions will accept as their `state: float_arr` argument. Read `compile.rail` for `tag_int`, `untag_int`, and the float_arr representation. Without this, JS can call the kernels but can't pass the state buffer.
- **#7 multi-witness consensus viz** — `ledatic.org/witness/<node>/latest` returns 404. Witness publisher exists in repo (commit `e251a75`) but isn't deployed/serving yet.
- **#14, #15** — chain-blocked by Tier 3-B.
- **#16** — chain-blocked by all of Tier 3 + deploy.
- **#10 daily posters** — out of single-session scope; best as a `/schedule` routine after deploy.

## Next-session P0

**Goal:** Get holo.html serving from ledatic.org and prove the live moonshot is production-grade end-to-end.

**Success criterion:** `curl -sI https://ledatic.org/holo` returns 200 and the page loads in Chrome + Safari + Firefox showing live plasma fed from `/entropy/frame/current`. Then schedule the cross-browser audit (#23) for 24h later.

**First step:**
```
ls ~/Desktop/rings || echo "need CF_TOKEN file at ~/Desktop/rings"
cd ~/projects/ledatic-site && CF_TOKEN=$(cat ~/Desktop/rings) ./deploy.sh holo.html
curl -I https://ledatic.org/holo
```

Then unblock distribution (`#8` /plasma/tv permalink — fastest follow-up, builds on holo).

**P1 (independent of deploy):** Tier 3-B JS glue. Start by reading `compile.rail` for tag/untag patterns:
```
grep -nE "tag_int|untag_int|float_arr.*tag|tagged" tools/compile.rail | head -40
```
Goal: load `tools/plasma/render.wasm`, call `wasm.seed_ot(stateHandle)` from JS, read the seeded state from `Float64Array(memory.buffer)`, verify `f64View[0]` ≈ 2.7777 (OT density IC). That closes Tier 3-A's full browser-harness gate.

## Open tasks (TaskList state)

| ID | Status | Subject |
|---|---|---|
| 5 | completed | MSAA 4× anti-aliasing |
| 6 | completed | Audio synthesis from 8 metrics |
| 8 | pending (blocked by #22) | /plasma/tv permalink with seed |
| 9 | pending (blocked by #22) | Embeddable web component |
| 10 | pending (out-of-session) | Generative posters daily |
| 11 | pending (blocked by #8) | Pulse-claim permalinks /pulse/N |
| 12 | completed | Tier 3-A: render.rail + render.wasm + build script |
| 13 | pending | Tier 3-B: JS glue, derived fields integration |
| 14 | pending (blocked by #13) | Tier 3-C: temporal LIC accumulator |
| 15 | pending (blocked by #12) | Tier 3-D: particle integrator |
| 16 | pending (blocked by #12-15 + #22) | Tier 3-E: site integration |
| 17 | completed | Picture-in-picture top-down |
| 18 | completed | B-field vector arrows on PiP |
| 20 | completed | 3D-anchored annotations |
| 21 | completed | Camera presets (iso/front/side/top) |
| 22 | pending (needs CF_TOKEN) | Deploy holo.html to ledatic.org |
| 23 | pending (blocked by #22) | Cross-browser audit |
| 1, 2, 3, 4, 7, 19 | deleted | redundant or out-of-scope (rationale in task descriptions) |

## Files on disk new since session start

```
tools/plasma/
├── live4k.html               (Tier 0, WebGL2)
├── holo.html                 (Moonshot, WebGPU, ~67 KB / ~1300 lines)
├── render.rail               (Tier 3-A source)
├── render.wasm               (built artifact)
├── render.wat                (text form)
└── build_render_wasm.sh      (reproducible build with export injection)

tools/train/
├── honest_grade.sh           (ld-exit-aware compile grade)
└── audit_dir.sh              (parallel batch grader)

docs/plans/
└── PLASMA_RAIL_WASM_RENDERER.md   (Tier 3 5-phase design)

docs/handoffs/
└── 2026-05-02.md             (this file)

ledatic-site/
└── holo.html                 (staged, byte-identical to source)

~/.claude/projects/-Users-user/memory/
└── holo_moonshot.md          (memory entry, partial — finalize next session)
```

## Memory entries to add (next session)

After deploy lands, write a new memory entry for the holo viewer's existence + URL. Suggested:
- `holo_shipped.md` — "tools/plasma/holo.html is the WebGPU plasma chamber viewer. Live at ledatic.org/holo. Beacon-driven. Don't rebuild from scratch — extend."

Also update `MEMORY.md` index with one-line pointer to `holo_moonshot.md`.
