diff --git a/docs/port/HANDOFF.md b/docs/port/HANDOFF.md index 3fb2706f..72703d38 100644 --- a/docs/port/HANDOFF.md +++ b/docs/port/HANDOFF.md @@ -14,6 +14,36 @@ delivered. + +## ✅ 2026-08-31 — submenus reset; the main menu is the only screen that remembers + +**measured, and it completes the focus rule.** `LOAD GAME`, `TUTORIAL` and +`OPTIONS` all **RESET** on re-entry, joining `EXTRAS`. With the main menu +persisting, that is **four of four submenus resetting** and one exception. + +| screen | verdict | +|---|---| +| `LOAD GAME`, `TUTORIAL`, `OPTIONS`, `EXTRAS` | **RESETS** | +| main menu | **PERSISTS** | + +Your `guard_focus_scope` can move from *"two measured screens disagree, three +unmeasured"* to *"submenus reset, the main menu persists"* — but the guard is still +right to exist: it is measured per screen, not derived. + +❔ **`NEW GAME` remains deliberately untested** — it starts a game. +❔ **And your MISSION-SELECT-vs-top-item question is still open.** None of these +three separates it: each opens on its own first item. `LOAD GAME` looked like a +counter-example — it opens on slot 01 with slots 19 and 20 drawn *above* — but that +is a wrapping list around a centred selection, and 01 is still first. + +⚠️ Reach: one boot, one round trip per screen, one direction, one entry each. A +reset after a **reboot** is untested. + +[data](../re/data/submenu-focus-all-reset.txt) · +[TUTORIAL](../re/captures/menu-nav/live-tutorial-submenu.png) · +[LOAD GAME](../re/captures/menu-nav/live-load-game-slots.png) + + ## ❔ 2026-08-30 — LOAD GAME, TUTORIAL and OPTIONS: still unmeasured, and why **No new value here. This is a negative, so you know what I tried and what it diff --git a/docs/re/data/submenu-focus-all-reset.txt b/docs/re/data/submenu-focus-all-reset.txt new file mode 100644 index 00000000..3aff70a4 --- /dev/null +++ b/docs/re/data/submenu-focus-all-reset.txt @@ -0,0 +1,62 @@ +# Do LOAD GAME, TUTORIAL and OPTIONS remember their cursors? ✅ NO -- ALL RESET. +# MEASURED 2026-08-31, one boot, fourth attempt. +# +# The main menu PERSISTS its cursor across menu -> title -> menu +# (focus-persists-across-title.txt). EXTRAS RESETS (extras-focus-resets.txt). +# Two screens disagreeing means no menu-wide rule and every screen must be +# measured. These are the three that were left. ❔ NEW GAME stays deliberately +# untested -- it starts a game. +# +# LOAD GAME RESETS in-cursor 21.6 from opened vs 86.3 from where left +# TUTORIAL RESETS in-cursor 2.3 from opened vs 113.2 from where left +# OPTIONS RESETS in-cursor 1.9 from opened vs 102.6 from where left +# +# ✅ SO: FOUR OF FOUR MEASURED SUBMENUS RESET. Only the MAIN MENU persists, and +# it is the exception rather than the rule. +# +################################################################################ +# WHY THIS RUN WORKED WHERE THREE DID NOT -- every control here is a previous +# failure: +# +# * DECISION ON THE CURSOR'S OWN REGION. The pixels that change when the cursor +# moves ARE the cursor, so no per-screen geometry is assumed. Sweep 1 voided +# all three because ring_row.py scans the MAIN MENU's gutter (x 500:542) and +# these screens put their cursors at x 97..231, 338..1099 and 153..479 -- it +# was reading a static element and reporting no motion. +# * NARROW back-on-the-menu test, by ring row. Sweep 2 died when a crash dialog +# covered the screen centre: a whole-frame identity test can never match again +# once anything overlays the frame, while the narrow column kept reading. +# * ABSOLUTE row check after EVERY navigation press, not just the total -- a +# constant offset passes a differential control exactly, which is how an +# earlier run walked to OPTIONS believing it was EXTRAS. +# * A TWO-SIDED SELF-TEST that constructs BOTH verdicts from known frames and +# exits 3 if either is wrong. It passed here; it had already caught a rule I +# broke myself in sweep 3, which would otherwise have reported RESETS for all +# three screens -- the same answer, fabricated. +# * Every press confirmed from the guest's own [RE-INPUT] log. +# * The tool COMMITTED BEFORE RUNNING, and nothing else run during the boot. +# +# ✅ AND THE SCREENS ARE CONFIRMED BY EYE, because a previous run was fooled about +# which screen it was on: +# captures/menu-nav/live-tutorial-submenu.png -- TUTORIAL: BASIC CONTROLS / +# HEADS-UP DISPLAY / RADAR under "Level 1", SUPPLY AND SPECIAL MOVES / RADIO +# ORDERS / ADVANCED CONTROLS under "Level 2", then BACK. Seven items in two +# groups, with a description panel on the left. +# captures/menu-nav/live-load-game-slots.png -- LOAD GAME: a SCROLLING slot +# list with the selection held at the vertical CENTRE, Details panel at right. +# +# 📌 LOAD GAME's 21.6 is the one number that is not near zero, and the capture +# explains it: the list SCROLLS rather than moving a ring, so a DOWN redraws the +# whole list and re-entry restores the scroll position rather than a cursor sprite. +# 4x separation, same verdict, different mechanism. +# +# ❔ STILL NOT SEPARATED: "resets to the named item" vs "resets to the TOP item". +# sylpheed-port asked for a submenu whose opening item is not its first, which +# would decide it. None of these is one. TUTORIAL opens on BASIC CONTROLS (first), +# OPTIONS on GAME SETTINGS (first), and LOAD GAME on slot 01 -- which LOOKS +# non-first because slots 19 and 20 are drawn above it, but that is the list +# wrapping around a centred selection, and 01 is still the first slot. +# +# ⚠️ REACH: one boot, one round trip per screen, one direction (DOWN), and one +# entry each. Not tested: a second re-entry, a reset after a reboot, or whether +# any submenu behaves differently when entered from a different parent focus. diff --git a/docs/re/menu-navigation-semantics.md b/docs/re/menu-navigation-semantics.md index c53074d1..ed40ac4b 100644 --- a/docs/re/menu-navigation-semantics.md +++ b/docs/re/menu-navigation-semantics.md @@ -30,6 +30,41 @@ with [`tools/re-capture/menu_focus.py`](../../tools/re-capture/menu_focus.py). Wrap holds on both screens tested — the 5-item main menu and the 3-item `EXTRAS` submenu — so it is a menu rule, not a per-screen table. +## ✅ 2026-08-31 — ALL FOUR measured submenus reset. The main menu is the exception. + +**measured** — [`data/submenu-focus-all-reset.txt`](data/submenu-focus-all-reset.txt), +`tools/re-capture/submenu_focus_sweep.py`, one boot, fourth attempt. + +| screen | verdict | in-cursor: from opened / from where left | +|---|---|---| +| `LOAD GAME` | **RESETS** | 21.6 / 86.3 | +| `TUTORIAL` | **RESETS** | 2.3 / 113.2 | +| `OPTIONS` | **RESETS** | 1.9 / 102.6 | +| `EXTRAS` (2026-08-30) | **RESETS** | 0.8 / 82.8 | +| **main menu** | **PERSISTS** | — | + +✅ **So the rule is simple after all, and it is the opposite of what one screen +suggested**: submenus reset; the **main menu alone** remembers. Four of four. + +✅ **Screens confirmed by eye**, because an earlier run was fooled about which +screen it was on: [`TUTORIAL`](captures/menu-nav/live-tutorial-submenu.png) — seven +items under `Level 1`/`Level 2` headers plus `BACK` — and +[`LOAD GAME`](captures/menu-nav/live-load-game-slots.png), a **scrolling** slot list +with the selection held at the vertical centre. + +📌 `LOAD GAME`'s 21.6 is the only figure not near zero, and the capture explains it: +that list **scrolls** instead of moving a ring, so re-entry restores a scroll +position rather than a cursor sprite. Same verdict, different mechanism. + +❔ **Still not separated: "resets to the named item" vs "resets to the top item".** +`sylpheed-port` asked for a submenu whose opening item is not its first. None of +these is one — `TUTORIAL` opens on `BASIC CONTROLS`, `OPTIONS` on `GAME SETTINGS`, +and `LOAD GAME` on slot **01**, which *looks* non-first only because slots 19 and 20 +are drawn above it by a wrapping list around a centred selection. + +⚠️ Reach: one boot, one round trip per screen, one direction, one entry each. +❔ `NEW GAME` stays deliberately untested. + ## ✅ 2026-08-30 — EXTRAS **resets**; the main menu **persists**. They differ. **measured** — [`data/extras-focus-resets.txt`](data/extras-focus-resets.txt),