fix(cafe): resolve invite ticket cooldown misread as list opened, preventing cascading errors

This commit is contained in:
Nik Afiq 2026-07-14 22:57:32 +09:00
parent e814b3d803
commit a0e1965353
3 changed files with 53 additions and 1 deletions

File diff suppressed because one or more lines are too long

View File

@ -24,6 +24,20 @@ had just taken the account's highest-affection students -- then invited
row 3 cleanly. Both newly-invited students were immediately patted
successfully in the same run, income was claimed, and the task returned
cleanly to the true home screen with no warnings anywhere in the log.
A follow-up real-usage bug (2026-07-14, reported with a screenshot after
the ticket used above went on cooldown): _open_invite_list originally
verified only "did the header stop reading as a plain subscreen", which
is also true when the ticket is on cooldown and the click raises a
"通知" notice ("待機時間が経過した後に、再度招待することができます。")
directly instead of opening the list -- misread as "list opened", it then
sent _ensure_invite_sort/_try_invite_row's row/sort-control coordinates
into a dialog that has none of them, repeatedly. Fixed by checking
navigation.is_modal_open (a real dialog's darker dim) before the
list-opened check: a dialog appearing before any row was clicked can only
mean the ticket click itself raised one directly, so this now dismisses
it via SWEEP_CONFIRM_BUTTON and returns False (skip invite this room)
instead of proceeding.
"""
from ba_auto import detector, navigation
@ -159,9 +173,37 @@ def _open_invite_list(driver, config):
# list-with-no-nested-dialog state actually produces (confirmed live:
# MODAL_DIM_PROBE read (252,145,165) with just the list open, which
# fails is_modal_open's all-channels-under-150 check).
#
# But that same "not on subscreen" reading is also produced by a
# completely different case: when the ticket is on cooldown, clicking
# the icon does NOT open the list at all -- it raises a "通知" dialog
# directly ("待機時間が経過した後に、再度招待することができます。",
# confirmed live 2026-07-14 via a real user report + screenshot) with
# the same dimming. The original version of this check couldn't tell
# the two apart and treated the cooldown notice as "list opened",
# which then sent _ensure_invite_sort/_try_invite_row's fixed row/
# sort-control coordinates into a dialog that doesn't have any of
# them -- exactly the "keep pressing the invite when it's not
# available and causing this popup and fail" the user reported.
#
# A real dialog (navigation.is_modal_open, which needs the DARKER
# reading a nested "通知" card produces, not just the list's own lighter
# dim) can only legitimately appear here if the ticket click itself
# opened one directly -- the list view has no dialog on top of it yet
# at this point, since no row has been clicked. So checking
# is_modal_open first, before the list-opened check, cleanly
# distinguishes "cooldown notice fired instead of the list" from "the
# list opened normally" and lets this dismiss the notice safely rather
# than misreading it as success.
for attempt in range(1, ROOM_OPEN_RETRIES + 1):
driver.click(*config.CAFE_INVITE_TICKET_ICON)
driver.wait(2)
if navigation.is_modal_open(driver):
title = detector.read_text(config.CAFE_INVITE_DIALOG_TITLE_RECT, psm=6, lang="jpn")
print(f"[cafe] invite ticket click opened a dialog instead of the list (title: '{title}') -- likely on cooldown, treating invitation as unavailable")
driver.click(*config.SWEEP_CONFIRM_BUTTON)
driver.wait(1)
return False
if not navigation.is_on_subscreen(driver):
return True
print(f"[cafe] invitation ticket list not detected after click (attempt {attempt}/{ROOM_OPEN_RETRIES})")

10
plan.md
View File

@ -334,6 +334,16 @@ Live-calibrated on nik-gpu (free — panning and patting don't spend a limited r
**Confirmed live with real game-state changes** (patting affects real affection, though it's a free, repeatable daily action, not a limited resource like the invite ticket): a full `cafe` run patted a real sparkle in room 2 (`score=0.997`) specifically after panning to an extreme — the sparkle would not necessarily have been visible from the room's default load position — while room 1 found nothing in either view that run (expected: sparkles are on a per-student cooldown, most checks legitimately find nothing). The task completed cleanly end-to-end (both rooms' invite-then-farm sequence, income claimed, confirmed clean return to home) with no warnings anywhere in the log.
#### Phase 6 follow-up #4: invite ticket cooldown misread as "list opened" (2026-07-14)
Real-usage bug report with a screenshot, filed once the account's invite ticket (spent twice during follow-up #2's live test, same day) went on cooldown: "I have problem with the script keep pressing the invite when it's not available and causing this popup and fail." The screenshot showed a "通知" dialog reading "待機時間が経過した後に、再度招待することができます。" ("you can invite again after the wait time passes") with a single OK/Enter button, no cancel.
Root cause: `_open_invite_list`'s check (`not navigation.is_on_subscreen(driver)`, added in follow-up #2 above) verifies only "something opened that dims the header" — true for the real MomoTalk list AND for this cooldown notice alike, since both dim `SUBSCREEN_HEADER_PROBE` the same way. It returned `True` (list opened) for the cooldown case too, so `_invite_student` proceeded straight into `_ensure_invite_sort`/`_try_invite_row`'s fixed sort-dropdown/row coordinates — none of which exist on this small single-button dialog — causing the cascading wrong clicks and failure the user reported.
Fix: check `navigation.is_modal_open` (the darker "real dialog" reading, not the list's own lighter dim) immediately after the ticket-icon click, before the list-opened check. A dialog appearing at this exact point can only mean the click itself raised one directly — no row has been clicked yet, so the normal per-row invite-confirm dialog can't be it. When detected, `_open_invite_list` now OCRs the title for logging, dismisses via the shared `SWEEP_CONFIRM_BUTTON` (same "通知" component position reused throughout this project), and returns `False` — which `_invite_student`'s existing (unchanged) fallback already handles correctly: skip the invite, log it, move on to farming.
**Confirmed live** (`live-test-runner` agent, real `cafe` run with the ticket confirmed still on cooldown for both rooms): both rooms logged `invite ticket click opened a dialog instead of the list (title: '...') -- likely on cooldown, treating invitation as unavailable` immediately, no cascading errors or misclicks followed, and the task proceeded normally to farming/income-claim and ended cleanly (exit 0, true home screen confirmed via screenshot). OCR of the dialog title came back noisy (`'通和 X'` instead of `'通知'`) but this doesn't matter — the fix's branch doesn't depend on the title text, only on `is_modal_open` firing before any row was clicked.
### Phase 7: setup.sh update
**Status: Done — `setup.sh` deploys `ba_daily.py` and `ba_auto/`.** `scripts/ba_dailies_legacy.sh` and `scripts/detect_and_click.py` were deleted once mailbox and cafe both migrated off them (Phases 56); `setup.sh` no longer references either.