diff --git a/.dsh/skills/board-ui-nav/SKILL.md b/.dsh/skills/board-ui-nav/SKILL.md index d582d106..bf011fdf 100644 --- a/.dsh/skills/board-ui-nav/SKILL.md +++ b/.dsh/skills/board-ui-nav/SKILL.md @@ -57,7 +57,8 @@ whenToUse: 需要上真机/台架进某页面看图(如故障录波、回放 1. `--where` 先看 STATUS:`PAGE` → 按 `s` 关页(导航器 `--to` 自动做); `STANDBY` → 按 `e` 唤醒(注意规则②:home 上 `e` 可能重开最近页); - `MENU depth>0` → `l` 收列,别按 `s`(菜单态 `s` 不收列)。 + `MENU depth>0` → 按 `s` 或 `l` 都收一级(台架复核 2026-11-02:菜单态 `s` 与 `l` 同走 + `menu_back`,父列选中留在原地;旧说法"`s` 不收列"系把待机态 `s` 无效误读成菜单行为)。 2. STATUS 无应答(老固件)才吃退避键序(默认 `esl`,`--backoff-keys sl` 可去 ENTER); ENTER 上限 1 次是硬闸(BACKOFF_MAX_E),报停机就 dump 帧人眼看,不许连按。 3. 反复落错页且 trace 里出现"像素与 STATUS 不一致" → 分类器或固件有账要记, diff --git a/docs/UI设计/UI_自动化测试流程.md b/docs/UI设计/UI_自动化测试流程.md index dab4f5b1..2836aee0 100644 --- a/docs/UI设计/UI_自动化测试流程.md +++ b/docs/UI设计/UI_自动化测试流程.md @@ -147,7 +147,7 @@ cmake --build simulator/build --config Debug # 0) 构建模拟器(须 0 警 另两条实测纪律(理由写死在代码注释里,此处不重述): -- **收级联列按 `l`、不按 `s`**:菜单态按 `s` 不收列,用 `ssssssss` 回根正是深页错位的来源之一; +- **收级联列的键语义已台架复核定型(2026-11-02,#69)**:菜单态按 `s` 与 `l` 同走 `menu_back`,**都收一级**且父列选中留在原位(实测 depth 1→0、sel 不变)——旧断言「菜单态按 `s` 不收列」是把**待机态 `s` 无效**(task-24 实证)误读成了菜单行为;`ssssssss` 盲按回根不可信这个结论仍然成立,不可信的是"不看回读连按",不是键本身。有 STATUS 时按 depth 收(弹框被屏裁时像素 `n_cols` 会漏数、固件 depth 不会),老固件继续按 `l` 收 + 验终点; - 菜单树的 `#P` 注记可能写在 `#page=` **之前**(`网口设置 #P #page=net_cfg`),解析顺序错了就 剥不掉,那一叶的页面 id 也永远认不出来。 @@ -196,9 +196,13 @@ cmake --build simulator/build --config Debug # 0) 构建模拟器(须 0 警 身份裁定,所以它会大声报错而不是静默走错页。实测 `自检记录` / `运行记录` 两页在模拟器 上 5 次枚举内没吃到,现场帧见 [popup_clipped](../测试说明/测试数据/boot_log_data/20261025_uinav_popup_clipped.png); - **真机上那层弹框究竟画在哪,留台架窗口取证后再定修法**——这是取证题,不是编码题。 - #69 之后:真机(新固件)侧该漏计已被 STATUS 的 `depth` 事实顶掉——"回根"直接认 - `depth==0`,不再依赖数得到列数;`KNOWN_UNREACHABLE` 两条按对称设计留待台架走到后销项。 + **真机上弹框位置的取证已完成(2026-11-02 台架,#69)**:菜单步进**依旧**吃不到这两叶 + (末列枚举落到同胞页 `alarm` / `selftest`——但落点现在由 STATUS 如实报出,不再谎称到达); + GOTO 直开两叶都到达且完整渲染(自检记录 ink 4073 / 运行记录 ink 3559,证据在 PR #70 + 台架段)。故 `KNOWN_UNREACHABLE` 对 `--to` 步进**保留**(对称设计的销项条件"真走到" + 尚未满足),已验证的绕行路径是 `--goto`;真机(新固件)侧"回根"改认 STATUS `depth`: + `depth==0` 直接返根、`depth>0` 按 s 逐级收(弹框被裁时像素漏计、固件 depth 不漏), + 旧的"补按 `l` 兜底"仪式只留给无 STATUS 的老固件像素路径。 2. 同一标题的多个显示态(网口设置的 只读 / 编辑 / 保存)在分类里都是同一个页面 id `net_cfg`;要区分得看行内文本,写路径判据需要时再加。 3. 认屏复用黄金参考的文案:改了页面文案而没同步 `simulator/tests/` 的文本断言表,本节脚本 @@ -245,3 +249,12 @@ cmake --build simulator/build --config Debug # 0) 构建模拟器(须 0 警 - **留档帧目录已并一**:`WALK_DIR` 与 `--walk` 存证目录同指 `ci-artifacts/uinav/walk/` (#69 前指 `ci-artifacts/uiwalk/`,走的新帧 BOARD_TRUTH 段永远读不到,静默"跳过(无 留档)")。 +- **实机验证记录(2026-11-02 台架,两档实烧,输出全文贴在 PR #70 的台架证据评论)**: + bench 档(`fw build: Nov 2 2026 22:25:12`)上 STATUS 首答 `{kind=MENU depth=0 path=[0] + sel=[0]}`;GOTO `wave_play` 一次往返到达——#38 那趟"进故障录波看波形"的级联盲走就此降为 + 一条命令;`selftest` / `runlog` 直开渲染完整(见 §7.4 第 1 条取证结论);PAGE 上按 s 回根 + 由 STATUS 证实;级联收列按 s 逐级收回(§7.2 纪律据此改写);根列光标可经 STATUS `sel` + 对位(记录查询 = 根行 6,对齐一击命中再 ENTER)。换回**产品档**(`fw build: Nov 2 2026 + 22:29:56 suite=NONE`,同一提交、未加宏)复烧后:STATUS 照常应答(它不设编译期闸), + GOTO 回 **status=4(不支持)**——同一对命令在生产/bench 两侧的行为差异由真机钉死,不止 + 纸面推理。烧录两轮均过 `/serial-boot-test` 闭环(身份戳匹配 + 回读 `no difference`)。 diff --git a/scripts/board_ui_nav.py b/scripts/board_ui_nav.py index b4996ccf..e99cd8f8 100644 --- a/scripts/board_ui_nav.py +++ b/scripts/board_ui_nav.py @@ -835,10 +835,13 @@ class Navigator(object): def to_root(self, limit=14): """回到"只有一列打开"的根菜单。 - 两条实测纪律写在这里: + 两条实测纪律写在这里(第二条已于 2026-11-02 台架复核改写,#69): · 页面态用 s 退(s = 退出页); - · **级联列只能用 l 收**,菜单态按 s 不收列(Lead 大窗实测)——沿用盲走脚本 - 的 ssssssss 回根法,正是深页错位的来源之一。 + · **级联列收级看回读**:有 STATUS 时按 depth 收——菜单态 s 与 l 同走 + menu_back、都收一级且父列选中留在原地(台架实测 depth 1→0、sel 不变); + 旧断言"菜单态按 s 不收列(Lead 大窗实测)"是把待机态 s 无效(task-24) + 误读成了菜单行为。盲按 ssssssss 回根依旧禁止:不可信的是"不看回读连按", + 不是键本身。老固件无 STATUS 时仍用 l 收(下方像素分支保留原路)。 """ unk = 0 unk_e = 0 # 本次 to_root() 已投出去的 ENTER 次数(见 BACKOFF_MAX_E) @@ -854,6 +857,14 @@ class Navigator(object): # 以前它被像素判成 BLANK 走"s 关页"分支——在待机页上按 s 是空转。 self._step("e", "待机态(STATUS)→ e 唤醒进菜单") continue + if s and s["kind"] == "MENU" and s.get("depth", 0) > 0: + # 有固件身份回读时按 depth 收级(2026-11-02 台架复核,#69):菜单态 + # s = menu_back,收一级且父列选中留在原地。子列弹框被屏裁时像素 + # n_cols 会漏数、固件 depth 不漏——这正替掉了旧"补按 l 兜底"仪式要 + # 防的那类漏计。s 在根列上无效但无害(台架同轮实测 depth0 按 s 原地)。 + self._step("s", "STATUS depth=%d 级联 → s 收一级(台架复核 2026-11-02)" + % s["depth"]) + continue if st["kind"] == "MENU" and self.n_cols(st) == 1: # "只有一列"不等于"在根":子列弹框被屏幕裁掉时它的选带根本不在可扫窗口 # 里,n_cols 会漏数它——于是上一轮留在弹框里的选中项还在,直接按 e 就 @@ -1050,7 +1061,11 @@ class Navigator(object): # 理由;把它写成断言而不是评论,是因为下次改 UI 后这条结论也要能被重新检查。 # 已声明的导航限度(不是"允许失败",是**记账**):这两页落在根列最后两行,其子菜单 # 弹框会被屏幕裁掉、选带不在可扫窗口内,"枚举 + 验终点"目前吃不到它们。 -# 依据与现场帧见 docs/UI设计/UI_自动化测试流程.md §7.4;真机上弹框画在哪要等台架取证。 +# 依据与现场帧见 docs/UI设计/UI_自动化测试流程.md §7.4。台架复核 2026-11-02(#69, +# bench 固件 + STATUS):菜单步进**依旧**吃不到这两叶(末列枚举落到同胞页 alarm / +# selftest,落点由 STATUS 如实报出、不再谎称到达);但 GOTO 直开两叶都能到达并完整 +# 渲染(自检记录 ink=4073 / 运行记录 ink=3559,证据在 PR #70 台架段)。本限度对 --to +# 步进继续有效,解法是 --goto 绕开被裁弹框,不是继续修枚举。 # ⚠ 对称设计:这两页哪天真走到了,本表就是**过期**——脚本会当成失败报出来,逼着同步删 # 条目与文档限度,免得限度清单变成永久遮羞布。 KNOWN_UNREACHABLE = {