v2-on-ui #4
@@ -641,7 +641,7 @@ repos:
|
||||
# 疑似 MSBuild 节点争用;此后 3 次干净树连跑均绿。判据:单次失败先复跑一次再看,
|
||||
# 连续两次失败才当真(不许直接 --no-verify 绕过)。
|
||||
- id: ui-golden
|
||||
name: UI 像素回归(菜单 8 状态 + 内容页 27 页 黄金参考)
|
||||
name: UI 像素回归(菜单 8 状态 + 内容页 40 页 黄金参考)
|
||||
entry: python scripts/check_ui_golden.py
|
||||
language: system
|
||||
files: ^(Drivers/BSP/UI/|App/task/ui_task\.(c|h)$|simulator/(tests|sim|src)/|simulator/main\.c$|simulator/CMakeLists\.txt$|simulator/lv_conf\.h$|scripts/check_ui_golden\.py$|\.pre-commit-config\.yaml$)
|
||||
|
||||
+38
-2
@@ -64,6 +64,20 @@ FAIL_DIR = None
|
||||
# 的 l 条件永不可达(classify 只在 MENU 态填 cols,UNKNOWN 恒 cols=None),等于静默连按 s:
|
||||
# 冷启动恰好落在待机态 = 闭环导航直接开不了工。--backoff-keys 可覆盖(如旧行为 "sl")。
|
||||
BACKOFF_KEYS = "esl"
|
||||
# ⚠ 但 e 在**内容页**上不是中性的:装置维护的 强制复归 / 清除记录 都是两段式确认——第一次
|
||||
# ENTER 只把该行标成「确认?」,**第二次 ENTER 就真的执行**(复归全部保护动作位并写 SOE /
|
||||
# 清 SOE·运行·操作记录)。而这两页恰恰最容易被判成 UNKNOWN(新字库缺字、白框、状态行变化
|
||||
# ——正是我们想在 UI 窗口里抓的东西)。bench-runner 2026-10-26 报出这条叠险路径后加两条硬闸:
|
||||
# ① 每次 to_root() 里 ENTER **最多按 BACKOFF_MAX_E 次**,还需要第二次就当场报错停机,
|
||||
# 而不是把第二个 ENTER 投出去;
|
||||
# ② 执行类页面默认**不进**(EXEC_PAGE_IDS);要看显示正确性去模拟器黄金参考,那里没有
|
||||
# 真机副作用。通用口径:**导航类自动化脚本默认零 ENTER**,ENTER 只允许出现在明确
|
||||
# 指定的、非执行类的用例步骤里。
|
||||
BACKOFF_MAX_E = 1
|
||||
# 执行类页面:进入即可能产生不可逆动作,导航器默认拒绝下钻(--allow-exec-pages 显式放行)。
|
||||
EXEC_PAGE_IDS = frozenset(("clear", "reset"))
|
||||
# 默认 False:执行类页面拒绝下钻。显式 --allow-exec-pages 才放行(放行 = 接受后果)。
|
||||
ALLOW_EXEC_PAGES = False
|
||||
|
||||
W = H = 160
|
||||
STRIDE = W // 8
|
||||
@@ -628,6 +642,7 @@ class Navigator(object):
|
||||
的 ssssssss 回根法,正是深页错位的来源之一。
|
||||
"""
|
||||
unk = 0
|
||||
unk_e = 0 # 本次 to_root() 已投出去的 ENTER 次数(见 BACKOFF_MAX_E)
|
||||
for _ in range(limit):
|
||||
fr, st = self.snap()
|
||||
if st["kind"] == "MENU" and self.n_cols(st) == 1:
|
||||
@@ -656,6 +671,17 @@ class Navigator(object):
|
||||
keys = BACKOFF_KEYS or "esl"
|
||||
ch = keys[unk % len(keys)]
|
||||
unk += 1
|
||||
if ch == "e":
|
||||
# 第二条硬闸:未知屏上的 ENTER 可能就是执行类页面的第二段确认。
|
||||
# 宁可停机让人看图,也不拿 ENTER 去试未知状态。
|
||||
if unk_e >= BACKOFF_MAX_E:
|
||||
raise RuntimeError(
|
||||
"UNKNOWN 退避需要第 " + str(unk_e + 1) + " 次 ENTER,已拒绝("
|
||||
+ "BACKOFF_MAX_E=" + str(BACKOFF_MAX_E) + ")。继续按 e 有真执行风险:"
|
||||
+ "装置维护的 强制复归/清除记录 是两段式确认,第二次 ENTER 即执行。"
|
||||
+ "请先看上面 dump 的帧判断这是哪一屏;确认不是执行类页面后,才用"
|
||||
+ " --backoff-keys 改用无 ENTER 的键序(如 sl)重来。")
|
||||
unk_e += 1
|
||||
why = ("UNKNOWN 屏第 %d 次:按 '%s'(退避键序 %r,可 --backoff-keys 覆盖)"
|
||||
% (unk, ch, keys))
|
||||
print("[未知屏] %s" % why)
|
||||
@@ -740,6 +766,12 @@ class Navigator(object):
|
||||
path = page_path(self.clf, pid)
|
||||
if not path:
|
||||
raise RuntimeError("菜单树里没有页面 " + pid)
|
||||
if pid in EXEC_PAGE_IDS and not ALLOW_EXEC_PAGES:
|
||||
# 硬闸 ②:执行类页面默认不进(理由见文件头 BACKOFF_MAX_E 处那段说明)。
|
||||
# 要看这两页的显示正确性,请走模拟器黄金参考——同一份 UI 源码、零真机副作用。
|
||||
raise RuntimeError("刻意跳过执行类页面 " + pid + ":进入后第二次 ENTER 即真执行"
|
||||
"(强制复归 = 复归保护位并写 SOE;清除记录 = 清 SOE/运行/操作记录)。"
|
||||
"显示正确性请走模拟器黄金参考;确需真机下钻才加 --allow-exec-pages。")
|
||||
last_err = None
|
||||
for attempt in range(0, tries):
|
||||
self.to_root()
|
||||
@@ -831,7 +863,7 @@ def selftest_board_frames(clf):
|
||||
|
||||
|
||||
def selftest_refs(clf):
|
||||
"""仓库黄金参考(27 页)逐帧分类自检:每张图的期望值 = 它的文件名。
|
||||
"""仓库黄金参考(40 页)逐帧分类自检:每张图的期望值 = 它的文件名。
|
||||
|
||||
这一组是**语义正确的基线**(模拟器与板端同一份 UI 源码),用来把"分类器错了"与
|
||||
"留档帧本来就是走歪的"分开——两类失败含义完全不同,混在一起就只能靠猜。
|
||||
@@ -941,7 +973,11 @@ def _dump_trace(log):
|
||||
|
||||
|
||||
def main(argv):
|
||||
global TRACE, FAIL_DIR, BACKOFF_KEYS
|
||||
global TRACE, FAIL_DIR, BACKOFF_KEYS, ALLOW_EXEC_PAGES
|
||||
if "--allow-exec-pages" in argv:
|
||||
ALLOW_EXEC_PAGES = True
|
||||
print("[警告] --allow-exec-pages 已开:导航器会下钻执行类页面 "
|
||||
+ str(sorted(EXEC_PAGE_IDS)) + "。第二次 ENTER 即真执行,后果自负。")
|
||||
if "--trace" in argv:
|
||||
TRACE = argv[argv.index("--trace") + 1]
|
||||
if "--dump-fail" in argv:
|
||||
|
||||
Reference in New Issue
Block a user