Commit graph

16 commits

Author SHA1 Message Date
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
8a19e5b52c refactor(ml)!: P2.1 storage-policy split — MLPCore<Storage>, fixed + dynamic models
Algorithms (forward, backprop/SGD, init, move_weights, diagnostics) now live
once in MLPCore<Storage> (nisps/ml/mlp.hpp). Storage models:

- FixedStorage (storage.hpp): template-sized std::array, zero heap. The
  classic MLP<NIn,H1,H2,H3,NOut,...> is an alias preserving kInput/kHidden*/
  kOutput/kNumLayers/weight_count() constexpr — firmware + bindings + modes
  compile unchanged.
- DynamicStorage (dynamic_storage.hpp): runtime dims, ONE arena allocation
  at construction, nothing per-call. #error under NISPS_TARGET_EMBEDDED
  (new macro in core/perf.hpp); sole lint-cpp.sh heap-allowlist entry, plus
  a lint check that fails if the #error guard disappears.

Verification:
- new ctest test_mlp_storage_parity: fixed↔dynamic BIT-identical across
  init/draw/inference/train(FIFO)/move_weights(pin mask)/eval_loss/
  layer_stats/set_weights/infer_batch/reset; invalid+moved-from inert
- golden ML vectors (pre-refactor constants) pass → bit-stable refactor
- native↔WASM parity PASS, max delta unchanged (2.4e-7)
- chokepoint B compile: PAFSynth .text 122324→122692 (+0.30%, ±1% budget);
  RAM +416B (eval scratch)
- fix: firmware-common.sh used bare 'python' (absent here) → ${PYTHON:-python3}

Part of one-core-engine-refactor P2. nisps_ml_create ABI untouched (P2.2 is
an operator stop-point).
2026-07-13 23:47:03 +02:00
monkey-w1n5t0n
0d1a2102eb feat(manifold)!: P1 — retire playground/, manifold is the sole browser app
Playground archived at branch archive/playground-solidjs (tag
playground-solidjs-final) and deleted from main. Retargets:

- run-all-tests.sh stage 5 → manifold (typecheck + bun test + build +
  playwright via non-snap node runner, BUILD-PLAN gotcha)
- ci.yml playground-tests → manifold-tests; osc-bridge.yml → manifold/osc-bridge
  (was already broken: playground/osc-bridge no longer existed)
- codegen: TS emission target removed (returns at P5 → manifold); golden
  test now C++-only; TS emitters retained dormant
