Skip to content

fix(GameUi): 过图加载时等待可识别页面,不再盲点关闭按钮 - #1944

Closed
Enough1122 wants to merge 1 commit into
runhey:devfrom
Enough1122:fix/navigator-loading-wait
Closed

Enough1122 wants to merge 1 commit into
runhey:devfrom
Enough1122:fix/navigator-loading-wait

Conversation

@Enough1122

@Enough1122 Enough1122 commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

现象

page_main -> page_guild 跳转反复失败,penalty 一路涨到 13,任务反复 strike,最后整个实例退出(Task KekkaiUtilize failed 3 or more times + Request human takeover)。日志:

Transition cannot reach page_guild: page_main->page_guild, penalty=1.0 ... 13.0
Page detect miss[current_page]: scoped=['global', 'kekkai_utilize']
Page detect miss[goto_page]: scoped=['global', 'kekkai_utilize']
Try switch to a supported page
GameTooManyClickError: Too many click between 2 buttons: PAGE_MAIN_GOTO_GUILD,

根因

失败时刻的 log/error/ 截图(10 张)拍到的全是过图加载画面(十周年加载图),不是任何可识别页面。导航层没有加载等待概念:

  1. _wait_for_destination 只等 4 秒,加载稍慢就判跳转失败;
  2. goto_page 里当前页为 None 就立刻调 close_unknown_pages 盲点返回键,这些恢复点击把游戏从加载带进了宴会厅等侧房间,之后就彻底对不上了。

已排除模板问题:用 cv2 把 page_check_guild.png 对失败截图全量匹配最高只有 0.4(画面里根本没有目标);注意该模板画的是结界入口按钮,在宴会厅右下角也会 cross-match 出 0.9,所以宴会厅里的命中不能作为到达寮的证据。

改动

  • _wait_for_destination 超时 4s → 15s;等待期间若识别到别的已知页则提前返回失败(真走错了不等满 15 秒),什么都认不出就继续等;
  • close_unknown_pages 动手前先静等 15 秒(新增 _wait_for_any_page),等到可识别页面就直接返回交给外层重识别,不点任何关闭按钮。

验证

  • 同一台机器、同一个寮宴活动夜:修复前从干净庭院重启两次都绕回宴会厅;修复后 Page arrived page_guild([26.8s]、[34.7s] 均超过旧 4 秒上限,证明走的是新等待路径),之后结界寄养任务正常跑起选卡 OCR。
  • 未完全 soak:寄养放置链路(UTILIZE_UTILIZE_ZONES_GROUP 点击无响应)是另一个独立问题,另起处理,本 PR 只解决导航误判。

Sourcery 总结

通过等待可识别的目标页面出现,再判定导航失败或采取恢复操作,使页面导航能够更好地应对加载缓慢的情况。

Bug 修复:

  • 延长等待目标页面的时间,并区分加载状态与已到达另一个已知页面的情况,避免将缓慢的页面转换误判为导航失败。
  • 在尝试恢复操作前,先等待可识别的页面出现,避免盲目点击关闭按钮而干扰加载画面。
Original summary in English

Summary by Sourcery

Make page navigation resilient to slow loading screens by waiting for recognizable destinations before declaring failure or taking recovery actions.

Bug Fixes:

  • Prevent slow page transitions from being misclassified as navigation failures by waiting longer for the destination and distinguishing loading states from arrival at another known page.
  • Avoid disrupting loading screens with blind close-button recovery clicks by waiting for a recognizable page before attempting recovery actions.

@Enough1122 Enough1122 closed this Oct 17, 2026
@Enough1122
Enough1122 deleted the fix/navigator-loading-wait branch October 17, 2026 08:56

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

嘿——我发现了 2 个问题

给 AI 智能体的提示
请处理这次代码审查中的评论:

## 单条评论

### 评论 1
<location path="tasks/GameUi/navigator.py" line_range="723" />
<code_context>
+        while not timer.reached():
+            page = self._detect_current_page(
+                skip_first_screenshot=False,
+                categories=self._default_detect_categories(),
+            )
+            if page is not None:
</code_context>
<issue_to_address>
**已识别的目标页面被关闭**

在恢复等待期间,如果出现的可识别页面不属于全局类别或当前任务类别,`_wait_for_any_page` 只会搜索全局类别和当前任务类别,因此无法发现该页面;随后 `close_unknown_pages` 会在导航重新识别该页面之前,对它运行关闭器。

