diff --git a/.dsh/skills/id-family-semantic-migration/SKILL.md b/.dsh/skills/id-family-semantic-migration/SKILL.md index 6a8e74c7..403c09b6 100644 --- a/.dsh/skills/id-family-semantic-migration/SKILL.md +++ b/.dsh/skills/id-family-semantic-migration/SKILL.md @@ -1,7 +1,7 @@ --- name: id-family-semantic-migration description: 编号族整族清退/停发 playbook:把一个编号族(字母+数字如保护功能号 L1-x~L5-x、网络条目号 F-*、登记簿旧号 N-x、台架阶段裸形 T1~T3、用例号 TC-*,或中文前缀「卡」+ 数字这类门禁语料里**没有机器识别面**的族)在全仓代码注释、测试、活文档与门禁配置里改成语义短语(含销项删行与逐号换算表入档),或把「不清退」裁定写成硬口径入档。触发语:清退某族编号、编号改成语义名或语义短语、还有多少号可清、残留多少、批次二/批次三/批次五、「卡 0」「卡 0b」「卡 1~12」、销项删行并去除相关编号、id-check 报悬空引用或不可判定超限、不可判定引用绝对数涨点、「这一族不做了」。 -whenToUse: 用于**整族**处理:先判这一族有没有机器识别面 → 清点存量 → 逐族分类 → 分批派单清退 → 收口 → 回写 docs/编号规范.md 与变更记录。单条待办行销项并写 void 别名用 ledger-row-retire-void-id;某个事实数(页数、叶数、钩子数)变了要同步全仓用 stale-doc-count-sweep;单个文件改名或挪目录用 scripts/rename_ref.py;跑 HEAD 版对照组用 task-worktree 的净室 worktree。这四类不由本技能覆盖,但「涨点归因」一节会用到净室 worktree。 +whenToUse: 用于**整族**处理:先判这一族有没有机器识别面 → 清点存量 → 逐族分类 → 分批派单清退 → 收口 → 回写 docs/编号规范.md 对应节。单条待办行销项并写 void 别名用 ledger-row-retire-void-id;某个事实数(页数、叶数、钩子数)变了要同步全仓用 stale-doc-count-sweep;单个文件改名或挪目录用 scripts/rename_ref.py;跑 HEAD 版对照组用 task-worktree 的净室 worktree。这四类不由本技能覆盖,但「涨点归因」一节会用到净室 worktree。 version: 1.1.0 --- @@ -88,7 +88,7 @@ version: 1.1.0 ./.venv/Scripts/python.exe scripts/archive/id_gate/check_ids.py --strict 2>&1 | tail -1 # [OK] 校验 1~6 无错误 ``` 报告「字面量 8787→8299→7828」「不可判定绝对数 1161→984→982→978(上限 1166)」「可判定比例 88.14%(基线 86.0%,容差 0.1pp)」。**绝对数与比例两根线都要报**:把可判定引用改成散文会稀释比值,所以另有不可判定绝对数上限。涨点归因见「净室归因」一节。 -13. **回写 `docs/编号规范.md`**:§4.1 族表(停发/待清栏)、§4.1.1 已停发栏、§9 存量表与批次结果表(只减不增)、§9 清点数字按最终实测同步;表格若保留动手前的清点数,**明确标注「不是当前存量,是动手前基线」**,否则就是拿旧数当现状。变更记录加一行(含用户裁定原文)。 +13. **回写 `docs/编号规范.md`**:§4.1 族表(停发/待清栏)、§4.1.1 已停发栏、§9 存量表与批次结果表(只减不增)、§9 清点数字按最终实测同步;表格若保留动手前的清点数,**明确标注「不是当前存量,是动手前基线」**,否则就是拿旧数当现状。**用户裁定原文与理由直接写进对应节**(§4.1.1 停发行 + 该族的批次结论段落)——2026-10-28 起不再往变更记录写流水(`docs/文档规范.md` §5.1)。 14. **裁定「不做」也要写成可执行硬口径入档**(不是只划掉一行——「不做」最容易被读成「那还可以继续发号」): - §4.1.1「已停发」栏新增该族一行:**游标冻结、现存号只减不增、新用例改用语义化测试函数名 + 文档表格行名**,并写清与「允许继续发号」栏为何不打脸; - §9.1 批次段落写明裁定原文与理由(该族是唯一真被脚本按字面量匹配的族:C 断言标签 + 测试函数名 + 文档用例表三处同一号),并给出**将来真要清退的前置条件**:追溯器(`check_test_traceability.py`)先同时认新旧两种形态、并行核对通过,**不许先改文档再改代码**; @@ -144,7 +144,7 @@ version: 1.1.0 6. **逐处替换断言命中数**(同第 7 步的 `rep(tag, old, new, want)`),且 `old` 串**从原文取、不凭记忆敲**:本仓中文引号与 ASCII 双引号混用(实测某文档里的「中文引号」其实是 ASCII `"`),凭印象写 `old` 必 `got=0`;断言抛错后先 `git status --porcelain=v1 -- <文件>` 自证文件未被别道改动,再回读该行真身重跑。删行类改动单独记 tag 并打印删了几行、行号与原行长度。多道并行时同一文件常被别道改过:`edit` 报 `file changed since it was read` → 重新 `read` 再改;报 `ReplaceFileW EIO (Win32 1175)` → 先自证文件字节完好(BOM / CRLF / `EF BF BD` 三项)再重试同一笔,不要顺手改内容。 7. **落地位置写死(这一族只有这几条兜)**: - `docs/编号规范.md` **§4.1.1「已停发的族」表加一行**,三列齐全,第三列直写「⚠ **机器面空白**:中文前缀不进 `scripts/archive/id_gate/check_ids.py` 语料 → 门禁咬不到,只有本表 + §9.3 + 评审三条兜;`id_aliases.json` 刻意不登记(登记了机器也看不见,只多一张没人核的表)」; - - `docs/编号规范.md` **§9.3 逐号换算表**(旧号形态 → 语义短语 → 现行口径出处;本族实测 14 行 = 0、0b、1~12)+ §9 批次段落 + 变更记录各一行,**写明旧号永久作废、不得重新取走**; + - `docs/编号规范.md` **§9.3 逐号换算表**(旧号形态 → 语义短语 → 现行口径出处;本族实测 14 行 = 0、0b、1~12)+ §9 批次段落(裁定原文与逐号结论都落在正文),**写明旧号永久作废、不得重新取走**; - 表内**把形态写成「卡」+ 数字而不复述字面量**:规范本身是门禁语料,复述字面量会把「讲规则的文档」变成自己的引用站点; - **同步叙述**:`AGENTS.md`「文档与图形」的销项条目、`docs/README.md`(例:`数据可信.md = 三项阻塞任务` → 两项)、`docs/任务规划/README.md`、`docs/任务规划/登记簿.md`——「剩余三项」这类旧口径实测归零; - **与有识别面族的判别写进同一张表**:能被脚本按字面量匹配 → 走 `rename_ids.py` + 别名登记;匹配不到(中文前缀、纯散文号、圈号)→ 走规范换算表,**不登记别名**; @@ -206,8 +206,8 @@ version: 1.1.0 4. `pre-commit run generated-fresh --all-files` PASS + 目检 svg diff 只有文案与框宽自适应(只在动过生成器时适用);`check_doc_links.py --all` 通过。 5. `@build`:`BUILD=0`、0 错 0 警、`Program Size` 与改前同数(零行为改动证据,**本回合真跑**);相关主机组(如 `net_socket 457/457`)全绿。 6. 真实 pre-commit 钩子全绿(如 `passed=33 failed=0`);提交笔内不含他道文件。 -7. 规范与台账已回写并复跑核数:自己先前写进规范的清点数字要么按最终实测改对,要么标明为动手前基线;「等你裁定」残留 = 0;「不做」裁定已在 §4.1.1 + §9.1 + 变更记录三处落地。 -8. **无识别面族**:`git grep -nE '卡[ ]*[0-9]' -- .` 无输出(裸跑读 rc);自建扫描器的站点/文件数与提交正文一致;交付里明写「本族不在 check_ids 语料内、门禁判不到」与「刻意不进 `id_aliases.json`」的理由;§4.1.1 停发行 + §9.3 换算表 + 变更记录三处齐全,换算表行数 = 该族字面量数(实测 14),且写明旧号永久作废、不得重新取走。 +7. 规范与台账已回写并复跑核数:自己先前写进规范的清点数字要么按最终实测改对,要么标明为动手前基线;「等你裁定」残留 = 0;「不做」裁定已在 §4.1.1 + §9.1 + 批次结论段落三处落地(原「变更记录」那一处已随 2026-10-28 清流水退场)。 +8. **无识别面族**:`git grep -nE '卡[ ]*[0-9]' -- .` 无输出(裸跑读 rc);自建扫描器的站点/文件数与提交正文一致;交付里明写「本族不在 check_ids 语料内、门禁判不到」与「刻意不进 `id_aliases.json`」的理由;§4.1.1 停发行 + §9.3 换算表 + 批次结论段落三处齐全,换算表行数 = 该族字面量数(实测 14),且写明旧号永久作废、不得重新取走。 9. **二次清洗三道各有实测数**:同句重复短语 0 行、各空格形态先计数后归一(复扫 0)、固定正则残留 0;被代码头注释引用的设计约束章节仍在(`git diff` 里没被动过)。 10. **叙述同步**:`AGENTS.md` / `docs/README.md` / `docs/任务规划/README.md` / `docs/任务规划/登记簿.md` 里旧口径(「三项」「卡 N」类)实测归零;`ci-artifacts/` 里本次 spec 与中间产物已删。 11. 门禁复跑清单齐:`check_ids.py` plain + `--strict`、`check_doc_links.py --all`、`bom-guard`、`no-mojibake`、`git diff --check`、`@build` 或受影响单测——**每个数字标明是本回合实测**。 diff --git a/.dsh/skills/stale-doc-count-sweep/SKILL.md b/.dsh/skills/stale-doc-count-sweep/SKILL.md index f0001e8a..485576c4 100644 --- a/.dsh/skills/stale-doc-count-sweep/SKILL.md +++ b/.dsh/skills/stale-doc-count-sweep/SKILL.md @@ -1,6 +1,6 @@ --- name: stale-doc-count-sweep -description: 全仓陈旧计数同步 playbook——某个事实数(黄金参考页数/张数、菜单树叶数与已绑叶数、字库字数与字形数、提交钩子数等)变了之后:每个数先剔伪命中再双源互证定真值 → 全形态全命中面扫描(含 .pre-commit 钩子显示名与 .dsh/skills 正文)→ 逐条分类(当前态改 / 变更记录只追加当日新行 / 同数不同义不动 / 带日期戳的测量只加「当时」/ 数字对但口径描述错另起一笔)→ 每处先读现文再字面替换并断言命中数 → 全文通读核对各小节 → 提交后再按全部旧形态复扫归零 → 跑门禁分笔提交。 +description: 全仓陈旧计数同步 playbook——某个事实数(黄金参考页数/张数、菜单树叶数与已绑叶数、字库字数与字形数、提交钩子数等)变了之后:每个数先剔伪命中再双源互证定真值 → 全形态全命中面扫描(含 .pre-commit 钩子显示名与 .dsh/skills 正文)→ 逐条分类(当前态改 / 历史行冻结(2026-10-28 起只剩保留变更记录的 5 篇) / 同数不同义不动 / 带日期戳的测量只加「当时」/ 数字对但口径描述错另起一笔)→ 每处先读现文再字面替换并断言命中数 → 全文通读核对各小节 → 提交后再按全部旧形态复扫归零 → 跑门禁分笔提交。 whenToUse: 某个计数/数字变了要跨 md/yaml/py/txt 同步、用户说「同步一下 / 全仓改一遍 / 这个页数(张数、叶数、字形数、钩子数)不对」、怀疑某个数是伪命中或口径错了(含 notdef 吗、含 ASCII 吗、是张数还是页数)、发现文档数字与实测不符、或同一份文档两节数字/顺序对不上要先核口径时。 --- @@ -54,7 +54,7 @@ whenToUse: 某个计数/数字变了要跨 md/yaml/py/txt 同步、用户说「 | 类别 | 判定 | 动作 | |---|---|---| | 当前态陈述 | 描述「现在是多少」 | 改成实测真值 | - | 变更记录历史行 | 形如「47 → 53 页」的当日事实 | **原样冻结不回改**;在该文件 §变更记录**追加当日新行**(本仓变更记录表按日期升序 → 新行是**末行**,不是表顶;含判据与实测来源) | + | 变更记录历史行 | 形如「47 → 53 页」的当日事实 | **原样冻结不回改**——但这条**只适用于保留变更记录的 5 篇**(台账 / 被别处当唯一证据出处的文档,清单 → `docs/文档规范.md` §5.1);其余文档的变更记录节已于 2026-10-28 整节删除,**不再追加任何流水行**,数字同步只改**当前态** | | 同数不同义 | `最坏路径 < 40KB` 这类内存/绘制缓冲红线 | **不动**,并在结论里写明「为什么不动」 | | 带日期戳的测量 | 「2026-10-26 实跑 …覆盖当时 40 页中的」 | **不臆改新数**,只补「当时」两字锁口径;新数留待下次实跑回填 | | 数字对但**口径描述错** | 数没错、句子把口径讲错了(实测:写「218 字(含 ASCII/符号,共 313 字形)」,而 `ui_cn_chars.txt` 的 218 个码点**全为非 ASCII**) | **另起一笔只改口径的提交**(`6daa01ae`),不与数字同步混笔;这类命中在任何数字 diff 里都看不见,只能把口径句逐句读一遍 | @@ -118,8 +118,8 @@ whenToUse: 某个计数/数字变了要跨 md/yaml/py/txt 同步、用户说「 - **张数与页数互相冒充**:一个 12 行分页页第 2 页要单独拍一张,于是「+2 页」可能等于「+3 张」。两个数分别报、分别换算,别互相顶替。 - **只扫 docs/**:漏 `.pre-commit-config.yaml` 钩子 `name:` 显示名里的页数、AGENTS.md 钩子清单、`.dsh/skills/*/SKILL.md` 自带的计数与脚本路径(skill 正文也是命中面:font-regen 的 179/274 本窗最后才改)。 - **提交完就收工**:第 7 步的提交后复扫才是把漏网当前态(架构总览 §3)揪出来的那一步;漏了它,仓库里就留下一行「当前态写旧数」直到别人再扫。 -- **变更记录新行插到表顶**:本仓三份文档(产品需求 §12、架构总览 §10、`docs/门禁说明/ui-golden.md`)的变更记录都按日期升序 → 新行**追加为末行**。插表顶会把首行「初版」挤成第二行,读起来像被改过序。 -- **历史行被当陈旧值改掉**:「47 → 53 页」是当天事实,改了就是伪造历史;正确动作是加当日新行。**历史行被写坏**时按无反引号兜底写法整行重写,别用同样写法再改一遍。 +- **去已删掉变更记录的文档里「补一行流水」**:2026-10-28 起全仓只有 **5 篇**保留变更记录表(清单 → `docs/文档规范.md` §5.1),计数同步**只改当前态**、过程交给 `git log`,别再到别的文档里找或加变更记录行。真要往那 5 篇的台账里加行,历史坑照旧:它们的表按日期**升序** → 新行**追加为末行**,插表顶会把首行「初版」挤成第二行。 +- **历史行被当陈旧值改掉**:「47 → 53 页」是当天事实,改了就是伪造历史;正确动作是**只改当前态那几处**、历史行一个字不动(保留变更记录的 5 篇要写台账也只追加、不回改)。**历史行被写坏**时按无反引号兜底写法整行重写,别用同样写法再改一遍。 - **照抄用户给的数**:用户说「从 40 扩到 47」也要自己数 `ref/*.bin`;数出来不一定是 47。 - **把节点行当叶子数**:42 是 `ui_menu_tree.txt` 的节点行数、33 才是叶子;不读文件头规则就数错(实测把错数写进两份文档,下一轮才自查出来)。 - **整文件正则批处理**:第一次尝试的正则没编译过、整批零落地。改法 = 逐条字面替换 + 每处 `assert count == expect`。 @@ -140,7 +140,7 @@ whenToUse: 某个计数/数字变了要跨 md/yaml/py/txt 同步、用户说「 - [ ] 替换脚本打印了每处 `old -> new xN` 且每处 `assert` 通过(无半落地;报错时已 `git diff --stat` 确认零写入) - [ ] 命中面覆盖 `.pre-commit-config.yaml` 钩子 `name:`、AGENTS.md、`docs/**`、`scripts/**`、`.dsh/skills/*/SKILL.md`,逐条在改动清单里出现 - [ ] 被改文件已全文通读,同文档各小节与配套 README/清单的顺序、计数、完成状态一致;口径闭合(如 `未绑 = 待做 + 不做`) -- [ ] 变更记录:历史行原文未动,只新增当日一行(升为末行);钩子一增一减写成同一行的两个阶段 +- [ ] 变更记录:**保留的 5 篇**历史行原文未动;其余文档本轮**零新增流水行**(当前态改完即止);钩子一增一减这类过程细节写进提交正文,不写进文档 - [ ] **提交后**又按全部旧形态复扫一次,当前态残留 = **0**,每条剩余命中都能归类(历史行 / 误报 / 已加「当时」);发现的漏网当前态已单独补一笔 - [ ] `check_doc_links.py --all --sections-strict` 打印「文档路径检查通过(N 个文档)」;`ci_local.py` / `pre-commit` 全绿(RC=0、`failed=0`);BOM 与原文件一致、无 `EF BF BD` - [ ] 分笔提交完成,回报 commit 号 + 每笔改了哪些文件 + 没动的那几类及理由 diff --git a/.dsh/skills/ui-verify/SKILL.md b/.dsh/skills/ui-verify/SKILL.md index be285fc8..a11e7b1c 100644 --- a/.dsh/skills/ui-verify/SKILL.md +++ b/.dsh/skills/ui-verify/SKILL.md @@ -31,7 +31,7 @@ cmake --build simulator/build --config Debug # 0) 构建模拟器(须 0 警 |---|---|---| | 内容页 FAIL,且**有意**改了该页视觉 | 预期变化 | 先肉眼确认新效果正确(窗口模式或 `i1_to_png.py` 出图对照 mockup),再 `.venv\Scripts\python.exe simulator/tests/check_content_pages.py --update` 刷参考,`git diff` 检查 ref/ 变化后随代码提交 | | 内容页 FAIL,但**未**有意改视觉 | bug(缺字/几何漂移/样式回归) | 修代码;**禁止**刷参考掩盖 | -| 池水位门禁失败但像素一致 | 结构/样式变更(常量样式转换、增删框体等) | 确认新值合理(残留分解见 `菜单页面设计.md` §9.5)→ 更新脚本常量 + 在流程文档变更记录登记 | +| 池水位门禁失败但像素一致 | 结构/样式变更(常量样式转换、增删框体等) | 确认新值合理(残留分解见 `菜单页面设计.md` §9.5)→ 更新脚本常量 + 把新值与它的实测来源写进 `docs/UI设计/UI_自动化测试流程.md` 正文常量表(2026-10-28 起不再记流水,见 `docs/文档规范.md` §5.1) | | 菜单回归失败 | 结构断言(白带占比/边框/往返一致) | 按脚本打印的未过断言清单逐项修代码,无参考文件可刷 | ## 池水位门禁常量(在脚本头部) diff --git a/docs/CI/README.md b/docs/CI/README.md index bb76ed7d..135400df 100644 --- a/docs/CI/README.md +++ b/docs/CI/README.md @@ -79,11 +79,4 @@ ## 变更记录 -| 日期 | 变更 | -|---|---| -| 2026-10-12 | 🐛 **首次真跑出 run**:`主机侧纯逻辑单测` **成功**(`10 runner(s), 647/647, fail=0`,与本地逐字一致);`静态门禁` **假失败**——gitlint 因 runner 无 git 身份而 `exit 254`(`Missing git configuration: please set user.name`),旧文案把它说成"提交信息违规",且该步 `exit 1` 连带让 26 个钩子全部没跑。已在 `ci_gitlint_range.ps1` 用 `GIT_CONFIG_*` 注入一次性身份(不写文件)并区分 254/1 退出码。另记:**新建分支的首次 push 不触发 run**,需 `workflow_dispatch` 或再推一个非文档提交。详见指南 §7 | -| 2026-10-12 | 🔀 本轮 CI 修复随 `master` **合入 `v2-on-ui`**(该分支另有 21 个功能提交;冲突仅 `AGENTS.md` 与 `docs/README.md` 两处,解法是"保留其新版结构 + 把 CI 指针搬进对应位置")。因该分支门禁更多(**26 钩子 / 10 单测套件** vs master 的 18 / 3),指南里写死的数字已改为**规则 + 分分支快照**,见指南 §6 / §7 / §10 | -| 2026-10-12 | ✅ 双看门狗缺陷**实测收敛**(管理员 `-StartNow` 清掉 3 个残留 → 单实例、链路恢复、runner online)。另修两处:daemon 日志走 stderr 被 PS 5.1 `2>&1` 包成 ErrorRecord(2 行真日志写成 8 行,每 4 行 3 行噪声)→ 启动器改 `ForEach-Object { "$_" }`;`-Status` 诚实化(非管理员读不到 SYSTEM 进程命令行 → 明说需提权而非谎报"无看门狗";重启循环判据改看进程存活时长,不再靠不轮转日志的尾部字符串报假警)。详见指南 §7.3 | -| 2026-10-12 | 🔴 **修复"双看门狗抢 `.runner.lock`"缺陷**:`Unregister-ScheduledTask` 不停旧实例进程 → 孤儿看门狗养着旧 daemon 占锁,新看门狗每 10 秒失败一次,而 runner 网页照样 online、`-Status` 也说"在跑"。现 `-StartNow` 先清残留进程再启动、`-Status` 报重复实例与锁冲突。同日清理机器侧:`config.yaml` 头部错误指引("改用 sc.exe / New-Service")改为看门狗口径,删除已废弃的 `deploy_runner_task.ps1` 与 `run_runner.cmd`,`check_env.ps1` 提示同步改指 bootstrap | -| 2026-10-12 | **单一口径清理**:合并稿初版对 4 处分歧"两说并存",现统一为本机实测现状——注册口径(`gitea-runner v4.0.1` / `D:\Docker\act_runner` / `127.0.0.1:3001`,旧 `act_runner v0.2.11` + `C:\act_runner` 段删去可复制命令只留警示)、`config.yaml`(`fetch_timeout: 1m0s`、`timeout: 30m0s`)、常驻方式(只认看门狗,`deploy_runner_task.ps1` 标废弃)、验收数字(主机侧纯逻辑单测 `288/288`,历史数字标注为快照)。并补"机器侧遗留脚本勿误用"警示 | -| 2026-10-12 | **新建本目录**:远程 CI 内容原先散在 `docs/环境与部署/`(两篇互相重叠的指南)、`docs/测试说明/测试开发标准流程.md` §9、`AGENTS.md` 提交门禁节共 4 处,约 2000 行;现合并为单一指南并把 `AGENTS.md` 压成一行指针。动因:远程 CI 只涉及本机一台 runner,与日常开发规范混在一起每次会话都被读,造成困惑 | +> (本文件不再记流水账:改了什么是正文说了算,改动过程查 git log。) \ No newline at end of file diff --git a/docs/CI/远程CI完整指南.md b/docs/CI/远程CI完整指南.md index 593c89a9..34eba310 100644 --- a/docs/CI/远程CI完整指南.md +++ b/docs/CI/远程CI完整指南.md @@ -1350,23 +1350,4 @@ powershell -ExecutionPolicy Bypass -File scripts\ci_runner_bootstrap.ps1 -DryRun ## 变更记录 -| 日期 | 变更 | -|---|---| -| 2026-10-25 | 🔒 **A-5 残余销项联动(§0.0 重写)**:体积门禁由"CI 不守"改为**同码凭证强制**——本地 `@build` 0/0 后 `ram_baseline.py --update` 盖 `scripts/size_attestation.json`,静态门禁作业末尾 `check_size_gate.py --ci` 复核同码性 + 红线复算(runner 无需 Keil);主干 push 拦红、其余事件 warn-only;`mem-budget` 补进 SKIP 名单诚实显示。指纹取 git 索引 blob(跨 checkout 稳定,修 7c4628b);三项仍守不住的口径唯一正文 = 脚本 docstring | -| 2026-10-12 | 🐛 **第一次真跑出 run,当场暴露 gitlint 门禁空转**:把本轮修复推到新分支 `v2-on-ui-ci` 后拿到 task 31/32——**主机侧纯逻辑单测成功**(`10 runner(s), 647/647 assertions passed, fail=0`,与本地逐字一致),**静态门禁失败**却与提交信息毫无关系:`exit code: 254` + `Missing git configuration: please set user.name`。根因是 `actions/checkout` 把 HOME 指向每次任务的临时目录、SYSTEM 账号没有 git 身份,gitlint 在读到规则之前就配置错误退出;旧脚本还把失败原因**写死**成"标题超 100 字符",加上该步 `exit 1` 让后面 26 个钩子**一个都没跑**。修法:脚本先探测身份,缺失就用 `GIT_CONFIG_COUNT/KEY/VALUE` 注入一次性身份(不写文件、不碰开发者机器),并区分 254(门禁没跑起来 → `exit 2`)与真实违规(→ `exit 1`)。另记一条新坑:**新建分支的首次 push 不产生 run**(§7 排障表 ④) | -| 2026-10-12 | 🔀 **随 `master` 合入 `v2-on-ui`:数字口径改为分支中立**。本指南原先写死 master 的数字(18 钩子 / 17 报告、3 runner / 288 断言),而 `v2-on-ui` 是 **26 钩子 / 10 套件**——同一篇文档在两个分支上必然有一个是错的。§6 验收第 8 行、§7 排障表、§10 验收标准三处改为讲规则(**报告数 = 定义数 − 1**;**runner 数 = `test/host/` 下 `run_unit_test.py` 个数**)+ 分分支实测快照。本次合并只带文档与脚本,**零 C 代码改动**;合并后本分支 `@build` 0 错 0 警、`ci_local.py` 全绿(静态门禁 25 钩子 + 主机侧纯逻辑单测 10 runner / 647 断言) | -| 2026-10-12 | ✅ **双看门狗缺陷实测收敛** + 修掉日志里的 PS 5.1 stderr 包装噪声与 `-Status` 假警。① 管理员 `-StartNow` 杀掉 3 个残留(孤儿看门狗 26900/19716 + 占锁 daemon 53848)→ `daemon up: pid 40360 (single instance)`,监管链 `svchost → 看门狗 → daemon`,看门狗日志 25 秒零增长、runner 回 online。② 新坑:daemon 日志写 **stderr**,PS 5.1 的 `2>&1` 把每行包成 ErrorRecord → `gitea-runner.exe : ` 前缀 + 4 行 `CategoryInfo` 块,实测 2 行真日志写成 8 行(**每 4 行有 3 行是噪声**,且就在文档让大家第一个打开的文件里)。启动器改为 `2>&1 \| ForEach-Object { "$_" } \| Out-File -Encoding utf8`(实测与 cmd 包装等价但免引号剥离坑,`$LASTEXITCODE` 不受影响);§7.2 方式 B 的示例原本正是 `> log 2>&1`(UTF-16LE + 包装双坑),已改;新增 §7.3 汇总这两条。③ `-Status` 两处诚实化:非管理员**读不到 SYSTEM 进程命令行**(`CommandLine` 为 null → 过滤器静默匹配 0 个),改为明说"需提权"而不是谎报"没有看门狗";重启循环判据不再靠"日志尾部有没有错误串"(文件不轮转,修好后旧失败仍在尾部 → 对健康 runner 报假警),改看 **daemon 进程存活时长**(CIM `CreationDate` 非管理员可读,`Process.StartTime` 对 SYSTEM 进程不可读) | -| 2026-10-12 | 🔴 **实测揪出"双看门狗抢锁"缺陷并修复** + 机器侧清理。① 现象:runner 网页 online、`-Status` 说 daemon 在跑,但 `runner-watchdog.log` 每 10 秒刷 `starting daemon → daemon exited, exit code 1`,daemon 日志 `runner file is already locked by another process`。② 根因:`Unregister-ScheduledTask` **不停旧实例启动的进程**——13:22 重跑 bootstrap 时旧看门狗(12:53 起)成孤儿并继续养着旧 daemon、占住 `.runner.lock`,新看门狗永远抢不到锁,任务实际谁也没管,日志以约 20 MB/天在刷。③ 修复:`ci_runner_bootstrap.ps1` 的 `-StartNow` 现在**先停孤儿看门狗与残留 daemon 再启动**并回显单实例确认;`-Status` 新增重复实例计数与锁冲突检测。④ 机器侧清理:`config.yaml` 头部那句**错误指引**("常驻改用 Windows sc.exe / New-Service",正是 §3.0 证伪的路)改为看门狗口径并指向本文;删除已废弃的 `deploy_runner_task.ps1` 与 `run_runner.cmd`(§3.2),`check_env.ps1` 指向它们的提示同步改指 bootstrap。⑤ 核实:`config.yaml` 改后 YAML 可解析且**所有配置值与改前逐项一致**(只动注释);`check_env.ps1` 带 BOM 且语法 0 错;删除前确认计划任务动作目标是 `run_runner_watchdog.ps1`,删除不影响在跑 runner | -| 2026-10-12 | 🧹 **单一口径清理(以本机实测现状为准)**:合并稿初版对 4 处分歧采取"两说并存 + 衔接注",本次统一。① 注册口径——`act_runner v0.2.11` + `C:\act_runner` + 公网域名 instance 一段**删除可复制命令**,只留"勿照抄"警示(核实 `C:\act_runner` 至今不存在,本机是 `gitea-runner v4.0.1` + `D:\Docker\act_runner` + `127.0.0.1:3001`);② `config.yaml` 示例 `fetch_timeout` 由 `5m0s` 改为磁盘实际值 **`1m0s`**、`timeout` 统一 `30m0s`,并补"不得超过 RPC timeout(1m0s)";③ 常驻口径统一为看门狗——§3.2 `deploy_runner_task.ps1` 标为**已废弃**并说明失效机理(单次 daemon = 正常退出,失败重启永不触发),§3.3 手动等价命令**重写为看门狗版任务对象**(旧版会教人手搓出坏配置),§10 TL;DR 第 4 步改指 `ci_runner_bootstrap.ps1`;④ 数字口径——主机侧纯逻辑单测期望值更新为 **288/288**(run#8 的 39/39 与 278/278 标注为历史快照,判定只看 `fail=0` 与 A==B),钩子数按现行 18 定义 / 17 报告。另同步:健康三查与排障表改用现行日志名(`runner-daemon.log` / `runner-watchdog.log`,`runner-stdout.log` 标为遗留且说明其混编码)、BOM 示例对象换成 `check_env.ps1` 并注明看门狗是纯 ASCII 无需 BOM、配套脚本表补 `run_runner_watchdog.ps1` 并标出磁盘上仍存的废弃脚本建议删除、补 `Next Run Time` 为空属正常的说明 | -| 2026-10-12 | **文档合并**:本次把 `CI配置指南.md` 与 `Gitea_Runner部署指南.md` 合并为本篇(`docs/CI/远程CI完整指南.md`)并迁入 `docs/CI/`,去重(runner 注册 / config.yaml / 装软件 / 排障表两篇均有)、补入 runner 看门狗与机器级变量实测教训;相对链接按新位置改写,原两篇互引改为本文内部引用 | -| 2026-10-11 | **bootstrap 自身修复**:`StartWhenAvailable` 误设到**触发器**上(该属性属**任务设置**,触发器没有)→ 脚本在"已注销旧任务、尚未注册新任务"之间抛 `SetValueInvocationException`,把 runner 任务删没了。现改为①先构建 action/trigger/settings、**后**注销旧任务,②`Register-ScheduledTask` 失败时显式告警"旧任务已删、CI 裸奔",③新增 **`-DryRun`**(免管理员即可全量校验任务对象),④`-Status` 在非管理员下额外提示"看不见任务 ≠ 任务不存在"。同时更正根因:旧任务其实存在,但跑的是**单次** `daemon`——daemon 属"正常退出"而非"失败",计划任务的失败重启**救不到**它,必须用看门狗循环重拉 | -| 2026-10-11 | **修"很多任务不执行"(runner 静默停摆)+ 补 gitlint 门禁**:① §2.4 重写——`gitea-runner` v4 的 `daemon` **无服务支持、首次 Declare 失败即退出进程**(日志实证),Gitea/机器重启一次 CI 就停摆,**run 16~21 共 12 个 job 零日志**(`cancelled`/`queued`,叠加 `cancel-in-progress` 后表现为"任务凭空消失"而非失败);新增 **`scripts/ci_runner_bootstrap.ps1`**(等 Gitea 就绪 + 崩溃自拉起的看门狗 + 开机计划任务 + `-SetEnv` 写机器级 `DTU_*` + `-Status` 只读体检)。② §3.1 重写——SYSTEM 可见性三重坑(PATH python 是 msys64 无 pre-commit / 用户级 site 对 SYSTEM 不可见 / `.venv` 已 gitignore)是 run 14~15 静态门禁全灭根因(`33a4aa4` 把候选收窄成这两个、又删了 cppcheck 目录兜底,而机器级 `DTU_*` 从未设置);探测收进 **`scripts/ci_find_python.ps1`**(两 job 共用、可离线自测、失败列出全部候选)并恢复机器级安装兜底。③ 新增 **gitlint 提交信息门禁**:钩子定义数比 CI 报告条数多 **1**(当时 17/16,master 并入 `test-cppcheck` 后为 18/17),缺的正是 gitlint——其 `stages: [commit-msg]` 声明在**上游** `.pre-commit-hooks.yaml`(`--all-files` 跑不到,且表现为全绿 → 长期无人发现)→ **`scripts/ci_gitlint_range.ps1`** 逐条校验本次 push/PR 范围(消息文件须写在仓库内 + UTF-8 无 BOM)。④ `GITHUB_ENV/PATH/OUTPUT` 写入统一显式 `-Encoding ascii`(PS 5.1 `Out-File -Append` 默认 **UTF-16LE**,实测落盘 `42 00 42 00 42 00 3D 00 31 00`)。§5 清单 8→10 条、§6 排障表 +5 行、§7 维护项重写 | -| 2026-10-02 | **S3 + S14**:新增 §0.0「CI 不覆盖的体积门禁」醒目声明;新增 §4.4「产物存档与结果汇总」(零依赖 `Tee-Object` + `$GITHUB_STEP_SUMMARY` + `::notice::` 汇总行,不用 `actions/upload-artifact`;记录 `$ErrorActionPreference='Stop'` 与 `2>&1 \| Tee-Object` 的陷阱及处置)。§5 验证清单(7→8 条)与 §6 排障表同步更新 | -| 2026-10-02 | **workflow 接入 `DTU_*` 机器级变量**(`本地工具路径环境变量方案.md` 实施):`static-gates` 的 Python 探测改为 `DTU_PRECOMMIT_PYTHON`(显式,无效即硬失败)→ PATH → `.venv`(删除 `C:\ProgramData\anaconda3` 固定候选);cppcheck 改为 `DTU_CPPCHECK` 优先 → PATH(**移除 `C:\Program Files\Cppcheck` 固定回退**);`host-unit` 的 MSVC 探测改为 `DTU_MSVC_CL` 优先 → `%ProgramFiles*` 推导的标准根(与 `unit_test_harness.py` 同步,不再写死盘符);新增 §5.1.3 机器级变量设置方法(`Machine` scope + 重启任务)、§5.2 与 check_env 样例、排障表 cppcheck 行、TL;DR 5b 步骤。§5.1.1 的报错原文标注为历史记录 | -| 2026-10-02 | ✅ **首次 CI 全绿(run#8:静态门禁 + 主机侧纯逻辑单测双 job Success)**。定位并修复最后两个拦路虎:① **§5.1.1 用户态 site-packages 陷阱**——`pre-commit` 只装在 `%APPDATA%\Roaming\Python\...`(SYSTEM 不可见);且提权 `pip install --no-user` 会因 pip 扫**整个 `sys.path`**、见 user-site 已满足而**静默跳过**全局安装(9 依赖中唯 `cfgv` 因版本相同被跳过→`-s` 下 `ModuleNotFoundError`)。修法:提权 + `--force-reinstall --no-deps` 强制落全局,并以 `-s` 复验。② **§5.1.2 doc-links 假阳性**——文档引用了 gitignore 的运行时文件 `.dsh/skills/serial-assistant/scripts/state/meta.json`,本地存在、干净克隆无 → 按《文档规范》§3.3 加同状态词「运行时未创建」。排障表补 6 条(pre-commit 不可见 / GBK 中文 / pwsh / cppcheck / doc-links / MSVC 降级)。新增配套脚本 `install_precommit_global.ps1`、`install_precommit_global2.ps1`、`fix_cfgv_global.ps1` | -| 2026-10-02 | 🔴 **常驻方式重大修正(实测推翻)**:`Start-Service gitea-runner` 必然失败。经二进制逆向确认 `gitea-runner v4.0.1` **无任何服务管理代码**(命令集仅 `bug-report/cache-server/config/daemon/exec/register`,无 `service.go`;`OpenSCManagerW` 等符号来自 Docker SDK,非服务安装代码),`daemon` 是纯控制台程序、不向 SCM 回报 `SERVICE_RUNNING`。**§4 全节重写为「任务计划程序」方案**(新增 §4.0 根因分析、§4.2 `deploy_runner_task.ps1`、§4.3 手动命令 + 72h 超时警示、§4.5 清理遗留服务、§4.6 提权);删除失效的 `deploy_runner.ps1`/`install_service.ps1`;排障表补「错误 1053」「LastTaskResult 非 0」「72 小时被杀」3 条;拓扑图/§5.1/§7 日志/§10 TL;DR 同步更新。另修 `config.yaml` 的 `fetch_timeout` 5m→1m(超出 RPC 1m 会被截断并告警) | -| 2026-10-02 | **修 `.ps1` 编码坑(实测)**:无 BOM 的 UTF-8 脚本被 WinPS 5.1 按 GBK 解读 → 中文乱码(`鐒跺悗鎵ц`)并撞坏引号配对,报 `源文本中包含无法识别的标记`/`字符串缺少终止符`。**新增 §7.1「给含中文的 `.ps1` 加 UTF-8 BOM」**(两种修法 + 解析器校验命令);排障表补该条目;配套脚本已统一加 BOM | -| 2026-10-02 | **按实测修正为 v4.0.1**:act_runner 已更名 **`gitea-runner`**,发布页迁至 `gitea.com/gitea/runner`。**v4 移除 `daemon install/start/stop/status`**;**v4 `log` 段无 `file` 键**(§3 改用 `log.job.dir`);补 §1.3 命令集对照、§6.1 MySQL 直查核验、排障表(`accepts at most 0 arg(s)` / `unknown config key log.file` 等) | -| 2026-10-02 | 初版:针对**本机 Gitea 原生部署**(`D:\Docker\Gitea\gitea.exe` + Windows 服务 + `127.0.0.1:3001`)定制 Runner 端部署全流程。核心要点:`--instance` 用回环地址、`--labels "windows:host"` 必须精确匹配 `runs-on`、PATH 运行账户坑、MSVC 路径约束、内网 action 拉取的零依赖改法 | -| 2026-10-01 | **修正 `DEFAULT_ACTIONS_URL` 说明**(原 §1.2 示例误导):新增 §1.2.1 明确它控制的是 **action 下载源**(默认 `github.com`;`self` = 从自己实例拉且需先镜像 action),**不是填自己的 Gitea 地址**;§4.3 同步修正(原文误写"gitea.com 代理"),并补零依赖写法为内网首选。依据:Gitea 官方 FAQ + config-cheat-sheet | -| 2026-10-01 | 初版:Gitea Actions 配置全流程(服务端开关 / Windows runner 注册 / runner 软件环境 / workflow 位置与触发 / 内网 action 拉取 / 端到端验证清单 / 故障排查 / 日常维护) | +> (本文件不再记流水账:改了什么是正文说了算,改动过程查 git log。) \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index 752f7f08..8767928c 100644 --- a/docs/README.md +++ b/docs/README.md @@ -241,7 +241,7 @@ docs/ | 位置 | 内容 | |---|---| -| [`任务规划/`](任务规划/README.md) | **统一待办入口(7 个文件)**:`README.md` = 现在做什么与全项目顺序;`UI补齐.md` = 当前唯一执行清单;`登记簿.md` = 后续任务、外部窗口与长期观察;`数据可信.md` = 两项阻塞任务及代码引用的设计约束;`暂缓-RS485.md`、`测试与架构专项.md`、`屏板链路.md` = 三个专项。完成即删,重复内容只保留一个归属 | +| [`任务规划/`](任务规划/README.md) | **统一待办入口(6 个文件)**:`README.md` = 现在做什么与全项目顺序;`UI补齐.md` = 当前唯一执行清单;`登记簿.md` = 后续任务、外部窗口与长期观察;`数据可信.md` = 两项阻塞任务及代码引用的设计约束;`暂缓-RS485.md`、`屏板链路.md` = 两个专项(`测试与架构专项.md` 已删除 2026-10-28,未闭环约束并入 `暂缓-RS485.md`)。完成即删,重复内容只保留一个归属 | | `硬件平台/` | 网表详细分析报告与语义图(V0.0 / V0.1);**[`ADC通道映射说明.md`](硬件平台/ADC通道映射说明.md)——V0.1 十七路 ADC 语义/网名/通道号权威映射表(固件取数、UI 显示、自检注入以此为准)** | | `芯片手册/` | 外部芯片数据手册转录(CH395F / GD5F2GQ5UE / SD2506 / TPAFE5160 / RTL8305NBI 等) | | `images/` | 文档技术配图(`.svg` 产物,由 `tools/arch_diagram/`、`tools/refgraph/` 生成) | @@ -282,23 +282,4 @@ docs/ ## 12. 变更记录 -| 日期 | 变更 | 说明 | -|---|---|---| -| 2026-10-21 | 新增算法专题 | 新建 `docs/算法/采样有效性校验设计说明.md`(`App/algo/adc_health.c` 单文件深设计:四类判据推导、位语义与位号对齐、闭锁与兜底责任划分、盲区与验证分工),并在 `tools/arch_diagram/` 新增三个配图生成器与产物 SVG;本索引 §5.2 补登记,`docs/算法/采集与算法层设计说明.md` §4 与 §13 加指针 | -| 2026-10-14 | 网络文档合并 | 《网络Socket监听生命周期设计说明.md》(B10 根治,587 行)并入 [`网络/网络自愈架构设计.md`](网络/网络自愈架构设计.md):原理与规范层论证 → §1.1~§1.4、FUN_PARA bit3 契约 → §4.9、代码级事实清点 → §9、决策记录 → §10、`net_listener.c` 模块化边界 → §11,原「引用与归档约定」顺延为 §12;过程类内容(分阶段勾选清单、台架验收记录)不迁、留 git 历史;原文档删除。全库引用同步 13 处(`net_listener.c`/`.h` 注释、Net层阻塞模型、BSD_Socket_API 两篇、陷阱记录 B10、编号规范 §4.2/§5.2/§7.2);本索引 §5.1 补登记 | -| 2026-10-14 | E14"丢中断"复核与归因更正 | 48 轮直读 SINT 矩阵复核历史"丢中断"说法:**芯片侧事件丢失 = 0**("丢失"= drain 读清消费 3/48 + 门控竞态 2/48 + 主机同步 1/48,幽灵态 0/48 未复现);根除性修复 = listen/relisten 路径排事件挪至 LISTEN 命令**之前**(吞新会话 CONNECT 的生产侧自伤窗);全局读收口(全局寄存器唯一读者=`net_poll`,I7 护栏);全库 17 文件约 40 处"丢中断"归因更正为"事件未收到/读清消费竞态",`docs/网络/网络自愈架构设计.md` §5.2 新增 E14 锚点;台架保留复核探针(drain-int/SINT 补读×3/超时归类);同日 E15 幽灵态归因复核(官网+手册实锤:0x04+旧端口 = 芯片**如实报告**旧连接拆链进行中——bit3=1 保留现场为自家配置、拆链窗与 §5.17 重传默认值吻合、WCH 官方博客确认断连即重连被拒且官方方案 = 关闭完成后重开,即 settle 等待) | -| 2026-10-13 | 网络自愈架构文档瘦身与改名 | 合并文档 `网络/N34-自愈审计.md`(2062 行审计全记录)瘦身为**终版设计描述**(281 行:不变量 I1~I8 / 架构与机制详解 / 参数与 E 锚点速查 / 红线 / 延后项),并经 `rename_ref.py` 改名 [`网络/网络自愈架构设计.md`](网络/网络自愈架构设计.md)(全库 16 文件 30 处引用同步);审计过程(T1~T4、E0~E13)归档 git 历史,考古命令见该文档「引用与归档约定」 | -| 2026-10-13 | 网络自愈审计归档 | 原 `docs/网络/N34-自愈审计/` 目录 7 份文档(根因总览 / net 层盘点 / 驱动层审计 / 主流对照 / 汇总裁决 / 实施方案 / 实验方案)**合并为单文档 [`网络/网络自愈架构设计.md`](网络/网络自愈架构设计.md)**,原目录删除;全库引用同步(`docs/` 4 篇 + 驱动/网络代码注释 + 配图生成器与 SVG)。本索引 §5.1 补登记 | -| 2026-10-12 | 新增环境与部署 | 新建 `docs/环境与部署/并行任务工作树方案.md`(**多任务并行开发机制规格**:`git worktree` 隔离、目录与共享/独占分配、`task-worktree` / `@task` skill 设计、单写者文档与合并残留审计、台架锁;**已落地并端到端实测**);本索引 §9.2 补登记 | -| 2026-10-12 | 远程 CI 文档独立成目录 | 新建 `docs/CI/`:原散在 4 处的远程 CI 内容(`环境与部署/CI配置指南.md` 477 行 + `环境与部署/Gitea_Runner部署指南.md` 917 行 + `测试开发标准流程.md` §9 + `AGENTS.md` 提交门禁节 4 条,共约 2000 行)**合并为 `CI/远程CI完整指南.md` 一篇**,`CI/README.md` 作唯一入口;`AGENTS.md` 压成一行指针、测试流程 §9 只留覆盖边界与本地等价。动因:远程 CI **只跑在本机一台 runner**,与日常开发规范混在一起每次会话都被读,造成困惑 | -| 2026-10-11 | 功能 | N-19 FTP 鉴权:`/config.ini` 新增 `[ftp]` 段(`user` / `pwd_hash` = SHA-256(user‖password) / `write`)+ 恒定时间比较 + 连续 5 次失败锁 60 s + 未登录命令门;出厂默认 admin/admin,默认口令在用有启动告警。新增 `App/util/sha256.*`、`Drivers/BSP/NETCFG/ftp_cfg.*`、`Drivers/BSP/NET/lftpd/lftpd_auth.*`;主机侧单测 `test/host/sha256/`(13 例)+ `test/host/ftp_auth/`(36 例),pre-commit 钩子 26→28;台架脚本 `test/host/ftp_auth_bench.py`。文档同步:`docs/子系统设计/网络配置说明.md`、`docs/架构设计/STM32F4-Base存储架构说明.md`、`docs/代码规范/pre-commit使用说明.md`、`docs/产品需求/产品需求设计文档.md` | -| 2026-10-11 | 文档调整 | `AGENTS编写指南.md` 新建后**同日删除**(要点已沉淀入 `AGENTS.md` 宏观重构与本索引变更记录,指南类内容不单独成文);撤销 §1 目录树与 §7.1b 登记;同日 `AGENTS.md` 完成宏观重构(补项目概况/目录地图、平台约束分组、边界块) | -| 2026-10-10 | 新增子系统设计 | 新建 `docs/子系统设计/ADC采样节拍设计说明.md`(ADC 采集链路 1 kHz 硬件定时器触发的 CubeMX 配置规格与代码改造清单,B1 遗留项规划);本索引 §5.1 补登记 | -| 2026-10-10 | 新增算法专题 | 新建 `docs/算法/继电保护功能复现规划.md`(保护链路复现总规划);本索引 §1 目录树补 `算法/`、§5 拆为 5.1 功能子系统 / 5.2 算法专题并登记 `算法/` 两篇文档 | -| 2026-10-05 | 新增产品需求文档 | 新建 `docs/产品需求/产品需求设计文档.md`(面向产品的需求基线);本索引新增 §3 产品需求、§2 推荐阅读顺序置顶、§1 目录树补 `产品需求/`;后续章节号顺延(本文 §4 … 本文 §12) | -| 2026-09-25 | 目录重组 + 索引建立 | 顶层 16 篇散落 md 归入 5 个新目录(`架构设计/` `子系统设计/` `网络/` `审查记录/` `环境与部署/`);全仓库 90 处引用同步;新建本索引(D-5) | -| 2026-09-25 | D-6 目录去空格 | `docs/UI 设计/` → `docs/UI设计/`;全仓库 67 处引用同步(含 URL 编码形态 `UI%20设计`);命名约定写入 §10 | -| 2026-09-25 | D-7 文档-代码一致性门禁 | 新建 `scripts/check_doc_links.py`(链接存在性,含行内代码豁免/就近状态词/`[计划]` 标记)、`scripts/gen_task_table.py`(任务表由 `Src/freertos.c` 生成/校验,锚点 `TASK_TABLE:BEGIN/END`);接入 pre-commit `doc-links`/`task-table` 钩子;全库 66 文档 0 失效 | -| 2026-09-26 | D-7 体积档落地 | 新建 `scripts/check_mem_numbers.py`(内存/Flash 数字以 `.map` 为事实源,锚点 `MEM_SNAPSHOT:BEGIN/END` + 陈旧散句数字扫描);接入 pre-commit `mem-numbers` 钩子;上线即抓出 6 处真实失真(RW_IRAM1 82,048→87,040、ROM 249,432→262,660 等) | -| 2026-09-25 | 新建 `文档规范.md` | 正式确立文档体系规范(目录命名/编码换行/链接形态/门禁/结构/写作约定);补入本索引 §7.1b | -| 2026-10-04 | 待办文档合并 + 报告归档 | 4 份待办文档(`待处理内容.md` / `项目审计改进清单.md` / `下一步任务规划.md` / `测试与架构改进建议.md`)合并为**统一待办登记簿** `待处理内容.md`;《项目审查与优化建议报告》移入 `问题记录/`,删除 `审查记录/` 目录;全仓库引用同步(该报告 2026-10-25 已删除,内容并入登记簿与模块文档) | +> (本文件不再记流水账:改了什么是正文说了算,改动过程查 git log。) \ No newline at end of file diff --git a/docs/UI设计/RemoDispBus协议与接收设计说明.md b/docs/UI设计/RemoDispBus协议与接收设计说明.md index 2108f282..f24e5ec3 100644 --- a/docs/UI设计/RemoDispBus协议与接收设计说明.md +++ b/docs/UI设计/RemoDispBus协议与接收设计说明.md @@ -303,13 +303,3 @@ if (n > 0) { | UI 设计架构 | `docs/UI设计/UI_设计架构.md` | | LVGL 模拟器部署 | `docs/UI设计/LVGL模拟器部署与使用说明.md` | | CH395F 网络测试 | `docs/测试说明/CH395F_Test_Guide.md` | - ---- - -## 7. 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-09-10 | 创建:RemoDispBus 协议设计 + 模拟器逐字节状态机接收解析设计;补充 MCU 整块解析差异 | -| 2026-09-10 | 双端统一:MCU 与模拟器共用同一份 `ui_net_sink.c`(逐字节状态机);底层改用 `net_*` BSD API(新增 `net_socket_sim.c` Winsock 后端、`net_socket.h` 以 `NET_NO_OS` 剥离 FreeRTOS)+ `ui_net_sink_backend` 平台抽象;消除 MCU 整块解析脆弱性与最小帧长判据差异、修复单连接断线重连;`RM_RX_BUF` 1024→64 | -| 2026-09-11 | 目录整理:PC 平台实现移入 `simulator/sim/`(`net_socket_sim.c` / `ui_net_sink_backend_sim.c` / `net_cfg_store_sim.c` / `sim_port.c/h`),`Drivers/BSP/` 仅留 MCU 端实现;§1.2 帧结构重绘为标准两行框图(字段名 + 字节数) | diff --git a/docs/UI设计/UI_界面制作流程.md b/docs/UI设计/UI_界面制作流程.md index 5682c7dc..7de2b718 100644 --- a/docs/UI设计/UI_界面制作流程.md +++ b/docs/UI设计/UI_界面制作流程.md @@ -5,7 +5,7 @@ > **配套文档**:`UI_设计架构.md`(系统如何工作)、`菜单页面设计.md`(菜单/导航行为与数据流设计)、`LVGL模拟器部署与使用说明.md`(模拟器)、`UI_中文字体生成与配置.md`(字体生成)、`UI_自动化测试流程.md`(P2/P3 回归门禁的可执行版本:脚本 + 池水位常量 + 黄金参考更新)。 > **首个实例**:界面 01 主界面(根页),规格 `mockups/01_主界面_说明.md`(本文所有示例数字均取自该试点)。 -> **沿革**:旧管线含"HTML 样机"阶段(参考图 → HTML 样机 → 代码),2026-09-13 起移除——设计基准改为**文本规格(布局参数表)+ 参考图**,视觉基准改为**模拟器出图**,用户视觉确认点移到 P2 模拟器窗口/出图(详见变更记录)。 +> **沿革**:旧管线含"HTML 样机"阶段(参考图 → HTML 样机 → 代码),2026-09-13 起移除——设计基准改为**文本规格(布局参数表)+ 参考图**,视觉基准改为**模拟器出图**,用户视觉确认点移到 P2 模拟器窗口/出图(沿革细节查 `git log`,本节只写现状)。 --- @@ -21,7 +21,7 @@ flowchart TD P2 --> C2{"输出图 ↔ 参考图
同构?"} C2 -- "否: 按根因修正(修代码 / 回 P0 修规格)→ 再出图" --> P2 C2 -- "是(Gate: 导航符合按键语义 + 自动化回归 PASS)" --> P3["P3 MCU 验证
→ 日志 + 上机目检结论"] - P3 -- "Gate: @build 0 错 0 警 + @test PASS + 上机目检通过" --> P4(["P4 归档
→ 变更记录/台账 + 随代码提交(代码+字体+字集+规格+文档)"]) + P3 -- "Gate: @build 0 错 0 警 + @test PASS + 上机目检通过" --> P4(["P4 归档
→ 受影响章节现状化/台账 + 随代码提交(代码+字体+字集+规格+文档)"]) ``` > 小改动(文案/间距/纯交互/字体重生成)走「小改动快速通道」一节(见文末第十节),无需全流程。 @@ -34,7 +34,7 @@ flowchart TD | P1 规格→代码 | (可选)抽查代码 | 逐参数翻译、字体重生成、内存预算、双端注册 | 代码 + 字体 | | P2 模拟器 | **视觉确认**(窗口模式/出图),指出差异 | 构建、离线出图、出图与原图逐项比对、依规格改码 | 比对结论 | | P3 MCU | **真机目检**(DTU-RemoteLCD) | @build / @test 执行、日志解析 | 日志 + 结论 | -| P4 归档 | — | 更新变更记录与台账 | 文档 | +| P4 归档 | — | 把受影响章节改成改动后的现状 + 更新台账 | 文档 | > 用户视觉确认点由旧"浏览器打开 HTML 样机"改为 **P2 模拟器窗口/出图**:P0 确认**参数表**(数值层面),P2 确认**渲染结果**(视觉层面);渲染结果与意图不符时按 §5.1 根因修正(代码错 → 修代码;参数表错 → 回 P0 修规格再修代码)。 @@ -265,9 +265,7 @@ flowchart TD ## 七、P4:归档 -1. 更新 `docs/UI设计/UI_设计架构.md`: - - 变更记录(日期 + 一行) - - 受影响章节:文件地图 / 关键参数 / 菜单架构 / 键位语义 +1. 更新 `docs/UI设计/UI_设计架构.md`:只改**受影响章节**(文件地图 / 关键参数 / 菜单架构 / 键位语义),把它们写成改动后的现状;**不再记流水**(2026-10-28 裁定,`docs/文档规范.md` §5.1) 2. 设计规格 `NN_界面名_说明.md` **保留**于 `mockups/`(定稿版 = 设计档案,后续改界面须先改规格再改代码) 3. 台账:该界面状态 → 已完成(日期) 4. 提交检查:代码 + 字体(`ui_font_cn_12.c`)+ `ui_cn_chars.txt` + 规格 + 文档 一起进 git @@ -389,29 +387,6 @@ P2 [ ] 模拟器构建 0 错误 P3 [ ] @build 0 错 0 警 [ ] @test PASS(Required:____ / Forbidden:FAIL;ERROR;HardFault) [ ] 真机目检通过 -P4 [ ] UI_设计架构.md 变更记录更新 +P4 [ ] UI_设计架构.md 受影响章节已改成现状(不记流水) [ ] 台账状态 → 已完成(代码+字体+字符集+规格+文档 一并提交) ``` - ---- - -## 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-09-03 | 初始版本:基于 01 主界面试点(P0/P1 已执行)沉淀全流程规范 | -| 2026-09-03 | P3 增加"离线出图比对":模拟器 `--screenshot` 出图 + `simulator/i1_to_png.py` 转 PNG,与样机渲染图(render_NN.png)逐项比对,不合适则依 HTML 改 LVGL 代码再出图,循环至一致 | -| 2026-09-03 | 字体 ▶(U+25B6)箭头:宋体无此字形 → 从 Segoe UI Symbol 提取位图合并入 `ui_font_cn_12.c`;`make_font.py` 内置 `merge_arrow_glyph()` 幂等自动补回,重生成字体后箭头不丢 | -| 2026-09-03 | 顶部"开口浅 V"装饰两腿不渲染:根因 `simulator/lv_conf.h` 设 `LV_DRAW_SW_COMPLEX 0`(省代码)→ `lv_line` 斜段被跳过。改为两端显式 `LV_DRAW_SW_COMPLEX 1` + `LV_DRAW_SW_CIRCLE_CACHE_SIZE 4`;三图(原图/HTML/截图)顶部装饰现已一致 | -| 2026-09-03 | 顶部"开口浅 V"两腿偏细(1bpp 斜线边缘被阈值吃掉):`ui_menu.c` 装饰拆 3 段 `lv_line`,两腿加粗 `MENU_DECO_LEG_W`=3、水平线 `MENU_DECO_HORIZ_W`=2(`deco_line_apply` 统一样式),三图腿粗现已一致(约 2~3px) | -| 2026-09-03 | §一 流程总览重画为清晰的纵向管线图:每阶段标注 产物 + Gate,P1/P3 的"比对→修正"迭代环显式标出(⟲);补全原先遗漏的 P1 原图校验环/`NN_说明.md` 产物、P2 双端注册、P3 导航 Gate,与各阶段细则(§3~§8)对齐 | -| 2026-09-04 | §九 新增 9.1"样机投入分流(按屏型)":明确 HTML 样机=静态外观轴(设计先行、非代码生成器),设计文档 + 模拟器=行为/数据轴;静态内容页走完整样机管线、导航/交互重屏 HTML 只做静态首帧、行为靠 `菜单页面设计.md`;配套文档补列 `菜单页面设计.md` | -| 2026-09-07 | §一 五阶段管线图由 ASCII 转 Mermaid flowchart:P1/P3"比对→修正"迭代环由行内 ⟲ 注记改为显式判定节点 + 回边(未收敛不得前进更直观);各 Gate 条件与产物标注保留、语义不变 | -| 2026-09-09 | 内容页三屏(装置信息/交流量/直流量,`ui_content_page`)落地后回填:C3 字符集 78→97 汉字(193 字形);§十 新增两坑——UI BOM 源文件 `snprintf` 中文格式串触发 C4819(改 `lv_snprintf`)、常驻动态样式池永久占用(改 `LV_STYLE_CONST_INIT` 常量样式,x64 实测省 88 B/个) | -| 2026-09-09 | 用户密钥密码页落地后回填:C3 字符集 97→102 汉字(198 字形,补"本/用/户/密/钥");新文案走 P4 字体重生成 + `check_content_pages.py` 新增密码页 4 状态黄金参考 | -| 2026-09-10 | 网口设置内容页落地后回填:C3 字符集 102→111 字符(208 字形,补网口设置/地址/掩码等,并修复 `lv_font_conv` 丢弃的低码位符号 U+FF0C 全角逗号 → 页脚逗号不再空白);新文案走 P4 字体重生成 + `check_content_pages.py` 新增网口设置 4 状态黄金参考(可编辑/只读/编辑光标反显/保存 OK);模拟器 `main` 调 `net_cfg_load` 使参考图显示工厂默认值 | -| 2026-09-13 | 移除 HTML 样机阶段:五阶段 → **四阶段管线**(P0 需求录入+设计规格 / P1 规格→代码 / P2 模拟器 / P3 MCU / P4 归档);设计基准改为"规格布局参数表 + 参考图",P2 比对基准由"样机渲染图"改为"参考图 + 规格参数表"(根因分流:修代码 / 回 P0 修规格);用户视觉确认点由 HTML 浏览器移到 P2 模拟器窗口/出图;删除 `mockups/01_主界面.html`、`render_01.png`、`tools/ui_mock/render_mockup.py`(**均已删除**),保留 `NN_说明.md` 规格与原始参考图;`NN_说明.md` 升格为唯一设计基准(P1 照参数表翻译代码,P2 出图对照参数表 + 原图);`UI_自动化测试流程.md` 门禁编号同步改为 P2/P3 | -| 2026-09-14 | 运行记录/自检记录页 + 待机屏落地后回填:C3 字符集 111→122 字(217 字形,补输/入/错/误/上/电/重/芯/片/异/常——**故障描述串在非 UI 源码中 extract_cn 扫不到,须手动补字**);新文案走 P4 字体重生成 + `check_content_pages.py` pwc 态参考更新(密码错误提示);池基线 4784→5440 / 往返 4864→5520(+656B = 待机模块常驻屏+容器,见两测试脚本头部注记) | -| 2026-10-25 | 字库扩充(页面扩充规划预置字):C3 字符集 122→179 字(217→274 字形;上次入表后 2026-10-15 字体瘦身实测 119 字/214 字形未回填本表,本次一并校正)。+60 字取自 `docs/UI设计/页面补齐规划.md`、`docs/UI设计/页面扩充详细方案.md` 的页面显示串(段/投/延/零/频/荷/闸/跳/低/过/Ⅰ/Ⅱ/Ⅲ 等 + 年/月/分/秒/分合/已请求/确认/取消/越界用字);源码未用期间 font-charset 记 [WARN] 属预期,批 2 页面接线后自然转"在用"。顺带修复 `make_font.py` 两处缺陷:补回字形 cmap 条目被宽稀疏 range 吞掉(Ⅰ 下探起点 0x2160 → ▶ 全变方框,A/B 同树实测)与 `verify_coverage()` 非首命中判定;菜单 8 状态 + 内容页 11 页黄金参考逐字节不变;ROM +1,528 B、RAM 0。详见 `docs/UI设计/UI_中文字体生成与配置.md` §4 与文末事故记录 | -| 2026-10-28 | UI 补齐批接线(单写者):记录 5 页 + 运行报告六叶在 `ui_menu_tree.txt` 加 ` #page=` 并重跑 `tools/menu_gen/gen_menu.py`(绑定叶 22→28、`UI_PAGE_MAP_COUNT` 22→28,节点 42 / 叶 33 不变)、6 个页面 `.c` 双端注册;C3 字库链重跑 185→218 字(280→313 字形,新增 33 字取自六页新文案(含运行报告补「计数可信」行用的「可」字);本行旧数 183/278 系 2026-10-26 之后未回填,改前实测 185 字/280 字形);`check_content_pages.py` 内容页黄金 53→59 页;ROM/RAM 增量待 Lead `@build` 后按 `.map` 实测回填 | -| 2026-10-28 | **复扫认错 + 当前态改报「张」**:上一行的「内容页黄金 53→59」按**页面个数**口径写,与本仓判据本体不同源——判据 = `simulator/tests/ref/` 入库 `shot_*.bin` 实数 **60** = `check_content_pages.py` 的 `PAGES` **60** 项(两源一致、id 逐一对齐),53 → 60 = **+7 张**(记录 5 页 + 运行报告 2 张:超屏那一页的第 2 屏单独拍一张)。上一行原文**冻结不回改**;本文件当前态此后一律报「60 张黄金参考」,「页」只指内容页/菜单屏本身。全仓口径更正见 docs/门禁说明/ui-golden.md 同日行。 | diff --git a/docs/UI设计/UI_自动化测试流程.md b/docs/UI设计/UI_自动化测试流程.md index 64d0b02f..24228e3b 100644 --- a/docs/UI设计/UI_自动化测试流程.md +++ b/docs/UI设计/UI_自动化测试流程.md @@ -56,7 +56,7 @@ cmake --build simulator/build --config Debug # 0) 构建模拟器(须 0 警 > 且一次性残留仍是 80 B(5448 − 5368)→ 泄漏特征未变,只是 `lv_theme_apply` 不再为已不存在的控件类登记样式条目。 **漂移处理**:菜单/页面结构或样式变更导致门禁失败时,先确认新值合理(残留分解见 -`菜单页面设计.md` §9.5),再更新脚本常量并在本文变更记录登记。**禁止为过门禁盲目改常量**—— +`菜单页面设计.md` §9.5),再更新脚本常量,并在上面的常量表里把当前值与它的实测来源写清(改了什么是正文说了算,过程查 `git log`)。**禁止为过门禁盲目改常量**—— 无法解释的漂移 = 内存回归 bug。 ## 四、黄金参考(入库)与目检 PNG(本地产物) @@ -204,27 +204,4 @@ cmake --build simulator/build --config Debug # 0) 构建模拟器(须 0 警 --- ## 变更记录 -| 日期 | 变更 | -|---|---| -| 2026-09-09 | Python 解释器统一为仓库 `.venv`(新增 `requirements.txt`,`.gitignore` 忽略 `.venv/`);§1/§2/§4 命令同步改用 `.venv\Scripts\python.exe` | -| 2026-09-09 | 初版:菜单 8 状态像素回归 + 内容页黄金参考回归(ref/ 3 图,I1 原始位图入库)+ 池水位门禁(4784/4864 B)。脚本自会话临时目录整理入 `simulator/tests/`(相对路径定位 exe、输出改临时目录),替代每次重写 | -| 2026-09-10 | `check_content_pages.py` 新增**文本级断言层**(字形模板匹配 50 条,独立于 `ref/`,先于像素比对运行、失败即中止防误刷参考);内容页扩至 11 页(+网口设置 4 态);§二/§四同步 | -| 2026-09-10 | 新增 `simulator/tests/regen_ref_png.py`(由 `ref/*.bin` 批量重生成目检 PNG,默认 `--scale 6 --invert`);`ref/*.png` 加入 `.gitignore`(本地调试产物不入库);§四 补"重生成目检 PNG"步骤(修复"刷了 `.bin` 参考但 `.png` 仍是旧渲染 → 看似乱码") | -| 2026-09-10 | `simulator/tests/ref/` **整目录不入库**(`.bin` 黄金参考 + `.png` 目检图均为本地生成物):`git rm --cached` 原有 3 个 `.bin`,`.gitignore` 改为忽略整目录;首次/换机后先 `--update` 生成参考;`--update` 先跑文本断言防误刷;§四 重写 | -| 2026-09-13 | 管线同步:`UI_界面制作流程.md` 移除 HTML 样机阶段(五阶段 → 四阶段 P0~P4),本文定位改为"P2/P3 门禁的可执行版本";§六 关系描述更新为 P0 规格 → P1 编码 → P2 本文回归 → P3 上机目检 → P4 归档;移除 `tools/ui_mock/` 引用 | -| 2026-10-11 | **裁剪 LVGL 死代码(F-1/F-2/F-3)时的门禁记录**:先用**未裁剪**配置 `--update` 生成 11 页黄金参考,再切到裁剪配置重编重跑 → **逐字节全部一致**(菜单 8 状态像素一致),证明裁剪零视觉影响。池水位门禁随之 5440/5520 → **5368/5448**(−72 B;一次性残留仍 80 B,故非泄漏变化,见 §三 水位历史)。顺带揪出并修掉 `Lib/lv_conf.h` 与 `simulator/lv_conf.h` 的**长期漂移**(模拟器早已 I1-only、MCU 端未裁)→ 规则见 `UI_设计架构.md` §1.4 第 10 条,量化见 `../内存管理/RAM使用分析与优化方案.md` §2.6.4 | -| 2026-10-15 | **回归改为自洽运行(修 `netcfg_save` 假失败)**:`check_menu_rows.py` / `check_content_pages.py` 一律以**空临时目录当工作目录**跑 `lvgl_sim`(模拟器按 CWD 读写 `sim_config.ini`,残留档会改变页面内容);`simulator/main.c` 的 `--cfgtest` 加外壳,**无论成败一律删除伪造的 4000 B 配置档**——旧行为连 PASS 路径也会留雷,之后每次 UI 回归的保存行都从 `OK` 变 `ERR`(引擎拒写超长文档,属正确行为)。脚本里"删 `sim_netcfg.bin` 残留"的旧兼容清理随之作废(旧档迁移 2026-10-10 已删),改为**只提示不删除**。修后 11 页 + 往返池水位 5,448 B 全过,**未刷任何黄金参考**;排查口径见 §五 | -| 2026-10-25 | 第七节同日修订:`--walk` 的存证默认落 `ci-artifacts/uinav/walk/`(第一版写进 - `scripts/walk/`,污染工作树);路径落在版本控制内直接拒绝;`--board` / `--walk` 需显式 - `--i-hold-bench-lock`(实测过一次未持锁就注入按键,故把确认做成参数而非文字纪律)| -| 2026-10-25 | 新增第七节「板端有状态导航判据」(`scripts/board_ui_nav.py`):真机侧闭环导航、 - 盲走 9 帧仅 3 帧名副其实的实测表、认屏三判据、`uinav-selftest` 钩子档位、四条已知限度与 - 过密码口径;三张证据 PNG 落 `boot_log_data/` | -| 2026-10-22 | **`ref/*.bin` 像素黄金参考改为入库**(撤销 2026-09-10 的"整目录不入库"):`.gitignore` 由忽略整目录收窄为只忽略 `ref/*.png`。动因是这条门禁不可移植——新克隆/新工作树里基准必然缺失,`ui-golden` 报「缺黄金参考」而不是回归结论;本仓实测两次同类踩坑(并行工作树里第一次跑必失败,只能现场 `--update` 造基准,而"现场造的基准"恰好失去意义)。入库前做了可复现性验证:主树(`ref/` 生成于 2026-10-11)与新工作树各自独立构建 `lvgl_sim`,11 个 `.bin` SHA-256 全部一致。§四 与"何时不该更新"随之改写:`--update` = 改基准,会进 `git diff`,须逐页过目并在提交正文说明 | -| 2026-10-27 | 内容页黄金参考 **40 → 47 页**(遥测死区与系数 2 页落地,`simulator/tests/ref/` 实测 47 张:7 张新增、存量 40 张逐字节零漂移);本文件的当前态计数同步改 47,历史行 27 → 40 原样保留 | -| 2026-10-27 | 内容页黄金参考 **47 → 53 页**(通讯设置页落地并绑 `#page=comm`;判据 = `simulator/tests/ref/` 入库 `shot_*.bin` 实数 53 张,`git diff --name-status 31ca4a1f HEAD -- simulator/tests/ref` 实测只有 6 个 `A`、零 `M` ⇒ 存量 47 张逐字节零漂移);本文件的当前态计数已同步 | -| 2026-10-26 | **内容页页数口径统一为 27**:正文里残留的「11 页 / 其余 10 页 / 18 张」按现状改正(判据本体 = `simulator/tests/ref/shot_*.bin` 入库实数 27 个、`check_content_pages.py` 的 `PAGES` 27 项,含整定 9 态);下方变更记录里的「11 页」是当时事实,按历史冻结不动。同类陈述同步在 `测试开发标准流程.md`、`自动化测试流程.md`、`主机单测覆盖率口径.md`、`内容页架构.md`、`simulator/tests/README.md`、`scripts/board_ui_nav.py` 改正 | -| 2026-10-26 | **文本级断言规模口径修正**:门禁表里的「50 条」是 2026-09-10 首版数字,现值 **242 条 / 覆盖 27 页中的 24 页**(`pwd` `pwe` `pwc` 三张密码态只进像素比对、未登记文本断言);正文的文本层说明补写了覆盖面与这条盲区。下方变更记录里的 50 条属历史,不动 | -| 2026-10-26 | **内容页黄金参考下限 27 → 40 页**(UI 三页落地,机器实测:`simulator/tests/ref/` 入库 `shot_*.bin` 40 个、`check_content_pages.py` 的 `PAGES` 40 项);文本断言随之 **242 → 310 条**、覆盖 **40 页中的 37 页**(`pwd` `pwe` `pwc` 三张密码态仍只进像素比对、无文本断言);27 张旧参考逐字节未变,往返池 5448 B 与菜单常驻堆 5368 B 均未变,字库仍 183 字。本文其余各处与 `AGENTS.md`、`docs/门禁说明/`、`simulator/tests/README.md`、`docs/测试说明/` 三篇同批改齐;**历史行里的 27 / 11 一律保留**(当时下限就是那个数,不改数造连续性)| -| 2026-10-28 | **内容页黄金参考 53 → 60 页**(UI 补齐收口批接线:记录 5 页 accident / oper / alarm / start / yk 与运行报告 runreport 两页,运行报告 13 行分 2 页故第 2 页单独拍一张 `shot_runreport_p2.bin` 钉「第 2 页,共 2 页」与 104 三枚计数,所以是 60 而非 59)。判据实测:`simulator/tests/ref/` 60 张 `shot_*.bin`、`git status --porcelain` 恰好 7 个 `??`、`git diff --name-only -- simulator/tests/ref` 为空 ⇒ **存量 53 张逐字节零漂移**(本批字库两轮共 +33 字、185→218 字 / 280→313 字形均未动既有字形,跑 `--update` 前后各测一次);文本断言 **425 正向 + 36 反向**、覆盖 60 页中的 57 页;`MENU_POOL_BASELINE` 5368 / `POOL_AFTER_ROUNDTRIP` 5448 **一字未动**(往返实测仍 5448 B) | -| 2026-10-28 | `check_content_pages.py` 新增 **`FRESH_CWD`**(记录 5 页各在**独立空目录**里跑,其余 55 页环境不变):模拟器把「人工操作留痕」当真记录写**当前工作目录**的 `sim_oper.log`(`simulator/main.c` 的 `sim_post_oper` → `syslog_post(SYSLOG_OPER, ...)`),60 页共用一个 tmp 时 `clock_save` / `netcfg_save` / `sparam_save` 已写满 3 条(192 B)→ **操作记录页拍不到空态**。这不是判据问题而是环境被前面的写路径污染,故隔离环境、不改页面也不改断言。反向断言同时补两组互钉:运行报告第 1 页不许出现「发送帧数」、第 2 页不许出现「上电次数」;五个记录页不许出现 SOE 假记录的时标串 | +> (本文件不再记流水账:改了什么是正文说了算,改动过程查 git log。) \ No newline at end of file diff --git a/docs/UI设计/UI_设计架构.md b/docs/UI设计/UI_设计架构.md index 0703fb3b..4ebb7d67 100644 --- a/docs/UI设计/UI_设计架构.md +++ b/docs/UI设计/UI_设计架构.md @@ -291,23 +291,4 @@ ENTER/→ 进子框: ## 六、变更记录(简表) -| 日期 | 变更 | -|---|---| -| 2026-08-30 | LVGL v9.3.0 入库;初始 UI(ui_port / ui_menu / ui_net_sink / ui_task);开启 192K 全部 RAM | -| 2026-08-31 | 推流/按键链路打通;移除 LVGL 未用 demos/tests;搭建 PC 模拟器(CMake + SDL2) | -| 2026-09-01 | 代码规范钩子落地,UI 代码随全库规范修复 | -| 2026-09-02 | 菜单重构:弃用 lv_menu → 基元控件页面导航(§4/§5);字体 83→78 字(补「返/回」);修复模拟器主循环吞事件致键盘失效(§5.7);修复选中行白底白字(§5.5) | -| 2026-09-03 | 关键约束 7:`LV_DRAW_SW_COMPLEX` 须=1(顶部"浅 V"斜线依赖);两端 lv_conf 显式固化,`LV_DRAW_SW_CIRCLE_CACHE_SIZE`=4 防零长数组 | -| 2026-09-04 | 菜单重构为"横向级联框"模型(见 `菜单页面设计.md` §四⑧):数据/显示/逻辑三层拆分(新增 `ui_menu_view` 显示层、`ui_menu_tab` 生成物,`ui_menu` 瘦身为纯状态机);字体重生成补缺字形(78 字,含菜单树新增的整/控/软/板等);模拟器加 `--keys ` 无头注键截图验证 | -| 2026-09-08 | 菜单 RAM 收敛两连:行对象→框体自绘(行降为数据,§4.4/§5.5);4 层容器→单一持久容器(焦点恒在其上,框深度由逻辑层 `s_depth` 决定,§4.3/§5.4)+ 根框装饰/状态行容器自绘(无对象);LVGL 池实测 根框 4872 B / 最深四级级联 6128 B | -| 2026-09-09 | 内容页模块 `ui_content_page`(§4.7):装置信息/交流量/直流量三叶子页,独立屏按需建毁 + 行自绘;flat 样式改常量样式(`LV_STYLE_CONST_INIT`,零池分配,§5.6);字体 78→97 汉字(193 字形) | -| 2026-09-09 | 菜单显示层 flat 样式同法转常量样式(§5.6):LVGL 池基线 4872→4784 B、最深四级级联 6128→6040 B(x64 省 88 B,MCU 同量级);`LV_STYLE_CONST_INIT` 生成外部链接符号,内容页同名者改名 `cp_style_flat` 避免两文件冲突 | -| 2026-09-09 | 内容页多页面架构定稿(`内容页架构.md`):框架+页面插件模型(每页一文件 `ui_page_xxx` + 4 个扩展钩子)、30 个待实现叶子页清单、新增页面六步流程;同日"浅 V"装饰提取为共享 `ui_deco` 模块(架构第一步,菜单根框/内容页共用,像素回归验证一致) | -| 2026-09-09 | 内容页拆分执行(`内容页架构.md` §九 变更记录):`ui_content_page` 提纯为纯框架(描述符表 + NULL 防护 + 描述符驱动绘制/按键、4 个扩展钩子);三页数据拆出 `ui_page_device_info` / `ui_page_ac` / `ui_page_dc`(extern const 描述符对象);双端注册;Keil 0 错 0 警 + 模拟器 0 警告 + `ui-verify` 五门禁全绿(像素一致、池 4784/4864 B 不变) | -| 2026-09-09 | 用户密钥密码页落地(首个表单/操作页,§4.7 / `内容页架构.md` §4.1):框架描述符新增 title_y/hide_deco/hide_footer/key_intercept + 新 API `ui_content_page_invalidate`;新模块 `ui_page_password`(3 数字框反显光标 + arm API);菜单受保护叶子路由(arm→开密码页,确认一致后回调**先关页再续做进入动作**);字体 97→102 汉字(198 字形);双端注册;回归扩至 7 页 + 往返水位,五门禁全绿 | -| 2026-09-10 | 网口设置内容页(§4.7 / `内容页架构.md`):新增 `Drivers/BSP/NETCFG`(Flash 持久化 + CRC-16,工厂默认 192.168.1.100/24)+ 页面插件 `ui_page_net_cfg`(5 行动态值 + 可编辑:↑↓调字节/←→移光标/ENTER 确认,保存行 ENTER → `net_cfg_save` 下次上电生效);框架新增钩子 `init_cb` + API `ui_content_page_selected_row`;`net_init` 增 `mac` 参数、netTask 等 `SYS_EVT_STORAGE_READY` → `net_cfg_load` → `net_init(ip,mask,gw,mac)` → 回写实际 MAC 影子;字体 102→111 字符(208 字形,修复低码位符号丢失);双端注册;回归扩至 11 页,五门禁全绿 | -| 2026-09-14 | 运行记录/自检记录内容页 + 待机显示模块:新增 `App/log/sys_log`(定长 64B 文本记录引擎,MCU 落 NAND `/log/run.log`、`/log/selftest.log`,FTP 可直下)+ 页面插件 `ui_page_runlog` / `ui_page_selftest`(动态列表:count_cb + refresh,每条 2 行时间戳/描述)+ `ui_standby`(空闲超时自动切待机屏,仅确认键回菜单);密码页错误提示"密码输入错误"+清空重输;字体 111→122 字(217 字形);详见 `docs/子系统设计/运行与自检记录设计说明.md` | -| 2026-10-25 | **F3 推流心跳边界(§5.8)**:`ui_net_sink_set_beat_cb()` 回调注入,accept/recv_nb/send/close/重建三件套返回处喂 UI 心跳(2026-10-25 大窗 bit4 8 连击实证:单轮多慢往返之和串成 800ms 缺席);往返语义不改(上界归 E-27/E-28);未注册 = 零行为变化(模拟器/黄金回归形态);新增 `test/host/ui_sink/` 主机套件 17 断言 | -| 2026-10-25 | 字库扩充(页面扩充规划预置字 +60,含罗马数字 Ⅰ/Ⅱ/Ⅲ):默认字体升至 179 字符/274 字形,像素基线不变,ROM +1,528 B、RAM 0;修复生成器 `make_font.py` 的 cmap 插入顺序缺陷——LVGL `get_glyph_dsc_id()` 线性扫描首个包含即返回,补回字形(▶)单码位条目被下探后的宽稀疏 range 吞掉即全渲染方框,现按首命中语义插位/守卫/校验(详见 `docs/UI设计/UI_中文字体生成与配置.md` 文末事故记录) | -| 2026-10-28 | UI 补齐批接线(单写者):事故/操作/保护告警/保护启动/遥控/运行报告六叶绑定内容页(生成物 `UI_PAGE_MAP_COUNT` 22→28,节点 42 / 叶 33 不变)+ 6 个页面 `.c` 双端注册;默认字体 185 字符/280 字形 → 218 字符/313 字形(+33 字,§1 概况表"默认字体"行同步,旧数 183/278 系未回填);内容页像素黄金参考 53 → 59 页;ROM/RAM 增量待 `@build` 后按 `.map` 实测回填 | -| 2026-10-28 | **全仓计数复扫(三数双源互证 + 口径更正)**:① `simulator/tests/ref/` 入库 `shot_*.bin` 实数 **60** = `check_content_pages.py` 的 `PAGES` 条目数 **60**(两源一致;其中 2 张是分页页多拍的第 2 页,所以**张数比页面个数多**。上一行「53 → 59 页」按**页面个数**口径、同日 `docs/门禁说明/ui-golden.md`「53 → 60」按**入库张数**口径——两个数各自成立,但**不许互相冒充**;本仓判据本体 = 入库张数,当前态一律报 **60 张**。② 已绑内容页 **28 叶**(生成物 `UI_PAGE_MAP_COUNT` = `ui_menu_tree.txt` 剔掉文件头注释示例行后的 `#page=` 实数 28;不剔是 29)/ 未绑 **5 叶** = 遥信类型 + 遥信防抖 + 双点遥信 + 手动录波 + SNTP 设置,与分类表逐项闭合。③ 中文字体 **218 唯一字 / 313 字形**:`ui_cn_chars.txt` 唯一码点 218(ASCII 区 **0** 个,ASCII 由生成器子集参数另打进去、不计入字数);`ui_font_cn_12.c` 的 `.bitmap_index` 条目 **314 条含 notdef** → 字形 = 314 − 1 = 313 = 218 + ASCII 95。④ 本次另笔补的漏改当前态:运行与自检记录设计说明 §2.1(122 字→218)、LVGL模拟器部署与使用说明 §6.2 与 Q4(83 / 186→218 / 313)、lvgl-simulator skill 正文(53 页→60 页);页面扩充详细方案 §1.1 的「已绑 6 叶」按立项快照冻结、只加现值指针 | +> (本文件不再记流水账:改了什么是正文说了算,改动过程查 git log。) \ No newline at end of file diff --git a/docs/UI设计/菜单页面设计.md b/docs/UI设计/菜单页面设计.md index 97442903..5c7c014e 100644 --- a/docs/UI设计/菜单页面设计.md +++ b/docs/UI设计/菜单页面设计.md @@ -869,42 +869,3 @@ bool ui_content_page_is_open(void); /* 查询是否有内容页 - +72 B:`lv_screen_load()` 内部对菜单屏执行 `lv_obj_set_pos(act_scr,0,0)` → 局部 X/Y 样式各分配一个零初始化 `lv_style_t`+属性数组;每屏一次性,随菜单屏销毁才释放 **常驻样式零池占用**:flat 样式用常量样式(`LV_STYLE_CONST_INIT` + `lv_style_const_prop_t[]`,属性存 Flash)。动态 `lv_style_t` 首次 set_prop 会从池分配 `values_and_props` 且永不释放(x64 实测 88 B/个)——常驻样式禁用动态初始化(见 `UI_设计架构.md` §5.6)。 - ---- - -## 十、变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-09-03 | 初始版本:依据用户 7 屏主菜单截图定义完整 4 级逻辑层级(42 节点)+ 导航逻辑 + 与现有 `g_menu_tab` 差异对照 | -| 2026-09-03 | 按范围调整:移除"内容页类型"相关内容,聚焦菜单层级(节点/父子/层级/导航);新增 `子项数` 列;标注"查看"子项为推测待确认 | -| 2026-09-03 | **查看(#12)子项经用户确认**与"整定"同构(参数/定值/控制字/软压板),由推测转为正式定义,移除全部 ⚠ 标记与待确认节 | -| 2026-09-03 | 新增 §六"菜单树数据结构":选型扁平"父子索引表"(邻接表/关系表模型,对比指针树/首子-兄弟/堆式),给出 `ui_menu_node_t` + 完整 42 节点表 + 导航 API(`menu_get_children`/`menu_has_children`/`menu_get_name`)+ 启动自检 + 声明式生成器 + 与现有 `g_menu_tab` 迁移映射 | -| 2026-09-03 | **声明式生成器落地**(§6.6 由"可选"转"已实现"):新增 `ui_menu_tree.txt`(缩进即层级源)+ `tools/menu_gen/gen_menu.py`(同 `make_font.py` 模式),生成 `Drivers/BSP/UI/ui_menu_tab.c/.h`(42 节点:9 菜单 + 33 叶子,最深 三级菜单);已跑通并校验 parent 下标/连通性/子项数全部正确 | -| 2026-09-04 | §四 新增"**导航走查**":用真实 `g_menu_tab` 下标逐步演示"移/进/退"如何由 `parent==当前节点` 一次过滤驱动(当前页=过滤、进=压页/终点、退=弹页、导航态=当前节点链),并修正根页模型为"主界面 node 0 的子项"(§6.2/6.7 同步,去掉"虚拟根页"表述) | -| 2026-09-04 | 新增 §七"导航运行时数据结构(完整清单)":静态层(`g_menu_tab` 只读)+ 运行时层(导航历史 `s_path`+`s_sel`+`s_depth`=13 B、持久容器 `s_cont[4]`、单套活跃行 `s_row*[]`、页头/装饰、样式);"存 vs 算"区分、操作×字段读写表、内存预算、与现有 `s_pages[4]` 收敛对照 | -| 2026-09-04 | 改名 `menu_is_menu` → `menu_has_children`(原名"menu 是不是 menu"含糊;新名=该节点有无子项);§四 路径/代码映射由旧 `s_pages[]` 统一为 §七 的 `s_path[]`/`s_depth`/`s_sel[]`/`s_row*[]` 模型,消除 §四/§七 不一致 | -| 2026-09-04 | 改名 `menu_children` → `menu_get_children`、`menu_name` → `menu_get_name`(裸名词改"动词+对象",API 统一 `has_`/`get_` 风格);§6.4 建页片段改用 `s_path`/`s_depth`/`s_cont` 现算模型(条目不落地) | -| 2026-09-04 | §6.4 补"签名约定"说明:`node`/`out` 取 `uint16_t` 因与 `parent`(须装 `0xFFFF` 根哨兵)同域、**非容量所需**(42 下标 8 位够);`max`=出参缓冲容量(防越界 + 对齐单页行数,今日 9≤16 不触发截断) | -| 2026-09-04 | **索引位宽 16→8 位**:`MENU_ROOT` 由 `0xFFFF` 降为 `0xFF`,`parent`/`node`/`out`/`s_path[]` 均改 `uint8_t`(菜单上限 255 项,远够);路径历史 13→9 B、省 ~20 B RAM,Flash 不变(结构体因指针仍 8 B/项);双护栏=生成器 `节点数>255 报错` + 头文件 C99 断言 `menu_tab_count_check`。生成器已改并重生成 `ui_menu_tab.c/.h`,MSVC /W4 编译 + 导航测试(根 7 / 整定 4 / 查看 4 / 记录查询 9)通过;同步 §四/§6.2/§6.4/§6.5/§七。取代上一条"签名约定(uint16_t)"决定 | -| 2026-09-04 | 修正 §四"进入/返回示例":返回行节点顺序原与进入行相反(参数在左)致 `←` 被读成"前进"方向;改为与进入行**同序**(主界面 在左…参数 三级菜单在右)+ `←`,并补"怎么读"注(`→`/`←` = 进/退动作方向;返回 = 从最右 参数(三级菜单) 沿 `←` 一级级退回最左 主界面) | -| 2026-09-04 | **子页面显示模型定稿(横向级联子框)**:§四 新增 ⑧"显示模型"——横向树,每级一框在上一级**右侧**、顶边对齐上级"选中行"行顶;水平**右锚定**(最深框钉右缘、父框超宽滚出左、行按屏上/外建毁)+ 框宽文字自适应 + **无动画**;垂直每框独立(顶边=上级选中行行顶、框高按内容、**仅底边>160 才上移**贴屏底、比整屏高则 `↑`/`↓` 滚);焦点=最右框(`↑`/`↓` 移选/滚、`→`/`ENTER` 进、`←`/`ESC` 关最右框)。§七 同步:行对象按层 `s_row[d][i]` 仅屏上框建、去掉逐框页头(`s_header`/`s_back_btn`/`s_title`)、新增每框滚动 `s_scroll[]`(8 B)、"存 vs 算"增 滚动=存/位置=算、持久态 9→17 B、内存预算(静态 ~0.75→~1.3 KB、LVGL 池=屏上 2~3 框)、对照表更新 | -| 2026-09-04 | **§四⑧ 按参考图 02~07 像素实测校准**(设备 px,误差 ≤3px):层级树/命名/箭头/选中态全部与图一致 ✓;显示模型两处修正——水平由"右锚定(钉屏幕右缘)"改为"**子框左缘=父框右缘**(共享边框列、零间隙)+ 宽自适应"(实测各子框均贴父框右缘 x≈67/106,最深框止于 x≈113~127 而非屏右缘);垂直溢出由"上移使底边贴屏底"改为"**上移使子框底边对齐父选中行行底**"(实测三遥 top=26/装置维护 top=54/通讯参数 top=82/记录查询 top=12 均吻合,且可叠到屏顶状态行区、顶部不钳制)。本菜单最深路径 ≈155<160 不会溢出;>160 行为与"根页框宽 99 vs 68"列为待确认。§7.2/§7.3/§7.4 "右锚定"表述同步 | -| 2026-09-04 | **实现落地,本文档与代码同步**:三层拆分实现(`ui_menu_tab` 生成物 + 新增 `ui_menu_view` 显示层、`ui_menu` 瘦身为纯状态机,§8.1);§四⑦/§6.4/§6.5/§6.6/§6.7 函数与 API 名同步为实际 `ui_menu_tab_*`/`ui_menu_view_*`/`menu_open\|menu_back\|menu_key_handle`;§五"待实现"→"已实现";§七 修正为实际字段(容器从不切 HIDDEN、`s_style_frame`、新增框几何缓存 `s_frame[]`,§7.2 G);§四⑧ 实测值区分"参考图/实现"两套(实现:根框 66、子框 42/46/54/6,顶 28/58/88/13,偏差入 §8.8 注 5),>160 溢出"待确认"落定为实现行为"屏缘裁切";新增 **§八 实现架构与关键实施细节**(布局常量/几何公式/对象模型/键路径/初始化时序/分级验证/6 条陷阱与保真度说明);验证:模拟器 7 状态对照参考图 01~07 + `@build` 0 错 0 警 | -| 2026-09-07 | **全文结构重排(理清三层架构与协作)**:旧版三层描述分散在 §六(数据结构)/§七(运行时数据)/§八(实现架构) 三处、§四 又混装导航逻辑与显示模型,读者难以看清各层职责与层间配合;重排为十章——**一 架构总览**(1.1 为什么拆三层 / 1.2 职责速览+依赖图 / 1.3 调用矩阵 / 1.4 一次按键的旅程 / 1.5 初始化时序 / 1.6 层间不变量)→ **二 菜单内容** → **三 数据层**(含 3.7 改菜单流程)→ **四 显示规范**(自 §四⑧ 抽出,含 4.5 参考图偏差)→ **五 显示层**(5.1 职责边界 / 5.5 公开 API 8 接口表)→ **六 逻辑层**(6.2 17 B 状态 / 6.3 导航规则含完整走查 / 6.4 键语义与分发)→ **七 层间配合细节**(7.1 逐键分层动作 / 7.2 框生命周期 / 7.3 存vs算 / 7.4 读写矩阵 / 7.5 内存预算带层归属)→ **八 验证与陷阱** → **九 迁移历史**(结构/运行时/内容三表收拢)→ **十 变更记录**;**修正归属错误**:`s_scroll[]` 实为**逻辑层** `ui_menu.c` 字段(17 B 导航状态之一,见 ui_menu.c),旧 §7.2 误划给显示层,新文 §6.2/§7.5 已归正;全部交叉引用同步到新章号;技术内容零删减 | -| 2026-09-07 | §1.2/§1.4/§1.5 三幅架构图由 ASCII 转 Mermaid(1 张 flowchart + 2 张 sequenceDiagram,初始化时序含表自检 alt/else 分支);键源措辞统一为“远端键”(与 `UI_设计架构.md`“远端客户端”一致:MCU 端按键经 TCP 7003 远端客户端 → ui_net_sink → keypad);职责表/调用矩阵/“两个要点”文字保留 | -| 2026-09-07 | 正文现状化:删除正文过渡性历史叙述(“设计阶段拟名…/实现采用…/见变更记录”等,旧文见 git 历史),各节改写为现状描述;移除 §九“迁移历史”整章(旧→新对照保留于本变更记录),变更记录重编号为 §九;§8 去日期注记,陷阱 3/4 改写为现状约束 | -| 2026-09-07 | §4.1 总览图由 ASCII 框线图升级为 SVG 精确几何图(新增 `docs/images/级联框总览.svg`,按 §5.2 常量 / §5.3 公式逐 px 绘制,含根框装饰 / 状态行 / 选中行反色 / 共享边框列标注 + ①~⑦ 位置标注);ASCII 版删除(旧图见 git 历史) | -| 2026-09-07 | 删除 §4.5“参考图与实现偏差”表(偏差数据已在 §8.2 注 5“参考图保真度”完整记载);正文两处引用(§四 引言、§8.1 验证表)改指 §8.2 注 5 | -| 2026-09-07 | §5.1 职责边界表去掉“不做”列、改为列表(负向约束已由章首“绝不做”行与 §1.6 层间不变量表承载,无信息损失) | -| 2026-09-07 | §6.1 职责边界表同样去掉“不做”列、改为列表(负向约束由章首“绝不做”行、§1.3 调用矩阵与 §1.6 层间不变量表承载,无信息损失) | -| 2026-09-08 | §5.3 几何计算重写为图文并茂:新增 `docs/images/级联框几何计算.svg` 四格图(① 行剖面定框宽 ② X 共享边框列 ③ Y 顶对齐 ④ Y 溢出上移,含虚线幽灵框 + 超屏红区示意),正文改为四步叙述 + 实测框宽表 + 公式汇总(五式内容不变) | -| 2026-09-08 | `menu_frame_t` 瘦身:`built` bool→`uint8_t`(与系统存储类型一致);`x/y/w/h` `int32_t`→`int16_t`(值域 0..160 / ≤242,16 位够;y 需有符号——钳制前可为负);`s_frame[4]` 96 B→48 B,省 48 B RAM(§5.4 对象模型表 / §7.5 内存预算表同步) | -| 2026-09-08 | 行 label 指针合并:删 `s_row_text` / `s_row_arrow` 两数组(省 512 B);文本/箭头颜色改在行容器 `s_row` 上设置、子 label 继承(LVGL `text_color` 为可继承属性,`lv_style.c` 属性标志表证实);§5.4 对象模型表 / §7.5 内存预算表同步(768 B→256 B) | -| 2026-09-08 | **行对象 → 自绘重写(方案1,省 LVGL 池"每行对象机制税")**:行不再是 LVGL 对象——行数据改 `s_row_node[4][16]`(`uint8_t` 节点下标,256 B→64 B),框体 `LV_EVENT_DRAW_MAIN` 自绘(选中行白带 `lv_draw_rect` + 每行 `lv_draw_label` 文本/箭头,按滚动偏移枚举可见行、重绘区外行 culling);框内滚动改 `LV_EVENT_GET_SELF_SIZE` 虚报内容高 + 手动跟随滚动(`view_scroll_to_sel`,替代 `lv_obj_scroll_to_view`);删 `s_style_selected`、`view_add_row` 与 flex 堆行;`frame_build/destroy/refresh` 改行数据注册/清空/重绘。§5.4/§5.6/§6.2/§7.1~7.5 同步。验证:`@build` 0 错 0 警 + 代码规范 PASS + 模拟器 8 状态像素回归(白带/边框/根框不变性 + 3 组往返态逐像素一致)全 PASS | -| 2026-09-08 | **4 层容器→单一持久容器 + 根框装饰/状态行自绘(RAM 收敛)**:焦点/键唯一入口 = 持久容器(框深度由逻辑层 `s_depth` 决定,键回调去掉 `user_data=depth`,`container`/`focus` 接口去参);根框装饰(浅 V)与状态行改容器 `DRAW_MAIN` 自绘(3 段 `lv_draw_line` + 1 行 `lv_draw_label`,删 3 `lv_line` + 1 label + 3 容器对象);静态显示层 ~0.5→~0.4 KB。验证:`@build` 0 错 0 警 + 代码规范 PASS + 模拟器 8 状态像素回归全 PASS(装饰/状态行像素级一致);LVGL 池实测 根框 7168→4872 B、最深四级级联 8488→6128 B(省 ~2.3 KB) | -| 2026-09-09 | **新增 §九"内容页(ui_content_page)"**:装置信息/交流量/直流量三叶子页落地(独立屏按需建毁 + 行自绘,几何实测自参考图 10/20/21);节点→页映射入逻辑层 `menu_content_page_for`(node 1/3/4),§2.1 叶子行为同步;flat 样式改常量样式(`LV_STYLE_CONST_INIT` 零池分配,动态常驻样式 x64 实测 88 B/个永久占用);关页后一次性残留 +80 B 分解入 §9.5(screens 数组高水位 +8、`lv_screen_load` 菜单屏局部 X/Y 样式 +72,均 LVGL 核心行为非泄漏)。验证:`@build` 0 错 0 警 + 代码规范 PASS + 模拟器三页对照参考图几何一致 + 菜单 8 状态像素回归全 PASS | -| 2026-09-09 | 用户密钥密码页落地(首个表单/操作页,§九 / `内容页架构.md` §4.1):框架描述符新增 title_y/hide_deco/hide_footer/key_intercept + 新 API `ui_content_page_invalidate`;受保护叶子路由(arm→开密码页,确认一致后回调**先关页再续做进入动作**);§9.2/§9.3/§9.4 同步。验证:回归扩至 7 页 + 往返水位全 PASS、五门禁全绿 | -| 2026-09-09 | 菜单显示层 flat 样式同法转常量样式(§5.6/§7.5/§9.5):LVGL 池基线 4872→4784 B、最深四级级联 6128→6040 B、内容页峰值 5648~6064→5560~5976 B(x64 省 88 B);`LV_STYLE_CONST_INIT` 生成外部链接符号,内容页同名者改名 `cp_style_flat`。验证:`@build` 0 错 0 警 + 代码规范 PASS + 菜单 8 状态像素回归全 PASS + 三页几何不变 | -| 2026-09-09 | 权限模型(§3.7/§3.8/§9.4 同步):菜单表行尾注记 ` #P`(需密码);`g_menu_tab` pwd 列改 0/1 布尔(API `ui_menu_tab_has_pwd`,表项仍 8 B/项);两个编译期密码(查看 000 / 修改 123)+ `ui_perm_t` 权限枚举在 `ui_pwd_def.h`(用户定案:密码仅编译期写入,不落 Flash、无运行期设置页)——密码页输查看密码授只读权限、输修改密码授修改权限(只有修改权限进入后才能改参数);逻辑层密码检查提前到内容页判断之前(带内容页的需密码叶子同样先经密码页,修复路由缺口);无密码叶子直接进、默认只读。验证:五门禁全绿(菜单 8 态 + 内容页 7 页像素一致、池 4784/4864 B 不变、Keil 0 错 0 警、代码规范 PASS) | -| 2026-10-26 | 9.5 节内存预算表与本文 1.5 节对齐:菜单基线 4784→**5368 B**、关页回落 4864→**5448 B**(2026-10-11 裁剪 LVGL 控件类后脚本常量即为此值);「内容页打开峰值」改为**增量口径** +776~1192 B,绝对水位标注为待按新基线重测,不臆造实测数 | diff --git a/docs/产品需求/产品需求设计文档.md b/docs/产品需求/产品需求设计文档.md index fb63323b..dfdcd142 100644 --- a/docs/产品需求/产品需求设计文档.md +++ b/docs/产品需求/产品需求设计文档.md @@ -2696,23 +2696,3 @@ docs/任务规划/UI补齐.md §5);原「当前执行 6 项」(记录 5 | RAM 预算与优化 | [`docs/内存管理/RAM使用分析与优化方案.md`](../../docs/内存管理/RAM使用分析与优化方案.md) | | AI 开发规范 | `AGENTS.md`(仓库根) | | 开发者入门 | `README.md`(仓库根) | - ---- - -## 12. 变更记录 - -| 日期 | 变更 | 说明 | -|---|---|---| -| 2026-10-05 | 初版 | 基于项目全量内容(架构 / 子系统 / UI / 测试 / 硬件网表 / 待办)编写完整产品需求设计文档:产品定位、六层架构与任务模型、V0.1 硬件规格、10 类功能需求(含 2 项待实现)、接口规范、非功能需求、UI 规格、待实现项与路线图、验收判据 | -| 2026-10-10 | FR-CFG-4 旧档迁移**取消** | 删除旧固件 `/cfg/netcfg.bin`(NCFG 二进制)的首启自动迁移:旧档若存在则被忽略(不读、不删、不迁移),配置回落工厂默认。理由:该一次性路径把整条配置写链挂进启动期调用图,defaultTask 静态最坏栈链 +600 B,而本仓库不存在携带旧档的设备;`net_cfg_legacy.c/h` 与 `cfg_store_legacy_path()` 一并移除。§7.1「掉电不丢配置」同步 | -| 2026-10-27 | **v1.1 全面刷新(以参考产品 CLS100 为横向基准)** | ① 新增 §2.5「与参考产品 CLS100 的能力对照」(12 个能力域逐域给出参考实现 / 本产品现状 / 结论),并据此重写 §2.1 现状口径与 §2.4 产品范围(分"已验收 / 已实现但受制约 / 非本期"三档);② 新增 §4.6「V0.1 硬件能力边界」(H1 双转换器无共同采样触发 / H2 无中点偏置 / H3 无出口开入 / H4 无本地屏 / H5 无 SDIO)作为范围裁剪的硬依据;③ 任务模型由 6 任务更正为 **9 任务**(补 `adcTask` / `iec104Task` / `protectTask`,栈配置改为 words/B 双列),事件位补至 bit8,启动时序补配置段注册与 `adc1_disable` 铁律,线程间通信补双区快照 / SPSC 环 / 脏位;④ **功能需求新增五节**:§5.9 ADC 采集与标定(FR-ADC,含标定折算与前端物理口径)、§5.11 遥测与相量(FR-MEAS)、§5.12 保护功能(FR-PROT,9 元件 + 四源闭锁)、§5.13 定值与运行参数(FR-SET)、§5.14 SOE 与动作记录(FR-SOE)、§5.15 IEC 104 上行(FR-IEC104,含点表推荐响应时间);⑤ 新增 §6.8 104 点表摘要,§6.7 对外 API 补 10 个模块;⑥ §7.2 补采样/相量/遥测/保护/上送七项实时指标,§7.3 内存与栈预算全部换为 2026-10-24 受管快照与 2026-10-22 栈快照,§7.4 门禁改为按族描述,§7.6 补 104 与配置面安全边界;⑦ §8 菜单绑定现状(22/33/42)与内容页分组重写;⑧ §9 改为「缺口总表(G1~G10)+ 推进顺序 + 未接线开关」,删除已闭环的 ADC/104 缺口;⑨ §10 验收补栈/体积门禁、采集与 104 锚点、六条现场项与五项台架闭环用例。**本次只改本文件** | -| 2026-10-27 | **v1.2 改为 1:1 复刻口径(以参考工程源码为唯一清单)** | ① **范围口径反转**:产品范围由「按硬件裁剪」改为「参考源码能力全集」,差异只允许来自 5 项物理不可移植项(X1 双核分工 / X2 VxWorks / X3 本地屏 / X4 一次设备接口 / X5 计量通道,§2.4.1);② §2.5 由「12 域能力对照 + 取舍依据」重写为 **「1:1 复刻基线」**,判定依据从参考项目的分析文档改为 **参考工程源码的常量表与模块文件**(§2.5.1 三要素:点表即契约 / 地址即接口 / 模块即元件);③ 新增 **§2.5.2 19 项能力清单**(源码实测):定值 **249 项 / 23 单元**(`g_tSetModelTab`)、104 定值映射 **107 项 `0x8820~0x8891`**(`g_tCommSetParaTab`)、遥测 **31**、遥测模型 35、电度 **8**、开入 **138**、开出 **31**、动作事件 **33**、录波通道 **65**、软压板 **9**、保护元件 **45 模块**、记录队列 **13 类**、自检 3 类型、录波 3 类型 / 6 段、规约 **12 种**、加密 SM2/SM3/ECDSA;④ 新增 **§2.5.3 104 地址空间 8 段表**并 **更正段基址笔误**——参考 `Rly_IEC104.h` 为 1 起编,遥测 `0x4001`、遥控 `0x6001`(v1.1 及更早写 `4000H+` / `6000H+`),§5.15 与 §6.8 同步更正;⑤ 新增 **§2.5.4 定值 23 单元分布表**(WatchDog 63 / SYS3 45 / VolTimeRecv 17 / AutoReCls 16 …,并说明枚举 28 个中 4 个表内无项的原因)与 **§2.5.5 45 元件九类归集表**(含 `PRS_OverCurrent.c` 判据结构对照);⑥ 新增 **§2.5.6 规约全集 13 行表**(对上 9 种 / 对下 3 类 / 加密)与 **§2.5.7 差异归因表**,结论改为「差距全部是进度而非范围」;⑦ **§9 重写为「复刻进度与路线图」**:删除全部「不做」表述,缺口分 **阻塞型**(标定闭锁 / 出口与开入 / 三相与同期 / 电度计量 / 对下采集 / 第三方送检)与 **规模型**(定值 40→249、映射 40→107、元件 9→45、录波子系统、规约 1→12、国密等)两表,条目一律用**语义短语**命名以免与其它文档的 `S`/`A`/`P` 编号族撞名(编号规范 P-8),推进顺序补「点表铺开必须晚于标定」铁律;⑧ §2.1 产品定位补 1:1 复刻目标与三项差距量化(定值 40 vs 249 / 遥测 9 vs 31 / 开入开出 0 vs 138·31);⑨ §6.8 点表摘要逐段补「与参考的差额」说明(遥测缺第二回线与线电压、遥信缺 138 点开入、定值缺整单元)。**本次只改本文件** | -| 2026-10-28 | **v1.3 缺口逐项细化(新增 §9.4~§9.12)** | ① **定值**:给出 40 项去向对账(覆盖参考 35 + 本地扩展 5),差额由「+209」更正为 **+214 项**;新增 23 单元逐单元差额表、已覆盖 35 项逐项对照(过流三段每段缺方向 / 低压 / 告警 / 低压定值 4 项;零序过流三段 18 项全缺,注意 `PS_3U0_*` 是零序**过压**不是过流;三级负荷只做一级;频率缺「跳闸投退」;电压缺 4 项跳闸 / 告警投退;PT·CT 缺 6 项)、完全未覆盖 163 项逐项清单(`SYS3` 45 / `VolTimeRecv` 17 / `AutoReCls` 16 / `SYN` 13 / `WAVESTART` 12 / `MeaLimit` 10 / `OverCurSpeed` 8 / `OverCurI0` 13 / 小单元 29);② **遥测**:31 点逐点对照,缺 22 点按依赖分三批(线电压与功率 13 / 第二回线 7 / 直流 2),指出「三相电压全落 TPAFE」可一次解锁 6 个线电压点;③ **开入开出**:138 = 软遥信 104 + 硬件 27 + 双点 6 + 多态 1,澄清「104 点 ≠ 104 个端子」;31 开出 = 出口 11 + 信号 20;④ **动作事件**:33 条(421~453)逐条对照,覆盖 9 条;记录参考源码 428/429 **同名**需按事件码区分;⑤ **保护元件**:口径改为模块级 45 → 8,37 个缺失模块逐个给出「缺它的后果 + 依赖」,差额由「+35」更正为 **+37**,指出 `MusterRecov` 总复归是唯一无硬件依赖、可立即开工的元件;⑥ **录波**:14 项硬指标(80 点/周波 = 4000 Hz、6 段、前 5 后 10 返回 2 手动 6 周波、9000 ms、RAM 16、COMTRADE 64/64/16、65 通道)与复刻所需四件东西;⑦ **记录体系**:13 类队列容量表,覆盖 8 类,缺越限 / 闭锁 / COS / 顺控 / 顺控执行;指出「闭锁记录」性价比最高(四源闭锁已全实现却无留痕);⑧ **规约栈**:12 种逐种链路 / 用途 / 工作量特征 + 四层排期,指出对上与对下是两套角色;⑨ 新增 **§9.12 复刻完成判据**(12 条可验证判据)。**本次只改本文件** | -| 2026-10-28 | **v1.4 屏板链路口径更正 + 逐字节复刻规格(新增 §5.16、§9.13)** | ① **口径更正**:v1.3 及更早把参考写成"**板载** LCD + 按键"、把本产品远端推流说成"等价替代",**两处都错**。参考源码中主机侧 5 个碰硬件的函数(`KeyGet` / `WriteScreenByByte` / `LCD_LED_Update` / `getRs485Key` / `anyNewKey`)**全树只有声明没有实现**,按键轮询函数名为 `Key_Rs485_Process()`(注释"轮询从485传来的按键值"),屏板插槽号 `CN_SLOT_DISP = 0`(注释"显示板插槽号固定为0")——**参考的屏和键同样在独立板件上、同样靠链路传输**,本产品与之**同构而非替代**;§2.4.1 X3 由「本地人机」改为「**就地屏板(板件本体)**」,并补口径更正说明段;② **§2.5.2 补第 20 项「远端屏与按键链路」**(状态 🔶),能力计数 19 → **20 项**、🔶 9 → **10 项**,§2.5.7 差异归因同步(X3 不再计为"已用等价方案替代");③ **新增 §5.16 远端屏与按键链路(FR-HMI)**:两条链路对照(RS-485 屏板通道 / TCP 7003 总线)、帧格式逐字节、CRC 覆盖范围、接收定界算法、**INIT 应答 29 B 逐字段偏移表**、键值位掩码语义、`bNeedFlash` 续传与拒绝语义(`-1` / `-2`)、按键状态机与合并优先级、三个定时器(500 ms / 1 分钟 / 200 ms)、发送状态机、`0x55`/`0xaa` 刷新互斥、任务参数(prio 111 / 栈 0x35000);④ **§5.16.9 给出 10 项与参考的差异**,其中 5 项为客户端可见的报文口径差(INIT **8 B vs 29 B** 为最大一条);⑤ **§6.2 按参考源码重写**:更正 INIT 应答长度(原写 8 B)、KEEPLIVE 改为**不应答**(原写"原样回显")、补最长帧 9800 B / 收发缓冲 10240 B / 按键码补 `F1`·`F2` 与位掩码可组合说明;⑥ **新增 §9.13 屏板链路复刻任务规划**:10 条语义短语任务 + 三批划分 + 唯一破坏性变更警示(INIT 长度变更必须与客户端同批发版);⑦ §9.1.2 补「屏板链路对齐」行、§9.12 补完成判据、§10.3 补现场验收第 13 项。**本次只改本文件** | -| 2026-10-28 | **v1.5 补串口屏板通道(显示信息不只走网络)** | ① **口径再更正**:v1.4 把串口通道写成"链路 A,随 RS-485 簇冻结",等于把它降级成可选——**错**。参考的架构是**一份显存、两个出口**:**串口屏板通道是主通道**(`LCD_LED_Update(显存 3200 B, LED 4 B)` 变化驱动 + `WriteScreenByByte` 500 ms 兜底),**TCP 7003 是镜像**;上行同理(`getRs485Key()` 物理键号 1~10 为主,`g_tRemoteKey` 为镜像,两者在 `Key_Read()` 汇合且**本地优先**)。§5.16 标题改为「**屏板链路:串口主通道 + 网络镜像**」并重写开篇;② **§5.16.1 重写为「一份显存、两个出口」**:显存物理基址 `CN_VIDEO_ADDRESS_BASE = 0xC1F00000`(非 cache 区)、三条下行路径与两条上行路径的归属任务 / 调用 / 载荷 / 节拍对照表;③ 新增 **§5.16.2「本产品的串口通道(待建)」**:V0.1 串口资源盘点(USART1 调试占用 / UART4 被冻结 RS-485 占用 / **UART5、USART2、USART3 空闲**),默认选 **USART3(PB10/PB11)**,若屏板为 RS-485 半双工则改 UART4 并先解冻该簇;④ 新增 **§5.16.3「参考实现的屏板侧接口一览」**,并**明确列出交付源码推不出的四项**(波特率与数据格式 / 帧头与校验 / 半双工方向控制 / 3200 B 是否分片与应答)——在拿到实测前不得声称"按参考协议实现";⑤ **§5.16.9 差异表由 10 行扩到 14 行**,新增「串口屏板通道整条缺失」「双出口并发缺失」「面板指示灯语义不同」「背光对比度」四项,并注明第 11/12 条是**整条链路缺失**而非报文细节;⑥ **§5.16.10 判据由 7 条扩到 12 条**,新增串口侧 5 条(键号注入 / 500 ms 内出帧 / 双通道并发不丢帧不串帧 / 拔插恢复 / 背光);⑦ **§9.13 任务由 10 条扩到 13 条**:原「RS-485 屏板通道」一条拆为「串口通道物理层定版 / 串口下行显存 / 串口上行按键 / 双通道并发回归」四条,批次表第三批改为**独立立项、不随 §5.10 冻结**,并补前置阻塞(需屏板实物验收;拿不到固件或抓包时不得把猜测定成契约);⑧ §5.16.8 `tTimerLCD` 行由"此路不实现"改为"串口通道周期兜底节拍(待建)",§2.5.2 第 20 项、§9.1.2、§9.12、§10.3 同步。**本次只改本文件** | -| 2026-10-28 | **v1.6 屏板源码到手:串口通道协议定版 + 状态灯下行** | ① **屏板固件已获得**(`D:\Code\DTU Code\DTU-LCD`,STM32F103ZE + UC1698U 160×160 单色 + **20 路状态指示灯** + 7 个物理按键),v1.5 列的"四项未知"**全部消解**;② **§5.16.2 重写为「串口通道:物理层与帧格式(屏板源码实测)」**:**700000 8N1**(APB1 42 MHz 分频零误差、`BRR = 0x3C0`)、软件 DE、**角色反转(屏板是 Modbus 主站、主机是从站 `0x01`)**、帧 A 6 B 召唤(`01 03 type key CRC_H CRC_L`,`KEY_CMD=0` / `RT_CMD=1`,CRC-16/MODBUS 只覆盖前 4 B、**高字节在前**)、帧 B **4208 B** 图像应答(3200 显存 + 4 B 状态灯 + 4 B info + 998 B 填充 + 2 B CRC,覆盖 `[0, 4205]`)、时序 275 ms / 200 ms / 5 次超时、200 ms 预算下 4208 B 约 60.1 ms(占 30 %)、主机端口默认 **USART3 + 另配 DE GPIO**(**不必解冻 UART4**);③ **§5.16.3 重写为「屏板侧行为:状态灯 / 按键 / 背光 / LOGO」**,新增**状态灯下行**:`info[0..3]` 为 **32 位小端位掩码**、**ID 0 = 电源灯硬件常亮、ID 1~19 对应 bit1~19**,给出 20 路 LED 引脚表,并指出"**位 → 业务状态映射表参考源码没有、须由本产品自定**";键值 `KEY_TYPE` 表(`0` 无键 / `1` ENTER / `2` UP / `3` DOWN / `4` ESC / `5` ADD / `6` DEC / `7` LEFT / `8` RIGHT / `9` RESET / `10` FACTORY),并**指出与参考主机 `getRs485Key()` 的 `9` / `10` 语义冲突**(参考是 `F1` 与 `F1+ENT`)、`key_configs[]` 仅 7 项且无 ADD/DEC 入口;背光自管、LOGO(Flash `0x0803F000`、魔数 `0x89 0x45`)、屏板健壮性(CRC 错 ≥3 仅清计数**不自愈**、**≈5000 s 自复位**、DMA 接收问题未解决);④ **§5.16.9 差异表**第 8 / 11 / 12 / 13 / 14 行按屏板实测重写,并新增"来自屏板固件的新增约束"5 条;⑤ **§5.16.10 判据由 12 条扩到 15 条**(275 ms 召唤 / ≤200 ms 回 4208 B、显存逐字节、7 键、**状态灯逐位**、双通道并发、**自复位容忍**、拔插恢复、**LOGO 下发**);⑥ **§9.13 任务由 13 条改为 15 条**:第 10 条由"物理层定版"改为"**串口物理层落地**"(参数已定)、新增第 12 条"**状态灯位映射表**"与第 15 条"**LOGO 下发流程**"、第 14 条并入"自复位容忍",批次表第三批改 10~15 并注明**不必解冻 UART4**,删除"拿不到固件不得定契约"告警(已消解),保留"**4208 vs 3208 待台架复核**";⑦ **§5.8 补屏板 20 路指示灯与主板 6 路 LED 是两套独立输出**;§5.6 FR-UI-1 改为"**双出口推流**";§6.2 口径注改为"串口通道是 Modbus RTU 风格裸帧、**不能共用组帧代码**";§2.4.1 X3、§2.5.2 第 20 项、§5.16.1、§5.16.8 `tTimerLCD` 行、§9.1.2、§9.12、§10.3 第 13 项同步。**本次只改本文件** | -| 2026-10-28 | **UI 现状同步(不 bump 版本号)** | ① 绑定叶数 22→28、未绑 11→5(记录 5 页与运行报告页落地绑页,§8.2 / §8.3 / §9.2);② 像素黄金 53→60 页(新增 7 张,含运行报告第 2 页);③ 字库当前态改 218 唯一字 / 313 字形(122/217、179/274、185/280 均为历史快照,§8.5);④ FR-SOE-3 由「展示层待补」转「软件面已落地,真机判据待台架」(§5.14);⑤ §2.4 立项未排去掉已交付的「记录 5 页」、§9.1 差距表 UI 记录页行改写现状与去向。真机判据登记 docs/任务规划/登记簿.md §7;模拟器结构性照不到的部分见 docs/测试说明/模拟器差距清单.md §2.3。 | -| 2026-10-28 | **v1.7 单色口径:删除多色协议,INIT 由 29 B 改 16 B** | 用户裁定"屏幕板都是单色的,多色协议可以删除、不必对齐"。**核查后确认这不是让步,而是删死字段**:① **三处源码证据**——`RemoDispBus.h:46` `CN_RDISP_TYPE_MONO = TRUE` → `CN_RDISP_LCD_TYPE = CN_MODE_GREY_MONO`、`CN_RDISP_MEMSIZE = (X>>3)*Y`(链路显存本就是 1 bpp);`RDisp_Form_InitInf` 里 `CN_RGB_RED/GREEN/BLUE` 是**编译期常量**而非逐帧数据;`RDisp_LcdColor_To_Mono()` 对 `CN_MODE_GREY_MONO` **直接 `return TRUE` 不转换**,真正干活的 `RDisp_Lcd16B_To_Mono()`(RGB565→单色)挂在 `CN_MODE_COLOR_16B` 下**本构建永不进入**(死代码);② **§5.16.5 INIT 应答表由 29 B 重写为 16 B**(宽 2 + 高 2 + 显存 4 + 8 键值表),删掉 1 B 颜色位 + 12 B RGB,并补"为什么是 16 B"的证据块;③ **§6.2 命令集 INIT 行**同步改 16 B 并加"单色口径"注(颜色位与 RGB 整段删除、`RDisp_LcdColor_To_Mono()` 不存在);④ **§5.16.6 第 6 条注**改为"该函数在参考单色构建下就是空转",避免误以为本产品漏了一步转换;⑤ **§5.16.9 第 1 行**由"补 21 B"改为"**补 8 B 键值表 → 16 B**,颜色 13 B 不对齐";"新增约束"补"单色"一条;末尾警示改为 **16 B vs 29 B 不可互换**(从偏移 4 起含义即不同,客户端不得复用参考 29 B 解析器截前 16 B);⑥ **§5.16.10 判据第 1 条**改 16 B 且"不得出现颜色位或 RGB";⑦ **§9.13 第 2 条**改"INIT 应答补足 **16** 字节 / 不加颜色位与 RGB"、第 9 条客户端按 16 B 解析、破坏性变更警示改 16 B(后 8 B 而非后 21 B)并补"不可与参考 29 B 互换";⑧ **§2.4.1 补"多色显示不在本表内"**——参考与本产品都是单色链路,删的是死字段,**不属于"决定不做"的能力**;§2.5.2 第 20 项、§9.1.2、§9.12、§10.3 第 13 项同步;⑨ **§8.1 色深行**补"无灰度、无彩色,7003 INIT 颜色字段已删",渲染行改为"串口屏板通道(主)+ TCP 7003(镜像)双出口"。**本次只改本文件** | -| 2026-10-28 | **v1.8 端口重排:屏板占 USART1,日志迁 RS-232 通道** | 用户裁定"把现在的日志 UART 让给屏幕,RS-232 通道后面用来输出日志"。**这条裁定把 v1.6/v1.7 的头号阻塞直接消掉了**:① **§5.16.2 新增「端口裁定」块**——屏板改走 **USART1(PA9/PA10,MCU 直出 TTL、不经任何收发器)**,因此 `U15 = TP8485E-SR` 只有 250 kbps 这件事**对屏板链路不再构成约束**;日志迁 **RS-232 通道**(V0.1 板上 RS232#3 = USART2 PD5/PD6 为默认,RS232#1 = UART5 PC12/PD2 为备选,两者都经隔离器 → U13 TPT3232E → CN1);② **纠正分频算法**——旧文写"`42 000 000 / 700 000 = 60` → `USARTDIV = 60.0`、`BRR = 0x3C0`"**漏了 16 倍过采样**,照此写实际波特率只有 43 750;正确值:USART1(APB2 84 MHz)`USARTDIV = 7.5` → **`BRR = 0x0078`**,APB1 实例(42 MHz)`USARTDIV = 3.75` → **`BRR = 0x003C`**,两者误差均为 0;③ **§5.16.2「主机侧端口选型」整表重写为「主机侧端口重排」**,按 `docs/硬件平台/V0.1_网表详细分析报告.md` §4.2 的三对 UART 轮换列明 RS485#4 = UART4(DE = PA15)、RS232#1 = UART5、RS232#3 = USART2,并补两条实现约束(`console_log.c` 里 `huart1` 5 处 + 自愈函数直写 `USART1_IRQn` / `MX_USART1_UART_Init()` 需收口成一处端口宏;新日志口必须 `UART_MODE_TX`,否则重演 ORE 锁存);④ **DE 口径改为「TTL 直连无 DE」**,仅"经外部 485 模块接 A/B"时才需处理,且极性由该模块决定;⑤ **主机 RX 口径**由"吃下 4208 B"改为"只需 6 B(16 B 缓冲够)",并说明 TTL 直连无自发自收;⑥ **§4.2 外设接口表**:USART1 行补"端口重排后改作屏板链路 + PA10 目前未接线",新增 USART2(RS-232 #3,日志口)与 UART5(RS-232 #1,备选)两行,UART4 行注明 V0.1 轮换依据;⑦ **§5.16.9「新增约束」**与 **§9.12** 的 700000 行同步为"USART1 TTL 直连、无 DE";⑧ **§9.13 新增第 16 条「日志口迁移」**并置于第三批首位,批次表注明 **16 必须排在 10 之前**(两者共用 `USART1->DR`);第 10 条改为 `BRR = 0x0078`、无 DE、`DMA2_Stream7/2` 现成;**前置阻塞**补两条物理前置(PA10 接线、台架串口线从 USART1 挪到 CN1)。**本次只改本文件** | -| 2026-10-28 | **v1.9 撤销"PA10 未接线",ORE 机理改正** | 用户反馈"PA10 这个端口我接线了,当时分析出这个问题来,我怀疑是错误的"。核查后确认:**`App/log/console_log.c`(文件头与 `con_uart_reinit()` 注释)与 `docs/子系统设计/控制台单写者日志设计说明.md` §12 里的"PA10 悬空 / 未接线"是 2026-10-02 的归因推断,不是实测**,且与用户确认的接线状态相反。改动:① **§4.2 外设接口表** USART1 行删掉"PA10 目前未接线、作屏板链路前必须接上",改为"PA10 双向均已接线";② **§5.16.2** 原"USART1 的 RX 目前没有接线"警示块整段重写为「旧结论已撤销 + ORE 真正机理」——ORE 的充分条件是**RX 使能却从不读 `DR`**(任意一个字节或噪声沿使 `RXNE` 置位后无人读,下一个事件即锁存 ORE,且只能靠"读 SR 再读 DR"清除 ⇒ **永不自愈**),与引脚悬空无关;据此补两条硬要求(屏板链路必须真的消费 `DR` 并在 `HAL_UART_ErrorCallback` 里清 ORE 后重挂接收;新日志口设 `UART_MODE_TX` 仍正确,因为那是从机制上摘掉 RX);③ **§9.13 前置阻塞**由"两条物理前置"改为"一条物理前置(台架串口线挪位)+ 一条实现纪律(RX 要真读、ORE 要真清)",并写明原"PA10 接线"结论已撤销;第 11 条的验收隐含"拔插 TX 线制造噪声后能自动恢复"。**当年那场 ORE 风暴的真因仍待定**——接线正常时更常见的是对端波特率不匹配或适配器 TX 在 USB 掉线时浮空,下次复现先量空闲电平与波特率,不要再默认"引脚悬空"。**本次只改本文件** | -| 2026-10-28 | **像素黄金口径更正(不 bump 版本号)** | 正文两处当前态由「60 页」改报「60 张」:判据本体 = `simulator/tests/ref/` 入库 `shot_*.bin` 实数 60 = `check_content_pages.py` 的 `PAGES` 条目数 60,其中 2 张是分页页多拍的第 2 屏 ⇒ 张数 ≠ 页数(同一句里「+7 张」与「60 页」并存就是口径混用的后果)。历史行 53 → 60 与更早的 27 / 40 / 47 一律按当日事实冻结,本行只追加。 | diff --git a/docs/代码规范/嵌入式C语言代码规范_V1.0.md b/docs/代码规范/嵌入式C语言代码规范_V1.0.md index ffc42d66..c83ba26f 100644 --- a/docs/代码规范/嵌入式C语言代码规范_V1.0.md +++ b/docs/代码规范/嵌入式C语言代码规范_V1.0.md @@ -4,11 +4,6 @@ 本文档旨在统一嵌入式C语言代码的编写风格,提高代码的可读性、可维护性、可移植性和可靠性,降低团队协作成本,减少代码缺陷。 ### 1.2 适用范围 本规范适用于所有基于C语言的嵌入式软件开发项目,包括但不限于51单片机、STM32、ARM、DSP等平台。 -### 1.3 修订记录 -| 版本号 | 修订日期 | 修订内容 | 修订人 | -| ---- | ---------- | ------ | --- | -| V1.0 | 2026-05-11 | 创建初始版本 | 王建锋 | -| V1.0.1 | 2026-09-01 | 修复示例与规则矛盾(括号风格、示例类型、变量初始化、硬编码、注释补全);规则定案:保护宏改`XXX_H`、常量在右、头文件常量用`#define`、存储类前缀优先、允许`void`返回值 | 王建锋 | ## 2. 文件结构规范 ### 2.1 头文件(.h)结构 diff --git a/docs/任务规划/README.md b/docs/任务规划/README.md index 5ef92987..f4ab631e 100644 --- a/docs/任务规划/README.md +++ b/docs/任务规划/README.md @@ -12,7 +12,6 @@ | UI 之后还有什么、哪些事在等条件 | `登记簿.md` | | ADC 标定为什么没做、保护为什么不动作 | `数据可信.md` | | RS-485 为什么冻结、重启要满足什么 | `暂缓-RS485.md` | -| 测试与架构还剩什么约束 | `测试与架构专项.md` | | 怎么让主机跟屏板通信、先决条件是什么 | `屏板链路.md` | **一件事只有一个归属。** 本文件只负责导航与顺序,不复制各任务的验收明细; @@ -87,8 +86,9 @@ docs/测试说明/模拟器差距清单.md §2.3「开机账本 boot_stats」一 2. **当前任务只改 `UI补齐.md`,后续事项只改 `登记簿.md`**;顺序变化才改本文件 §2。 3. `数据可信.md` 的 §2、§4、§7~§10 仍被代码头注释引用为设计依据,不能按“已完成” 删掉;其待办只认 §5 的两项。 -4. `测试与架构专项.md` 的断言与体积门禁章节仍是代码和门禁的规格锚点,即使事项已完成 - 也不能删;当前未闭环的只有 RS-485 侧采集链路测试约束。 +4. 专项文档只放**还没闭环的约束**;已落地事项的规格正文归代码头注释或模块文档, + 销项即删文件并把引用改指现行出处(先例:`测试与架构专项.md` 已删除 2026-10-28, + 唯一未闭环的「采集链路测试可验证性约束」并入 `暂缓-RS485.md`)。 5. 任务分支不直接修改 `docs/任务规划/**`;状态更新与销项由主工作树统一处理。 6. 并行开发机制、工作树和锁的使用见 `docs/环境与部署/并行任务工作树方案.md`。 本文件夹不再另维护一份分道、批次和写域方案。 diff --git a/docs/任务规划/屏板链路.md b/docs/任务规划/屏板链路.md index 5f25c574..472c6482 100644 --- a/docs/任务规划/屏板链路.md +++ b/docs/任务规划/屏板链路.md @@ -22,28 +22,6 @@ **执行顺序因此是**:挪台架线 → 迁日志口 → 才开始写屏板链路。 第一步是拧螺丝,第二步约 20 行代码(§3 批 0),第三步才是原来规划的那些批次。 -好消息是:**主机侧 RX 只需要 6 B**(屏板发的是 6 字节召唤帧),4208 B 只出现在**发送方向**, -所以内存和缓冲压力比想象中小得多(§1.3)。 - -> ⚠ **顺带纠正一处机理(2026-10-28)**:当年把 ORE 锁存归因于"PA10 悬空",既然 PA10 是接线的, -> 这条归因就不成立。真正的充分条件**与引脚悬不悬空无关**——**RX 使能了却从不读 `DR`**: -> 线上只要出现任意一个字节或一个噪声沿,`RXNE` 置位后没人读,下一个事件就把 **ORE 锁存**; -> 而 ORE 只能用"先读 SR 再读 DR"清除,于是**永不自愈**。悬空只是让它更容易发生,不是必要条件。 -> -> 这条纠正对实现有直接影响: -> 1. **屏板链路要用 RX,就必须真的消费 `DR`,并在 `HAL_UART_ErrorCallback` 里清 ORE** -> (`__HAL_UART_CLEAR_OREFLAG` 或读 SR 再读 DR)。否则一次噪声就永久锁死, -> 症状与"屏板不回帧"一模一样,很容易又查错方向。 -> 2. **新日志口设 `UART_MODE_TX` 仍然是对的**——那是从机制上把 RX 摘掉,与 PA10 接不接线无关。 -> 3. 当年那场风暴的**真因仍待定**:接线正常时更常见的是**对端波特率不匹配**(适配器不是 115200) -> 或适配器 TX 在 USB 掉线时浮空。下次复现先量适配器 TX 的空闲电平与波特率, -> 别再默认"引脚悬空"。 - -> 顺带纠正另一条旧结论(本文 v1 写错了):`docs/硬件平台/V0.1_网表详细分析报告.md` §4.2 做过一次 -> "三对 UART 轮换"——**V0.1 的 RS485#4 = UART4(PC10/PC11,DE = PA15)**,RS232#1 = UART5、RS232#3 = USART2。 -> 所以 `rs485_init(&g_rs485, &huart4, …)` 与 V0.1 **一致,不用动**;V0.0 报告里的"RS485 = UART5"是旧板。 -> 之前把它当成"网表自相矛盾"是拿 V0.0 摘要行对 V0.1 代码,判断依据错了,结论也就错了。 - --- ## 1. 现状盘点 diff --git a/docs/任务规划/暂缓-RS485.md b/docs/任务规划/暂缓-RS485.md index bbfb4812..adb21abc 100644 --- a/docs/任务规划/暂缓-RS485.md +++ b/docs/任务规划/暂缓-RS485.md @@ -7,6 +7,27 @@ |---|---|---| | **B2** | **RS-485 采集链路实现**:双缓冲 + 序号(防包撕裂)+ DE 收尾(超时路径等 TC)+ ModBus RTU 状态机(`App/protocol/` 正是为此预留) | **RS-485 接线门禁尚未满足**:先修单缓冲包撕裂、TX 超时拉 DE 未等 TC 两条,修完才允许接消费者 | | RS485 DE 收尾 | RS485 DE 收尾(原属结构债一档剩余,已移出) | 同上 | -| 采集链路测试可验证性约束 · RS485 侧 | 双缓冲 + 序号、DE 超时路径覆盖,`测试与架构专项.md` §2.2) | 随 B2 设计文档落地 | +| 采集链路测试可验证性约束 · RS485 侧 | 双缓冲 + 序号、DE 超时路径覆盖(约束正文 = 本文「采集链路测试可验证性约束」一节) | 随 B2 设计文档落地 | | 待确认-3 | RS-485 PD0 DE 半双工方向语义硬件实测确认(本次仅静态审查) | 需硬件实测窗口 | | 网络性能资源建议簇中 DE 项 | `HAL_Delay(1)` 阻塞 DE | 随 B2 | + +--- + +## 采集链路测试可验证性约束(B2 动手前必须落实) + +> 原属 `docs/任务规划/测试与架构专项.md` §2.2(该文档已删除,2026-10-28)。ADC 侧随 B1 闭环, +> **没落实的只剩 RS-485 侧**,所以约束正文收在本节——重启 B2 以这里为准,不要再另起一份。 + +本项**不是缺陷,是对上游 B2 的设计约束**:`rs485_task.c` 仍是空桩、`App/protocol/` 只有占位文件;动手前不落实 +这三条,事后无法补测(撕裂与错误路径在真机上不可稳定复现)。 + +1. **协议解析必须与硬件 I/O 分离**:`App/protocol/` 的解析函数应接受 `(const uint8_t *buf, size_t len)` 并返回 + 解析结果,使其成为**主机侧纯逻辑单测的天然适格对象**(参考 `cfg_file` 的"核心 + 后端"模式); +2. **采集缓冲必须双缓冲 + 序号**:否则消费者读到撕裂数据,而**撕裂在单测里测不出来**(时序相关), + 必须在设计上消除; +3. **DE 收尾必须有超时路径覆盖**(RS-485 半双工特有陷阱)。 + +**完成判据**:B2 设计文档体现上述三条;协议解析函数有对应的主机侧纯逻辑单测。 +(ADC 侧不需要再做:它没有协议解析面,"同一时刻性"由 `tpafe5160_snapshot()` 原子快照保证,2026-10-10 随 B1 + 闭环 → `docs/硬件平台/ADC通道映射说明.md` §8 与 `App/algo/README.md`。) + diff --git a/docs/子系统设计/IEC104上行设计说明.md b/docs/子系统设计/IEC104上行设计说明.md index bd0eb27e..38866e9b 100644 --- a/docs/子系统设计/IEC104上行设计说明.md +++ b/docs/子系统设计/IEC104上行设计说明.md @@ -255,17 +255,3 @@ 「拒绝非白名单」= close + re-listen,端口扫描可打成 SPI/看门狗风暴,且配错 即锁死真主站(FTP 口令那套失败锁的代价在 104 侧没有等价护栏可低成本复刻) → 待送检/现场需求明确后另行立项,`[comm]` 段当前**没有**该键。 - -## 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-10-12 | 建档(B4):范围/分层/点表/链路流程/接入决策/预算/测试方案;§5 接线细节随实现回填 | -| 2026-10-12 | B4 落地回填:承载改**专用 iec104Task**(netTask 承载会 RPC 自死锁);§5 全量回填(门控/代次/拆链/对时/看门狗位 7);抢占策略修正为**首到优先**(§8 第 7 条);§6 实测(640 words,链 1456 B,余 43% PASS) | -| 2026-10-12 | **B7 定值持久化 + 软压板**:YK12 转真(§3.3,两段式 → `PS_GLOBAL_EN`);定值执行段改 `prot_set_set_sealed` 原子写+封存(§3.4,收口 B5 竞态窗口);本地项 `comm_addr=0` 不可寻址;持久化 = 脏标志 → `SYS_EVT_PROT_SET_SAVE` → defaultTask 原子写 `/prot_set.bin`,开机屏障前整表原子装载(损坏拒绝保默认 + 自检留痕);单测 +7(iec104 94 断言)+ prot_set blob 往返/损坏 33 断言 | -| 2026-10-12 | **B7 台架腿闭环**(§7 台架行回填):主站工具加 `--b7-pre/--b7-post/--b7-mark/--b7-check` 四模式(中间 ST-LINK 复位);pre 21/21(YK12 OFF→低定值不动作 / ON→YX15·16 即动作)、post 13/13(**压板退出态跨复位保持** + 重启后联动在位)、mark/check 4/4+4/4(**非默认定值 7.5 跨复位保持**);开机日志 `[CFG] prot set loaded (/prot_set.bin)`;证据 `../测试说明/boot_log_data/20261012_B7_*` | -| 2026-10-25 | **标定折算落地联动(下游常数按工程量重定)**:遥测读数由原始码值改工程量(§3.1 注已重写);死区按额定 0.5% 逐点重定(0.5 V / 0.005 A / 0.5 Hz),§8 第 4 条改「已落地,8020H 段仍归运行参数段」 | -| 2026-10-25 | **运行参数段(道D,「数据可信」M6-①)**:新增 `App/algo/run_par.c/h`——遥测死区 9 点真源收编([run_par] 段 9 键 int32 毫单位落盘,工厂默认 = 下游常数按工程量重定的档位;pts 层 s_yc_db 副本删除、set/get 转转发壳并保留清确认计数语义);104 **0x8020~0x8058 读写映射**(§3.4 新表:逐项地址本仓自定、送检点表到位后替换常量段;0x8027~0x802A 永不覆盖,路由 run_par 先 prot_set 后);**k/b 系数覆盖 = adc_cal_set 代理**(合法带/越带留痕复用,run_par 不存系数);持久化走新事件位 `SYS_EVT_RUN_PAR_SAVE`(1<<8) 整档外科 save;单测 test/host/run_par 新建(TC-RUNPAR-001~008,67 断言)+ iec104 套 +TC-IEC104-029 路由钉(141 断言);台架/送检腿待排窗 | -| 2026-10-25 | **104 改读快照与频率点绑定(道D,「数据可信」M5/M6)**:YC 板端源改读 测频与遥测快照(削顶五路从点表绑死 -1 改为**槽位绑定 + 快照品质 CLIPPED→IV**,V0.2/N-18 零改动启用);`0x401D` 绑频率源(`freq_valid()==0` → IV);死区改运行时副本 + `iec104_pts_yc_set_deadband()`(运行参数段接线点);COV 遥测腿 = 死区连续 2 点确认(快照 `seq` 去重)+ 品质翻转直报;`iec104_pts_src_t` 表尾追加 `yc_read_ex`(旧源退路语义不变);单测 97→127(TC-IEC104-025~028 走真实 全周傅氏相量链);台架腿(总召读回一致 / 频率 ±0.01 Hz)待排窗——主站工具已记 val+qds,无需改工具 | -| 2026-10-12 | **B9 时标 SOE**:自发单点 YX 换 **M_SP_TB_1(30)**(SIQ+CP56,§3.2 注;总召/周期保持 NA 型);link cfg 增 `epoch_ms` 时标源(NULL/无效 → IV 如实);serv 绑 `sys_clock`(秒域 → ms 域=秒×1000);主站工具解析 type 30/1 双型;单测 iec104 94→97(TB 时标 + IV 路径,两种类型都断言);台架腿见 §7 B9 行;落盘侧见 `App/log/README.md` soe 节 | -| 2026-10-26 | **道G task-8:`[comm]` 段落地(「UI 补齐」波次里的非 UI 前置项)**——ca/端口从写死改 `[comm]` 可配(getter 合法带自愈,键表 → `docs/子系统设计/网络配置说明.md` §3.6);`iec104_comm_init()` 内核前注册于 `app_main_init`(先注册后 load 契约,同 [adc_cal]/[run_par]);生效 = 改后重启(ca 任务启动读一次;port 下次重 bind 自然生效),不挂回调不新增事件位;§5/§8 同步销项,**主站地址不做**的理由登记 §8 第 8 条;死 define `IEC104_PORT` 删除(零 .c 消费);`IEC104_SERV_PORT` 降为快照兼容出口(真源 getter,task-9 切 ui_data_feed);单测 = `test/host/iec104` TC-IEC104-031~033(套件 174/174 PASS)+ `test/host/iec104_serv` TC-I104SRV-001b/c(37/37 PASS)+ `test/host/cfg_file` TC-CONFIG-056/057(207/207 PASS)| diff --git a/docs/子系统设计/控制台单写者日志设计说明.md b/docs/子系统设计/控制台单写者日志设计说明.md index 39a57091..ac640d7d 100644 --- a/docs/子系统设计/控制台单写者日志设计说明.md +++ b/docs/子系统设计/控制台单写者日志设计说明.md @@ -486,12 +486,4 @@ D4 否决理由对现状仍逐条成立(115200 发送率低、日志行稀疏 ## 修订记录 -| 版本 | 日期 | 说明 | -|------|------|------| -| v1.0 | 2026-09-25 | 初版:完整设计说明(背景根因 / 单写者模型 / 详细设计 / API / 参数 / 失效模式 / 内存预算 / 设计决策 / 验证记录);实现位于 `App/log/console_log.{h,c}` | -| v1.1 | 2026-09-25 | 文件拆分同步:写者任务体迁至 `App/task/default_task.c`(`Src/freertos.c` 只留 CubeMX 接线与崩溃钩子);§3.2 文件清单 / §4.3 / §6 / §11 位置引用更新 | -| v1.2 | 2026-10-02 | 新增 §12 ORE 僵尸通道(台架日志代次 288 实证:节奏性喂狗饥饿,非死等;缓解已做、TX-only 根治待办)+ §11 时间线两条 10-02 记录;§13 新增 O4;原 §12/§13 顺延为 §13/§14 | -| v1.3 | 2026-10-10 | 栈链整改(**未抬栈**)三处:① 裸发改为纯寄存器轮询——DWT 不可用时走 `con_tx_counted`(计数上界),**不再回退 `HAL_UART_Transmit`**(tick 依赖不可信 + 其调用链污染所有任务最坏栈链);② 切断 `drain → syslog_post → write_line` **调用图成环**,改为置标志 + 写者任务在 drain 之外补记(新 API `dbg_console_tx_fault_log_take`);③ 行缓冲按模块可收紧(`dbg_log.h` 新增 `DBG_LINE_BUF_MAX`,深链模块 128)+ 时间戳缓冲并入行缓冲(32 → 24)。§4.4 / §5 / §6 / §7 / §8 同步;实测 defaultTask 静态最坏链 5312 → 2776 B | -| v1.4 | 2026-10-10 | 新增 `dbg_console_writer_ready()`(写者就绪查询)并固化"未注册期只有 defaultTask 记日志、周期任务用就绪门控"纪律;更正 §3.4 / §7 / §9-D5 / §13-O1 的"只丢不交错"旧结论(裸发已改寄存器级轮询、无 `gState` 互斥) | -| v1.6 | 2026-10-25 | 新增文末**附录:日志静默观察项 × 步骤 8 合并评估**(道F 批 2 / task-18,零代码):A.1 步骤 8 已由单写者形态在生产者侧达成(4402µs/行 → µs 级入环);A.2 TX 中断/DMA 维持 D4 否决、复议绑定 S-3 落地后 `tx_timeout` 实测;A.3 该观察项判据②已具备、①给出「无源 vs 真停滞」判别口径与 V5 复跑销项条件;A.4 遗留面全部既有、无新增。§11 时间线同步 | -| v1.5 | 2026-10-24 | **主机单测批次照出的四条现状全部处置**(生产码在 `App/log/console_log.c`,用例在 `test/host/console_log/`):① 冷却判据改用独立 `s_con_cooling` 标志,不再拿 `HAL_GetTick()` 的 0 值当哨兵——旧写法在 tick==0 那一拍(开机头 1 ms,或 49.7 天回绕到 0)冷却等于没记;② `con_append` 的空位判据 / 推进 head / 整行拷贝收进同一临界区——旧实现是临界区外 check-then-act,多生产者可在环 >95% 满时双双过判据把 head 推过容量 → 静默覆盖且**既不打 [ERR] 也不计 dropped**;③ `Instance == NULL`(未初始化)与僵尸通道**分诊**,未初始化绝不 reinit(旧路径会在 HAL 未就绪时经 MspInit 重配 RCC/GPIO);④ 三本账,见本文 §13-O2。**dropped 的单位口径变了**:一次 = 一行(缓冲满)或一个块(没能确认送达 / 通道不可用),故 `[ERR] CONSOLE dropped N lines` 的 N **不恒等于行数**(为兼容 `@test` 标记匹配,文案未改词)。本文 §3.1 与 §4.1 的「单生产者 vs 全上下文生产者」矛盾一并消除 | +> (本文件不再记流水账:改了什么是正文说了算,改动过程查 git log。) \ No newline at end of file diff --git a/docs/子系统设计/系统墙钟时间维护说明.md b/docs/子系统设计/系统墙钟时间维护说明.md index f2a84f62..2478a644 100644 --- a/docs/子系统设计/系统墙钟时间维护说明.md +++ b/docs/子系统设计/系统墙钟时间维护说明.md @@ -338,8 +338,6 @@ SD2506 有 **70 字节电池保持用户 SRAM**(寄存器 `2CH~71H`,`Drivers --- ---- - ## 15. 时间同步(PC 推送 / TCP) 除 RTC 自身走时与开发期校时宏外,系统支持由 **PC 通过 TCP 主动推送本地墙钟** 来同步板子时间,使板子时间与开发电脑一致(无需公网 NTP)。 @@ -417,14 +415,3 @@ PC 端 `test/host/time_sync_server.py` 发送 8 字节后**必须保持连接打 ``` PC 端 `python test/host/time_sync_server.py` 每 `interval` 秒推送一次,epoch 随电脑本地时间递增即表示同步正常。 - ---- - -## 变更记录 - -| 日期 | 变更 | -|------|------| -| 2026-10-27 | **时基口径定稿:内部一律本地钟面(用户裁定「时基先本地为准」)**:新增 §1.1;§2 的 epoch 行原写「自 1970 UTC 起」与 §15 网络校时字段「本地 Unix 时间戳」互相矛盾(代码按后者走),现统一为本地口径;§13 时区行的旧建议「API 层加偏移参数」作废。**未决**:104 上行 `CP56Time2a` 现把内部值直接按 UTC 分解发出(= 发的是本地钟面值),要不要上行前转 UTC 属产品对外语义决定,送检前单独裁定,本轮不改 `iec104_asdu.c` | -| 2026-09-15 | v1.3:① `sys_clock_get` 30 天惰性再基准化——修复 49.7 天墙钟回绕(§3/§7/§12);② `sys_clock_init` 检查 RTC 读返回值/写回复验,失败降级为默认时间基准并返回 -1——激活"时钟芯片异常"自检(§5/§6/§9);③ 修正未初始化哨兵判断(§12-6);④ 时间同步任务启动/Socket 占用描述同步为事件屏障 + 单连接实现(§15);⑤ 新增日志串用 ASCII——本机 ARMCC 按 CP936 解读无 BOM 源文件,奇数汉字字符串会吞掉结束引号致编译失败(见 AGENTS.md 编码铁律) | - -*文档依据 `App/util/sys_clock.c` / `App/sync/time_sync.c` 实现与《嵌入式C语言代码规范_V1.0》整理。* diff --git a/docs/子系统设计/网络配置说明.md b/docs/子系统设计/网络配置说明.md index edbd1e01..4ade2d29 100644 --- a/docs/子系统设计/网络配置说明.md +++ b/docs/子系统设计/网络配置说明.md @@ -348,16 +348,3 @@ ENTER 进入选中地址行 → `↑/↓` 调活动字节(0..255 **环绕**) | 启动顺序 / 就绪屏障 | `docs/架构设计/项目启动顺序管理.md` | | 项目分层架构 | `docs/架构设计/项目架构总览.md` | | 内容页框架(含网口设置页) | `docs/UI设计/内容页架构.md` | - ---- - -## 9. 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-10-26 | v2.5:**新增 §3.6 `[comm]` 段(道G task-8,「UI 补齐」波次里的非 UI 前置项)**——104 公共地址/监听端口 2 键、改后重启生效口径、主站地址不做的理由登记、段容量台账 6/8 与机器钉 | -| 2026-10-25 | v2.4:**新增 §3.5 `[run_par]` 段(「数据可信」运行参数段一项)**——遥测死区 9 键毫单位布局、104 写路径合法域、系数覆盖不落本段(真源 [adc_cal])、守卫仅在写路径、事件化落盘 | -| 2026-10-11 | v2.3:**新增 §3.4 `[ftp]` 段(N-19 FTP 鉴权)**——`user` / `pwd_hash`(SHA-256(user‖password))/ `write` 字段表、鉴权流程(USER 恒 331 / 恒定时间比较 / 未登录命令门 / 5 败锁 60 s)、改口令步骤与忘口令恢复路径、出厂默认口令启动告警、明文嗅探边界 | -| 2026-10-10 | v2.2:**删除旧档 NCFG 迁移**——`net_cfg_legacy.c/h` 整体移除、`cfg_store_legacy_path()` 撤销;旧档 `/cfg/netcfg.bin` 若存在则被忽略(不读、不删、不迁移),配置回落工厂默认。理由:该一次性路径把整条配置写链挂进启动期调用图,defaultTask 静态最坏栈链 +600 B,且本仓库无携带旧档的设备 | -| 2026-09-14 | v2.1:存储迁移至**通用配置文件** `/config.ini`(INI `[network]` 段,cfg_file 引擎:逐键校验 / 外科手术式保存 / 原子写 / 旧档首启迁移 / 沉降轮询);`net_cfg_store.*` 弃用(由 `cfg_file_store.*` 取代);对外 API 不变 | -| 2026-09-10 | MAC 显示改为常识格式 **`A4:94:B6:12:34:56`**(冒号分隔,17 字符);页面布局左移(名 x=4 / 值 x=54)以容纳 102px 宽度,编辑光标段偏移随之为 3i | diff --git a/docs/文档规范.md b/docs/文档规范.md index b0662849..2d3c5dfa 100644 --- a/docs/文档规范.md +++ b/docs/文档规范.md @@ -264,6 +264,8 @@ **章节引用(D 类)另有的跳过**:昵称式引用(「内存方案 §2.1」)、非紧邻写法、变更记录小节内的历史指称、外部手册编号(RM0090 等)、目标文档本身不用数字编号标题。 +> 「变更记录小节内的历史指称」这条跳过规则为何还留着:2026-10-28 起新文档不再设该节(见 §5.1),它现在只为**保留变更记录的存量 5 篇**与 `scripts/archive/` 下的归档文档服务——历史行里的编号是「当时那个编号」,既不回改也不校验。 + > ⚠️ 状态词按**就近**(±40 字符)判定,不是整行——否则文件名本身含「不存在」「删除」等字样时会误豁免同行的其它真实引用(2026-09-25 实测修正)。 ### 4.4 生成物与生成器:必须同一笔提交(`generated-fresh`) @@ -316,7 +318,7 @@ | **一级标题** | 文档首行为 `# 标题`,标题即主题,不写"文档""说明"等冗余后缀 | | **开篇引言** | 可选 `>` 引用块,写明**适用对象 / 阅读前提 / 相关文档** | | **章节编号** | 多章节文档用 `## 1.` `### 1.1` 编号,便于交叉引用(`§3.2`) | -| **变更记录** | 设计类、流程类文档**建议**末尾保留「变更记录」表(`日期 \| 变更 \| 说明`) | +| **变更记录** | **2026-10-28 裁定:新文档不再设「变更记录」节**——文档只写现状、改了什么是正文说了算,改动过程查 `git log`。**例外**(整表保留、被别处当台账或唯一证据出处引用的 5 篇):`docs/子系统设计/看门狗设计说明.md`、`docs/子系统设计/配置文件设计说明.md`、`docs/内存管理/RAM预算台账.md`、`docs/UI设计/内容页架构.md`、`docs/环境与部署/本地工具路径环境变量方案.md` | ### 5.2 新增文档检查清单 @@ -376,8 +378,4 @@ ## 变更记录 -| 日期 | 变更 | 说明 | -|---|---|---| -| 2026-09-25 | 建立本文档 | 正式确立目录/命名/编码/链接/门禁/结构与写作约定;承接 D-6(去空格)与 D-7(一致性门禁),配套交付 `scripts/check_doc_links.py`、`scripts/gen_task_table.py` 两个门禁脚本与 `doc-links`/`task-table` 两个 pre-commit 钩子 | -| 2026-09-25 | 文件名风格统一(D-6 剩余) | `代码规范/嵌入式C语言代码规范(V1.0).md` → `嵌入式C语言代码规范_V1.0.md`(全角括号 → 下划线),同步 5 个文档 + 1 个脚本共 9 处引用;§1.2 明确禁用全角括号与版本号写法;`docs/芯片手册/` 作为外部资料例外 | -| 2026-09-26 | 体积档门禁落地(D-7 第三档) | 交付 `scripts/check_mem_numbers.py` + pre-commit `mem-numbers` 钩子;§4.2 增「受管区域(锚点)」与「陈旧数字扫描」两节,记录误报取舍 | +> (本文件不再记流水账:改了什么是正文说了算,改动过程查 git log。) \ No newline at end of file diff --git a/docs/架构设计/图形绘制流程.md b/docs/架构设计/图形绘制流程.md index 0d9820ae..58e29827 100644 --- a/docs/架构设计/图形绘制流程.md +++ b/docs/架构设计/图形绘制流程.md @@ -133,16 +133,3 @@ sequenceDiagram - [ ] 引用它的 `.md` 里图片**相对路径**正确(能显示)。 - [ ] 脚本 + 产物 `.svg` **一并**暂存(产物入库)。 - [ ] `pre-commit run --files <脚本> ` 全过(无乱码 / 行尾空白 / 编码 OK)。 - ---- - -## 六、变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-09-11 | 创建:统一图形绘制流程(选型 / SVG 生成器 / Mermaid / 约定 / 检查清单);新增 `tools/arch_diagram/gen_frame_svg.py`(通用协议帧图)+ `docs/images/RemoDispBus帧格式.svg` | -| 2026-09-11 | 新增专门配图目录 `docs/images/`:收拢 `docs/` 根与 `docs/UI设计/images/` 下 5 张 SVG;同步更新 3 个生成器 OUT 路径、4 处文档图片引用、`AGENTS.md` 与 `.gitignore`(PNG 预览规则);流程沉淀为 `draw-diagram` skill | -| 2026-09-11 | 存量 ASCII 框图清理:`STM32F4-Base存储架构说明.md` 两图(存储栈分层 / 物理分区布局)重绘为 SVG(生成器家族新增 `gen_storage_stack_svg.py` / `gen_partition_svg.py`);`RemoDispBus协议与接收设计说明.md` 删 ASCII 帧图(SVG 帧格式图已在,信息无损失);`测试说明/CH395F_Test_Guide.md` 4 图(2 组件架构 + 2 会话时序)转 Mermaid | -| 2026-10-22 | 澄清 §派生物一句:`simulator/tests/ref/` 下作为像素黄金参考的 `.bin` 已入库,只有派生的 `.png` 目检图仍不入库(原表述把两者混为"参考图不入库",会诱导后来者把整个目录继续忽略掉) | -| 2026-10-27 | 新增 `gen_adc_frontend_svg.py` → `docs/images/ADC前端电路.svg`:把 `docs/硬件平台/ADC通道映射说明.md` §7.1 与 `docs/测试说明/ADC前端注入验证流程.md` §2 的 ASCII 拓扑图换成 SVG。ASCII 版把滤波支路画成挂在信号节点下的一根竖线,读起来像 2:1 分压——恰是要否掉的结论;SVG 把 `ADC7` / `ADC7_GND` 画成两个节点并加 STM32 侧对照面板。生成器沿用 §3.2 约定(纯标准库 / `html.escape` / `newline="\n"` / `ElementTree` 自检 + 文字溢出预检);目检用无头 Chrome 截图完成(`cairosvg` 未装,截图不入库) | -| 2026-10-27 | 新增 `gen_adc_code_scale_svg.py` → `docs/images/ADC码值刻度.svg`:给 `docs/测试说明/ADC前端注入验证流程.md` §4 的「码」定义配图。两张刻度尺上下对照,标出 `11430 码 ≈ 1.744 V`(TPAFE)与 `1000 码 ≈ 0.806 V`(STM32),把"同一整数在两片转换器上代表不同电压"变成可见的,避免台架抄数时混用两套 LSB | diff --git a/docs/架构设计/项目架构总览.md b/docs/架构设计/项目架构总览.md index 925bd31f..a3a5f129 100644 --- a/docs/架构设计/项目架构总览.md +++ b/docs/架构设计/项目架构总览.md @@ -343,30 +343,3 @@ flowchart LR | 驱动已知陷阱 | `docs/问题记录/{CH395F,GD5F2GQ5UE,SD2506}_Trap_Records.md` | | 各模块测试指南 | `docs/测试说明/` | | 代码规范 | `docs/代码规范/` | - ---- - -## 10. 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-09-10 | 初版:六层全景架构 + 任务/就绪屏障 + 启动时序 + 存储栈 + 网络栈 + UI 分层 + 目录组织 | -| 2026-09-10 | §1 全景分层架构重绘:由"36 节点 + 跨层虚线"改为**分层色带(每层一框)+ 职责表 + 跨层依赖表**,消除连线交叉、提升可读性 | -| 2026-09-10 | §1 再改为**手绘 SVG**(`tools/arch_diagram/gen_arch_svg.py` → `项目架构总览.svg`:分层色带 + 模块芯片 + 单向下箭头,布局确定);PNG 预览本地渲染、不入库 | -| 2026-09-10 | `net_cfg` 分层定位修正:按项目规划归入 **① 应用层**(原列在 ③ 服务/中间件);SVG 与 §1.1 表同步(模块物理路径仍在 `Drivers/BSP/NETCFG/`) | -| 2026-09-10 | §1 布局修正:**应用层与 UI 层同级并列**(同一行并排,均向下依赖);生成器数据由"每层一行"改为 `ROWS`(行内可放多个并列层),顶层两框各引一条向下箭头 | -| 2026-09-10 | §1 层级重定(按项目规划):**① 业务层**(改名,原"应用层")为**顶层**,含 `net_cfg`(被 UI 与基础服务共用)+ 业务编排;**② UI 层与 ③ 基础服务层同级并列**其下;`time_sync` 归基础服务层 | -| 2026-09-10 | §1 定稿(严格版):**① 业务层顶层仅 `net_cfg` 一块**;`app_main`/`sys_clock`/`sys_events`/`app_cfg`/`task/*`/`util/*` 并入 **③ 基础服务层**(任务编排 + 网络/存储/图形);② UI 层与 ③ 同级并列 | -| 2026-09-10 | §1 新增 **④ 中间件层**(通用库 / 协议栈:`net_socket`·`net_select`·`lftpd`·`FatFs`·`nand_ftl`·`LVGL`·`util`),位于 ③ 基础服务层与驱动层之间;③ 基础服务层收敛为**应用侧服务与编排**(`app_main`·`sys_clock`·`sys_events`·`app_cfg`·`task/*`·`time_sync`);层号顺延至 ⑦ 硬件 | -| 2026-09-10 | `lftpd` 由 ④ 中间件层移入 **③ 基础服务层**(FTP 视为应用侧服务);中间件层余 `net_socket`·`net_select`·`FatFs`·`nand_ftl`·`LVGL`·`util` | -| 2026-09-10 | §2.2 就绪屏障图由 Mermaid 改为**手绘 SVG**(`tools/arch_diagram/gen_barrier_svg.py` → `就绪屏障.svg`):三栏(生产者 / 事件组 / 消费者)+ 水平对齐 + All 汇合点,消除原图 9 条边的交叉;PNG 预览本地渲染、不入库 | -| 2026-09-13 | `sys_clock` 由 ③基础服务层改归 **④中间件层**(通用平台时间服务,日志/文件/对时共用;文件移入 `App/util/` 与 crc/ringbuf 同目录,include 路径不变):`FatFs` → `sys_clock` 成为**层内引用**,工程反向依赖消除;同日新增的 §1.2 "反向依赖例外" 条目撤销 | -| 2026-09-14 | 通用配置文件(P3):网口配置存储由 `/cfg/netcfg.bin`(NCFG 二进制)迁移至 `/config.ini`(INI `[network] 段`,`App/cfg/cfg_file` 引擎 + `cfg_file_store` 双端后端);`net_cfg` 对外 API 不变;旧档首启自动迁移;`cfg_file` 列为 MCU/模拟器共享源码 | -| 2026-09-14 | 运行/自检记录:新增 `App/log/sys_log`(定长 64B 文本记录引擎,MCU 后端 `/log/run.log`·`selftest.log`,defaultTask 唯一写者)+ UI 页面插件 `ui_page_runlog`/`ui_page_selftest`(动态列表)+ `ui_standby` 待机屏(空闲超时切入);密码页错误提示;字体 111→122 字(217 字形);详见 `docs/子系统设计/运行与自检记录设计说明.md` | -| 2026-09-21 | **§2.2 屏障语义修正 + FTP 永不监听缺陷修复**:`osEventFlagsWait` 默认消费所等位,就绪位(`NET_READY`/`STORAGE_READY`)被 netTask/uiTask/timeSync 先消费后,`ftpTask` 的 `WaitAll(两位)` 永不成立 → 任务永久阻塞、21 端口从未监听(静默);5 处就绪位等待统一加 `osFlagsNoClear`(命令位 `CFG_SAVE`/`NET_RECONFIG` 保持消费型)。同轮新增**栈可观测性**:`Src/freertos.c` 的 `stack_probe_poll`(串口 `[STACK]` 水位)+ `scripts/stack_report.py`(Keil 静态调用图 × 运行时水位,判定取两者更坏者);§2.1 任务表补齐实测栈数据并修正过期的 defaultTask/testTask 栈配置,§3 时序图补 `NoClear` 与 FTP 启动日志,§5 补 FTP 启动门/单客户端实测注意 | -| 2026-09-21 | **栈宽整改落地(内存方案 §1.4:lftpd 大局部缓冲静态化)**:`Drivers/BSP/NET/lftpd/lftpd.c` + `lftpd_log.c` 共 **9 处**大局部数组(`message[256]`/`response[512]`/`name[256]`×2/`buffer[1024]`×2/`read_buffer[512]`/`arg_buf[512]`/`client` 会话上下文/日志 `buffer[256]`)改为函数级 `static`(lftpd 单客户端、全部在 ftpTask 内串行);**ftpTask 实测峰值 3480 → 1184 B(余量 15% → 71%,判定 PASS)**,静态调用图 2528 → 472 B,代价静态 BSS +4,616 B(RW_IRAM1 82,048 / 131,072 B,余量仍 ~48 KB);§2.1 栈实测数据同步,原"涨栈到 1600 words"方案取消;FTP 功能回归 10/10 + 128KB 逐字节一致 | -| 2026-09-24 → 09-25 | **控制台单写者日志**(09-24 实证驱动:多任务并发日志字符级交错 + HardFault 脏指针直达 UART):4KB 环形缓冲 + defaultTask 唯一发送(行级原子 + 指针可控)+ 内核前/ISR/异常钩子有界直发回退 + `fputc` 收敛到单写者路径;09-24 初版实施于 `Src/usart.c` USER CODE 区,09-25 迁出至 `App/log/console_log.{h,c}`(HAL 生成文件不含应用代码),`dbg_log.h` 改 `#include "console_log.h"`(调用点零改动),`Src/usart.c` 恢复纯 CubeMX 形态;`@build` 0/0 + `@test` PASS;详见 `docs/子系统设计/控制台单写者日志设计说明.md` | -| 2026-09-25 | **defaultTask 任务体文件拆分**:`Src/freertos.c` 的 `StartDefaultTask` 任务体(存储 bring-up / 配置引擎属主 / 控制台单写者 attach+drain / syslog 落盘 / LED / 栈水位探针 `stack_probe_poll`)整体迁至 `App/task/default_task.c`(`default_task_func()`,与其余任务文件同址);`freertos.c` 恢复"CubeMX 接线 + 崩溃钩子"形态(719→361 行),`@build` 0/0 复验;栈配置属性仍定义于 `freertos.c`(`stack_report` 数据源不变) | -| 2026-10-10 | **删除旧档 NCFG 迁移(栈整改)**:`Drivers/BSP/NETCFG/net_cfg_legacy.{c,h}` 整体移除、`cfg_store_legacy_path()` 撤销,`net_cfg_load` 不再调用 `net_cfg_legacy_migrate()`;旧档 `/cfg/netcfg.bin` 若存在则被忽略(不读、不删、不迁移),配置回落工厂默认。理由:该一次性路径把整条配置写链挂进启动期调用图,defaultTask 静态最坏栈链 +600 B,本仓库无携带旧档的设备。同轮栈整改(未抬栈):defaultTask 静态最坏链 5312 → 2776 B / 实测峰值 3392 → 2152 B、timeSyncTask 1736 → 1024 B,6 任务全 PASS;代价静态 BSS +4,128 B | -| 2026-10-14 | **任务面与 NET 内部模块同步现状**:§1.1 补 ④ 中间件层 `net_events`/`net_pending`/`net_listener` 与 ③ 层 `algo/*`(语义取数与有效性~保护判据)、⑦ 硬件行去重(原两行重复编号且 UART5/TIM7 过期 → UART4/TIM3/ADC1);§1.2 增 NET 三内部模块与 algo→adcTask/protectTask 两条跨层依赖;§2.1 任务表 6 → 9 行(补 adcTask/iec104Task/protectTask,栈值按 `freertos.c` 校准:defaultTask 5120、netTask 3840、 timeSyncTask 2560、adcTask 2560、iec104Task 2560、protectTask 2048 B),栈实测更新至 2026-10-10~14 并注明堆已迁 CCM 扩容 56KB;§3 时序图补 adc_input/phasor/freq/prot_set/prot_elm 内核前初始化与 TIM3 节拍启动、新增 iec104Task/protectTask/adcTask 参与者;§5 网络栈图补三个 NET 内部模块与 iec104_serv 消费者,单客户端恢复窗更新为实测 p50 208 ms,登记 SEND pending 二期与 2026-10-14 FTP 实测;§7 目录树补 `algo/`/`fs/`、iec104_serv/protect_task、NET 三新文件;§9 补 Net 阻塞模型/网络自愈/algo/ADC 节拍/IEC104 五条专项文档索引 | -| 2026-10-28 | **UI 现状补同步(§3 图形/字体节)**:记录 5 页与运行报告页落地绑页,中文字体当前态 122 字/217 字形 → **218 字/313 字形**(本页上一版只同步到 UI 设计文档,架构总览这行漏了);页面数与字数的权威口径仍分别见 docs/UI设计/页面补齐规划.md §2.3 与 docs/UI设计/UI_中文字体生成与配置.md §7 | diff --git a/docs/测试说明/串口助手使用指南.md b/docs/测试说明/串口助手使用指南.md index f9c9a51b..6a483395 100644 --- a/docs/测试说明/串口助手使用指南.md +++ b/docs/测试说明/串口助手使用指南.md @@ -374,11 +374,3 @@ PowerShell 示例: Invoke-RestMethod http://127.0.0.1:18765/status Invoke-RestMethod -Method Post http://127.0.0.1:18765/send -Body '{"text":"ping"}' ``` - -## 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-09-15 | 初版:命令全参考(含实测输出)、日志规范、典型工作流、故障排查、FAQ、HTTP 附录;与 v1.1 实现(含 4 项 Windows 缺陷修复)对齐 | -| 2026-10-10 | 第一批可靠性修复同步:① `wait-idle` `no_data` 改按**本次增量**判(旧实现常驻 daemon 下永不触发)、加**首字节门** `--first-timeout-ms`、`rx_bytes` 改回本次增量;② `log` 改**先过滤后截尾**并加 `-i`/`--regex` + `scanned`/`matched` 计数(旧顺序即"log --grep 不可信"根因);③ `wait-idle` CLI 超时按 `--max-ms` 自动推导(不再需手工 `--timeout`),且超时不再被误判成"daemon 不可达"——旧实现会顺手拉起一个绑不上 HTTP 口的 daemon(`daemon.log` 里成串的 `listening`/`HTTP port busy` 即由此而来),现改为快速失败并提示调大 `--timeout`;④ 配置读取改 `utf-8-sig` 并显式回显 `config_error`;⑤ `status.daemon.exclusive_bind` 可验 HTTP 口独占绑定是否真生效 | -| 2026-10-10 | 第三批同步:① `ports` 加 `configured_present` + `hint`(换 USB 口/换机后 COM 号变了,系统里只有一个候选时直接给出口名;`open` 的 `port not found` 报错里也带 `[hint: ...]`);② `status` 加 `rx_age_ms`(判"板子是不是根本没在说话"不必自己减时间戳);③ `open` 幂等分支不再吞 `--dtr/--rts`——不带这俩参数时**保持当前 DTR/RTS**(旧实现把"没给"当 False,重开即静默拉低),显式给则现场应用并在 `note` 回显 `applied dtr=1` | diff --git a/docs/测试说明/串口助手设计说明.md b/docs/测试说明/串口助手设计说明.md index f68d4b8f..2713e81d 100644 --- a/docs/测试说明/串口助手设计说明.md +++ b/docs/测试说明/串口助手设计说明.md @@ -264,11 +264,3 @@ flowchart LR | 1 | Serial Studio MCP(GUI 依赖、导出文件定位问题) | 已清理(2026-09 前) | | 2 | Adancurusul/serial-mcp-server(Rust,MCP+CLI) | **被本工具取代**:二进制绑定用户档案(本机缺失)+ 无历史缓冲(采集窗口仪式) | | 3 | **serial_tool(本文,Python 仓库内)** | 当前方案 | - -## 13. 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-09-15 | v1.1 实施完成(S1–S6)。实施中实测发现并修复 4 个设计文档未覆盖的 Windows 实现级缺陷:① `SO_REUSEADDR` 在 Windows 允许多个活跃 socket 绑同端口 → HTTP 服务改**独占绑定**(`SO_EXCLUSIVEADDRPLACE`,发行版未导出时用数值 0x40 兜底)+ restart 强制确认旧实例死亡,防"already_running"假成功留下旧代码;② 写句柄 `"ab"` 追加模式在 Windows **禁读** → 溢出截头的"读尾部"必崩,改 `"a+b"`(自测用独立句柄故未暴露,真实 daemon 溢出路径已 E2E 验证);③ Windows 对**不存在**的 COM 口常报 Access Denied → 误报"port busy",改以 `list_ports` 枚举结果为"不存在/占用"判定准绳;④ 静默判据默认 2s 会截断 boot(任务间 3~4s 自然静默间隙),`-SettleMs` 默认改 8000ms。验收状态:A1–A5/A8 PASS(本机无 CH340,用 COM1 替代口验证;A5 溢出用进程内驱动真实 writer_loop 验证);A6/A7 正路径待硬件接入补验 | -| 2026-10-10 | **第一批可靠性修复**(5 项,均实测复现后修,`selftest` 加 T5/T6 共 6 个回归用例,16/16 PASS):① `wait_idle` `no_data` 改按**本次增量**判——旧实现比 daemon 累计 `rx_bytes` 是否为 0,常驻 daemon(本机 rx_bytes=1.2MB)下板子全程静默也返回 `idle:true`,@test 的 no_data 拦截形同虚设;同时加**首字节门**(首字节到达前不启动 settle 计时,`--first-timeout-ms` 兜底)并把返回的 `rx_bytes` 改为本次增量;② `log` 改**先过滤后截尾**(旧顺序 + 默认 `--tail 50` = 开机 marker 必然查不到,即 AGENTS.md"log --grep 实测不可信"的真根因),并加 `-i` / `--regex` 与 `scanned`/`matched` 计数;③ `wait-idle` 的 CLI 超时按 `--max-ms` 自动推导(旧版固定 5s 掐断长等待 → daemon.log 累积 16 次 `ConnectionAbortedError` traceback,现 handler 侧静音 `ConnectionError`);同时 CLI 不再把**超时**误判成"daemon 不可达"——旧实现超时与拒连走同一分支,一次 1s 超时就会额外拉起一个 daemon(新实例绑不上 HTTP 口,打 `HTTP port busy` 后退出;daemon.log 里 36 条 `listening` 大半是这种抖动攒出来的),现超时快速失败并提示调大 `--timeout`,只有真·拒连才自动拉起(`selftest` T7 锁);④ **§13 09-15 那条"独占绑定"其实是坏的**:`SO_EXCLUSIVEADDRPLACE` 是拼错的名字(真名 `SO_EXCLUSIVEADDRUSE`,值 **-5**),数值兜底 `0x0040` 是无效选项 → `setsockopt` 抛 `WinError 10042` 被 `except` 吞掉,独占从未生效;现改真名 + 失败打 WARN + `status.daemon.exclusive_bind` 可验(实测 true);⑤ 配置读取改 `utf-8-sig`(旧版遇 BOM 静默回退成"没配端口")并把解析错误显式回显;另加 `daemon.log` 超 1MB 原地保尾 256KB。顺带纠正一条误诊:进程列表里两个 `--serve` 是 **venv stub + 基解释器父子对**,不是"多 daemon 并存" | -| 2026-10-10 | **第三批:采集卫生 + 查询面**(`selftest` 加 T8/T9/T10,23/23 PASS):① 无换行残行 **64KB 封顶**(旧实现二进制垃圾无限攒内存,且把后续正常行拼成一条读不出的长行);② `open`/`close`/`clear` 作为**会话边界**丢弃残行(`splitter_gen` 计数,串口线程下轮生效,避免跨线程直接改缓冲)——旧实现上一段会话被复位截断的半行会粘进新会话首行;③ `cap_truncate` **按行边界**截头(旧实现按字节切 → 截出来的首行是半行,破坏"只含完整行"不变量);④ `open` 幂等分支不再吞 `--dtr/--rts`:不带参数 = **保持当前 DTR/RTS**(旧实现把"没给"当 False,重开即静默拉低线路),显式给则现场应用并回显;⑤ `ports` 回 `configured_present`/`hint`(单一候选才给,多候选不猜),`open` 的 `port not found` 也带 `[hint: ...]`;⑥ `status` 回 `rx_age_ms` | diff --git a/docs/测试说明/主机单测覆盖率口径.md b/docs/测试说明/主机单测覆盖率口径.md index df9ba8ff..30a27b9d 100644 --- a/docs/测试说明/主机单测覆盖率口径.md +++ b/docs/测试说明/主机单测覆盖率口径.md @@ -732,46 +732,3 @@ uint16_t ch395f_link_change_count(void); **不要盯着 88.2% 看**——那只是"已进分母部分"的自分数,新增大块未测代码时会**被摊薄而下降,那不是回退**(§5 已注明)。 3. 终点判据不是百分比,而是:**`untested_sources` 里剩下的每一条都能在 P3 那张表里找到归属**。 找不到归属的(既没进分母、也不属于"刻意不做")才是真窟窿。 - -## 变更记录 - -| 日期 | 说明 | -|---|---| -| 2026-10-23 | 新建。落地 `scripts/check_test_coverage.py` 与 `scripts/test_coverage_baseline.json`:首次实测 16 套全通过,并集 2552/2893 行(88.2%)、函数 193/207(93.2%),在测 19 文件 / 未触及 125 文件。同步销项原评审报告的 §4.8 空白 ①(覆盖率口径)与 §5.5 第 5 条前半、§0.1 / §0.4 / §7 对应行;`malloc(` 正则那条**同日也落地**(`coding-standard` CODE-RULE-20,见 `docs/门禁说明/coding-standard.md`)。**同日补 §2.1**:用户问「为什么不用 GCC」,实测本机 WSL2 Ubuntu 有 gcc/gcov 15.2.0,16 套单测在 gcc 下**全部编过且全绿**、`gcov -b -c` 确实给出分支覆盖(`nand_ftl.c` 分支 41.40%)——但换编译器=换分母(`sha256.c` gcc 105 行 vs MSVC 114 行),故默认通道不变。 | -| 2026-10-23 | **用户裁定:本仓只留 MSVC 一条覆盖率通道**,不建 gcc/WSL 第二条("后面可能引入更多问题")。实测数据与三条代价保留在 §2.1 当决策依据,§7 第 1 条把分支覆盖改记为**已接受缺口**,§8 下一步删掉"建通道"并写明重开该裁定的前提(必须先答"两份分母怎么对齐")。脚本与基线**不受影响**,仍是 `mscoverage` 一条路 | -| 2026-10-23 | **P1 第①批落地**(net_cfg / ftp_cfg / prot_set_store / task_prof 四个模块,104 条断言): - 套件 16→20、`files_tested` 19→23、分母 2,893→3,163;照出并修掉 `net_cfg` 的 WAIT 契约违背与 - "定长 11 字符"错记(详见 §9 落地进度) | -| 2026-10-23 | 新增 **§9 建桩优先级清单**:对 47 个未触及 `.c`(9,657 行)逐个画像(有效代码行 / 函数数 / -逻辑度=1−硬件符号密度 / 要桩的外部头 / 可复用现有桩 / fix 提交数),分为 **P1 13 个 2,617 行、 -P2 5 个 2,226 行、P3 29 个 4,814 行明确不做**(四条对得上:13+5+29=47、三段相加=9,657); -§8 下一步第 1 条改为指向本节 | -| 2026-10-24 | **P2 落地(三名队友并行,本分支)**:新增 5 套 **659 条断言**(`net_socket` 420 / - `console_log` 104 / `sys_log_mcu` 75 / `cfg_file_store_mcu` 34 / `soe_store` 26),套件 28 → **33** 全绿、 - `files_tested` 32 → **37**、未触及 `.c` **34 → 29**(恒等式 `29 = 0(P1) + 0(P2) + 29(P3)`,清单吃穿)、 - 分母 4,684 → **6,245**、`line` 85.8% → **89.3%**、`func` 90.1% → **92.2%**(这批**没有摊薄**:5 个文件 - 全都以 ≥98.7% 进分母)。新建共享假 FatFs `test/host/common/fatfs_fake.{h,c}`、共享假 CH395F 纯扩展 - (两个与真头不符的常量改成真值 + 加真头/假件常量文本核对闸,负例验证过)。补 `TC-HOST-*` 五族 - (22 → 27)与 `scripts/test_coverage_baseline.json` 重登(逐文件比对:下降 0 个)。照出 **10 条现状** - (重点:`sys_log_mcu.c:509~537` 卷忙整批丢日志、`net_socket.c` 同文件两套 IP 字节序、UDP 两个公开 API - 绕过 netTask、`console_log.c` 冷却哨兵与空位判据),**生产码一行未改**,逐条登记在 §9「P2 落地」表内待裁定; - §8 第 1 条同步改为「清单已吃穿」 | -| 2026-10-24 | **第 1 轮修复(同日续)**:用户裁定「全部修」,11 条现状里 **10 条已处置 + 1 条撤销**(`net_recv_locked` 那条是误报:非阻塞分支已能报 EOF,`:1885` 核过)。生产码改动跨 `sys_log_mcu.c`(整批回投 / 文案与节流 / 删不可达截断支 / 新增 `s_is_selfheal_code` 收敛自愈触发集 / post 两层留痕节流)、`soe_store.c`(注释更正 + 触发集同源更保守子集)、`cfg_file_store_mcu.c`(`FR_NO_SYSTEM` 不存在)、`sys_log.h`(读侧容量契约)、`net_socket.c/.h/net_types.h`(`s_addr` 统一到 POSIX 网络序 + UDP 两入口执行任务守卫,新码 `NET_ERR_NOT_IN_NETTASK = -12`)、`net_socket_sim.c`(同步 + 有意不对称)、`console_log.c/.h`(冷却独立标志 / 空位判据收进临界区 / 未初始化分诊 / 三本账 + 新读口)。**`@build` 0 错 0 警**(`Code=213720 RO=18860 RW=1204 ZI=131500`);全量闸 **33/33 全绿**、`5605/6275(89.3%)`、`396/429(92.3%)`、逐文件比对**下降 0**。设计文档同步:`控制台单写者日志设计说明.md`(§4.1 口径 + §13-O2 销项 + v1.5)、`运行与自检记录设计说明.md`(§4.4/§4.5 四条)、`STM32F4-Base存储架构说明.md`(§10.1 第 10 条推论)、`CH395F_Trap_Records.md`(TRAP-NET-21 后续)、`BSD_Socket_API_使用指南.md`(新增 §9.0 唯一约定)。本轮新增处置表、后续项 5 条、台架复验 7 条、新踩坑 8 条见 §9 | -| 2026-10-24 | **第 2 轮:测试字面量统一纯 ASCII**(单独提交):用户裁定「统一」,口径 = AGENTS 铁律「字符串字面量必须纯 ASCII」(无 BOM 文件里奇数个汉字会吞掉结束引号),中文只写注释。四名工人四组互斥目录并行,25 套 / 30 个 `.c` 的非 ASCII 字面量全部改成等值英文。粗口径普查 34 文件/1,552 行、严格口径(剥注释后取字面量)30 文件/**1,535** 行——差值那 4 个文件的命中全在注释里(`ns_peers.c`、`net_socket/stub/ns_rtos.h`、`common/ch395f_fake.h`、`common/fatfs_fake.c`),按口径**不改**。**Lead 独立终检五条硬判据**(TC 号集合不变 / 断言宏计数不变 / **行数与 HEAD 相等** / 代码区非 ASCII=0 / 字节卫生)→ **30 文件漂移 0**;每套断言数与 `--module` 覆盖率复量逐字不变(`net_socket` 887/889·53/53、`console_log` 199/200·16/16、`sys_log_mcu` 324/326·13/13、`adc_input` 103/103、`sys_clock` 100/100…),生产码零改动故基线不需重登。⚠ `@build` 对 `test/host/**` 无覆盖力,本轮证据只能来自 `*-unit-test` + `test-cppcheck` + `test-coverage`。方法、两版事故与协作纪律见 §9「第 2 轮」小节 | -| 2026-10-24 | **第 3 轮:台架必验项复跑 + 投递即拷贝(B 方案)**:用户裁定「上台架跑那 7 条必验项」。 - 三条**硬通过**——FTP PASV 的 227 报文按解出的 IP+端口真建数据连接并落地 512 KB;FTP 对端日志地址 - 正序(`connection received from 192.168.1.2:` + 端口号);阶段 7 的 NET 层 TCP 出向连接(建连 + - 64 B 回显字节级比对 + 关闭重连 ×3,`Phase 7: 26/28`,余 2 条是并发上限与该用例要求的「服务器须关」 - 互斥,均属既有现象)。**第一次全量超时不是固件问题**:直连网卡落在 Public 配置文件、且本机入站 - Allow 规则只绑被放行的解释器,两条坑 `docs/问题记录/CH395F_Trap_Records.md` 早已记下。第 5 条给出 - 非破坏性的**正/负双向证明**(卷忙窗口内 12/12 全落且序号严格递增;临时废掉 `-2` 支路只落 5/12, - 两轮独立复现一致),据此把待发条目由「只存指针」改为**投递即拷贝**(`+352 B ZI / +60 B Code`, - 串口水位 `heap free=15624 min_ever=8464`),回归钉在 `TC-SYSLOG-108` / `TC-SYSLOG-108b`。需要 - 破坏性窗口的第 6 条经用户裁定**暂停**;需物理拔接串口 TX 的子项另因 `dbg_console_tx_timeout()` - 未接读端而在台架上无能可见。台架与临时改动全部反向还原,设备回到产品构建并回读校验通过。 - 详见 §9「第 3 轮」与 `docs/子系统设计/运行与自检记录设计说明.md` §4.4;合回主干后以 `4288658` - 回填内存台账,主干 `pre-commit run --all-files` 39 项全绿。 | -| 2026-10-27 | 内容页黄金参考 **40 → 47 页**(遥测死区与系数 2 页落地,`simulator/tests/ref/` 实测 47 张:7 张新增、存量 40 张逐字节零漂移);本文件的当前态计数同步改 47,历史行 27 → 40 原样保留 | -| 2026-10-27 | 内容页黄金参考 **47 → 53 页**(通讯设置页落地并绑 `#page=comm`;判据 = `simulator/tests/ref/` 入库 `shot_*.bin` 实数 53 张,`git diff --name-status 31ca4a1f HEAD -- simulator/tests/ref` 实测只有 6 个 `A`、零 `M` ⇒ 存量 47 张逐字节零漂移);本文件的当前态计数已同步 | -| 2026-10-26 | UI 侧「不做」理由里的页数口径修正为 **内容页 27 页**(原写 18,与 `simulator/tests/ref/` 入库的 27 个 `shot_*.bin` 不符)| -| 2026-10-26 | UI 侧「不做」理由里的黄金参考页数 **27 → 40 页**(与 `simulator/tests/ref/` 入库 40 个 `shot_*.bin` 对齐);历史行保留 | diff --git a/docs/测试说明/卷锁单元测试说明.md b/docs/测试说明/卷锁单元测试说明.md index 9f56d905..2e6dddcf 100644 --- a/docs/测试说明/卷锁单元测试说明.md +++ b/docs/测试说明/卷锁单元测试说明.md @@ -164,7 +164,7 @@ test/host/vol_lock/vol_lock_test.c 1. 加一个 `static void tc_xxx(void)`;首行调 `fakes_reset()`; 2. 通过桩变量造场景:`s_new_fail = 1`(创建失败)、`s_wait_ok = 0`(等待超时); -3. `CHECK(cond, "描述")` 断言;在 `main()` 里注册(并同步更新本文档 §2 与变更记录)。 +3. `CHECK(cond, "描述")` 断言;在 `main()` 里注册(并同步更新本文档 §2)。 > ⚠ 用例之间**必须** `fakes_reset()`:`s_lock` 是全局态,不复位会把上一用例的句柄串进来。 @@ -201,11 +201,3 @@ test/host/vol_lock/vol_lock_test.c 竞争 → 恢复旋转饥饿喂狗点 → IWDG 误复位)只能由板端判据复现;本单测负责**防止契约被改坏** (例如有人把 fail-open 的 `return 1` 误改成 `return 0`,或给 fail-open 路径加上 `osMutexWait`)。 - ---- - -## 5. 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-10-10 | 创建;33 断言点全绿(`TC-VL-001..014`);覆盖 `init` 创建与幂等、`wait` 获取 / 超时 / 自动 init / **fail-open**、`release` 释放与判空;挂 pre-commit 钩子 `vol-lock-unit-test` | diff --git a/docs/测试说明/存储维护与容量恢复.md b/docs/测试说明/存储维护与容量恢复.md index 1221dc25..6380bc8c 100644 --- a/docs/测试说明/存储维护与容量恢复.md +++ b/docs/测试说明/存储维护与容量恢复.md @@ -121,12 +121,3 @@ - 另记一条定位事实:`gd5f2gq5ue_bbt_rebuild()` 在产品镜像里**不被链接**(map 明写 `Removing … (604 bytes)`,产品构建无调用者),只有本动作 A/B 的恢复构建会把它链进去——所以这条坑只在 **做恢复的时候**才存在,也正因如此平时不会有迹象。 - -## 5. 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-09-21 | 新建:A/B/C 三个维护动作;容量恢复原理(dhara checkpoint 坏块计数不清零)与全片擦除恢复路径(实测 95200 → 96064) | -| 2026-10-22 | 加 §4.1「根目录残留文件清理」(动作 D,与 A/B/C 区分):台架实测 27 个探针残留文件 / 262 KB 已清;判据 = 只删显式点名、保留 `/config.ini`、`/PROT_SET.BIN`、`/log`;清后 `@test` PASS + LIST 完整性回归 PASS | -| 2026-10-22 | 加 §4.2「自检台账清零,重建 S7 审计基线」:29 条历史记录(16 × `watchdog reset` + 13 × `heap low water`,10-10 → 10-14,两案均已结案)按用户决定删除;安全判据 = `sys_log_mcu.c` 每条记录开-写-关、不持常驻句柄;`run.log`/`wdev.log`/`soe.log` 属产品数据不动;顺带删掉孤儿 `/log/flushchk.bin`(32 KB、0..255 图案的写盘校验填充、全库零引用,删前留档);清后 `this-run` 与 `all` 两条判定路径都 PASS(清零前 `all` 是 29 条 FAIL) | -| 2026-10-23 | 加 §4.3:恢复流程的 ECC 开关改为"失败即中止 + 回读 B0h 验生效"——S-5 R4 上线照出来的第一处静默降级;给出运维判据——出现 `ECC restore FAILED` / `ECC not enabled` 即本次恢复不算完成,须断电重启重走 init;并记明该函数在产品镜像中不被链接(`Removing … 604 bytes`),只有恢复构建才有这条路径。顺带修正本文结构:`## 5. 变更记录` 原先误插在 §4.1 与 §4.2 之间,已移到文末(原位置会让 §4.2 变成 §5 的子节) | diff --git a/docs/测试说明/实机测试实施指南.md b/docs/测试说明/实机测试实施指南.md index bec40446..410c2c34 100644 --- a/docs/测试说明/实机测试实施指南.md +++ b/docs/测试说明/实机测试实施指南.md @@ -8,7 +8,7 @@ > **上游**:`docs/任务规划/README.md`(统一登记簿:P-x / N·S·T-x / > S1x·A-x / 阶段排序 / 诊断基线)· > `子系统设计/看门狗设计说明.md`(§7 验证记录)。 -> **约定**:本文事项完成后**先销上游登记**,再在文末变更记录留一行; +> **约定**:本文事项完成后**先销上游登记**,再把结论写进正文对应小节(本文不再记流水,过程查 `git log`); > 结论与证据沉淀进对应模块文档/问题记录(2026-10-02 台架窗口的完整取证链—— > IWDG PR/RLR 静默错配 / dhara resume 回滚 / ORE 僵尸通道——见 `看门狗设计说明.md` 2026-10-02 变更记录、 > `STM32F4-Base存储架构说明.md` §5.4.1、`控制台单写者日志设计说明.md` §12;修复已随 `930215f` 提交)。 @@ -30,7 +30,7 @@ | **步骤 7** | 工程卫生(P3 + 待核实项) | ✅ 已闭环 | §8 | > **每步出口**:`@build` 0/0 → 一轮 `@test` PASS → ST-LINK 全片回读 `No difference found` → -> 上游登记销项 + 文末变更记录留痕。 +> 上游登记销项 + 把结论写进正文对应小节。 > > **参考**(非执行步骤):§9 执行注意(实测陷阱)· §10 已完成事项与证据去向 · §11 引用闭环。 @@ -489,20 +489,3 @@ CH395F / STORAGE / GD5F,未含 RTC;怀疑 RTC 构建下 `testTask` 不被创 > **模拟器差距清单 §3 的六条"必须回真机"规则**决定"哪些改动**必须在本规划内验证—— > 改动触及 `Drivers/BSP/` 寄存器时序 / 模拟器差距清单的硬件专属项 / 配置变更检测与回调 / 网络重建并发 / 启动段 / 内存预算, > 一律在本文件找到对应批次。 - ---- - -## 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-10-27 | **§9 新增第 9 条「导航类自动化脚本默认零 ENTER」**(task-41):装置维护两页是两段式确认、第二次 ENTER 即真执行,故导航器禁止用 ENTER 从未知状态脱身;`scripts/board_ui_nav.py` 两条硬闸(`BACKOFF_MAX_E` ≤1 停机、`EXEC_PAGE_IDS` 默认拒绝且投键前即拒)做成 `--selftest-quick` 7 条常驻用例(假设备零注键,提交钩子跑这档),并钉住常量本身(上限调高 / 清单清空 / 默认翻成允许 → 报红,三条均实测能红) | -| 2026-10-03 | **步骤 5/6/7 闭环**:§6 GD5F 错误通道回归 PASS(`=== GD5F2GQ5UE Tests: 16/16 PASSED (failed=0) ===`;E-10/42/53/54/56/57 全部销项;顺带发现并修复编排器判据缺口——GD5F 的 TC-GD5F-704 故意触发 `[ERR]` 回落轮询,`run_all_suites.py` 改为**按套件**覆盖 `--forbidden`,与 `verify_log.py` 说明一致)→ §1/§6 改「✅ 已闭环」。§7 网络稳定性:**7.1 正常路径 ✅**(V5 120/120 FTP、零复位;负向路径转 `N-16`,台架拓扑受限);**7.2 N-2 ✅判据②/未复现判据①**(丢弃可观测性代码已有:`console_log.c` `s_con_drop`+`[ERR] CONSOLE dropped`、`sys_log_mcu.c` 队列满 `DBG_ERROR`、TX 僵尸通道自愈;V5 30 min 日志间隔分析最大静默 41s 且在开机边界、运行期 24 处 >10s 静默**全为 ~28s 且均在 `e02_probe` 窗口内**=N-17 同源)→ N-2 降级低风险观察项;**7.3 N-3 ⬜ 待 PC peer** → §1/§7 改「◐ 部分闭环」。§8 工程卫生:S5 `test-cppcheck` 钩子 PASS(仅 warning,排除模拟器桩);S4 `scripts/check_test_traceability.py` 落地并跑通(**30 处差异**,默认 warn-only);**待核实项 `TEST_SUITE_SELECTED` 实机核实 = 死代码**(全仓无使用点;`start_test_task()` 直接按宏分支,RTC 套件实际正常执行;真缺口 = 缺 `=== RTC Tests: N/M PASSED ===` 汇总行,已补 `test/board/sd2506_test_task.c` 并修正 Phase 级汇总累计问题;`test/board/test_config.h` 补齐 RTC 并注释"当前无引用")→ §1/§8 改「✅ 已闭环」 | -| 2026-10-03 | **步骤 3/4 闭环**:V2/V4/V5 台架验收通过(V2 任务饿死声明 stall 后 ≤2.5s `reset cause: IWDG`;V4 关中断死循环每 ~4.9s 稳定 IWDG 复位;V5 30 min / **120×FTP 全 PASS、零 IWDG 复位**)→ §1 总览与 §4 状态改「✅ 已闭环」,实施细节与证据移入 `子系统设计/看门狗设计说明.md` 变更记录。S11 堆告警代码落地、V5 全程未触发(`min_ever=4728 B` > 3072 B)→ §5 改「✅ 已闭环」,基线入 `内存管理/RAM使用分析与优化方案.md`。新登记 `待处理内容.md` **N-17**(V5 期间 44 次 stall 与 `e02_probe` 的 time_sync 30s 掉线+监听重建重合;隔离实验「仅 FTP 120s = 0 stall」证实探针场景专属) | -| 2026-10-03 | **重构为纯执行流程**:确立单一组织逻辑——本文 = **按顺序执行**的上板测试流程(步骤 1~7 + 状态标记),参考内容(§9 执行注意 / §10 已完成事项去向 / §11 引用闭环)后置。已完成事项(S7、A1~A4)的实施细节与真机证据**移出本文**,§10 只留「事项 → 去向」指针;§3 只留复跑命令与判据;§1「事项总览」改「执行流程总览」(步骤/状态列) | -| 2026-10-03 | **§3.2 去"待上板"框架**:A1~A4 均已落地并(A1 全项 / A2~A4 正常路径)经真机验证,删除"待上板事项(代码状态 2026-10-02 核对)"表述,改写为**客观事实记录**(列名改为「实施内容(已落地)」+「验证判据」);§1 总览 P0-B 状态由「待上板」改「✅ 已闭环」;抬头与 `docs/README.md` 索引同步为「真机验证状态」。残留事实(A2/A3/A4 故障分支 + A4 推流压测需专项窗口、N-16 拔线负向测试)仍如实保留 | -| 2026-10-02 | **更名**:`实机测试规划.md` → `实机测试实施指南.md`(与文档性质对齐——常设执行判据,非规划;引用面改造后仅剩 `docs/README.md` 索引 1 处,同步更新) | -| 2026-10-03 | **A2/A3/A4 实施 + 真机验证**:A2 = `net_task.c` 初始组网失败/重建失败 → 自检留痕 + 30s 周期重试(分片喂心跳,不自驻留);A3 = `ch395f.c` 3 处字节级 SPI 调用 `HAL_MAX_DELAY` → 100ms 有限超时 + 返回值检查 + 故障锁存 `ch395f_spi_byte_fault()`(首条记日志);A4 = `ui_net_sink.c` `remo_send` 校验 `net_send` 返回值,短写告警、连续 3 次失败阻断推送、新连接/网络重建解除(单连接模型不 `net_close` 数据 fd)。`@build` 0/0 + 静态门禁/主机侧纯逻辑单测全绿 + 模拟器构建通过;上板 `@test` PASS 7/7:A1 判定 PASS(含 IP 改→复位→持久→可达闭环,原档已恢复)、A2/A3/A4 正常路径零回归;自检清单 18→20 处(`net init fail` / `net reinit fail`);上板新数据:min_ever 下限 3,712 B(S11 阈值建议改 3,072 B)、开机良性 `MISS start` 行新增陷阱 §9.8;拔线负向/短写压测记 `待处理内容.md` N-16 | -| 2026-10-02 | 初版:无 MCU 窗口建立。汇总 P0-A 环境预检 / P0-B `@test`+S7 / P1-A IWDG V2/V4/V5 / P1-B S11 / P2-A S9 / P2-B P1-8+N-2+N-3 / P3 S5+S4+待核实项,共 **7 批**。每项含现状证据 / 目标 / 判据(量化)/ 执行步骤(精确命令)/ 风险回滚。18 处自检调用点清单 + 模拟器差距清单 §3 决策规则交叉引用 | -| 2026-10-02 | **台架窗口执行交接**:新增 **§0.5**(P0-A 通过;S7 已落地并提交 `4a4cd29`;P0-B 唯一阻断 = 0 字节 STOR → IWDG 误复位(round 3~6 后仍 5/5 复现);round 1~6 修复集摘要;**round 7 纯取证埋点设计 + 判据表**;P0-B 出口闭环(含 FTL flush 诱导式清台账);设备/台账/本地证据快照;**7 条实测陷阱**);§2.1 标注 S7 已落地、命令形态已确认 | -| 2026-10-02 | **文档改造**(同 `本地工具路径环境变量方案.md` 思路):删除一次性台架窗口状态(原 §0.5——round 1~9 取证全过程、快照、未提交警告:结论已沉淀 `看门狗设计说明.md`/`STM32F4-Base存储架构说明.md` §5.4.1/`控制台单写者日志设计说明.md` §12,修复随 `930215f` 提交)与规划框架(预估耗时/阶段措辞),重组为执行判据说明——§1 事项总览 / §2 环境预检 / §3 `@test` 闭环+自检判定+A1~A4 项 / §4 IWDG 注入长跑 / §5 堆告警 / §6 GD5F 错误通道 / §7 网络基线 / §8 工程卫生 / §9 实测陷阱 / §10 引用闭环;A1~A4 代码状态按当日代码核对改写(A1 已落地 / A2 部分 / A3、A4 未补码);A4 基线更新 264,284 B、A7 端口更正 COM6;原 §0.5.x 的 8 处代码注释、`待处理内容.md` 3 行、`看门狗设计说明.md` 变更记录、`docs/README.md` 同步重指向模块文档 | diff --git a/docs/测试说明/时间同步单元测试说明.md b/docs/测试说明/时间同步单元测试说明.md index a4eb4c7b..20099fad 100644 --- a/docs/测试说明/时间同步单元测试说明.md +++ b/docs/测试说明/时间同步单元测试说明.md @@ -186,7 +186,7 @@ test/host/time_sync/time_sync_test.c 再驱动被测函数。 3. **跳出任务循环**:生产 `time_sync_task` 是 `for(;;)`,无法自然返回。桩在脚本耗尽时 调 **`longjmp(s_jmp, N)`** 强行跳出(见 §4.1),跳出后正常断言。 -4. `CHECK(cond, "描述")` 断言;在 `main()` 里注册(并同步更新本文档 §2 与变更记录)。 +4. `CHECK(cond, "描述")` 断言;在 `main()` 里注册(并同步更新本文档 §2)。 --- @@ -229,11 +229,3 @@ Flash 写耗时等主机侧无法建模的因素。故: - 板端 ✅ 保证"实测缺口 + 调度抖动仍小于 1701ms"。 两者都过,这个心跳缺口才能闭环。 - ---- - -## 5. 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-10-10 | 创建;80 断言点全绿(`TC-TS-001..006` / `010..015` / `020..029` / `040..044`);覆盖分片喂狗延时、监听建立与退避、时间包重组(半包 / 粘连 / EOF / 真错 / 预算耗尽 / tick 回绕)、任务主循环(就绪屏障 / accept 轮询 / 代次变化重听 / 监听失败退避);修复静态量暂定定义合并缺陷;挂 pre-commit 钩子 `time-sync-unit-test` | diff --git a/docs/测试说明/模拟器差距清单.md b/docs/测试说明/模拟器差距清单.md index 815bc42c..eef10882 100644 --- a/docs/测试说明/模拟器差距清单.md +++ b/docs/测试说明/模拟器差距清单.md @@ -106,13 +106,3 @@ - **格式**:沿用本表列(差距 / 模拟器行为 / 真机行为 / 影响 / 回归补测)。 - **联动**:若该差距影响模拟器回归门禁的可信度,须同步在 `UI设计/UI_自动化测试流程.md` 引用本清单。 - **收敛**:当某差距被后续工作**消除**时,不删行——改标 ~~删除线~~ + 注明消除日期与提交,保留"曾经差在哪"的历史。 - ---- - -## 5. 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-10-28 | **新增 `§2.3`「开机账本 `boot_stats`」一行**(UI 补齐「运行报告」页联动):模拟器不编译 `boot_stats.c`(依赖 SD2506 用户 SRAM 与 `RCC_CSR`),运行报告页四个数在 PC 侧是 `simulator/main.c` 的固定假数据 → 像素黄金只验**显示口径**,累计 / 落盘 / 电池域掉电 / 跨重连语义必须回真机(触发条件 = 本批改 `simulator/main.c` 的 info 帧装配) | -| 2026-10-13 | **自愈收敛阶段 1.5 recv 语义主流化**:`net_socket_sim.c` 镜像 `net_recv_nb` / `net_recv_to` / `net_setblocking`,阻塞语义改按控制块 `blocking` 属性在包装层模拟(Winsock 句柄仍恒 FIONBIO)——N-3 的 `net_recv_to` 缺失部分**已消除**(划线留档),N-6 改写为"模式属性 + 包装层模拟";内部挂起模型(N-1)不变 | -| 2026-10-02 | 初版(S13):收录 6 条网络差距(N-1~N-6)、4 条日志/配置差距(L-1~L-4)、7 条硬件专属差距(H-1~H-7)、4 条"有意对齐"项。证据来源:`net_socket_sim.c` 文件头设计要点 + 双端导出函数逐一对比(MCU 有而 sim 缺 9 个)+ 各子系统文档既有记载汇总。§3 给出 6 条"必须回真机"决策规则 | diff --git a/docs/测试说明/测试开发标准流程.md b/docs/测试说明/测试开发标准流程.md index 2756c891..6a1efe1f 100644 --- a/docs/测试说明/测试开发标准流程.md +++ b/docs/测试说明/测试开发标准流程.md @@ -381,7 +381,7 @@ cmake --build simulator/build --config Debug # 0) 构建模拟器(须 0 警 - `simulator/tests/ref/*.bin`(像素黄金参考)**入库**(2026-10-22 起,新克隆即可跑回归;跨独立构建目录逐字节可复现已实测);派生的 `.png` 目检图仍不入库; - `--update` 有**误刷保护**(先跑文本层断言,失败即中止)——**未有意改视觉而 FAIL = bug,修代码,禁止刷参考掩盖**;基线入库后刷参考会在 `git diff` 里显形,必须逐页过目并在提交正文说明; - 刷新参考后必须重跑 `regen_ref_png.py` 重生成目检 PNG(否则旧 PNG 看似乱码); -- 门禁常量漂移:先确认新值合理(残留分解见 `菜单页面设计.md` §9.5)→ 更新常量 + 在 `UI_自动化测试流程.md` 变更记录登记; +- 门禁常量漂移:先确认新值合理(残留分解见 `菜单页面设计.md` §9.5)→ 更新常量 + 在 `UI_自动化测试流程.md` 正文写清当前常量值与它的实测来源; - **UI 新增中文文案提交前必须先跑 font-regen**(extract_cn → make_font → diff 检查):字符集 `ui_cn_chars.txt` 缺字则上机显示空白——**2026-10-15 起该约定已入门禁**(`font-charset` 钩子:源码在用字符 ∉ txt 或 txt ∉ 字体 cmap → 提交 FAIL,详见 `docs/门禁说明/font-charset.md`)。 --- @@ -474,8 +474,8 @@ flowchart TD | 事件 | 动作 | |---|---| | 测试发现陷阱(硬件 / 协议 / 工具链 / 时序) | 写入 `docs/问题记录/<模块>_Trap_Records.md`:现象 / 根因 / 修复 / 规避 | -| 代码变更影响判定标准 | 立即同步更新模块 Test_Guide,并登记该文档变更记录 | -| 有意改视觉 | 刷黄金参考 + 重生成目检 PNG + `UI_自动化测试流程.md` 变更记录登记 | +| 代码变更影响判定标准 | 立即把模块 Test_Guide **正文**改到与代码一致(现状说了算,不再记流水) | +| 有意改视觉 | 刷黄金参考 + 重生成目检 PNG + 把新口径写进 `UI_自动化测试流程.md` 正文对应小节 | | 新增测试工具 / 新标记 | `自动化测试流程.md` 命令清单登记(§4.2) | | 栈 / 堆预算相关改动或基线重采 | 把 `@test` 的 boot_log 快照(`%TEMP%\serial-boot-test\boot_log_*.txt`)存入 `docs/测试说明/boot_log_data/` 并在其 §3 清单登记(防临时目录被清理 / 长跑日志截头丢 `[STACK]` 行) | @@ -493,7 +493,7 @@ flowchart LR D -->|PASS| E["G3 ui-verify
(UI 改动时)"] E --> F["人工目检上机目检"] F --> G["提交
G0 门禁 + 逻辑提交"] - G --> H["沉淀:陷阱记录 /
文档同步 / 变更记录"] + G --> H["沉淀:陷阱记录 /
文档同步 / 正文现状化"] D -->|FAIL| I["[MISS]/[HIT] 定位"] I --> B ``` @@ -620,30 +620,3 @@ CI 就静默停摆(2026-10-11 实测 run 16~21 共 12 个 job 零日志)。 | `docs/测试说明/看门狗单元测试说明.md` | 看门狗判定状态机(主机侧纯逻辑单测) | | `docs/测试说明/系统时钟单元测试说明.md` | 系统时钟换算(主机侧纯逻辑单测) | | `docs/测试说明/配置文件单元测试说明.md` | 配置引擎解析/契约(主机侧纯逻辑单测) | - -## 变更记录 - -| 日期 | 变更 | -|---|---| -| 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__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 移植层 主机侧纯逻辑单测,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` 不读、不删、不迁移,配置回落工厂默认),该测试候选随之撤销 | -| 2026-10-02 | **S6**:`test/run_all_suites.py` 新增 **`--check-build`**(只编译不烧录,纯离机,不需要 MCU/串口/ST-LINK);新增 **§3.6.1** 说明其解决的问题(测试构建无独立门禁,2026-08~09 CH395F 套件实例)、判定语义与用法。**实测 4 套件全部 `BUILD_OK: 0 errors, 0 warnings`**(即 T-4 提到的"CH395F 不可编译"已修复) | -| 2026-10-02 | **S1-b + S2**:新增 **§4.2.1「主机侧纯逻辑单测适格模块台账」**(判据 + 模块状态表 + "两条实证":sys_clock / cfg_file 首测即各抓一处生产缺陷);§4.1 登记 `test/host/cfg_file/` 新单测。同步新增 [`配置文件单元测试说明.md`](配置文件单元测试说明.md)(含抓出的 `s_encode` 返回值误判 P0 缺陷记录) | -| 2026-10-02 | **S3 + S14**:§9.1 第 2 条改正(原文"强制跑 `mem-numbers`"自相矛盾 → 改为"按 `.map` 有无自适应跳过")并加 🔴 门禁盲区声明;§9.2 补 S3 结果可见性(`Tee-Object` 落盘 + `$GITHUB_STEP_SUMMARY` + `::notice::` 汇总行,不用 `actions/upload-artifact`)。另:§4.1 登记 `test/host/sys_clock/` 新单测(S1-a) | -| 2026-10-01 | 新增 **§9 CI 持续集成(Gitea Actions,T-6)**:`.gitea/workflows/ci.yml`(`static-gates` + `host-unit-tests`,Windows runner);**静态门禁 + 主机侧纯逻辑单测上 CI、板端测试套件/主机侧回归/人工目检留本地**;刻意不跑 `@build`、`.map` 缺失时自适应跳过 `mem-numbers`;新增 `scripts/ci_local.py` 本地等价命令(§4.1 登记);§1 补 CI 说明;`docs/任务规划/README.md` T-6 销项 | -| 2026-10-01 | §3.6 新增 **`test/run_all_suites.py`** 多套件回归编排(`try/finally` 无条件还原套件开关;T-5);`test/README.md` 同步 | -| 2026-10-01 | §3.2 断言宏改为**集中内核**:新增 `test/board/test_common.h`(`test_stats_t` + `TEST_CHECK_IMPL`/`TEST_REPORT_IMPL`),4 套件各自用一行宏绑定自身统计变量(T-4;零行为变化、零 RAM 增量、`@build` 0/0,四套件均 0/0 验证)。附 `test_common.h` 不 include `dbg_log.h` 的原因(`DBG_TAG` 冻结 → `#47-D`) | -| 2026-10-01 | 新增 §7.1 钩子 **`test-suite-switch`**(测试套件开关=产品构建,防测试固件静默提交)+ §3.1 铁律(跑完套件回归务必改回产品构建);依据 `docs/任务规划/README.md` T-1(测试架构评审 P0)。同步更新 `../代码规范/pre-commit使用说明.md` §2.13 | -| 2026-10-01 | §4.1/§4.2 更新:主机侧单测运行器统一走通用 harness `test/host/common/unit_test_harness.py`(T-3),模块运行器只做声明式配置;§6.2.1 新增套件汇总行校验(T-2) | -| 2026-10-01 | §4.2 补 **主机侧纯逻辑单测环境要求表**(MSVC `cl.exe` = 装了 VS 即有、与模拟器共用;Windows SDK;纯标准库 Python;缺失时退出码 2 且 pre-commit 钩子拦截)+ "不调 `vcvars64.bat`(`reg.exe` 受限)"原因说明;§4.1 工具清单标注该运行器需 VS。同步更新 `../环境与部署/项目部署环境要求.md`(§2.3 / §2.7 / 第 3、10 步 / 清单 / 下载表 / 速查表) | -| 2026-09-15 | §3.4 更新:P1-6 修复落地(基础线程策略)——USER CODE 区冗余 netTask 创建删除 + `net_task_func` 入口 `ENABLE_HW_LAYER_TESTS` 自挂起守卫;"代码事实/设计约束"按修复后现状重写(硬件层模式中断断言恢复安全、NET 层/产品仍按"netTask 恒在轮询"设计);彻底方案(`.ioc` 移除)经评估未采用。同日构建验证发现两处**存量**测试固件缺陷(与 P1-6 无关,A/B 对照确证):① `net_test_task.c` `s_rx_buf` 使用先于声明 → NET 层配置自 2026-08(88160a5)起不可编译;② 128KB 静态 RAM 预算溢出(产品镜像 123.6KB,HW 全阶段固件超 8.7KB、NET 固件超 ~28KB)——已立 P1-9/P1-10 跟踪 | -| 2026-09-13 | 重写:对齐现测试架构——统一 `test_config.h` 套件(旧版仅描述 CH395F 单套件与 `ch395fTestTask` 旧入口);新增 @test 自动化闭环、pre-commit 门禁、UI 模拟器五步门禁、主机侧工具约定;新增"测试构建下 netTask"已知问题(旧版"硬件层模式 netTask 不创建"表述与代码不符,改为设计约束并给出重构路径);修正附录路径(旧版 `docs/测试说明/CH395F_Test_Guide.md` 等已移入 `docs/测试说明/`);新增双端注册、内存预算、陷阱沉淀要求 | -| 2026-10-22 | §5.3 黄金参考纪律更新:`ref/*.bin` 入库(新克隆即可跑 UI 像素回归)、`.png` 仍不入库;补充"刷参考会在 `git diff` 显形,须逐页过目并在提交正文说明" | -| 2026-10-26 | 像素层页数口径修正为 **27 内容页**(判据 = `simulator/tests/ref/` 入库的 27 个 `shot_*.bin`;旧写「11」是页面扩充前的数字)。同类陈述同步在 `UI_自动化测试流程.md` 等六处改正 | -| 2026-10-26 | 三层断言表的文本层规模由「50 条」修正为 **242 条、覆盖 24 页**(现值取自 `simulator/tests/check_content_pages.py` 的 TEXTS 实跑计数;三张密码态无文本断言)| -| 2026-10-26 | 三层断言表同步 UI 三页落地后的真值:像素层 **27 → 40 内容页**、文本层 **242 → 310 条(覆盖 37 页)**;上方变更记录里的 27 / 242 属当日事实,保留不动 | -| 2026-10-27 | 三层断言表的像素层计数同步真值:**40 → 47 内容页**(判据 = `simulator/tests/ref/` 入库 `shot_*.bin` 实数 47 张 + `check_content_pages.py` 的 `PAGES` 47 项);文本层 310 条 / 覆盖 37 页仍是 2026-10-26 实跑口径,未随新增页重测,留待下次实跑回填;本条只加新行,历史行 27 → 40 原样保留 | -| 2026-10-27 | 三层断言表的像素层计数同步真值:**47 → 53 内容页**(判据 = `simulator/tests/ref/` 入库 `shot_*.bin` 实数 53;6 张新增是通讯设置页六态,`31ca4a1f..HEAD` 对 ref 目录只有 6 个 A、零 M)| -| 2026-10-28 | §9.1 那条 2026-10-11 审计里的钩子数(定义 18 / 只报 17 / 其中跳过 1)加「当时」二字锁死口径,不臆改成现值:本轮同步钩子计数实测口径 = YAML 解析条目 **51**,静态门禁实跑 **50** 条 + 提交信息门禁 1 条 = 51(三数同源),自查命令 → `docs/门禁说明/README.md` §2 | diff --git a/docs/测试说明/测试文档模板规范.md b/docs/测试说明/测试文档模板规范.md index 64206325..6a8e5587 100644 --- a/docs/测试说明/测试文档模板规范.md +++ b/docs/测试说明/测试文档模板规范.md @@ -38,7 +38,6 @@ ## 附录 A:通过/失败汇总矩阵 ## 附录 B:测试覆盖 vs 设计原则 ## 附录 C:API 覆盖(驱动类模块建议) -## 变更记录 ``` --- @@ -213,9 +212,11 @@ TC-{MOD}-{NNN} ### 7.6 文档维护(与代码同步) -- 代码变更影响用例 / 判定标准 / 日志文案 → **当天**更新本文档,并在变更记录登记(与 `测试开发标准流程.md` §7.3 同标准); +- 代码变更影响用例 / 判定标准 / 日志文案 → **当天**更新本文档正文对应章节(与 `测试开发标准流程.md` §7.3 同标准); - 测试发现陷阱 → 写入 `docs/问题记录/<模块>_Trap_Records.md`(现象 / 根因 / 修复 / 规避),并在本文档"已知陷阱与故障模式"章节留链接; -- 判定标准经实测修正 → 更新用例表并在变更记录注明修正原因。 +- 判定标准经实测修正 → 更新用例表,并把修正后的判据与实测依据写进正文(为什么这么判、拿什么证的),改动过程本身查 `git log`。 + +> **测试文档不再设「变更记录」节**(2026-10-28 用户裁定,口径见 `docs/文档规范.md` §5.1):文档只写现状,「哪天改了什么」由 `git log` 负责;例外只有被别处当台账 / 唯一证据出处的文档(那份清单也在 `docs/文档规范.md` §5.1)。 --- @@ -298,11 +299,6 @@ TC-{MOD}-{NNN} | API | 已覆盖 | 用例 | |-----|--------|------| - -## 变更记录 - -| 日期 | 变更 | -|---|---| ``` ### 8.2 附录模板 @@ -323,11 +319,3 @@ TC-{MOD}-{NNN} | API | 已覆盖 | 用例 | |-----|--------|------| ``` - ---- - -## 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-09-13 | 补充完善:模块缩写表更新为项目实际用法(`NET`/`GD5F`/`STO`/`RTC`/`FTP`,取代旧版 `PHY`/`NAND`,历史文档不回改);概述新增"套件与入口"与"回归接入"章节(衔接 `test_config.h` 套件互斥与 `@test` 闭环,标记须与串口实际输出逐字一致);用例表新增"机器可判"字段(四通道 + 人工目检层);类型枚举新增"集成测试";TC 序号约定"分阶段套件百位放阶段号"(TC-NET-601 = Phase 6);新增附录 C API 覆盖;陷阱引用路径修正为 `docs/问题记录/`;新增 §7.6 文档维护规范与文末变更记录章节 | diff --git a/docs/测试说明/相量层单元测试说明.md b/docs/测试说明/相量层单元测试说明.md index 4abc02f4..c5c3bbc8 100644 --- a/docs/测试说明/相量层单元测试说明.md +++ b/docs/测试说明/相量层单元测试说明.md @@ -165,7 +165,7 @@ test/host/phasor/phasor_test.c 1. 加一个 `static void tc_xxx(void)`;用 `gen_sine()` 造正弦窗、`frame_at()` 造整帧(喂实例层); 2. 驱动实例层三步:`sample_ring_push_frame()` → `phasor_run()` → `phasor_get()`; -3. `CHECK(cond, "描述")` 断言;在 `main()` 里注册(并同步更新本文档 §2 与变更记录)。 +3. `CHECK(cond, "描述")` 断言;在 `main()` 里注册(并同步更新本文档 §2)。 > ⚠ 实例层是**全局态**(双区 + 采样环),跨用例必须先 `phasor_init()`——它会同时 > `sample_ring_init()`,等价于"刚上电"。否则上一用例的环内容会串进来。 @@ -203,13 +203,3 @@ C03 二次谐波、C04 五次谐波;**本项目**按 V0.1 **有效通道**(` `k_inst[]` 每项为 `{name, sem, harm}`,`phasor_run()` 遍历该表取窗并计算。因此新增一个 相量实例(如「遥测谐波轨(可选)」的遥测谐波轨)**只需在表里加一行**,本单测的"实例数 == 5"与 "逐实例复核"两条断言会**自动扩展到新实例**——但需同步更新该常量断言。 - ---- - -## 5. 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-10-10 | 创建;52 用例(TC-PH-001..022)全绿;覆盖系数表 / 幅值·相位 / 谐波抑制与提取 / 频偏 / 采样环 / 实例层 / 滑动窗 / 双区交换 | -| 2026-10-10 | 补 TC-PH-030..034(`phasor_zero` 四字段清零 + `phasor_init` 双区清零 / 使用区与就绪标志复位 / 幂等)→ 57 用例;函数级覆盖审计 `App/algo` 三源共 20 函数、0 未覆盖;挂 pre-commit 钩子 `phasor-unit-test` | -| 2026-10-10 | §4.3 由"与规划表的一处待对齐"改为"实例数 4 → 5:规划表已对齐"——规划 §3.2 的全周傅氏相量层行同步为 **5 个实例**(并加注 4 → 5 的来历),`傅氏算法详解.md` §7 的"4 个实例"标注为**参考项目**口径 | diff --git a/docs/测试说明/看门狗单元测试说明.md b/docs/测试说明/看门狗单元测试说明.md index ba37f6b0..15eb9a01 100644 --- a/docs/测试说明/看门狗单元测试说明.md +++ b/docs/测试说明/看门狗单元测试说明.md @@ -4,7 +4,7 @@ > **测试类型**:**主机侧纯逻辑单元测试**(见 §1.5)——在 PC 上离线验证 > 判定状态机,零硬件、零烧录、秒级、不占 MCU 的 RAM。 > **状态**:✅ 已落地(47 断言,`@build` 0/0,已挂 pre-commit 钩子) -> **日期**:2026-10-01(2026-10-25 v1.5 按位分账改造,见变更记录) +> **日期**:2026-10-01(2026-10-25 v1.5 按位分账改造;改造史与设计依据见 `docs/子系统设计/看门狗设计说明.md` 变更记录——本文档不再设变更记录节) > **关联文档**: > [`../子系统设计/看门狗设计说明.md`](../子系统设计/看门狗设计说明.md)(被测行为的设计依据)、 > [`测试开发标准流程.md`](测试开发标准流程.md)(测试分层与门禁总览)、 @@ -175,13 +175,3 @@ if (s_miss_streak >= WD_MISS_TOLERANCE) { DBG_ERROR("[WD] task stall: ..."); } > 本单测**不能**替代板端验证:IWDG 实际溢出时间、LSI 频率漂移、`SHCSR`/复位原因 > 寄存器的真机行为,仍需 `@test` 台架闭环确认。 - ---- - -## 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-10-25 | **v1.5 按位分账同步**:停喂判据从复合连击改为**单个必需位**连击(设计说明 §2.2/§3.2/§5.3),TC-WATCHDOG-004/005/006/008/013 断言按新语义改写(缺席窗在容忍下照常喂)、新增 TC-WATCHDOG-017(交替缺席零误报)/ TC-WATCHDOG-018(同位连击必报 + 账本重启),39→47 断言;顺带修正 TC-WATCHDOG-003 行陈旧的 `0x37`(B4/B5 后应为 `0x1F7`) | -| 2026-10-01 | §1.3/§1.4/§1.5 更新:工具链逻辑抽取到通用 harness `test/host/common/unit_test_harness.py`(T-3),本模块 `run_unit_test.py` 改为**声明式** `TestBuild`(原 170 行 → 55 行);hooked 触发范围加 `test/host/common/unit_test_harness.py`。行为与退出码契约不变(39/39 PASSED) | -| 2026-10-01 | 创建:看门狗判定状态机主机侧单元测试(39 用例)+ 平台层抽取(`task_watchdog.h` 末段三个 `__weak` 钩子)+ pre-commit 钩子 `watchdog-unit-test`;记录两处已知行为(stall 复报、测试隔离) | diff --git a/docs/测试说明/系统时钟单元测试说明.md b/docs/测试说明/系统时钟单元测试说明.md index 63dc690c..1e04a82e 100644 --- a/docs/测试说明/系统时钟单元测试说明.md +++ b/docs/测试说明/系统时钟单元测试说明.md @@ -253,11 +253,3 @@ TC-SYSCLK-019 的期望星期由 Python `datetime.date(...).weekday()` 独立生 > 本单测**不替代**板端验证:I2C 时序、BCD 编解码、掉电保持、温度读等真机行为, > 仍需 `@test` 台架闭环确认。 - ---- - -## 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-10-02 | 创建:`sys_clock.c` 主机侧单元测试(20 用例 / 100 断言点)+ 强符号桩(零侵入生产代码)+ pre-commit 钩子 `sys-clock-unit-test`。**首次落地即抓出 Zeller 星期公式缺陷(1970~2099 全部日期星期皆错)并修复**,`@build` 0/0 | diff --git a/docs/测试说明/自动化测试流程.md b/docs/测试说明/自动化测试流程.md index 16e0924d..63c00279 100644 --- a/docs/测试说明/自动化测试流程.md +++ b/docs/测试说明/自动化测试流程.md @@ -139,17 +139,4 @@ ## 变更记录 -| 日期 | 变更 | -|---|---| -| 2026-09-13 | 「UI 屏幕自动化(当前缺口)」更新:UI 初始化 DBG 打印已实现(`ui_task.c`),屏幕内容已纳入模拟器像素回归;测试分层与门禁见 `测试开发标准流程.md` | -| 2026-09-15 | 采集机制整体切换:serial-mcp-server(采集窗口/first-byte/EOF 重试)→ 仓库内置 Python 串口助手(daemon 常驻全量日志 + `wait-idle` 静默判据 `-SettleMs`/`-MaxWaitMs`);`serial_capture.ps1` 删除,流程/脚本清单/失败模式表同步 | -| 2026-09-21 | 默认 Forbidden 增补 `[ERR]`:固件 `DBG_ERROR` 前缀是 `[ERR]`(≠ `ERROR` 子串),此前驱动/模块错误日志不会被自动闭环拦截;`verify_log.py` / `run_boot_test.py` 默认值同步,测试套件运行需显式放宽 | -| 2026-10-10 | 采集链可靠性修复(serial_tool 第一批):`wait-idle` 的 `no_data` 改按本次增量判(旧实现常驻 daemon 下永不触发,"烧录后无数据"这一失败模式实际测不出来)+ 首字节门 `--first-timeout-ms`(`run_boot_test.py` 新增 `--first-wait-ms`,默认 12000);`log --grep` 改先过滤后截尾(旧顺序导致 marker 必然查不到)并加 `-i`/`--regex`;`wait-idle` CLI 超时自动推导,不再需手工 `--timeout`;HTTP 口独占绑定修正(旧选项名/数值均无效,实际未生效) | -| 2026-10-10 | **第二批:闭环补上"烧进去的是哪份镜像"与"跑的过程中有没有偷偷复位"**:① 固件身份戳——`App/app/app_main.c` 开机打印 `fw build: <__DATE__> <__TIME__>`,`run_boot_test.py` 从待烧 hex 里抠出该串追加成 Required 标记(旧镜像/错镜像此前所有固定标记照样全中);② 烧录回读校验进闭环——`reset.bat` 新增 `cmp` 子命令(`-CmpFile` 全片比对),采集后自动跑,不一致 exit 2;实测 `-CmpFile` 连接时会复位目标,故必须排在采集之后;③ 启动锚点计数——`verify_log.py` 新增 `--max-boot-count`/`--boot-marker`/`--expect-reset-cause`,`reset cause:` 出现 0 次或 >1 次判 FAIL;④ 修 `--flash-cmd` 带参数时预检必 missing、以及 `cmd /c` 对含空格路径(本仓库目录名 `DTU Code`)的引号解析把回读假判成"芯片不一致"(改为直接 CreateProcess 跑 .bat)。真机验证:完整烧录闭环 PASS(含戳匹配 + `No difference found` + 锚点 x1);伪造戳 → 其余标记全中仍 FAIL | -| 2026-10-10 | **第三批:判定可读性 + 时序 + 采集卫生**:① Forbidden 命中逐行打印行号+内容(旧只报条数);② boot_log 每行加 `[+Nms]` daemon 毫秒时基(`--raw-log` 关闭),据此量开机耗时(实测 `net init: OK` = **+537ms**;`--max-boot-ms` 默认 0 只报告);③ `--require-order` 标记先后顺序校验(全中但失序此前不可见);④ `--json` 结构化判定(退出码不变);⑤ `--keep-out`(默认 20)清理 out 目录旧产物(本机曾堆到 31+7 份);⑥ daemon 侧:无换行残行 64KB 封顶 + open/close/clear 会话边界丢弃残行 + 截头按行边界对齐(旧实现截出来的首行是半行)+ `open` 不带 `--dtr/--rts` 时保持现状、显式给则现场应用;⑦ `ports` 回 `configured_present`/`hint`,`status` 回 `rx_age_ms`。selftest 23/23、verify_log 离线回归 17/17、真机闭环 PASS | -| 2026-10-11 | **身份戳覆盖测试宏**(N-31 复测时发现):切 `test/board/test_config.h` 的套件宏后 `app_main.c` 未被重编,测试镜像与产品镜像顶着同一个 `fw build:` 戳 → 戳校验对"两种构建互换"失明(当时只有 `-CmpFile` 回读发现镜像不同)。修复:`app_main.c` `#include "test_config.h"`(头依赖 → 改宏必重编、戳必刷新)+ 戳串追加 ` suite= dstr=`(`FW_BUILD_VARIANT`,戳内容本身区分构建)。实测:`20:36:11 suite=NONE dstr=off` ↔ `20:36:40 suite=CH395F dstr=on`;`@test` 闭环对新格式 PASS(脚本无需改动,戳按"标记后连续可打印 ASCII"抠取)。失败模式表补一行:戳命中但 `suite=` 与要跑的套件不符 = 烧了产品镜像 | -| 2026-10-22 | **自检台账判据改为「只看本次启动新增」**(修两处叠出来的假绿):① 抓取用的 FTP 登录还写着匿名,而设备自鉴权落地起就没有匿名通道 → 抓取**必然** 530 失败,旧实现又把"抓取失败"和"设备侧无此文件"都返回空、一律按"无记录 → PASS"处理 → `--require-selftest-pass` 从写下那天起没真正看过文件;② 就算抓到了,`/log/selftest.log` 是 512 条环形累计历史,"非空即 FAIL"在任何做过故障注入/长跑的设备上永远不可能 PASS(本仓台架实测 29 条记录全是 2026-10-10 ~ 10-14 留下的)。现在:烧录前取基线、启动后只判新增;抓取失败 / 无数据源 / 基线被环覆盖 **一律 FAIL**;`--selftest-scope all` 保留累计口径用于审计与首次建基线;FTP 凭据 `--ftp-user/--ftp-pass`(默认出厂 admin/admin)。凭据与判据两处都过真机:`this-run` → PASS(无新增)、`all` → FAIL(累计 29 条)、无 `device_ip` → FAIL(无数据源)。 | -| 2026-10-27 | 内容页黄金参考 **40 → 47 页**(遥测死区与系数 2 页落地,`simulator/tests/ref/` 实测 47 张:7 张新增、存量 40 张逐字节零漂移);本文件的当前态计数同步改 47,历史行 27 → 40 原样保留 | -| 2026-10-27 | 内容页黄金参考 **47 → 53 页**(通讯设置页落地并绑 `#page=comm`;判据 = `simulator/tests/ref/` 入库 `shot_*.bin` 实数 53 张,`git diff --name-status 31ca4a1f HEAD -- simulator/tests/ref` 实测只有 6 个 `A`、零 `M` ⇒ 存量 47 张逐字节零漂移);本文件的当前态计数已同步 | -| 2026-10-26 | UI 屏幕自动化段的页数口径修正为 **27 页**黄金参考(与 `simulator/tests/ref/` 入库的 27 个 `shot_*.bin` 对齐;旧写 11)| -| 2026-10-26 | UI 屏幕自动化段的黄金参考页数 **27 → 40 页**(`simulator/tests/ref/` 入库 `shot_*.bin` 实测 40 个);历史行保留 | +> (本文件不再记流水账:改了什么是正文说了算,改动过程查 git log。) \ No newline at end of file diff --git a/docs/测试说明/配置文件单元测试说明.md b/docs/测试说明/配置文件单元测试说明.md index 215878d4..7aef8344 100644 --- a/docs/测试说明/配置文件单元测试说明.md +++ b/docs/测试说明/配置文件单元测试说明.md @@ -282,7 +282,4 @@ if (s_encode(p_key, ..., v, sizeof(v)) >= 0) { ## 6. 变更记录 -| 日期 | 变更 | -|---|---| -| 2026-10-02 | 创建;20 用例 / 139 断言点全绿;抓出并修复 `s_encode` 返回值误判 P0 缺陷(外科手术保存死码);挂 pre-commit 钩子 `cfg-file-unit-test` | -| 2026-10-25 | 随配置引擎新增 `CFG_VAL_INT`(「数据可信」有符号零点类型)补登记 TC-CONFIG-006~008;套件 200/200 PASS | +> (本文件不再记流水账:改了什么是正文说了算,改动过程查 git log。) \ No newline at end of file diff --git a/docs/环境与部署/并行任务工作树方案.md b/docs/环境与部署/并行任务工作树方案.md index d6751960..05217743 100644 --- a/docs/环境与部署/并行任务工作树方案.md +++ b/docs/环境与部署/并行任务工作树方案.md @@ -144,7 +144,7 @@ D:/Code/DTU Code/ | 文件 | 冲突原因 | 回收时的处理 | | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | | `docs/任务规划/`(整个文件夹) | 全项目唯一登记簿,每个任务都要销项 | 由主工作树统一改,任务分支不碰 | -| `AGENTS.md`、`docs/README.md`(索引/登记类) | 每个任务都要在「按主题查哪份文档」表、`docs/README.md` §9.2 环境表、变更记录里**各加一行** → 两任务必冲突(2026-10-12 实测:主工作树里本任务的行与他任务的行已并排混在**同一 hunk**) | 由主工作树统一追加;提交时**只 `git add` 本任务的行**(`git apply --cached` 选择性入库),勿整文件 `git add` | +| `AGENTS.md`、`docs/README.md`(索引/登记类) | 每个任务都要在 AGENTS.md 的「按主题查哪份文档」表、`docs/README.md` §9.2 环境表、`docs/README.md` 的文档索引表里**各加一行** → 同一张表的新增行两任务必撞(2026-10-12 实测:主工作树里本任务的行与他任务的行已并排混在**同一 hunk**)。变更记录那一路**不再是冲突面**:2026-10-28 起新文档一律不设变更记录节(`docs/文档规范.md` §5.1),存量也只剩 5 篇台账/证据文档 | 由主工作树统一追加;提交时**只 `git add` 本任务的行**(`git apply --cached` 选择性入库),勿整文件 `git add` | | `AGENTS.md` 的 `TASK_TABLE` 块 | 生成物,两个任务都抬栈就冲突 | 合并后重跑 `scripts/gen_task_table.py` **重新生成**,不手工并 | | `MDK-ARM/STM32F407-Demo.uvprojx` | 新源文件注册 + UV4 自动改写 | 手工并 `` 条目 → 重跑 `registration-check` → `@build` | | `.pre-commit-config.yaml` | 新增主机单测要加钩子 | 并集处理 | diff --git a/docs/环境与部署/项目部署环境要求.md b/docs/环境与部署/项目部署环境要求.md index f593a334..555cc0f5 100644 --- a/docs/环境与部署/项目部署环境要求.md +++ b/docs/环境与部署/项目部署环境要求.md @@ -651,27 +651,4 @@ $env:DTU_KEIL_UV4 = 'D:\NotExist\UV4.exe' # 仅当前会话,不动用户级 ## 变更记录 -| 日期 | 变更 | -|---|---| -| 2026-10-28 | **§3.2 外设引脚口径由 V0.0 更正为 V0.1**:① TPAFE5160 控制组由 `PD3 RD / PD4 CONVST / PD7 BUSY` 改为 **`PC6 FRSTDATA / PC7 BUSY(EXTI9_5) / PC8 RD / PC9 CONVST / PA8 OS2 · PA11 OS1 · PA12 OS0`**(V0.1 把 7 线整组从 PD/PF 迁到 PC/PA);② RS-485 由 **UART5**(`PC12 TX / PD2 RX / PD0 DE`)改为 **UART4**(`PC10 TX / PC11 RX / PA15 DE`)——依据 `App/app/app_main.c` 的 `rs485_init(&g_rs485, &huart4, ST_DIR4_GPIO_Port, ST_DIR4_Pin)`;③ LED1/LED2 驱动脚由 `PC4/PC5` 改为 **`PC5/PB0`**(PC4 让位给 ADC17),并补网名↔丝印 `LED(n+4)` 倒序提示(V0.1 网表关注点 V3)。引脚口径改以 `Inc/main.h` 与 `V0.1_网表详细分析报告.md` §4.1 为准 | -| 2026-10-22 | **§3.2 / §3.3 与 §2.2 内存事实纠偏**:① §3.3 资源预算表由 2026-09-11 快照刷新为 2026-10-22 实测——Flash 231,768 B / 22.1%,主 SRAM1 由"125,104 B / 95.4% / 极度紧张"更正为 **75,264 B / 57.4%(余 55,808 B)**,并**补上 CCM 行**(57,376 B / 87.9%,余 7,904 B)——当前红线在 CCM 而非 SRAM1;② 删除 §3.3 的任务栈副本表(无门禁、已缺 `adcTask`/`iec104Task`/`protectTask`),改指针到 `README.md`/`AGENTS.md` 受管表与 `RAM使用分析与优化方案.md` §2.3/§0.6;③ §2.2 链接布局补 `RW_CCM 0x10000000` 段(2026-10-11 已启用、**不可 DMA**),§3.1 MCU 行更正为**单精度 FPU、无 TrustZone**(原写"双精度 FPU / TrustZone"是芯片事实错误,也正是报告 F-6 双精度软浮点被长期误判的土壤) | -| 2026-10-12 | **远程 CI 文档迁出本目录**:`CI配置指南.md` 与 `Gitea_Runner部署指南.md` 合并为 **`docs/CI/远程CI完整指南.md`**(入口 `docs/CI/README.md`),本文三处引用改指新路径与新章节号(§4.1.3 机器级变量、§7 相关文档登记)。原因:远程 CI 只涉及本机一台 runner,不应与"任何机器都要过"的部署核对清单混在一起 | -| 2026-10-10 | **删除旧档 NCFG 迁移**(升级/迁移口径变更):旧固件遗留的 `/cfg/netcfg.bin` 不再"首启自动迁移"——旧档若存在则被忽略(不读、不删、不迁移),配置直接回落工厂默认(`/config.ini` `[network]` 段模板)。`net_cfg_legacy.c/h` 与 `cfg_store_legacy_path()` 已移除;携带旧档的设备升级后需经 UI 或 FTP 重新配置网口。§五 现场部署 IP 行同步 | -| 2026-10-02 | **模拟器构建修复**(配置引擎重构遗留):`simulator/CMakeLists.txt` 的配置文件引擎引用同步到迁移后位置——包含目录 `App/`→`App/cfg/`(`cfg_file.h`/`cfg_file_store.h`)、源文件 `App/cfg_file.c`→`App/cfg/cfg_file.c`、包含目录 `test/`→`test/board/`(`test_config.h`/`net_latency_test.h`);全量 include 离线核查无其他断链,模拟器全量构建恢复(`--cfgtest` 四场景 PASS,rc=0)。§2.12 验证链 ⑤ 行同步更新 | -| 2026-10-02 | 更正 Device Pack 必装范围:`Keil::CMSIS` pack 不再列为必装项——本工程不依赖它(核心头文件由仓库 `Drivers/CMSIS/` 提供,`.uvprojx` 只引用 DFP pack;2026-10-02 本机实测未装 CMSIS pack 构建 0/0 通过),且其 keil.com 直链(5.7.0~6.1.0)均已下架 404;必装的只有 `Keil::STM32F4xx_DFP`(3.1.1,与 `.uvprojx` PackID 一致)。§2.2 / 第 2 步 / 搭建清单 / §2.10 同步更正 | -| 2026-10-02 | 新增 §2.12「跨机验证(第二台机器 / 换机验收清单)」:变量配置 + sanity check → 六步验证链(含期望结果与失败诊断,含模拟器既有 CMake 问题标注)→ 反向 fail-fast 测试 → 通过判定,作为方案跨机验收的标准操作 | -| 2026-10-02 | **本地工具路径环境变量方案落地**(`本地工具路径环境变量方案.md`):仓库脚本不再含本机绝对工具路径——10 处调用点(`build/download/reset.bat`、`_build.cmd` 退役、`ci_local.py`、`ci.yml`、`gen_refgraph.py`、`unit_test_harness.py`、`build_sim.ps1`、`make_font.py`)统一改为"`DTU_*` 变量优先 + 自动发现回退"(显式设置但无效 = 硬报错,不静默回退);新增 §2.1.1 变量清单/设置方法/解析语义;Keil 安装路径、Graphviz、cppcheck、VS/SDK 自动探测、Python 重建示例与速查表同步改为变量口径;`requirements.txt` 增 `pre-commit`(重建 `.venv` 即可直接跑静态门禁);本机已按 §2.1.1 配置用户级 `DTU_KEIL_UV4`/`DTU_STLINK_CLI` 并全链路验证(@build 0/0、ci_local 静态门禁+主机侧纯逻辑单测全绿、refgraph 重生成、reset 探针识别) | -| 2026-10-02 | 新增 **`Gitea_Runner部署指南.md`**:针对**本机 Gitea 原生部署**(`D:\Docker\Gitea\gitea.exe` + Windows 服务 + `127.0.0.1:3001`)定制的 Runner 端全流程——下载 / `register`(**`--instance` 用回环、`--labels "windows:host"` 必须精确匹配 `runs-on`**)/ `config.yaml` / `daemon install` 常驻 / 软件与 PATH 坑 / MSVC 路径约束 / 内网 action 零依赖改法 / 排障表 / `check_env.ps1` 自检脚本;§七相关文档登记 | -| 2026-10-01 | 新增 **`CI配置指南.md`**(Gitea Actions 配置全流程:服务端 `[actions] ENABLED` / Windows runner 注册(`--labels "windows:host"`)/ runner 软件环境与 PATH / workflow 位置与触发 / 内网拉不到 `actions/checkout` 的三种处置 / 端到端验证清单 / 故障排查表 / 日常维护);§七相关文档登记 | -| 2026-10-01 | **新增 §2.11 CI runner 环境(Gitea Actions,T-6)**:Gitea ≥1.21(实测 1.25.4)+ `[actions] ENABLED` + Windows runner(装 Python/cppcheck/pre-commit/MSVC);**不需要 Keil**(刻意不跑 `@build`,无 `.map` 时 `mem-numbers` 自动跳过);补"CI 不能替代本地门禁"与 `scripts/ci_local.py` 过渡命令 | -| 2026-10-01 | **补主机侧单元测试环境要求**:§2.3 由"PC 模拟器环境"扩为"PC 侧编译环境(模拟器 + 主机侧单元测试)"——明确**同一套 VS 的 `cl.exe` 同时服务模拟器与单测**,MSVC 从"仅模拟器需要"升级为"提交门禁需要";§2.7 pre-commit 表补 `watchdog-unit-test` 钩子及"未装 VS 会被拦截";第 3 步 / 第 10 步冒烟 / 搭建清单 / §2.10 下载表(补 VS2022/2026 行)/ 速查表(补 `cl.exe` 缺失与 `C1083 stdio.h` 两条)/ 相关文档同步;总览拓扑图加 `MSVC cl.exe` 节点 | -| 2026-09-21 | 更正 SDL2 描述:`simulator/SDL2/` 并不入库(gitignore,fresh clone 缺失),原"**随仓库提供**/不用装"表述有误;第 3 步补全官方预编译包下载(直链 + 内网中转)、解压、`include/SDL2/` 头文件复制、5 文件校验步骤;§2.3 表格与速查表同步修正 | -| 2026-09-21 | 模拟器构建改为自适应:新增 `simulator/build_sim.bat/.ps1`(vswhere 自动探测本机 VS 大版本 → 生成器 16=2019 / 17=2022 / 18=2026;`build/` 生成器不符自动删除重建,删除带重试抗文件锁);VS 版本不再固定,2019/2022/2026 兼容:总览图、§2.3、第 3 步、第 10 步冒烟、搭建清单、速查表同步更新 | -| 2026-09-16 | 补 Graphviz(引用关系图渲染,可选):新增 §2.8,原 §2.8/§2.9 顺延为 §2.9/§2.10(章节内步骤号不变);总览图、搭建清单、§2.10 下载表、相关文档各补一项 | -| 2026-09-13 | 初版:汇总开发机(Keil / VS2019+SDL2 / Python venv / 字体 / 串口工具 / pre-commit)、目标板(引脚 / 资源预算 / 下载 / 功能开关)、网络现场部署(默认参数 / 端口 / 验收清单)、远端客户端四类环境要求,附一次性搭建清单(含分步安装命令与冒烟验证)与常见环境问题速查 | -| 2026-09-13 | §2.8 各组件补手动下载网址;新增 §2.9 手动下载来源速查表 | -| 2026-09-15 | 串口调试/自动测试工具由 serial-mcp-server 切换为仓库内置 Python 串口助手(serial_tool,.venv + pyserial,免安装):§2.4 依赖清单、§2.6、§2.8 第 7/9/10 步、搭建清单、§2.9 下载表(去 Rust/serial-mcp-server)、速查表、相关文档同步 | -| 2026-09-13 | 补 STM32CubeMX 6.17.0 + STM32Cube FW_F4 V1.28.3(与 .ioc 一致):拓扑图 / §2.2 / 第 2 步 / §2.9 / 搭建清单,常见问题速查增加再生成版本不匹配条目 | -| 2026-09-13 | 新增"Keil 初始化配置(机器侧项,非项目自带)":license / Device Pack(含 FLM 来源解析路径)/ 下载器驱动,并列出项目自带免配置项;§六 速查补 FLM 缺失、license 过期两条 | -| 2026-09-13 | 补 RAM/Flash 链接布局说明:手动 scatter 文件 `STM32F407-Demo.sct`(在仓库)为链接依据(128KB = SRAM1+SRAM2,SRAM3/CCM 未映射),新机器无需重设、勿改 GUI Target 页 | -| 2026-10-22 | 换机自检去掉「首次须 `--update` 生成参考图」一步(`simulator/tests/ref/*.bin` 已入库,检出即带基准);排障表「内容页回归参考缺失」一行改为按"检出不完整"处置(`git checkout -- simulator/tests/ref/`,禁止就地 `--update` 造基准) | +> (本文件不再记流水账:改了什么是正文说了算,改动过程查 git log。) \ No newline at end of file diff --git a/docs/算法/采样有效性校验设计说明.md b/docs/算法/采样有效性校验设计说明.md index f045bfb9..5db1a989 100644 --- a/docs/算法/采样有效性校验设计说明.md +++ b/docs/算法/采样有效性校验设计说明.md @@ -36,7 +36,6 @@ - [14. 改它之前必读](#14-改它之前必读) - [15. 兜底新鲜度门(保护侧独立通道)](#15-兜底新鲜度门保护侧独立通道) - [16. 相关文档](#16-相关文档) -- [变更记录](#变更记录) --- ## 1. 三分钟建立心智模型 @@ -650,14 +649,3 @@ stateDiagram-v2 - `docs/内存管理/RAM使用分析与优化方案.md` §2.3 与 §4.0.6 —— `adcTask` 栈配置、最坏链与余量台账 - `App/algo/README.md` —— 目录级文件清单与构建测试入口 - `docs/子系统设计/ADC采样节拍设计说明.md` §3.4 —— TIM3 启动位置与顺序(兜底门开机不误锁的前提) - ---- - -## 变更记录 - -| 日期 | 变更 | 说明 | -|---|---|---| -| 2026-10-21 | 新建 | 首版单文件深设计:判据推导、四种位语义、闭锁与兜底责任矩阵、验证分工与现场判读手册;新增三张配图生成器(`tools/arch_diagram/gen_adc_health_flow_svg.py`、`gen_adc_health_bitmap_svg.py`、`gen_adc_health_timeline_svg.py`)与产物 SVG | -| 2026-10-21 | §6.2 / §10 | 丢帧口径统一:语义取数与有效性的 `adc1_gap` 由「次数」改为「帧点数」,与 `tgap` 同单位;§10 盲区第 4 条改写、§11.2 台架证据标注历史日志为旧口径 | -| 2026-10-21 | 新增 §15 | 兜底新鲜度门:`adc_health_age_stale()` 无状态纯判据 + `ADC_HF_STALE`(bit8)+ `protectTask` 独立观测;§7 位表、§8 责任矩阵与「已知窗口」段、§10 盲区、§11 用例表、§12 判读、§14 清单与位图配图全部同步 | -| 2026-10-21 | §14 更新 | 初始化入口已接线:`adc_task_func()` 进循环前调 `adc_task_init()`(该入口不再打日志);同时删除 `App/task/net_task.c` 里的空壳 `net_task_init()` | diff --git a/docs/算法/采集与算法层设计说明.md b/docs/算法/采集与算法层设计说明.md index 3c46a4f1..0e3658e2 100644 --- a/docs/算法/采集与算法层设计说明.md +++ b/docs/算法/采集与算法层设计说明.md @@ -39,7 +39,7 @@ ADC1)、不做出口动作。 - **这样分离换到什么**:`sample_ring` / `phasor` / `adc_health` / `prot_set` / `prot_elm` / `freq` **零平台依赖**(只用 `stdint.h` / `math.h` / `stddef.h` 与本目录头),因此可被主机侧 - 单测以 `#include` 原样纳入、离线全覆盖(落实 `docs/任务规划/测试与架构专项.md`「采集链路测试可验证性约束」),不需要真机就能钉死判据。 + 单测以 `#include` 原样纳入、离线全覆盖(落实 `docs/任务规划/暂缓-RS485.md`「采集链路测试可验证性约束」),不需要真机就能钉死判据。 - **上下文约束**:`*_init()` 一律无 RTOS 依赖、幂等,由 `app_main_init()` 在**内核启动前**调用; `adc_input_poll()` / `phasor_run()` / `freq_run()` **仅任务上下文**(快照走临界区)。 - **消费者在 `App/task/`**:`adcTask` 采集并压环、`protectTask`(B5)跑 `prot_elm_run()`; diff --git a/docs/编号规范.md b/docs/编号规范.md index 8a600570..23c4b9da 100644 --- a/docs/编号规范.md +++ b/docs/编号规范.md @@ -167,7 +167,7 @@ ### 5.5 销项与归档 删登记行 + **同步清掉全仓引用**(清引用是销项的一部分,不是"以后再说")+ 别名表标 `void`。 -冻结的历史(变更记录行、`[示例]` / `[计划]` 行)不回改,门禁对它们已豁免。**唯一例外**(用户裁定 2026-10-28):这类行里**已停发 / 作废族的示例编号**可改成形态描述(写成「字母紧跟数字」这类说法)——改的是示例的写法,不是历史事实;**保留现存号**族的游标数字与硬件位号举例不在例外内,形态化等于毁证据。 +冻结的历史(变更记录行、`[示例]` / `[计划]` 行)不回改,门禁对它们已豁免。**现状补充**:2026-10-28 起新文档一律不再设「变更记录」节(`docs/文档规范.md` §5.1),所以这条冻结规则只对**仍保留变更记录表的 5 篇**(同一份清单)与 `scripts/archive/id_gate/` 下的归档文档生效——不是「以后还能往变更记录里写」的理由。**唯一例外**(用户裁定 2026-10-28):这类行里**已停发 / 作废族的示例编号**可改成形态描述(写成「字母紧跟数字」这类说法)——改的是示例的写法,不是历史事实;**保留现存号**族的游标数字与硬件位号举例不在例外内,形态化等于毁证据。 ### 5.7 语义标识的登记与别名 短语就是登记处的行名,不需要别名表;**只有"号转短语"**时才在别名表留一条 `retired-to-phrase`, @@ -214,10 +214,4 @@ ## 变更记录 -> 2026-10-28 以前的流水(编号族清退的每一批、每批的实测数字)已移入 -> `scripts/archive/id_gate/编号治理历史.md` 的「变更记录」节——要查某个号是哪一批退的,去那里。 - -| 日期 | 变更 | 说明 | -|---|---|---| -| 2026-10-28 | **§4.1.1 加一行「测试验证层级号」停发指针**(本族当日整族清退成语义名;事实本体在 `scripts/archive/id_gate/编号治理历史.md` §10,活文档只留指针、不复述换算表) | 用户裁定 A 方案:代码 + CI + 文档一次改到底 | -| 2026-10-28 | **门禁三步退役 + 本文瘦身** | ① 两根护栏(可判定比例 / 不可判定绝对数)转报告制,不再拦提交;② 全库语料审计换成「只查新增行」的 `id-check-new`(零语料);③ 99 族语料与脚本移入 `scripts/archive/id_gate/`,钩子 52 → 51。本文同步从 36 节 / 58 KB 瘦到只留现行口径(约 150 行),过程记录与换算表进归档。 | +> (本文件不再记流水账:改了什么是正文说了算,改动过程查 git log。) \ No newline at end of file diff --git a/docs/网络/BSD_Socket_API_使用指南.md b/docs/网络/BSD_Socket_API_使用指南.md index c1f0143b..b4985e46 100644 --- a/docs/网络/BSD_Socket_API_使用指南.md +++ b/docs/网络/BSD_Socket_API_使用指南.md @@ -1,6 +1,6 @@ # BSD Socket API 使用指南 -> **恢复说明**:本文档曾在提交 `4e9ac0d`(2026-08-28)中误删,2026-09-13 从 git 历史恢复。API 随代码多轮同步(2026-09-13:`net_init` 4 参数 / `net_socket` 2 参数 / 网络代次号 / `NET_NO_OS` 双端构建;2026-09-23:`net_recv_to` / `net_sock_state` / `net_resync_listen` / `net_relisten`、挂起 recv 化、D10 非阻塞重监听、TRAP-NET-17 周期对账、TRAP-NET-18 排渣隔离)。详见文末变更记录。 +> **恢复说明**:本文档曾在提交 `4e9ac0d`(2026-08-28)中误删,2026-09-13 从 git 历史恢复。API 随代码多轮同步(2026-09-13:`net_init` 4 参数 / `net_socket` 2 参数 / 网络代次号 / `NET_NO_OS` 双端构建;2026-09-23:`net_recv_to` / `net_sock_state` / `net_resync_listen` / `net_relisten`、挂起 recv 化、D10 非阻塞重监听、TRAP-NET-17 周期对账、TRAP-NET-18 排渣隔离)。历次同步的完整过程查 git log。 > > **伴读文档**:本文回答"上层该怎么调";**内部函数之间的调用关系、每个函数的设计作用与意图**(netTask / 消息队列 / 挂起 recv / D10 重试 / TRAP-NET-17 对账 / TRAP-NET-18 排渣各子系统,含总体调用图与端到端时序)见 `docs/网络/BSD_Socket_API_函数调用关系.md`。 @@ -1477,26 +1477,3 @@ CH395F 底层驱动返回的状态码(`ch395f_get_cmd_status()` 或 `ch395f_po | **TC-NET-604**"接收冻结"虚警 | 旧判读脚本把"对端填满 2KB RX 窗口"误判为 STALL/WEDGE | **结论:非缺陷**(芯片 RX 缓冲即窗口,对端填满是常态);判据改为脚本层 STEP + 客户端内容校验(RET SHA-256),虚警工具归档(`MDK-ARM/retracted_bench_20260922/`,README 禁重跑) | 真实 FTP 路径 227 轮全通过(8KB×10 … 1MB×2);并发 UI 流 600/600 CRC;设备零 FAIL/ERROR/WARN | **排障判据**(无 Wireshark 环境,纯生产路径):`MDK-ARM/ftp_freeze_probe.py`(真实 STOR + RETR SHA-256)、`test/host/ftp_abort_probe.py`(RST/FIN 中止复连)、`MDK-ARM/tcp_reconnect_probe.py`(快速复连存活甄别)、`MDK-ARM/bench_verdict.py`(脚本层 STEP 为真值;**`probe_classify.py` A/C 判读不可信**,见 retracted 归档 README)。详见 `docs/问题记录/CH395F_Trap_Records.md`。 - ---- - -## 变更记录 - -| 日期 | 变更 | -|------|------| -| 2026-10-14 | **二期 SEND pending 化**(架构见 `docs/网络/Net层阻塞模型架构设计.md` §4.5/§5.5/§7):`net_send` 快路径改为**有界自旋**(`NET_SEND_SPIN_MS` = 2ms,健康链路块间等待 med 219µs ≪ 2ms,行为不变),超预算登记挂起 send,由新增 `net_send_pending_tick` 按主循环节拍分块推进(①断连 ②推进 ③写完 ④无进展超时),调用方睡任务通知——netTask 最坏停滞由 `NET_SEND_TIMEOUT_MS`(1s)压到 2ms。返回值恒为**已写入字节数**(短写须检查);`NET_SEND_TIMEOUT_MS` 降级为**无进展**超时(每次成功写块刷新)。主循环 tick 由 3 个增至 **4 个**(新增 `net_send_pending_tick`,与 `net_pending_tick` 并列);§3.3 / §3.5 / §3.6 / §10.2 / §12 同步 | -| 2026-10-13 | **自愈收敛阶段 3 自愈合并 + E-02 收口**(实施规格现沉淀 `docs/网络/网络自愈架构设计.md` §4.1):`net_listener_pump` **删除**,与 `net_reconcile_tick` 合并为**单一 100ms tick**(覆盖原对账①②⑤ + 原 pump③④/U11;判据读**驱动状态缓存** `ch395f_sock_state_cached`,唯一刷新点 = `net_poll` 每轮全量刷新,E2 实测单次回读 18.1µs;**分级去抖** ②=1 轮 / ③④⑤=2 轮 / ①=4 轮(M3 让位窗 400ms)+ 1s 冷却;§2.2 / §3.3 / §3.6(五层 → **四层**)/ §10.2 / §12.1 / §12.10 同步,主循环自愈 tick 由 4 个回到 **3 个**;常量 `NET_LISTENER_PUMP_PERIOD_MS` / `NET_LISTENER_STABLE_N` / `NET_LISTENER_COOLDOWN_MS` 删除);**忙等统一**——`net_listen_locked` / `net_connect_locked` open 失败重试"close+盲等 500ms"与 `net_close_locked` 500ms 排空循环改走驱动 `sock_reset` 原语(`net_sock_reset_sync`,GRACEFUL 100ms 底),`net_close_locked` 不再读清全局中断寄存器(F-NET-7:全局寄存器唯一读者 = `net_poll`);新增 **`net_drop_conn(sockfd)`**(§10.1,E-02 收口:拆会话**保监听**、幂等、EOF 路径不得调;新消息类型 `NET_MSG_DROP_CONN`;timeSync 30s 预算耗尽路径接入;模拟器实现为关数据连接);`net_poll` 每轮对在用 Socket 步进 `ch395f_sock_reset_poll`(同步包装 600ms 放弃后复位机不搁浅);`net_sock_state_t` 注释声明为"本层会话投影"(芯片事实源 = 驱动缓存,`net_types.h`);台架回归全绿(最终构建 Code=211348,E-02 双 PASS,见 `docs/网络/网络自愈架构设计.md` §5.2 E-02) | -| 2026-10-13 | **自愈收敛阶段 1.5 recv 语义主流化**(规格现沉淀 `docs/网络/网络自愈架构设计.md` §4.5):`net_recv()` 默认**无限阻塞**(删 `NET_RECV_TIMEOUT_MS` 30s 默认预算,唤醒源=数据/EOF/close/网络重建 CONNRESET);新增 `net_recv_nb()`(`NET_MSG_DONTWAIT` 路径转正)与 `net_setblocking(fd, on)`(模式挂 socket 控制块属性,`net_sock_t.blocking`,默认阻塞);`net_recv_to()` 保留为**显式预算**便捷入口(`timeout_ms=0` 语义从"默认 30s"改为"无限"故仍拒 INVAL);内部 recv 看门狗降级为 **tripwire**(挂起超 60s 只 `[ERR]` 留痕一次,不再"到点 +1s 强制了结"伪造 TIMEDOUT);⚠ 新增**文档契约**:IWDG `required_mask` 内任务禁止无限阻塞 recv(必须 `net_select` 超时或 `net_recv_to` 显式预算);`ui_net_sink` / `iec104_serv` 迁移 `net_recv_nb`,lftpd / timeSync 维持显式预算;模拟器 `net_socket_sim.c` 镜像三 API(blocking 属性包装层模拟) | -| 2026-10-13 | **自愈收敛阶段1 API 面收敛**(审计过程已归档 `docs/网络/网络自愈架构设计.md` §12,现状见其 §4):删除手动自愈 API `net_relisten()` / `net_resync_listen()`(生产零调用;后者语义并入对账**⑤**——本层 ESTABLISHED 而芯片 0x05/0x01 静默回收 → RESYNC 只修本层,§3.6 对账由两类扩为三类①②⑤;前者与 pump/D10 重叠且对健康监听器是 footgun)与 `net_can_accept()`(只认 ESTABLISHED 的旧门控挡死丢 CONNECT 探针,监听门控统一 `net_listener_armed()`,§10.1 门控节改写);`NET_MSG_RESYNC_LISTEN` / `NET_MSG_RELISTEN` 消息类型删除;timeSync 会话收尾不再 `net_close`(同 fd 续 accept,监听跨会话常驻);lftpd 应用层阻塞重试退役(就绪屏障已消除 TRAP-NET-09 启动形态) | -| 2026-10-12 | **N-32 监听生命周期模块化 + 单一所有者**:监听生命周期抽为 `net_listener.c`(§2.2 文件表新增该行,真机专属);主循环自愈 tick 由 3 个增至 **4 个**(新增 `net_listener_pump`,100ms,**唯一重建入口**);`net_reconcile_tick` 对账收窄为 ①②,③④ 移交 pump;`handle_disconnect_event` / `handle_timeout_event` 改为 `net_listener_settle(GRACEFUL 100ms / QUARANTINE 400ms)` **只置事实**、不再自行重建;§3.3 / §3.6(四层自愈 → **五层**)/ §12.10 同步。权威设计见 `docs/网络/网络自愈架构设计.md` §11 | -| 2026-10-10 | 新增 **`net_can_accept()` / `net_can_read()` 就绪门控 API**(§10.1):纯 RAM 读控制块、**不走消息队列、不等 netTask 回执**,供实时性敏感任务在发 RPC 前判断"有没有活"(动因 = `ui_net_sink_poll()` 每 10 ms 一次 `net_accept` 把 uiTask 拖成最坏 ≈50 ms;原拟登记 N-19 / C7,当日结案不入登记簿;设计与实测见 `docs/子系统设计/看门狗设计说明.md` §11(原分析文档已并入该节));§3.5 补"netTask 运行要求"例外条;⚠ 记录两条使用约束——**不可作为唯一判据**(`readable` 只由 RECV_OK 中断置位,须保留低频兜底 recv)与**模拟器后端恒返 1**(`net_socket_sim.c`,Winsock 无 RPC 成本) | -| 2026-09-23 | 同步 L3 pending 化、D10 非阻塞重监听、TRAP-NET-17 对账、TRAP-NET-18 排渣隔离后的现状:新增 `net_recv_to` / `net_sock_state` / `net_resync_listen` / `net_relisten`(§10.1)及 `net_getsockname`;§3 新增 3.6(对账与自愈四机制)、3.3/3.5 改写(recv 挂起模型、队列语义、netTask 运行要求);§4/§5 示例更新(监听由就绪屏障后服务任务建立、`net_sock_state` 轮询);§10.2 改述 `net_process_messages()` 每轮节奏(重监听重试 → 挂起 recv 完成 → 200ms 对账 → 队列),补 `timeout_ms`/新消息类型说明;新增 §11.2 分片阻塞读(`net_recv_to`);§12.1/12.3/12.4/12.9 更新,新增 §12.10(自愈行为数据与排障判据,含 TC-NET-604 结案) | -| 2026-09-21 | **修正公开 API 的错误码回传**:`net_msg_t` 按值拷入队列 → netTask 对消息的写入调用方不可见,改用 `xTaskNotify()` 通知值回传具体错误码(负值),公开 API 恢复 errno 后统一返回 -1(此前被覆盖成 `NET_ERR`,使 `net_get_errno() != NET_ERR_WOULDBLOCK` 的"空轮询"判断恒成立 → `ui_net_sink` 连上即 `net_close`);§12.4 补单连接模型断开处理(EOF 时不得 `net_close` 监听 socket);§12.9 补错误码回传约束 | -| 2026-09-15 | 同步配置引擎属主变更(P1-3):`net_init` 调用方说明改为"netTask 只读 RAM 副本"(网口配置由 defaultTask 在就绪屏障前加载);模拟器端启动序列补 `net_cfg_save_run()`(主循环 = 模拟器侧配置引擎属主,执行 UI 保存请求) | -| 2026-09-13 | 从 git 历史恢复(`4e9ac0d` 2026-08-28 误删);同步当前代码:`net_init` 4 参数(新增 `mac`)、`net_socket` 2 参数(移除 `protocol`)、新增 `net_get_generation` / `net_generation_inc` / `net_listen_locked`、`NET_NO_OS` 双端构建、netTask 周期 10ms → 1ms | -| 2026-09-13 | 配图:§2.1 分层架构改 SVG 生成器产物(`tools/arch_diagram/gen_net_stack_svg.py` → `docs/images/BSD网络栈分层.svg`);§2.4 状态机、§3.2 消息队列时序改 Mermaid(状态名对齐代码 `net_sock_state_t`,补 `UDP_OPEN` / `auto_relisten` 迁移,修正旧 ASCII 图不准处) | -| 2026-09-13 | 新增 §2.3「PC 模拟器端:net_socket_sim」(Winsock 后端、`NET_NO_OS` 裁剪清单、MCU/模拟器行为差异表、模拟器端启动序列);§2.2 文件表补模拟器后端行 | -| 2026-08-28 | 原版最后更新(删除前):`net_socket()` / `net_recv()` / `net_close()` 等返回值语义统一(0 / -1,`net_socket()` 返回描述符) | -| 2026-08-20 | 增加 8 Socket 架构、事件回调机制、select/poll、字节序处理 | -| 2026-08-18 | 增加消息队列模式、线程安全设计 | -| 2026-08-15 | 初版:BSD Socket API 概览与基本用法 | diff --git a/docs/网络/网络自愈架构设计.md b/docs/网络/网络自愈架构设计.md index 6159db20..b3aa50ba 100644 --- a/docs/网络/网络自愈架构设计.md +++ b/docs/网络/网络自愈架构设计.md @@ -20,7 +20,7 @@ | `TRAP-NET-nn` | **陷阱记录**条目 | 同上 | | `N-nn` | `docs/任务规划/登记簿.md` 的**任务/发现编号**(⚠ 已销项的号不再可查,本文引用处即其最终事实描述) | 该登记簿 | | `D1`~`D7` | 本文**决策记录** | §10 | -| `自愈收敛阶段 N` | 2026-10 的分阶段实施标签,**只存在于历史文档与变更记录**(代码注释已全部改为平实语言);勾选清单已归档(§12)——**勿用它叙述设计,也勿再写回注释** | §12 | +| `自愈收敛阶段 N` | 2026-10 的分阶段实施标签,**只存在于历史文档与归档**(2026-10-28 清理流水后全仓仅剩 5 篇保留的变更记录)(代码注释已全部改为平实语言);勾选清单已归档(§12)——**勿用它叙述设计,也勿再写回注释** | §12 | | `TSL` / `TSC` / `TSD` | SPI 命令与数据之间的**时序间隔**要求 | `docs/芯片手册/CH395F.md` §7.4 | | `n30` | 压测脚本 `n30_repro.py`(:21 背靠背 STOR 30 轮),自愈回归的**主判据** | `test/host/` | | 沉降窗 / 隔离期 | 释放会话后、重建监听前的**最短等待**(GRACEFUL 100 ms / QUARANTINE 400 ms) | §4.3 | @@ -868,5 +868,5 @@ accept 走 `handle_connect_event`),且 `NET_RECON_STABLE_DEATH` 两边共用 `git log --oneline -- docs/网络/N34-自愈审计/`; - 监听生命周期(本文 §1.1~§1.4 / §4.9 / §9~§11 的来源,含 P0~P3 勾选清单与台架验收记录): `git log --oneline -- docs/子系统设计/网络Socket监听生命周期设计说明.md`; - - `自愈收敛阶段 N` 只出现在历史文档与变更记录里(代码注释已清理为平实语言)—— + - `自愈收敛阶段 N` 只出现在历史文档与归档里(变更记录节已清理,仅 5 篇保留)(代码注释已清理为平实语言)—— **勿再引入**,设计含义一律以本文 §2~§4 为准。 diff --git a/docs/门禁说明/bom-guard.md b/docs/门禁说明/bom-guard.md index 1ed7f47e..6f82fbb0 100644 --- a/docs/门禁说明/bom-guard.md +++ b/docs/门禁说明/bom-guard.md @@ -86,9 +86,3 @@ AGENTS 铁律第 2 条的名单、钩子 `files` 正则、脚本内 `BOM_LIST` - 改名单必须同时改三处(§6.2 会拦着); - 新增判定分支必须先在 `--selftest` 里加用例(含正反两向),它是这篇文档里唯一可执行的部分; - 别在这里加"自动修复":见 §4 的编码风险。 - -## 9. 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-10-25 | 首版(道E task-20)。立项依据:同日 task-15 内 4 次 + 批 1 一次 BOM 剥离事故;端到端实测(真剥掉 `ui_w_records.c` 的 BOM → 钩子 rc=1)随 task-20 提交正文留存 | diff --git a/docs/门禁说明/bsp-err.md b/docs/门禁说明/bsp-err.md index 0bce67e3..88015c1a 100644 --- a/docs/门禁说明/bsp-err.md +++ b/docs/门禁说明/bsp-err.md @@ -143,9 +143,4 @@ BSP 约定:命中 38(在册 38 / 新增 0),基线共 38 ## 9. 变更记录 -| 日期 | 变更 | -|---|---| -| 2026-10-23 | 首版三项检查(错误通道 / 超时宏命名 / 必须写返回值)随 S-5 契约落地,存量基线 19 条 | -| 2026-10-23 | 还掉 18 条缺「返回值:」;`return-doc` 改为忽略空格匹配(此前两条因散文里出现"返回值"而误判通过) | -| 2026-10-23 | 新增第四项 `consume-result`,上线暴露 37 条存量丢弃;名单扩到 `.c` 内 static 定义;修两次判据(行尾注释漏判、setter 误判);同日修掉 `bbt_rebuild` 的 ECC 开关丢弃 | -| 2026-10-23 | 四项由 `R1~R4` 改名为语义标签(该裸形在本仓与"专项风险"编号撞车,且编号门禁因同号不同义白名单不会报);基线 38 条随改名一起换 | +> (本文件不再记流水账:改了什么是正文说了算,改动过程查 git log。) \ No newline at end of file diff --git a/docs/门禁说明/check-added-large-files.md b/docs/门禁说明/check-added-large-files.md index 5b7324a0..c4a4d4d2 100644 --- a/docs/门禁说明/check-added-large-files.md +++ b/docs/门禁说明/check-added-large-files.md @@ -47,9 +47,3 @@ check for added large files..............................................Failed ## 7. 豁免与基线 / 8. 改这个门禁本身 - 无基线、无逐文件豁免开关;放宽只能给 `args` 加 `--maxsize`,而那会同时放宽**所有**新文件。 - -## 9. 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-10-23 | 首篇逐项文档(预防性门禁,未记录到本仓实际拦截案例) | diff --git a/docs/门禁说明/check-merge-conflict.md b/docs/门禁说明/check-merge-conflict.md index 5bb5fbc8..9e19fdc9 100644 --- a/docs/门禁说明/check-merge-conflict.md +++ b/docs/门禁说明/check-merge-conflict.md @@ -42,9 +42,3 @@ check for merge conflicts................................................Failed ## 7. 豁免与基线 / 8. 改这个门禁本身 - 无基线。要演示冲突标记,**改写法**(不放行首)比改门禁或放宽更合适。 - -## 9. 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-10-23 | 首篇逐项文档(含"行首 7 连等号会被误判"这个写作注意点) | diff --git a/docs/门禁说明/check-yaml.md b/docs/门禁说明/check-yaml.md index 9a297293..f99b503d 100644 --- a/docs/门禁说明/check-yaml.md +++ b/docs/门禁说明/check-yaml.md @@ -54,9 +54,3 @@ check yaml...............................................................Failed `& '.venv\Scripts\python.exe' -m pre_commit run --all-files`,然后确认目标钩子**出现在输出里** 且状态是 `Passed` 而不是 `Skipped`(`Skipped` = `files:` 没覆盖到,等于没挂)。 - 新增 `repo: local` 钩子时,`language: system` + 相对路径入口是最容易写错的两处。 - -## 9. 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-10-23 | 首篇逐项文档(含 `always: true` 只告警不报错这条实测教训) | diff --git a/docs/门禁说明/coding-standard.md b/docs/门禁说明/coding-standard.md index c254671f..58510f55 100644 --- a/docs/门禁说明/coding-standard.md +++ b/docs/门禁说明/coding-standard.md @@ -116,11 +116,3 @@ Drivers/BSP/X/x.c:42 [CODE-RULE-09] 函数 foo_bar 缺少函数注释(应含 C/H 共 **151 个文件**,命中只有 `cfg_file_store_sim.c` 那两行(即 §7 那条豁免)→ 直接**硬拦截、 零基线**;`pre-commit run coding-standard --all-files` 实测 Passed。自证:临时样例里 `malloc/calloc/free` 各报一处,`pvPortMalloc/vPortFree/buf_alloc(`、注释、字符串 全部不误报。 - -## 9. 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-10-23 | 首篇逐项文档(19 条规则逐条列出,含 CODE-RULE-14 缺号说明) | -| 2026-10-23 | 新增 **CODE-RULE-20 禁 C 库堆分配**(硬拦截、零基线;唯一豁免 = 平台分配后端的 - 宿主侧实现文件)。出处是 AGENTS.md 平台约束而非规范 V1.0;规范 §6.1 示例已同日加"本仓禁止"批注 | diff --git a/docs/门禁说明/cppcheck.md b/docs/门禁说明/cppcheck.md index 6fb7e141..ffab7b9b 100644 --- a/docs/门禁说明/cppcheck.md +++ b/docs/门禁说明/cppcheck.md @@ -81,9 +81,3 @@ Drivers\BSP\XXX\x.c:123:45: warning: ... [someCheckId] - 加抑制项 = 永久放弃一类检查,必须在提交说明里写清噪音样本;能单行抑制就别整类抑制。 - 加/减 `--enable` 档位前,先跑一次全库看新增多少条——直接挂钩子会把所有人卡在提交外。 - 两个钩子的抑制清单**有意不同**(`test-cppcheck` 少几条),改的时候别顺手"对齐"成一套。 - -## 9. 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-10-23 | 首篇逐项文档;补记"照不出返回值丢弃"这条实测负结果(它是 `consume-result` 的由来) | diff --git a/docs/门禁说明/cubemx-survival.md b/docs/门禁说明/cubemx-survival.md index 5a4006a7..3dad5274 100644 --- a/docs/门禁说明/cubemx-survival.md +++ b/docs/门禁说明/cubemx-survival.md @@ -63,7 +63,7 @@ CubeMX 重生成存活审计.......Failed **`--write` 必须与"确认过的改动"写在同一个提交里并说明。** 6. 它不判断定制**是否仍然正确**,只判断"还在不在原来的位置"。 7. **基线漏项 = 静默不检**(2026-10-25 实证):`--check` 只比对基线里已登记的条目——一条定制 - 若从未进过基线,检查面再全也不会报它。`docs/任务规划/测试与架构专项.md` 那次返工时 + 若从未进过基线,检查面再全也不会报它。专项文档(原 `docs/任务规划/测试与架构专项.md`,已删除 2026-10-28)那次返工时 `--write` 顺带补出了原本缺失的 `net-msgq-adopt`(`Src/freertos.c` RTOS_QUEUES 区须含 `net_msg_queue_adopt`),该条目此前 处于"不存在于基线 → 永不检查"态。**新增标记区外定制时,登记必须与代码同提交**(同 §5 的 @@ -84,9 +84,3 @@ CubeMX 重生成存活审计.......Failed - 新增受保护项:先想能不能落到 `USER CODE` 区或 `.ioc`——清单越长,人工维护越重; - 自造标记区(自定义 `BEGIN/END` 名字)会被官方模板换代抹掉,别拿它当保护手段。 - -## 9. 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-10-23 | 首篇逐项文档(含 2026-09-29 一次覆盖 4 处的实测记录) | diff --git a/docs/门禁说明/doc-links.md b/docs/门禁说明/doc-links.md index 47b7f4da..f61080b8 100644 --- a/docs/门禁说明/doc-links.md +++ b/docs/门禁说明/doc-links.md @@ -88,6 +88,4 @@ D 类刻意只校验**紧邻写法**:文档名与 `§` 之间只允许空白 ## 9. 变更记录 -| 日期 | 变更 | -|---|---| -| 2026-10-23 | 首篇逐项文档(数据为当日实跑:149 篇 / 2594 处章节引用 / 可判定 58%) | +> (本文件不再记流水账:改了什么是正文说了算,改动过程查 git log。) \ No newline at end of file diff --git a/docs/门禁说明/end-of-file-fixer.md b/docs/门禁说明/end-of-file-fixer.md index 5d9b4f08..3ad33f96 100644 --- a/docs/门禁说明/end-of-file-fixer.md +++ b/docs/门禁说明/end-of-file-fixer.md @@ -47,9 +47,3 @@ Files were modified by this hook. ## 7. 豁免与基线 / 8. 改这个门禁本身 - 无基线。若真有"某类文件必须无末尾换行"的需求,加豁免并写明原因,别用 `--no-verify` 绕过。 - -## 9. 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-10-23 | 首篇逐项文档 | diff --git a/docs/门禁说明/font-charset.md b/docs/门禁说明/font-charset.md index af4fca38..75a2f522 100644 --- a/docs/门禁说明/font-charset.md +++ b/docs/门禁说明/font-charset.md @@ -101,8 +101,4 @@ A 通过 + B 通过 ⟹ 字体覆盖"源码在用"与"刻意保留"的每一个 ## 9. 变更记录 -| 日期 | 变更 | -|---|---| -| 2026-10-23 | 首篇逐项文档(两段链条判定口径 + 生成期校验覆盖不到的那一环) | -| 2026-10-25 | 新增 §6.1:实名登记「按 extract 输出重写字符集 = 洗字形」这条事故路径;把当时「未知冗余」WARN 的 35 字**成组**并入 `KEEP_EXTRA`(实测 extract 144 字 vs 清单 183 字,差 39 字 = 逐字 4 + 成组 35),并写清删除前置条件(道E task-15) | -| 2026-10-28 | 全仓计数复扫:§6.1 的「183 字」是 2026-10-25 实测口径,**只补「当时」锁口径、不臆改新数**;现值实测 = `ui_cn_chars.txt` 唯一码点 **218** 个(其中 ASCII 区 0 个,ASCII 由生成器的子集参数另计,不算进字数)。同一句实测在 `scripts/check_font_charset.py` 的成组保留注释里同步锁「当时」 | +> (本文件不再记流水账:改了什么是正文说了算,改动过程查 git log。) \ No newline at end of file diff --git a/docs/门禁说明/generated-fresh.md b/docs/门禁说明/generated-fresh.md index 9a5a8a32..8aaccefe 100644 --- a/docs/门禁说明/generated-fresh.md +++ b/docs/门禁说明/generated-fresh.md @@ -184,16 +184,3 @@ - 临时目录一律 `tempfile.mkdtemp()`:任何「顺手写回仓库」的改动都不要加——本钩子的全部安全性 来自它不写仓库(写了就要还原,还原就要面对别人在飞的改动)。 - 自测:`--selftest`。探针字符串若在生成器里被改名,自测会直接报「探针已不存在」,不会假过。 - -## 9. 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-10-26 | **补 §6 第 8 条(本窗口最值钱的一条机制)**:pre-commit 的 stash 只覆盖**已跟踪**文件的未暂存改动(`git diff-index` 取补丁 → `git checkout -- .`),未跟踪文件不进 stash、`git add -N` 也只撤索引 —— 于是别人的半成品(实测 `ui_page_clock.c` / `ui_page_reset.c` 未绑 `#page`)会把**任何人**碰 UI 的提交拖红;红的内容对、账不该记在别人身上。附现场日志与两条正解,明确禁止为绿放宽 `files:`。通用机制同步写进 `docs/代码规范/pre-commit使用说明.md` §2.2 | -| 2026-10-26 | **补记**:§2 与 §4 补上「entry 为什么不能只是裸 python」的同一条实测线(解释器解析 + 探针校验),与本页 §9 上一行同批 | -| 2026-10-26 | **同日修假红**:entry 的裸 `python` 在提交环境里被解到机器级解释器(无 fontTools),字体链 - 一项报 `No module named fontTools`——跑了一次真实提交才暴露。现由脚本按 ci_local 的优先级解析生成器 - 解释器并逐个探针校验(新增显式变量 `DTU_GEN_PYTHON`),挑不出来打 `[ENV]` + 候选表 + 修法、退出码 2 不 - SKIP;`--selftest` 加「假解释器必须可诊断」第二项。判据与基线未变 | -| 2026-10-26 | 首篇逐项文档(task-18 接线当日):实证 = `0f7b5a87` 改模板没重跑 + 接线前实测 5 张 `docs/images/*.svg` 已漂(钉成只减不增基线);在册 4 项 = `gen_menu` / `extract_cn` / `make_font` / `tools/arch_diagram` 全量配图;接线实跑 `menu-gen` 70 文件一致、字库链两向无差、14 个配图生成器 9 干净 5 在册 → PASS | -| 2026-10-28 | 全仓计数复扫(本轮漏改面之一):§7 接线基线那句里的「183 字」补「当时」二字锁口径。那一行是 2026-10-26 接线的实跑记录,当日实跑数按当日冻结、不臆改成现值;现值另测 = ui_cn_chars.txt 唯一码点 218 个(ASCII 区 0 个;ASCII 0x20~0x7E 由生成器的子集参数另打进子集,不计入字数)。本行只追加 | diff --git a/docs/门禁说明/gitlint.md b/docs/门禁说明/gitlint.md index 308e00aa..19fb0137 100644 --- a/docs/门禁说明/gitlint.md +++ b/docs/门禁说明/gitlint.md @@ -63,10 +63,3 @@ gitlint..............................................................Failed - 无基线;放宽只能改 `.gitlint`。抬长度前先确认你要的不是"把长句拆短"。 - 想加严(例如要求正文非空、要求带模块前缀):先在最近 20 条真实提交上试跑,别直接关闸。 - -## 9. 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-10-23 | 首篇逐项文档(生效值:标题 100 / 正文行 ≤80 / `body-is-missing` 已忽略) | -| 2026-10-28 | 同步 §3 漏网面计数:`--no-verify` 跳过的「其它钩子」39 → **50**。口径 = `.pre-commit-config.yaml` 经 YAML 解析出的 **51** 条减去 `gitlint` 自身(当日 51 → 52 加 `id-check-new`、随即 52 → 51 退役 `id-check`,一增一减净零);39 是上一轮加钩子时漏同步的快照数 | diff --git a/docs/门禁说明/host-unit-tests.md b/docs/门禁说明/host-unit-tests.md index 950d8691..34db6d75 100644 --- a/docs/门禁说明/host-unit-tests.md +++ b/docs/门禁说明/host-unit-tests.md @@ -136,11 +136,3 @@ - **新增模块的宿主单测 = 复制一个 runner 模板 + 在 `.pre-commit-config.yaml` 加一个钩子 + 登记 TC 号段**,三件事缺一件就会出现"测试存在但没人跑"或"跑了但无号可引"。 - 改 `include_dirs`/源文件清单时,务必确认失败是环境问题而不是逻辑回归(先看是编译错还是断言错)。 - -## 9. 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-10-27 | **裁定入档**(task-28):18 套无专属钩子(含 `ui_sink`)**是设计不是缺口**,不补第 23 根;补钩子的判据、两个方向的空头账、「读总闸输出别数钩子」写进 §6 第 4 条。同日复核配置实数 = 解析 51 条 / 专属单测 22 根 / 套件 40 套 / 无专属钩子 18 套,与 AGENTS 那句一致 | -| 2026-10-26 | **数字与机器面对齐**(task-18 复核带出):实例 16 → **22**(2026-10-25 由 3528644e / 48bc50e7 / ffd462ef / 8c726986 / 201d7132 / 484d0682 各挂一根,§1 表补齐 6 行);§6 第 4 条「12 套无专属钩子 / 总闸 28 套」按实测更正为 **18 套 / 40 套**,并给出「没有专属钩子 ≠ 没被跑」的证据(总闸 rglob 发现规则 + 退出码语义)与补钩子的判据;顺带纠正 AGENTS 的「23 个 / 含 ui-sink」——`ui-sink-unit-test` 在配置历史里从未存在 | -| 2026-10-23 | 首篇逐项文档(16 个实例清单 + 今天两个 runner 需补 include 目录的实测) | diff --git a/docs/门禁说明/id-check-new.md b/docs/门禁说明/id-check-new.md index fc92bb21..5f84b01c 100644 --- a/docs/门禁说明/id-check-new.md +++ b/docs/门禁说明/id-check-new.md @@ -100,9 +100,3 @@ 前缀级枚举才是它便宜的原因。 - 与 `id-check` 的关系变更(摘掉旧的)要同批改:本页、`docs/编号规范.md` §8.5、 `docs/门禁说明/README.md` 的索引与计数、`AGENTS.md` 的钩子数。 - -## 9. 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-10-28 | **新建(编号门禁第二步)**:只查新增行、零语料;破折形态未知前缀 FAIL、已停发族 WARN、单字母+数字放行。与 `id-check` 双跑观察期。白名单由最近 80 笔真实提交回放调出(15 种未知形态 → 12 种进白名单、3 种只告警,误报 0)。自检 5 正例 + 29 反例通过;端到端探针:暂存一个自造前缀 + 数字 → 钩子 FAIL;清理后 Passed。 | diff --git a/docs/门禁说明/id-check.md b/docs/门禁说明/id-check.md index 021d8fec..783fef86 100644 --- a/docs/门禁说明/id-check.md +++ b/docs/门禁说明/id-check.md @@ -72,7 +72,7 @@ ## 5. 好处 -- **拦下过真事(2026-10-25 追加)**:`docs/任务规划/测试与架构专项.md` 一条返工提交被 **校验 6** +- **拦下过真事(2026-10-25 追加)**:一份专项文档(原 `docs/任务规划/测试与架构专项.md`,已删除 2026-10-28)的一条返工提交被 **校验 6** 拦下 4 处——C 注释里裸写该文档的条目编号、未紧邻属主文档名;补齐文档名即过。 实证**紧邻写法在代码注释里同样是硬约束**,不是只约束 Markdown。 @@ -240,14 +240,4 @@ ## 9. 变更记录 -| 日期 | 变更 | -|---|---| -| 2026-10-28 | **两根护栏转报告制(减负第一步)**:护栏 1(可判定比例基线)/ 护栏 2(不可判定绝对数上限)不再影响退出码,只打 `[报告]` 两行;探针实测基线 99.9% + 上限 1 处 → 退出码 0。边界自证:新文件里写一个自造前缀 + 数字 → 校验 1 与增量拦截照旧 FAIL。口径与退役路线见本文 §7.6.1 与 `docs/编号规范.md` §8.5 | -| 2026-10-28 | **批次六收口复测自证**(Lead 单道执行,本轮未并行派单):把 「retired-to-phrase」 与 「void」 两类别名当探针全库复扫(排除 `excluded_paths`、门禁自身语料与变更记录行口径),**真编号活引用 0**——剩余命中面是变更记录行(§4.3 不回改)、元器件位号与 Socket 状态组合(§4.4 判非编号,清它等于改硬件资料)、属主文档的历史对照列。教训两条:① 本文件的当日构成表按冻结证据保留不重打,§8.1 那两根护栏的账面数**随在飞改动漂移**,把某天的实测值写进正文表格等于给自己造一条会过期的断言,本轮第一次尝试就这么撞了一次(写完再跑,数已经变了);② 想留当日数就写进 `ci-artifacts/` 下的仓库外口径文件,正文只留结论与口径。本笔零编号增删,护栏基线不动。 | -| 2026-10-27 | **本仓第一次真正「还」第二根护栏的债**(道G task-45):卷锁观测计数旁自造的四位状态号(一字母+一数字的裸形写法)全量换成语义短语——`App/fs/vol_lock.c`、`App/fs/vol_lock.h`、`test/host/vol_lock/vol_lock_test.c`、`docs/测试说明/卷锁单元测试说明.md` 四处共 36 处出现清零,四态语义只留 `App/fs/vol_lock.h` 一处。改前实测不可判定绝对数 1,162(03:15),改后 1,156(03:22),余量从 4 格变 10 格;`--strict` exit 0、卷锁套件 45/45 未掉、未动 `undecidable_total_ceiling`。**顺带查清一件口径事,比这次还债本身更值得记**:绝对数只统计**落不进任何已登记族**的裸形;撞进已登记族的写法(台架/测试那一族的族模式只覆盖到该字母加一位数字的 0~3)本来就记在**可判定**一侧——于是这次 36 处里只有 6 处真正减了绝对数,另 23 处删掉是同时缩分子与分母(比值几乎不动:86.74% → 86.77%)。⇒ 「删裸形」不等于「按出现次数还债」;要腾余量得优先清**无族可归**的裸形态,而写文档时一开始就别用裸形才是正解。另注:写在模块头修改记录行里的第 7 处本来就被「变更记录行豁免」挡住不计数,所以账面是 6 不是 7。 | -| 2026-10-27 | 新增 §7.7:实测拆解「不可判定绝对数」的构成(裸形盲区 834 + 噪声白名单 326 + 真·硬不可判定 2 = 1,162,精确闭合),并写入每批自证没吃余量的五项式做法(含「不得用 stash/checkout 回退别人在飞改动」与 --update-baseline 只下调);同批撤回一条 Lead 错指令——「怕吃余量而把编号写成散文」恰好是 §7.6 这根护栏要防的稀释行为 | -| 2026-10-26 | **方案 B(同日续批)**:登记簿系 `N-x`/`S-x`/`T-x`/`A-x` 与 UI 簇 `U1~U5` 共 20 个号停发、约 418 处引用转语义短语(字面量净减 443:8,946 → 8,503);新增第二根护栏「不可判定引用绝对数上限」(`undecidable_total_ceiling`,只减不增),并把比例基线下调——理由与实测(比例跌、绝对数不涨)见 §7.6;`CHANGELOG_ROW` 补「版本号 + 日期」表头的变更记录行 | -| 2026-10-26 | **清号批次**(用户裁定:字母+数字编号太多、没人认得):全仓删除「属主已死 / 从未启用」的编号约 1,100 处,规范 §4.1 收成全活族 + §4.1.1 列已清除族,§4.2/§4.5/§7.1/§9 作废压缩。门禁口径不变(族仍登记,只拦新增引用);扫描面 / 字面量总数 / 台账 / 比例基线按本批实跑重打(见 §3、§7)。新增 §7.5 讲清"比例上升 ≠ 卫生变好"的读法 | -| 2026-10-25 | 二进制工件跳过(§6 第 9 条):`iter_files` 按 gzip 魔数/头 2KB NUL 嗅探排除 gz/png 等,防乱码伪编号顶出校验 1 假新账(f3rounds gz 入库实测触发);602 处存量台账口径不变 | -| 2026-10-25 | 补「`owner_docs` ≠ 定义集」口径(§2 末条):`snapshot_only` 族的登记处挂在规范正文时,`_def_owners` 为空 → 只恢复可判定、不参与悬空/撞号/裸形/紧邻。基线 82.6% → **84.0%**(删《项目审查与优化建议报告》+ 补登 11 条已死号别名后重打,实测 84.02%、696 文件 / 10410 字面量) | -| 2026-10-23 | 首篇逐项文档(数据为当日实跑:551 文件 / 8868 字面量 / 台账 640 处 / 可判定 82.85%) | +> (本文件不再记流水账:改了什么是正文说了算,改动过程查 git log。) \ No newline at end of file diff --git a/docs/门禁说明/layer-deps.md b/docs/门禁说明/layer-deps.md index b04f0dc2..d8f1b61b 100644 --- a/docs/门禁说明/layer-deps.md +++ b/docs/门禁说明/layer-deps.md @@ -97,7 +97,4 @@ ## 9. 变更记录 -| 日期 | 变更 | -|---|---| -| 2026-10-23 | 首篇逐项文档(在册 6 条基线逐条列出,含每条的属主背景) | -| 2026-10-25 | 道B(task/UI-rec-reader)还清 UI 记录 3 条:`ui_w_records` 注入式 reader(§7.2 契约落地),基线 6 → 3 | +> (本文件不再记流水账:改了什么是正文说了算,改动过程查 git log。) \ No newline at end of file diff --git a/docs/门禁说明/lv-conf-sync.md b/docs/门禁说明/lv-conf-sync.md index 8ed917ec..1e54647d 100644 --- a/docs/门禁说明/lv-conf-sync.md +++ b/docs/门禁说明/lv-conf-sync.md @@ -77,9 +77,3 @@ - 扩充受检宏清单要同步 `--list` 输出;新增 INVALID 词表时要跟着 LVGL 版本走,否则会把合法宏 误判成不认(假阳性会逼人 `--no-verify`,比没有门禁更糟)。 - -## 9. 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-10-23 | 首篇逐项文档(含 64,576 B / 23.5% 死代码实测出处) | diff --git a/docs/门禁说明/mem-budget.md b/docs/门禁说明/mem-budget.md index 8cab17f8..d8db3411 100644 --- a/docs/门禁说明/mem-budget.md +++ b/docs/门禁说明/mem-budget.md @@ -92,10 +92,3 @@ RAM 预算门禁 FAIL:RW_CCM 占用 92.3% > 92%(阈值 92%) - 抬阈值前必须在台账里写清"为什么 92% 变松了",否则等于把刹车线往后画; - 新增区域(例如再开一个自定义段)要同时改解析器与台账口径,否则新区域完全不在监控内; - `--update` 的 tsv 是趋势事实源,改列格式会让 `--trend` 的历史对比失效。 - -## 9. 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-10-27 | §6 补第 8 条:同码凭证按 **git 索引 blob** 生成,工作区有在飞改动时 `--local` 必红;该检查只在 `ci_local` 的体积门禁,**不是 pre-commit 钩子**,不拦提交(成因由道G 报出、Lead 复核) | -| 2026-10-23 | 首篇逐项文档(实跑:`RW_IRAM1 57.4%` / `RW_CCM 87.9%`,阈值 92%) | diff --git a/docs/门禁说明/mem-numbers.md b/docs/门禁说明/mem-numbers.md index 21d9b8b5..e17963da 100644 --- a/docs/门禁说明/mem-numbers.md +++ b/docs/门禁说明/mem-numbers.md @@ -70,9 +70,3 @@ - 新增要核对的文档/字段:改脚本里的文档清单与解析器,**先确保 `.map` 解析不出错**再挂进提交; - 别把 `--write` 接进钩子——"自动改数字"等于允许文档自己证明自己是对的。 - -## 9. 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-10-23 | 首篇逐项文档(含 2026-09-26 的数字漂移实测记录) | diff --git a/docs/门禁说明/nested-comment.md b/docs/门禁说明/nested-comment.md index 586e69f3..cde2bb09 100644 --- a/docs/门禁说明/nested-comment.md +++ b/docs/门禁说明/nested-comment.md @@ -112,9 +112,3 @@ 注释里写了一遍那个 grep 模式,文本 grep 的计数当场虚高 1(口径与自查命令见 `docs/门禁说明/README.md` §2 首条)。数数交给 YAML 解析,注释只描述。 - 加/删一条钩子要同批改三处:AGENTS.md 的钩子数、本目录 §2 标题、配置声明,外加索引行。 - -## 9. 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-10-27 | 首篇(task-29 接线当日)。当日实测:全仓 403 文件、新发 0、存量 2 处入基线;形态电池 10/10、自测 4/4、真字节空基线回放 2 处 [NEW]。编译器侧原文按 §2.1 **冻结引用**存档——构建日志会被下次构建覆盖,所以不写「最近一次日志里仍有」这种会过期的话 | diff --git a/docs/门禁说明/no-mojibake.md b/docs/门禁说明/no-mojibake.md index dffc34a3..cb1a3e81 100644 --- a/docs/门禁说明/no-mojibake.md +++ b/docs/门禁说明/no-mojibake.md @@ -62,9 +62,3 @@ Forbid U+FFFD mojibake.......Failed - 若把覆盖面扩到 `.md`/`.py`:先全库扫一遍存量数(历史上文档里可能已有),**有存量就别直接挂 硬拦截**(会把所有人卡在提交外),要么先清要么走基线式增量拦截。 - -## 9. 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-10-23 | 首篇逐项文档(含"只覆盖 C/H、文档侧仍是人工"这条覆盖面错配的定性) | diff --git a/docs/门禁说明/registration-check.md b/docs/门禁说明/registration-check.md index 713552ec..3a474a2e 100644 --- a/docs/门禁说明/registration-check.md +++ b/docs/门禁说明/registration-check.md @@ -78,9 +78,3 @@ - 加新的注册面(例如新增一套第三方构建脚本)要同步"正向 + 反向"两向检查,只查单向会漏幽灵注册; - 放宽第 ② 类(更多豁免)前,先确认该文件真的不需要在 PC 上跑——模拟器不编译意味着该文件的 逻辑永远没有主机侧单测(见 `host-unit-tests`)。 - -## 9. 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-10-23 | 首篇逐项文档(四类缺口与两条真实死代码案例) | diff --git a/docs/门禁说明/setview-check.md b/docs/门禁说明/setview-check.md index 27e98bbd..18ee7c61 100644 --- a/docs/门禁说明/setview-check.md +++ b/docs/门禁说明/setview-check.md @@ -98,9 +98,3 @@ - 行表写法一改(新增字段、换初始化风格),先跑脚本:退出码 2 就是"脚本要先跟上"; - 新增校验项时同步新增一条"如果这行解析不到就 FAIL"的期望,不要让新校验继承 §6.1 的静默; - 想把它扩成通用"表 vs 元数据"检查器之前,先数一下真有几个这样的对象(现在只有一个)。 - -## 9. 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-10-25 | 首版(道E task-20 追加批;脚本与实现来自 task-15 批 3)。素材:`\w+` 静默跳行、CP936 半路崩、满屏横杠与 4 字符位两条像素教训 | diff --git a/docs/门禁说明/task-table.md b/docs/门禁说明/task-table.md index 9eee4838..176cf3a7 100644 --- a/docs/门禁说明/task-table.md +++ b/docs/门禁说明/task-table.md @@ -65,9 +65,3 @@ FreeRTOS 任务表一致性.......Failed - 加新的属性字段(例如 `mpu_stack_size`)要同步解析器与表头,否则新字段静默丢失; - 改列顺序会同时改两处文档,属于"生成物改动",提交里要写明。 - -## 9. 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-10-23 | 首篇逐项文档(含 2026-09 两张表落后的实测数字) | diff --git a/docs/门禁说明/test-suite-switch.md b/docs/门禁说明/test-suite-switch.md index bdabbeab..6ee8ae0c 100644 --- a/docs/门禁说明/test-suite-switch.md +++ b/docs/门禁说明/test-suite-switch.md @@ -67,9 +67,3 @@ - 新增套件宏要同时更新判定与互斥名单,否则新宏会被当成"没开"而放过; - 若改成"允许提交测试构建但要求写进提交说明",需要先想清楚:那种提交怎么和真实产品构建区分。 - -## 9. 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-10-23 | 首篇逐项文档(含"HEAD 里躺着测试固件"的实测背景) | diff --git a/docs/门禁说明/trailing-whitespace.md b/docs/门禁说明/trailing-whitespace.md index 0e9944e8..871ef996 100644 --- a/docs/门禁说明/trailing-whitespace.md +++ b/docs/门禁说明/trailing-whitespace.md @@ -54,9 +54,3 @@ Files were modified by this hook.(下面列出被改的文件) ## 7. 豁免与基线 / 8. 改这个门禁本身 - 无基线;豁免只有生成文件那一段锚点。**新增豁免目录前先自问:是不是只是今天不想整理**。 - -## 9. 变更记录 - -| 日期 | 变更 | -|---|---| -| 2026-10-23 | 首篇逐项文档 | diff --git a/docs/门禁说明/ui-golden.md b/docs/门禁说明/ui-golden.md index 7e072999..2a890139 100644 --- a/docs/门禁说明/ui-golden.md +++ b/docs/门禁说明/ui-golden.md @@ -79,11 +79,4 @@ ## 9. 变更记录 -| 日期 | 变更 | -|---|---| -| 2026-10-23 | 首篇逐项文档(含 +3 像素注入实验与"有基线 ≠ 有门禁"的缺口来源) | -| 2026-10-27 | 内容页黄金参考 **40 → 47 页**(遥测死区与系数 2 页落地,`simulator/tests/ref/` 实测 47 张:7 张新增、存量 40 张逐字节零漂移);本文件的当前态计数同步改 47,历史行 27 → 40 原样保留 | -| 2026-10-27 | 内容页黄金参考 **47 → 53 页**(通讯设置页落地并绑 `#page=comm`;判据 = `simulator/tests/ref/` 入库 `shot_*.bin` 实数 53 张,`git diff --name-status 31ca4a1f HEAD -- simulator/tests/ref` 实测只有 6 个 `A`、零 `M` ⇒ 存量 47 张逐字节零漂移);本文件的当前态计数已同步 | -| 2026-10-28 | 内容页黄金参考 **53 → 60 页**(「UI 补齐」清单清空:记录 5 页 accident / oper / alarm / start / yk 与运行报告 runreport 六页落地并在菜单树绑 #page=。运行报告 13 行分 2 页(8 + 5),第 2 页单独拍一张 shot_runreport_p2.bin 钉「第 2 页,共 2 页」页脚与 104 三枚计数,故 60 而非 59。判据 = simulator/tests/ref/ 入库 shot_*.bin 实数 60 张(tracked 53 + 新增 7)+ 存量 53 张逐字节零漂移(本批字库净新增 33 字:185→218 字 / 280→313 字形,两轮 make_font 后对既有 58 页像素零影响);文本断言 425 正向 / 36 反向(2026-10-26 写的 310 条为当时数)| -| 2026-10-26 | 内容页黄金参考下限 **27 → 40 页**(UI 三页落地;`simulator/tests/ref/` 入库 `shot_*.bin` 实测 40 个、`check_content_pages.py` 的 `PAGES` 40 项 / 文本断言 310 条覆盖 37 页 / 反向断言 29 条 16 页),标题与「拦不住什么」段同步;未列入状态那一段的覆盖面口径不变 | -| 2026-10-28 | **口径同步(数字一律不动)**:当前态计数单位「页」→「张」。判据本体 = `simulator/tests/ref/` 入库 `shot_*.bin` 实数 **60** = `check_content_pages.py` 的 `PAGES` 条目数 **60**(两份 id 列表逐一对齐、零孤儿),其中 2 张是分页页多拍的第 2 屏 ⇒ **张数 ≠ 页数**;§1 那句「60 个内容页」同批改写为「60 张 = 60 个截图态条目」。同批 16 文件 23 处(含本文件标题、`.pre-commit-config.yaml` 钩子显示名、`AGENTS.md` 钩子清单、`.dsh/skills/lvgl-simulator/SKILL.md` 正文、`scripts/board_ui_nav.py` docstring)。历史行(27 → 40 / 40 → 47 / 47 → 53 / 53 → 60)与本文件 2026-10-26 行按当日事实**原样冻结不回改**,本行只追加为末行。 | +> (本文件不再记流水账:改了什么是正文说了算,改动过程查 git log。) \ No newline at end of file diff --git a/scripts/size_attestation.json b/scripts/size_attestation.json index 996c8aa2..383a2399 100644 --- a/scripts/size_attestation.json +++ b/scripts/size_attestation.json @@ -1,15 +1,15 @@ { - "built_at": "2026-10-28T10:38:53+08:00", - "fingerprint": "b4562719f05544c215ae12c3f9de42c1bf5a7d7ec3a94e0a79df456642dd7bfa", + "built_at": "2026-10-28T21:41:36+08:00", + "fingerprint": "9715eaf78851fd5d7a972d7ccaa7d186b7c6f0de0139f9b86d9c55b73d7a6082", "fingerprint_files": 1452, "fingerprint_source": "git-index", "gated_regions": [ "RW_IRAM1", "RW_CCM" ], - "git_head": "eb2c454aed29411e806241f899db4a34494233c6", + "git_head": "8f8d97b3d8e07598d07249d4409b79f8e883b59d", "map": "MDK-ARM/STM32F407-Demo/STM32F407-Demo.map", - "map_mtime": 1793155110, + "map_mtime": 1793194894, "pct": { "ER_IROM1": 25.23, "RW_CCM": 87.89,