Twinned from https://github.com/cfsh/ninefold/issues/367 by tools/beads/import_github.py's reconcile pass.
Suggestions from ninefold-reviewer's review of #334. All are advisory residuals left at result=CONVERGED — none blocked the PR, none are regressions.
1. games/tonapse/CONTROLS.md never updated for #334 (flagged on all three passes).
The PR adds a genuinely new gesture — the mouse wheel scrolls both the SONG window and the SOUNDS strip (SongGrid.OnScrollViewInput:214, SoundPicker.OnChipWheel:169) — plus hard-wired d-pad neighbours that clamp the SOUNDS strip horizontally so focus can never leave the row (SoundPicker.cs:120-121). The doc's own footer: "_Update this doc whenever a control gesture is added or changed._"
Separately, the Focus-model Scroll bullet (CONTROLS.md:87-88) still describes ScrollContainer.FollowFocus with bottom headroom; TonapseHome.cs says that was removed in #308, so that line is stale independent of this PR.
2. The F1 regression leg can't actually fail on F1.
tools/probes/grid-scroll.json now edits the settled bottom cell and asserts expect_focus: SongCellButton — but under the F1 bug focus *was* alive on the cell, just scrolled outside the clip window and invisible. The assertion passes either way; only the scroll-02b-edit-rebuild-keeps-offset shot shows the difference, and shots aren't assertions. Worth a probe verb that asserts the focused control's rect is inside its scroll window's rect (or an expect_visible-style check), so the worst defect this PR carried gets a test that can go red.
3. Boundary sweep still only covers 8 sounds.
The threshold this PR *introduces* is MaxVisibleRows = 5.5f (SongGrid.cs:170) — 5 sounds (no overflow: hint hidden, _scrollY forced to 0 by the contentH <= viewH early return at :188) vs 6 sounds (first overflow, first peek). Neither side is asserted, nor the 1-sound / no-song-loaded cases. aedanpope's ask was explicitly count-dependent ("when I have exactly 8 sounds…"), so 5↔6 is the next one likely to bite.
4. Mouse-wheel scrolling decouples the focus ring from the window.
ScrollBy (SongGrid.cs:222) moves _scrollTarget without touching focus, and nothing re-clamps to the focused row until the next UpdateScrollLayout. Wheel far enough and the focused cell leaves the clip window — but FocusGlide draws at the target's global rect on an unclipped overlay (FocusGlide.cs:73-74, 101-104), so the ring paints over the SOUNDS card with no cell under it. Self-recovers on the next d-pad press, and mouse-only, so well below the gate — but it's the same visual as the F1 symptom. Options: re-clamp the focus target after a wheel scroll, or clip the glide to the focused control's nearest ClipContents ancestor.
5. Cosmetic: UpdateScrollLayout calls _scrollHint.Sync twice per invocation — :186 (pre-clamp _scrollY, needed only so the early return at :188 hides the hint) and :209. Hoisting the hide into the early-return branch would leave one sync on the live path.
None.
No comments.