- .gitignore: manifold/osc-bridge paths; drop dead playground faust exception
- docs: AGENTS.md gates, README quickstart, MAP.md, ALIGNMENT.md (C15 now
  archive-only — defect #1 updated), AGENT-REFERENCE.md, specs/MAIN.md

Part of docs/specs/plans/one-core-engine-refactor.md P1.
2026-07-13 23:27:56 +02:00
monkey-w1n5t0n
29dc88be3a chore(build): P0 plumbing — WASM build/parity retarget to manifold/public
- build-wasm.sh emits to manifold/public/ (transitional copy to
  playground/public/ until P1 retires the playground)
- parity-check.sh + parity_wasm.mjs read the manifold artifact
- fix stale MLP<2,...> arity in AGENT-REFERENCE.md + nisps/wasm/README.md
- gitignore .claude/worktrees/
- plan one-core-engine-refactor.md: P0 marked landed

Gate: run-all-tests green; parity PASS from manifold artifact (2.4e-7);
manifold builds against freshly-built nisps.wasm.
2026-07-13 23:14:23 +02:00
monkey-w1n5t0n
0a17b3e76e feat(animations+firmware): /next/animations showcase (videos + interactive demos), in-app Help link, Arch firmware build script
- assets/media/showcase/index.html: standalone showcase on Manifold tokens —
  the 4 Manim explainers + 2 live interactive demos (knob->number, XY->two sliders).
- Help drawer links to it (animations/).
- scripts/build-firmware-arch.sh: Omarchy/Arch firmware build (pacman deps +
  arduino-cli + delegates to setup-firmware-toolchain.sh; clear error on the
  unreachable memllib pin).
2026-06-28 04:42:27 +02:00
monkey-w1n5t0n
517bd2f987 feat(firmware): wire Explore-and-place glue to hardware buttons + selftest
Map enter/exit-explore, reroll, nudge, begin-place, commit-place to the
peripheral buttons via the shared FeedbackController. (Not compiled here —
no arduino-cli; Placing-audition static_output hook is a flagged follow-up.)
2026-06-28 04:14:30 +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
w1n5t0n
3138701100 Stream 11: verification infrastructure (golden vectors + parity + lint + CI + Playwright migration)
Agent ran out of API credits before committing. Files staged + committed by orchestrator. Coverage:
- tests/cpp/ml_golden_vectors.cpp: fixed-seed regression tests for MLP determinism
- tests/cpp/engine_impulse.cpp: white-noise impulse responses with binary baseline
- tests/cpp/parity_check.cpp + parity_wasm.mjs + parity_diff.mjs: native vs WASM bit-equivalence
- scripts/build-cpp-tests.sh, lint-cpp.sh, parity-check.sh, run-all-tests.sh
- playground/tests/e2e/{ml-engine,modes,persistence,ui-interactions}.spec.ts (+helpers)
- .github/workflows/ci.yml

(meml-x06)
2026-04-29 19:50:55 +03:00
w1n5t0n
5fc37f760e Stream 6: extract firmware glue under firmware/
Move the Arduino sketch into firmware/MEMLNaut-NISPS/ and bridge the
hardware (memllib) to the platform-agnostic nisps/ library through a
slim glue layer. Delete the legacy root-level *AudioApp.hpp,
modes/MEMLNautMode*.hpp, voicespaces/, IMLInterface.hpp, XiasriAnalysis,
and the src/memlp submodule.

Glue layout (firmware/MEMLNaut-NISPS/glue/):
  audio_driver.hpp - bridge memllib block callback to Mode::process
                     via per-Mode templated trampoline (no virtual dispatch)
  peripherals.hpp  - joystick/pots/buttons -> Mode::set_input + ML primitives
  midi_io.hpp      - MIDI in -> mode.note_on/update_bpm/set_playing,
                     drains mode ControlEvent ring -> MIDI UART
  mode_select.hpp  - using-aliases mapping MEMLNautMode<Name> to
                     nisps::modes::*Mode (build script rewrites the
                     #define MEMLNAUT_MODE_TYPE line)
  input_router.hpp / output_router.hpp - top-level wire/drain entry points

The sketch tree uses src/{memllib,daisysp,nisps} symlinks because
Arduino-CLI rejects ".." in include paths from sketch-tree headers.
mode_select.hpp #undefs Arduino's sq/min/max/abs/round macros before
including nisps headers (some nisps engines use those identifiers as
method names). The audio bridge struct is extern in the header and
defined in the .ino because inline + __not_in_flash section attribute
collide at link time.

Verification: arduino-cli compile succeeds for PAFSynth, ChannelStrip,
and BreakOr (rp2040:rp2040:solderparty_rp2350_stamp_xl:opt=Optimize3,
-std=gnu++20). Host C++ tests under nisps/build still pass (3 binaries,
110+ tests). Build script (scripts/build-firmware.sh) updated to point
at the new sketch path; mode-rewrite logic unchanged.

Closes meml-gkm.
2026-04-29 17:05:38 +03:00
w1n5t0n
f26ec923e1 feat(playground/wasm): WASM bridge between C++ core and SolidJS playground (meml-tgm)
Stream 7 wires nisps/ml + nisps/engines into the playground via Emscripten.

Highlights:
- nisps/wasm/bindings.cpp: flat C API per architecture.md §6.2. Fixed-arch
  MLP<2, 10, 14, 18, 126>; engine string→type dispatch table with NoOp
  fallback.
- scripts/build-wasm.sh: emcc invocation, MODULARIZE=1, exports listed
  explicitly; produces playground/public/nisps.{js,wasm}.
- playground/src/ml/wasm-iml.ts: main-thread MLP host (sync inference,
  sync training, RL ops, weights I/O, layer stats, localStorage).
- playground/src/ml/wasm-worker.ts: disposable Web Worker for off-thread
  async training, owns its own WASM instance.
- playground/src/ml/dataset.ts: Float32Array-backed FIFO with sample-weight
  modes (uniform/global/local/combined). Port of legacy dataset.js.
- playground/src/audio/engine-host.ts: AudioContext + AudioWorkletNode
  lifecycle, with start/stop/setEngine/setParams.
- playground/src/audio/worklet/nisps-processor.ts: WASM-loading
  AudioWorkletProcessor that runs engine.process_block per 128-sample
  block. Loads its own WASM instance from main-thread-supplied bytes
  (no fetch in worklet).
- playground/src/stores/ml-store.ts: wired stub methods to WasmIML
  singleton; lazy initialize().
- playground/src/debug/probe.ts: window.__nisps now calls real WasmIML
  via the store; lazy-init on first use.

Verified:
- bash scripts/build-wasm.sh succeeds (94 KB nisps.wasm)
- bun run typecheck OK
- bun run build OK (production bundle)
- vite dev server serves /nisps.{js,wasm} with COOP/COEP

Known limitation: WASM is fixed at one MLP shape. Multi-arch deferred —
documented in nisps/wasm/README.md.
2026-04-29 16:36:29 +03:00
w1n5t0n
c7da7bf4f7 Improve UF2 bootloader detection 2026-04-16 00:52:39 +09:00
w1n5t0n
6b26168a29 Preserve firmware variant capitalization 2026-04-16 00:46:02 +09:00
w1n5t0n
d1c12dd2b1 Fix firmware variant prompt TTY detection 2026-04-16 00:44:52 +09:00
w1n5t0n
39312a0d1f Add firmware variant selection to build scripts 2026-04-16 00:37:58 +09:00
w1n5t0n
314408aba9 Add firmware helper scripts and docs 2026-04-16 00:32:32 +09:00