--- kind: finding date: 2026-07-21 immutable: true --- # Simplification Audit 2026-07 — full-repo smell/bloat/spec review vs the one-core vision _Dated 2026-07-21. Method: a 66-agent workflow — 11 parallel subsystem reviewers (ml-core, dsp-engines-modes, wasm-bridge, manifold-ui, manifold-backends-inputs, firmware, schemas-codegen, specs-docs, tests-build, satellites-hygiene, architecture-gap) → adversarial verification (per-finding skeptics for architectural/structural claims, batch spot-checks for local/style) → a completeness critic. 113 findings survived, 0 were refuted outright, 22 were downgraded/corrected by verifiers. Yardstick: the operator's five-bullet target vision (2026-07-20): (1) one C++20 NISPS core serving RP2350 firmware and the browser, performance-sensitive on the MCU; (2) firmware modes runnable as modes in Manifold; (3) curated-presets default with a maximalist "advanced" dev mode; (4) PlatformIO, no more .ino; (5) Manifold as interface/editor for the hardware. Actionable mitigations are phased in `../plans/simplification-plan.md`; the strategic tier is promoted into `ALIGNMENT.md` (both updated in the same commit as this finding)._ ## Headline 1. **CI has been 100% red on main since 2026-07-13** and nothing noticed. The memllib submodule pin (`b37fc53`, branch `feat/nisps-core-swap`) is reachable from **no remote** — GitHub's `submodules: recursive` checkout fails before any gate runs, so every P4–P6 "gates green" claim rests on local runs only, and fresh clones cannot build firmware. Verified live via `gh run list` (all recent main runs `failure`) and `git branch -r --contains b37fc53` (empty). 2. **Those three memllib commits exist only on one disk.** A single disk failure loses firmware-critical code. (The `w1n5t0n` fork remote exists but does not contain them.) 3. **Production deploys are gated by nothing.** Push to main → VPS webhook → live at `meml.lnfinitemonkeys.org/next/`, with CI red and the committed `manifold/public/nisps.wasm` having no freshness gate — what users run is whatever was last committed, unverified. 4. **Real behaviour bugs surfaced**, not just smells: the TS example-store mirror caps at 100 while the C++ store caps at 128, so `train()` and `trainAsync()` silently train on different datasets past 100 examples (plus a latent OOB read on sample weights); VCV bridged mode truncates the input vector to 2-D against a 32-input head; the VCV plugin has an audio-thread data race and does full-state JSON on the audio thread. 5. **The five-bullet vision has zero footprint in ALIGNMENT.md or the spec corpus** — nothing records PlatformIO, curated/advanced, or the hardware-editor role as goals, so nothing was steering toward them. 6. **No performance measurement exists anywhere** — the headline "performance-sensitive" constraint is enforced entirely by static discipline (no heap/virtual, section attrs) and vibes; no benchmark, no size report, no CPU-load assertion on either target. The codebase itself is in **better shape than its vibe-coded provenance suggests**: the `nisps/` core's storage-policy split is justified and parity-pinned, hot paths are clean, the CRTP mode scaffold genuinely centralises, the backend/input contracts are uniform. The dominant rot is *vestigial mass* (dead subsystems, decorative UI, executed-plan specs presented as live contracts, hand-maintained registries that codegen should own) — most fixes are deletions. ## Area verdicts **ml-core** — The ml-core area (nisps/core, nisps/ml, nisps/pipeline) is genuinely one of the healthier parts of this codebase: the MLPCore policy split is justified (two real consumers — zero-heap firmware FixedStorage, arena-allocated browser/VCV DynamicStorage — sharing one algorithm body, pinned by a bit-parity test), hot paths are heap-free, virtual-free, .f-consistent, and RNG is deterministic per instance. Jolt/OU/replay/geo_push are small, inert-by-default, and cleanly ported. The rot is concentrated in vestigial baggage rather than wrong abstractions: feedback.hpp carries two whole legacy […] **dsp-engines-modes** — The dsp/engines/modes stack is in better shape than the vibe-coded provenance suggests: the DSP primitives are lean, faithful ports with no maximilian/daisysp vestiges beyond honest attribution comments; all 8 engines have real consumers on both targets; the CRTP ModeBase genuinely centralizes orchestration (inputs, jolt, OU, events) rather than hiding duplication. The biggest gap versus the vision is architectural: the modes/ layer is consumed ONLY by firmware — the WASM bindings include engines but zero mode headers and re-assemble mode behavior (jolt stepping, OU, routing) in bindings.cpp […] **wasm-bridge** — The wasm-bridge is in better shape than its history suggests: the P3 'SWAP POINT' duplication is genuinely resolved (jolt.ts/ou-explore.ts are deleted; exploration.ts is now a thin timer-driver over the shared C++ core), the flat C API in bindings.cpp is stylistically coherent (consistent null-guards, grouped, documented wire layouts), and worklet messaging is RT-acceptable (postMessage between render quanta, fixed-size param buffer, no allocation inside process() beyond trivial subarray views). The real problems are accretion and dead mass: roughly a dozen API entries exist across a 5-file […] **manifold-ui** — The manifold UI is functional and the engine wiring (FeedbackController → shared C++ core, backend manager, input layer) is genuinely live, but the console layer carries heavy sediment from its window-global JSX ancestry: a dead four-way "focus/altitude" system whose only reachable branch is 'composite' (SplitStage, ReadoutStrip, InputMini, AltitudeNav all unreachable), a large stratum of decorative state that renders real-looking controls doing nothing (learning-rate/decay/spread/tame sliders, master volume, bpm, A/B toggle, snapshots, health/gradient visuals), and a ConsoleCtx god-object […] **manifold-backends-inputs** — This is one of the cleaner vibe-coded areas: the OutputBackend contract is genuinely uniform (start/send/teardown/status with in-backend throttle+dead-zone), mapping.ts is a single shared truth, presets.ts is real and consumed by OutputsBackendConfig (not a stub), and midi-devices/ is proper schema→codegen with one import path. The real debts are: (1) the VCV bridged-training path is pinned to an obsolete 2-D input assumption while the engine has a 32-input head and the spine already stores the full N-dim raw vector — so VCV mode silently truncates gamepad/MIDI inputs; (2) the OSC bridge […] **firmware** — The firmware C++ glue itself is in decent shape — it is thin (~1.4k lines), template-based with no virtual dispatch in the audio path, the SPSC/dual-core discipline is respected, and peripherals.hpp/selftest.hpp are unusually well-commented and readable for vibe-coded work. The rot is concentrated in the build system, which is exactly what vision bullet 4 targets: the Arduino-CLI toolchain forces a symlink forest, a build script that mutates the committed .ino (variant flips pollute git history), a triple-bookkept mode list (the .ino comment block, mode_select.hpp aliases, and a […] **schemas-codegen** — The schemas→codegen pipeline is one of the better-built parts of this vibe-coded repo: both generators validate via ajv, emit deterministic/idempotent output, and the generated C++ is genuinely sane (inline constexpr arrays, string_views, .f literals, no heap — spot-checked against the perf contract). But the "schemas are the single source of truth" story is only about half true in practice: net dimensions are hand-duplicated in every C++ mode's MLP template args with no compile-time tie back to the generated constants (browser reshapes from schema, firmware uses the hand-written dims — the […] **specs-docs** — The corpus has an unusually good ontology (spec/plan/finding/ADR split, _archive dir, front-matter kinds) and MAP.md is ~90% accurate and current — but the July one-core refactor (P4–P6, landed 2026-07-14/18) rotted the registry layer faster than the doc-sync discipline caught it. MAIN.md, the corpus entry point, now makes at least six false or self-contradictory claims; two 2026-06-era specs describe the RETIRED SolidJS playground world as present tense; both plans that are done still carry status:active in ways the corpus's own ontology forbids (BUILD-PLAN) or defensibly (one-core, gated on […] **tests-build** — The test estate is in genuinely good shape at its core: 42 focused C++ test files with a documented hand-rolled harness, a 7-stage native-vs-WASM parity blob, committed golden baselines (impulse, ML vectors), fixed↔dynamic storage parity, VCV-adapter parity, and post-P4 pipeline-golden fixtures whose provenance and re-baselining are exemplary — the fixtures are meaningful, not frozen accidents. The problems cluster at the edges: an entirely dead root-level Playwright rig left over from the retired playground (config points at an HTML file that no longer exists anywhere in the tree, and […] **satellites-hygiene** — The satellites are in better shape than their paperwork. Post-P6, vcv/src/iml.hpp genuinely is a thin adapter over MLPCore (pinned bit-exact by tests/cpp/test_vcv_iml_parity.cpp, wired into CMake), and keeping the module in-repo is coherent since it builds against ../../nisps directly; the one defensible wart is the insertion-order example mirror (features_/labels_), which carries a named requirement (JSON persistence + cross-thread staging) and is acceptable. firmware/useq-celium is the cleanest corner of the repo: I byte-verified the protocol.h ↔ useq-protocol.ts mirror […] **architecture-gap** — Scored against the 5-bullet vision: (1) "one C++ core" is ~80% real — the algorithm layer (ML, feedback, jolt/OU, pipelines, curves) genuinely lives once in nisps/ after the P0–P6 refactor, but the MODE layer does not: nisps/modes/ never compiles to WASM, so the browser recomposes engine+ML in TS and every ModeBase behaviour (event ring, voice spaces, note_on/BPM, analysis feature-splicing, pinning) is firmware-only. (2) Consequently "firmware modes runnable in Manifold" is ~40%: 4 of the 9 catalogued browser modes are non-functional (sequencers emit events nobody drains; audio-in modes have […] ## Completeness-critic gaps _A final agent asked "what did the audit miss?". Verdict: file-tree coverage was strong; the systematic blind spot was everywhere the repo touches the outside world._ **CI has been entirely red on main since 2026-07-13 and no auditor noticed.** Verified live: `gh run list` shows 8/8 recent runs on main FAILED, spanning every P3–P6 push (2026-07-14 through 2026-07-18). Cause confirmed from run 29641902005: the cpp-tests job dies at the Checkout step — 'remote error: upload-pack: not our ref b37fc53…' — because ci.yml uses `submodules: recursive` and the memllib gitlink was re-pinned (commit 43ef6d5, 2026-07-13) to a commit that exists on no remote. The vcv-plugin workflow fails identically. The firmware area found the unreachable pin ('fresh clones cannot build firmware') and tests-build criticized CI *content* drift, but the compound fact is worse than either: the entire C++ gate […] **The unpushed memllib fork is a data-loss single point of failure, and its ownership question is unasked.** The three commits on memllib's local `feat/nisps-core-swap` branch (bf9691c 'swap memlp includes for nisps/core, inline RL utilities', 32cc831 newlib RNG fix, b37fc53 seed-helper rename) are NISPS-load-bearing source that exists ONLY in this working copy — `git ls-remote` of MusicallyEmbodiedML/memllib shows no ref containing them, and the operator has no fork remote configured. One disk failure loses firmware-critical code. The audit framed this purely as a build blocker; the trivial mitigation (push the branch to a monkey-w1n5t0n/w1n5t0n Forgejo or GitHub fork and repoint .gitmodules) was never proposed. The deeper unasked question matters […] **The production deploy pipeline was audited by nobody — live deploys are gated by nothing.** manifold/ONBOARDING.md:43 documents it: push to GitHub main → VPS webhook → builds manifold/ → rsyncs to the live meml.lnfinitemonkeys.org/next/. Three consequences no area examined: (a) deploys do not wait for CI — and CI is red anyway (gap 1), so every P4–P6 push went straight to the live site with zero automated gate between a nisps/ change and production; (b) the webhook builds only manifold/, so vite copies the COMMITTED manifold/public/nisps.wasm into dist — the 'stale artifact, no freshness gate' finding that tests-build scoped to browser tests actually extends to what users run in production; (c) the webhook config itself (on the […] **No performance measurement exists anywhere, though 'super performance-sensitive on the microcontroller' is the vision's first bullet.** Every area checked perf DISCIPLINE statically (no heap, no virtual, .f literals, section attrs) but nobody asked how the project would ever KNOW the audio path meets budget or regressed: grep across scripts/ and tests/cpp/ finds zero benchmark harness, no cycle/CPU-load assertions, no blocks-per-second smoke for engine_process_block (native or WASM), and no firmware flash/RAM budget report in any gate — the 16 KB dead loss-history buffer was found by reading, not by a size report that would have caught it mechanically. The only perf scaffolding is on-device (src/memllib/utils/perf.hpp, included by the .ino) with no automated consumer. A […] **Training-health telemetry is one product decision fragmented into four uncoordinated findings.** Four areas each hold one limb of the same feature: ml-core flags the 16 KB loss-history buffer in every firmware MLP (nothing reads it); specs-docs verifies wasm-worker.ts:304 fakes a 1-element lossHistory; manifold-ui flags the health/gradient visuals as decorative; architecture-gap notes the real get_layer_stats API is plumbed end-to-end and unused. Nobody asked the single question that resolves all four: IS training-health telemetry a feature of this instrument? If yes (plausible — 'interactive control visualisation' is in vision bullet 5 and 'advanced mode as preset-authoring dev tool' in bullet 3 wants training introspection), the fix […] **The osc-bridge release workflow already names the surviving bridge — and two of three workflows were reviewed by nobody.** tests-build audited only ci.yml, but .github/workflows/ contains three workflows. osc-bridge.yml (tag-triggered) deno-compiles ONLY manifold/osc-bridge/bridge.ts into cross-platform release binaries — that is the named external consumer that settles the manifold-backends 'two hand-maintained bridge implementations' finding: bridge.ts has a release pipeline, bridge.mjs has no consumer in any workflow, so the mjs twin is the deletion candidate. vcv-plugin.yml was also unreviewed: it fails on the same unreachable submodule pin as ci.yml (verified in the 2026-07-18 run), and still triggers on stale feat/manifold-mission / feat/vcv-dist branch […] ## Findings inventory _`confirmed` = an adversarial verifier re-read the cited code and the claim held; `downgraded` = the claim held but severity or fix needed correction (fix shown is the verifier's). IDs are referenced from `../plans/simplification-plan.md`; evidence lives at the cited lines._ ### Architectural (8) **A1. Mode layer is not shared: nisps::modes never compiles to WASM; Manifold rebuilds modes in TS** (architecture-gap, downgraded, week+) `nisps/wasm/bindings.cpp:54`, `nisps/modes/base.hpp:113`, `manifold/src/console/model.ts:199`, `manifold/src/engine/spine.ts:1` bindings.cpp includes nisps/engines/* and nisps/ml/* but nothing from nisps/modes/ (includes at lines 54-77; engine dispatch at 267-275 instantiates bare engines). grep for events/voice_space/note_on/update_bpm in bindings.cpp returns nothing. So ModeBase behaviours — initial inference at setup […] *Fix:* Reunify mode BEHAVIOUR in C++ without pretending the browser can host one monolithic mode object: (1) storage-policy ModeBase exactly as P2 did for MLPCore — ModeBase, ...> with Fixed for firmware (zero-heap intact) and Dynamic for WASM (heap at construction only), so browser modes stay runtime-reshapeable; (2) split the mode C ABI along the […] **A2. Manifold catalogues 4 modes that structurally cannot work in the browser** (architecture-gap, downgraded, days) `manifold/src/console/model.ts:206`, `nisps/engines/breakor.hpp:123`, `manifold/src/engine/engine-host.ts:1`, `manifold/src/engine/worklet/nisps-processor.ts:287` SCHEMA_MODES (model.ts:199-221) lists all 9 schema modes including breakor, elysiamorf (sequencers: engine audio is silence; their whole output is pop_events, breakor.hpp:123-128) and xiasri, sound_analysis_midi (audio-in). But: (a) no WASM binding drains engine events and no manifold code […] *Fix:* Immediate (hours, manifold-only): add a manifold-side audio-topology map keyed by engineId in model.ts — 'generator' (paf_synth, memlcelium→also slp_workshop, elysiamorf? no: event-only) vs 'audio-in-fx' (channel_strip, verb_fx, xiasri) vs 'event-only' (breakor, elysiamorf) vs 'analysis' (sound_analysis_midi) — and surface it as a 'firmware-only'/'needs audio-in' badge on […] **A3. No curated/advanced split exists; Manifold is 100% dev-maximalist with no preset data model to author against** (architecture-gap, downgraded, week+) `manifold/src/settings/settings-store.ts:24`, `manifold/src/backends/presets.ts:30`, `manifold/src/console/ConsoleApp.tsx:105` Grep for advanced/curated across manifold/src finds only BackendAdvanced.tsx (per-backend transport settings) — no global mode toggle. settings-store.ts:24-40 holds only cosmetic prefs (icon colour, input-map shape, corner radius). The only preset machinery is presets.ts: per-BACKEND output-routing […] *Fix:* Split into three differently-sized items. (a) NOW, small bug: add `cv` to OutputPresetRow, rowsFromParams, and applyPreset in manifold/src/backends/presets.ts (three one-line additions). (b) IF/WHEN the curated-default direction is actually adopted, first record it in ALIGNMENT.md (it currently contradicts open question Q2) — then build the unified preset artifact by EXTENDING […] **A4. Hardware-editor (vision 5) is a facade: serial stub in the UI, zero firmware command surface, zero on-device persistence** (architecture-gap, downgraded, week+) `manifold/src/serial/memlnaut-serial.ts:102`, `manifold/src/console/Drawers.tsx:590`, `firmware/MEMLNaut-NISPS/MEMLNaut-NISPS.ino:126` memlnaut-serial.ts saveModel/restoreModel/getSettings are explicit no-op stubs (lines 102-132: 'TODO: real protocol', returns false/null/{}), and git log shows manifold/src/serial untouched since the June initial commit. EditorPanel is shipped live in the Settings drawer (Drawers.tsx:590) with […] *Fix:* Drop the short-term step — the 'not wired' badge already exists in EditorPanel.tsx:88-94; at most soften the dock description in output-mode.ts:79 ('configure / save / restore — protocol not yet implemented'). Real path stands as proposed: spec the USB-serial protocol the useq-celium way (shared versioned header under firmware/, mirrored TS + frame-size unit test), add a […] **A5. modes/ layer has one consumer: WASM bindings bypass it and re-orchestrate modes from engines + ml primitives** (dsp-engines-modes, downgraded, days) `nisps/wasm/bindings.cpp:54`, `nisps/wasm/bindings.cpp:844`, `nisps/modes/base.hpp:311`, `firmware/MEMLNaut-NISPS/glue/mode_select.hpp:41` bindings.cpp includes all 8 engine headers (lines 54-62) and ml/jolt.hpp, ml/ou_noise.hpp directly, but not a single nisps/modes/*.hpp; only firmware glue (mode_select.hpp:41-50) consumes the mode classes. bindings.cpp:844-851 (nisps_ml_jolt_step) is a line-for-line duplicate of […] *Fix:* Do NOT bind the mode classes into WASM and do NOT delete the per-primitive jolt/OU C API — both contradict the locked one-core-engine architecture (runtime-shaped browser MLP, P2; primitives-via-C-ABI, P3) and the two-WASM-instance RT split. Instead: (1) collapse the one true code duplication by moving the copy→morph→writeback sequence into the shared primitive — e.g. a […] **A6. Arduino-CLI/.ino build machinery: build mutates committed source, triple-bookkept mode list, symlink forest — PlatformIO migration deletes ~400 lines of hackery** (firmware, confirmed, days) `scripts/firmware-common.sh:192-208`, `scripts/firmware-common.sh:298-337`, `firmware/MEMLNaut-NISPS/MEMLNaut-NISPS.ino:37-59`, `firmware/MEMLNaut-NISPS/glue/mode_select.hpp:90-106` Mode selection lives in THREE hand-synced places: the .ino comment block (lines 38-54) that firmware-common.sh greps (load_firmware_variants:192-208), the mode_select.hpp using-aliases (54-85), and the NISPS_ST_* macro table (90-104). set_firmware_variant (298-337) runs an inline Python script that […] *Fix:* Migrate to PlatformIO in one cut, no dual path: platformio.ini with maxgerhardt/platform-raspberrypi + board_build.core=earlephilhower (the FQBN solderparty_rp2350_stamp_xl proves the variant exists in arduino-pico; verify the PIO board def or add a small custom board JSON). One [env] per firmware variant with build_flags = -std=gnu++20 -DMEMLNAUT_MODE_TYPE= (keep […] **A7. No curated-default/advanced split and no in-UI instrument picker — UI structure fights the core vision** (manifold-ui, downgraded, days) `manifold/src/console/ConsoleApp.tsx:355`, `manifold/src/console/ConsoleApp.tsx:61`, `manifold/src/settings/settings-store.ts:24`, `manifold/src/console/Drawers.tsx:1` The vision requires curated presets/modes by default with maximalist settings behind an 'advanced' gate. Settings (settings-store.ts:24-38) contains only monochromeIcons/unfocusedIconColour/inputMap/cornerRadius — no advanced flag exists anywhere. The default surface is the full five-drawer console […] *Fix:* Render the instrument-mode picker from the already-plumbed ctx.modes/setModeId (pure UI; engine reshape-on-mode-switch already works per P5; keep the window.__mf seam for e2e). Drop the global advancedMode boolean: progressive disclosure is already designed and partly built as the per-drawer depth ladder (dock-spec §0 peek/expand/FULL with FULL as the advanced page). If more […] **A8. The operator's target vision (PlatformIO, curated-presets default vs advanced mode, Manifold as hardware editor) has zero footprint in ALIGNMENT or the spec corpus** (specs-docs, confirmed, hours) `ALIGNMENT.md:48`, `docs/specs/MAIN.md:140`, `MAP.md:150`, `manifold/src/serial/memlnaut-serial.ts` No spec, plan, ALIGNMENT defect, or open question mentions PlatformIO anywhere (grep -ri platformio docs/ MAP.md ALIGNMENT.md hits only firmware/useq-celium, which already uses it — proving the toolchain is in-house viable). MAP.md:150 codifies the .ino/Arduino-CLI flow as a Convention; ALIGNMENT […] *Fix:* Add three dated ALIGNMENT entries (PlatformIO migration — killing the .ino sketch-tree symlink hacks MAP.md:161 documents; curated-presets/advanced-mode product model — promoting Q2 from question to defect and linking the pending manifold-parity presets plan; hardware-editor role for manifold/src/serial). Specs follow when each is picked up. ### Structural (35) **S1. Mode identity is ~6 hand-maintained registries with demonstrated drift, not one source of truth** (architecture-gap, downgraded, day) — `manifold/src/console/model.ts:199`, `manifold/src/console/model.ts:324` Adding a mode touches: schema JSON (canonical) + hand C++ mode (legit) PLUS (a) mode_select.hpp using-alias, (b) the NISPS_ST_* zero-table, […] *Fix:* Keep points (1), (4), (5) as proposed: codegen an ALL_MODE_SCHEMAS array (TS-side codegen template change; SCHEMA_MODES becomes a mode_id→overlay map, keeping hand label/glyph/cls/ordering, which are legitimately display truth); collapse […] **S2. Vision 4 (PlatformIO) not started; the .ino build machinery is actively hostile (symlink farm, sed-mutates-source mode selection, macro undef dance)** (architecture-gap, downgraded, days) — `scripts/firmware-common.sh:311`, `firmware/MEMLNaut-NISPS/glue/mode_select.hpp:19` Mode selection = build scripts regex-rewriting the .ino's #define line in place (firmware-common.sh:194-205 grep/sed discovery, :311 python […] *Fix:* Migrate firmware/MEMLNaut-NISPS to one platformio.ini with an env per variant passing -DMEMLNAUT_MODE_TYPE= (grep/sed/python rewrite machinery, the .ino comment registry, and the NISPS_ST_* SelfTest grep-discovery tag all deleted; […] **S3. Two 'authoritative' specs still prescribe the retired SolidJS/playground2 world** (architecture-gap, downgraded, hours) — `docs/specs/engine-architecture.md:38`, `docs/specs/aimmersive-clone-spec.md:1` engine-architecture.md (kind: spec — 'wins over code by intent' per MAIN.md §0) mandates building in a fresh `playground2/` tree with […] *Fix:* One commit, three coordinated edits. (1) engine-architecture.md: do not flatten to one page — excise the dead sections (§1 playground2 tree, §3 reuse-vs-rebuild, §4 two-entry Vite/nginx serving, §5 S0–S7, stale §6 open questions) and […] **S4. DriverConfig is a dead contract: required by the AudioEngine concept, implemented by all 8 engines, consumed by nobody** (dsp-engines-modes, confirmed, day) — `nisps/core/concepts.hpp:62`, `nisps/core/types.hpp:59` Repo-wide grep for driver_config/DriverConfig finds only the struct (types.hpp:59), the concept requirement (concepts.hpp:62), and the 8 […] *Fix:* Decide once: either wire the firmware audio driver to read the active mode's engine().driver_config() at mode start (makes the mic/line settings real), or delete DriverConfig, the concept line, and all 8 implementations. Do not keep the […] **S5. Per-mode kSchema aggregates are hand-written 12-field boilerplate that codegen should emit** (dsp-engines-modes, confirmed, hours) — `nisps/modes/breakor.hpp:76`, `nisps/modes/memlcelium.hpp:48` Nine mode headers each contain a mechanically identical positional ParamSchema aggregate wiring 12 generated constants (kXModeId, […] *Fix:* Move struct ParamSchema into generated/schema_types.hpp and have codegen emit 'inline constexpr ParamSchema kXSchema{...}' per mode; each mode's param_schema() becomes a one-line return of the generated constant. Delete the 9 hand-written […] **S6. MLP topology is a dual source of truth: hand-typed template args vs generated hidden_layers** (dsp-engines-modes, confirmed, hours) — `nisps/modes/memlcelium.hpp:28`, `nisps/modes/generated/memlcelium_schema.hpp:19` Every mode hardcodes its net shape (e.g. ml::MLP<4u,10u,14u,18u,56u> at memlcelium.hpp:28) while the generated header carries the same dims […] *Fix:* Have codegen emit 'using MemlceliumMLP = ::nisps::ml::MLP<4u,10u,14u,18u,56u>;' (or a static_assert block comparing MLP dims to kXHiddenLayers) into each generated header, and make modes use the alias. One source of truth, compile-time […] **S7. memllib submodule pin is unreachable from any remote — fresh clones cannot build firmware** (firmware, confirmed, hours) — `.gitmodules:1-3`, `scripts/build-firmware-arch.sh:74-79` git submodule status → b37fc53 (heads/feat/nisps-core-swap). Inside src/memllib, `git branch -r --contains HEAD` returns EMPTY — the pinned […] *Fix:* Push feat/nisps-core-swap to the monkey-w1n5t0n/memllib fork and change the .gitmodules URL to the fork (or upstream the changes to MusicallyEmbodiedML and re-pin). Then delete the compensating error-message paragraph in […] **S8. daisysp is fully dead weight: 41 .cpp files compiled into every firmware build with zero consumers, and docs mislabel it a live submodule** (firmware, confirmed, hours) — `firmware/MEMLNaut-NISPS/src/daisysp`, `nisps/dsp/pitch_shift.hpp:3` grep for daisysp across firmware glue, the .ino, nisps/, and the symlinked memllib subdirs (audio/hardware/interface/synth/utils) finds […] *Fix:* Delete the firmware/MEMLNaut-NISPS/src/daisysp symlink and the vendored src/daisysp tree; correct MAP.md, firmware/README.md, and setup-firmware-toolchain.sh in the same commit. (Answers the focus question: yes, the granular pitch-shift […] **S9. Firmware compilation is in no automated gate: CI, run-all-tests.sh, and lint all skip firmware/** (firmware, confirmed, day) — `scripts/run-all-tests.sh`, `.github/workflows/ci.yml:14-15` grep 'firmware' scripts/run-all-tests.sh → no hits. ci.yml comments that 'firmware build is documented as a manual […] *Fix:* After the PlatformIO migration, add a CI job running `pio run -e slpworkshop -e selftest -e pafsynth` with a cached toolchain (arduino-pico core download is the only heavy step). Pre-migration stopgap: a weekly/manual-dispatch arduino-cli […] **S10. VCV bridged mode truncates the input vector to 2-D against a 32-input engine head** (manifold-backends-inputs, downgraded, day) — `manifold/src/engine/engine-api.ts:264`, `manifold/src/backends/vcv-backend.ts:67` engine-api.ts inputVector() returns `[this.spine.lastRawX, this.spine.lastRawY]` (a fresh 2-element array allocated on EVERY spine tick […] *Fix:* In manifold TS only: (1) change EngineApi.inputVector() to return spine.lastRawInputs (signature ArrayLike; document "live reused buffer — copy, don't retain"; VcvBackend.setInputVector already copies). (2) Make VcvBackend […] **S11. Two hand-maintained OSC bridge implementations (bridge.ts Deno + bridge.mjs Node)** (manifold-backends-inputs, confirmed, hours) — `manifold/osc-bridge/bridge.ts:1`, `manifold/osc-bridge/bridge.mjs:1` bridge.mjs is not compiled output — it is a separate hand-written Node port (node:dgram + ws dependency vs Deno.listenDatagram; deno […] *Fix:* Delete bridge.mjs; keep bridge.ts as the single source and compile.sh binaries as the no-Deno distribution. Fix the spec line that calls .mjs 'compiled'. **S12. Inputs: spec promises source composition, code enforces exclusive single-source; composition machinery unreachable** (manifold-backends-inputs, downgraded, day) — `docs/specs/inputs-spec.md:16`, `docs/specs/inputs-spec.md:230` inputs-spec.md §0 says the operator picks 'one source *or a combination*' and §223-230 specifies multi-source composition ('XY pad + a MIDI […] *Fix:* Do not prune the composition machinery or rewrite the spec to exclusive — mix-and-match is a recorded, unreversed operator decision (2026-06-28 memory; commit 9e59eb0 and docs/specs/recon/midi-gamepad-inputs-worklog.md both mark the […] **S13. Per-backend config side-channel + instanceof special-casing in the manager's hot path** (manifold-backends-inputs, downgraded, day) — `manifold/src/backends/manager.ts:69`, `manifold/src/backends/manager.ts:78` The OutputBackend contract carries mappings/names via BackendContext, but each real backend ALSO needs an index-aligned parallel specs […] *Fix:* Two independent fixes, narrower than proposed. (a) Replace the per-tick instanceof (manager.ts:69) with an optional `setInputVector?(vec: ReadonlyArray): void` on OutputBackend, implemented only by VcvBackend — this alone removes […] **S14. MEMLNaut Editor (vision bullet 5) is a 237-line shell: sound connect lifecycle, zero protocol, and a third unshared Web Serial implementation** (manifold-backends-inputs, downgraded, week+) — `manifold/src/serial/memlnaut-serial.ts:102`, `manifold/src/serial/EditorPanel.tsx:72` memlnaut-serial.ts is honestly labelled STUB: saveModel returns false, restoreModel returns null, getSettings returns {} (lines 102-133); […] *Fix:* When bullet 5 is scheduled: (1) define the wire FRAMING as a C header under firmware/ following the useq-celium discipline (header single source of truth → TS mirror → parity test asserting frame sizes/offsets) — this part of the original […] **S15. Dead focus/altitude system: SplitStage, ReadoutStrip, InputMini, AltitudeNav, CompactAxis are unreachable** (manifold-ui, confirmed, hours) — `manifold/src/console/ConsoleApp.tsx:105`, `manifold/src/App.tsx:78` ConsoleApp.tsx:105 `const [focus, setFocus] = useState(initialFocus)` — setFocus is never called anywhere in the repo (grep […] *Fix:* As proposed (delete SplitStage.tsx, ReadoutStrip.tsx, InputMini.tsx, AltitudeNav, CompactAxis, the UI Focus type/prop, the focus branches + stripPinned + vacuous keyboard gates in ConsoleApp, and the barrel exports; keep MiniMeters), with […] **S16. Decorative/fake controls: training-param sliders, master volume, bpm, A/B toggle, snapshots and health/gradient visuals drive nothing** (manifold-ui, downgraded, day) — `manifold/src/console/ConsoleApp.tsx:113`, `manifold/src/console/Drawers.tsx:242` Verified by grep: learningRate/decay/tame/spreadLevel (ConsoleApp.tsx:126,149-151) are read ONLY by their own Drawers.tsx:242-255 sliders — […] *Fix:* Deletion-first, with three corrections. (1) Delete the A/B machinery (ab/aRef/setHoldingA/toggleAB, the VerdictCluster props, and the '+ A/B toggle' header comment), the fake seed, seededGradient + rev/weightsRevision, the unconsumed […] **S17. VCV backend UI is unreachable: no OutputMode maps to BackendId 'vcv'** (manifold-ui, confirmed, hours) — `manifold/src/console/output-mode.ts:40`, `manifold/src/console/types.ts:27` OutputMode type (types.ts:27) is 'particles'|'midi'|'osc'|'cv'|'synth'|'editor' and OUTPUT_MODES (output-mode.ts:40-83) maps these to […] *Fix:* Decide which: add `{ id: 'vcv', backend: 'vcv' }` to OUTPUT_MODES + OutputMode + MODE_ICON (three small edits) to make the path live, or delete VcvConfig/VcvChannelEditor/forwardVcvFeedback/vcv ctx state. The first is likely intended given […] **S18. Per-backend config editors duplicated in two files and BOTH rendered in the same expanded drawer** (manifold-ui, confirmed, hours) — `manifold/src/console/Drawers.tsx:646`, `manifold/src/console/Drawers.tsx:677` BackendAdvanced.tsx:8-9 self-describes as 'the full-depth duplicate of the inline config in OutputsBackendConfig; both write the same […] *Fix:* Delete BackendAdvanced.tsx and the Drawers.tsx:674-679 block (keep SynthGroupNote inline in Drawers if its one paragraph is wanted). OutputsBackendConfig already covers every backend. **S19. ConsoleCtx god-object: ~25 of its fields have zero consumers outside ConsoleApp** (manifold-ui, downgraded, day) — `manifold/src/console/types.ts:56`, `manifold/src/console/ConsoleApp.tsx:789` Grep across console/, dock/, serial/ (excluding ConsoleApp/types): ctx.modes, setModeId, axes, setAxis, preset, setPreset, offsetActive, […] *Fix:* Prune ConsoleCtx to the 57 fields Dock/Drawers/OutputsBackendConfig actually read (plus mode). Delete outright: the Axes type + axes/setAxis state, the preset/setPreset/offsetActive chain (permanently 'Sculpt'/false), and the dead ctx […] **S20. Dead legacy feedback modes: RandomiseOutputs, RandomiseMlp, AvoidStyle::Diffuse, on_drag have no product consumer** (ml-core, downgraded, day) — `nisps/ml/feedback.hpp:59-73`, `nisps/ml/feedback.hpp:258-271` The only product callers of the feedback controller select two behaviours: firmware sets only FeedbackMode::ExploreAndPlace […] *Fix:* Treat as a spec-governed decision, not dead-code removal. First surface to the operator: deleting AvoidStyle::Diffuse reverses the explicit "keep for A/B comparison" decision in docs/adr/rl-feedback-design.md, and deleting […] **S21. perf.hpp SRAM-section macro regime is mostly dead; the one real NISPS_AUDIO_FUNC use is shape-mismatched; docs claim discipline that doesn't exist** (ml-core, confirmed, hours) — `nisps/core/perf.hpp:26-35`, `firmware/MEMLNaut-NISPS/glue/midi_io.hpp:72` Repo-wide grep: NISPS_AUDIO_MEM and NISPS_APP_SRAM are used ZERO times outside perf.hpp and comments (the .ino uses memllib's own AUDIO_MEM […] *Fix:* Delete NISPS_AUDIO_MEM/NISPS_APP_SRAM/NISPS_AUDIO_FUNC from perf.hpp; change midi_io.hpp:72 to plain 'inline void ...' (or Pico's __not_in_flash_func(name) applied correctly); rewrite MAP.md:151/164 and drop ALIGNMENT #4. If SRAM placement […] **S22. All vcv/ user-facing docs describe the pre-P6 nisps-core-era module (2×12, v1 3D weights, dead paths)** (satellites-hygiene, confirmed, hours) — `vcv/README.md:3`, `vcv/README.md:31` README.md:3 says '2 inputs … 12 outputs' (module is 8×16 per MEMLNaut.cpp:16-17); README.md:31+265 and BUILDING.md:29+73 reference […] *Fix:* Rewrite README.md's numbers/paths (small diff), delete the playground-sharing sections, and either rewrite NISPS-FORMAT.md against the v3 flat layout or delete it and point at docs/specs/vcv-module.md (which the /specs corpus already owns) […] **S23. Retired-playground build output and its root E2E harness still tracked on main** (satellites-hygiene, confirmed, hours) — `playground/dist/index.html`, `playground/dist/nisps.wasm` git ls-files shows playground/dist/* (1.2 MB: bundled JS+sourcemaps, a second nisps.wasm and nisps.js) tracked, though the playground app […] *Fix:* git rm -r playground/ tests/e2e/ package.json package-lock.json playwright.config.js; delete root node_modules and the playground dir from disk. The archive branch already preserves the app; nothing else names these paths. **S24. CI never runs codegen — the 'schema changes require regenerated outputs in the same change' gate is unenforced** (schemas-codegen, confirmed, hours) — `.github/workflows/ci.yml:24`, `scripts/run-all-tests.sh:51` ci.yml's two jobs (cpp-tests, manifold-tests) contain no codegen step at all. The golden test runs only in local run-all-tests.sh stage 5, […] *Fix:* Add a CI step (in the manifold-tests job, where bun is already set up, before typecheck): `cd codegen && bun install --frozen-lockfile && bun run generate.ts && bun run generate-midi-devices.ts && cd .. && git add -N nisps/modes/generated […] **S25. MLP net dimensions are a dual source of truth: hand-written template args in every C++ mode vs schema dims used by the browser** (schemas-codegen, confirmed, hours) — `nisps/modes/paf_synth.hpp:31`, `nisps/modes/memlcelium.hpp:28` All 9 modes hand-write dims, e.g. paf_synth.hpp:31 `ml::MLP<4u, 10u, 10u, 14u, 33u>` duplicating schemas/modes/paf_synth.json ml {4, […] *Fix:* Use the generated constexpr constants as the template args directly — they are valid constant expressions today: ml::MLP […] | | L9 | dsp-engines-modes | Dead no-op VoiceSpace boilerplate on five engines | `nisps/engines/breakor.hpp:37` | Delete the VoiceSpace enum/table/setter from the five engines with zero real voice spaces; keep them only on PAFSynth, VerbFX, ChannelStrip. ModeBase […] | | L10 | dsp-engines-modes | VerbFXEngine recomputes the full 47-param voice-space mapping every audio sample (and its […] | `nisps/engines/verb_fx.hpp:77` | Run smoothing + voice-space mapping at a shared control rate (e.g. every 16-32 samples, same divisor on both targets so native↔WASM parity holds), […] | | L11 | dsp-engines-modes | ExternalSynthMIDIMode hand-rolls its schema and ML config outside codegen | `nisps/modes/external_synth_midi.hpp:132` | Fold the ext-synth ML config into the schema/codegen pipeline (a shared 'ext_synth' base schema emitting the constants), or at minimum define the […] | | L12 | firmware | NISPS_ST_ selftest token-paste table silently out of date: SLPWorkshop (the currently active […] | `firmware/MEMLNaut-NISPS/glue/mode_select.hpp:90-106` | Fold into the PlatformIO migration: delete the entire NISPS_ST_ table and the SelfTestRig tag type, and select the selftest build with […] | | L13 | firmware | midi_io.hpp uses the misshapen NISPS_AUDIO_FUNC macro that MAP.md and ALIGNMENT.md both claim […] | `firmware/MEMLNaut-NISPS/glue/midi_io.hpp:72` | Apply ALIGNMENT #4 option A: make NISPS_AUDIO_FUNC(name) decorate a function NAME on both targets, update the handful of use sites (midi_io.hpp here; […] | | L14 | firmware | peripherals.hpp: dead declarations, duplicated commit-and-train block, and the documented […] | `firmware/MEMLNaut-NISPS/glue/peripherals.hpp:67` | Delete kAnalogInputCount, PeripheralBindings, and the unused spread local; extract one commit_and_train(mode, feedback) helper used by both branches; […] | | L15 | firmware | MAP.md documents a vendored firmware/MEMLCelium-upstream/ directory that does not exist on […] | `MAP.md:30-31` | Delete the MAP.md entry (or, if the snapshot lives untracked on another machine and is genuinely wanted, commit it — but name the consumer first; the […] | | L16 | manifold-backends-inputs | Dead protocol legs from the retired playground: sendState/sendWeights, legacy array format, […] | `manifold/src/backends/osc-client.ts:116` | Delete sendState/sendWeights, the legacy-array branch in both bridges (or the one surviving bridge), […] | | L17 | manifold-backends-inputs | Status/throttle boilerplate duplicated across all four real backends while inputs/ already has […] | `manifold/src/backends/midi-backend.ts:163` | Extract a small BaseBackend (status plumbing + throttle gate + lastSent management), mirroring BaseSource. Pure deletion-by-refactor, no behaviour […] | | L18 | manifold-backends-inputs | MIDI input floods React with per-CC-message state updates and snapshot allocations | `manifold/src/inputs/midi-input-source.ts:224` | Only call notifyBindings on binding-LIST changes (learn capture, clearBinding, clearAllBindings); if the drawer wants live values, read them on the […] | | L19 | manifold-backends-inputs | BackendManager.setActive silently drops a switch requested while another is in flight | `manifold/src/backends/manager.ts:131` | Store the latest requested id when switching is true and re-run setActive with it in the finally block (3-4 lines). | | L20 | manifold-ui | Solo-mode selector offers three behaviours but soloMode is behaviourally inert | `manifold/src/console/Drawers.tsx:142` | Collapse to a single non-selectable label until train_masked lands in the C API, or disable the two unimplemented options with a 'pending core […] | | L21 | manifold-ui | FeedbackController vestiges: unused seed/undoDepth options, never-called engine-interface […] | `manifold/src/feedback/controller.ts:57` | Delete seed/undoDepth options and maxUndo; trim ControllerEngine to the members actually called; change dislike to (output: Float32Array) and update […] | | L22 | manifold-ui | 5 of 12 design primitives are dead (Panel, StatusLine, ControlAxis, CurvePlot, Sparkline) | `manifold/src/primitives/index.ts:1` | Delete the five unused primitives (Sparkline/CurvePlot may return with the deferred diagnostics suite — re-add then). Optionally promote […] | | L23 | manifold-ui | Dual backend catalogues: BACKENDS duplicates OUTPUT_MODES; OutputControl/toOutputControl dead | `manifold/src/dock/output-state.ts:40` | Delete OutputControl/toOutputControl and ModeIconComponent; delete BACKENDS and use modeDesc.label/description in Drawers (or derive BACKENDS from […] | | L24 | manifold-ui | ConsoleApp global-listener effects run without dependency arrays — re-subscribed on every […] | `manifold/src/console/ConsoleApp.tsx:684` | Hold the verdict handlers in refs (or useEffectEvent) and give both effects [] / [inputs] deps, matching Manifold's existing onMoveRef pattern. | | L25 | ml-core | 16 KB loss-history buffer baked into every firmware MLP instance with zero product consumers | `nisps/ml/storage.hpp:200` | Decide plumb-or-delete now. Smallest: delete lh_/loss_hist_buf/loss_history()/loss_history_count_ (train already returns final loss) and the […] | | L26 | ml-core | dislike_multiplier_ is upstream-InterfaceRL bookkeeping that drives nothing | `nisps/ml/feedback.hpp:406-407` | Delete dislike_multiplier_, its update/halving logic, the accessor, and the test line — or, if the upstream behaviour it was meant to drive is […] | | L27 | ml-core | nisps/core/fixed_buffer.hpp is dead code | `nisps/core/fixed_buffer.hpp:1-77` | Delete fixed_buffer.hpp, test_fixed_buffer.cpp, the CMake/ctest entry, and the MAP.md:8 mention. Trivially revivable from git if a consumer ever […] | | L28 | ml-core | get_weights() forces a permanent whole-net scratch copy (flat_buf) and double-copies on every […] | `nisps/ml/storage.hpp:199` | Add a copy_weights_to(std::span dst) (and set from span, which already exists) and switch feedback.hpp's take_snapshot/push_undo/nudge to it; […] | | L29 | ml-core | OutputChain's firmware story is aspirational — pipeline chains have browser-only consumers | `nisps/pipeline/output_chain.hpp:12-13` | Either wire InputChain/OutputChain into the firmware control tick (peripherals/ModeBase) as the named vision-5 requirement, or soften the header […] | | L30 | satellites-hygiene | ALIGNMENT.md declares the VCV module dead while vcv/ is actively maintained | `ALIGNMENT.md:72` | Delete the ALIGNMENT.md:72 entry (the module now DOES consume nisps/ directly — the entry's own 'if revived' condition is met and closed). While […] | | L31 | satellites-hygiene | MAP.md documents firmware/MEMLCelium-upstream/ which does not exist on disk or in any git ref | `MAP.md:30` | Delete the MAP.md:30 entry (the port provenance is already captured in ALIGNMENT.md's geometric-dislike entry and nisps/ml file headers; upstream […] | | L32 | satellites-hygiene | Agent-worktree fragment committed to main (.claude/worktrees/agent-ae87fe47/…) | `.claude/worktrees/agent-ae87fe47/playground/js/shapeseq […]` | git rm -r .claude/worktrees/ (the ignore rule then holds for the future). Also consider pruning the 30+ stale worktree-agent-*/worktree-wf_* local […] | | L33 | satellites-hygiene | vcv/test/ is dead: smoke test includes a nonexistent header, tests the retired 2×12 shape, and […] | `vcv/test/smoke_test.cpp:6` | git rm -r vcv/test/ and vcv/Makefile.dist (update BUILDING.md's two references). In osc_server.hpp, delete the unreachable reply-to-sender branch and […] | | L34 | satellites-hygiene | Data race: audio thread reads imlShadow's example vectors while the worker may be mutating them | `vcv/src/MEMLNaut.cpp:514` | Have the worker deep-copy features/labels into pending staging buffers (alongside pendingWeights, e.g. under stagingMutex) BEFORE setting […] | | L35 | satellites-hygiene | Full-state JSON serialize/parse runs on Rack's audio thread | `vcv/src/MEMLNaut.cpp:474` | Move JSON build/parse to the existing worker thread: stage the raw string in/out with the same atomic-flag pattern already used for oscStagedJson, […] | | L36 | satellites-hygiene | Dead root planning docs and dead data/ directory from retired eras | `NISPS_CORE_EXTRACTION_PLAN.md` | git rm both NISPS_CORE_* files (history preserves them; docs/specs/plans/ is the sanctioned home for plans) and git rm -r data/. If the CSVs matter […] | | L37 | schemas-codegen | modeEngineId switch in manifold hand-duplicates schema engine_id and silently drops new modes […] | `manifold/src/console/model.ts:324` | Delete the switch; route on mode.engineId with the single named exception (sound_analysis_midi → 'analysis', or add an optional analysis-engine […] | | L38 | schemas-codegen | Two divergent TS applyCurve implementations for the per-output curve knob | `manifold/src/console/model.ts:278` | Pick one formula (mapping.ts's, which is spec-anchored and has a sane 0.5=linear midpoint), delete the other, and re-export the survivor; update […] | | L39 | schemas-codegen | seed-midi-devices.ts silently clobbers the canonical hand-tunable device schemas it created | `codegen/seed-midi-devices.ts:11` | Delete the script (its purpose is served; it lives in git history and synth-midi-cc.json keeps provenance), or make it skip existing files. Drop the […] | | L40 | schemas-codegen | Mode schema content is partially placeholder: 20 params across paf_synth/channel_strip/xiasri […] | `schemas/modes/paf_synth.json:16` | Accept as dated debt but record it (ALIGNMENT.md entry): name the placeholder slots during the first preset-curation pass per mode, or shrink […] | | L41 | specs-docs | MAP.md documents a phantom vendored firmware (firmware/MEMLCelium-upstream/) that exists […] | `MAP.md:30` | Delete the MAP.md:30 bullet (or, if the snapshot exists untracked on another machine and is genuinely wanted, commit it — but the smallest fix is […] | | L42 | specs-docs | aimmersive-clone-spec.md specs a retired product (SolidJS clone of a-immersive) and still […] | `docs/specs/aimmersive-clone-spec.md:7` | Move to docs/specs/_archive/ with deprecated-by front matter (or reclassify kind: finding, dated, noting it describes the deployed vanilla app); […] | | L43 | specs-docs | feedback-modes-port-spec.md is an executed port plan masquerading as an evolving spec, with […] | `docs/specs/feedback-modes-port-spec.md:6` | Archive it (kind: plan, status: executed, deprecated-by: docs/adr/rl-feedback-design.md + code). The ADR + feedback.hpp are the surviving truth; […] | | L44 | specs-docs | BUILD-PLAN.md still status:active though executed, with stale locked-decision facts | `docs/specs/plans/BUILD-PLAN.md:3` | Flip to status: executed, add a two-line 'what survives' note (non-snap-node gotcha → MAP), update the MAIN registry row. | | L45 | specs-docs | engine-architecture.md's 'One Engine, Two Skins' framing is superseded but the file carries no […] | `docs/specs/engine-architecture.md:7` | Add a supersession header pointing at one-core-engine-refactor §0, retitle/trim to what remains authoritative: the browser-side EngineApi seam […] | | L46 | specs-docs | vcv-module.md is a three-era palimpsest whose 'retained for reference' sections state stale […] | `docs/specs/vcv-module.md:169` | Prune pass: delete the 2→12-era architecture/prerequisite/Phase-0 text (git keeps it), keep the current 8→16 contract + threading/persistence […] | | L47 | specs-docs | ALIGNMENT.md staleness: dead VCV deferred-debt entry, mitigation pointing at a deleted file, […] | `ALIGNMENT.md:72` | Delete :72; repoint #5's source reference to upstream MusicallyEmbodiedML memlp (or the archive branch); prune the 2026-04-29 resolved entries. | | L48 | specs-docs | 818 lines of dead nisps-core extraction relics at repo root | `NISPS_CORE_EXTRACTION_PLAN.md` | git rm both files (history retains them; the executed outcome is already narrated in ALIGNMENT's resolved log). | | L49 | specs-docs | MAP.md and AGENT-REFERENCE.md still carry pre-P5 'modes slice the default 126 outputs / TS […] | `MAP.md:155` | Update the three sentences to past-tense schema-real reality (or delete the convention bullet — MAP's manifold section already states it correctly). | | L50 | specs-docs | backends/dock/inputs spec trio grounds itself in a deleted world (playground paths, a-app.js […] | `docs/specs/inputs-spec.md:14` | One pass across the three files: mark the audit/grounding sections as historical ('as of 2026-06-27, pre-refactor'), fix the handful of dead-path […] | | L51 | tests-build | Parity runner headers document 4 stages / blob v1 while the code implements 7 stages / v5 | `tests/cpp/parity_check.cpp:14-45` | Rewrite both file headers' payload/stage lists to match the v5 blob (or replace the duplicated prose lists with a one-line pointer to the stage […] | | L52 | tests-build | parity-check.sh FAIL branch is unreachable under set -e | `scripts/parity-check.sh:18` | Wrap: `if node "$TESTS_DIR/parity_diff.mjs" ...; then echo PASS; else status=$?; echo FAIL; exit $status; fi` — or delete the dead branch and let the […] | | L53 | wasm-bridge | fetch + indirect-eval glue loading duplicated in two files; build could emit an ES module […] | `manifold/src/engine/wasm-iml.ts:56` | Add `-sEXPORT_ES6=1` (and `-sENVIRONMENT=web,worker` stays) to build-wasm.sh, replace both eval blocks with a single shared `await import(/* […] | | L54 | wasm-bridge | Worklet WASM loader carries dead scaffolding and a silent-stub failure trap | `manifold/src/engine/worklet/nisps-processor.ts:104` | Delete the unused `imports` object, the 'c' branch, `exMap`, and the duplicate second loop. Replace the generic `() => 0` stub with a throwing stub […] | | L55 | wasm-bridge | Retired playground's dist/ build artifacts still tracked in git | `playground/dist` | git rm -r playground/dist and remove the leftover untracked directory; add playground/ to .gitignore or delete the folder entirely. | ### Style (15) | ID | Area | Finding | Where | Fix | |----|------|---------|-------|-----| | ST1 | dsp-engines-modes | Engine header comments describe implementations that don't exist (doc drift cluster) | `nisps/engines/breakor.hpp:4` | Rewrite the four comment blocks to describe the actual code; drop stream-plan tense. | | ST2 | firmware | input_router.hpp is a zero-logic speculative layer with one consumer | `firmware/MEMLNaut-NISPS/glue/input_router.hpp:18-21` | Delete input_router.hpp; have the .ino call bind_peripherals directly (or rename bind_peripherals to wire_inputs inside peripherals.hpp). Drop the […] | | ST3 | manifold-backends-inputs | Stale comments/docs: 'inputs-spec.md is absent', 'fixed WASM head = 2', 'Editor → BackendId' | `manifold/src/inputs/types.ts:10` | Delete/correct the three claims; one small comment pass. | | ST4 | manifold-ui | GROUP_COLOR maps duplicated in four files and keyed on obsolete JSX-era group names | `manifold/src/console/shared-ui.tsx:83` | One shared map in model.ts (or a hash-to-palette function over arbitrary group strings, which would actually work for schema groups); delete the […] | | ST5 | manifold-ui | Minor prop/doc lint: duplicate onReroll/onRandomise, unused CompositeStage mode prop, probe […] | `manifold/src/console/ConsoleApp.tsx:1092` | Collapse to one onReroll prop; drop the mode prop; rewrite the probe header to describe the actual surface. | | ST6 | ml-core | feedback.hpp header comment asserts the retracted 'geometric push NOT ported' claim, […] | `nisps/ml/feedback.hpp:8-12` | Rewrite the header's mode summary to match the four current modes and the Geometric default (fold into the dead-modes deletion commit). | | ST7 | ml-core | MAP.md and math.hpp still describe the pre-P3/P4 world (interim TS jolt/OU, playground curve […] | `MAP.md:79-81` | Update MAP.md:79-81 to describe exploration.ts as a thin timer-driver over the WASM core, and replace math.hpp's playground-mirror paragraph with the […] | | ST8 | satellites-hygiene | License story is self-contradictory: MPL-2.0 repo, 'proprietary' VCV plugin manifest | `LICENSE:1` | Set plugin.json license to MPL-2.0 (or GPL-3.0-or-later per VCV convention) and drop the 'in spirit' hedge in iml.hpp — one licence, stated once. | | ST9 | schemas-codegen | schema.json's own description states the direction of truth backwards | `schemas/schema.json:5` | Rewrite the description sentence: schemas are the canonical contract; codegen emits C++ and TS; provenance notes live in params_notes.md. | | ST10 | schemas-codegen | codegen/README.md is wholesale stale (playground paths, phantom temp-dir, resolved stream-1 […] | `codegen/README.md:6` | Rewrite codegen/README.md against current reality (or shrink it to a pointer at MAP.md §codegen); drop port-solidjs from ci.yml triggers. | | ST11 | schemas-codegen | codegen/templates/ are dead 'reference' files already drifting from the real emitters | `codegen/templates/cpp_schema.hpp.template:4` | Delete codegen/templates/ and the README line pointing at it. | | ST12 | schemas-codegen | Duplicated helper block across the two codegen scripts, justified by a false rationale comment | `codegen/generate-midi-devices.ts:17` | Extract a tiny codegen/lib.ts with the shared helpers and correct the comment (keep both drivers). Or just fix the comment and accept the 40 lines. | | ST13 | schemas-codegen | synth-midi-cc.json lives at repo root; its only machine consumer is the seed script | `synth-midi-cc.json:1` | Move to schemas/midi_devices/synth-midi-cc.sources.json (one-line path update in the seed script — moot if that script is deleted per the clobber […] | | ST14 | tests-build | test_helpers.hpp documents NISPS_EXPECT as non-fatal but it throws; NISPS_ASSERT is a plain […] | `tests/cpp/test_helpers.hpp:10-11` | Smallest fix: correct the comment to say both are fatal and delete the NISPS_ASSERT alias (or keep the alias, one line). Only implement true […] | | ST15 | wasm-bridge | Doc/comment drift lagging the P1–P4 refactors | `MAP.md:79` | One doc-sync pass: fix MAP.md:79, rewrite the nisps/wasm/README paragraph and either complete or delete its API table (point at bindings.cpp as the […] |