diff --git a/docs/re/captures/main-menu-items.png b/docs/re/captures/main-menu-items.png new file mode 100644 index 00000000..222b719c Binary files /dev/null and b/docs/re/captures/main-menu-items.png differ diff --git a/docs/re/nav-guards.md b/docs/re/nav-guards.md index 3ba415da..b679eee6 100644 --- a/docs/re/nav-guards.md +++ b/docs/re/nav-guards.md @@ -53,3 +53,54 @@ below 640×360 return `none` rather than a screen name (commit `30e53f5`). * Why the capture came back as a sliver at all when `bin/screenshot` is supposed to take the largest `xenia_canary` window by area. It succeeded for the other shots in the same run (1279×675), so it is intermittent, not systematic. + +--- + +## ✅ Both ends fixed, and the route now verifies end-to-end + +The sliver had to be stopped at **both** ends, because either alone leaves the +failure reachable: + +* **Producer** (`bin/screenshot`, commit `290cbe3`) — the app really does own two + windows of class `xenia_canary`, listed in the tree right now as + `10x10+10+10` and `1280x745+1+20`. Largest-by-area picks the game window while + both are present, but during a load the game window is briefly *absent* and the + 10×10 helper wins by default; cropping 720 rows at its `+10` gives exactly the + `10x710` seen. Candidates narrower than 640 are now ignored, so nothing is + selected and the existing fall-through hands back the raw root grab — itself a + valid full frame. Verified on the selection logic directly: both windows listed + → unchanged `1280x745+1+45`; only the helper listed → old logic returned + `10x10+10+10`, new logic selects nothing. +* **Consumer** (`screen_id.py`, commit `30e53f5`) — captures below 640×360 return + `none` instead of a screen name. + +A full guarded run then went through cleanly: + +``` +guard: menu confirmed (1279x675) +loaded ... READYROOM ... armed ... >>> HUD +FLIGHT: flight green=0.0143 +=== GUARD 2 === +OK: UN_f101_TCAF_Acropolis is in the 14 definitions +exit=0 +``` + +**Stage 02, asserted rather than assumed.** + +## ✅ The menu order is confirmed by looking at it + +![main menu](captures/main-menu-items.png) + +`NEW GAME · LOAD GAME · TUTORIAL · OPTIONS · EXTRAS`, cursor on **NEW GAME**. +So `dpad down` ×1 → `LOAD GAME` is right, and `dpad down` ×2 → **TUTORIAL** — +one press further. That is exactly the observed failure: a single extra or +mistimed press, issued while the guard was looking at a sliver, lands on the +tutorial. (`structures/ui-paint-order-key.md` already recorded this item list; +this confirms it visually and pins the cursor's start position.) + +## ❔ Still open + +* **n = 1.** One clean run after the fix. The mechanism is understood and + unit-tested, but "the route is now reproducible" rests on a single success. +* Why the game window leaves the window tree during a load at all was not + investigated — only guarded against.