运行未知页面关闭器之前,请搜索所有已注册的页面类别,包括目标类别。

另见 `tasks/GameUi/navigator.py:724`。
</issue_to_address>

### 评论 2
<location path="tasks/GameUi/navigator.py" line_range="494-506" />
<code_context>
         """

         timer = Timer(timeout).start()
+        last_probe = 0.0
         while not timer.reached():
             if self.confirm_page(destination, skip_first_screenshot=False):
                 self.navigator.current_page = destination
                 return True
+            now = time.time()
+            if now - last_probe >= 3.0:
+                last_probe = now
+                landed = self._detect_current_page(
+                    skip_first_screenshot=True,
+                    categories=self._navigation_detect_categories(destination),
+                )
+                if landed is not None and landed.key != destination.key:
+                    return False
         return False
</code_context>
<issue_to_address>
**成功的页面转换受到惩罚**

执行转换操作后、目标页面出现前,如果源页面仍可识别,`_wait_for_destination` 会将源页面视为一次失败的探测并返回 `False`。因此,目标页面还没来得及出现,`_execute_transition` 就会记录一次失败的转换并施加惩罚。

如果检测到的页面仍是转换源页面,请继续轮询;只有目标页面等待超时后才判定失败。
</issue_to_address>

Sourcery 评估

待批准。 请先处理 2 项发现。

阻塞性发现:tasks/GameUi/navigator.py:723、tasks/GameUi/navigator.py:506


Sourcery 对开源项目免费——如果您喜欢我们的审查结果,欢迎分享 ✨
Original comment in English

Hey - I've found 2 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="tasks/GameUi/navigator.py" line_range="723" />
<code_context>
+        while not timer.reached():
+            page = self._detect_current_page(
+                skip_first_screenshot=False,
+                categories=self._default_detect_categories(),
+            )
+            if page is not None:
</code_context>
<issue_to_address>
**Recognized destinations get dismissed**

When a recognizable page appears outside the global and current-task categories during the recovery wait, `_wait_for_any_page` searches only the global and current-task categories, so it misses the page and `close_unknown_pages` runs a closer against it before navigation can re-detect it.

Search all registered page categories, including the destination category, before running unknown-page closers.

Also at `tasks/GameUi/navigator.py:724`.
</issue_to_address>

### Comment 2
<location path="tasks/GameUi/navigator.py" line_range="494-506" />
<code_context>
         """

         timer = Timer(timeout).start()
+        last_probe = 0.0
         while not timer.reached():
             if self.confirm_page(destination, skip_first_screenshot=False):
                 self.navigator.current_page = destination
                 return True
+            now = time.time()
+            if now - last_probe >= 3.0:
+                last_probe = now
+                landed = self._detect_current_page(
+                    skip_first_screenshot=True,
+                    categories=self._navigation_detect_categories(destination),
+                )
+                if landed is not None and landed.key != destination.key:
+                    return False
         return False
</code_context>
<issue_to_address>
**Successful transitions get penalized**

When the source page remains recognizable after the transition action but before the destination appears, `_wait_for_destination` treats the source page as a failed probe and returns `False`, so `_execute_transition` records a failed transition and adds a penalty before the destination has time to appear.

Keep polling when the detected page is still the transition source, and only fail after the destination wait expires.
</issue_to_address>

Sourcery assessment

Approval pending. 2 findings to address first.

