Stream 7 wires nisps/ml + nisps/engines into the playground via Emscripten.
Highlights:
- nisps/wasm/bindings.cpp: flat C API per architecture.md §6.2. Fixed-arch
MLP<2, 10, 14, 18, 126>; engine string→type dispatch table with NoOp
fallback.
- scripts/build-wasm.sh: emcc invocation, MODULARIZE=1, exports listed
explicitly; produces playground/public/nisps.{js,wasm}.
- playground/src/ml/wasm-iml.ts: main-thread MLP host (sync inference,
sync training, RL ops, weights I/O, layer stats, localStorage).
- playground/src/ml/wasm-worker.ts: disposable Web Worker for off-thread
async training, owns its own WASM instance.
- playground/src/ml/dataset.ts: Float32Array-backed FIFO with sample-weight
modes (uniform/global/local/combined). Port of legacy dataset.js.
- playground/src/audio/engine-host.ts: AudioContext + AudioWorkletNode
lifecycle, with start/stop/setEngine/setParams.
- playground/src/audio/worklet/nisps-processor.ts: WASM-loading
AudioWorkletProcessor that runs engine.process_block per 128-sample
block. Loads its own WASM instance from main-thread-supplied bytes
(no fetch in worklet).
- playground/src/stores/ml-store.ts: wired stub methods to WasmIML
singleton; lazy initialize().
- playground/src/debug/probe.ts: window.__nisps now calls real WasmIML
via the store; lazy-init on first use.
Verified:
- bash scripts/build-wasm.sh succeeds (94 KB nisps.wasm)
- bun run typecheck OK
- bun run build OK (production bundle)
- vite dev server serves /nisps.{js,wasm} with COOP/COEP
Known limitation: WASM is fixed at one MLP shape. Multi-arch deferred —
documented in nisps/wasm/README.md.
Fresh playground/ now sits on:
- Vite 5 + vite-plugin-solid + Solid.js 1.9
- TypeScript strict (jsx preserve, target ES2022)
- index.html → main.tsx → App.tsx with a tiny pushState/popstate router
- Design tokens (dark immersive palette, JetBrains Mono) at src/styles/tokens.css
- COOP/COEP headers in vite.config.ts (server + preview) so SharedArrayBuffer
is available for the C15 + AudioWorklet wiring stream 7 will land.
- Debug-probe stub at src/debug/probe.ts: window.__nisps with placeholder
methods + __ready=false marker. Stream 10 fills it in. Keeping the install
point stable from day one means Playwright tests can rely on the global
existing.
Stores, pipelines, and primitives ride in the next commits.
Stream 8 of the rewrite (meml-911).