Commit graph

5 commits

Author SHA1 Message Date
monkey-w1n5t0n
e37f16739e refactor(nisps): delete dead core/ML mass; keep the legacy feedback modes
Phase 1 group 2 (L27, L26, L28, S21, L13, ST6, S20).

- L27: fixed_buffer.hpp + its test + the CMake entry — no consumers.
- L26: dislike_multiplier_ and its doubling/halving bookkeeping — upstream
  InterfaceRL residue that drove nothing. The audit pointed at the wrong test
  file for the surviving reference; the actual assert was in
  test_mlp_geo_dislike.cpp:211, removed here.
- L28: added copy_weights_to(std::span<float>) to FixedStorage and
  DynamicStorage and switched feedback.hpp's take_snapshot/push_undo/nudge to
  it. Drops the permanent whole-net flat_ scratch buffer from FixedStorage and
  the per-gesture double copy. Behaviour-identical: same source values, same
  write order, same RNG draw order in nudge().
- S21 + L13: deleted NISPS_AUDIO_MEM / NISPS_APP_SRAM / NISPS_AUDIO_FUNC —
  zero use sites outside perf.hpp and comments — and rewrote midi_io.hpp's one
  misshapen NISPS_AUDIO_FUNC use as a plain `inline void`. perf.hpp now
  documents only the inlining/hotness macros that actually exist, and
  audio_driver.hpp no longer claims an SRAM discipline the code never had.
- ST6: feedback.hpp's header now describes the four current modes and the
  Geometric default, dropping the retracted "geometric push NOT ported" claim.

S20 — OPERATOR DECISION (§7.1): the four legacy feedback behaviours
(RandomiseOutputs, RandomiseMlp, AvoidStyle::Diffuse, the RandomiseMlp branch of
on_drag) are KEPT, not deleted. They are wanted as building blocks for
experimenting with how different instruments feel under different behaviours.
Each is now marked at its definition as deliberately-retained research reserve
so future audits stop flagging it as dead code.

L25 (the 16 KB firmware loss-history buffer) is NOT done here — see the phase
report; it turned out to be coupled into the shared mlp.hpp, and its fate
belongs with the browser telemetry build (§7.3 / plan §6.5e).

Gates: run-all-tests.sh ALL GREEN.
2026-07-21 12:48:27 +02:00
monkey-w1n5t0n
9490e20a7a feat(ml)!: P3 core — geometric dislike in nisps/, jolt/OU + geo ABI
Geometric dislike (rl-feedback-design §2.1/§4; upstream InterfaceRL @
0a541cc ported verbatim, constants included):

- nisps/ml/replay.hpp: ReplayView over storage-owned buffers — deepen-or-
  store negatives (dedup 0.05, clamp -16), k-NN positive centroid with
  deterministic index tie-break + fixed accumulation order, proportional
  decay (0.0025*max(|r|,1)) + eviction, order-preserving compaction.
- nisps/ml/geo_push.hpp: push-away target (pushStep clamp(|avgNeg|,.25,1)
  *0.5, taper /(1+len), useRandom on len<=1e-4 via nisps::Rng — the single
  deliberate divergence from libc rand()), negLRRatio 0.5-0.4*negFraction.
- mlp.hpp: train_targets(input, computed-target, lr, out_mask) — trains
  toward computed targets (negative lr = cold-start train-away); solo/
  focus gating zeroes masked derivs.
- feedback.hpp: AvoidStyle {Geometric (new default), Diffuse (legacy
  move_weights, kept for A/B)}; dislike_geometric() collapses upstream's
  press+optimise into one synchronous call; on_up in geometric Avoid
  feeds the positive centroid; dislike-multiplier bookkeeping. Storage
  gains replay buffers (Fixed: ReplayCap=32 firmware default ≈ +8KB SRAM;
  Dynamic arena: cap 64).
- bindings: nisps_ml_feedback_{dislike_geometric,store_positive,
  positive_count,negative_count,set_avoid_style} + P3.2 jolt/OU ABI:
  nisps_ml_jolt_{press,step,release,active,lr_scale,tick_lr_ramp},
  nisps_ml_explore_{intensity,get_intensity,apply} (OUNoise<4096>
  over-provisioned; same code the firmware ModeBase runs).
- parity v4: Stage 6 scripted geometric session (2 likes → 2 dislikes,
  f32-exact heard vectors via Math.fround) — 961 floats PASS at 2.4e-7.
- tests: test_mlp_geo_dislike.cpp (replay dedup/deepen/clamp, centroid
  tie-break, push direction/taper/mask/clamp, cold-start inertness +
  train-away, determinism, Diffuse legacy); legacy Avoid test pinned to
  Diffuse per the ADR's deliberate-break note.

