diff --git a/CLAUDE.md b/CLAUDE.md index b1fc206..8b571ef 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -662,6 +662,38 @@ Note `NAME_TAG_THRESHOLD = 0.26` (the hover path, line ~289) is deliberately muc was NOT changed — Akara genuinely hovers at ~0.28 (Bug 3). The two thresholds serve different paths; don't unify them. +### Bug 31: merc panel check left the CHRONICLE panel open for the whole game (2026-08-27) +**File:** `src/bot.py` — `on_maintenance()`, merc-alive confirmation + +`resurrect_merc` confirms a live merc by pressing `o` and looking for `MercPanelText`. It +then closed the panel **only when that check passed**: + +```python +keyboard.send("o") +merc_panel_open = is_visible(ScreenObjects.MercPanelText) +if merc_panel_open: + keyboard.send("o") # the ONLY path that closed anything +``` + +On this client `o` (skill slot 54) opens the **CHRONICLE** collection panel, not the merc +panel. So `MercPanelText` never matched, the closing keypress was never sent, and Chronicle +stayed open for the rest of the game — a large centred panel that blanks every subsequent +template match. The run then died on `click_red_portal` after ~66s of clicking at a covered +screen. + +**Why nothing caught it:** the health manager's panel guard looks for `LeftPanel` / +`RightPanel`. Chronicle is centred and matches neither, so it was never auto-escaped. + +**Fix:** always dismiss whatever appeared. If `MercPanelText` is not found, send `esc`, then +re-check `LeftPanel`/`RightPanel` and send `esc` again if something is still up. + +**The general rule:** *any* keypress that may open a panel must be paired with an +unconditional dismiss. Closing only on the happy path leaves the UI wedged on every other +path — and here that cost a whole run each time. + +**Symptom to grep for:** `FAIL>` records showing `step=resurrect_merc` followed by +`run.approach!` with a long duration, or an error screenshot with a UI panel covering the map. + --- ## The run timeline — `grep "TL>"` diff --git a/src/bot.py b/src/bot.py index e9dce12..ab7a74d 100644 --- a/src/bot.py +++ b/src/bot.py @@ -974,6 +974,18 @@ class Bot: keyboard.send("o") wait(0.2, 0.3) merc_visible = True + else: + # 'o' opened SOMETHING that is not the merc panel and nothing closed it. + # On this client it opens the CHRONICLE collection panel, which covers + # the screen and blanks every later template match — the run then dies + # on click_red_portal after ~66s of flailing at a covered screen + # (g90 2026-08-27). Always dismiss whatever appeared, then confirm. + keyboard.send("esc") + wait(0.25, 0.35) + if is_visible(ScreenObjects.LeftPanel) or is_visible(ScreenObjects.RightPanel): + Logger.warning("Merc check: a panel is still open after esc — sending esc again") + keyboard.send("esc") + wait(0.25, 0.35) gs = self._game_stats skip_until = getattr(gs, "_merc_resurrect_skip_until", 0) if not merc_visible and gs._game_counter < skip_until: