feat(UI): W6 第一波——设计令牌层、页面注册表生成器与 UI 门禁补强

启动 docs/任务规划/README.md 的 W6 UI 扩展簇(用户裁定,覆盖 2026-10-11
的"本轮不排期")。四个工作包,全部验证通过。

## U1 设计令牌层(零行为变化)
新建 Drivers/BSP/UI/ui_tokens.h(20 个宏),框架 + 7 个页面 + App/task/
ui_task.c 全部接入。屏幕几何**复用 ui_port.h 既有 UI_SCREEN_W/H**,不重复
定义;令牌头自身只 include ui_port.h,不把 LVGL 拖进全部消费者。
补收了报告没列但代码里真重复的量:UI_TEXT_BAND_H 15(7 次)、列表左右边界
与每页行数(各 4 个页面逐字复制)、推流协议几何与显示几何同源(此前硬编码
3200 且注释写着"须与 UI_FB_SIZE 一致"——典型漂移隐患)、UI_TASK_TICK_MS
(ui_port_step 与 osDelay 必须同值,原先靠注释维系)。
故意不收页面私有几何与"同形不同义"的值(device_info 的 pitch=15 与列表
UI_ROW_PITCH=14 合并即改像素)。

## U3 页面注册表与生成器(删手工分发)
ui_page_registry.{c,h} 由生成器产出,**手工 menu_content_page_for() 已删
除**(仓库内仅存 2 处历史说明注释)。密码页按代码实况**单独出口**
(ui_page_registry_password())——它非节点绑定,任何 #P 叶子进同一页。
顺带落地此前判定"U1 阶段做不了"的共享 flat 样式 ui_style.{c,h}。
生成器除产注册表外**自动把新 .c 写进 uvprojx 与 CMakeLists.txt**,且
**双向对账**:加页打印 registered、删页打印 pruned,不留死条目;并双向
校验(#page 找不到实例报错、实例未被任何 #page 引用也报错)。

## U4 门禁补强(35 个钩子)
新增 font-charset 钩子(scripts/check_font_charset.py):复用
tools/font_gen 的同一套提取与 cmap 解析规则(importlib 直载,零第二套
规则),A 段查源码在用 vs 字符集、B 段查字符集 vs 字体 cmap。
registration-check 补第 ④ 类:实测原规则对"进了两端构建但没接描述符表"
的页面**全绿**——desc 被链接器剥离、编译链接全过、菜单永远打不开的死代码。
仍照不出的两项已如实写进文档(枚举漏加归 @build、菜单树漏挂归 golden)。

## 字体子集瘦身(D 案,4 留 3 删)
ui_cn_chars.txt 122→119 字(恰删 上/电/重,零新增)。异/常/片/芯 进
KEEP_EXTRA 带理由白名单:它们曾在 9eb1bd63 被写进中文自检描述落盘
/log/selftest.log(定长 64B 记录跨固件持久),删字形会使历史故障记录
渲染空白且不可逆。保留字按**必需**处理,反向有牙——谁只跑 extract_cn
把它们静默洗掉,钩子直接 FAIL 并逐字打印理由。
--strict 口径为"未知冗余 = 0"而非"冗余 = 0"。

## 验证
@build 0 错 0 警;ER_IROM1 232,052 B(较 HEAD −228 B)、RW_IRAM1
75,232 B **零增量**、RW_CCM 87.9% 未变。golden:菜单 8 状态全像素一致 +
内容页 11 页逐字节一致,**参考图 sha256 差异 0 条**(未用 --update 刷
基线);池水位菜单基线 5368 B、开页-关页往返 5448 B 与 U1 时相同。
38 个在途修改文件逐个核对 BOM/CRLF/U+FFFD 全部与 HEAD 一致。
L0 33 钩子 + L0.5 16 runner / 1104 断言全绿;check_doc_links --all
142 篇、无法判定 0;mem-budget / mem-numbers 已回填。

## 单位成本实测(U5 排期依据)
临时页 zzprobe 绑到"遥信量"叶子 → 只跑生成器 → 带页 @build 0/0 →
注册表出现 {5u, &ui_page_zzprobe_desc} → 回滚后 6 个产出文件 zzprobe
残留计数均 0、重编回基线。
**结论:新增一页 = 3 处人工(新 .c + 新 .h + 菜单树那一行加
 #page=<名>)+ 1 条生成器命令,手工编辑注册文件 0 处。**
据此修正报告原口径"8 处降到 1 处"——那个 1 只在"1 处对既有文件的修改"
意义下成立,页面自身 2 个文件本就要写,真实处数是 3。

## 文档同步与两处自我修正
§0.1 UI 行 B → B+;§6.1「内容页」「设计令牌」两行按实况回填;§6.5 U1/U3
状态更新;§6 顶部加"建议栏不可照抄"总警示(本轮四次证伪:ui_port.h 已有
同名宏、LV_COLOR_BLACK/WHITE 不存在且极性反了、27 页实为目标页数现存 7
个、生成器草图漏密码页非节点绑定)。
两处改口:① §6.5 U4 从我上一版**误写的 3/3 改回 2/3**——"golden 脚本早已
存在"不等于"已进自动门禁",两个 golden 脚本至今未挂 pre-commit,该缺口
单列为待办;② 原计划"分三笔提交"**作废**,U1 与 U3 改同一批文件、文件内
交叠,硬切会产生不可编译的中间态,故整波一笔。
This commit is contained in:
2026-10-20 21:14:14 +08:00
parent 9d06798f2d
commit dafc18f5ed
47 changed files with 1447 additions and 450 deletions
@@ -167,3 +167,20 @@ OK 43614 bytes -> ...\Drivers\BSP\UI\ui_font_cn_12.c
| `ui_cn_chars.txt`(工程根) | 实际显示汉字清单记录(可删) |
| `tools/font_gen/extract_cn.py` | 提取字符集脚本(见第 3 节) |
| `tools/font_gen/make_font.py` | 生成字体脚本,自动定位 lv_font_conv 并处理 `.ttc`(见第 4 节) |
---
## 重生成前的安全流程(2026-10-15 实测沉淀)
字体是**生成物**,但它进的是**像素基线 + 台架可见效果**。工具链一旦漂移,损失的是"保留字形静默变化"——而这种变化**编译和链接都不报错**。下面四步是必做项,不是可选:
1. **仓库外 dry-run**:先在临时目录搭一个最小生成器根(拷 `tools/font_gen` 两脚本 + 目标 `ui_cn_chars.txt`;`make_font` 的 ROOT 由自身位置推导,所以整目录拷走即可独立运行),在沙箱里跑完整生成链,确认 rc / coverage / 字节数 / BOM / LF / `EF BF BD` 全部正确,**才允许在仓库内跑正路**。
2. **确定性实证**:沙箱产物与仓库产物做 sha256 对比。一致即证明生成器确定性,之后任何 A/B 对比都可以用"快照 + 字节级还原",不必重新生成。
3. **逐码位结构对账(关键一步)**:解析新旧字体 `.c` 的 `glyph_bitmap`(按 `/* U+XXXX */` 注释切块)与 `glyph_dsc`,断言三件事——**删除集 == 预期字符集**、**其余码位位图字节零差异**、**度量多重集不变**。这一步把"golden 应该不变"**从期望升级为结构证明**,golden 跑出来只是复核。换工具版本(例如新装 `lv_font_conv`)时此项**必做**——它能照出"工具版本漂移导致保留字形悄悄变化",那才是真正会刷爆 golden 的事故源。
4. **A/B 必须同树**:并行开发时**千万不要拿别人给的"绿灯基线数"当 before**——那个数可能已经含了本次改动(实测照出过这种情况,见下)。正确做法:`git show HEAD:<字体路径>` 字节级换回旧产物 → 在**同一棵当前树**重跑 before → sha256 校验换回新产物跑 after。
> **口径:字体源文件字节数 ≠ ROM 降幅。** 源文件 ~45 KB 编到 `.constdata` 只有 ~4.5 KB,剔 3 个字形的真实降幅是**百字节量级**(实测 `ER_IROM1` −80 B、字体对象 RO −81 B,与"3 字 × ~25 B 位图 + 3 × 12 B 描述符、对齐后"预测吻合)。**报尺寸变化一律用 `.map` 的 `ER_IROM1` / 对象 RO**,不要把源文件字节数当成 Flash 增量。
> **保留字形(`KEEP_EXTRA`)的存在理由**:`ui_cn_chars.txt` 里除了"源码在用",还可能有**刻意保留**的字——当前为 异 / 常 / 片 / 芯,因为它们曾在 2026-09-14 `9eb1bd63` 被写进中文自检描述落盘 `/log/selftest.log`(定长 64 B 记录跨固件升级持久),删字形会使历史故障记录渲染空白且不可逆。`scripts/check_font_charset.py` 把这类字**按必需处理**:既照"缺字",也照"保留字被静默剔除"(严格模式下 FAIL 并逐字打印保留理由)。
> **所以"只跑 `extract_cn` 重新生成字符集"会把保留字洗掉**——这是本流程最容易犯的错,钩子就是为了挡住它。`--strict` 的判据因此是"**未知**冗余 = 0",而不是"冗余 = 0"。
+24 -6
View File
@@ -25,8 +25,9 @@ git commit
├─ cubemx-survival CubeMX 重生成存活审计(易失定制清单 + 基线漂移)
├─ watchdog-unit-test 看门狗判定状态机主机侧单测(L0.5)
├─ test-suite-switch 测试套件开关=产品构建(防测试固件静默提交)
├─ registration-check 双端注册反向校验(uvprojx + CMakeLists,N-23)
└─ mem-budget RAM 预算 92% 阈值门禁(N-27 三件套,2026-10-12)
├─ registration-check 双端注册反向校验(uvprojx + CMakeLists,N-23;含 UI 页面描述符表接线,U4)
├─ mem-budget RAM 预算 92% 阈值门禁(N-27 三件套,2026-10-12)
└─ font-charset UI 字符集差集检查(防缺字白框,U4,2026-10-15)
└─ commit-msg(.git/hooks/commit-msg)
└─ gitlint 校验 commit message 格式
```
@@ -52,6 +53,7 @@ git commit
| scripts/check_test_suite.py | 随仓库提交 | 测试套件开关门禁(纯 Python,无依赖) |
| scripts/check_registration.py | 随仓库提交 | 双端注册反向校验(纯 Python,无依赖) |
| scripts/ram_baseline.py | 随仓库提交 | RAM 预算 92% 门禁 + 趋势台账(纯 Python,无依赖) |
| scripts/check_font_charset.py | 随仓库提交 | UI 字符集差集检查(纯 Python,无依赖;复用 `tools/font_gen/` 两个生成器的提取与 cmap 解析规则) |
> **PATH 要求**:cppcheck 安装后需在 PATH 中可找到(winget 自动写入 User PATH,但当前终端不会立即生效,需**重开终端**);装在非 PATH 位置时可用 `DTU_CPPCHECK` 环境变量指向 `cppcheck.exe` 完整路径(显式设置但无效 → 硬报错,不静默回退)。
@@ -360,17 +362,18 @@ cppcheck 是开源 C/C++ 静态分析工具,**不运行代码**,通过语法
| **为什么需要** | 锁定 60 s / 解锁 / 清零 / 回绕是**防口令爆破契约核心**——板端每验一条要真等 60 s、回绕要跑满 49.7 天;纯函数设计(tick 注入)就是为让这些分支主机侧毫秒级穷举 |
| **运行器** | `test/host/ftp_auth/run_unit_test.py`(MSVC `cl.exe`,L0.5) |
### 2.18 registration-check — 双端注册反向校验(2026-10-12 加,N-23)
### 2.18 registration-check — 双端注册反向校验 + UI 页面接线(2026-10-12 加,N-23;U4 补强 2026-10-15)
| 项 | 说明 |
|---|---|
| **触发条件** | 任意 `.c` 文件 + `*.uvprojx` + `CMakeLists.txt` + 脚本自身变动(pre-commit 4.x 无 `always: true`,`files:` 必须覆盖全部触发面) |
| **处理方式** | **阻止提交**(存在**新**缺口或幽灵注册即拦截);存量缺口走白名单只 `[WARN]` 不拦 |
| **检查对象** | 扫描 `App/`、`Drivers/BSP/`、`Src/` 下全部 `.c`(排除第三方),对照两份注册表:`MDK-ARM/STM32F407-Demo.uvprojx` 的 `<FilePath>` + `simulator/CMakeLists.txt` 的显式源列表(先展开 `${NETCFG_DIR}` 等变量) |
| **三类缺口** | ① 存在但未进 uvprojx(固件不编译)② 存在但未进 CMakeLists(模拟器不编译,**仅当本应进模拟器时**才算)③ 注册了但文件不存在(**幽灵注册**,改名/删除后残留) |
| **四类缺口** | ① 存在但未进 uvprojx(固件不编译)② 存在但未进 CMakeLists(模拟器不编译,**仅当本应进模拟器时**才算)③ 注册了但文件不存在(**幽灵注册**,改名/删除后残留)④ UI 页面模块未接入描述符表(见下行,U4) |
| **UI 页面门禁(U4,2026-10-15 补)** | UI 页面的"注册"有**两层**:**构建注册**(uvprojx + CMakeLists,①② 类)与**框架注册**(`ui_content_page.h` 枚举 + `ui_content_page.c` 的 `s_defs[]` 描述符表)。①②③ 原本只照得出前者——实测"页面已进两端构建但没接 `s_defs[]`"时钩子**全绿**:desc 无人引用被链接器整段剥离,两端编译链接全过、菜单永远打不开这一页,是又一形态"写了却从不生效"的死代码。故补 ④:凡 `ui_page_*.c` 定义 `ui_page_<name>_desc`,该符号必须在 `Drivers/BSP/UI/` 内(除该页自身 `.c`/`.h`)被引用,否则 `[GAP]` FAIL。**新增 UI 页面必须过本钩子**即此机械口径;U3 落地生成式 `ui_page_registry.c` 后规则依旧成立(不定义自身 desc 的 `ui_page_*.c` 不判为页面模块)。⚠ 本钩子照不出**枚举值漏加**(`ui_content_page.h` 的 `content_page_id_t`)与**菜单树漏挂节点**——前者是 `s_defs[]` 下标依据(漏加则表项编译不过,由 `@build` 兜底),后者归 U3 生成器 + golden 回归 |
| **豁免机制** | MCU-only 文件不进模拟器是**正确**的(模拟器另有 `*_sim.c` 替身或无对应)。豁免用**显式清单 + 每行理由**(命名模式 `*_mcu.c` + 个别点名),**不整目录一刀切**(N-23 教训正是目录级盲区);唯一目录级豁免 `Src/`(CubeMX 生成,MCU 专属)→ 见脚本 `SIM_EXEMPT` |
| **存量白名单** | `KNOWN_GAPS` 登记 N-23 存量缺口(`App/task/rs485_task.c`、`Drivers/BSP/NET/lftpd/lftpd_log.c`,Lead 处置中)→ 命中打 `[WARN]` 不拦,只对新缺口 FAIL,故钩子可立即上线不拦现有提交;`--strict` 关白名单供审计 |
| **为什么需要** | 新 `.c` 必须手动注册两处才会被编译;历史上 `rs485_task.c`/`lftpd_log.c` **两处都没注册** = 写了却从不参与任何一端编译的**死代码**,误导读者以为功能已生效(出处审查报告 N-06 残余) |
| **为什么需要** | 新 `.c` 必须手动注册两处才会被编译;历史上 `rs485_task.c`/`lftpd_log.c` **两处都没注册** = 写了却从不参与任何一端编译的**死代码**,误导读者以为功能已生效(出处审查报告 N-06 残余);④ 的出处是报告 §6.5 U4"把注册检查算作 UI 页面门禁一环"(2026-10-15 实测 ①②③ 对未接线页面全绿,故补规则) |
| **运行器** | `scripts/check_registration.py`(纯标准库;退出码 0=一致 / 1=有缺口 / 2=环境错误) |
### 2.19 mem-budget — RAM 预算 92% 阈值门禁(2026-10-12 加,N-27 三件套)
@@ -429,6 +432,20 @@ cppcheck 是开源 C/C++ 静态分析工具,**不运行代码**,通过语法
| **为什么需要** | N-12 / N-13 两类缺陷真机**极难复现**:is_free 误判要恰好撞上"页首 0xFF、后段有数据"的页形态,越界地址要哨兵从别处漏进来;两者发作后都只表现为"某次复位后丢数据",无从定位。移植层是纯逻辑 + 假芯片,能钉死真机极难复现的越界/误判路径,且"越界不产生任何芯片访问"这类判据在板端**根本拿不到观测面** |
| **运行器** | `test/host/nand_port/run_unit_test.py`(MSVC `cl.exe`,L0.5);套件说明见 `test/host/README.md` |
### 2.24 font-charset — UI 字符集差集检查(2026-10-15 加,报告 §6.5 U4 残余)
| 项 | 说明 |
|---|---|
| **触发条件** | `Drivers/BSP/UI/` 下任意文件(含字体 `ui_font_cn_12.c` 自身)、`App/task/ui_task.(c\|h)`、`ui_cn_chars.txt`、`tools/font_gen/`(两个生成器)或本脚本自身变动(pre-commit 4.x 无 `always: true`,`files:` 必须覆盖全部触发面) |
| **处理方式** | **阻止提交**(存在"白框方向"缺口即 FAIL);字符集**冗余**字 `[WARN]` 不拦(只费 Flash 不致白框,`--strict` 升级为 FAIL 供审计/瘦身排期) |
| **判定口径** | 两段链条:**A.** UI 源码在用字符 vs `ui_cn_chars.txt`——源码有、txt 无 → FAIL(字体必然无此字形);txt 有、源码无 → WARN。**B.** `ui_cn_chars.txt` vs `ui_font_cn_12.c` 的 cmap——txt 有、字体无 → FAIL(`lv_font_conv` 对缺字形/低码位**静默丢字**)。A 过 + B 过 ⟹ 字体 ⊇ 源码每个在用字 |
| **单一规则源** | 本脚本**不自创第二套解析规则**:字符集提取复用 `tools/font_gen/extract_cn.py` 的 `SCAN` 清单 + `collect()` 状态机(跳注释/字符常量、只取双引号串内非 ASCII),cmap 覆盖判定复用 `tools/font_gen/make_font.py` 的 `verify_coverage()`(含稀疏 `unicode_list` 与补回字形的单码位条目),importlib 直载零副作用——生成期校验与提交期校验**同源**,杜绝两套规则漂移(§5.5 同类教训) |
| **典型报错** | `[GAP] 字体缺字 1 个(在字符集、不在 Drivers/BSP/UI/ui_font_cn_12.c 的 cmap -> lv_font_conv 静默丢字,上机白框): 压(U+538B)`,附 font-regen 四步修复提示 |
| **修复方式** | 按 **font-regen** skill 重跑 `extract_cn.py` → `make_font.py` → diff 检查,`ui_cn_chars.txt` 与 `ui_font_cn_12.c` 随代码一起提交 |
| **为什么需要** | `ui_font_cn_12.c` 是**子集**字体,只含 txt 列出的码位;`make_font.py` 的 `verify_coverage` 只在**生成期**校验"txt ⊆ cmap"——改完 UI 字符串忘了重跑 font-regen 就提交,缺字上机渲染为空白(白框),无日志无报错、只能肉眼截图发现。font-regen skill 的约定此前**纯靠自律**,本钩子把它机械化(U4 三钩子至此齐:golden ✅、字符集差集 ✅、注册检查算作 UI 门禁 ✅ → §2.18 ④) |
| **首次落地实测(牙齿)** | 注入均打在**临时副本**(`--chars` / `--font` 覆盖,不碰仓库文件):① txt 删 ▶ → FAIL 点名 `▶(U+25B6)`;② 字体副本删 U+25B6 单码位 cmap 条目 → FAIL 同字;③ 字体副本删 U+538B 的稀疏 `unicode_list` 偏移 → FAIL 点名 `压(U+538B)`;基线 PASS。落地时 txt 内有 **7 个历史冗余字**(上/常/异/片/电/芯/重,源码已不用)→ 仅 WARN 不拦,下次 font-regen 顺带瘦身 |
| **运行器** | `scripts/check_font_charset.py`(纯标准库;`--chars` / `--font` 指临时副本做注入测试、`--strict` 升级冗余字;退出码 0=通过 / 1=白框缺口 / 2=环境错误) |
---
## 3. 日常工作流
@@ -556,7 +573,7 @@ $env:PATH = [Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [Env
| 文件 | 位置 | 说明 |
|---|---|---|
| `.pre-commit-config.yaml` | 仓库根 | 钩子配置(**34 个钩子**,2026-10-15 清点;本文 §2 详解非单测类——N-19 新增的两个单测钩子见 §2.16/§2.17,N-23 双端注册反向校验见 §2.18,N-27 RAM 预算门禁见 §2.19,B4 IEC104 协议栈单测见 §2.20,B8 频率测量单测见 §2.21,B9 SOE 动作记录单测见 §2.22,N-21 dhara NAND 移植层单测见 §2.23,其余主机侧单测见 AGENTS.md 门禁条;主机侧单测共 16 个) |
| `.pre-commit-config.yaml` | 仓库根 | 钩子配置(**35 个钩子**,2026-10-15 清点;本文 §2 详解非单测类——N-19 新增的两个单测钩子见 §2.16/§2.17,N-23 双端注册反向校验(含 U4 补强的 UI 页面描述符表接线 ④)见 §2.18,N-27 RAM 预算门禁见 §2.19,B4 IEC104 协议栈单测见 §2.20,B8 频率测量单测见 §2.21,B9 SOE 动作记录单测见 §2.22,N-21 dhara NAND 移植层单测见 §2.23,U4 残余字符集差集检查见 §2.24,其余主机侧单测见 AGENTS.md 门禁条;主机侧单测共 16 个) |
| `.gitlint` | 仓库根 | gitlint 规则(宽松,兼容中文) |
| `.cubemx_survival_baseline.json` | 仓库根 | CubeMX 易失定制基线(哈希;`--write` 重建) |
| `scripts/check_mojibake.py` | scripts/ | U+FFFD 检测脚本 |
@@ -567,6 +584,7 @@ $env:PATH = [Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [Env
| `scripts/check_cubemx_survival.py` | scripts/ | CubeMX 重生成存活审计 |
| `scripts/check_lv_conf_sync.py` | scripts/ | 两份 `lv_conf.h` 特性子集一致性(比对生效值 + 无效宏名 + 重复定义) |
| `scripts/check_test_suite.py` | scripts/ | 测试套件开关门禁(防测试固件静默提交) |
| `scripts/check_font_charset.py` | scripts/ | UI 字符集差集检查(复用 `tools/font_gen/` 提取与 cmap 解析规则,防缺字白框) |
| `docs/代码规范/嵌入式C语言代码规范_V1.0.md` | docs/代码规范/ | 代码规范原文(S1~S19 规则来源) |
| `docs/代码规范/cppcheck使用说明.md` | docs/代码规范/ | cppcheck 钩子详解(规则/配置/抑制) |
| `docs/文档规范.md` | docs/ | 文档体系规范(链接形态/命名/门禁要求) |
@@ -36,10 +36,10 @@
<!-- MEM_SNAPSHOT:BEGIN generated by scripts/check_mem_numbers.py -->
| 区域 | 用量 | 容量 | 占比 |
|---|---|---|---|
| ER_IROM1 | 232,280 B (226.84 KB) | 1,048,576 B (1024 KB) | 22.2% |
| ER_IROM1 | 232,052 B (226.61 KB) | 1,048,576 B (1024 KB) | 22.1% |
| RW_IRAM1 | 75,232 B (73.47 KB) | 131,072 B (128 KB) | 57.4% |
| RW_CCM | 57,376 B (56.03 KB) | 65,280 B (64 KB) | 87.9% |
| **Flash (ROM 合计)** | **233,416 B (227.9 KB)** | 1,048,576 B (1024 KB) | **22.3%** |
| **Flash (ROM 合计)** | **233,192 B (227.7 KB)** | 1,048,576 B (1024 KB) | **22.2%** |
<!-- MEM_SNAPSHOT:END -->
各区的容量与常量来源:
+2 -2
View File
@@ -15,7 +15,7 @@
<!-- MEM_BUDGET:BEGIN generated by scripts/ram_baseline.py -->
| 区域 | 用量 | 容量 | 占比 | 门禁(≤92%) |
|---|---|---|---|---|
| ER_IROM1 (Flash) | 232,280 B | 1,048,576 B | 22.2% | 参考 |
| ER_IROM1 (Flash) | 232,052 B | 1,048,576 B | 22.1% | 参考 |
| RW_CCM | 57,376 B | 65,280 B | 87.9% | PASS |
| UNINIT_CCM | 48 B | 256 B | 18.8% | 参考 |
| RW_IRAM1 | 75,232 B | 131,072 B | 57.4% | PASS |
@@ -24,7 +24,7 @@
|---|---|---|---|
| 网络 | 13,690 B | 12 KB | ⚠ 超 1.4 KB |
| 存储 | 7,056 B | 12 KB | OK |
| UI | 30,412 B | 16 KB | ⚠ 超 13.7 KB |
| UI | 30,416 B | 16 KB | ⚠ 超 13.7 KB |
| RTOS 堆 | 57,376 B | 56 KB | 堆=配额 |
| 应用 | 14,911 B | 8 KB | ⚠ 超 6.6 KB |
| 其它 | 9,184 B | — | 参考 |
@@ -382,7 +382,7 @@ cmake --build simulator/build --config Debug # 0) 构建模拟器(须 0 警
- `--update` 有**误刷保护**(先跑文本层断言,失败即中止)——**未有意改视觉而 FAIL = bug,修代码,禁止刷参考掩盖**;
- 刷新参考后必须重跑 `regen_ref_png.py` 重生成目检 PNG(否则旧 PNG 看似乱码);
- 门禁常量漂移:先确认新值合理(残留分解见 `菜单页面设计.md` §9.5)→ 更新常量 + 在 `UI_自动化测试流程.md` 变更记录登记;
- **UI 新增中文文案提交前必须先跑 font-regen**(extract_cn → make_font → diff 检查):字符集 `ui_cn_chars.txt` 缺字则上机显示空白。
- **UI 新增中文文案提交前必须先跑 font-regen**(extract_cn → make_font → diff 检查):字符集 `ui_cn_chars.txt` 缺字则上机显示空白——**2026-10-15 起该约定已入门禁**(`font-charset` 钩子:源码在用字符 ∉ txt 或 txt ∉ 字体 cmap → 提交 FAIL,详见 `../代码规范/pre-commit使用说明.md` §2.24)。
---
@@ -625,6 +625,7 @@ CI 就静默停摆(2026-10-11 实测 run 16~21 共 12 个 job 零日志)。
| 日期 | 变更 |
|---|---|
| 2026-10-15 | **U4 残余入门禁(钩子总数 34→35)**:① 新增 `font-charset` 钩子(`scripts/check_font_charset.py`)——UI 源码在用字符 vs `ui_cn_chars.txt` vs `ui_font_cn_12.c` cmap 两段差集,白框方向 FAIL、冗余字 WARN;提取与 cmap 解析**复用** `tools/font_gen/` 两个生成器同一套规则(importlib 直载),牙齿实测=临时副本注入缺字三例全 FAIL 点名到字。② `registration-check` 补第 ④ 类缺口——`ui_page_*.c` 定义的 `ui_page_<name>_desc` 未接入 `ui_content_page.c` 的 `s_defs[]` 描述符表即 FAIL(实测原 ①②③ 对"进了两端构建但菜单打不开"的页面全绿)。§5.3 font-regen 铁律补"已入门禁"指针;详解见 `../代码规范/pre-commit使用说明.md` §2.18/§2.24 |
| 2026-10-15 | **新增 `test/host/nand_port/`(dhara NAND 移植层 L0.5,N-21 / 报告 N-12+N-13)**:`#include` 真实 `nand_ftl.c` + 真实 `Lib/dhara/{journal,map}.c`,芯片侧换成 **RAM 假芯片**(32 块 × 64 页 × 2048 B,两段式读缓存 + NOR 叠加编程 + 双编程违规计数 + 访问次数记账),149 断言覆盖 is_free 整页扫描、六入口越界守卫(`-1` + `DHARA_E_CORRUPT_MAP` + 零芯片访问 / 零标坏块)、故障注入与 dhara map"写入 → 重新 resume"场景;**内联一份"只看页首 64 B"的旧算法做对照**,证明断言能咬人。挂 pre-commit 钩子 `nand-port-unit-test`(第 16 个主机侧单测,钩子总数 33→34)。§4.1 登记运行器、§4.2.1 台账新增该模块并给"其余驱动不适格"补例外说明(驱动不适格 ≠ 驱动之上的胶水层不适格) |
| 2026-10-12 | **§9 瘦身:机器侧内容迁出**(远程 CI 文档独立成 `docs/CI/`)。§9.2 两个 job 的**步骤级细节**并入 `docs/CI/远程CI完整指南.md` §5.5、§9.4 部署前置表并入其 §0.2;本文 §9 只保留**测试分层视角**的内容(CI 覆盖哪些层、两个 job 各守哪层、触发与 paths-ignore 语义、本地等价 `ci_local.py`、"CI 不替代本地门禁")。§9.1 两个 🔴 块压缩为结论 + 指针(机制根因与排障口径归 `docs/CI/`)。相关文档表两行 CI 条目合并为一行指向 `docs/CI/README.md` |
| 2026-10-10 | §4.2.1 台账:`Drivers/BSP/NETCFG/net_cfg_legacy.c` 由 `⬜ 候选` 改为 **`⛔ 已删除`**——旧档 NCFG 迁移整体移除(`net_cfg_legacy.{c,h}` 删除、`cfg_store_legacy_path()` 撤销;旧档 `/cfg/netcfg.bin` 不读、不删、不迁移,配置回落工厂默认),该测试候选随之撤销 |
@@ -397,7 +397,7 @@ docs\内存管理\RAM使用分析与优化方案.md:585 [路径引用] docs/内
| 主题 | 去处 |
|---|---|
| 提交门禁 34 个钩子 | `docs/代码规范/pre-commit使用说明.md` |
| 提交门禁 35 个钩子 | `docs/代码规范/pre-commit使用说明.md` |
| 自动化测试与台架流程 | `docs/测试说明/自动化测试流程.md` |
| 文档写作规范(编码/链接/登记) | `docs/文档规范.md` |
| 工具路径环境变量(换机) | `docs/环境与部署/本地工具路径环境变量方案.md` |
@@ -28,7 +28,7 @@
| 模块设计 | **A−** | 看门狗(IWDG + 心跳位图 + 4 个 Fault 现场 + `.noinit`)、就绪屏障、卷锁、FTP 鉴权、`Error_Handler` 自恢复、ADC 全链均已落地;**原列的 dhara 移植层两处缺陷(N-12/N-13)与日志逐条开关(N-16)已于 2026-10-15 修复** → `GD5F2GQ5UE_Trap_Records.md` Trap 07、`../架构设计/STM32F4-Base存储架构说明.md` §5.3、`../子系统设计/运行与自检记录设计说明.md` §4.4/§4.5 | 驱动层无统一错误码约定(S-5)、RS485 无协议栈(随 B2 暂缓) |
| 内存使用 | **B+** | 堆迁 CCM + 栈/堆三面观测常开 + `mem-budget` 92% 门禁 + 预算台账与趋势基线;**R-9 已落地(2026-10-15)→ SRAM1 由 74.9% 降到 56.1%;同日移植层与日志修复 +1.6 KB → 现 **57.4%(余 55,840 B)**,不再是卡点** | **内存优化簇已整簇暂缓**(用户裁定 2026-10-15):R-2 后半(待迁 29,570 B → CCM,只差缩堆 56→32 KB)与 R-3 / R-4 / R-6 不再排期,理由与重开条件见 §5.3;**当前真正的约束是 CCM 只剩 7,904 B**——加任务 / 抬栈 / 加堆会先在这里撞墙,届时按 §5.3 重开;MicroLIB 512 B C 堆仍无机械检查(§5.5) |
| Flash 使用 | **A−** | F-1/F-2/F-3 落地省 64,576 B → 占用 **22.2%(232,280 B)** | F-4/F-5/F-6 ≈10 KB + 编译时长(§5.4) |
| UI 标准化 | **B** | golden 回归已建(`simulator/tests/` 四脚本,含池水位门禁) | 无令牌层 / 无组件库 / 无页注册表(手写 `case` 仍在)、**27 页**未落地、golden 与字符集差集未挂门禁(§6) |
| UI 标准化 | **B+** | W6 第一波已落地(2026-10-15):**L0 设计令牌层** `ui_tokens.h` 建成、**L2 页面注册表** `ui_page_registry.{c,h}` 由生成器产出并**删除了手写 `case` 分发**、`font-charset` 钩子 + `registration-check` 第 ④ 类接线校验上线、字体子集瘦身 −80 B | 无组件库(L1 `ui_w_*` 未建)、**目标页未落地**(现存 7 个 `ui_page_*.c`)、**golden 两脚本仍未挂 pre-commit**(`font-charset` 已挂,golden 未挂)、`ui_w_form` 推迟 U5(§6) |
### 0.3 主线建议
@@ -429,12 +429,29 @@ Select-String -Path 'MDK-ARM\STM32F407-Demo\STM32F407-Demo.map' -Pattern '__heap
## 6. UI 界面标准化实现方案
> ⚠ **本节"建议 / 目标结构 / 草图"不可照抄——落地前必须逐条对代码核实**(2026-10-15 立此口径)。
>
> 本节是**体系评审视角的建议**,不是实现规格。启动 W6 后按 §6 实际执行 U1 / U3 / U4 三包,**四次证伪**:
>
> | # | 报告写的 | 代码实况 | 照抄的后果 |
> |---|---|---|---|
> | 1 | §6.3 L0 清单要新建 `UI_SCREEN_W/H` | `ui_port.h:21-22` **早有同名宏** | 同名宏二次定义 |
> | 2 | `UI_COL_FG = LV_COLOR_BLACK` / `UI_COL_BG = LV_COLOR_WHITE` | LVGL 9.3 **无这两个宏**(只有 `lv_color_black()/white()` 函数);且**极性反了**——代码里所有墨色恒用 `lv_color_white()`,选中行才是黑字 | 先编译失败,改完若按报告极性则**整屏反色** |
> | 3 | §6.5 U1 行"27 页未落地" | 现存 `ui_page_*.c` 实测 **7 个**;27 是**目标页数**不是文件数 | 工作量与拆包按错数排 |
> | 4 | §6.3 生成器草图 `@page=deadzone` | **密码页不是节点绑定的**(任何 `#P` 叶子进同一页),注册表必须单独出口 | 做不出能进密码页的注册表 |
>
> 另有 §6.3 L0 清单 **9 条取值/存在性错误**(行距 13→实为 14、列表顶 15→实为 24、滚动条宽 2→实为 4、`UI_PAD_X 3` 不存在、`UI_ROW_H 12` 不存在、`UI_TITLE_H 11` 不存在、`UI_STYLE_FLAT` 在 U1 阶段做不了……)**逐条明细见 §6.3 更正块**,此处不重复。
>
> **执行规则**:① 按本节动手前,先 grep 代码核一遍建议值与建议结构是否已存在、取值是否对;② 发现不符**一律以代码为准**,不要"先按报告做再改";③ 把差集**回报并记进本节**,不要静默修正(否则下一个人还会再踩);④ 本节"发现"栏(现状描述、问题定位、成本量化)经复核**仍然可信**,不可照抄的是**建议栏**。
>
> **同一规律在本报告之外也复现过**:§4 的 N-13 建议用了本仓裁剪版 dhara 里**不存在**的 `DHARA_E_UNSUPPORTED`(照抄编译失败)。所以这不是 UI 章节的局部问题,而是**"建议"这一体裁的通病**——写建议时没有对代码核。后续任何按本报告排期的工作包,任务卡都应显式写一句"以代码实况为准,报告建议值不可直接采用"。
### 6.1 现状(框架已有,但未"闭环")
| 层 | 现状 | 评价 |
|----|------|------|
| 内容页 | `ui_content_page.c` 描述符表 `s_defs[]` **7 页**(DEVICE_INFO/AC/DC/PASSWORD/NET_CFG/RUN_LOG/SELFTEST_LOG) | ❌ `ui_menu_tab.h:28` 42 节点(**叶子 33 个**),有内容页的叶子 **6 个**(PASSWORD 非叶子映射);`menu_content_page_for()`(`ui_menu.c:118-128`)仍是手写 `case 1u/3u/4u/30u/39u/40u:` |
| 设计令牌 | **无**(每页自带 `CP_SCREEN_W/H 160`、`CP_TITLE_Y 2`、`CP_PAGE_LINE_Y 143`、`CP_ROW_BUF_LEN 32` 等布局常量) | ❌ 魔法数字分散在各页,`Drivers/BSP/UI/ui_tokens.h` 不存在(U1 未办) |
| 内容页 | 描述符 `content_page_def_t` 仍是**唯一**页面描述符(刻意不新建第二套);节点→页面映射由**生成器产出** `ui_page_registry.c`,`{node, desc}` 表 + `ui_page_registry_for()` + `ui_page_registry_password()` | ✅(2026-10-15 U3)**手写 `menu_content_page_for()` 已删除**,仓库内仅存 2 处历史说明注释;密码页按代码实况**单独出口**(非节点绑定),不进 `node→desc` 映射 |
| 设计令牌 | `Drivers/BSP/UI/ui_tokens.h` **已建**(2026-10-15 U1,20 个宏),框架 + 7 页 + `App/task/ui_task.c` 全部接入;**屏幕几何复用 `ui_port.h` 既有 `UI_SCREEN_W/H`**,不重复定义 | ✅ 纯替换验收:`@build` 0/0 且 Program Size 逐字节不变、golden 逐像素一致、池水位未变。⚠ 落地时修正本报告 L0 清单 9 处取值/存在性错误(见 §6.3 更正块) |
| golden 回归 | `simulator/tests/` 四脚本:`check_menu_rows.py`(菜单 8 状态全像素)、`check_content_pages.py`(内容页黄金参考逐字节 + 文本断言 + **LVGL 池水位门禁**)、`regen_ref_png.py`、`check_remo_sink.py` | 🟡 **有基线但未入门禁**:两个脚本未挂 pre-commit / `ui-verify` |
### 6.2 新增一个页面要走多少步(当前)
@@ -476,6 +493,17 @@ graph LR
#define UI_COL_SEL_FG UI_COL_BG
#define UI_COL_SEL_BG UI_COL_FG
/* 样式:只用 const 描述符(动态 lv_style 会每次泄漏 88 B,见 ui_content_page.c) */
> ⚠ **上面这份 L0 清单与代码实况有 9 处不符,U1 落地时已按代码为准修正**(2026-10-15 实测,`ui-tokens` 报回)。**照抄会翻车的两条**:
> ① **`UI_SCREEN_W/H` 不是新建**——`ui_port.h:21-22` 早有同名宏,在 `ui_tokens.h` 再定义一次就是同名宏二次定义;实际做法是 `ui_tokens.h` 只 include `ui_port.h` 复用,并把散落的 7 处 `160`(`CP_/MENU_/SB_/DECO_/PW_SCREEN_`、推流协议 `UI_W/H`)收敛到这一个来源。
> ② **`UI_COL_FG = LV_COLOR_BLACK` / `UI_COL_BG = LV_COLOR_WHITE` 两处都错**——本仓 LVGL 9.3 **没有** `LV_COLOR_BLACK/WHITE` 宏(全库 0 处定义),只有函数 `lv_color_black()/lv_color_white()`,照抄直接编不过;而且**极性反了**:代码里所有墨(文本 / 分隔线 / 边框 / 滚动条)恒用 `lv_color_white()`,选中行才是黑字。按本报告写会把整屏反色。落地定义:`FG=white`、`BG=black`、`SEL_FG=black`、`SEL_BG=white`。
>
> 其余 7 条是取值/存在性错误(报告值 → 代码实况):`UI_TITLE_H 11` → 代码无此值,真实重复量是 `+15` 文本条带(建为 `UI_TEXT_BAND_H 15`);`UI_ROW_PITCH 13` → 列表行距实为 **14**(13 是字体行高/选中带高);`UI_ROW_H 12` → 代码无 12 作行高,选中白带高 **13**(`UI_ROW_BAND_H`);`UI_LIST_TOP 15` → 列表首行顶实为 **24**;`UI_SCROLLBAR_W 2` → 实为 **4**;`UI_PAD_X 3` → 不存在"统一内边距 3",那个 3 是选中白带**右内缩**(建为 `UI_SEL_BAND_INSET_R 3` 配 `_L 2`);**`extern const lv_style_const_prop_t UI_STYLE_FLAT[]` 在 U1 做不了**——共享 `extern` 数组需新增 `.c` 落定义 → 必须双端注册(U1 禁碰注册文件),退化成头里 `static const` 又会在"包含但未使用"的 TU 上招 `#177-D` 破 0 警,已并入 U3。
>
> **教训**:本报告的 UI 章节是**体系评审视角的建议**,不是实现规格。落地前必须逐条对代码核一遍——本次 9 条里若照抄,两条编译失败、一条整屏反色。U3/U5 执行时同样以代码为准,发现与本节不符**直接按代码做并在回报里列出**。
>
> ⚠ **U3 开工侦察又补两条**(2026-10-15,`ui-tokens`):① **密码页不是节点绑定的**——任何 `#P` 叶子都进同一个密码页,所以注册表除 `node→desc` 映射外**必须单独出口一个"密码页"入口**;本节生成器草图的 `@page=deadzone` 没覆盖这条,照抄会做不出能进密码页的注册表。② **`ui_w_form` 从 U3 推迟到 U5**(Lead 裁定):全仓只有 **N=1** 个表单实例(`ui_page_net_cfg.c`),且它的"表单"实质是"5 行地址列表 + 逐字节编辑光标"、**并未走配置引擎的段注册表**,与本节设想的"cfg 段/键绑定 + 十进制/IP 输入约束"**并不同形**。从单一实例反推接口等于猜,而这是要动像素的重构——**重复三次再抽象**。U3 范围因此收敛为「注册表 + 删手工分发 + 共享 flat 样式」三件(这才是 U5 能并行的真前提);`ui_w_form` 等 U5 有 2~3 个真实 form 实例可对照时再抽。
> 同批裁定:**不新建 `ui_page_desc_t`**——代码里 `content_page_def_t`(title/count_cb/refresh/draw_cb/key_cb/edit_capable…,7 个页面全在用)已是唯一描述符,再造一套等于一个页面两套描述符;注册表只加 `ui_page_entry_t{node, desc}` 做节点绑定。**不加 archetype 枚举**(无消费者的元数据,真正需要它的是 U5 的"由原型自动实例化页面")。
extern const lv_style_const_prop_t UI_STYLE_FLAT[];
```
@@ -542,10 +570,10 @@ const ui_page_desc_t ui_page_deadzone = UI_FORM_PAGE("遥测死区", s_items_dea
| 步骤 | 内容 | 交付判据 | 状态 |
|------|------|---------|------|
| U1 | `ui_tokens.h` 令牌化(纯替换,不改行为) | `@build` PASS + 模拟器截图与替换前逐像素一致 | ❌ 未办。🟡 **验收条件如今可机械执行**——golden 基线已建,"逐像素一致"从口头判据变成可跑断言 |
| U1 | `ui_tokens.h` 令牌化(纯替换,不改行为) | `@build` PASS + 模拟器截图与替换前逐像素一致 | ✅ **已落地(2026-10-15)**:`ui_tokens.h` 20 个宏 + 15 个文件接令牌。**零行为变化证据**:`@build` 0 错 0 警且 `Program Size` 与改前**逐字节相同**(Code=213540 / RO=18740 / RW=1136 / ZI=131520);golden 菜单 8 状态全像素一致 + 内容页 **11 页逐字节一致**,且比对对象是改前备份的 sha256 基线(**不是 `--update` 刷出来的**);池水位 5368 / 5448 B 未变。⚠ 落地时修正本节 L0 清单 9 处与代码不符(见上) |
| U2 | `ui_w_records`(合并 runlog/selftest) | 两页行为不变,代码 −1 个文件 | ❌ 未办(两份结构几乎相同的代码仍在) |
| U3 | `ui_w_form` + `ui_page_desc_t` 原型化 + 生成器产注册表 | 手工 `menu_content_page_for()` 删除;新增一页只需"改树 + 加实例文件" | ❌ 未办(`ui_page_registry.c` / `gen_page_registry.py` 均不存在) |
| U4 | golden + 字符集检查 + 注册检查入 pre-commit | 三个新 hook 全绿 | 🟡 **1/3 落地**:golden 已建;❌ 字符集差集、❌ 注册检查未入门禁(注册检查钩子已存在,缺的是把它算作 UI 门禁的一环) |
| U3 | `ui_w_form` + `ui_page_desc_t` 原型化 + 生成器产注册表 | 手工 `menu_content_page_for()` 删除;新增一页只需"改树 + 加实例文件" | ✅ **已落地(2026-10-15)**:`ui_page_registry.{c,h}` + `ui_style.{c,h}`(原"U1 做不了"的共享 flat 样式一并落)+ 扩 `gen_menu.py` 产注册表**并自动写 `uvprojx`/`CMakeLists.txt`**;手工 `menu_content_page_for()` 已删。**实测单位成本:新增一页 = 3 处人工**(新 `.c` + 新 `.h` + 菜单树那一行加 ` #page=<名>`)**+ 1 条生成器命令,手工编辑注册文件 0 处**;生成器**双向对账**(增 `registered` / 删 `pruned`)且双向校验死代码。验收:`@build` 0/0、golden 菜单 8 状态 + 内容页 11 页逐字节一致、池水位 5368/5448 B 未变、`ER_IROM1` 232,052 B(较已提交 HEAD −228 B)、SRAM1 零增量。⚠ **本报告原口径"8 处降到 1 处"须修正**:那个 1 只在"1 处对既有文件的修改"意义下成立,页面自身 2 个文件本就要写,真实改动处数是 **3** |
| U4 | golden + 字符集检查 + 注册检查入 pre-commit | 三个新 hook 全绿 | 🟡 **2/3 落地(2026-10-15)**:`font-charset` 新钩子(字符集差集,防缺字白框)+ `registration-check` 补第 ④ 类"UI 页面描述符表接线"检查。钩子数 34 → **35** 。钩子数 34 → **35**。⚠ **修正我自己上一版的错**:此处原写"3/3 落地",是把"golden 脚本早已存在"误当成"golden 已进自动门禁"。实况是**两个 golden 脚本至今未挂 pre-commit**(一直在人工跑,无自动门禁),故改回 **2/3**,缺口单列为待办。⚠ **`--strict` 的验收口径已改**:判据是"**未知**冗余 = 0"而非"冗余 = 0"——`ui_cn_chars.txt` 里 异/常/片/芯 4 字属**刻意保留**(2026-09-14 `9eb1bd63` 写入的中文自检描述曾落盘 `/log/selftest.log`,定长 64 B 记录跨固件持久,删字形会使历史故障行渲染空白),按 `check_registration.py` 的 `KNOWN_GAPS` 同构做法进带理由的保留清单;上/电/重 3 字已证从未出现在任何字符串字面量(仅注释),照删。为几百字节牺牲已落盘审计记录的可读性不划算——同一权衡口径见 §5.3 内存簇暂缓裁定 |
| U5 | 用原型批量落剩余 **27 页**(每页 ≤30 行) | 菜单树全绿、无 `CONTENT_PAGE_COUNT` 哨兵命中 | ❌ 未动 |
> ✅ **2026-10-15 用户裁定启动**(覆盖 2026-10-11 的「本轮不排期」,登记簿 U 簇 / W6):已开智能体团队推进。**并行度受注册文件约束**——新增一个 `.c` 必须同时改 `MDK-ARM/STM32F407-Demo.uvprojx` 与 `simulator/CMakeLists.txt` 这两个共享文件,所以任何时刻只允许一个成员碰它们。实际排法:**第一波 U1(令牌层,不新增 .c)∥ U4 残余(只动 scripts/ 与门禁文档)真并行** → U3(原型化 + 生成器,独占注册文件,串行段)→ U2 → U5(页面批量,须等 U3 的生成器把注册自动化,否则无法并行)。⚠ 本节原写「27 页」是**目标页数**,现存 `ui_page_*.c` 实测只有 **7 个** → U5 开工前先对齐目标页清单差集。
@@ -573,7 +601,7 @@ const ui_page_desc_t ui_page_deadzone = UI_FORM_PAGE("遥测死区", s_items_dea
| `Drivers/BSP/UI/ui_w_{list,kv,records,form,msgbox,title}.{c,h}` | 组件库(需双端注册) | U2/U3 | ❌ 未建 |
| `tools/menu_gen/gen_menu.py` 扩展 + `ui_page_registry.c` 生成 | 生成器 | U3 | ❌ 未建 |
| `check_coding_standard.py` 加 `malloc(` 正则 | 门禁补强 | §5.5 第 5 条 | ❌ 未建 |
| 字符集差集检查 + golden 挂 pre-commit | 门禁补强 | U4 残余 | ❌ 未建 |
| `scripts/check_font_charset.py`(字符集差集)+ `registration-check` 第 ④ 类 UI 接线检查 | 门禁补强 | U4 残余 | ✅ **已建(2026-10-15)**——提取与 cmap 解析复用 `tools/font_gen/` 同一套规则(`importlib` 直载,零第二套规则);牙齿实测三例(缺字 / 字体缺码位 / 稀疏 cmap 缺偏移)均 FAIL 并点名到具体字符 |
---
@@ -631,6 +659,8 @@ const ui_page_desc_t ui_page_deadzone = UI_FORM_PAGE("遥测死区", s_items_dea
| **2026-10-15** | **删除 §0.2「未闭环问题」小节** | Top 2 修复销项后该节只剩指针与暂缓说明,而三条内容都已在别处**单点详述**:未闭环清单 → §0.4;内存簇暂缓 → §0.3 主线一与 §5.3 横幅;Top 2 修复证据 → 上一条变更记录与文末「已销项条目的记录去处」。按 `../文档规范.md`「同一事实只在一处详述」删除,不留空壳。**§0.3 / §0.4 编号保持不变、不重排**——`../任务规划/README.md` §2 前言引用本报告 §0.3,本报告内部另有 §0.4 交叉引用,重排会全断(与本表 2026-10-14 行第 ⑤ 条"报告自有编号不回改、不重排"同一口径)。文首「销项状态」行的指针由「§0.2 / §0.4」改为「§0.4」 |
| **2026-10-15** | **删除 §0.3 主线建议第 1 条("内存这条线到此为止")** | 该条是同日暂缓裁定的**复述层**,同一事实已有三处单点详述:§0.4 内存两行(⏸ 暂缓)、§5.3 暂缓横幅(三条理由 + 保留常开的治理面 + 重开条件)、登记簿 N-27 与 `../内存管理/` 两份文档的横幅。按 `../文档规范.md`「同一事实只在一处详述」删复述、留权威。⚠ 上一条变更记录里"内存簇暂缓 → §0.3 主线一"这个去处**自此失效,以本行为准**(变更记录本身不改,它是历史)。§0.3 现只剩 UI 一条主线;标题「两条主线建议」→「主线建议」,**§0.3 编号不变**(`../任务规划/README.md` §2 前言引用的是编号不是标题) |
| **2026-10-15** | **启动 W6 UI 标准化簇**(用户裁定,覆盖 2026-10-11 的「本轮不排期」) | §0.3 删掉内存主线后只剩 UI 这一条,随即启动。已按 §6.5 的 U1~U5 拆成 5 个工作包上共享任务板,第一波 **U1 令牌层 ∥ U4 门禁补强** 两名成员并行(写范围严格不相交:U1 只写 `Drivers/BSP/UI/` + `App/task/ui_task.c`,U4 只写 `scripts/` + 门禁与规范文档)。**并行度的真实约束不是任务数量,而是注册文件**:新增 `.c` 必须改 `uvprojx` + `CMakeLists.txt` 两个共享文件,同工作树两人同改必互相踩,故 U3(生成器/注册表)是必须串行的一段,U2/U5 排在它后面——U5 的页面批量要等 U3 把注册自动化之后才谈得上并行。同步 §6.5 注与本表 W6 行;`../任务规划/README.md` §2.0 W6 行同步。另修正交付物清单:移植层单测拟名 `test/host/dhara/` 实际落地为 `test/host/nand_port/`,状态 ❌ → ✅ |
| **2026-10-15** | **§6 顶部加"建议栏不可照抄"总警示** | 启动 W6 后按 §6 执行 U1/U3/U4,**四次证伪**:① §6.3 要新建 `UI_SCREEN_W/H` 而 `ui_port.h:21-22` 早有同名宏;② `LV_COLOR_BLACK/WHITE` 在 LVGL 9.3 不存在**且极性反了**(墨色实为 white),照抄先编译失败、改完整屏反色;③ "27 页未落地"是**目标页数**、现存 `ui_page_*.c` 实测 7 个;④ 生成器草图漏掉**密码页非节点绑定**。另有 L0 清单 9 条取值错,明细在 §6.3 更正块。**不再逐条打补丁**,改为节顶立总口径:动手前逐条 grep 对代码核、不符一律以代码为准、差集必须回报不得静默修正;并明确**"发现"栏可信、"建议"栏不可照抄**。同一规律在 §4 的 N-13(`DHARA_E_UNSUPPORTED` 不存在)已复现,故这不是 UI 章节局部问题,而是"建议"这一体裁的通病 → 后续任务卡须显式写"报告建议值不可直接采用" |
| **2026-10-15** | **W6 第一波落地:U1 + U3 验证通过并回填现状表** | Lead 亲自验证(成员被模型路由变更连续打断,最终停用):`@build` **0 错 0 警**;golden **菜单 8 状态全像素 + 内容页 11 页逐字节一致**、池水位 **5368 / 5448 B 与 U1 基线相同**、参考图 sha256 **差异 0 条**(证明无人用 `--update` 刷基线);`registration-check`(含第 ④ 类"页面必须被表引用")与 `font-charset` **Passed**;`ER_IROM1` **232,052 B**(较已提交 HEAD −228 B)、`RW_IRAM1` **75,232 B 零增量**;对 38 个在途修改文件逐个核对 **BOM / CRLF / U+FFFD 全部与 HEAD 一致**。**单位成本实测**(临时页 `zzprobe` 绑到 `遥信量` 叶子 → 只跑生成器 → 带页 `@build` 0/0 → 注册表出现 `{5u, &ui_page_zzprobe_desc}` → 回滚后 6 个产出文件的 `zzprobe` 残留计数均为 0、重编回基线)得出 **新增一页 = 3 处人工(新 `.c` + 新 `.h` + 树那一行加 ` #page=<名>`)+ 1 条生成器命令,手工编辑注册文件 0 处**,并确认生成器 `registered` / `pruned` **双向对账**(不只增、也减)。据此修正 §0.1 UI 行(B → **B+**)、§6.1「内容页」与「设计令牌」两行、§6.5 U3 行;并把 §6.5 U4 从我上一版**误写的 3/3 改回 2/3**(golden 两脚本至今未挂 pre-commit,"脚本已存在"≠"已进自动门禁");§6.5 U3 原口径"8 处降到 1 处"改为**真实 3 处**。**"分三笔提交"计划作废**:U1 与 U3 改同一批文件、文件内交叠,硬切会产生不可编译的中间态,改为整波一笔 |
| **2026-10-14** | **清理:删除已完成与过时内容** | ① **已修复项按销项删除**(去处见下表):N-02(FTP 鉴权)、N-03c(`Error_Handler` 降级)、**N-11(DMA 可达性三层防线 + 规则族 R1~R4)**、S-3(注册反向校验)、P2-5/P2-6(SD2506 负温度与 WRTC)、P2-8(`NET_RECV_TIMEOUT_MS` 已删)、P2-9(`mkdir` 幂等重试)、§5.5 前三条(内存治理三件套)、交付物清单已建项。② **删除过时层**:2026-09-16 / 2026-10-11 双列基线表与"复核期间未提交改动"口径说明、旧"组合结果预估"表、逐条"2026-10-11 复核"批注、历史变更记录行——内存数字改由 `../内存管理/RAM预算台账.md` 与 `scripts/ram_baseline.tsv` 持有。③ **按 2026-10-14 `.map` 与代码重测**全部保留结论的数字(含 `lftpd_log.c` 已删除并入 `lftpd_auth.c`,N-06 残余只剩 `rs485_task.c` 一条刻意缺口)。④ **修正三处错误**:R-5(`configMAX_PRIORITIES` 56→32)**判定不可行**(CMSIS-RTOS2 `#error`);原 §7 把报告 S-5(驱动统一错误码)与登记簿 S-5(卷锁覆盖面)混为一谈;原 §5.5 第 4 条建议的 `_Static_assert` 形态在 AC5 上取不到链接期地址,已被"窗口断言 + 启动自检 + 运行时守卫"三层取代。⑤ 报告自有编号**不回改、不重排**(`../编号规范.md`) |
### 已销项条目的记录去处