| Input pipeline | *(TS-only concept)* | `playground/src/input/pipeline.ts` ≡ `manifold/src/engine/input-pipeline.ts` | Port to core (P4) |
| Output pipeline + curves | curves mirror `nisps/core/math.hpp` | byte-identical TS pairs in playground + manifold | Port to core (P4) |
| Audio DSP engines (×8) | `nisps/engines/` | none — both targets run the WASM ✓ | Keep |
| TS engine spine (wasm-iml, worker, host, worklet) | — | manifold forked from playground; several files byte-identical | Single home in manifold (P1) |
| `playground/` | **Retired.** Archived to branch `archive/playground-solidjs`, deleted from main. Manifold is the sole browser app; WASM build, parity-check, codegen all retarget manifold. |
| Depth of "one core" | **All algorithms in C++.** Feedback (incl. geometric dislike), Jolt, OU, RNG, input/output pipelines, curves move into `nisps/`; TS keeps UI/reactivity/transport only. |
| MLP arity | **Template the hardware, dynamic browser.** Firmware keeps compile-time `MLP<...>` (zero-heap contract intact); WASM/VCV targets get a runtime-shaped MLP sharing the same algorithm code. Heap allowed at construction time on non-RP2350 targets only. |
| VCV | **In scope, final phase** (P6); may slip without blocking anything else. |
- ✅ `scripts/build-wasm.sh` emits to `manifold/public/` (keep `playground/public/` copy only until P1 lands).
- ✅ `scripts/parity-check.sh` (and `tests/cpp/parity_wasm.mjs`) read the manifold artifact.
- ✅ Fix stale doc: the `MLP<2,…>` line was in `docs/AGENT-REFERENCE.md` + `nisps/wasm/README.md` (MAP.md was already correct); both now say `MLP<32u,10u,14u,18u,126u>`.
- ✅ `ml-debug.log`/`graphify-out/` were already absent from the tree; `.claude/worktrees/` gitignored.
- **Gate met:** `run-all-tests.sh` green (Playwright leg via the BUILD-PLAN non-snap-node VPS runner); parity PASS reading `manifold/public/` (max delta 2.4e-7); manifold typecheck+build green against the freshly-built artifact.
- Manifold `input-pipeline.ts` / `output-pipeline.ts` become thin calls into the main-thread WASM instance
(state lives C++-side, per-instance, serialisable for persistence).
- Golden TS-vs-C++ tests retire; replaced by direct use.
- **Gate:** spine e2e unchanged; recorded-gesture regression: same pointer trace → same routed output
pre/post migration (capture fixture before starting).
### P5 — Schema/codegen serves manifold (≈2 days)
-`codegen/generate.ts` emits `manifold/src/modes/generated/` alongside the C++ headers (playground target
removed in P1). `MF_MODES` in `console/model.ts` is derived from generated schemas, not hand-written —
labels/ordering may stay a manifold-side overlay, but params/ranges/ml-config come from schema truth.
- With P2's dynamic MLP, per-mode `ml.input_size/output_size/hidden` in schemas becomes *real* in the
browser; codegen gains a check that firmware modes still fit the fixed template.
- **Gate:** codegen idempotence golden test extended to manifold output; e2e per-mode param count/range
assertions driven from schema.
### P6 — VCV reunification (later; may slip)
-`vcv/src/iml.hpp` deleted; module consumes `nisps/ml/` with `DynamicStorage` (its 8→16 runtime shape is
exactly the P2 case). `DetRng` replaced by `nisps/core/rng.hpp`. Closes vcv-module.md delta #5.
- OSC server stays vcv-local (transport, not behaviour).
- **Gate:** vcv builds; seeded train/infer parity vs native ctest.
## 4. Risks
| Risk | Mitigation |
|---|---|
| P2 template refactor destabilises firmware perf (chokepoint B) | Fixed-storage path stays `std::array` + same attrs; compare `.text`/RAM and audio-callback timing before/after; land behind a ctest parity gate. |
| Dynamic storage leaks heap use into firmware paths | Compile-time guard (`#if NISPS_TARGET_EMBEDDED` excludes `DynamicStorage`); `lint-cpp.sh` already fails heap under `nisps/` — carve an explicit allowlist for the dynamic TU only. |
| Per-event WASM calls for pipelines add latency | Pointer-rate ≈120 Hz, one call each — negligible; batch API as fallback. rAF/canvas never calls WASM. |
| Geometric-dislike port changes feel vs firmware | Port from upstream source verbatim, seeded-trajectory parity test, then hardware A/B (chokepoint A) before deleting the TS fallback. |
| Retiring playground loses a working reference | Archive branch + tag; parity fixtures (recorded gestures, golden outputs) extracted *before* deletion in P1. |
| Manifold worklet + main thread now both depend on retargeted wasm build | P0 gate builds manifold from fresh artifact in CI, killing the manual-copy hazard permanently. |
## 5. Doc-sync obligations
- On each phase landing: update `MAP.md` (it is the shipped-behaviour authority) and burn down this plan's
phase table; when all phases land, set `status: executed`.
-`MAIN.md` registry: this file added; `engine-architecture.md` remains authoritative for the *browser-side*
seam only; BUILD-PLAN.md's MLP row annotated as superseded (done 2026-07-13).
-`ALIGNMENT.md` defect #3 (fixed WASM arity) closes at P2; the accepted-divergence log entries for Jolt/OU