memlnaut-nisps/playground/src/modes/mode-helpers.ts

67 lines
2 KiB
TypeScript
Raw Normal View History

/**
* Helpers shared across mode TSX files. Pure functions; no Solid state.
*/
import type { Param } from './generated/types';
import type { SliderConfig } from '../primitives/SliderBank';
import type { CurveName } from '../output/curves';
/**
* Convert a schema param list into SliderConfig entries that the SliderBank
* primitive understands. Sliders are grouped by the schema's `group` field
* so the bank renders collapsible sections.
*/
export function paramsToSliderConfig(params: ReadonlyArray<Param>): SliderConfig[] {
let lastGroup: string | null = null;
return params.map((p) => {
const isNewGroup = p.group !== lastGroup;
lastGroup = p.group;
const cfg: SliderConfig = {
id: p.name,
label: p.label,
min: p.min,
max: p.max,
curve: p.curve as CurveName,
};
if (isNewGroup) cfg.section = formatGroupName(p.group);
return cfg;
});
}
/**
* Map a Float32Array (length = N) of normalized values [0,1] to a flat
* array sized to match the slider config (already in min/max range).
playground/stream-10: wire phase 1-4 features into modes (meml-5wg) Builds the SolidJS-side feature parity with the legacy a-immersive playground. Every Phase 1–4 feature called out in .local/recon/04-playground.md now flows through the runtime → stores → primitives pipeline. Phase 1 (compound axes / zoom / drawer / trail): - control-routing.ts: resolves Boldness/Memory/Precision into input/output/exploration store writes via createEffect. - SettingsDrawer (new): tabbed sections for Input / Training / Exploration / Output / Per-param overrides / Advanced. Per-param ParamEditor list wires through modeStore.setOverride. - JoyMap navigator added to ModeShell; tap-to-return + long-press region pin handlers wired into the runtime. - Anchor mode toggle (auto/sticky/center) exposed via drawer. Phase 2 (pinning / history / A/B): - features/snapshots.ts: bridge sessionStore push/pop to actual Float32Array weights. Auto-snapshot before train/randomize/thumbs-down. - Undo button + long-press snapshot list popup wired in ModeShell. - A/B capture/toggle/accept/revert in SettingsDrawer. - features/overrides.ts buildPinMask() composes override `pinned` flags + sessionStore param pins; passed to mlStore.moveWeights. - Region pinning long-press → addRegionPin + auto-snapshot tag "pinned baseline". Phase 3 (refinement / exploration): - features/heatmap-sampler.ts: 16x16 grid via mlStore.inferBatch, three colour modes, throttled 5/sec, refreshed on ml.trained / ml.delta_update bus events. - exploration-store.ts (new): RL noise level, floor/cap/growth/decay, spread, learning rate, weight decay, auto-explore, pressure. - Auto-explore timer in mode-runtime drives moveWeights at user interval, zoom-scaled intensity. - Pressure feedback: window pointerdown/up timestamps mapped to explorationStore.setPressure; feeds growNoise/decayNoise. Phase 4 (output / persistence / polish): - features/weight-health.ts: histogram, status, per-layer L2 deltas, vanishing/exploding/converged classification. - features/session-preset.ts: full state capture/restore + base64url URL sharing; main.tsx applies on load. - SettingsDrawer Advanced tab renders WeightHealth, GradientFlow, LayerStats, Heatmap, session preset save/load/share. Override application: - features/overrides.ts applies per-param mute/freeze/curve/range between MLP outputs and the engine. Mode runtime exposes `paramOutputs` (length = schema.params) which all modes now bind to OutputDisplay so ranges and mutes are visible. - Freeze flags push into outputStore.freezeMask reactively. Mic input: - features/mic-input.ts: getUserMedia + AnalyserNode-derived {energy, brightness, pitch, aperiodicity}. Mode runtime feeds them into channels 2..(input_size-1) when active. ModeShell shows a Mic toggle for audio_in modes. Debug probe (probe.ts): - Synchronous bypass for snapshot, A/B, pins, overrides, axes, spread, output freeze, heatmap, weight health, session presets, URL params, bus emit/on. Untracked reads/writes throughout to avoid SolidJS reactivity surprises in tests. Modes: - All 8 firmware mode TSX files now use the default SettingsDrawer (no per-mode SliderBank scaffolding). They bind OutputDisplay to runtime.paramOutputs (post-override) instead of processedOutputs. Build status: - bun run typecheck: clean - bun run build: clean - dev server smoke: index, /modes, mode-runtime, SettingsDrawer, features/* all serve. Note: bd close meml-5wg failed because Dolt server unreachable from this worktree. Issue should be closed manually by orchestrator.
2026-04-29 16:33:01 +02:00
*
* If `overrides` is supplied, per-param min/max overrides are honoured
* instead of the schema defaults this is what the mode UI sliders
* display when the user has tightened the active range.
*/
export function outputsToSliderValues(
outputs: Float32Array,
params: ReadonlyArray<Param>,
playground/stream-10: wire phase 1-4 features into modes (meml-5wg) Builds the SolidJS-side feature parity with the legacy a-immersive playground. Every Phase 1–4 feature called out in .local/recon/04-playground.md now flows through the runtime → stores → primitives pipeline. Phase 1 (compound axes / zoom / drawer / trail): - control-routing.ts: resolves Boldness/Memory/Precision into input/output/exploration store writes via createEffect. - SettingsDrawer (new): tabbed sections for Input / Training / Exploration / Output / Per-param overrides / Advanced. Per-param ParamEditor list wires through modeStore.setOverride. - JoyMap navigator added to ModeShell; tap-to-return + long-press region pin handlers wired into the runtime. - Anchor mode toggle (auto/sticky/center) exposed via drawer. Phase 2 (pinning / history / A/B): - features/snapshots.ts: bridge sessionStore push/pop to actual Float32Array weights. Auto-snapshot before train/randomize/thumbs-down. - Undo button + long-press snapshot list popup wired in ModeShell. - A/B capture/toggle/accept/revert in SettingsDrawer. - features/overrides.ts buildPinMask() composes override `pinned` flags + sessionStore param pins; passed to mlStore.moveWeights. - Region pinning long-press → addRegionPin + auto-snapshot tag "pinned baseline". Phase 3 (refinement / exploration): - features/heatmap-sampler.ts: 16x16 grid via mlStore.inferBatch, three colour modes, throttled 5/sec, refreshed on ml.trained / ml.delta_update bus events. - exploration-store.ts (new): RL noise level, floor/cap/growth/decay, spread, learning rate, weight decay, auto-explore, pressure. - Auto-explore timer in mode-runtime drives moveWeights at user interval, zoom-scaled intensity. - Pressure feedback: window pointerdown/up timestamps mapped to explorationStore.setPressure; feeds growNoise/decayNoise. Phase 4 (output / persistence / polish): - features/weight-health.ts: histogram, status, per-layer L2 deltas, vanishing/exploding/converged classification. - features/session-preset.ts: full state capture/restore + base64url URL sharing; main.tsx applies on load. - SettingsDrawer Advanced tab renders WeightHealth, GradientFlow, LayerStats, Heatmap, session preset save/load/share. Override application: - features/overrides.ts applies per-param mute/freeze/curve/range between MLP outputs and the engine. Mode runtime exposes `paramOutputs` (length = schema.params) which all modes now bind to OutputDisplay so ranges and mutes are visible. - Freeze flags push into outputStore.freezeMask reactively. Mic input: - features/mic-input.ts: getUserMedia + AnalyserNode-derived {energy, brightness, pitch, aperiodicity}. Mode runtime feeds them into channels 2..(input_size-1) when active. ModeShell shows a Mic toggle for audio_in modes. Debug probe (probe.ts): - Synchronous bypass for snapshot, A/B, pins, overrides, axes, spread, output freeze, heatmap, weight health, session presets, URL params, bus emit/on. Untracked reads/writes throughout to avoid SolidJS reactivity surprises in tests. Modes: - All 8 firmware mode TSX files now use the default SettingsDrawer (no per-mode SliderBank scaffolding). They bind OutputDisplay to runtime.paramOutputs (post-override) instead of processedOutputs. Build status: - bun run typecheck: clean - bun run build: clean - dev server smoke: index, /modes, mode-runtime, SettingsDrawer, features/* all serve. Note: bd close meml-5wg failed because Dolt server unreachable from this worktree. Issue should be closed manually by orchestrator.
2026-04-29 16:33:01 +02:00
overrides?: Record<string, { min: number; max: number; muted?: boolean; fixedValue?: number }>,
): number[] {
const out: number[] = [];
for (let i = 0; i < params.length; ++i) {
const v = outputs[i] ?? 0;
const p = params[i]!;
playground/stream-10: wire phase 1-4 features into modes (meml-5wg) Builds the SolidJS-side feature parity with the legacy a-immersive playground. Every Phase 1–4 feature called out in .local/recon/04-playground.md now flows through the runtime → stores → primitives pipeline. Phase 1 (compound axes / zoom / drawer / trail): - control-routing.ts: resolves Boldness/Memory/Precision into input/output/exploration store writes via createEffect. - SettingsDrawer (new): tabbed sections for Input / Training / Exploration / Output / Per-param overrides / Advanced. Per-param ParamEditor list wires through modeStore.setOverride. - JoyMap navigator added to ModeShell; tap-to-return + long-press region pin handlers wired into the runtime. - Anchor mode toggle (auto/sticky/center) exposed via drawer. Phase 2 (pinning / history / A/B): - features/snapshots.ts: bridge sessionStore push/pop to actual Float32Array weights. Auto-snapshot before train/randomize/thumbs-down. - Undo button + long-press snapshot list popup wired in ModeShell. - A/B capture/toggle/accept/revert in SettingsDrawer. - features/overrides.ts buildPinMask() composes override `pinned` flags + sessionStore param pins; passed to mlStore.moveWeights. - Region pinning long-press → addRegionPin + auto-snapshot tag "pinned baseline". Phase 3 (refinement / exploration): - features/heatmap-sampler.ts: 16x16 grid via mlStore.inferBatch, three colour modes, throttled 5/sec, refreshed on ml.trained / ml.delta_update bus events. - exploration-store.ts (new): RL noise level, floor/cap/growth/decay, spread, learning rate, weight decay, auto-explore, pressure. - Auto-explore timer in mode-runtime drives moveWeights at user interval, zoom-scaled intensity. - Pressure feedback: window pointerdown/up timestamps mapped to explorationStore.setPressure; feeds growNoise/decayNoise. Phase 4 (output / persistence / polish): - features/weight-health.ts: histogram, status, per-layer L2 deltas, vanishing/exploding/converged classification. - features/session-preset.ts: full state capture/restore + base64url URL sharing; main.tsx applies on load. - SettingsDrawer Advanced tab renders WeightHealth, GradientFlow, LayerStats, Heatmap, session preset save/load/share. Override application: - features/overrides.ts applies per-param mute/freeze/curve/range between MLP outputs and the engine. Mode runtime exposes `paramOutputs` (length = schema.params) which all modes now bind to OutputDisplay so ranges and mutes are visible. - Freeze flags push into outputStore.freezeMask reactively. Mic input: - features/mic-input.ts: getUserMedia + AnalyserNode-derived {energy, brightness, pitch, aperiodicity}. Mode runtime feeds them into channels 2..(input_size-1) when active. ModeShell shows a Mic toggle for audio_in modes. Debug probe (probe.ts): - Synchronous bypass for snapshot, A/B, pins, overrides, axes, spread, output freeze, heatmap, weight health, session presets, URL params, bus emit/on. Untracked reads/writes throughout to avoid SolidJS reactivity surprises in tests. Modes: - All 8 firmware mode TSX files now use the default SettingsDrawer (no per-mode SliderBank scaffolding). They bind OutputDisplay to runtime.paramOutputs (post-override) instead of processedOutputs. Build status: - bun run typecheck: clean - bun run build: clean - dev server smoke: index, /modes, mode-runtime, SettingsDrawer, features/* all serve. Note: bd close meml-5wg failed because Dolt server unreachable from this worktree. Issue should be closed manually by orchestrator.
2026-04-29 16:33:01 +02:00
const ov = overrides?.[p.name];
if (ov && ov.muted && ov.fixedValue !== undefined) {
out.push(ov.fixedValue);
continue;
}
const min = ov?.min ?? p.min;
const max = ov?.max ?? p.max;
out.push(min + v * (max - min));
}
return out;
}
function formatGroupName(group: string): string {
if (!group) return '';
return group
.split(/[_\s]+/)
.map((p) => p.charAt(0).toUpperCase() + p.slice(1))
.join(' ');
}