feat(manifold): default to geometric push + add Clear examples button

Geometric-dislike ('Push away', Mode 1) is now the default feedback mode
instead of explore-and-place, which works poorly. Add a Clear button to
the Learning drawer that forgets all recorded examples and wipes the
on-map visuals (feedback markers + placed-anchor pins) via the existing
ctx.onClear, now also resetting pins.
This commit is contained in:
monkey-w1n5t0n 2026-06-29 00:36:32 +02:00
parent 031c7f97ff
commit d2b0427ec6
3 changed files with 24 additions and 5 deletions

View file

@ -196,9 +196,10 @@ a setting → `--r-*` tokens.
### Feedback — `src/feedback/`
- `controller.ts` (**~490 lines**) — `FeedbackController`, framework-neutral, owned by ConsoleApp.
Two modes: **explore-and-place** (default, Mode 2, positive-only — drives the C++ core's
snapshot/scratchpad/undo lifecycle; caller accumulates anchors and trains on finalise with
warm-start) and **geometric-dislike** (Mode 1, selectable). Solo/arm via per-output mask.
Two modes: **geometric-dislike** (default, Mode 1, "Push away" — down carves the current sound
away from what you like, directed repulsion) and **explore-and-place** (Mode 2, positive-only,
selectable — drives the C++ core's snapshot/scratchpad/undo lifecycle; caller accumulates anchors
and trains on finalise with warm-start). Solo/arm via per-output mask.
- `rng.ts``SeededRng` (deterministic xorshift32 + gaussian). **Stand-in** until the C++ nudge owns
the stream — not bit-identical to `nisps::Rng`.
- **`--- C++ GAP ---` markers** flag behaviour approximated in TS pending C++ port: true geometric

View file

@ -112,8 +112,9 @@ export function ConsoleApp({ focus: initialFocus = 'composite' }: ConsoleAppProp
const [sandwich, setSandwich] = useState(false);
// Learning-behaviour store (dock-spec §1; rl-feedback-design). Default
// feedback mode = "Explore and place"; default solo = "Mask gradients".
const [feedbackMode, setFeedbackModeState] = useState<FeedbackModeUI>('explore-and-place');
// feedback mode = "Push away" (geometric); default solo = "Mask gradients".
// (Explore-and-place is selectable but the geometric push is the better default.)
const [feedbackMode, setFeedbackModeState] = useState<FeedbackModeUI>('geometric-dislike');
const [soloMode, setSoloMode] = useState<SoloMode>('mask-gradients');
const [exploring, setExploring] = useState(false);
const [learningPaused, setLearningPaused] = useState(false);
@ -654,10 +655,14 @@ export function ConsoleApp({ focus: initialFocus = 'composite' }: ConsoleAppProp
onAddExample: addExample,
onTrain: train,
onClear: () => {
// Drop the recorded training examples AND every on-map visual that
// represents them (feedback markers + placed-anchor pins). The cursor
// trail is ephemeral and self-decays, so it needs no explicit reset.
engine?.clearExamples();
setExamples(0);
setLoss([]);
setMarkers([]);
setPins([]);
},
snapshots,
onJump: (id) => {

View file

@ -168,6 +168,19 @@ function LearningDrawer(ctx: ConsoleCtx, depth: DrawerDepth) {
</p>
)}
<SectionLabel>Recorded examples</SectionLabel>
<div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
<Chip>
{ctx.datasetCount} example{ctx.datasetCount === 1 ? '' : 's'}
</Chip>
<Button size="sm" variant="secondary" onClick={ctx.onClear}>
Clear
</Button>
<span style={{ fontSize: 'var(--fs-xs)', color: 'var(--fg-dim)' }}>
forget every example & wipe the on-map marks
</span>
</div>
{depth === 'expanded' && (
<>
<SectionLabel>Solo / arm scope</SectionLabel>