Blocking findings: tasks/GameUi/navigator.py:723, tasks/GameUi/navigator.py:506


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment thread tasks/GameUi/navigator.py
while not timer.reached():
page = self._detect_current_page(
skip_first_screenshot=False,
categories=self._default_detect_categories(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 中 · 已识别的目标页面被关闭

在恢复等待期间,如果出现的可识别页面不属于全局类别或当前任务类别,_wait_for_any_page 只会搜索全局类别和当前任务类别,因此无法发现该页面;随后 close_unknown_pages 会在导航重新识别该页面之前,对它运行关闭器。

运行未知页面关闭器之前,请搜索所有已注册的页面类别,包括目标类别。

另见 tasks/GameUi/navigator.py:724。

给 AI 智能体的提示
在 `tasks/GameUi/navigator.py` 第 723 行:

**已识别的目标页面被关闭**

在恢复等待期间,如果出现的可识别页面不属于全局类别或当前任务类别,`_wait_for_any_page` 只会搜索全局类别和当前任务类别,因此无法发现该页面;随后 `close_unknown_pages` 会在导航重新识别该页面之前,对它运行关闭器。

运行未知页面关闭器之前,请搜索所有已注册的页面类别,包括目标类别。

另见 `tasks/GameUi/navigator.py:724`。
Original comment in English

🟡 Medium · Recognized destinations get dismissed

When a recognizable page appears outside the global and current-task categories during the recovery wait, _wait_for_any_page searches only the global and current-task categories, so it misses the page and close_unknown_pages runs a closer against it before navigation can re-detect it.

Search all registered page categories, including the destination category, before running unknown-page closers.

Also at tasks/GameUi/navigator.py:724.

Prompt for AI agents
In `tasks/GameUi/navigator.py` at line 723:

**Recognized destinations get dismissed**

When a recognizable page appears outside the global and current-task categories during the recovery wait, `_wait_for_any_page` searches only the global and current-task categories, so it misses the page and `close_unknown_pages` runs a closer against it before navigation can re-detect it.

Search all registered page categories, including the destination category, before running unknown-page closers.

Also at `tasks/GameUi/navigator.py:724`.

Comment thread tasks/GameUi/navigator.py
Comment on lines +494 to +506
last_probe = 0.0
while not timer.reached():
if self.confirm_page(destination, skip_first_screenshot=False):
self.navigator.current_page = destination
return True
now = time.time()
if now - last_probe >= 3.0:
last_probe = now
landed = self._detect_current_page(
skip_first_screenshot=True,
categories=self._navigation_detect_categories(destination),
)
if landed is not None and landed.key != destination.key:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 高 · 成功的页面转换受到惩罚

执行转换操作后、目标页面出现前,如果源页面仍可识别,_wait_for_destination 会将源页面视为一次失败的探测并返回 False。因此,目标页面还没来得及出现,_execute_transition 就会记录一次失败的转换并施加惩罚。

如果检测到的页面仍是转换源页面,请继续轮询;只有目标页面等待超时后才判定失败。

给 AI 智能体的提示
在 `tasks/GameUi/navigator.py` 第 494–506 行:

**成功的页面转换受到惩罚**

执行转换操作后、目标页面出现前,如果源页面仍可识别,`_wait_for_destination` 会将源页面视为一次失败的探测并返回 `False`。因此,目标页面还没来得及出现,`_execute_transition` 就会记录一次失败的转换并施加惩罚。

如果检测到的页面仍是转换源页面,请继续轮询;只有目标页面等待超时后才判定失败。
Original comment in English

🟠 High · Successful transitions get penalized

When the source page remains recognizable after the transition action but before the destination appears, _wait_for_destination treats the source page as a failed probe and returns False, so _execute_transition records a failed transition and adds a penalty before the destination has time to appear.

Keep polling when the detected page is still the transition source, and only fail after the destination wait expires.

Prompt for AI agents
In `tasks/GameUi/navigator.py` at lines 494-506:

**Successful transitions get penalized**

When the source page remains recognizable after the transition action but before the destination appears, `_wait_for_destination` treats the source page as a failed probe and returns `False`, so `_execute_transition` records a failed transition and adds a penalty before the destination has time to appear.

Keep polling when the detected page is still the transition source, and only fail after the destination wait expires.

@github-actions

Copy link
Copy Markdown
Contributor

Findings

  • C2 [风险]
    位置:tasks/GameUi/navigator.py:GameUi._wait_for_any_page、GameUi.close_unknown_pages
    原因:未知页恢复等待只扫描 _default_detect_categories(),未包含当前导航目标的分类;目标页属于其他任务分类时,已出现可识别页面仍会等待满 15 秒后继续执行关闭动作。
    修改:将目标页或导航识别分类传入未知页恢复流程,或改为扫描本次导航允许的分类集合,并补充对应回归测试。
  • C7 [不确定]
    位置:tasks/GameUi/navigator.py:_wait_for_destination、_wait_for_any_page
    原因:本次新增等待和提前失败分支没有随 PR 提交自动化测试;当前检查状态仍有 Run 失败,无法确认慢加载、误落其他页面和恢复等待三条路径均稳定。
    修改:补充模拟页面识别与计时器的单元测试,并修复或说明失败检查后再合并。

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • ab.chatgpt.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "ab.chatgpt.com"

See Network Configuration for more information.

Generated by PR Review Checklist for #1944 · codex · gpt56 · 10.3 AIC · ⌖ 2.75 AIC · ⊞ 12.1K · ◷

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant