memlnaut-nisps/docs/specs/recon/simplification-audit-2026-07.md
monkey-w1n5t0n fd0aee2354 docs(audit): simplification audit 2026-07 — recon findings, phased plan, ALIGNMENT rewrite
66-agent adversarially-verified audit vs the five-bullet one-core vision.
113 findings: CI red since 2026-07-13 (memllib pin on no remote), ungated
deploys, unshared mode layer, no curated/advanced split, dead-mass inventory.
Recon: docs/specs/recon/simplification-audit-2026-07.md (immutable).
Plan: docs/specs/plans/simplification-plan.md (proposal; phases gated on
operator adoption, §7 decisions). ALIGNMENT rewritten; MAP flatly-false
lines fixed (phantom MEMLCelium-upstream entry, exploration.ts, daisysp
non-submodule, pre-P5 sentence, perf-attr claims); MAIN registry updated.
2026-07-21 01:24:35 +02:00

64 KiB
Raw Blame History

kind date immutable
finding 2026-07-21 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 P4P6 "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 (P4P6, 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 P0P6 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 P3P6 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 P4P6 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<Derived, EngineT, MLCore, ...> 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 S0S7, 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<number>): 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<Focus>(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<generated::kPafSynthMLConfig.input_size, generated::kPafSynthHiddenLayers[0], generated::kPafSynthHiddenLayers[1], […]

