This repository has been archived on 2026-09-16. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Syplheed-Reborn/docs/re/nav-guards.md
Sylpheed RE agent 540eefeae8 tools: add assert_stage.py and a menu guard; record that the guard was not enough
assert_stage.py checks the DEFINITION table against an expected stage marker and
earned its keep immediately: its first live run reported MISMATCH -- the capture
had a live flight HUD and would have been filed as Stage 02, but was the S01
tutorial.  That is exactly the failure that silently invalidated an earlier
cross-run comparison.

require_menu (launch_mission.sh) refuses to press until screen_id reads `menu`.
It is NOT sufficient, and this refutes my previous explanation: the run DID
confirm the menu and still loaded the tutorial.  The real cause was that the
guard's own capture was a 10x710 sliver which classified as `menu` -- fixed
separately in 30e53f5.

Left open: whether the menu guard suffices now that slivers are rejected (not
re-run), and why the capture was a sliver at all when the other shots in the same
run were 1279x675.
2026-08-26 22:56:22 +00:00

56 lines
2.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Nav guards — one works, one was not enough, and the real cause was a sliver
Added and exercised 2026-08-26 against a live run.
## ✅ Guard 2 works, and earned its keep on the first run
`tools/re-capture/assert_stage.py` states the expected stage and checks it against
the **definition table** (definitions are the stage's cast and are present from
load; instances arrive in waves). Its first live run:
```
MISMATCH: UN_f101_TCAF_Acropolis is NOT in the 13 definitions
UN_S01_Asteroid_cmesh_01a ... UN_e106_ADAN_Destroyer
```
The run had reached a live flight HUD and would have been recorded as a valid
Stage 02 capture. It was the **S01 tutorial**. Without this check the wrong-stage
roster looks exactly like a right one — which is how the earlier cross-run
comparison was silently invalidated.
Use it as the precondition for any runtime measurement:
`./assert_stage.py UN_f101_TCAF_Acropolis` (exit 0 iff Stage 02 is loaded).
## ❌ Guard 1 was necessary but NOT sufficient — my explanation was wrong
`require_menu` in `launch_mission.sh` refuses to press until `screen_id.py` reads
`menu`. [The previous note](stage-drift-is-navigation-not-save.md) said the
tutorial was selected because the d-pad went out "from a state never confirmed to
be the main menu". **That explanation is refuted:** this run confirmed the menu
first, and *still* loaded the tutorial.
## ✅ The actual cause: the guard was shown a 10×710 sliver
![sliver](captures/sliver-classified-as-menu.png)
The guard's own capture was **10 × 710** — not a frame at all. Every statistic in
`screen_id.py` is an area fraction, so the sliver classified cleanly as `menu`
(`green 0.0000, white 0.0157`). The guard passed on garbage, the fixed key
sequence went out blind, and the selection landed on a tutorial entry.
🔑 **`bin/screenshot`'s own header already records this failure mode** from
2026-08-18 — a second window of class `xenia_canary` meant grabs came back as
slivers, and "a whole session's screen ids were noise". That fix hardened the
**capture** side. It did not harden the **consumer**, so the same failure walked
straight back in through a different path. Fixed now in `screen_id.py`: captures
below 640×360 return `none` rather than a screen name (commit `30e53f5`).
## ❔ Still open
* Whether the menu guard is sufficient **now that the classifier rejects
slivers** — not re-run. The sliver explains this run, but it does not prove the
cursor/item-order assumption behind `dpad down` = LOAD GAME is correct.
* 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.