Commit Graph

781 Commits

Author SHA1 Message Date
wandering1 b46e44d92c docs(采集可信): 数据可信文档台阶化重构并立项故障录波
两份工作互锁(互相引用),故同一笔提交。

数据可信:全文按「五级台阶」重排(§1 全局 → §2 信度现状 → §3 M4 退出判据逐条 →
§4 设计约束 → §5 任务卡 → §6 顺序 → §7 决策 → §8 风险 → §9 边界 → §10 关系)。
恢复 §2.2 量纲错配(该节此前被瘦身删掉,test/host/prot_dim 的两处引用一直悬空);
新增 §2.7 与 §4.6:ADC 只验过直流静态标定,正弦动态波形一次也没采过——用信号发生
器在既有注入点注 ±2 V 以内的正弦即可验全周傅氏、测频、快照与削顶路由,不必往端子
加压、也不需要标准源。§6 手绘框图改 Mermaid。章节编号未重排:§2 / §4 / §7 / §10 被
App 与 test 的头注释当规范引用。

故障录波:用户裁定 2026-10-29 录波先行,三条口径——1 kHz(每周波 20 点)、8 路
电气量全录、一屏只画一路共 8 路可切换。新增设计说明(与产品需求 80 点/周波口径的
偏离显式登记;存原始码值而非工程量,绕开未标定闭锁与测频幅值门;四个所有者的跨
任务边界与三条并发陷阱;段文件字节布局;单通道回放显示契约;约 5.9 KB 静态增量
触发 R6)与卡片登记簿(数据面最小闭环 → 手动与保护启动触发 → 现场单通道回放页,
二期的 4 kHz、突变量启动、COMTRADE、104 文件传输不返工的结构约束写进设计文档)。

两张旧配图与一张新配图改由 tools/arch_diagram/ 的生成器产出,脚本与产物同笔提交。
代码一行未动:本波只交付文档与设计。
2026-10-29 13:18:28 +08:00
wandering1 49cddac0dd docs(门禁计数): 工作树方案的「31 钩子」改回声明的 51——同文件第 22 行本就写着 51
真值三源互证:YAML 解析条目数 51(仓库口径的自查命令)、带 stages:[manual] 的 3 根、AGENTS.md 的
「共 51 个钩子 / 提交期实跑 48 根」、门禁说明 README 的「声明的 51」与「51 个 hook → 28 篇」、
pre-commit 使用说明的「51 声明数,一次 git commit 实跑 48 根」——全部一致,唯一离群值就是方案文档
那条表格行里的 31;而同一份文档第 22 行自己写着 51,属文档内部自相矛盾,这是最硬的判据。

:248 取 51 而不是 48:该行主语是 ci_local,本次实跑日志实证它覆盖静态 passed=47 + manual 三根 rc=0
+ gitlint 十条,正好是声明的 51 根全跑;48 是「一次 git commit 实跑」的口径(47 静态 + gitlint),
两个数分列、不许混写。同时把裸数字改成带出处指向的写法,下次加钩子这里少一个查不到来源的数。

远程CI 指南那处只加「当时」两个字:26 是 2026-10-12 那次 gitlint 环境事故的观测值,数字本身不算错,
但句子是现在语气,会被读成今天静态段的条数(现 47)。按计数同步 playbook 的最小动作加注,不重述数字。

冻结并写明类别:pre-commit 使用说明的「当时 40 个 hook」、主机单测覆盖率口径的 39/16(句中已有
「当时」);同数不同义不动——run_boot_test.py 的「31 份 boot_log」是日志份数、verify_log.py 的
rec[31:59] 是字节偏移;命中面之外不动——.venv/ 与 Lib/ 第三方、.git/ 内的 stray 报告。
邻族实测自洽、本轮未碰:22 根专属钩子 + 19 套无专属 = 41 套、28 篇索引、51/48/47 三分列。

门禁:编号门禁 [OK];doc-links --all --sections-strict RC=0(2602 处引用、无法判定 0、194 文档,
章节引用 +1 就是新增的这处 §2 指向);两文件无 BOM、CR=0、无 U+FFFD、无行尾空格、结尾单 LF、
表格仍为 5 列;旧形态复扫「31 钩子 / 31 个钩子 / 31钩子」全仓命中 0。改动不落体积门禁指纹面,
不需要 @build。
2026-10-29 08:54:41 +08:00
wandering1 8cab390aa7 chore(task-worktree): 活跃任务上限 3 提到 8——磁盘不是依据,锁排队才是(引用面 15 处同步)
唯一事实源是脚本常量 MAX_CONCURRENT(task_worktree.py:30),报错文案与 new 的插件树提示都插值它;
其余全是引用面同步:SKILL.md 12 行(含 frontmatter 的 description 与 whenToUse——它会进技能目录)、
方案文档表格行 + 依据段重写、启动日志原子性复验流程 1 行去掉数字。

依据段按今天的实测重写,不再拿磁盘当理由:一棵纯净检出 84.0 MiB / 2857 个受控文件(docs 独占
46 MiB),.venv 与 simulator/SDL2 走目录联接共享、不随树复制,D 盘余 1.4 TB → 8 棵全开最坏约
3.2 GB(每棵再叠一次构建产物:Keil 中间件 289 MB + 模拟器 35 MB)。真正随并行数上涨的是排队:
build 锁 TTL 1.0h、bench 锁 TTL 6.0h 分别串行化 @build 与 @test,done 的合并也必须串行——8 棵是
8 个空间,仍是一套 Keil 授权 + 一块板。

扫描按全形态跑(上限 3 / 最多 3 / 第 4 棵 / MAX_CONCURRENT = 3 / 硬上限 3 / 名额),整行打印后
另抓到两处只按数字搜不到的形态:whenToUse 里的「白占 3 个名额之一」、「确实要同时开第 4 棵」
(上限变了它必须跟着变第 9 棵,否则自相矛盾)。

冻结不改并写明类别:带日期戳的历史测量(2026-10-28 一次回收 3 棵、各 89 MB)、用户原话引语、
列表与步骤序号。「83 MB」是当时 du 口径、与本次内容字节和 84.0 MiB 同数不同义 → 只补口径注并
指回方案 §4,不合并成同一个数;方案 §2 的「对象库 234 MB」保留——今天的 294 MB 含待两周宽限期
过期的不可达对象,不把临时态钉进文档。

本轮我自己写错并已改掉:新段落引用了不存在的子命令 lock list,真命令是 lock status(全仓零残留)。

验证:上限生效用 %TEMP% 隔离小仓实测(脚本按同深度拷贝,因 REPO_ROOT 由 __file__ 反推)——前 8 棵
全成功,第 9 棵 exit 2 且文案为「已有 8 个活跃任务(上限 8)」,--force 照旧放行,list 9 行;真仓
零副作用(worktree list 仍 1 条、同级 _wt 无新建目录、无 t0* 残留)。门禁:doc-links --all
--sections-strict RC=0(2601 处、无法判定 0)、编号门禁 [OK]、py_compile RC=0、四文件无 BOM、
纯 LF、无 U+FFFD、无行尾空格。改动不落体积门禁指纹面,不需要 @build。
2026-10-29 08:44:03 +08:00
wandering1 1576d7b709 fix(task-worktree): 联接列改三态点名——半联树不再被说成已联,adopt 没补齐不许报就绪
同一个谎有两处,根因是「联没联上」有两套判定:列表只取样 JUNCTION_SPECS 首项
(.venv),而 adopt 填两条。于是「有 .venv、缺 simulator/SDL2」的半联树被报成已联,
adopt 遇主线缺 SDL2 走 skip、联接失败走 warn,回来照样打「现在可以跑」——宣布就绪。

改法是把判定收成一处:
- 新增 junction_states() 三态(link / real 实体内容 / absent 真缺)与 junction_label(),
  plugin_trees() 改读三态;adopt_junctions() 也改读同一函数,消除两处逻辑分叉。
- 列表按缺的那一样分别说后果:缺 .venv 会**静默**落到机器级解释器(无 fontTools,
  即 generated-fresh 假红的老根因);缺 simulator/SDL2 是模拟器当场报错(CMakeLists.txt
  的 SDL2_DIR 是裸 set,没有环境变量逃生口)。实体目录单列齐(实体SDL2),不算共享。
- adopt 补完复算一次,仍缺就打「还不能算就绪」,不再打「现在可以跑」;锁归属与
  锁命令照常打印。
- SKILL.md 同步四处措辞,并把「adopt 之前跑不了 Python」这条不准确的说法换成上面
  两种真实失败方式(一条是静默错解释器、一条是响亮报错)。

验证:scratch 仓 16 条断言全 PASS(全联 / 只摘 SDL2 那条 → 缺 SDL2 且不得再出现已联 /
实体目录不被覆盖 / unadopt 只摘联接 / 主线缺 SDL2 时 skip + 不报就绪 / 已联的 .venv
不误报 / 两样都缺 → 缺 .venv+SDL2),同一半联态上新旧对照 = 缺 SDL2 vs 已联。
py_compile 通过;doc-links --all --sections-strict 与编号门禁绿;两文件无 BOM、无
U+FFFD、纯 LF、无行尾空格。改动只落在 .dsh/,不进体积门禁指纹面,也不需要 @build。
2026-10-29 08:18:49 +08:00
wandering1 db5109e41d chore(size): 重打体积同码凭证——补上一笔注释收尾提交的同码缺口
@build 0 错误 0 警告之后跑 ram_baseline.py --update:新增 2026-10-29 趋势行,并由它
自动 --stamp 重打 scripts/size_attestation.json。

数字与 2026-10-28 那行逐项相同(Code 236,456 / RO 28,124 / RW 1,876 / ZI 137,084;
RW_IRAM1 62.2%、RW_CCM 87.9%,红线 92%)——所以缺的不是体积变化,是"这份源码对应
一次真实链接"的同码性:上一笔收尾提交改了保护任务源文件(纯注释)却没有重测,凭证
自那次起一直红着,主干 push 会被它拦下。

现在 check_size_gate --show 与 --local 均判同码通过;本地 CI(含体积步)全绿。
2026-10-29 07:50:33 +08:00
wandering1 21c68521ff feat(task-worktree): 桥接 DSH worktree 插件——补共享联接、锁归属 pw:<name>、修释放不掉
诉求最初是升级 dsh-task-worktree:实测已装 0.4.6 = npm dist-tags.latest,无需升级;
真正的缺口是本仓 skill 看不见插件建的树(.dsh-worktrees/),故按用户追加指令把两套
系统接起来。回收方向刻意不打通:本 skill 永不删插件的树。

脚本 task_worktree.py:新增 plugin 子命令 list/adopt/unadopt,事实源是 git worktree
list(不是插件 manifest,免得被绕过);adopt 只补缺失的 .venv 与 simulator/SDL2
联接,已有联接跳过、实体目录绝不碰;锁归属用 pw:<name> 前缀;new 顺带提示另有 N 棵
插件树、不占活跃上限 3。
一并修一处真 bug:lock release --bench-pass 在任务无台账时先 EnvError 退出、锁释放
不掉,导致每个任务的 done 收口连坐失败;现在改为警告后仍然释放。

keil-build:default_lock_task() 增加 .dsh-worktrees/ 反推分支,插件树内的构建归属
pw:<name> 而不是兜底的 build-cli(主树行为未变,本次 @build 实测仍走 build-cli)。

.gitignore 预先忽略 .dsh-worktrees/,让插件的 ensureIgnored() 找到同一字面量、不再
改写这份受控文件。check_doc_links / check_layer_deps / gen_refgraph 三处扫描面同步
排除:仓里再放一份仓会让 doc-links 假红、并让生成的配图字节漂移到 generated-fresh。

