feat(门禁): 编号门禁 id-check 落地(36→37 钩子)+ 批 1 编号单词化改名
新增门禁本体 - scripts/check_ids.py:实现 docs/编号规范.md §8 八项校验;默认 warn-only, 唯一硬拦项是「可判定比例跌破基线」(防回退的本体) - scripts/id_registry.json:66 个前缀族,逐项来自 §4 总表 + 全库实测游标, 偏差一律写进 cursor_note,不凭记忆编造 - scripts/id_aliases.json:旧号 → 新号 / 作废标记(照搬 section_aliases.json 范式) - 顺带收编 check_test_traceability.py:正则补齐大写后缀与无模块码形态, 比对范围扩到 test/host 与 7 篇「单元测试说明.md」,另加 --board-only 回退旧口径 批 1 改名(用户授权解禁「不改写存量号」) - 代码规范条款 S1~S19 → CODE-RULE-nn:78 处 / 2 文件 - UI 像素回归状态 S0~S7 → MENU-STATE-nn:61 处 / 3 文件(冻结在 07) - 两族属主登记处 = 脚本自身的规则表 / STATES 表,文档只作引用方 - 新增 scripts/rename_ids.py(§7.3 规划脚本):映射表驱动、显式 scope、默认干跑、 自动写 scoped 别名,跳过 [示例]/[计划] 行与变更记录表,按原字节读写保 BOM 行尾 - 已应用映射表存档 scripts/rename_maps/batch1.json 作审计轨迹 有牙实测(证明门禁不是空转) - 注入 Z-99 / 裸形 / 悬空 / 越游标 / 未紧邻 / 跨文档重复定义 六例, 分别被校验 1/2/3/5/6/4 点名,--strict 退出码 1;临时档删除后工作树干净 验证与同步 - 可判定比例基线 82.3% → 82.7%(已 --update-baseline 入档);错误级 1312 → 1291 - ci_local.py 全绿(L0 + L0.5 共 1104 断言);ui-golden Passed; check_doc_links.py --all 无法判定 0 - 未改任何 C/H 源文件,故本次不需 @build - 文档:AGENTS.md 与 pre-commit使用说明.md 计数 36→37 并新增 §2.25 详解; 编号规范 §4.1 补两行、§8.1 落地记录、§8.2 规范与仓库偏差、§8.3 迁移批次记录
This commit is contained in:
@@ -8,16 +8,16 @@ check_menu_rows.py — 自绘菜单 8 状态像素回归(160x160 I1,MSB-firs
|
||||
前置:simulator 已构建(build/Debug/lvgl_sim.exe 存在);纯标准库,任意 python3。
|
||||
|
||||
状态(键序注入,u=上 d=下 e=Enter s=Esc):
|
||||
S0 "" 根框 7 行 sel=0
|
||||
S1 "d" sel=1
|
||||
S2 "dd" sel=2
|
||||
S3 "ddu" 回退 → 须与 S1 全像素一致
|
||||
S4 "de" 开 L2(实时数据 3 子项),根框不变
|
||||
S5 "ded" L2 sel=1
|
||||
S6 "des" 返回 → 须与 S1 全像素一致(销毁/重建一致性)
|
||||
S7 "ddes" 根框 sel=2、L2 已毁 → 须与 S2 全像素一致
|
||||
MENU-STATE-00 "" 根框 7 行 sel=0
|
||||
MENU-STATE-01 "d" sel=1
|
||||
MENU-STATE-02 "dd" sel=2
|
||||
MENU-STATE-03 "ddu" 回退 → 须与 MENU-STATE-01 全像素一致
|
||||
MENU-STATE-04 "de" 开 L2(实时数据 3 子项),根框不变
|
||||
MENU-STATE-05 "ded" L2 sel=1
|
||||
MENU-STATE-06 "des" 返回 → 须与 MENU-STATE-01 全像素一致(销毁/重建一致性)
|
||||
MENU-STATE-07 "ddes" 根框 sel=2、L2 已毁 → 须与 MENU-STATE-02 全像素一致
|
||||
断言:选中行白带(白占比>0.50)+ 带内黑字;非选行黑底白字(0.03<占比<0.45);
|
||||
框体 1px 白边框;一致性状态逐字节相同;S0 池水位 = MENU_POOL_BASELINE。
|
||||
框体 1px 白边框;一致性状态逐字节相同;MENU-STATE-00 池水位 = MENU_POOL_BASELINE。
|
||||
|
||||
退出码:0 全 PASS;1 有断言失败;2 运行/环境错误(exe 缺失等)。
|
||||
"""
|
||||
@@ -33,14 +33,14 @@ from pathlib import Path
|
||||
EXE = Path(__file__).resolve().parents[1] / "build" / "Debug" / "lvgl_sim.exe"
|
||||
|
||||
STATES = [
|
||||
("S0", ""),
|
||||
("S1", "d"),
|
||||
("S2", "dd"),
|
||||
("S3", "ddu"),
|
||||
("S4", "de"),
|
||||
("S5", "ded"),
|
||||
("S6", "des"),
|
||||
("S7", "ddes"),
|
||||
("MENU-STATE-00", ""),
|
||||
("MENU-STATE-01", "d"),
|
||||
("MENU-STATE-02", "dd"),
|
||||
("MENU-STATE-03", "ddu"),
|
||||
("MENU-STATE-04", "de"),
|
||||
("MENU-STATE-05", "ded"),
|
||||
("MENU-STATE-06", "des"),
|
||||
("MENU-STATE-07", "ddes"),
|
||||
]
|
||||
|
||||
W = H = 160
|
||||
@@ -135,17 +135,17 @@ def main():
|
||||
r.stderr.decode(errors="replace")[:200]))
|
||||
return 2
|
||||
paths[name] = out
|
||||
if name == "S0":
|
||||
if name == "MENU-STATE-00":
|
||||
s0_out = r.stdout
|
||||
|
||||
# S0(空键序)= 菜单基线:池水位门禁
|
||||
# MENU-STATE-00(空键序)= 菜单基线:池水位门禁
|
||||
m = re.search(r"pool after keys: used=(\d+)", s0_out.decode(errors="replace"))
|
||||
if not m:
|
||||
print("FAIL: S0 输出未找到 'pool after keys'")
|
||||
print("FAIL: MENU-STATE-00 输出未找到 'pool after keys'")
|
||||
return 2
|
||||
used = int(m.group(1))
|
||||
check(used == MENU_POOL_BASELINE,
|
||||
"S0 池水位 %d != 基线 %d(菜单结构/样式变更?确认合理后更新常量)"
|
||||
"MENU-STATE-00 池水位 %d != 基线 %d(菜单结构/样式变更?确认合理后更新常量)"
|
||||
% (used, MENU_POOL_BASELINE))
|
||||
|
||||
shots = {n: load(p) for n, p in paths.items()}
|
||||
@@ -169,46 +169,46 @@ def main():
|
||||
check(px[y0][x] == 1 and px[y0 + h - 1][x] == 1,
|
||||
"%s 上下边框 x=%d 非白" % (tag, x))
|
||||
|
||||
# --- S0:根框 7 行,sel=0 ---
|
||||
p = S["S0"]
|
||||
# --- MENU-STATE-00:根框 7 行,sel=0 ---
|
||||
p = S["MENU-STATE-00"]
|
||||
border_check(p, ROOT_X0, ROOT_Y0, ROOT_W, ROOT_H, "S0根框")
|
||||
for i in range(7):
|
||||
row_check(p, *root_row_strip(i), band=(i == 0), tag="S0行%d" % i)
|
||||
|
||||
# --- S1/S2:sel 移位 ---
|
||||
for name, sel in (("S1", 1), ("S2", 2)):
|
||||
# --- MENU-STATE-01/MENU-STATE-02:sel 移位 ---
|
||||
for name, sel in (("MENU-STATE-01", 1), ("MENU-STATE-02", 2)):
|
||||
p = S[name]
|
||||
border_check(p, ROOT_X0, ROOT_Y0, ROOT_W, ROOT_H, name + "根框")
|
||||
for i in range(7):
|
||||
row_check(p, *root_row_strip(i), band=(i == sel), tag=name + "行%d" % i)
|
||||
|
||||
# --- S4:L2 开于 sel=1 行右侧(3 子项、无箭头),根框区与 S1 相同 ---
|
||||
p = S["S4"]
|
||||
# --- MENU-STATE-04:L2 开于 sel=1 行右侧(3 子项、无箭头),根框区与 MENU-STATE-01 相同 ---
|
||||
p = S["MENU-STATE-04"]
|
||||
lx0, ly0, lw, lh = l2_geom(1, 3)
|
||||
border_check(p, lx0, ly0, lw, lh, "S4-L2框")
|
||||
border_check(p, lx0, ly0, lw, lh, "MENU-STATE-04-L2框")
|
||||
for i in range(3):
|
||||
row_check(p, *l2_row_strip(lx0, ly0, i, lw), band=(i == 0), tag="S4-L2行%d" % i)
|
||||
# 根框区(x 0..65)须与 S1 逐像素一致
|
||||
row_check(p, *l2_row_strip(lx0, ly0, i, lw), band=(i == 0), tag="MENU-STATE-04-L2行%d" % i)
|
||||
# 根框区(x 0..65)须与 MENU-STATE-01 逐像素一致
|
||||
for y in range(H):
|
||||
for x in range(0, ROOT_X0 + ROOT_W):
|
||||
check(S["S1"][y][x] == p[y][x], "S4 根框区(x=%d,y=%d) 与 S1 不一致" % (x, y))
|
||||
check(S["MENU-STATE-01"][y][x] == p[y][x], "MENU-STATE-04 根框区(x=%d,y=%d) 与 MENU-STATE-01 不一致" % (x, y))
|
||||
# L2 框下方区域须全黑(无残留对象)
|
||||
f = frac(p, lx0 + 1, lx0 + lw - 2, ly0 + lh + 1, min(ly0 + lh + 14, H - 1))
|
||||
check(f == 0.0, "S4 L2 框下方有像素(占比 %.3f)" % f)
|
||||
check(f == 0.0, "MENU-STATE-04 L2 框下方有像素(占比 %.3f)" % f)
|
||||
|
||||
# --- S5:L2 sel=1,根框区仍与 S1 同 ---
|
||||
p = S["S5"]
|
||||
# --- MENU-STATE-05:L2 sel=1,根框区仍与 MENU-STATE-01 同 ---
|
||||
p = S["MENU-STATE-05"]
|
||||
lx0, ly0, lw, lh = l2_geom(1, 3)
|
||||
for i in range(3):
|
||||
row_check(p, *l2_row_strip(lx0, ly0, i, lw), band=(i == 1), tag="S5-L2行%d" % i)
|
||||
row_check(p, *l2_row_strip(lx0, ly0, i, lw), band=(i == 1), tag="MENU-STATE-05-L2行%d" % i)
|
||||
for y in range(H):
|
||||
for x in range(0, ROOT_X0 + ROOT_W):
|
||||
check(S["S1"][y][x] == p[y][x], "S5 根框区(x=%d,y=%d) 与 S1 不一致" % (x, y))
|
||||
check(S["MENU-STATE-01"][y][x] == p[y][x], "MENU-STATE-05 根框区(x=%d,y=%d) 与 MENU-STATE-01 不一致" % (x, y))
|
||||
|
||||
# --- 一致性状态:逐字节全像素比对 ---
|
||||
for a, b, tag in (("S3", "S1", "ddu==d"),
|
||||
("S6", "S1", "des==d(往返)"),
|
||||
("S7", "S2", "ddes==dd(往返)")):
|
||||
for a, b, tag in (("MENU-STATE-03", "MENU-STATE-01", "ddu==d"),
|
||||
("MENU-STATE-06", "MENU-STATE-01", "des==d(往返)"),
|
||||
("MENU-STATE-07", "MENU-STATE-02", "ddes==dd(往返)")):
|
||||
if raw(paths[a]) == raw(paths[b]):
|
||||
print("[%s] PASS 全像素一致 (%s)" % (a, tag))
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user