Files
my-botty/test/test_game_menu_guard.py
alexpolo1andClaude Opus 5 a139fb3230 fix(view): pause the panel check during save_and_exit — the menu guard raced the shutdown
Follow-up to the GameMenu guard, caught by its own instrumentation: 75 menu
escapes across 15 games, ~5 per game, all clustered around game end.

save_and_exit deliberately opens the in-game ESC menu, but callers only pause
the panel check AFTER it returns:

    18:58:48.142  game | end | ok
    18:58:48.334  In-game menu open - closing it (1/6)      <- the guard
    18:58:48.487  Clicking SAVE_AND_EXIT_NO_HIGHLIGHT       <- the bot
    18:58:48.736  In-game menu open - closing it (2/6)      <- the guard again
    18:58:49.098  Health Manager is now paused              <- too late

Games still completed, so this was noise rather than breakage — but it is a
race, and the guard was pressing esc while the shutdown clicked the menu.

save_and_exit now pauses the panel check for the whole sequence and restores it
in a finally, so it cannot leak the paused state if save/exit raises.

The guard itself is working: 15 games, 0 failures, 0 portal failures, and the
loot-filter/Chronicle/Options incidents have not recurred.

MANA> instrumentation has also settled #23 — see the issue.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-28 19:26:45 +02:00

67 lines
2.7 KiB
Python

"""The in-game ESC menu must be detected and closed.
2026-08-28: the bot was found sitting in OPTIONS -> VIDEO with a "settings have
changed, apply or discard?" modal. Discarding revealed the cause — the in-game
ESC menu carries these buttons at SCREEN CENTRE:
OPTIONS / SAVE AND EXIT / RETURN TO GAME / LOOT FILTER / CHRONICLE
A stray esc opens the menu, and the bot's next movement click lands on one of
them. The HUD mask deliberately leaves screen centre clickable, so nothing
stops it.
That single mechanism explains three separate incidents: the loot filter being
toggled, CHRONICLE blanking every template match for a whole run, and the video
options being opened and changed.
It has NO close button, so CenterPanel (which matches CLOSE_PANEL_2) cannot see
it. Bug 31 warned about exactly this: "just send esc is WORSE: with nothing
open, esc opens the GAME MENU".
"""
import inspect
def test_game_menu_screenobject_exists():
from ui_manager import ScreenObjects
assert hasattr(ScreenObjects, "GameMenu")
def test_guard_closes_the_menu_before_chickening():
from health_manager import HealthManager
src = inspect.getsource(HealthManager)
assert "ScreenObjects.GameMenu" in src, "the guard never checks for the in-game menu"
menu_at = src.index("ScreenObjects.GameMenu")
chicken_at = src.index("Chickening to be safe")
assert menu_at < chicken_at, "menu escape must come before the chicken path"
def test_mana_threshold_crossings_are_logged():
"""Issue #23 cannot be settled without this.
Mana was only logged when a potion was DRUNK, so a second dip that failed to
trigger was indistinguishable from mana never dipping twice.
"""
from health_manager import HealthManager
src = inspect.getsource(HealthManager)
assert "MANA>" in src, "no threshold-crossing log; #23 stays undecidable"
assert "_mana_below_threshold" in src, "crossings are not edge-triggered"
def test_save_and_exit_pauses_the_panel_check():
"""The guard must not fight the shutdown it was built to protect.
save_and_exit deliberately opens the in-game ESC menu. The health manager
now closes that menu on sight, and callers only pause AFTER save_and_exit
returns — so the guard raced the shutdown: 75 escapes across 15 games,
interleaved with the save/exit clicks.
"""
import inspect
from ui import view
src = inspect.getsource(view.save_and_exit)
assert "set_panel_check_paused(True)" in src, (
"save_and_exit opens the ESC menu without pausing the panel check, so "
"the GameMenu guard will close it mid-shutdown"
)
assert "finally" in src, "the pause must be released even if save/exit raises"