Firmware: PAFSynth .text/.data unchanged (geometric path not referenced
by current glue). NOTE: discovered pre-existing bug 10c3e55c — the
explore/place wiring is linker-GC'd out of the PAFSynth ELF (predates
this refactor; evidence in the ergo task).
2026-07-14 04:16:21 +02:00
monkey-w1n5t0n
b6819fd26f feat(wasm)!: P2.2 — nisps_ml_create honours dims; runtime-shaped browser MLP + reshape
Operator-approved ABI change (P2 stop-point). The WASM MLP is now
MLPCore<DynamicStorage>:

- nisps_ml_create(input, output, hidden[3], n, seed) honours its args;
  non-positive/null fall back to the historical 32→[10,14,18]→126, so
  every pre-P2 caller (manifold, worker, parity harness) stays
  bit-identical. Invalid/oversized dims (>4096) → null.
- NEW nisps_ml_reshape(ml, in, out, hidden, n, spread): fresh net at the
  new dims, warm-started via nisps/ml/warm_start.hpp (overlapping region
  copied; rest keeps spread init); feedback controller re-created (state
  resets — reset-on-reshape modal is the front-end contract). Failure
  leaves the old net untouched.
- nisps_ml_describe(ml, out): takes the handle; null reports defaults.
- FeedbackController got the same storage split: algorithms in
  FeedbackControllerCore<FbStorage>; FixedFeedbackStorage keeps firmware/
  tests source-identical via the old alias; DynamicFeedbackStorage (one
  arena) sizes to the runtime net. Firmware .text unchanged (122692).
- MLHandle: per-instance scratch vectors; dropped the dead 2MB
  batch_out_scratch.
- TS: types.ts decls (+_nisps_ml_reshape), wasm-iml re-describes the
  created instance, worker carries a shape-contract note for P2.3.

Verified: ctest 4/4 incl. new warm-start grow/shrink test; reshape ABI
smoke (dims honoured, overlap survives, invalid rejected, outputs
bounded); parity PASS unchanged (2.4e-7); lint clean; manifold 9 unit +
20 e2e green; firmware .text 122692 (+0.30% vs pre-P2 baseline).
2026-07-14 03:38:06 +02:00
monkey-w1n5t0n
c986377b4c feat(firmware): reposition gesture — relocate an existing example to a new input
Add a "grab → move → drop" gesture that moves an existing positive
example's output to a new input position, preserving the output. This is
the new core's home for upstream InterfaceRL's drag-store/reposition-commit,
distinct from Explore→Place (which places newly-auditioned scratchpad sounds).

- nisps/ml/feedback.hpp: begin_reposition()/commit_reposition()/repositioning().
  Reuses the Placing state (static_output holds the carried vector) but a
  reposition_ flag makes commit AND the mode-switch teardown SKIP the weight
  restore — the real net is never set aside here, so restoring snapshot_ would
  clobber the live trained net. Guards cancel_place + abort_explore_place.
- firmware glue: state-gate Toggle B. Exploring → reroll/nudge (unchanged);
  Idle → MomB1 grab, MomB2 drop (commit + add_example + train). The 4D variant
  has no joystick button, so the gesture lives on the momentary toggle. Also
  fix a stale top-of-file control-map comment that contradicted the bindings.
- tests: 4 reposition cases (hold without snapshot; commit stores carried
  output with no restore; mode-switch aborts without clobber; begin-only-Idle).
- MAP.md: document the full ExploreAndPlace lifecycle + reposition wiring.

Audio-hold (carrying the sound audibly during the move) remains the existing
unwired static_output() TODO and affects Explore→Place identically.
Firmware compile unverified (no arduino-cli); host tests + lint pass.
2026-06-28 23:45:27 +02:00
monkey-w1n5t0n
22efb1c411 feat(nisps/ml): crystallise Explore-and-place into shared FeedbackController
Add FeedbackMode::ExploreAndPlace + Idle/Exploring/Placing state machine
(no-heap, deterministic nisps::Rng): enter/exit_explore, reroll, nudge, undo,
begin_place, commit_place, cancel_place + on_down/on_up browser policy. Wire
the nisps_ml_feedback_* C API + EXPORTED_FUNCTIONS, extend parity Stage 5d.
Fix set_mode(3) falling back to Avoid. Native ctest 4/4; parity native==WASM
within 1e-5 (max delta 2.4e-7). Rebuilt nisps.{js,wasm}.
2026-06-28 04:14:12 +02:00