S26. Large fraction of the schema surface has zero consumers — the single-source-of-truth claim is ~half freight (schemas-codegen, downgraded, day) — schemas/schema.json:45, codegen/generate.ts:195 Verified by repo-wide grep excluding generated dirs: (a) ml.input_channels names — read nowhere (input_router.hpp:4 admits it may 'grow […] Fix: Keep the per-field wire-or-delete structure, with three corrections. (1) default_learning_rate/default_max_iterations: wire BOTH platforms in one change or delete from both — if wiring, firmware glue passes […]

S27. MAIN.md (corpus entry point) carries at least six claims the code or its own table contradicts (specs-docs, confirmed, hours) — docs/specs/MAIN.md:42, docs/specs/MAIN.md:67 (1) :67 'TS schema emission is dormant since P1; it returns at P5' — P5 landed 2026-07-18; codegen/generate.ts:8-12 writes […] Fix: Keep the original editing pass over docs/specs/MAIN.md (fix §1.2 superset claim per ALIGNMENT #1 — same eight nisps engines on both targets, C15 archived, mic input unwired; fix §2 to state TS emission is live at […]

S28. manifold-parity-features-spec.md is part-executed, part-pending, but still labelled 'no implementation authorised' with ground-truth references deleted from main (specs-docs, confirmed, day) — docs/specs/manifold-parity-features-spec.md:9, docs/specs/manifold-parity-features-spec.md:20 Front matter: aspirational; body :9-11 'Status: draft — awaiting review... no implementation is authorised'. But its §0 principle 1 (bind […] Fix: Reclassify as kind: plan; mark §on Jolt/OU as executed-by-other-means (one-core P3, core bindings — its own preferred route); repoint playground references to the archive branch/tag; keep presets/pins/control-surface sections as the active […]

S29. Root Playwright rig is dead: tests a page that no longer exists, invoked by nothing (tests-build, confirmed, hours) — playwright.config.js:13-22, package.json:1-13 playwright.config.js webServer serves cwd './playground' and testDir './tests/e2e'; tests/e2e/helpers.js:19 does […] Fix: Delete playwright.config.js, package.json, package-lock.json, and tests/e2e/ at the repo root; rm -rf root node_modules/, playwright-report/, test-results/ (already gitignored). No consumer exists: CI, run-all-tests.sh, MAP.md's entry […]

S30. lint-cpp.sh heap audit has proven false-negative modes and never covers nisps/pipeline/ (tests-build, confirmed, hours) — scripts/lint-cpp.sh:121, scripts/lint-cpp.sh:122 (1) Line 121 hardcodes subdirs dsp/engines/ml/modes — nisps/pipeline/ (the P4 control-rate hot path) and nisps/core/ are never scanned for […] Fix: In lint-cpp.sh: add "$NISPS_DIR/pipeline" and "$NISPS_DIR/core" to the subdirs array; replace the grep -v ' *//' post-filter with comment-stripping before matching (same perl strip already used by audit_float_suffix at lines 78-98); […]

S31. CI re-implements run-all-tests.sh and has drifted: codegen golden test not gated in CI (tests-build, confirmed, hours) — .github/workflows/ci.yml:24-131, scripts/run-all-tests.sh:3 run-all-tests.sh:3 says 'Designed to be the single command CI invokes', but ci.yml never calls it — it re-lists the stages as discrete […] Fix: Add one step to the manifold-tests job (bun is already installed): working-directory: codegen; run: bun install --frozen-lockfile && bun run tests/golden_test.ts. Fix the false 'single command CI invokes' header comment in […]

S32. Committed manifold/public/nisps.{js,wasm} has no freshness gate — all browser tests validate a potentially stale artifact (tests-build, downgraded, day) — .github/workflows/ci.yml:88-122, manifold/tests/wasm-load.ts:48-49 manifold/public/nisps.{js,wasm} are tracked build artifacts, last rebuilt/committed at 1672fe3 (P4). The manifold-tests CI job […] Fix: Replace the byte-diff with a toolchain-agnostic behavioral freshness gate: in the cpp-tests job, BEFORE the 'Build WASM' step (i.e. while manifold/public/ still holds the committed artifact), run the existing wasm parity harness against it […]

S33. Dead API entries threaded through the full 5-layer registration chain (wasm-bridge, downgraded, day) — nisps/wasm/bindings.cpp:643, nisps/wasm/bindings.cpp:868 Grepped all of manifold/src, manifold/tests, e2e, and tests/cpp/parity_wasm.mjs (the WASM parity driver — I extracted its full list of […] Fix: Delete the dead entries at every layer as proposed, with two corrections. (1) EXPORTED_RUNTIME must remain ["HEAP32","HEAPU8","HEAPF32","cwrap"] — tests/cpp/parity_wasm.mjs (parity-check.sh gate) and manifold/tests/wasm-load.ts […]

S34. publishWeights_ channel: full weight-vector copy at up to 200 Hz into a field nothing reads (wasm-bridge, confirmed, hours) — manifold/src/engine/wasm-iml.ts:1093, manifold/src/engine/wasm-iml.ts:929 publishWeights_() (wasm-iml.ts:1093-1096) runs getWeights() — a C→heap copy plus a fresh Float32Array allocation — then sink.setWeights, […] Fix: Delete EngineSink.setWeights, Spine.setWeights/weights()/liveWeights, and all publishWeights_ call sites (keep getWeights for persistence and the debug probe). If a weight-health view ever materialises, it should pull getLayerStats on […]

S35. Dual example store with mismatched caps: train() and trainAsync() diverge past 100 examples; latent OOB read on sample weights (wasm-bridge, downgraded, hours) — manifold/src/engine/wasm-iml.ts:167, manifold/src/engine/dataset.ts:81 WasmIML keeps a TS Dataset mirror (default cap 100, wasm-iml.ts:167) AND pushes every example into the C++ FIFO ring (DynamicStorage […] Fix: Keep the cap-alignment core of the proposal: name the constant once in nisps (e.g. constexpr kDefaultMaxExamples = 128 shared by storage.hpp:55 and dynamic_storage.hpp:43 defaults), expose it through nisps_ml_describe (extend the dims […]

Local (55)

ID Area Finding Where Fix
L1 architecture-gap Console health UI shows fabricated gradient data while the real layer-stats API sits plumbed […] manifold/src/console/model.ts:305 Delete seededGradient; wire the health readout to engine.getLayerStats() (already reactive via the version counter). Separately land the half-day […] (verifier: All cited lines verify: seededGradient (model.ts:305-319) fabricates norms/statuses from the rev counter, is […])
L2 architecture-gap MAP.md drift: swap points and TS prototypes described as live are already swapped/deleted MAP.md:79 Fix the two MAP.md entries (exploration = thin WASM wrappers, controller = thin driver, drop rng.ts and the phantom files). Delete the dead […]
L3 dsp-engines-modes nisps/modes/voice_space.hpp is entirely dead code nisps/modes/voice_space.hpp:27 Delete the file.
L4 dsp-engines-modes Dead oscillators: SineOsc/SawOsc/SquareOsc have no consumers nisps/dsp/osc.hpp:28 Delete the three classes; keep detail::kPi/kTwoPi, PAFOperator, FMOp. (verifier: SawOsc and SquareOsc are genuinely dead, but SineOsc has a live consumer the reviewer's grep scope missed: […])
L5 dsp-engines-modes ModeBase::input_dirty_ is write-only state nisps/modes/base.hpp:165 Delete the flag, or actually gate tick_control's inference on it (measure first; deletion is the safe default).
L6 dsp-engines-modes VerbFXEngine dead fields and setters: delay_to_verb_ computed 12 times, never read; […] nisps/engines/verb_fx.hpp:242 Delete delay_to_verb_, enable_reverb_, enable_delay_to_reverb_, and the unused set_enable_* setters (keep the ones a named consumer appears for). If […]
L7 dsp-engines-modes MEMLCeliumEngine feedback path is inert: feedback_ never written in process() nisps/engines/memlcelium.hpp:180 Check the original MEMLCeliumAudioApp: if it writes feedback, port the missing write; if not, delete feedback_, fbzm1_, fb_smooth_alpha_ and the […]
L8 dsp-engines-modes Sequencer machinery duplicated across engines: ratio_seq, event queue, bar/MIDI-clock phasors, […] nisps/engines/breakor.hpp:178 Extract dsp/ratio_seq.hpp (free function template), a small SeqClock struct (bar phasor + MIDI clock + counter + update_bpm), and EventQueue<E,64> […]
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 P1P4 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 […]