文档:并行任务工作树方案新增 §3.4 两套系统边界对照;SKILL.md 加 §F 共存一节,同时把
§B 从 53 行压到 29 行(净 +39,用户此前在飞的改写已 rebase 保留、未被覆盖)。

验证:@build 0 错误 0 警告;scripts/ci_local.py 48 根提交期钩子与 gitlint 全绿;
check_doc_links --all --sections-strict 通过(2596 章节引用、无法判定 0);id-check-new
通过;改动文件字节体检无 BOM、CRLF 与 U+FFFD。桥接行为在临时 scratch 仓端到端跑过
(adopt 建两个 reparse、unadopt 只摘联接、pw 锁取放、缺台账也能释放、越界 name 退 2)。
2026-10-29 07:50:05 +08:00
wandering1 5f69f38dfd chore(term): 并发会话收尾四处——注释术语、引用路径、计数解绑
这四处是并发会话留在工作区的完成态改动,按用户「全部都提交」一并
入库,逐项依据如下。

- App/task/protect_task.c:三处静态变量注释「上拍」→「上一拍」,
  纯注释无语义变化。@build 实测 0 错误 0 警告(Code=236456
  RO-data=28124 → ER_IROM1 264580,与 scripts/size_attestation.json
  同数;RW=1876 / ZI=137084)。
- docs/UI设计/RemoDispBus协议与接收设计说明.md:补术语同义说明
  (「远程显示」与「远程画面推送」同义,都指 RemoDispBus 推流)。
- docs/测试说明/m2_data/README.md:对端脚本路径改为
  test/host/latency_peer.py——原写的 test\latency_peer.py 已不存在
  (实测 No such file,脚本现落在 test/host/ 下)。
- docs/环境与部署/并行任务工作树方案.md:408:索引行改为「提交门禁
  钩子逐项详解」,不在文档里写死钩子条数(声明数唯一口径源 =
  docs/门禁说明/README.md §2,加钩子时少一处必改点)。

门禁:pre-commit run --all-files = 47 根 Passed、0 Failed,rc=0。
2026-10-29 00:58:23 +08:00
wandering1 41670a1cc6 docs(gates): 主机单测套数复点同步——41 套 / 无专属钩子 19 套
第 41 套 boot_stats 由 728d6067(2026-10-27 11:29)入库,全仓写的
「40 套 / 18 套无专属钩子」从那天起过期;本轮按实测复点同步。

