Phase 3 (L38, ST4).
L38 is a REAL, VISIBLE behaviour change, and it is a bug fix rather than a wash.
There were two divergent applyCurve implementations: model.ts's
(`e = 0.25 + c*1.75`, linear at c≈0.43) drove the on-screen bars, while
mapping.ts's spec-anchored version (0.5 = exactly linear, symmetric in
log-exponent space) drove `mapOutput` — i.e. the value actually sent to MIDI/OSC/
VCV. So the display disagreed with the signal at every curve setting except the
shared endpoint. mapping.ts's survives; model.ts's is deleted and re-exported.
Displayed values now move visibly, and they now match what is transmitted.
That unification exposed a third copy the finding did not mention: CurvePad.tsx
inlined the same deleted formula to draw the curve-knob preview and its numeric
readout. Left alone it would have matched NEITHER implementation — the knob
would have drawn one response while the bars and the output used another.
CurvePad now calls the same applyCurve, so knob, bars and transmitted value are
one thing. The readout shows the actual exponent.
ST4: GROUP_COLOR was duplicated across four files (Phase 1's ReadoutStrip
deletion removed a fifth). All four now import the single map in model.ts —
including OutputStage.tsx's OUT_GROUP_COLOR, which was outside the sweep's scope
and would have been the last survivor.
NOT done, deliberately: ST4 also invited replacing the fixed map with a
hash-to-palette function, because its keys (formant/pitch/amp/filter/fx/mod) are
JSX-era placeholders that do not match the real schema group strings
(verb/sequencer/general/filterbank/delays/eq/midi/...), so most groups currently
fall through to the accent colour. That is a visual redesign, not a
deduplication, and it should be one deliberate change now that every consumer
reads one map.
Gates: typecheck clean, 17/17 unit tests, 33 e2e specs.
Phase 1 group 5 (S15, S16, S18, S19, L22, L23, L20, L21, L1 delete-half).
- S15: the four-way focus/altitude system. setFocus was never called anywhere,
so only the 'composite' branch was reachable. Deleted SplitStage,
ReadoutStrip, InputMini, AltitudeNav, CompactAxis, the UI Focus type/prop,
the focus branches, stripPinned and the vacuous keyboard gates. MiniMeters
kept; engine.feedback.setFocus (a different, live thing) untouched.
- S16 + L1: the decorative stratum that rendered real-looking controls driving
nothing — A/B machinery, the fake seed, seededGradient + weightsRevision,
snapshots, master volume, bpm, and the learningRate/decay/tame/spreadLevel
sliders with their Drawers rows. Each was confirmed self-referential first.
NOTE a real behaviour change falls out of dropping `snapshots`: Undo outside
an active explore-and-place session used to pop a UI-only snapshot that
restored noiseCap/seed. It is now simply inactive unless a genuine
core-backed scratchpad undo exists. Geometric-dislike mode never had a real
undo primitive in the core, so only the fake path is gone.
- S18: BackendAdvanced.tsx and its Drawers block. It self-described as a
duplicate of the inline OutputsBackendConfig editor and BOTH rendered in the
same expanded drawer. OutputsBackendConfig already covers every backend.
- S19: pruned ConsoleCtx to the fields Dock/Drawers/OutputsBackendConfig
actually read; deleted the Axes type + axes/setAxis and the
preset/setPreset/offsetActive chain (permanently 'Sculpt'/false).
KEPT ctx.modes and ctx.setModeId despite having no reader today — the
Phase 5 instrument picker (§7.6, adopted) is built on exactly that plumbing.
- L22: the 5 dead primitives (Panel, StatusLine, ControlAxis, CurvePlot,
Sparkline) and their barrel exports, plus the now-dead .mf-axis-input CSS.
- L23: OutputControl/toOutputControl, ModeIconComponent and the BACKENDS
catalogue; Drawers now reads modeDesc.label/description from OUTPUT_MODES,
the surviving single catalogue.
- L20: the solo-mode selector's two unimplemented options no longer pretend to
be selectable.
- L21: FeedbackController vestiges — seed/undoDepth options, maxUndo, and six
ControllerEngine members nothing called (the finding named three; the other
three are used on the real EngineApi by debug/probe.ts, a different
interface, so removing them from ControllerEngine is safe).
Gates: run-all-tests.sh ALL GREEN (typecheck, 33 Playwright specs).
- mf-slider-input fill used calc(var(--mf-pct)*100%) but three consumers
(OutputControlRow held slider, OutputEditor, shared-ui Field) never set
--mf-pct, so the coloured track-fill stayed empty while only the native
thumb moved. Set --mf-pct inline on all three; harden the base class
(appearance:none + transparent bg + --mf-pct fallback + moz-range-progress).
- hide the two concentric noise-cap exploration rings around the input dot.
Adds the Manifold app (manifold/) — the convertible-mode React front-end on
the real NISPS ML+audio engine, served live at meml.lnfinitemonkeys.org/next/.
Console chrome trimmed per UI pass:
- drop mode label + subtitle from the top-left overlay (keep MEMLNaut wordmark)
- remove the composite split preset/ratio readout (top-centre)
- remove the OUTPUT corner tag above the bars
- remove the A/B compare toggle from the verdict cluster
- remove the follow button + input/noise readout (bottom-left)
- remove AltitudeNav focus switcher (bottom-right)