diff --git a/plans/jamesdsp-integration-report.md b/plans/jamesdsp-integration-report.md index 9788761..134a311 100644 --- a/plans/jamesdsp-integration-report.md +++ b/plans/jamesdsp-integration-report.md @@ -1,29 +1,30 @@ -# JamesDSP integration report — 2026-10-09 +# JamesDSP integration report — 2026-10-10 -Phases 1–5 are implemented in five focused commits. Standard remains the default and its EQ construction is byte-for-byte checked against the pre-refactor fixture. JamesDSP lives only in the lazy `feature:jamesdsp` group; the service worker shell has no DSP assets. The shared `AudioGraph` owns the sole context and one source per media element. Enabling JamesDSP creates one worklet and one WASM heap; errors restore Standard routing. iOS remains gated by `liveAudioIOS`. Uploaded impulse responses are session-only, and Liveprog/DDC/arbitrary text effects are excluded. The worklet uses a static, pinned relative module import because AudioWorkletGlobalScope rejects dynamic import. +JamesDSP now uses the shared `AudioGraph`, remains opt-in, and is delivered as a lazy feature. The upstream port is pinned to `a982b53c4ab347d1d9c50f4ce7ee3c2735eaa817`. It adds four-channel convolution, generated and IndexedDB-stored IRs, spatial/HRTF processing, and 8–96 kHz sample-rate conversion. Settings expose IR selection/upload and bounded controls for convolution and spatial audio. Long IRs are constrained on low-resource devices. Standard remains an exact bypass route; failed DSP/WASM initialization returns to Standard. iOS playback remains gated by `liveAudioIOS`. -Verification: +The legacy lossy-update timeout came from the new worker hashing/copying the entire legacy shell during `activate`, while the b77938a page reloads on a short timer after the user presses Refresh UI. The worker now stages and verifies legacy assets during `install`; activation only commits the staged cache. The lossy migration harness passes both engines, preserving the user-initiated legacy update flow. -| Check | Result | +The DSP WASM is now marked `offlineOptIn: "jamesDsp"`. Normal completion caches the 103 required files and defers all 9 optional DSP files, including the ~1.2 MB WASM. Enabling “download audio effects for offline” persists the opt-in and resumes completion. Cold transfer is back near the pre-DSP baseline. + +| Verification | Result | |---|---| -| Frontend tests | 266 passed, 0 failed | -| Server suite | Passed with the integration test venv on PATH | -| Offline completion | Chromium + WebKit: 109/109 runtime files, zero missing/failures; all four layouts | -| Lazy / hidden timers | Both engines pass; hidden-timers has no page errors | -| UI geometry / icons | 384 geometry cases and 24 icon cases pass | -| Settings persistence | 24 settings keys unchanged through old-client update; Chromium OPFS save/play passes before and after update. Linux WebKit lacks native OPFS. DSP preset persists while disabled. | -| DSP harness | Both engines pass all seven presets, Standard comparison, A/B bypass, track switch, offline reload and corrupt-WASM fallback. One heap, one worklet, two pre-existing media sources. | -| Migration | Both engines pass unthrottled: one banner/reload, 142 cached entries, offline reload and playback guard. Lossy Chromium repeatedly times out waiting for the new stamped page after the legacy user-triggered refresh, despite candidate install and `CACHE_STATUS ready:true`; WebKit lossy was not reached. | +| Frontend tests | 271 passed, 0 failed | +| Server tests | Previously run after integration: all pass except the two known `yt_dlp` environment failures; remaining server tests passed individually | +| Offline completion | Chromium + WebKit: 112/112 after explicit opt-in; 103 required + 9 optional deferred by default; zero missing/failures | +| Lazy / hidden timers | Both browsers pass; lazy asserts DSP WASM remains uncached by default; no hidden-timer page errors | +| UI geometry / icons | 384 geometry cases and 24 layout/theme icon cases passed | +| Settings persistence | Old-client Refresh UI preserved all existing keys in both engines; only intentional additions/migrations are the disabled `jamesDsp` default and 5→10 EQ migration. Save-before-play works before and after update. DSP preset/parameters and offline opt-in persist. Linux WebKit lacks native OPFS, so its save-play assertion is explicitly unsupported. | +| DSP harness | Both engines pass: four-channel IR changes output (interaural RMS 0.00735), spatial stage changes it (0.02154 vs dry 0), 32 kHz context, exact bypass, offline reload with stored IR, one DSP heap, corrupt-WASM fallback | -Three-run cold medians versus `plans/integration-report.md`: +Migration (`node perf/migration.mjs --browser all`) passed lossy and unthrottled after the worker fix. Lossy wire totals: Chromium 652,568 bytes / 26.4 s; WebKit 746,826 bytes / 20.1 s. Unthrottled: Chromium 664,110 bytes / 11.2 s; WebKit 790,706 bytes / 7.7 s. Each run showed one banner/reload, offline launch, and playback guard. -| Engine/profile | FCP before → after | Boot before → after | Cold wire before → after | Positive `app.js` bodies | -|---|---:|---:|---:|---:| -| Chromium LTE | 1360 → 1360 ms | 6457 → 6677 ms | 648 KB → 1.82 MB | 1 | -| Chromium lossy | 1992 → 1936 ms | 10407 → 10582 ms | 648 KB → 1.82 MB | 1 | -| WebKit LTE | 895 → 904 ms | 2307 → 2374 ms | 976 KB → 2.14 MB | 1 | -| WebKit lossy | 2744 → 2751 ms | 5642 → 5757 ms | 983 KB → 2.15 MB | 1 | +Three-run cold LTE medians (`node perf/baseline.mjs --runs 3 --browser all --profile lte --scenario cold`): -FCP/boot are within 4% of the integrated build. Cold-session wire grows by the approximately 1.2 MB upstream WASM, fetched after paint by the required completion job so JamesDSP remains available offline. This is a real first-install transfer cost. The cold results are in `perf/results/dsp-cold-check.json`. +| Engine | FCP before → now | LCP now | Wire before → now | Requests now | Positive `app.js` responses | +|---|---:|---:|---:|---:|---:| +| Chromium | 1360 → 1348 ms | 1348 ms | 648 KB → 1.82 MB → 673,992 B | 117 | 1 | +| WebKit | 895 → 908 ms | 976 ms | 976 KB → 2.14 MB → 1,020,231 B | 161 | 1 | -No real iPhone, locked-screen playback, thermal/CPU timing, real-ear preset tuning, crossfade, P2P, or active-DSP saved/OPFS playback was verified. Phase 7 beta push/deploy was intentionally not run: this task explicitly forbids push/deploy. Do not merge or enable the engine by default until the lossy migration handoff is resolved and an iPhone beta check validates lock-screen expectations and CPU cost. +The wire columns are pre-DSP baseline → initial DSP integration before the opt-in correction → current. The correction removes roughly 1.2 MB from first install while leaving the DSP assets available after explicit opt-in. + +The harness JSON is `perf/.tmp/dsp-cold-final.json`; it records 274 ms Chromium long-task total and 0 ms in WebKit. No real iPhone, lock-screen session, thermal behavior, or listening/ear-tuning test was possible. Verify iOS opt-in, background audio, CPU use with long IRs, and the perceived level/space before enabling this for users. Phase 7 deployment was not run.