真值双源互证:test/host/*/run_unit_test.py 实数 41(43 个目录,除
common 与 __pycache__)= scripts/check_test_coverage.py 自报
suites=41/41。专属钩子 22 根(YAML 解析 id 以 -unit-test 结尾,
22 条全对得上有 runner 的目录)⇒ 无专属钩子 19 套 = 41 − 22。

改当前态共 18 处:AGENTS.md 提交门禁节三处、.pre-commit-config.yaml
test-coverage 注释、docs/门禁说明/host-unit-tests.md §6 第 4 条六处
(无钩子名单首位补 boot_stats、目录数 42→43、裁定句改「裁定当时
18 套,2026-10-28 现值 19 套」)、docs/门禁说明/README.md、
docs/代码规范/pre-commit使用说明.md 两处、docs/编号规范.md、
scripts/README.md、docs/任务规划/分工说明-20261028 一条、
docs/测试说明/主机单测覆盖率口径.md 追加 2026-10-28 = 41 套 ~105 s
新实测点、test/host/sys_log_mcu/sys_log_mcu_test.c 注释行。

刻意不动:带日期戳的历史耗时与套数行(只追加新的实测点,不覆写)、
host-unit-tests.md 里「22 根 / 40 套 / 18 套无专属钩子」这句复核原文
(只在后面追加更正)、scripts/archive/id_gate/ 留档两处、
同数不同义的五处(40KB 级 / −20~40% / 不到 40 行 / 18 断言点 /
板端 RTC 套件)。钩子数 51、专属 22 根、提交期实跑 48 根本轮实测
未变,相关句一字未动。

门禁:doc-links --all --sections-strict / id-check-new --worktree /
no-mojibake / bom-drift / validate-config 全 rc=0,
test/host/sys_log_mcu 单测 rc=0;改后复扫「40 套」仅剩 3 处
(1 处刻意保留 + 2 处留档)、「42 个目录」0 处、「18 套」仅剩 2 处
(都带「当时」口径)。
2026-10-29 00:58:23 +08:00
wandering1 295eb9911f ci(gates): 覆盖率总闸与全量 cppcheck 移到远端 CI 强制(提交期实跑 48 根)
用户裁定 2026-10-28:慢钩子不再压在每个 git commit 上,由远端
CI 强制;本地等价入口 = scripts/ci_local.py 的 manual 段。

实测三根耗时:cppcheck 20.5 s、test-cppcheck 38.1 s、
test-coverage 105.2 s,合计 ~165 s ≈ 一次带代码提交耗时的
三分之二(test-coverage 的 files: 覆盖 App/,改一行就跑光 40 套)。

- .pre-commit-config.yaml:cppcheck / test-cppcheck /
  test-coverage 加 stages: [manual] + 理由注释;替换掉
  test-coverage 上方「没写 stages → 所有阶段都跑、输出出现两次」
  的旧坑注释(固定 manual 后不再有这一坑)。
- .gitea/workflows/ci.yml:static-gates job 在静态门禁步之后
  新增「手动阶段门禁(覆盖率总闸 + 全量 cppcheck)」步,
  if: always(),逐根 --hook-stage manual(pre_commit run 不支持
  多 id),日志 ci-artifacts/manual-stage.log + 归档 + STEP_SUMMARY,
  rc≠0 即失败;run 块纯 ASCII。
- scripts/ci_local.py:新增 MANUAL_STAGE_HOOKS 与 run_manual_stage()
  (静态段之后默认跑),删 run_coverage() 死代码,--coverage
  降级为兼容别名。
- AGENTS.md + 12 篇 docs/scripts/README:三数同源口径改为
  声明 51 / 提交期 --all-files 实跑 47 / +gitlint = 48,
  其余 3 根在 manual 阶段;历史测量数字只加「当时」不回改。

验证:pre-commit run --all-files = 47 Passed / 0 Failed rc=0;
manual 三根 Passed(test-coverage line 89.8% func 93.2% 41/41 套);
ci_local.py --static-only 全绿;check_doc_links --all
--sections-strict rc=0、mojibake / bom-drift / id-check-new rc=0;
ci.yml yaml.safe_load 通过。未改任何 .c/.h,故未跑 @build。
2026-10-28 23:04:59 +08:00
wandering1 e9cae5fdcd chore(size): 重打体积凭证(合树后同码 @build 0/0,数字未变)
前面几笔(含并发会话那两笔)改动了在册文件,凭证指纹还停在 21:41 的
索引上,体积门禁因此报「代码与测量不同码」。现在按合树后的状态重打:
@build 0 错 0 警,Program Size Code=236456 RO=28124 RW=1876
ZI=137084,与 scripts/ram_baseline.tsv 的 2026-10-28 行完全一致,
所以台账不追加新行(ram_baseline.py --update 自行判定同码不重复登记)。

check_size_gate.py --stamp / --local 均 rc=0。
2026-10-28 22:24:33 +08:00
wandering1 261bd9fd31 fix(keil-build): 定性并挡住 %SystemDrive% 字面量垃圾目录(并发会话在飞工作)
@build 与 fontTools 类脚本在残缺环境里起子进程时(run_code 的 Node
进程 process.env 为空),Windows known-folder 的**可展开串**展开不了
→ 变成相对路径,于是仓库根长出 %SystemDrive%/ProgramData/Microsoft/
/Windows/Caches/(约 1 MB 缓存的字面量复刻),它不是任何人在飞的改动。

- SKILL.md:新增「构建副产物」一节——症状 / 根因(三条现场证据)/
  清理(只用 bash 引号形态,明令禁止 rd /s /q %SystemDrive%,cmd 会
  把它展开成 C: 等于对系统盘下令递归强删)/ 两层防复发(.gitignore
  已入库 + 脚本守卫),并在坑表加一条速查
- keil_build.py +115 行:拉起 UV4 前 harden_windows_env() 回填缺失的
  SystemDrive/SystemRoot/ProgramData/USERPROFILE/TMP 等并就地展开残留
  的 %VAR% 字面量,命中打 WARN: ENV_SPARSE;构建后
  check_percent_literal_junk() 见到字面量目录只打 WARN: JUNK_DIR 并
  给出安全删除命令(守卫是兜底不是许可:@build 仍须走继承完整环境
  的 shell,删目录也不由构建脚本代劳)

py_compile 通过、--help 正常。本笔是并行会话在飞的改动,按用户
「把所有内容都 commit」的指示代为落盘;要退回:git reset --soft HEAD~1。
2026-10-28 22:22:59 +08:00
wandering1 16be01915d chore(docs): 补齐文件末尾换行(end-of-file-fixer 实测 18 篇)
CI / 静态门禁 (pre-commit) (push) Failing after 46s
CI / 主机侧单测 (MSVC) (push) Failing after 43s
提交后台跑 scripts/ci_local.py 时 end-of-file-fixer 报 Failed 并就地修复:
17 篇补文件末尾换行、1 篇去掉行尾空行。

内容零变化:git diff --ignore-all-space 只有 1 处空行删除;18 篇均在
上一笔流水清理里被改过,恢复补丁时把上一轮的 EOF 修复冲掉了,这一
笔补回。
2026-10-28 22:12:59 +08:00
wandering1 94cce8b615 docs+scripts: 删除测试与架构专项文档并把引用改成就地口径
这是并行的另一路在飞的改动(本会话按用户「全部提交」指示代为落盘):
移除 docs/任务规划/测试与架构专项.md,并把指向它的引用改成就地口径
(app_assert.h / net_socket.c / ch395f_test.h 头注释改指本文件注释或
对应文档,check_size_gate.py 与 ram_baseline.py 的出处改指 CI 文档,
RAM预算台账、暂缓-RS485、采集与算法层设计说明、cubemx-survival、
id-check、两份 README 同步改引)。

如要拆回:git reset --soft HEAD~1 即可把这一笔退回工作区。
合树后 @build 0 错 0 警(Code=236456 RO=28124 RW=1876 ZI=137084)。
2026-10-28 22:00:34 +08:00
wandering1 511fd30cc6 docs: 清理全仓变更记录流水(43 篇整节删 / 23 篇留一行 / 5 篇保留)
用户裁定:文档只写现状,历史流水一律删掉,过程查 git log。

- 43 篇「变更记录 / 修订记录」整节删除:继电保护规划 12.6 KB、产品
  需求 11.8 KB、项目部署环境 5.5 KB、BSD Socket 指南 5.3 KB、架构
  总览 5.0 KB、实机测试实施指南 3.8 KB 等
- 23 篇别处仍有指向:只留节名 + 一行「本文件不再记流水账,过程查
  git log」,节号与锚点不位移(doc-links 不因此断链)
- 5 篇整表保留(被当唯一证据 / 活台账引用):看门狗设计说明、配置
  文件设计说明、RAM预算台账、内容页架构、本地工具路径环境变量方案
- 规范同步:文档规范 §5.1 改新裁定;测试文档模板规范删示例节与
  登记句;测试开发标准流程 / UI 两篇 / 实机测试实施指南 / 四篇单测
  说明 / 并行任务工作树方案 / 编号规范 的「登记变更记录」改「写进
  正文」
- 技能同步:stale-doc-count-sweep / ui-verify / id-family 三个 SKILL
  正文不再要求追加流水行(顺带消掉 SKILL.md:121「产品需求 §12」
  失效引用)
- 修 5 处悬空指针:采样有效性校验目录锚点、BSD 指南「文末变更
  记录」、docs/README 过期描述、网络自愈架构两处指向面

72 篇文档净减 600 余行;check_doc_links --all --sections-strict 可判
定比例 61% → 78%、失效引用 0;静态门禁 passed=50 failed=0;gitlint
10 条历史提交信息 0 failed。

未提交他人在飞改动:.dsh/skills/keil-build/*(%SystemDrive% 守卫)。
2026-10-28 22:00:34 +08:00
wandering1 0e4cc03c2d docs(ADC): 更正注入验证口径——已知电压注入 2026-10-27 台架已闭环
数据可信.md §2.6 原写「ADC 从未采过已知电压」,那是 2026-10-23 挂账
时的现状,与 2026-10-27 的台架实测矛盾——按现状重写:实测 × 判据表 +
④ 段(端子 → AINn 子板变比)缺口 + M4 承诺边界(只到 ADC 引脚电压、
eng = 0);§2.6 节号与「承诺边界」口径保留,代码头注释的引用不断。

同族陈旧现在时一并更正:继电保护规划「引脚级注入验证仍为待做项」、
ADC通道映射 §7.1「不填任何实测数值」、ADC输入层单测说明「板端无信
号源、无法验证读到的是哪只脚」、adc_input.c 与 test/host/adc_input
两份注释「注入验证做不了」→ 统一改成「台架已一次性验过(§8.1),
主机单测与开机自检仍必要」。首帧悬案等历史叙述删除,只留结论。

顺带:ADC 输入层单测计数 101 → 103(runner 报 103/103 与 CHECK 调用
点 103 处双源互证),test/host/README.md 同数同步。

验证:@build 0 错 0 警(Code=236456 RO=28124 RW=1876 ZI=137084);
test/host/adc_input 103/103 rc=0;check_doc_links --all 0 处失效;
该批文件里的变更记录节按同日裁定一并清理。
2026-10-28 22:00:33 +08:00
wandering1 8f8d97b3d8 docs(编号): 批次六余账文档面——CubeMX 层号、双写疤、采集链旧层名共 61 站点
CI / 静态门禁 (pre-commit) (push) Failing after 8m4s
CI / 主机侧单测 (MSVC) (push) Successful in 27s
- CubeMX 防丢失三层优先级 L1/L2/L3(批次 3c 漏网 30 处):看门狗设计说明 25、
  门禁说明/cubemx-survival 3(含「优先 L1/L2」→「优先写进 .ioc 与搬进 USER CODE
  区」)、ADC通道映射 2。
- 改名遗留的中文重叠双写 14 处:菜单页面设计「一级菜单菜单」×6、「二级菜单菜单」
  ×2;README「语义取数与有效性」重复;存储架构「3字节字节地址」;链路延迟
  「队列往返队列往返」;继电保护「出口出口与记录层」;产品需求「全周傅氏相量」重复。
- 采集链旧层名 5 处:「L2 相量层」→ 全周傅氏相量、「L0 采样驱动」→ 采样驱动层、
  「L2-x 前缀」→ 相量输出标签前缀、「L1 层 v2.3」→ 语义取数与有效性层 v2.3。
- UI 菜单层级 2 处:产品需求「4 级(L0~L3)」→「4 级(主界面 / 一级 / 二级 /
  三级菜单)」、「主界面 (L0)」→「主界面」。
- 登记簿条目改名「L5 队列往返基线待重验」→「队列往返基线待重验」+ 引用侧 5 处
  同步(登记簿 §1/§7、实机测试实施指南 §7.3 与步骤表、编号规范 §1 好例子清单——
  那个混在短语里的 L5 恰恰是个坏例子)。归档里的历史 note 原文不动。
- 归档 §10.3:四族收口记录 + 边界与裁定(peer JSON 键属冻结证据 schema 不改;
  REQ2FIRST / FULLFRAME 不并入 FRAME_RT;L1-3/L1-4 属不可还原死号,就地删号留
  事实;「原 L2 基线 3/10」按上下文读作主机侧回归的早期基线)。
- 判族保留(永久):硬件位号与封装尺寸 27 处(网表 L1~L3 磁珠电感、
  SOT-23_L2.9-W1.3、CRYSTAL-L3.2)、芯片手册原文 3 处双写;伪命中 4 条没删
  (「遥测量 测量值」「已登记登记簿」「谁来监视监视者」×2)——那些是正常词组。
- 门禁:check_doc_links --all --sections-strict 通过(195 篇、章节引用 3292 处);
  git diff --check 干净;逐文件 BOM / U+FFFD / CRLF 与 HEAD 一致。
2026-10-28 18:57:03 +08:00
wandering1 da36f4ba56 refactor(编号): 自愈层号与 timeSync 挂起、CubeMX 三层、采集链层名清号(代码面)
批次六余账之二(代码与脚本面)。四族都是「批次一 / 三c 改了文档、漏了代码」的半改
状态。

- 日志自愈:「L1 文件级自愈」→「文件级自愈」、「L2 错误去重」→「错误去重」(正文
  本来就这么叫,层号纯属多余):App/log/soe_store.c、sys_log_mcu.c 三处、
  test/host/sys_log_mcu 的测试与假件头共 10 处。
- timeSync:「L3 pending 化」→ 挂起请求 / pending 化——这条口径早写在记忆里,
  今天才算全仓一致。App/sync/time_sync.c 3 处。
- CubeMX 防丢失三层优先级:scripts/check_cubemx_survival.py 6 处「由 L3 升级为
  L2」「L2 受保护」「L3 兜底」→ 写进 .ioc / 搬进 USER CODE 区 / 审计兜底;变迁史
  句子按「换号留事实」改写、日期原样保留。
- 采集链旧层名:App/README.md「采集与算法层(L1/L2/L3)」→「采集与算法层」;
  protect_task.c/.h「(L3 板端接线,B5)」→「(板端接线,B5)」。
- phasor 断言文案 19 处:改为 ASCII 的 phasor-in ring(C 字面量必须纯 ASCII)。
  改前先证明这些串无耦合——全仓只有本文件含它们、harness 只看 returncode 与汇总
  标记;改后 phasor 57/57 与基线同数。
- 零行为:剥注释 + 套登记表后与 HEAD 逐字节 / AST 相同;sys_log_mcu 141/141、
  phasor 57/57、watchdog 47/47、freq 46/46 均与动手前基线同数。
- 同一四族的文档面(CubeMX 30、采集链 5、菜单层级 2、双写 14)由下一笔收。
2026-10-28 18:52:37 +08:00
wandering1 6572591181 refactor(编号): 链路时延段号 L1~L11 → 权威 ASCII 段名(含 C 宏名与 peer 变量)
批次六余账之一。批次 3b 当时只改了 net_latency_test.c 的日志串与注释,本笔收掉剩下
的:标识符、peer 脚本、其余四个 board 文件。

- 段名映射(权威表在 scripts/archive/id_gate/编号治理历史.md §10):SPI_CMD /
  SPI_DMA / CHUNK_WAIT / TO_PC / QUEUE_RT / ECHO_RT / FRAME_RT / PROD_CYCLE /
  RELISTEN / LOGTAX / UI_LOOP。C 侧纯 ASCII,文档侧沿用中文段名。
- C 标识符 29 条规则 86 token:LAT_P13_OP_L5_RECV → LAT_P13_OP_QUEUE_RT_RECV、
  P13_ST_L3 → P13_ST_CHUNK_WAIT、LAT_P13_L3_SAMPLES → LAT_P13_CHUNK_WAIT_SAMPLES,
  并把文件内既有的 CW / QRT / LT 三个缩写前缀一并展开成同一套词,不留两套词汇。
- REQ2FIRST / FULLFRAME **不并入** FRAME_RT:它们是整帧往返段内两个不同测量
  (报告标签本就叫 req2first_mcu / fullframe_mcu),并入会撞名并丢掉区分度。
- peer(test/host/latency_peer.py)42 条标识符 + 7 个小写局部量 + 操作表整表重排。
  **JSON 输出键 l5_recv / seg_l6 / frames_l7 等 48 token 刻意不改**——它们是
  docs/测试说明/m2_data/ 五份冻结实测数据的 schema,改名等于让代码与归档证据
  漂移;边界与理由写进归档 §10.3,是**有记录的例外**不是漏网。
- 注释 23 处;顺带修一处上一批路径残留:peer 被写成 test/latency_peer.py,实际
  在 test/host/ 下,三处注释改对。
- 站点:test/board 111 + Drivers/BSP/CH395F/ch395f.h 1 + peer 46(无词边界口径)。
- 零代码生成变化:@build 改前/改后各一次,均 0 错 0 警且 Program Size 完全相同
  (Code=236456 RO=28124 RW=1876 ZI=137084)。被改名的标识符全落在
  ENABLE_PHASE13_TESTS 区间内 → 另开 TEST_SUITE_CH395F + PHASE13 组合编一次
  (0 错 0 警),套件开关事后无条件还原、sha256 与还原前一致,再重建产品构建。
- 等价证明:剥注释 + 套登记表后与 HEAD 逐字节相同(not_equivalent=0)。
- 禁改一字未动:console_log 的 "L1\r\n"(测试数据)、lftpd 与
  ftp_capture 的 "215 UNIX Type: L8"(FTP 应答断言)。
2026-10-28 18:49:45 +08:00
wandering1 83011abb16 docs(编号): 测试验证层级文档面清号 + 修上一批改名留下的双写与错族疤(27 篇)
同族第三道(文档面)。上一批只改了 10 篇测试文档,本笔清掉余下 27 篇的层级号,并修
那批机械替换留下的两类疤。

- 层级号改语义名:各单元测试说明的「**门禁层级** | L0.5 层(介于 L0 静态门禁与 L1
  板端套件之间)」→「主机侧纯逻辑单测(介于静态门禁与板端测试套件之间)」;
  「板端(L1)」「L1/L2」「L3 人工」等表头与列值同批改写;测试文档模板规范的模板
  字段同步(它决定以后每篇测试说明怎么写这一栏)。
- 「模拟器回归」旧号(原文标 L3/L2)**不映射**成新语义名,就地写「模拟器回归」:
  它与「主机侧回归」是两回事,硬映射等于造一处新的口径错。
- 修双写疤 17 处(替换串套替换串的产物):文档道改完 Lead 点名的 8 处后中途失败,
  Lead 接手余下 9 处——测试开发标准流程 7、CI README 1、门禁说明/host-unit-tests 1、
  任务规划/测试与架构专项 1。
- 修**错族替换疤**(比双写更坏:字面改对、意思改错):ADC输入层单元测试说明与
  相量层单元测试说明的「介于 L0 静态门禁与 语义取数与有效性板端套件之间」——上一批
  把测试层的 L1 换成了采集链层名;本笔随该行改写一并修正。产品需求 §7.4 同类问题
  在上一笔(代码道)修。
- 变更记录历史行按「行内换号、日期与技术事实不动」处理(与「卡」族先例一致),
  换算表与撞族警示在 scripts/archive/id_gate/编号治理历史.md §10 / §10.1。
- 刻意未动:docs/芯片手册(外部手册原文)、UI 菜单层级残留 2 处与采集链旧层名残留
  (已登记 task-12)、test/board 的链路时延段号残留(task-11)。
- 门禁:check_doc_links --all --sections-strict 通过(195 篇、章节引用 3292 处);
  id-check-new --worktree rc=0(剩 2 处 WARN 是变更记录行里的已停发测试专项号,
  不拦提交,本笔不越族去动它);112 个改动文件 U+FFFD=0、无 CR、BOM 与 HEAD 一致;
  git diff --check 干净。
2026-10-28 17:56:21 +08:00
wandering1 04997e48aa refactor(编号): test/host 与 App/Drivers 注释去测试层级号(73 站点 / 64 文件)
同族第二道:代码注释面。41 个 run_unit_test.py 文件头与引用行、common harness 与两份
README、4 个 *_test.c 文件头、App/** 14 处(含 BOM 文件 App/cfg/cfg_file.c)、
GD5F nand_ftl.c 1 处,共 73 站点 / 64 文件;措辞取「主机侧纯逻辑单元测试运行器
(纯标准库)」避免同行「主机侧」重复。

零行为改动(机器证据,不是口头):
- 17 个 .c/.h 剥掉注释后与 HEAD **逐字节相同**;
- 42 个 .py 走 ast.dump 比较、仅归一 docstring(真实字符串字面量参与比较,故旗标或
  输出文本被动过必然报红)→ 全部相等;behaviour_changed=0。
- py_compile 42/42;抽跑 watchdog 47/47、freq 46/46(动手前先取基线,改后同数);
  CR 字节 0、EF BF BD 0、BOM 与 HEAD 逐一一致、check_bom_drift rc=0。

刻意未动:6 处字符串字面量(FTP 应答 "215 UNIX Type: L8"、lftpd_test.c SYST 断言、
console_log_test.c 的 "L1\r\n"、phasor_test.c 的 "L2-in ring" 文案与 printf 标题)——
改了就是改测试输出/行为;UI 设计令牌层 L0(ui_tokens.h、ui_content_page.c)与
test/host/README.md 的算法层号是**另外的族**。

两条 SyntaxWarning(ftp_cfg / net_cfg 文件头 \S 转义)**HEAD 同样存在**,已对 HEAD 副本
复现证明非本次引入,未顺手改。
2026-10-28 17:52:55 +08:00
wandering1 842d711ed6 refactor(编号): 测试验证层级去号——CI job / 门禁输出 / 命令行旗标换语义名 + ASCII 段名
用户裁定「我不想看到编号」。测试验证层级这一族的整族清退分三道并行:本笔是**代码与 CI 道**
(CI 步骤与门禁输出面),代码注释面另走、文档面由文档道走。

口径(旧 → 语义名 → ASCII 段名,段名只进日志/旗标/job id/文件名):
  L0 静态门禁 static | L0a 钩子解释器预检 preflight | L0b 提交信息门禁 commitmsg
  L0c 体积门禁 size | L0.5 主机侧纯逻辑单测 host-unit | L0.5c 覆盖率 coverage

- scripts/ci_local.py 43 站点:段标题与 [SUMMARY] 标签改 ASCII 段名(static: /
  host-unit:),函数 run_l0/run_l05 → run_static_gates/run_host_unit_tests,
  收尾「已跑:」列表用段名。旗标改 --static-only / --host-unit-only,**旧旗标
  --l0-only / --l05-only 保留为 argparse 别名**(肌肉记忆与既有脚本片段不断档,
  实测 --help 两名列出)。
- .gitea/workflows/ci.yml 42 站点:job id l0-gates → static-gates、
  l05-host-unit-tests → host-unit-tests;步骤名与 step-summary 标题改语义名;
  日志名 l0-pre-commit.log → static-pre-commit.log、l05-<模块>.log →
  host-unit-<模块>.log;::error::/::notice:: 文案同步。yaml.safe_load 核过
  两个 job id 与步骤名。
  host-unit-tests;步骤名与 step-summary 标题改语义名;日志名 l0-pre-commit.log →
  static-pre-commit.log、l05-<模块>.log → host-unit-<模块>.log;::error::/::notice::
  文案同步。yaml.safe_load 核过两个 job id 与步骤名。
- 门禁脚本 18 站点:check_registration(登记簿理由串 7)、check_test_coverage 5、
  README 8、check_generated_fresh 2、ram_baseline 2、check_size_gate 1、
  ci_find_python.ps1 2、ci_runner_bootstrap.ps1 2、.pre-commit-config.yaml 2、
  requirements.txt 1(保持纯 ASCII)。
- skills 7 站点:task-worktree(含 [SUMMARY] 样例两行)、mem-budget、ui-verify、
  task_worktree.py 的实跑标签。
- AGENTS.md 3 站点:CI 段「只跑静态门禁 + 主机侧纯逻辑单测」、自查命令段、
  「2026-10-11 静态门禁全灭」事件名。
- 归档:编号治理历史.md 新增 §10 换算表 + **撞族警示**(同形 L0/L1/L2/L3 还属 UI 设计
  令牌层 / UI 菜单层级 / 采集链 / 链路时延段 / CubeMX 三层 / 硬件位号与 FTP 应答字面量
  等六个族,其中 6 处在字符串字面量里,改了就是改行为——故全程只按行内置换、先判族)。
- docs/产品需求 §7.4 测试分层表:去号 + 顺带修掉上一批**错族替换疤**(该表 L1/L2 行曾被
  采集链层名「语义取数与有效性 / 全周傅氏相量」「保护判据」顶替,现按内容改写为板端测试
  套件 / 主机侧回归两行)。同文档 §1.5 G5 判据行同步。

门禁:ci_local --help 两面旗标并列;py_compile 7 个 .py 全过;yaml 解析通过;
check_ids_new --worktree rc=0;git diff --check 干净;17 个改动文件 FFFD=0、无 CR、
BOM 与原文件一致(含 requirements.txt 纯 ASCII)。本族无机器识别面(单字母+数字是
新增行门禁的自述盲区),口径来自自建逐行扫描器,复扫本族形态归零。
- 交接说明:文档道 teammate 在改 CI 指南时中断,剩余 9 处双写疤与 29 处 CI 标识
  (job id / 日志名 / 汇总行字面量)由 Lead 接手改完,逐处仍走断言式行内置换。
2026-10-28 17:46:52 +08:00
wandering1 b3336ab0c3 docs(skill): stale-doc-count-sweep 收进第四轮实测教训(双源互证 / 伪命中 / 口径错)
- 新增「各计数权威口径速查表」:黄金参考张数、已绑叶数、钩子数、字库字数、字形数、
  菜单节点与叶子,每行给至少两个独立来源与已知伪命中的换算式。
- 真值步骤升级为「先剔伪命中,再双源互证」:菜单 #page= 首条是文件头注释示例行
  (计数 29 对注册表 28)、字库 bitmap_index 314 条含 notdef 故字形数 313、钩子数
  只认 YAML 解析后的条目数(grep 声明行会多算一条注释掉的候选)。
- 分类从四类增到五类:新增「数字对但口径描述错」——必须另起一笔只改口径句,混进
  数字同步那笔会让复核者以为只是顺手改措辞。
- 命中面明确宽于文档目录:含 .pre-commit-config.yaml 钩子显示名、AGENTS.md、
  skills 正文自带的计数与脚本路径。
- 新增两条硬步骤:「一笔只装一类事」、「提交后再按全部旧形态复扫归零」;并纠正
  变更记录新行位置(本仓按日期升序 → 追加为末行,不是插表顶)。
- 编号门禁口径同步到只查新增行的那道(全库语料审计已退役进归档目录)。
- 修正该 skill 自身一处错命令:把自检旗标写成了无连字符形态,实测报
  unrecognized arguments(rc=2);改成正确旗标后内建正反例自检通过。
2026-10-28 16:40:15 +08:00
wandering1 6b2c6ced1b chore(repo): 仓库根清场——一次性脚本与提交信息草稿移出,补落位口径
- 删除根目录 5 个未跟踪的一次性产物:sweep_golden_append / count / final / last 四
  个脚本与 commitmsg_a.txt。它们是 2026-10-28「内容页黄金参考计数 页→张」口径同步
  留下的映射表驱动改写脚本,本轮实测确认已全部耗尽:旧串全仓命中 0、变更记录新行
  已在各文件末行,产物入库见 dc214e14 / c0fcf4c4 / 4ba02212 / 078a27a0;全仓按脚本
  名前缀 grep = 0 引用(无任何门禁、文档、skill 提到它们)。
- 副本移入 ci-artifacts/oneshot_2026-10-28_golden_count_sweep/(已忽略目录)留可
  追溯,附 README 记录来源与「零命中 = 无剩余工作」的复跑证据。
- 同批删除:__pycache__/(两个陈旧 pyc,其中一个文件名被某次重定向写坏)、
  %SystemDrive%/(约 1 MB 字体缓存库,已核实非 junction,真系统目录未受影响)、
  sim_run.log 与 sim_selftest.log(模拟器陈旧输出,main.c 下次跑自动重建)、
  tmp_save.bin(3200 字节全零 = 一帧 160×160 单色绘制缓冲,全仓零引用的孤儿)。
- .gitignore:把「不入库」升级成「而且不落仓库根」并写明本次实测到的 5 个 ??;
  新增 /commitmsg*.txt 兜底反选(实测该命名已命中规则)。不给一次性脚本加忽略——
  忽略等于掩盖,正解是别让它们长在根目录。
- AGENTS.md 目录地图补同口径一句,让 agent 侧每次在场。
- 保留 ui_cn_chars.txt 与 ui_menu_tree.txt(生成器按仓库根定位、全仓 69 / 67 处
  引用、README 目录树已列)与 sim_config.ini(模拟器配置后端声明的运行文件)。
- 门禁:check_ids_new --worktree rc=0;check_doc_links --all 195 篇通过;
  git diff --check 干净;两份改动 U+FFFD=0、无 BOM、无 CR、无行尾空白。未碰 C 代码。
2026-10-28 16:39:46 +08:00
wandering1 078a27a096 docs(补漏): 提交后复扫逮到两处——张数口径漏网 + 绑定叶数口径闭合
这一笔是**提交之后**按全部旧形态复扫才揪出来的(复扫是收尾硬步骤):
- docs/任务规划/README.md §1:当前态仍写「内容页黄金参考 53 → 60 页」,
  与前两笔刚定的口径(当前态一律报「张」)自相矛盾 → 改报 60 张,并把
  换算式写进同一句(张数 = 页面个数 + 分页页多拍的那一张)。
- docs/UI设计/页面补齐规划.md §2.3 复核行:本表说「22 叶已落地」、而
  全树实测已绑 28 叶,两个数不同口径却并存在读者面前 → 补闭合式:本表
  22 叶 + 立项前就已绑定、不在本表内的 6 叶(装置信息 / 交流量 / 直流量
  / 网口设置 / 自检记录 / 运行记录)= 28 叶 = UI_PAGE_MAP_COUNT;本表
  未落地 5 叶 = 菜单树未绑 5 叶(33 − 28)。同时把可复核的重算方法写进
  文档(按缩进判叶子:有更深缩进后继者即非叶子;再按行内 #page= 数已绑),
  避免下轮再把 42 个节点行当叶子数。

刻意不动(本轮复扫的其余 37 处命中,逐条都能归类):
- 变更记录历史行(27 → 40 → 47 → 53→60 / 59、122/217、179/274、185/280、
  183/278)按当日事实冻结,只追加不回填;
- 带日期戳的实测已加「当时」(font-charset.md §6.1、generated-fresh.md §7、
  check_font_charset.py 注释、UI_自动化测试流程.md §2、主机单测覆盖率口径.md);
- 同数不同义:绘制缓冲红线 < 40KB、网表引脚号 119/122、字节数 262144、
  覆盖率分数 97/97、uinav 快检档自己的 18 张参考帧;
- Drivers/BSP/UI/ 三个 .c 注释里的「183 字子集」是当时的 font-charset
  实测注记:实测「天」「率」至今仍不在 218 字清单里,结论未失效,
  而改 .c 注释按 AGENTS 须先 @build 0 错 0 警,不混进文档同步这笔。
2026-10-28 15:45:43 +08:00
wandering1 c0fcf4c4f7 docs(口径): 三处带日期戳的实测只补「当时」锁口径,不臆改成现值
三条命中都不是陈旧值、而是**当时的实测记录**,改成现值等于把历史测量
冒充现状;动作 = 只补「当时」二字(并按需注明现值出处):
- docs/内存管理/RAM使用分析与优化方案.md §4.1.1:2026-10-15 缩池那次的
  验证口径里「11 页黄金参考」→「当时 11 页」;该集合现按入库张数报 60 张。
- docs/门禁说明/generated-fresh.md §7:2026-10-26 接线基线里的「183 字」
  →「当时 183 字」(现值 = ui_cn_chars.txt 唯一码点 218,ASCII 区 0 个),
  并按日期升序在 §9 末行追加当日一行说明本次只锁口径、没动旧数。
- docs/UI设计/UI_数据供给设计说明.md §9 判据表:2026-10-26 双次逐字节
  一致那次写的是「当时下限 27 页」,同句现值改报 60 张(与判据本体同源)。

同数不同义、刻意不动(写明理由):docs/UI设计/UI_界面制作流程.md 的
「最坏路径 < 40KB」是绘制缓冲红线;docs/硬件平台/V0.1_网表详细分析报告.md
的 119/122 是引脚号;docs/测试说明/CH395F_Test_Guide.md 的 262144/4097
是字节数;docs/测试说明/主机单测覆盖率口径.md 的 97/97 是覆盖率分数。
2026-10-28 15:40:40 +08:00
wandering1 4ba02212eb docs(门禁): 钩子计数与门禁索引同步到实测口径(51 / 50+1 / 22 / 28 篇)
实测口径(三数同源):
- YAML 解析后的 hook 条目数 = 51(不是文本 grep 声明行)。
- gitlint 未声明 stages(实测 stages = None)→ 按默认属全阶段计,
  pre-commit 阶段 50 + commit-msg 阶段 gitlint 1 = 51。
- 带 -unit-test 后缀的专属钩子实测 22 根(AGENTS 的 Lead 裁定 2026-10-27:
  不补第 23 根)。
- docs/门禁说明/ 下除 README 外实测 28 篇(上一轮加钩子没同步篇数)。

逐处:AGENTS.md 补齐 2026-10-25 道E 三根钩子的逐项枚举(补齐后该行
各项相加才等于 51);docs/代码规范/pre-commit使用说明.md 两阶段表
49/50 → 50/51、§5 文件表 40 → 51 并注当日 51 → 52 → 51 净零;
docs/门禁说明/gitlint.md 的 --no-verify 跳过面 39 → 50(= 51 减自身);
docs/门禁说明/README.md 索引 27 → 28 篇、grep 自查口径改为锚定行首的
实测结果、硬拦截行 16 → 22 个主机单测;test/host/README.md 16 → 22 两处;
docs/环境与部署/并行任务工作树方案.md 30 / 40 → 51;
docs/测试说明/测试开发标准流程.md 那条 2026-10-11 审计的「18 个钩子」
加「当时」锁口径、不臆改成现值;两份 skill 正文里的 id-check 说法改为
「已于 2026-10-28 退役、现行只查新增行」。
2026-10-28 15:37:02 +08:00
wandering1 dc214e1426 docs(UI): 内容页黄金参考当前态改报「60 张」,三数按双源实测同步
三数实测真值(每项两个独立来源互证):
- 张数 60:simulator/tests/ref/ 入库 shot_*.bin 实数 60 =
  check_content_pages.py 的 PAGES 条目数 60(id 逐一对齐)。
- 已绑 28 叶 / 未绑 5 叶:ui_page_registry.h 的 UI_PAGE_MAP_COUNT 28 =
  ui_menu_tree.txt 剔掉文件头注释示例行后的 #page= 实数(不剔是 29)。
- 字体 218 唯一字 / 313 字形:ui_cn_chars.txt 唯一码点 218(ASCII 区 0
  个,ASCII 0x20~0x7E 由生成器子集参数另计、不算进字数);
  ui_font_cn_12.c 的 .bitmap_index 条目 314 条含 notdef,剔掉 notdef →
  313 = 218 + ASCII 95。

口径更正(数字一律不动):当前态计数单位由「页」改报「张」——张数 =
页面个数 + 分页页多拍的第 2 屏(runreport_p2 / sparam_p2 两张),两个数
不许互相冒充。同日先前那行「53 → 59 页」是页面个数口径、与判据本体
不同源,原文冻结不回改,只在各文件变更记录末行追加当日更正。

历史一律冻结:变更记录里的 27 / 40 / 47 / 53→60 / 59 与字库 122/217、
179/274、185/280、183/278 都是当日快照,只追加、不回改。

夹带说明:.pre-commit-config.yaml 一并入本笔——pre-commit 要求配置本身
已 staged 才允许提交;该文件的改动是 ui-golden 显示名(60 页→60 张)与
一条钩子计数口径注释(同日 51 → 52 → 51 净零,属另一类,已在此点名)。
2026-10-28 15:33:42 +08:00
wandering1 a75bc03ab5 docs(任务规划): 菜单树叶数实测复核 42/33/28/5 全部成立,只补判定方法与「当时」口径
按 ui_menu_tree.txt 文件头规则实测(缩进即层级、每级 2 空格、# 开头为
注释、空行忽略):节点行 42 = 9 个菜单节点 + 33 叶;叶行行尾带 #page=
的已绑 28、未绑 5(遥信类型 / 遥信防抖 / 双点遥信 / 手动录波 / SNTP设置)。
双源互证:tools/menu_gen/gen_menu.py 的 parse_tree 重跑得
nodes=42 leaves=33 bound=28 unbound=5;生成物 ui_menu_tab.h 的
UI_MENU_TAB_COUNT=42 与 ui_page_registry.h 的 UI_PAGE_MAP_COUNT=28
——两源逐项一致。剔伪命中:grep -c #page= 得 29,多的 1 是文件头第 5 行
注释里的示例行,不算节点行,故真值取 28 而不是 29。

结论:两份规划文档的当前态叶数本来就对,本笔不改任何数字,只补口径与方法:
- UI补齐.md §1 判定新增第 4、5 条:未绑 = 待做 + 不做(0 + 5 = 5)闭合式;
  并写明按文本计数会把头部注释示例行算进来(29 = 28 + 1),真值以生成物为准。
- UI补齐.md §1 三个错算法:21 / 23 两个错数分属 2026-10-27「已绑 21 叶」
  与「已绑 22 叶」两个时点,加「当时」锁口径,并补同一错法今天的重跑值
  (未绑 14、grep 29、去重 29),注明两个 29 只是撞号、都与真值 28 无关。
- README.md §1:同步闭合式 +「42 是节点行数、不是叶数」+ 伪命中提示。
两份文档都没有变更记录表(UI补齐.md §2 明示不留完成史)→ 无历史行可追加。
未动:docs/UI设计/页面补齐规划.md 的「27 空叶子 / 6 叶落地」与
docs/UI设计/页面扩充详细方案.md §1.1 的「已绑 6 叶」都是立项快照,
文内已有 2026-10-28 复核对齐行;id_aliases.json 的「UI 剩余 21 叶」是
退役别名留档;「最坏路径 < 40KB」一类绘制缓冲红线与叶数同数不同义。
并发提示:仓库另有在飞批次(黄金参考张/页口径,含本文件 60 页→60 张一行),
本笔只含叶数相关三处改动,未带走他人内容与他人暂存的文件。
门禁:check_doc_links.py --all --sections-strict 打印「文档路径检查通过
(195 个文档)」;check_ids_new.py 查暂存区 [OK] 新增行无未登记编号。
2026-10-28 15:03:21 +08:00
wandering1 599f05be22 refactor(编号): 测试验证层级 L0/L0.5/L1/L2/L3 → 语义名(批次 3d·文档层)
这族是验证层级:静态门禁 / 主机侧纯逻辑单测 / 板端测试套件 / 主机侧回归 / 人工目检。
实测它出现在 **97 个文件**(40+ 个 test/host 的 run_unit_test.py、.gitea workflow、
ci_local.py 的阶段标签、以及十来篇文档)。本批只做**文档层**,代码层单列一批(见下)。

改动:10 篇文档 110 行 + 三处收尾——
  测试开发标准流程 / 实机测试实施指南 / 主机单测覆盖率口径 / 门禁说明 README 与
  host-unit-tests / CI README 与远程CI完整指南 / docs README / 测试与架构专项 /
  pre-commit 使用说明。
映射:L0 → 静态门禁、L0.5 → 主机侧纯逻辑单测、L1 → 板端测试套件、L2 → 主机侧回归、
L3 → 人工目检;`L0b`(ci_local 的内部阶段标签)在文档里写成「提交信息门禁」。
测试层级那张表的「层级」列被删掉(名称列已承载同一信息,留着就是两列重复)。

**未做(代码层,单列批次 3d-2)**:`scripts/ci_local.py` 的阶段标签、`.gitea` workflow、
`test/host/*/run_unit_test.py` 的输出前缀、以及代码头注释里的 L0/L0.5 —— 那些是**程序标识**,
改名要连带 CI 日志格式与文档里对 `[SUMMARY] L0: ...` 的引用,属跨端改动,需单独验证。

验证:三篇主文档的层号残留 = 0;doc-links 通过;mojibake / git diff --check 干净;
表格列数已收敛为 3 列(名称 / 载体 / 抓住什么)。
2026-10-28 13:20:28 +08:00
wandering1 b9f5df5d28 refactor(编号): 链路延迟分段 L1~L11 → 段名(文档中文名 / C 日志 ASCII 短码,批次 3b)
这族是延迟测试的分段号(L1 SPI 字节命令 … L11 uiTask 节拍)。特殊之处:**号直接打进
串口日志字符串**,而 C 字符串必须纯 ASCII(AGENTS 铁律)——所以两份落地面用两套名:

  文档(人读):SPI 字节命令 / SPI DMA / 发送分块握手 / 芯片→线上+PC / 队列往返 /
                请求→首字节 / 整帧 3209B 往返 / 生产路径帧周期 / 连接/重监听 / 日志税 / uiTask 节拍
  C 日志(ASCII):SPI_CMD / SPI_DMA / CHUNK_WAIT / TO_PC / QUEUE_RT / ECHO_RT /
                FRAME_RT / PROD_CYCLE / RELISTEN / LOGTAX / UI_LOOP

改动:`链路延迟测试说明.md` 84 行(分段定义表的「段」列删掉、名称列即段名;正文与
基线表同步);`test/board/net_latency_test.c` 61 行(日志串与注释,行数不变、逐行替换)。
标识符一律不碰:`LAT_P13_OP_L5_RECV` / `P13_ST_L5_SEND` 这类宏与枚举仍在(它们是代码符号,
不是给人读的段号)——7 处已核完整。

一次事故:第一版把该 .c 写坏了(整篇被同名表格行覆盖),已 `git checkout` 回滚,改成
「只改命中行 + 行数断言」重做,本次 61 行、1313→1313 行不变。

验证:文档与 C 两侧段号残留为 0;doc-links / mojibake / 新编号门禁 / git diff --check 全绿。
该文件属板级测试套件(产品构建不编译它),本次只动注释与字符串,不改任何逻辑。
2026-10-28 13:19:04 +08:00
wandering1 0f0158508a refactor(编号): CubeMX 防丢失三层 L1/L2/L3 → 写进 .ioc / 搬进 USER CODE 区 / 审计兜底(批次 3c)
这族只在两处出现:AGENTS 的「平台约束 / CubeMX 与 Fault」段与 `cubemx-regen` skill 全文。
含义是重生成防丢失的三层优先级,与采集链分层 / UI 菜单层级 / 延迟分段三族都不同。

改法:层号直接换成动作短语,层级顺序用「第一层/第二层/第三层」交代——
  L1 写进 .ioc          → 写进 .ioc(第一层,权限最高)
  L2 搬进 USER CODE 区  → 搬进 USER CODE 区(第二层)
  L3 审计兜底           → 审计兜底(第三层)
另有 `L1/L2/L3 方法论` → 「这三层方法论」、`(L1 检查)` → 「(第一层检查)」、
「L3 清单已清空」→「审计清单已清空」等 8 处措辞跟着落。skill 的 description 也改了,
否则目录里还挂着编号(本次会话的技能目录快照已同步显示新描述)。

验证:doc-links / mojibake / bom-guard / 新编号门禁 / git diff --check 全绿。
本批不涉及 C 代码,@build 不必重跑(上一批 0 错 0 警的构建仍有效)。
2026-10-28 13:15:05 +08:00
wandering1 7e15f49ff3 refactor(编号): UI 菜单层级 L0~L3 → 主界面/一级/二级/三级菜单(批次 3a)
这族是菜单深度号:L0 根、L1 一级、L2 二级、L3 三级。用户 2026-10-28:「编号看不懂」,
且与采集链分层的 L1~L5 撞形(同一份文档里两套 L 号,读的人得先猜是哪套)。

改法(生成物走生成器,不手改):
- `tools/menu_gen/gen_menu.py`:加 MENU_LEVEL_NAMES 常量,生成 ui_menu_tab.c 的注释从
  `/* 12 L2 */` 变成 `/* 12 二级菜单 */`;重跑生成器,生成物 42 行注释随之更新。
- 文档 4 篇 113 行:菜单页面设计(94)、内容页架构(10)、01_主界面_说明(8)、
  中文字体生成与配置(1)。映射:L0 → 主界面(根)、L1/L2/L3 → 一级/二级/三级菜单;
  `4 级(L0~L3)` → `4 级(主界面 → 三级菜单)`;括号里的 `(L1)` → `(一级菜单)`。

范围纪律:只动 UI 菜单这一族。同名的测试层级族(L0/L0.5/L1/L2/L3,见测试开发标准流程)
与链路延迟分段 L1~L8 不动——那两个属批次 3 的另两族。

验证:@build 0 错 0 警;check_menu_rows 8 状态 PASS(5368 B 池不变);生成器重跑幂等
(rc=0,生成物只剩注释差异 42/42 行);doc-links 通过(195 文档);mojibake / bom-guard /
新编号门禁 / git diff --check 全绿。
2026-10-28 13:12:06 +08:00
wandering1 ed997a76a2 refactor(编号): 层内条目号 L1-1…L5-4 清退成语义层名(批次 2)
这族是保护规划的功能子号(层号-子项号),2026-10-27 已整族退役;本批把残留清掉。
实测:24 个唯一号 / 55 站点,分布极窄——52 站点在变更记录行(冻结历史)、1 行在
相量层单测说明、1 行在技能手册正文举例,其余为 .pre-commit 注释。

判据按《编号规范》§5.5「唯一例外」办:变更记录行里已停发族的号改写成层名/形态描述,
历史事实与数字一律不动。映射:
  L1-* → 语义取数与有效性层     L2-* → 全周傅氏相量层
  L3-* → 保护判据层             L4-* → 出口与记录层
  L5-* → 动作留痕层
并列写法(L1-3/L1-4、L4-4/L4-5、L1-1~L1-3)折叠成一个层名,不留「第几项」。

改法要点:**只改命中的行**。第一版按整文件做,把无关行的中文间空格也吃掉(6 个文件
被误伤),已整体回滚重做;本版最终 14 行 / 3 文件,并自证「纯空格变化 = 0」。
顺带修掉批次 1 遗留的「测频与遥测快照测频」重复词。

有意不动:docs/测试说明/boot_log_data/ 里的真机日志与说明(现场证据,改它等于篡改);
docs/硬件平台/ 里的电感/磁珠位号(L1~L4 同形但另一族)。

验证:doc-links --all --sections-strict 通过;mojibake / git diff --check 干净;
新编号门禁自查通过;本批无 C/H 改动,@build 不涉及(上一批代码尺寸未变)。
2026-10-28 13:08:24 +08:00
wandering1 593c5d0c84 refactor(编号): 采集链分层 L1/L1.5/L2/L2.5/L3/L4/L5 → 语义名(批次 1)
用户裁定(2026-10-28):L1/L1.5/L2/L2.5/L3 这套层号「谁能看懂」,改用语义名。
映射(同一批定稿,含 L4/L5):
  L1   → 语义取数与有效性
  L1.5 → 标定折算
  L2   → 全周傅氏相量
  L2.5 → 测频与遥测快照
  L3   → 保护判据
  L4   → 出口与记录
  L5   → 动作留痕

实测规模:384 站点 / 62 文件(App/algo、App/task、test/host 六个套件、docs/算法、
产品需求、架构总览、启动顺序、ADC 采样节拍、IEC104 上行、采集短板评测、内存管理、
AGENTS.md、README.md、docs/README.md、.pre-commit-config.yaml 与 scripts 里的注释)。

改法(不是全局替换,逐模式有上下文规则):
- 先吃同位语再落裸词:L1 有效性校验 → 语义取数与有效性校验、L2 相量层 → 全周傅氏
  相量层、L3 保护 → 保护判据、L2.5 遥测快照 → 测频与遥测快照,避免「保护判据保护判据」
  这类重复(第一版就是这么坏掉的,已整体回滚重做)。
- .c/.h 只改注释:先把字符串字面量切出去(引号数为奇数的跨行注释按整行处理),
  C 字符串里的 L2-in ring 之类原样保留——AGENTS 铁律「字符串字面量必须纯 ASCII」。
- 层内条目号(L1-3 / L2-3 这类)**本批不动**,属批次 2;另外三族(UI 菜单层级
  L0~L3、链路延迟分段 L1~L8、CubeMX 防丢失三层)也不动,属批次 3。
- 顺手修的措辞:范围写法 L1~L3 → 「分层(语义取数与有效性 → 保护判据)」、
  CI 段「不含 L1/L2/L3」→「不含采集链分层」、目录地图里同一处并列表述。

验证:@build 0 错 0 警(Code=236456,与改前逐字节同尺寸——纯注释改动);
内存布局配图已按新脚本重生成(自检通过);doc-links --all --sections-strict 通过
(195 文档);mojibake / bom-guard / coding-standard / 新编号门禁自查 全 rc=0;
git diff --check 干净。
2026-10-28 13:04:02 +08:00
wandering1 89b6132c1f docs(编号): 瘦身——58 KB/473 行 → 22 KB/222 行,过程记录进归档
用户裁定 A 方案:这份文档的「规范体系」部分已随门禁退役而死,但四件仍活着的东西
只有这里写着——① §1 政策(默认不发号 / 先问三句);② §3.3 语义标识怎么写;
③ §4.1 族总表 + §4.1.1 已停发栏(现行门禁白名单的机器投影源头);
④ §4.4 这些不是编号(防把 YX15 / 元件位号当垃圾清)。再留 §5.5 销项、
§8 门禁现状与 §8.5 退役路线、§10 速查。

其余 16 节逐字搬进 scripts/archive/id_gate/编号治理历史.md(40 KB):
1.2 / 2 八条原则 / 4.2 / 4.5 / 6 模块码表 / 7+7.1~7.3 / 8.1 基线 / 8.3 批次 /
8.4 台账 / 9+9.1~9.3(含「数据可信」任务卡号换算表),以及原变更记录 17 行流水。
归档文件带「这不是现行口径」横幅 + 归档目录,写清哪些节对应哪段历史。

两处刻意的选择:
- 节号沿用旧编号、不重排——外部文档与脚本引的是 §4.1 / §8.5 这些号,重排等于
  制造一批假链接;文首加「本文范围」说明跳号去哪了。
- 文首那段「机器面才是事实源」改写:现行机器面是 check_ids_new.py 的两张
  前缀级白名单(KNOWN_DASH / KNOWN_BARE),旧的 registry / 别名表 / 八项校验脚本
  已随全库审计退役进归档,只在手工复查存量时才用。

引用重修(6 份文档、10 处):AGENTS 的 §9.3 换算表、数据可信 §9.3 ×2、
门禁说明 id-check 与 host-unit-tests、docs/README 的 §4.5、技能手册的 §9、
以及正文里 §4.2 / §4.5 / §8.1 / §8.3 / §8.4 / §1.2 的裸引用。

验证:doc-links --all --sections-strict 通过(195 文档);mojibake / bom-guard /
git diff --check 全 rc=0;新门禁 --worktree 自查通过;钩子数仍 51。
2026-10-28 12:51:17 +08:00
wandering1 967d29e633 docs(id-check-new): 补一条盲区——--all-files 下它是空转的
本门禁自己读 git diff,不看钩子传进来的文件名:pre-commit run --all-files
(也就是 ci_local.py 的 L0)把文件当全量传入、暂存区却是空的 → 它打印通过。
这与 §6 第 4 条(未跟踪文件不在扫描面)同源,但后果不同:那条只影响手工自查,
这条会让 L0 全绿被误读成「没有新编号」。写进文档,别让人踩。
2026-10-28 12:42:15 +08:00
wandering1 1668842d61 chore(id-check): 退役全库编号语料审计(钩子 52 → 51)
第三步(用户裁定跳过观察期直接做)。第一步 bf2a5c21 把两根护栏转报告制,
第二步 a5832788 立起只查新增行的新门禁,本笔把旧的全库语料审计整体退役:
语义标识已是默认形态,这套 99 族语料不再有人需要维护。

移动(保留可复现性,不再进提交门禁):
- scripts/check_ids.py → scripts/archive/id_gate/check_ids.py
- id_registry.json(87.6 KB,99 族)/ id_aliases.json(187 KB)/ id_known_backlog.json
  一并归档;新写 archive README:为什么退役、现在用什么、怎么手工跑、归档纪律。
- 归档脚本改了自定位(仓库根往上 4 层、语料与脚本同目录)与一行退役横幅;
  从新路径实跑:811 文件 / 8,051 字面量,--strict rc=0。

钩子:删 id-check(52 → 51)。现役编号门禁只剩 id-check-new(只查新增行、零语料)。
声明数 51 = commit 阶段 50 + gitlint 1,三数已对齐(AGENTS / 门禁索引 / YAML)。

连带改动:
- rename_ids.py 的别名表路径指向归档(改名工具本身没退役);
- check_ids_new.py 排除面加 scripts/archive/(语料里全是编号字面量,天经地义);
- doc-links 跳过 .mnemon/ 与 ci-artifacts/(本地记忆状态与草稿,非项目文档)——
  语料搬家后这些目录里的旧路径引用会假红,它们本来就不该参与文档门禁;
- 全库 .md 里的旧路径引用改指 scripts/archive/id_gate/(含两份 skill 手册);
- id-check.md 加退役横幅并保留原文作留档;门禁索引把该行标成已退役;
- 编号规范 §8 改成「现行只有一道门禁」+ §8.1~§8.4 标为退役留档 + §8.5 ③ 置已完成;
  各加一条 2026-10-28 变更记录行。

验证(实测):YAML 口径 51 个钩子、id-check 不在其中;doc-links --all --sections-strict
通过(194 文档);mojibake / bom-guard / coding-standard / git diff --check 全 rc=0;
新门禁自检 5 正例 + 29 反例仍全过。
2026-10-28 12:38:38 +08:00
wandering1 a5832788e9 feat(id-check): 编号门禁第二步——新增行拦截(零语料)
背景:第一步(bf2a5c21)把两根护栏转成报告制,但全库语料审计仍在跑。
它真正的用途只有一个——拦住「新写一个自造编号」;这件事不需要 99 族语料。
所以本笔落第二步:只查 git diff 的新增行,判据收窄成两张前缀表。

新增 scripts/check_ids_new.py(241 行,零语料):
- 破折形态:首段不在 KNOWN_DASH(活族 + 标准名,11 条)→ FAIL;
  在 RETIRED_DASH(已停发族)→ 只 WARN,提示改语义短语。
- 裸形态:前缀不在 KNOWN_BARE(外设/器件/协议/点号,约 90 条)→ FAIL。
- 单字母 + 数字一律放行(元件位号与层次号同形,显式盲区)。
- 算术排除(SIZE-2 / LEN-1 这类是减法不是编号);跳过 [示例]/[计划] 行;
  行内 [编号豁免] 为最后手段。默认查暂存区,另有 --worktree / --range / --self-test。

接线:新钩子 id-check-new(钩子数 51 → 52,AGENTS 与门禁索引已同批改),
与 id-check 双跑一个观察期;观察期后按 docs/编号规范.md §8.5 ③ 退役旧语料。
旧门禁的排除面加上新脚本(它必然写着示例令牌,否则自己拦自己)。

白名单是按真实数据调出来的,不是拍脑袋:回放最近 80 笔提交,未知形态只有 15 种,
其中 12 种是设备/协议名(RS232、RS485、OVER8、YT/YH 点号等,已进白名单)、
3 种是已停发族(P-8、N-1、F-NET-*,只 WARN)→ 调好后回放误报 0。

自证(实测):
- 自检 5 正例全部拦下、29 反例全部放行(含 TC-NET-204 / TRAP-ADC-01 / TPAFE5160 /
  GD5F2GQ5UE / C12 / U15 / L3 / SIZE-2 / GPIO_PIN_5)。
- 端到端:暂存一个自造前缀 + 数字 → 钩子 FAIL;清理后 Passed。
- 反向:本页文档里举的反例自己也被拦过一次,改成带 [示例] 标记后才过——
  这条正好证明它没有「文档路径」的例外面。
- 两条门禁互不干扰:old-gate rc=0、new-gate rc=0、doc-links 通过(211 文档)。
2026-10-28 12:27:57 +08:00
wandering1 2f70230646 docs(id-check): 记一条实测盲区——未跟踪文件不在扫描面
做 ①②③ 第一步时给两根护栏做反向自证(往一个新文件里写自造前缀 + 数字)发现:
第一版探针文件没被 git 追踪,门禁报 0 处——因为 iter_files() 走 git ls-files。
提交时跑不受影响(要提交的文件必然已进索引),但手动在暂存前跑会得到假绿。
补进 §6 限制与盲区第 11 条,免得下次有人拿手工跑的结果当门禁结论。
2026-10-28 12:18:18 +08:00
wandering1 bf2a5c21b0 chore(id-check): 两根护栏转报告制——编号门禁减负第一步
背景(用户裁定 2026-10-28):语义标识已是默认形态,编号体系本身不再产生价值,
而门禁每次都花时间。实测拆账:单次运行只有 1.8 s,但 近 80 笔提交里 61 笔 改了
id_registry.json / id_aliases.json / check_ids.py / docs/编号规范.md;语料共 99 族
(78 族已冻结、8 族快照、21 族未冻结),registry 87.6 KB + 别名表 187 KB。
结论:贵在养语料,不在跑检查。故先摘掉语料审计的强制面。

本笔只做第一步(①②③ 路线见 docs/编号规范.md §8.5):
- 护栏 1(可判定比例基线)与护栏 2(不可判定引用绝对数上限)改为 只打印、不影响退出码;
  输出标签由 [比例] 改 [比例·报告],越线打 [报告] 两行并指向 §8.5。
  --update-baseline 保留(只用来把当前值记成新记录基线)。
- 校验 1~6 不动:台账外新账照旧拦提交,这是本次减负的边界。
- 同步改口径文档:docs/编号规范.md §8 表与 §8.1 护栏行 + 新增 §8.5 退役路线,
  docs/门禁说明/id-check.md §1 表 + §6 限制第 7 条 + 新增 §7.6.1,AGENTS.md 门禁段,
  id_registry.json 两条 note,各加一条 2026-10-28 变更记录行。

自证(实测):
- 把 decidable_ratio_baseline 临时改 99.9、undecidable_total_ceiling 临时改 1 →
  两护栏必然越线,实跑 退出码 0,只出 [报告] 两行;字节级还原 registry 后复跑正常。
- 反向自证牙还在:往一个新文件写一个自造前缀 + 数字(让 git 看见该文件)→
  校验 1 报 1 处错误 + 增量拦截 FAIL,退出码 1。
- 全门禁:check_ids --strict 校验 1~6 无错误(可判定 87.15% / 不可判定 1033,仅报告);
  doc-links --all --sections-strict 通过(210 文档);mojibake / bom-guard /
  coding-standard / git diff --check 全 rc=0。钩子数不变(替换口径,不加不减)。
2026-10-28 12:18:00 +08:00
wandering1 6daa01aea4 docs(UI): 字体口径更正——218 是不含 ASCII 的汉字/符号数
§7「字体体积」原写「218 字(含 ASCII/符号,共 313 字形)」与全仓其余五处口径矛盾:
实测 ui_cn_chars.txt 的 218 个码点**全是非 ASCII**(汉字与 ▶/,/: 等符号),
ASCII 0x20~0x7E 那 95 个字形是 make_font 用 -r 0x20-0x7E 另外打进去的(见同文件 §4 命令行)。
改成本仓统一口径并补上算术:字形数 = 218 + 95 = 313,
glyph_dsc 数组实含 notdef 共 314 条(逐条实测计数)。

其余各处在 94b0d790 与本轮同步里已是正确写法(UI_设计架构 §1 表、界面制作流程 C3、
菜单页面设计、simulator/README、架构总览 §3、产品需求 §8.5),本次是消除最后一处反例。
同段旧数 185 字/280 字形、183 字/278 字形(未回填)按历史快照保留不动。

验证:check_doc_links --all --sections-strict 通过(210 个文档);check_ids --strict 无错误;
check_bom_drift / check_mojibake 通过,git diff --check 干净。纯文档。
2026-10-28 12:10:19 +08:00
wandering1 11d600572b docs(架构): 补漏——中文字体当前态 122 字/217 字形 → 218 字/313 字形
UI 补齐批把页数与字数同步进了 UI 设计侧与产品需求文档,架构总览 §3「界面层」这行漏网,
是本轮全仓复扫(210 个文档)里唯一残留的当前态命中;其余 122/217、47→53、53→60
之类命中都在变更记录历史行里,按「冻结不回改」保留。

同步在本文变更记录加一行(升为末行,2026-10-14 之后本文首次改动),
并把口径指向权威处:逐叶清单 docs/UI设计/页面补齐规划.md §2.3、
实测体积与字形数 docs/UI设计/UI_中文字体生成与配置.md §7。字形数 = 字符数 + ASCII 95。

验证(实测):check_doc_links --all --sections-strict 通过(210 个文档);
check_ids --strict 校验 1~6 无错误;check_bom_drift / check_mojibake 通过;
git diff --check 干净。纯文档,不涉及构建与真机。
2026-10-28 12:08:03 +08:00
wandering1 cbb4fdb893 docs(产品需求): UI 现状同步——绑定 28 叶、黄金 60 页、字库 218/313
补上此前被并行会话丢弃的那轮同步(我在 94b0d790 里改过、随后随未提交稿一起消失),
这次落在当前版本结构上,逐项按实测真值改:

- §8.2 绑定现状:已绑内容页 28 叶 / 未绑 5 叶,页面注册表 UI_PAGE_MAP_COUNT = 28
 (2026-10-28 实测);未绑 5 叶 = 无开入硬件 3 + 手动录波 1 + SNTP 1,
  取舍与重开条件指向 docs/任务规划/UI补齐.md §5。
- §8.3 内容页:已绑 28 页;分组表补两行——记录查询 5 页(每记录 2 行、空态显无记录)
  与运行报告(13 行分 2 页、四个数逐个挂范围标签);未绑段去掉已落地的当前执行 6 项;
  像素黄金 53 → 60 页(+7 张,含运行报告第 2 页那张)。
- §8.5 中文字体:当前态改 218 唯一字 / 313 字形(实测 ui_cn_chars.txt 218 个字符,
  字形数 = 字符数 + ASCII 0x20~0x7E 共 95);122/217、179/274、185/280 标注为历史快照。
- §5.14 FR-SOE-3:由「展示层待补」改「软件面已落地;真机判据待台架」——写清七类文本
  记录 + 二进制 SOE、记录类型即日志 ID 本身、运行报告四个数的真源与下发通道,
  并把软件面已满足(空态与标签由 60 页黄金钉住)与待台架复核(真记录翻页、掉电保持、
  清除后归零、boot_count 自增与四态)分成两段,不混成一个已完成。
- §2.4 立项未排去掉已交付的记录 5 页;§9.1 差距表 UI 记录页行改写现状与去向;
  §9.2 顺序表第 1 行改「清单已清空(2026-10-28)」、第 2 行改「下一顺位(未开工),
  切换条件已满足、开工待用户点头」。§12 变更记录加一行(不 bump 版本号,v1.6 之后)。

验证(实测):check_doc_links --all --sections-strict 通过(210 个文档);
check_ids --strict 校验 1~6 无错误,可判定 7006/8039 = 87.15%(基线 86.0%),
不可判定 1033 处(上限 1166,本笔未增加);check_bom_drift / check_mojibake /
git diff --check 均 rc=0。纯文档,不涉及构建与真机。
2026-10-28 12:00:33 +08:00
wandering1 e94ce92c9f docs(产品需求·屏板链路): 提交用户的两处删除,并把删除留下的引用衔接补平
删除由用户本人在并行会话里做,本笔按「整理并收工提交」指令代提交;
Lead 只做引用衔接与形态整理,未改其结论。

产品需求设计文档 §2.4.1 范围外表删掉「屏板(板件本体)」一行后,X 表实为
X1 双核分工 / X2 工具链 / X3 一次设备接口 / X4 独立计量通道。正文里 14 处
仍按旧号引用(旧 X4 指一次设备、旧 X5 指电度、X1~X5、X4 / X5、X1~X3 等),
已逐处按新号改写;变更记录里 v1.2 / v1.3 等历史行按「冻结不回改」保留旧号
(口径 docs/编号规范.md §5.5)。

两处依赖「屏板本体是范围外项」的表述随之改写:屏板链路已从范围外项移入
范围内待做(规格 §5.16,执行规划 docs/任务规划/屏板链路.md),主机侧链路与
参考 1:1 同构、不属替代方案;不在本仓实现的只剩屏板板件硬件本体(独立工程
DTU-LCD)。§9.1 解除表的「算力 / 形态」行同步去掉对已删行的引用。

屏板链路.md:§0 风险表删掉「250 kbps 收发器上限」(已解除)与「PA10 未接线」
(已撤销)两行后,剩余两项重编号为 1、2;表格单元补一个空格成「竖线 空格 号」
形态,与全仓表格写法一致。

验证(实测,纯文档不涉及构建与真机):check_doc_links --all --sections-strict
通过(210 个文档);check_ids --strict 校验 1~6 无错误,可判定 7006/8039 =
87.15%(基线 86.0%),不可判定 1033 处(上限 1166;本笔 +3 来自改写后的号提及);
check_bom_drift / check_mojibake / check_coding_standard 与 git diff --check
均 rc=0。
2026-10-28 11:48:12 +08:00
wandering1 155bd5e1e8 docs(任务规划): 新增 RS-485 解锁与门禁口径对账分工说明
A 线(RS-485 驱动契约):补两条未修缺陷——单缓冲包撕裂改双缓冲
加帧序号,消费者一次取整帧,对齐临界区原子快照语义;
TX 超时路径先等 TC 再拉 DE,避免尾字节被截;错误码走 bsp_err 通道,
返回值不得裸丢弃(consume-result 会拦)。结论回填问题记录,
并写清解锁条件是否满足。

B 线(门禁口径对账):把 AGENTS 与《门禁说明》§2 的钩子计数对到实跑;
口径 = YAML 解析后的条目数,声明 / 文档 / 实跑三数同源,
注释掉的候选钩子不计入。

跨线接口先在本文件登记再动手;两线互不编辑对方范围。
本文件只分工、不改行为;接线节奏与建任务 / 抬栈属 Ask first,
是否接线由用户裁定,不由本分工决定。

整理项(Lead 代提交前修的 2 处门禁问题):两条指向尚不存在产物的引用,
按《文档规范》「计划中」形态在反引号内加 [计划] 前缀——
test/host/rs485/run_unit_test.py 与 docs/问题记录/RS485_Trap_Records.md;
改后 check_doc_links --all --sections-strict 由 2 处失效转为通过。

风险与回滚:纯文档新增,单提交可 git revert,不涉及构建与真机。
2026-10-28 11:40:44 +08:00
wandering1 02c42dea94 docs(编号): 已停发族的示例编号改形态描述;技能手册按有无机器识别面分两条路
口径变更(用户裁定 2026-10-28,写进《编号规范》§5.5):销项冻结的历史行一般不回改,
唯一例外是「变更记录行里已停发 / 作废族的示例编号」——把字面号改写成形态描述,
事实、结论与数字一律不动。本次随之形态化三处:F 前缀三段形态(原写作孤儿号字面量)、
A 前缀 + 数字、字母 U 紧跟一位数字(区间两端即该簇首尾两枚)。§9 加当日变更行。

技能 id-family-semantic-migration 扩写(+147/−44):Steps 按族的「机器识别面」拆
  成两条路
——字母+数字族走门禁计数与映射表,中文前缀族(如已清退的「数据可信」任务卡号)门禁
咬不到,必须自建带标签扫描器并落地 §4.1.1 一行 + §9.3 换算表 + 叙述同步三处;
另加「三套计数都要挑明」与「不可判定绝对数涨点的净室归因」两节。

验证(实测):check_ids --strict 校验 1~6 无错误,可判定 7006/8036 = 87.18%(基线
   86.0%),
不可判定 1030 处(上限 1166);check_doc_links --all --sections-strict 通
  过(210 文档);
check_bom_drift / check_mojibake / check_coding_standard / git
   diff --check 均 rc=0。

归属说明:这两处的语义出自并行的 RS485 / 屏板道(用户在另一会话里裁定),
Lead 按「整理并收工提交」指令代提交,未改动其口径与结论;文件在提交前后字节一致。
2026-10-28 11:39:09 +08:00
wandering1 f50e74c63b docs+log: 撤销"PA10 未接线"结论,ORE 机理改为"RX 使能却不读 DR"
用户反馈:PA10 这个端口是接线的,当年那个分析应该是错的。

核查确认:console_log.c(文件头与 con_uart_reinit() 注释)和
控制台单写者日志设计说明.md 12 节里的"PA10 悬空 / 未接线"是 2026-10-02 的
归因推断,不是实测,且与用户确认的接线状态相反。

ORE 的充分条件本来就不依赖引脚悬空:RX 使能了却从不读 DR,
线上任意一个字节或一个噪声沿使 RXNE 置位后无人读,下一个事件即锁存 ORE
(常伴 NE/FE/PE);而 ORE 只能靠"先读 SR 再读 DR"清除,所以永不自愈。
引脚悬空只影响发生率,不是必要条件。

当年那场风暴的真因仍待定:接线正常时更常见的是对端波特率不匹配
(适配器不是 115200)或适配器 TX 在 USB 掉线时浮空。下次复现先量
适配器 TX 的空闲电平与波特率,不要再默认"引脚悬空"。

改动:
- console_log.c:函数注释改按正确机理表述;修改记录加 2026-10-28 一条
  说明归因更正。纯注释,Code 236456 B 与上版一致,@build 0/0。
- 控制台单写者日志设计说明.md 12 节:机理段后加更正块,写明观察与缓解
  措施仍成立、只有归因需要改写。
- 产品需求文档:4.2 表 USART1 行改为"PA10 双向均已接线";5.16.2 的
  "PA10 没接线"警示块整段重写为"旧结论已撤销 + 真正机理 + 两条硬要求"
  (屏板链路必须消费 DR 并在错误回调清 ORE;新日志口仍设 UART_MODE_TX);
  9.13 前置阻塞由"两条物理前置"改为"一条物理前置 + 一条实现纪律";
  12 节加 v1.9。
- 屏板链路规划:0 章第 2 行标为已撤销、执行顺序去掉"接 PA10";
  批 0 由 4 项减为 3 项;批 1 第 3 项判据补"拔插 TX 线制造噪声后能自动
  恢复";风险表把"PA10 没接"换成"一次噪声后链路永久静默"。
- 任务规划 README 独立轨道行同步为两条前置。

体积凭证随索引刷新(scripts/size_attestation.json),数字未变。
2026-10-28 10:41:32 +08:00
wandering1 eb2c454aed docs(产品需求): 端口重排——屏板占 USART1,日志迁 RS-232 通道
用户裁定:现在的日志串口让给屏幕,RS-232 通道以后用来输出日志。

这条裁定把原来的头号阻塞直接消掉了:屏板改走 USART1(PA9/PA10),
是唯一一条 MCU 引脚直出 TTL、不经收发器的通道,所以 U15 = TP8485E-SR
只有 250 kbps 这件事对屏板链路不再构成约束,也不用改任何硬件。

顺带纠正一处算错的波特率分频:
- 旧文写 42 000 000 / 700 000 = 60 -> USARTDIV = 60.0、BRR = 0x3C0,
  漏了 16 倍过采样,照此写实际只有 43 750 baud。
- 正确:USART1(APB2 84 MHz)USARTDIV = 7.5 -> BRR = 0x0078;
  APB1 实例(42 MHz)USARTDIV = 3.75 -> BRR = 0x003C,误差均 0。

端口归属按 V0.1 网表 §4.2 的三对 UART 轮换核实:
RS485#4 = UART4(DE = PA15)、RS232#1 = UART5、RS232#3 = USART2。
所以 rs485_init(&g_rs485, &huart4, ...) 是对的,不动;屏板链路规划 v1
里"网表自相矛盾"那条判断依据错了(拿 V0.0 摘要行对 V0.1 代码),已纠正。

产品需求文档:
- 5.16.2 补端口裁定块与分频更正,重写"主机侧端口选型"为"端口重排"。
- DE 口径改为 TTL 直连无 DE;主机 RX 由"吃 4208 B"改为"只需 6 B"。
- 4.2 外设接口表补 USART2 / UART5 两行,USART1 行注明 PA10 未接线。
- 9.13 新增第 16 条"日志口迁移",批次表注明 16 必须排在 10 之前
  (两者共用 USART1->DR);第 10 条改 BRR = 0x0078、无 DE。
- 12 变更记录加 v1.8。

屏板链路规划:
- 0 章由"三个硬约束"改为"一条已解除 + 四条前置",执行顺序钉死为
  接 PA10 -> 挪台架串口线 -> 迁日志口 -> 再写屏板链路。
- 决策一、二 标记已裁定;批 0 换成"腾位置"4 项;批 1 的 DE 项降为
  条件项,新增"日志口迁移"的改动点与判据。
- 5 章台架步骤补第 0 步;6 章风险表换成迁移期的新风险;7 章加判据 0。

任务规划 README 的独立轨道行同步为"端口已裁定、剩三条物理前置"。
2026-10-28 10:22:37 +08:00
wandering1 fec0052865 docs(任务规划): 新增屏板链路执行规划,并记下 700 kbaud 的硬件阻塞
新增 docs/任务规划/屏板链路.md:让主机跟 DTU-LCD 屏板真正通信的
执行级规划(需求侧仍在产品需求文档 5.16 与 9.13,不重复)。

核查后发现三个必须先解决的硬约束:

- 本板唯一 485 收发器 U15 = TP8485E-SR,手册上限 250 kbps,而屏板
  固件写死 700 kbaud,差 2.8 倍。这是唯一可能让整件事搁浅的点。
- 4208 B 帧在 250 kbps 下需 168.3 ms,已占满屏板 200 ms 应答窗口的
  84%,无实用余量;留 50% 余量需 >= 500 kbaud。
- 现有 rs485 驱动装不下长帧:RS485_RX_BUF_SIZE 与 RS485_TX_MAX_LEN
  都是 256,4208 B 会被直接判 BSP_ERR_PARAM。

规划要点:
- 四个决策(波特率与收发器、端口、宿主、键值 9/10 语义),其中
  波特率给 A 换器件 / B 屏板降速 / C TTL 直连三条路及代价。
- 分 4 批共 18 项任务,每项带改动点与判据。
- 端口建议:USART2 软件最优(DMA1_Stream5/6 空闲),USART3 硬件最顺
  (U5 子板连接器直连 TTL)但 TX DMA 被 SPI2 占用。
- 宿主用 xTaskCreateStatic(configSUPPORT_STATIC_ALLOCATION=1),
  不占已满的 RTOS 堆;栈 768 B,不进看门狗必需位掩码。
- 主机侧 RX 只需 16 B(屏板只发 6 B 召唤帧),别照抄屏板的 4208 B。
- 台架五步,先用 TTL 把软件全部跑通再等硬件决策。
- 复用 ui_net_sink_get_lcdmem / ui_net_sink_inject_key,不改
  ui_net_sink.c,也不改 rs485.c 的常量。

同步:
- 产品需求文档 5.16.2 补 700 kbaud 硬件阻塞警示与出处。
- 产品需求文档 9.13 加执行细则指针。
- 任务规划 README 导航表与 2.0 顺序表加独立轨道一行。
- docs/README.md 索引计数 5/6 -> 6/7 个文件。
2026-10-28 10:11:36 +08:00
wandering1 11b4b2af70 docs(产品需求): 单色口径——删除多色协议,INIT 应答 29 B 改 16 B
屏板是单色面板,多色协议不对齐。核查参考源码后确认这不是让步,
而是删死字段,三处证据:

- RemoDispBus.h:46 CN_RDISP_TYPE_MONO = TRUE,LCD_TYPE =
  CN_MODE_GREY_MONO、MEMSIZE = (X>>3)*Y,链路显存本就是 1 bpp。
- RDisp_Form_InitInf 的 CN_RGB_RED/GREEN/BLUE 是编译期常量,不是
  逐帧数据,每次召唤都发同样的 12 B。
- 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,附证据块。
- 6.2 命令集 INIT 行同步,加单色口径注。
- 5.16.6 第 6 条注改为"该函数在参考单色构建下就是空转"。
- 5.16.9 第 1 行改为"补 8 B 键值表 -> 16 B、颜色 13 B 不对齐",
  新增约束补单色一条,警示改为 16 B 与 29 B 不可互换。
- 5.16.10 判据第 1 条改 16 B 且不得出现颜色字段。
- 9.13 第 2 条改 16 字节且不加颜色位与 RGB,第 9 条客户端按 16 B
  解析,破坏性变更警示改后 8 B。
- 2.4.1 补"多色显示不在不可移植项内"——参考同样单色。
- 8.1 色深行补无灰度无彩色,渲染行改双出口。
- 2.5.2 第 20 项、9.1.2、9.12、10.3 第 13 项同步。
版本 v1.6 -> v1.7。
2026-10-28 09:55:44 +08:00