Commit Graph

814 Commits

Author SHA1 Message Date
wandering1 51604f7717 merge: task/doctrim-adc-tick-history 合入 v2-on-ui
CI / L0 静态门禁 (pre-commit) (push) Failing after 50s
CI / L0.5 主机侧单测 (MSVC) (push) Failing after 45s
任务 doctrim(3 个提交)经 task-worktree 回收:
- chore(注释): 清掉源码里不可检索的过程编码
- docs(algo): App/algo/README 缩成目录索引,详细设计迁入 docs/算法
- docs(ADC): 采样节拍设计说明只留现状,历史决策与台架记录移出
2026-10-21 11:44:31 +08:00
wandering1 5a9988b557 chore(注释): 清掉源码里不可检索的过程编码
清掉的(读者无从解析、且所指文档已不存在)
- 已删任务文档的编号:Task #32、其内部 §5 / §4.3、P1-5、P0-2、P1-4a、
  "方案 a"、"Lead 批准 2026-10-12"
- 正文里当代词用的文件版本号:"(v2.7 起为 AboveNormal)""已随 v2.0 事件
  驱动改造删除""(v2.0:DMA 消费)""见文件头 v1.3 说明"等 → 改写成陈述现状
- 测试与脚本同类:adc_input 桩头"v2.0:DMA 模型"、stub/adc.h 的 v2.0、
  check_cubemx_survival.py 段头的"2026-10-10 v2.8"、run_all_suites.py 的"方案 A"

刻意保留
- 可检索登记簿锚点:P-AUDIT 真条目(P0-1/P1-8/P2-1/P2-9/P3-11)、S6/S11、
  E-31/E-44、N-18/N-23/N-32、B1/B5/B7/B8、L1-x~L5-x 功能号
- 文件头修改记录块内的 vN.M(规范 V1.0 §2.1/§2.2 要求保留该块;块内编号
  在本文件内自洽可读)

顺带纠正注释与代码已经不一致的过时事实
- 仍把 TIM6 写成现行节拍源:Src/main.c 的 include 注释与回调注释、
  Src/freertos.c 的 adcTask 块 → 改 TIM3;adc_input.h 修订条目里"ADC1 只认
  TIM2/TIM3/TIM8 的 TRGO"不准确 → 换成指向判据(ADC采样节拍设计说明 §3.2)
- App/algo/phasor.c 双区注释称"唯一消费者是 adcTask、为后续保护任务预留",
  实际 protectTask 已跨上下文读(prot_elm_run -> phasor_get)→ 改为"读者跨
  adcTask 心跳与 protectTask 判据两个上下文,勿改加锁、勿取消双区",并同步
  修正 docs/算法/采集与算法层设计说明.md 同一句
- adc_tick_irq_notify() 的"拒绝 ISR 内计算"理由仍写"内含 2 ms 忙等"(DMA 化
  后已无忙等)→ 换成三条真实理由:任务级共享数据 / 计算量 / 生成区回调
- 裸 §5(指代不明)与"规划 §1.6 / 规划 §4"昵称式 → 写成完整路径紧邻式

字节卫生(Edit 会静默剥 BOM)
- App/task/ui_task.c 与 Drivers/BSP/UI/ui_net_sink.c 被剥掉 BOM 两次,均按
  3 字节 EF BB BF 前缀补回并复验;全部 20 个文件 CR=0、U+FFFD=0、无行尾空白

门禁
- @build 0 错误 0 警告,且 Program Size 与清理前逐项相同
  (Code=213356 RO=18580 RW=1184 ZI=131480)→ 纯注释改动、中文未被误重编码
- ui-golden 首跑红:新工作树缺被 gitignore 的黄金参考 simulator/tests/ref/
  (不入库、只在主工作树生成过);从主工作树复制该基线后复跑通过 → 注释改动
  零像素影响
- 全套 pre-commit 在这 20 个文件上 Passed(coding-standard / cppcheck /
  6 个主机单测 / doc-links / task-table / mem-numbers / cubemx-survival /
  registration-check / mem-budget / font-charset / ui-golden / id-check)
- id-check 可判定比例 82.71% -> 82.88%(删掉的是"形似 P-AUDIT 但查无定义"的
  假锚点),悬空引用 863 -> 854
2026-10-21 11:39:53 +08:00
wandering1 64d8b052b1 docs(algo): App/algo/README 缩成目录索引,详细设计迁入 docs/算法
拆分层级
- 新建 docs/算法/采集与算法层设计说明.md(413 行、13 节)承接机制、契约、
  判据与设计理由:定位与边界 / 数据流与初始化落点 / adc_input / adc_health /
  sample_ring / phasor / freq(7.1 为什么自适应窗、7.2 判据 J1~J6)/
  prot_set / prot_elm / 关键约定与禁令 / 资源足迹 / 验证与判读 / 相关文档
- App/algo/README.md 360 -> 128 行:只留文件清单、依赖、逐文件"改代码必须
  知道"的红线、构建与测试入口、新增模块动作;深挖改成逐条指针
- README 保留 §3.1-§3.7 原编号,既有"§3.7"引用不失效

索引与引用同步
- 索引:docs/README.md §5.2 新增行;项目架构总览主题表拆成"设计与判据 /
  目录索引"两行;AGENTS.md 与 App/README.md 指向(后者原文还写着 L1/L2)
- 按内容重指(编号仍在但内容已搬走,只核编号会静默指错):App/algo/freq.h、
  test/host/freq/freq_test.c、run_unit_test.py、继电保护规划 L2-4 行、
  pre-commit使用说明 J4 行 -> 指向设计说明
- ADC采样节拍设计说明的两处指向同步改到新文档

修 README 内过时事实
- 挂载写"八个 .c",实际 uvprojx 内 7 个
- SIM_EXEMPT 写"prot_set / freq 才登记豁免",实际七个全在表内
- freq-unit-test 标"待登记",实际已在 .pre-commit-config.yaml
- 定值项数一处 31->40、一处 32->40;blob 144->176 B 证明是 32->40
- 用例与判据数字不再三处复制:属主是 test/host/<模块>/ 与 docs/测试说明/

门禁
- doc-links --all 无新增问题;--sections-strict 覆盖 10 篇文档通过
- id-check 可判定 82.65%(基线 82.6,容差 0.1);TC 双向追溯差异 124 处不变
- registration-check PASS(1 条已知 WARN);freq 单测 46/46;@build 0 错 0 警
- 全部改动文件无 BOM、无 CR、U+FFFD = 0
2026-10-21 11:39:53 +08:00
wandering1 0f0d002afc docs(ADC): 采样节拍设计说明只留现状,历史决策与台架记录移出
删除(已确定的决策与过程记录,无现状信息量)
- §2 方案选型(方案 A 推荐 / 方案 B 备选与结论)
- §9 变更记录整表(9 行"已实现 / 已验收 / 已落地 / 复核修正"叙事)
- §7.1、§10.3、§11.5 三张台架实测对照表 + 反向验证记录 + boot_log 证据行
- 用户决策与过程编号(Task #32 P1-5 方案 a、B1、P0-1/P0-2、v2.0/v2.2/v2.7/v2.8、
  "规划未预见""原规划写错了"更正叙事)
- §4 代码改造清单(改造已完成)与 §8 / §10.5 的后续规划口吻

保留并补齐现状
- 链路总览(新增 TIM3 同源 Mermaid)· 实现落点表 · TIM3 配置与"为什么是 TIM3"
  (F4 触发清单是硬约束)· ADC1 + DMA 四条硬约束与半区无竞态推导 · 上电自校准
  · TPAFE 侧契约与原子快照 · 就绪门与节拍缺失 fail-safe · 单周期时序
  · 心跳计数逐个判读(含相位伪影为何阈值取 2)· 性能与资源特征
  · 设计边界与已知代价(N-18 无同刻性、滞后一拍、TPAFE 未 DMA 化的前提未定、
  调频能力现状)· 设计铁律
- 468 -> 344 行

顺带修掉文档自相矛盾
- 原 §3 / §4 仍在教人配 TIM6(§11 已改 TIM3)-> 全文统一 TIM3
- 上位需求引用写成 继电保护功能复现规划.md §3.2,实际 L1-1 在 §3.1

连带引用同步(7 文件 8 处)
- App/algo/adc_input.c -> §8;App/task/adc_task.c -> §6;Src/main.c -> §3.3;
  Src/freertos.c -> §9 与 §10(顺带纠正已失效的"ADC 2 ms 忙等"表述,DMA 化后
  单拍取数已零忙等)
- 看门狗设计说明 §6 与 §9 / §4.4;ADC通道映射说明 §4 与 §6;
  继电保护功能复现规划 §3.2
- 其中 2 处活断链 doc-links --all 抓不到(整行含"已消""已实现"状态词被豁免),
  另写脚本按「文档名 + 章节号」全库扫出后修复

门禁
- doc-links --all(非 SDL2 问题 0,可判定 57% -> 58%)与 --sections-strict 通过
- no-mojibake / trailing-whitespace / end-of-file-fixer / id-check 通过;
  task-table / mem-numbers 一致;@build 0 错误 0 警告
- 改动文件均无 BOM、无 CR、U+FFFD = 0;CubeMX 文件的注释改动都落在 USER CODE 区
2026-10-21 11:39:52 +08:00
wandering1 858434492c feat(门禁): id-check 关闸——按债务台账增量拦截,warn-only 时代结束
机制(--strict 不再「有错就失败」,而是只拦台账外的新账)
- scripts/id_known_backlog.json:340 条指纹覆盖 710 处存量(②167 类 / ⑥135 / ③38)
- 指纹 = (文件, 校验号, 字面量) → 计数,故意不含行号:行号每改必漂,
  用它当指纹会让台账天天假新增,三天后没人敢看 strict,台账失效比没台账更糟
- 带计数而非集合:同一文件里同一个号多出现一次也算新账(复制粘贴式扩散
  正是编号烂掉的主路径,只按「出现过没有」判会放过它)
- 新增 --write-backlog 与 --prune-backlog(只减不增;台账内条目变多当场点名);
  --strict 缺台账返回 2,绝不退化成一次性拦死存量;--only 与 --strict 互斥
- 钩子 entry 加 --strict;--only 与 --strict 互斥
- 顺带修 _scan_malformed 的反向 bug:原条件 (skip and name != "空格形 Trap")
  语义正好写反,带 [示例] 的行反而专被 Trap 规则咬;改为示例行全部不判
- 第一次提交就被自己的台账咬住(id_known_backlog.json 里当然写着 P1-3 等号,
  被当成新引用)→ 台账加入 excluded_paths:登记号的表不是引用号的文档,
  与 id_aliases.json / id_registry.json 同一条道理

为什么不照「清零再升 strict」的原节奏(§8.4 详述)
- 存量 710 处清完要数周,这期间新债一条都不拦,而新增才是烂掉主因
- 「等清零」让人习惯「报红但照样提交」,真关闸那天没人再信门禁;
  本仓已有 mem-budget / mem-numbers 走 --no-verify 的先例,不再开第二个口子

关闸验收三例(临时件当场还原、git diff 干净)
- A 全新前缀 Z-99 → exit 1 点名 ✅ 咬
- B 同号计数 1→2 → exit 1 点名 ✅ 咬
- C 干净态 710 处 → exit 0 放行 ✅ 放(放不住存量就会逼出 --no-verify)

验证:--strict 干净态 exit 0;可判定比例 82.74%(基线 82.6%);
doc-links 失效/待确认 0;未改 C/H 不需 @build。
文档:编号规范 §8 上线节奏改写 + 新增 §8.4 机制表;pre-commit使用说明 §2.25;
AGENTS.md 门禁行由 warn-only 改为已关闸增量拦截。
2026-10-21 11:35:30 +08:00
wandering1 d74cd030ea fix(门禁): 追溯脚本与 B 层口径对齐 + [示例] 行豁免写反的 bug
为什么改(第 1 件,用户裁定的顺序)
- B 层已认 test/host/<模块>/* 为 TC 号属主登记处,但 check_test_traceability.py
  仍按老规矩要求"每个号都必须出现在文档" → 两处判据互相打脸
- 实测矛盾面 284 处里有 173 处属于该口径:照老口径升 --strict 会当场拦死这些
  本不该写文档的号,唯一出路是 --no-verify——门禁公信力就是这么丢的

追溯差异改为三档(口径与编号门禁一致)
- DOC-ONLY:文档声明了、代码没有 → 真断链,38 处
- CODE-ONLY:代码有、母号不在登记处、**且号旁边没写人话意图** → 真未登记,7 处
- IN-CODE:靠"号旁写着意图"放过 → 238 处,**弱于文档的保证,单列示数不算过关**,
  对外举证仍需 C 层模块级说明(脚本里写明这条边界,禁止把它读成"已登记")
- 小写子项后缀(TC-TIMESYNC-003b)按母号算,与 check_ids 的 subitem_ok 同口径
- 真差异从 284 降到 45(38 + 7)

顺带修两个自己的 bug
- TC_RE 模块码上界停在 {0,4}:批 2 模块码单词化(ADCHEALTH 9 位)后代码侧集合
  从 556 悄悄缩到 217(339 个号隐形)→ 放宽到 {0,8}。**同一个坑第二次踩**,
  第一次是 check_ids.py 的候选正则——改名必须复核**所有**识别面,已写进 §8.1
- _scan_malformed 的豁免条件写成 `(skip and name != "空格形 Trap")`,语义正好反了:
  带 [示例] 的行反而专门被 Trap 规则咬。改为示例行**全部**形态规则不判,
  并给引用示例号的两行文档补 [示例] 标记

验证
- 编号门禁:错误级 712 → 710,可判定比例 82.73%(基线 82.6% 未跌破),校验 1/4/5 仍 0
- 追溯:代码侧 578 / 文档侧 298 / 交集 260 / 差异 45;--board-only 回退口径不变
- check_doc_links.py --all 文档路径与章节引用均通过;字节卫生复查 BOM=否、CR=0
- 未改 C/H,不需 @build

文档:docs/编号规范.md §8「顺带收编」条目改写 + §8.1 口径修正记录补两行 + 变更记录;
docs/代码规范/pre-commit使用说明.md §2.25「顺带收编」行同步三档口径
2026-10-21 11:24:05 +08:00
wandering1 4b9a4f4e24 refactor(编号): B 层口径落地——主机侧单测认代码为属主登记处
为什么不是"补 7 篇文档"
- 实测这些号在代码目录外**零消费者**(NANDPORT 47 / PROTELEM 13 / PROTSET 11 /
  FREQ 11 / FTPAUTH 10 / SHA256 8 / SOE 7 / ADCHEALTH 11 / IEC104 23,共 141 号),
  唯一"外部引用"是 scripts/id_aliases.json 自己 → 逐号写文档等于造一份没人读、
  还要跟着代码同步改的复述层(违反"同一事实只在一处详述")

判据与注册表改动
- 新增 9 族 TC-HOST-<模块码>:class 仍为 TC(跨模块同号照旧由校验 4 抓)、
  owner_docs_glob = test/host/<目录>/*、每模块游标做号段不越界(含 IEC104 补漏:
  它上批改名前是纯数字 TC-104-*,没进当时的悬空普查所以漏建族)
- 新旗标 allow_orphans(不补该旗标会让 141 号全变孤儿告警)、
  subitem_ok(小写子项后缀母号在册即算已定义,差异仍由双向追溯如实报)
- snapshot_only:§4.3 冻结快照族不参与"定义位优先"——先试无差别生效时,已销项的
  登记簿 N-21 被审计报告同号接管,校验 6 从 266 暴涨到 1437、可判定比例假崩 68.7%,
  且提示会教人补错文档名(正是 §1.2 的 N-31 撞号制造方式),故回退并改为快照族豁免
- excluded_paths 加 scripts/id_aliases.json 与 scripts/id_registry.json:
  别名表/注册表自身不得制造引用面
- T-2 / T-3 / T-4 / T-6 入别名表标 void(2026-10-02 复审专项条目,销项只删行没清引用)

修自己的漏配(这条是 bug 修复,不是口径)
- N / S-LDG / T-LDG 族漏登记 docs/任务规划/README.md(活登记处,N-21 在其中出现 2 次),
  只登记了 docs/任务规划/登记簿.md(N-21 为 0)→ 74 处真条目被误判

数字与诚实交代
- 错误级 1318 → 711(②398 + ③44 + ⑥269);可判定比例 82.74%(基线 82.6%)
- ⚠ 其中 504 处属**口径修正**、74 处属**修 bug**,**真正变好 0 处**;已在
  docs/编号规范.md §8.1 写口径修正记录表,禁止拿 711 与 1318 直接比
- 文档:§4.1 补 TC-HOST 说明、§8.1 口径修正记录、§8.3 批 3 行、变更记录;
  pre-commit使用说明 §2.25 判定口径与最新实测同步
- 未改任何 C/H,不需 @build;提交钩子即 L0 + L0.5 全量验证
2026-10-21 10:51:25 +08:00
wandering1 bda7ab2b50 refactor(编号): 16 个测试模块码单词化 + 门禁识别面连带放宽
批 2(用户授权改名 + 「新名要一眼看懂」裁定)
- 16 个有歧义模块码单词化,共 1,146 处随 scripts/rename_ids.py 改写:
  AI→ADCIN、AH→ADCHEALTH、PS→PROTSET、PE→PROTELEM、PH→PHASOR、
  TS→TIMESYNC、VL→VOLLOCK、NP→NANDPORT、CFG→CONFIG、CLK→SYSCLK、
  WD→WATCHDOG、STO→STORAGE、SH→SHA256、FA→FTPAUTH、FR→FREQ、104→IEC104
- 不动 NET/GD5F/RTC/SOE/UI/ADC/LOG/RS485/TOOL(已是单词、芯片名或业界通用词,
  改了纯属 churn)
- 别名按全局登记:这批字面量已完全限定(TC-<码>-<nnn>),不存在裸形多义
- 映射表存档 scripts/rename_maps/batch2.json 作审计轨迹;§6 模块码表同步

连带修门禁(关键教训)
- 模块码涨到 9 位(ADCHEALTH/WATCHDOG)后,候选正则与族正则的 {0,4} 上界
  会让改名后的号**整批从门禁眼里消失**:实测编号字面量从 8271 掉到 7315、
  悬空假降 490 处。已放宽到 {0,9} 并写进 §6 注记
- 结论:改名批次必须连带复核识别面,只改数据不改判据 = 静默放行;
  这次是靠「可判定比例跌破基线即失败」那条线拦下来的

现状与遗留
- 校验 1 未登记前缀 0 处;可判定比例 82.71%(基线 82.6%,只涨不跌成立)
- 遗留:7 个模块的「单元测试说明.md」仍缺(PROTSET 116、NANDPORT 109、
  PROTELEM 65、FREQ 48、FTPAUTH 45、SHA256 25、SOE 14 处悬空)——改名不解决
  缺文档,处置方式待议
- 遗留:T-2/T-3/T-4/T-6 历史任务号悬空(别名表未收全,属本工具批次漏项)
- 未改任何 C/H 可编译语义(仅注释与宏名内的编号),故不需 @build
2026-10-21 09:53:28 +08:00
wandering1 301c3e5183 feat(门禁): 编号门禁 id-check 落地(36→37 钩子)+ 批 1 编号单词化改名
新增门禁本体
- scripts/check_ids.py:实现 docs/编号规范.md §8 八项校验;默认 warn-only,
  唯一硬拦项是「可判定比例跌破基线」(防回退的本体)
- scripts/id_registry.json:66 个前缀族,逐项来自 §4 总表 + 全库实测游标,
  偏差一律写进 cursor_note,不凭记忆编造
- scripts/id_aliases.json:旧号 → 新号 / 作废标记(照搬 section_aliases.json 范式)
- 顺带收编 check_test_traceability.py:正则补齐大写后缀与无模块码形态,
  比对范围扩到 test/host 与 7 篇「单元测试说明.md」,另加 --board-only 回退旧口径

批 1 改名(用户授权解禁「不改写存量号」)
- 代码规范条款 S1~S19 → CODE-RULE-nn:78 处 / 2 文件
- UI 像素回归状态 S0~S7 → MENU-STATE-nn:61 处 / 3 文件(冻结在 07)
- 两族属主登记处 = 脚本自身的规则表 / STATES 表,文档只作引用方
- 新增 scripts/rename_ids.py(§7.3 规划脚本):映射表驱动、显式 scope、默认干跑、
  自动写 scoped 别名,跳过 [示例]/[计划] 行与变更记录表,按原字节读写保 BOM 行尾
- 已应用映射表存档 scripts/rename_maps/batch1.json 作审计轨迹

有牙实测(证明门禁不是空转)
- 注入 Z-99 / 裸形 / 悬空 / 越游标 / 未紧邻 / 跨文档重复定义 六例,
  分别被校验 1/2/3/5/6/4 点名,--strict 退出码 1;临时档删除后工作树干净

验证与同步
- 可判定比例基线 82.3% → 82.7%(已 --update-baseline 入档);错误级 1312 → 1291
- ci_local.py 全绿(L0 + L0.5 共 1104 断言);ui-golden Passed;
  check_doc_links.py --all 无法判定 0
- 未改任何 C/H 源文件,故本次不需 @build
- 文档:AGENTS.md 与 pre-commit使用说明.md 计数 36→37 并新增 §2.25 详解;
  编号规范 §4.1 补两行、§8.1 落地记录、§8.2 规范与仓库偏差、§8.3 迁移批次记录
2026-10-21 09:33:54 +08:00
wandering1 efeaccbb18 docs(规划): U5 明确暂缓,等页清单
CI / L0 静态门禁 (pre-commit) (push) Failing after 3m27s
CI / L0.5 主机侧单测 (MSVC) (push) Successful in 39s
报告 §6.5 U5 行与任务规划 README 的 W6 行补一句带日期的裁定:
剩余页面尚未规划,本轮不补页;现存 7 个 ui_page_*.c 即当前全部内容,
报告里的 27 页是目标数、不可当差集清单用。
U1-U4 已全部落地,故 U5 未来开工是纯增量活(实测新增一页 = 3 处人工 +
1 条生成器命令,且 ui-golden 已在提交门禁兜像素)。

此前这两处读起来像"随时可开工",与实情不符,会误导排期。
未改 §1.1 编号列表(§2 有引用,不可重编号),只改两个表格行。
2026-10-20 23:11:40 +08:00
wandering1 fafe13f7ea docs(报告): 状态表与 U2 落地对齐
§6.x 组件清单 `ui_w_records` 行:未建 -> 已建成,附证据与实测增减(-116 B / +8 B)。
§6.5 U2 行:未办 -> 已落地,指回组件行避免同一事实两处详述。
§0.1 UI 行:改为"组件库已起步但仅此 1 个组件",不夸大成已有组件体系。
代码已随 64abefa 入库,此处只补状态表,不让文档比仓库旧。
2026-10-20 22:58:39 +08:00
wandering1 64abefaa00 refactor(UI): U2 合并运行/自检记录两页为共享组件 ui_w_records
ui_page_runlog.c 与 ui_page_selftest.c 各 102 行,逐行比对后差异全是命名:
唯一的功能变量是日志 ID(SYSLOG_RUN / SYSLOG_SELFTEST),计数、每记录 2 行、
同记录读盘缓存、空态伪行的实现两边逐字相同。是真重复,不是推测出的抽象。

## 落地
新建 Drivers/BSP/UI/ui_w_records.{c,h}(已在 uvprojx + CMakeLists 双端注册;
生成器只自动管 ui_page_*.c,故这两处手工加)。两页各留一个实例与两个薄跳板,
.count_cb/.refresh 名字不变 => 注册表与生成器零改动。
净效果:两页 90 删 / 28 增(−62 行),重复逻辑收成一份。

## 合并唯一的真陷阱:缓存归属
count_cb/refresh 签名里没有 user context,最容易写的版本是把
s_cache_valid / s_last_rec / s_ts / s_desc 留成组件级静态——那样两页共用一份
缓存,从 A 页切到 B 页会因记录号相同而直接命中缓存,显示另一页的陈旧行,
是静默错数据而非崩溃。故缓存内嵌进实例(ui_w_records_t),每页各一份。

## 验证
@build 0 错 0 警;golden 经真实 ui-golden 钩子跑通:菜单 8 状态 + 内容页
11 页(含这两页)逐字节一致,未用 --update 刷基线 => 语义搬迁行为等价有证。
ER_IROM1 232,052 → 231,936 B(−116 B)。RW_IRAM1 75,232 → 75,240 B(+8 B),
原因如实记录:原先 4 个文件级静态零初始化落 ZI,现在 s_rec 带 .id 初值整个
结构体落 .data(RW),两页合计净 +8 B;要压回 0 需把 .id 留零再加 init 钩子,
为 8 字节引入运行时初始化顺序不值得,故保留并把账写在此处。
stack_report FAIL 行数 0(间接层未顶破栈预算);mem-budget / mem-numbers 已
按 @build 后规定回填台账。

## 过程中的两处自我失误(已修复,记录以免重犯)
① 用 stem[:2] 生成函数前缀,对 selftest 得到 se_ 而非 st_,锚点失配。
② 撤销脚本里 ${UI_DIR} 被 PowerShell here-string 插值吞掉,导致"边校验边写"
   把树留在引用组件但未注册的链接错误态。教训:回滚脚本必须比正向脚本更保守,
   全部校验通过后才允许写盘。
2026-10-20 22:57:13 +08:00
wandering1 44dec5c49b feat(UI): golden 像素回归入提交门禁(W6 U4 第三件,35→36 钩子)
补上我上一轮自己标记为 2/3 的那块缺口:两个 golden 脚本早已存在且一直在
人工跑,但**从未进自动门禁**——"有基线"不等于"有门禁"(§6.1 原文即自认)。

## 先实测成本再定形态
改一个 UI 源文件后「增量重编模拟器 + 两条 golden」合计 **2~4 秒**,支持走
自动门禁。若实测要几分钟,正确做法是明确不挂、改为文档化人工门禁——一个
逼人 --no-verify 的门禁等于没有门禁,故这个数字是本决定的前提而非附注。

## 落地
新增 scripts/check_ui_golden.py:串「增量构建 → 菜单 8 状态 → 内容页 11 页
+ 池水位」。**有意忽略 argv 且 pass_filenames: false**——两条 golden 按整棵
菜单树 + 全量参考图工作,不接受文件参数,pre-commit 传的变更名对它无意义。
files: 覆盖 UI 源 + ui_task.{c,h} + 模拟器 tests/sim/src + main.c +
CMakeLists + lv_conf.h + 包装器与本配置自身(pre-commit 4.x 无 always: true,
files 是唯一触发手段)。

## 端到端验的是钩子,不是脚本
干净树连跑 3 次 rc=0 全 Passed;给 ui_page_dc.c 的 .top_y 注入 +5 位移 →
**钩子 Failed** 并点名 `[dc] FAIL 与参考页不一致(1882 px 差异)`;还原后
git diff 干净、simulator/tests/ref 的 git status 为空——**全程未用 --update
刷基线**(那正是本钩子要防的行为)。
诚实记录瑕疵:首次实测在"连续注入/还原的紧邻重建"之间偶发失败一次,疑似
MSBuild 节点争用,此后 3 次连跑均绿。已把"单次失败先复跑、连续两次才当真、
不许直接 --no-verify 绕过"写进钩子注释。

## 文档同步
AGENTS.md 钩子数与文末索引 35→36 + 钩子清单补 ui-golden;
pre-commit使用说明.md 概览计数同步;报告 §6.5 U4 由 2/3 → **3/3**(这次是
"真进了自动门禁",不是"脚本存在")、§6.1 golden 行转 ✅、§0.1 缺口描述更新。

## W6 剩余
U2 合并两页记录、U5 落地目标页(须先对齐"目标页 vs 现存 7 个 ui_page_*.c"
的差集——报告的"27 页"是目标数而非现状数)。
2026-10-20 22:14:42 +08:00
wandering1 dafc18f5ed feat(UI): W6 第一波——设计令牌层、页面注册表生成器与 UI 门禁补强
启动 docs/任务规划/README.md 的 W6 UI 扩展簇(用户裁定,覆盖 2026-10-11
的"本轮不排期")。四个工作包,全部验证通过。

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

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

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

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

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

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

## 文档同步与两处自我修正
§0.1 UI 行 B → B+;§6.1「内容页」「设计令牌」两行按实况回填;§6.5 U1/U3
状态更新;§6 顶部加"建议栏不可照抄"总警示(本轮四次证伪:ui_port.h 已有
同名宏、LV_COLOR_BLACK/WHITE 不存在且极性反了、27 页实为目标页数现存 7
个、生成器草图漏密码页非节点绑定)。
两处改口:① §6.5 U4 从我上一版**误写的 3/3 改回 2/3**——"golden 脚本早已
存在"不等于"已进自动门禁",两个 golden 脚本至今未挂 pre-commit,该缺口
单列为待办;② 原计划"分三笔提交"**作废**,U1 与 U3 改同一批文件、文件内
交叠,硬切会产生不可编译的中间态,故整波一笔。
2026-10-20 21:14:14 +08:00
wandering1 9d06798f2d docs(规划): 删 §0.3 内存主线复述层,记录 W6 UI 簇启动与并行度约束
§0.3 第 1 条「内存这条线到此为止」是同日暂缓裁定的**复述层**,同一事实已有
三处单点详述(§0.4 内存两行、§5.3 暂缓横幅、登记簿 N-27 与内存管理两份文档
的横幅)。按「同一事实只在一处详述」删复述、留权威。§0.3 现只剩 UI 一条
主线;标题「两条主线建议」→「主线建议」,**编号不变**(任务规划 README §2
前言引用的是编号不是标题)。上一条变更记录里「内存簇暂缓 → §0.3 主线一」
这个去处自此失效,以本次新增行记载为准——变更记录本身是历史,不回改。

启动 W6:用户裁定**覆盖** 2026-10-11 的「本轮不排期」,按覆盖记录而非静默
改掉。已把 U1~U5 拆成 5 个工作包上共享任务板,第一波 U1 令牌层 ∥ U4 门禁
补强两名成员并行,写范围严格不相交。

并行度的真实约束已写进文档:不是任务数量,而是**注册文件**——新增一个 .c
必须同时改 uvprojx 与 CMakeLists.txt 这两个共享文件,同一工作树里两人同改
必然互相踩。所以 U3(原型化 + 生成器)是必须串行的地基段,U2/U5 排在它
后面;U5 的页面批量要等 U3 把注册自动化之后才谈得上并行。

修正两处失真:① 交付物清单里移植层单测还写着拟名 `test/host/dhara/` ❌
未建,实际落地为 `test/host/nand_port/`(149 断言、第 16 个 -unit-test
钩子)→ ✅;② 报告称「27 页未落地」实为**目标页数**,现存 `ui_page_*.c`
实测只有 7 个,已在 §6.5 注明 U5 开工前先对齐目标/已实现差集,不要照抄
报告数字。

check_doc_links --all:142 篇、无法判定 0。
2026-10-15 14:42:08 +08:00
wandering1 118ea4f005 docs(报告): 删除 §0.2「未闭环问题」小节
Top 2 修复销项后该节只剩指针与暂缓说明,而三条内容都已在别处单点详述:
未闭环清单 → §0.4;内存簇暂缓 → §0.3 主线一与 §5.3 暂缓横幅;Top 2 修复
证据 → 变更记录与文末「已销项条目的记录去处」。按 ../文档规范.md「同一
事实只在一处详述」删除,不留空壳。

§0.3 / §0.4 编号保持不变、不重排:../任务规划/README.md §2 前言正引用
本报告 §0.3,报告内部另有 §0.4 交叉引用,重排会全断(与本报告 2026-10-14
变更记录第 ⑤ 条「报告自有编号不回改、不重排」同一口径)。代价是 §0 下
现为 0.1 → 0.3 → 0.4 的空号,已在变更记录里写明理由。

文首「销项状态」行指针 §0.2 / §0.4 → §0.4;变更记录补一行删除说明。
check_doc_links --all:142 篇、无法判定 0。
2026-10-15 13:45:54 +08:00
wandering1 db16694a87 refactor(nand): dhara 几何字面量收单一真源 + 两条编译期守卫
CI / L0 静态门禁 (pre-commit) (push) Failing after 1m45s
CI / L0.5 主机侧单测 (MSVC) (push) Successful in 18s
上一笔提交 720f841 留下的待办,已登记在报告与 GD5F Trap Records 遗留 3。

ftl_page_in_range() 的越界上界 = num_blocks << log2_ppb,完全依赖 log2_ppb;
而这两个 log2_* 原本在 disk_initialize 里是裸字面量 11 / 6。将来换 128 页/块
的兼容片、只改了 GD5F_* 常量而忘了同步字面量,守卫会**静默算错**——偏大就是
越界守卫失效,正是它要防的那一类错误,且不报任何错。

收口方式比"加一条断言"更彻底:字面量收成 FTL_LOG2_PAGE_SIZE / FTL_LOG2_PPB
单一真源(disk_initialize 与守卫同取此宏,杜绝两处各写一遍再各自漂移),再加
两条负数组编译期守卫 FTL_PAGE_SIZE == (1 << FTL_LOG2_PAGE_SIZE) 与
GD5F_PAGES_PER_BLOCK == (1 << FTL_LOG2_PPB)。AC5 不支持 C11 _Static_assert,
负数组是本项目惯用法(同本目录 gd5f2gq5ue.h 的 N-26 DMA 契约守卫)。

验证:@build 0 错 0 警且**代码尺寸逐字节不变**(Code 213,540 / ER_IROM1
232,280 B / RW_IRAM1 75,232 B)→ 纯语义等价重构;主机侧移植层单测
149/149 PASSED。**守卫牙齿实测**:临时把 FTL_LOG2_PPB 改成 7 → 编译失败
(nand_ftl.c:70 error C2118 负下标),改回即恢复,证明它真会拦而不是摆设。

文档:GD5F Trap Records 遗留 3 由"待办"改为"同日已收口"并记收口方式;
nand_ftl.c 模块头修改记录补第 ④ 条。
2026-10-15 13:35:31 +08:00
wandering1 720f841494 fix(storage): dhara 移植层 is_free 整页精度 + HAL 越界守卫;日志读写批量化
登记簿 N-21(报告 N-12/N-13)与 N-24(报告 N-16)两项未闭环问题修复并销项。

N-12:dhara_nand_is_free() 旧实现只读页首 64 B 判全 0xFF,会把"页首
0xFF、后段有数据"的已编程页误判空闲,dhara 遂往已编程页再编程 = 位碰撞、
journal/map 指向垃圾且不报任何错。改整页扫描(栈上 64 B 分块、页首命中即
早退,故"已编程且页首有数据"的绝大多数页成本与旧实现同价)。

N-13:报告原建议经核对不成立——本仓裁剪版 dhara 既无 DHARA_NO_PAGE(哨兵
实为 DHARA_PAGE_NONE,journal.h:46)也无 DHARA_E_UNSUPPORTED(error.h 枚举
里没有,照抄直接编译失败),且 map.c 三处 dhara_journal_copy 调用点各自已
挡掉哨兵。真风险是移植层零上界校验:越界页号被芯片地址位截断成某个真实页
→ 静默读写错页。改为六个 HAL 入口统一几何上界守卫 + DHARA_E_CORRUPT_MAP。
错误码选择是刻意的:BAD_BLOCK 会让 journal.c:904 标坏无辜好块,RECOVER 会
让 map.c:275 启动回收;无错误通道的 is_free/is_bad/mark_bad 一律取保守值。

N-16 写侧:一次排空合并成"每文件一次 open/write/close"(≤8 条 = 512 B
静态缓冲)。掉电语义不变——批次仍在同一次 drain 调用内 close,而 close
回写目录项这个不同 LPN 会把 FTL 单页写回缓存逼出到 NAND;失败尾部回投
队列,条目不丢(旧实现 -2 卷忙会直接丢掉那一条)。容量轮转仍只在按条慢
路径做,批量路径发现装不下一批就返回 -3 退回。
N-16 读侧:s_read_raw() 加 8 条滑动读窗口 + 写者代数失效,API 与 UI 零改动。

验证:@build 0 错 0 警(Code 213,540 / ER_IROM1 232,280 B = 22.2%,
RW_IRAM1 75,232 B = 57.4%,ZI +1,640 B 全为静态缓冲、不吃任务栈);
@test PASS,且台架 journal 恢复点与修复前同轨——连续四次启动 sectors used
恒 14,094、Map head 每轮 +128 单调推进、epoch 稳定 3 → 整页 is_free 未
改变恢复语义、无双编程、无回退;stack_report 9 个任务全 PASS(defaultTask
静态最坏链 3,024 B / 余 40%,实测峰值 2,164 B / 余 57%)。

新增主机侧移植层单测 test/host/nand_port/(第 16 个 -unit-test 钩子):
RAM 假芯片 + 真实 dhara map/journal 源,149 断言,含"旧算法只看页首 64 B"
对照用例(将来有人把 is_free 改回去会立刻红)与 dhara 级 resume 双编程计数
为 0 的场景。L0.5 由 15 runner / 955 断言 → 16 runner / 1,104 断言。

文档:存储架构说明 §5.3 加移植层两条硬约束;运行与自检记录设计说明
§4.4/§4.5 写批量化与读窗口;GD5F Trap Records 新增 Trap 07(含三条遗留
代价与一条待办编译期断言);登记簿 N-21/N-24 删行销项并同步 README
§1/§2.0/§2.1、排期详述 C3、报告 §0.1/§0.2/§0.4/§4.x/§7 与去处表;
钩子计数 33→34、主机侧单测 15→16 全库同步。
2026-10-15 12:34:39 +08:00
wandering1 8739faa7fe docs: 裁定——内存优化簇整簇暂缓(R-2 后半 / R-3 / R-4 / R-6)
用户判定"把 LVGL 池与 UI 帧缓冲(现 ≈29.6 KB)搬进 CCM 作为后续
功能预算来源"这个决定不合适,内存优化的事先放一放。据此把这条
主线降级为暂缓,同时明确:不回退已落地的部分,不拆治理面。

报告(docs/问题记录/项目审查与优化建议报告.md):
- §0.2 Top 3 → Top 2:R-2 剩余移出,表下加一条 ⏸ 说明
- §0.3 主线一由"把内存从卡死变富裕"改写为"这条线到此为止"
- §0.4 两条内存条目 🟡/❌ → ⏸ 暂缓
- §5.1 结论段与 §5.2 诊断补"不代表现在要动"
- §5.3 加暂缓横幅:三条理由(没有功能等这块预算 / 搬迁有风险和
  工时 / 收益与代价不对称)+ 保留常开的治理面 + 三条重开条件
- §5.3 表内 R-2 / R-3 / R-4 / R-6 优先级一律 ~~P1/P2~~ → ⏸ 暂缓
- §7 路线图 W3 划掉标暂缓,映射行改为"暂缓期间无验收动作"
- 去处表 R-9 行注明"该簇其余部分已暂缓";变更记录加一条

任务规划:登记簿 N-27 波次 W3 → 暂缓,并写清代价——CCM 只剩
7,904 B、FreeRTOS 堆实测 min_ever 8,464 B,**加任务 / 抬栈 / 加堆
会先在这里撞墙**,届时 mem-budget 会先报警,那就是重开信号。
README §1 结构/健壮性 7 → 6、暂缓块 1 簇 → 2 簇、§2.0 第 3 条
订正(顺带修掉旧值 ≈8,160 B → 实测 7,904 B)、W3 行与 §2.1 链路
图标暂缓、§3 暂缓规则推广到"只在原处标注"的簇。**W3 槽位保留
不重编号**,避免全库改 W4~W7 引用。

内存管理三篇:RAM预算台账 §2 把 UI 超配额改判为"已知长期挂账"
(R-2 暂缓后这条 ⚠ 会一直挂着,别每轮当新问题追)、§3 解锁链标
暂缓并去掉"← 现在卡在这一步";RAM使用分析 §4 加实施状态横幅
(测量与长效机制常开 / 已落地不回退 / 1.2、1.3、2.2、2.3 与 8KB
试探暂缓)、§5 加"别拿目标列当现状"、§6 S5 补 ✅ 2026-10-15、
S6/S7/S8 改暂缓、S9 台账门禁补 ✅、1.5 里"缓冲已迁 CCM"订正为
"实际仍在 SRAM1";存储栈RAM优化调研加同款横幅(P0-2 / P1-5 /
第三步)。

校验:check_doc_links --all 通过(142 文档、无法判定 0);
check_mem_numbers 与 .map 一致;6 个文件无 BOM/CRLF/U+FFFD。
纯文档改动,不涉及代码与构建,故未跑 @build / @test。
2026-10-15 10:27:02 +08:00
wandering1 ff9fcbd43c docs(报告): 补漏——§0.1 六维评分与口径/附录数字追平 R-9 后状态
用户指出 §0.1「内存使用」行仍写"LVGL 池 + UI 两份缓冲 54,146 B
仍在 SRAM1,而 CCM 只剩 7,904 B → R-2 后半被堵死,须先 R-9"。
上一条 R-9 提交只改了 §0.2/§0.3/§0.4/§5.x,漏了 §0.1、§1 术语表、
§3.1 体量表与附录 A 证据表。全库重扫后修这些:

- §0.1 内存使用:SRAM1 74.9% → **56.1%(余 57,504 B)**,瓶颈收敛
  到 CCM 单点(87.9%、只剩 7,904 B),待迁体量 29,570 B,只差
  "缩堆"一步;评级 B → **B+**(SRAM1 由卡点变富裕、治理三件套与
  观测齐备;扣分项换成 CCM 单点 + MicroLIB C 堆无机械检查)
- §0.1 Flash、§1 术语表、§6.4:231,036 → **231,084**
- §1 术语表:`ROM = 231,324 B` 是**算术错**,Code+RO+RW 实为
  **232,196 B**(§5.1 早前已修,这处漏了)
- §1 术语表 RAM 占用定义:98,144 / 74.9% → **73,568 / 56.1%**
- 附录 A 证据行:改 `RW_IRAM1 Size: 0x00011f60`、余 57,504 B
- §0.1 与 §3.1:工程文档 88 篇 / 31,416 行 → **87 篇 / 30,781 行**、
  受控文件 2,466 / 79.3 MB → **2,465 / 79.2 MB**(随 506eccc 删除
  错误码传播审计.md,−1 篇 / −635 行);同表 docs/ **56.9 MB** 与
  手册图片 **703 张 / 36.3 MB** 实测未变,保留
- §0.1 / §0.2 / §0.4 与附录的复核日期统一标 2026-10-15
- 最近复核行的 HEAD 改指 a7f5265,并注明"后续文档与模拟器侧提交
  不影响固件",避免每提交一次就再次过期

未改一处:§3.1"全部 Markdown 只有 5.4 MB"——本次复算得 5.8 MB /
192 篇,但原计数规则无法复现,差异也远超一次删除的量级,不猜着改,
留给下次复核定口径。

校验:check_doc_links --all 通过(142 文档、章节引用无法判定 0);
check_mem_numbers 与 .map 一致;无 BOM / CRLF / U+FFFD。
2026-10-15 10:14:34 +08:00
wandering1 172b3f4a20 fix(sim): UI 回归改为自洽运行——修 netcfg_save 假失败
现象:check_content_pages.py 只有 netcfg_save 一页 FAIL(保存行值列
显示 ERR 而非 OK),其余 10 页像素与两处往返池水位全过。

真因不是代码回归:模拟器按**当前工作目录**读写 sim_config.ini,而
--cfgtest 的 E-01 场景 2 会伪造一份 4000 B 纯注释"雷"文件、并断言
"拒写后原文件不动"(size == 4000)——连正常通过路径也不删除它。
实测仓库根那份是 2026-10-11 08:37 留下的。之后每次运行都会加载它
→ 外科式保存要在 4000 B 注释后补写受管段 → 输出必超
CFG_FILE_MAX_LEN → 引擎按设计拒写 → 保存行显示 ERR,与"工厂默认
态"的黄金参考对不上。引擎行为是对的,错在自检留雷 + 回归不自洽。

修三处:
- simulator/main.c:run_cfgtest 拆成 scenarios + 外壳,无论成败一律
  cfg_store_remove 配置路径与临时路径,让配置回到"无文件 = 工厂默认"
- check_menu_rows.py / check_content_pages.py:以空临时目录当工作
  目录跑 lvgl_sim(cwd=tmp),调用目录里的残留档不再影响结果
- check_content_pages.py:作废"删 sim_netcfg.bin 残留"的旧兼容清理
  (旧档迁移 2026-10-10 已删),改为只提示、不删别人的档

验证:--cfgtest PASS 且跑完不再留下 sim_config.ini;
check_menu_rows.py PASS(8 状态 + 池基线 5,368 B);
check_content_pages.py "PASS: 11 内容页 + 往返池水位全部通过",
往返 5,448 B。**未刷任何黄金参考**——参考本来就是对的。顺带删掉
本地两份 4000 B 残留(仓库根与 build/Debug,均 gitignore 产物)。

未跑 @build:本次只改 simulator/ 侧代码,固件工程无涉及;模拟器
CMake 构建 0 错 0 警,cppcheck 钩子覆盖 simulator/main.c。

文档:UI_自动化测试流程 §五 加排查行 + 变更记录;simulator/README
§3.7 说明删除保证与原因;lvgl-simulator skill 同步;订正审查报告
R-9 那条把该差异误归给 cfg_file 改动的表述。
2026-10-15 10:05:37 +08:00
wandering1 0cece5a305 docs(编号规范): 新增 P-8 语义优先与语义标识规范(§3.3 / §5.7)
规划 / 待办类条目改以一行短语作标识,不再分配字母+数字号:
- §2 加 P-8「语义优先」,七条原则变八条
- §3 主轴由"两层编号"扩为 编号 / 语义标识 / 章节引用 三种形态
- 新增 §3.3 形态规则与适用分界:TC / TRAP / FR / NFR 等需机器
  解析或作历史证词的仍保留编号,并强制带语义括注(P-7)
- 新增 §5.7 登记、冻结与别名规则:短语即标识,改措辞等于换 ID;
  销项 = 删行 + 清全库引用,短语不复用
- §4.2 加修订说明,§9 加「0.5 语义标识」迁移阶段

起因:N-31 销项删行后按"现存最大值 +1"又被取走,与两处历史引用
撞号(见 docs/任务规划/README.md §0)。

注:本文件不是 R-9 会话所改,按"全部提交"一并入库。
2026-10-15 09:56:33 +08:00
wandering1 a7f526569a perf(mem): R-9 落地——LVGL 池 40→16 KB,SRAM1 74.9%→56.1%
取值依据是实测水位,不是预估:菜单根框 5,368 B、开页-关页往返
5,448 B、最重页面峰值 6,568 B(占 16 KB 的 40%)、真机开机
used=3,192 B。注意 16,384 B 建池后 lv_mem_monitor 报的 total 是
15,020 B(TLSF 控制块与对齐元数据 ≈1,364 B),核算余量用后者。

两端 lv_conf.h 同步改值(lv-conf-sync 生效值比对 163 项 PASS),
Lib/lv_conf.h 的 UTF-8 BOM 已按原样补回(Edit 会静默剥掉)。

验证:
- @build 0 错 0 警;ZI 154,456 → 129,880,精确 −24,576 B
- SRAM1 98,144/74.9% → 73,568/56.1%(余 57,504 B);CCM 不变 87.9%
- 模拟器菜单回归 PASS(8 状态像素 + 池基线 5,368 B 未变);11 页
  黄金参考逐字节 10/11 一致,往返池水位 5,448 B 分毫未变
- 唯一差异 netcfg_save 保存态:用 40 KB 旧池做 A/B 复测同样失败,
  确认与本改动无关(属 506eccc 的 cfg_file 行为变化),未刷黄金
  参考掩盖,留给该改动属主处置
- @test PASS:fw build Oct 15 2026 07:31:34,无 [ERR]/Fault,
  开机 622 ms 到 net init: OK,menu build done: used=3192
- 本地 CI 全绿(L0 + L0.5,15 runner / 955 断言)
- 台账受管区与内存快照区已 --write 回填,mem-budget / mem-numbers
  由红转绿

连带结论:R-2 后半待迁体量 54,146 → 29,570 B,瓶颈由 SRAM1 换到
CCM(只剩 7,904 B);解锁链第 ① 步完成,下一步只差缩堆 56→32 KB
(B5 是反向扩容,缩回前须重跑 stack_report.py + 上板 min_ever)。

文档同步 20 处:本报告按修复即销项删除 R-9 行,并改写 §0.2/§0.3/
§0.4/§5.1/§5.2/§5.3/§6.4 与变更记录、去处表;RAM使用分析 §2.6.2
新增实测水位表、阶段 1.1 标已执行;台账 §3 解锁链、登记簿 N-27、
任务规划 README W3 行与链路图;UI 四篇、产品需求、内存内容分配
策略、运行与自检记录、项目部署环境要求、测试开发标准流程、
simulator/README、ui-verify skill 常量。顺带订正三处与脚本不符的
旧值:池水位常量 4784/4864 → 5368/5448、FreeRTOS 堆 48 → 56 KB。
2026-10-15 09:56:15 +08:00
wandering1 506eccc68f docs: 错误码传播审计收口并删除该文档(E-xx 转历史编号族)
本次会话先后销项与关闭:
- E-61 SD2506 清 INTAF:原实现只读取 CTR1,而按手册 ARST=0 时读操作
  不清标志,属空操作;改为读-改-写 CTR1,并按手册订正 CTR1 位宏
  (INTAF/INTDF/BLF 位置,ARST 归 CTR3)
- E-16 cfg_file:新增 CFG_FILE_MAX_NAME_LEN(段名/键名 ≤15),注册时
  拒绝超长键名;s_gen_document 两处 snprintf 改检查式;补 TC-CFG-024
  用例(主机单测 149→151 PASSED)
- E-23 TC704:PHASE7_MULTI_COUNT 8→5(并发上限 = 8 − 3 个常驻监听),
  accept 失败分支加网络代次检查(网络重建即重建监听)
- E-26(UDP)按“保留 API + 文档定案”关闭;E-30 评估为不必要后关闭;
  N-4(ACCEPT 决定不实施)关闭

审计文档剩余 5 项 P2 + 2 项监督,经用户裁定“都不重要”后整体删除:
- 删除 docs/问题记录/错误码传播审计.md(634 行)
- 九类缺陷模式表迁入 docs/编号规范.md §4.2.1(PAT-01~09)
- E-xx 转为纯历史编号族:编号规范 §4.1 属主改“无(原属主已删除)”,
  §4.3 保持冻结;全仓 26 处引用按“保留编号、去悬空文档名”处理
- 顺带修正 N-4 收口遗留:排期详述 C1 才是 E-25/E-27/E-28 的承载处
  (审计 §4 曾误写为登记簿);README 两处 C1 旧名改回“net 层跨上下文收口”

一并提交此前遗留的体系层评审报告 2026-10-14 复核 WIP(六维评分复核、
未闭环 Top 5→3、三区水位实测刷新)。

校验:Keil 构建 0 错误 0 警告(Code=212344);check_doc_links
--sections-strict 与 --all(142 文档)通过;内存双台账刷新后均 PASS。
2026-10-15 07:39:38 +08:00
wandering1 803f7717ed chore(skills): 纳入 template-skill 骨架(DSH 建 skill 的空白模板)
.dsh/skills/ 是入库的项目知识(.gitignore 用 `!.dsh/skills/` 显式放行),
此前该目录未被跟踪,现按同一口径纳入。

内容为 DSH 新建 skill 的空白骨架:description 仍是占位文案、正文未填。
后续要落地具体 skill 时直接改写本文件;确认不需要则删目录即可。
2026-10-14 23:22:26 +08:00
wandering1 617c84f570 docs: 文档去阶段化——清理"自愈收敛阶段 / L3 pending / 一期二期"标签
CI / L0 静态门禁 (pre-commit) (push) Failing after 2m11s
CI / L0.5 主机侧单测 (MSVC) (push) Successful in 17s
代码注释去阶段化已在 task-arch-docs-sync 分支 d770e36 落地,本次把
同一口径补到文档正文(文末变更记录行作为历史保留不动)。

- BSD 使用指南 / 函数调用关系:删 自愈收敛阶段 N、N-32 P1/P2、
  L3 pending、一期二期;职责边界与实现位置改为现状口径
- CH395F_Trap_Records:TRAP-NET-17 / -21 / B10 状态行改述为现行形态
- 链路延迟测试说明:L3 pending → 挂起 recv;P0-a 阶段标签删除
- 模拟器差距清单:N-3 / N-4 / N-6 行改述(对账形态③④、无手动 relisten)
- 错误码传播审计:L3 pending → 挂起 recv;"N-4 二期" → N-4
- 任务规划 README / 登记簿 N-4 / 排期详述 C1 / 基线与待确认 §2.1:
  一期二期 → recv 挂起已落地 / ACCEPT pending 化(§2.1 标题同步)
- CH395F_Test_Guide:阶段 15 标题去掉撞名的"自愈收敛阶段 2"
- IEC104 上行设计说明:门控迁移改现状口径;"随二期" → 未登记具体条目
- 保留可检索锚点:TRAP-NET-*、E* / U* / D10、形态③④、N-4、Phase 15

门禁:check_doc_links.py --all 通过(143 文档、可判定章节引用 1282 处、
0 错 0 警);check_mojibake 全过;CR=0、U+FFFD=0、无 BOM 变化。
本轮只改 .md,无代码改动,故不跑 @build。
2026-10-14 23:05:17 +08:00
wandering1 1e568b8549 merge: task/ARCHDOCS-sync-20261014 合入 v2-on-ui
任务 ARCHDOCS(2 个提交)经 task-worktree 回收:
- refactor(NET): 源码注释去阶段化 + 网络两份文档重构 + 不稳根因图更新
- docs(架构): 全景/启动顺序/存储/引用图与 README 同步任务面与 NET 内部模块

备注:架构设计文档+README 同步现状(补登记:任务先以 task-arch-docs-sync 手工分支完成,现按 task-worktree 规...
2026-10-14 22:52:40 +08:00
wandering1 d770e36c7c refactor(NET): 源码注释去阶段化 + 网络两份文档重构 + 不稳根因图更新
- 源码注释:删去自愈收敛阶段
1/1.5/3等 scaffolding 称谓,改为语义引用
  (E-02 收口 / F-NET-2/3/4 / docs/网络/网络自愈架构设计.md §5.2 E13);
  涉及 net_socket/.h、net_events、net_listener、net_pending、net_types、
  net_config、ch395f、time_sync、iec104_serv、ui_net_sink、lftpd、
  simulator/sim/net_socket_sim、board/host 测试与探针
- 文档重构:网络自愈架构设计.md 与 Net层阻塞模型架构设计.md 改为现状口径
  (删历史节与阶段叙事),NET/README.md、docs/README.md 同步
- 工具与配图:gen_net_instability_svg.py 与
  docs/images/网络不稳根因总览.svg 随源码口径一并更新
- 门禁:@build 0 错误 0 警告
2026-10-14 22:05:53 +08:00
wandering1 cea2b51efb docs(架构): 全景/启动顺序/存储/引用图与 README 同步任务面与 NET 内部模块
- 项目架构总览 v1.1:§1.1 去重复⑥行、硬件行 UART4/TIM3/ADC1;§2.1
  任务表 6→9 行且栈值按 freertos.c 校准;§3 补采集算法链与 TIM3 节拍;
  §5 补 net_events/net_listener/net_pending 与 iec104_serv,单客户端
  恢复窗更正为实测 p50 208ms;§7 目录树、§9 索引、§10 变更记录同步
- 项目启动顺序管理:任务表 5→10 行;启动轨迹表 8→14 行(fw build、
  ADC input layer、phasor/freq/protection、SD2506 明细、TIM3 启动)
- 存储架构说明:§1 初始化顺序块重写(gd5f 归位 app_main_init 内、
  rs485Task 未创建、补 TIM3 与 L1~L3 链)
- 引用关系图说明 §7 统计与产物重跑刷新;就绪屏障 SVG 补 iec104Task
  消费者后重生成(1400x912)
- README:外设引脚纠错(RS485=UART4/PC10/PC11/PA15、TPAFE 控制脚
  PC8/PC9/PC7)、启动流程补 sys_clock/adc_input/TIM3、任务表重生成
  (9 任务)、目录树与 NET 小节同步、ftp_speed_test→regression/
  integrity、文档表补四条专项索引
- 工具:gen_task_table.py 补 iec104Task/protectTask 职责;
  gen_barrier_svg.py 补 iec104Task 消费者与 bit0 计数
2026-10-14 19:07:48 +08:00
wandering1 4f8e298394 chore(gitignore): .dsh 会话草稿不入库,skills 照常跟踪
现象:每轮 agent 会话在 .dsh/ 根目录留下草稿(提交信息草稿、门禁输出、台架
日志、一次性改名脚本、故障注入 patch),全部以 ?? 挂在 git status 里,混在
真改动中间。本次清掉 17 个:196 KB 门禁输出、台架日志、3 份提交信息草稿、
4 个注入 patch、2 个已合并实现的过程 diff、1 个一次性改名脚本。

规则:`.dsh/*` 忽略 + `!.dsh/skills/` 放行 —— skills 是**入库的项目知识**
(子域方法论),30 个已跟踪文件不受影响。

判据写进注释而非只写"忽略草稿",命中任一就不值得留:
  ① 能重跑的(门禁输出、日志);
  ② 内容已在 git 历史里的(已合并实现的过程 diff —— 如 T0/T1 E17 与
     sock_reset,主干已有 ch395f_sock_reset_begin/poll);
  ③ 离开已丢弃的任务分支就跑不通的(依赖 NET_FAULT_INJECT 的注入产物)。
第 ③ 条是关键:这类东西提交进去是"看着有证据、实际不可复现"的**假证据**,
比没有更坏;方法应沉淀成文档文字 —— docs/网络/网络自愈架构设计.md §5.2
E18/E19 已完整记录注入点、触发方式、判据与实测结果,patch 不是唯一载体。

与 MDK-ARM/retracted_bench_20260922 归档先例的区别(避免下次误套):那次
归档的 probe_*.py 独立可运行,归档理由是"判据是错的,但要立牌警示后人别
再用"。归档的前提是**还能跑、结论错**,不是"根本跑不起来"。

验证:git check-ignore 双向确认(草稿命中 .dsh/*、skills 路径不被忽略);
删除前逐个 git ls-files --error-unmatch 确认未跟踪,**未用 git clean**(会
误伤 skills 下可能存在的未跟踪文件);skills 跟踪数 30 不变;.gitignore 无
BOM / 无 U+FFFD / 无 CR。
2026-10-14 18:25:23 +08:00
wandering1 2a6080827d docs(网络): 自愈架构 §4.1 形态详解 / §4.10 读即清审计 / §1.5 横向对照
四块内容,都是"把已经做完的事写进文档",无新增设计。

1. §4.1 形态表扩成 6 小节:两个所有者 / 四个词 / 形态表(补"芯片命令"列与
   U11 独立行)/ 每个形态为什么长这样、怎么验的 / 为什么 ①③⑤ 常态 0 命中 /
   M3 可疑门与沿革。
   ⚠ 修一处文档 bug:原 ④ 行实际描述的是 U11,真正的 ④ 没有行。已补 U11
   独立行,并在 ⚠ 注记里记录这次更正及其 U12 后果。

2. §4.10 读即清信源审计:两个读即清寄存器与两级门控、现存读清点全量清单
   (产品代码 6 处)、已根除的三条互吞实例、一处"看着像缺陷其实是配对
   消费"、新增一处读清的三条准入判据 + 结构性残余。AGENTS.md 的 CH395F
   单连接 socket 条目加指针。

3. §1.5 与主流 offload 驱动的代码级对照(正面回答"是不是过度设计"):
   ioLibrary close()/listen() 原文、四个机制一一映射、三条约束差异表、
   "死等把代价挪到运行时"、lwIP/Zephyr 对照、诚实清单(可省 16 B / 不可省
   沉降窗 + D10 + listen 前排清 + 登记执行分离)、唯一杠杆是芯片。

4. 模块归属修正(承接 63cf73b 的 net_events.c 抽出):
   - §11.5 新增一节,含"为什么是一个模块而不是两个"(对账真实调用事件
     处理器 2 处 + NET_RECON_STABLE_DEATH 两边共用)与三处非纯搬移;
   - §9 行数快照更新,并加警告:这类快照**当天就会漂移**,是地图不是判据;
   - §1.5 的 net_listener.c 行数随注释精简同步(508/277 → 386/155)。
   引用修正波及 5 个文件:BSD_Socket_API 使用指南文件职责表(拆出
   net_events.c 行)、函数调用关系 §4.8 标题、Net 层阻塞模型两处形态⑤表格、
   CH395F_Trap_Records 两处"对应文件"(保留"原在 net_socket.c"的历史)。
   ⚠ doc-links 只校验 § 编号存在性,照不出"函数在哪个文件"——这类归属
   漂移门禁不拦,必须人工扫。

验证:check_doc_links --all --sections-strict PASS(2146 处引用,可判定
1263,无法判定 0,142 文档);ci_local L0 32 钩子 + L0.5 953/953 全过。
2026-10-14 18:18:06 +08:00
wandering1 dd51221ebc docs(NET): net_listener.c 注释精简 −44%(代码逐行未改)+ 判据指向修正
动机:508 行里注释占 277(54%),其中大量是逐行复述代码的噪音(/* 当前
tick */、/* 置 BUSY(结果回传调用方) */ ×4、/* 交重试轮询(30ms 后复检) */
×3 等),以及把整段陷阱推演塞在调用点旁边。

做法:删逐行复述;删各函数的"出口参数:无"字段;陷阱叙述压成"一句结论 +
指向文档"(→ 网络自愈架构设计 §4.3 / §4.10.3 / §4.2 / §11)。

保留的判断性内容(不是噪音,删了会重新踩坑):2KB 残渣静默截断、
SETTLE < DEADLINE 的时序约束、"只清理不等待 0ms 实测 4/4 仍截断"、严禁
osDelay 忙等、排事件必须在 LISTEN 之前(E14)、U12 对称 close、芯片已在听
绝不发 open、session_dead 刻意不清、clear 必须全清(跨轮残留)、scratch 勿
静态化、预算耗尽 ≠ 放弃、留痕只打首轮。

⚠ 另删一条**自相矛盾的过期注释**("上限 NET_RELISTEN_SETTLE_MS 后强制
放行")——它与 E19 把上限降级为"只留痕"直接冲突,留着比删掉更危险。同时
在相关处补一条显式守卫:此处**绝不**读全局中断寄存器(原警告埋在 7 行
"已删除"说明里,等于没有)。

结果:508 → 386 行(注释 277 → 155,−44%)。**代码逐行未改**:剥注释后
HEAD 与工作版均为 204 行且逐行一致;@build 尺寸完全不变
(Code 212296 / RO 18740 / RW 1112 / ZI 154456)。

顺带修正文件头指向:周期判据 net_reconcile_tick 已于 63cf73b 移入
net_events.c,原写"见 net_socket.c"(.c / .h 各一处)。
2026-10-14 18:17:49 +08:00
wandering1 63cf73b4d0 refactor(NET): 事件处理与周期对账抽出 net_events.c,net_socket.c 3720→3119
动机:net_socket.c 3720 行(注释 1878 / 代码 1518 / 54 函数),BSD 连接层
与"状态面收敛"两套职责混在一个文件里。16 个消费者只依赖 net_socket.h,
故搬移对应用层零波及;模拟器另有 net_socket_sim.c,新模块走 SIM_EXEMPT。

为什么是一个模块而不是两个:实测对账区真实调用事件处理器 2 处(形态② 补
accept 走 handle_connect_event),且 NET_RECON_STABLE_DEATH 两边共用——
拆成 net_events.c + net_reconcile.c 会造出跨模块调用,合起来则跨模块导出
为零。二者同属"芯片状态面与本层镜像的收敛"一个职责。

搬出:5 个 handle_*_event + fire_event + net_reconcile_tick +
net_lost_connect_probe + NET_RECONCILE_*/NET_RECON_STABLE_* 常量 +
net_bench_cmd_log(含其 2 个 static)。

搬移时 4 处 fd 取法替换(其余代码逐行未改,已用剥注释后的代码行多重集
证明差异恰好等于声明的改动集):
- p_sock - s_net_socks → p_sock->ch395_sock(net_socket() 里
  ch395_sock = sockfd,恒等;模拟器同构造)
- 对账循环 &s_net_socks[i] → net_sock_raw(i)

⚠ 随之收窄两处沉降登记的范围门 (qfd >= 0) && (qfd < MAX) → qfd < MAX:
ch395_sock 是 uint8_t,(int) 后恒非负,下界在类型上不可能越界;留着会被
cppcheck 判 knownConditionTrueFalse 拦提交。已在文件头写"勿加回"。

新增 net_sock_raw():对账必须看到 in_use==0 / state==CLOSED 的槽位
(形态④ 认领孤儿监听正依赖 CLOSED 态),而 net_get_sock() 对未在用槽位返
回 NULL 会漏掉这一类。声明放 net_socket.h 而非内部头 net_events.h——规范
S17 2.2 要求非 static 函数声明在配对头文件(同 net_set_errno 先例)。

验证:
- 代码行多重集差异 = 声明的改动集,无一处意外
- @build BUILD_OK 0 错 0 警;Code 212316→212296(−20 B,拆 TU 布局差),
  RO/RW/ZI 完全不变
- cppcheck / coding-standard / registration-check 全 PASS
- @test 硬件闭环 PASS:635ms 到 net init: OK,:8888/:2404/FTP 均建立,
  [ERR]/Fault/relisten/reconcile 命中 0 条
- 台账随 Code 变化同步(ram_baseline --write / check_mem_numbers --write)

遗留(与仍未提交的文档工作同文件,另提):BSD_Socket_API 使用指南的文件
职责表、net_listener.c/.h 文件头"见 net_socket.c"、自愈架构设计 §11 仍把
net_reconcile_tick 记在 net_socket.c——doc-links 只校验 § 编号存在性,
照不出"函数在哪个文件",需在文档提交中一并修正。
2026-10-14 18:04:57 +08:00
wandering1 0edbfaf08b fix(NET): 监听重建单一所有者收口 + 沉降窗 800ms 上限只留痕
CI / L0 静态门禁 (pre-commit) (push) Failing after 1m12s
CI / L0.5 主机侧单测 (MSVC) (push) Successful in 17s
T0 降噪 + T1 单一所有者:四处重建触发(recon/accept/eof/drop)与 pending
第五处统一走 net_listener_request(),由 net_listener_tick 单点执行;
沉降重试日志改"只留首末"(E0 口径),每次恢复少打 3 行重复行。

force open 降级为只留痕(E19 反事实 A/B 实测):芯片未回 CLOSED 时强行
open 注定吃 USE 错(TRAP-NET-09),放行与不放行的端口恢复时刻同一分布
(放行 +512 / 不放行 +505·533 / 降级后 +509 ms)——恢复由芯片何时回
CLOSED 决定。真正兜住"监听器永久失效"的是 D10 预算到期 + 对账形态④
重新登记,不是放行。新增 s_relisten_capped[] 使上限留痕只打一次,
隔离标志不清 → 下一轮继续排空残渣(构建 B 实测每 30ms 两行会刷屏)。

负向注入三轮打靶(E18,注入代码不入库):形态① 吞掉 DISCONNECT 后
4/4 救回、③ 空闲监听器静默失位两轮独立复现、⑤ 开盲区吞掉芯片自发中断
+ 收回 LISTEN 后 -> resync 命中且挂起 recv 被取消 → 三条均不可降级为
只留痕。顺带稳定复现 [ERR] relisten retry budget exhausted = 对端不配合
拆链的签名,非回归。

台架:boot PASS;ftp_abort_probe RST 10/10 + FIN 5/5;relisten_stress
:21 50/50(p50 507ms);n30_repro 30/30。构建 0 错 0 警 Code=212316;
netTask 静态最坏链 1920→1912 B;RAM 台账受管区已 --write 同步(RW +8B)。
文档:E17/E18/E19 三行 + §4.1 常态 0 命中归因 + §4.3 兜底归属改正;
登记簿 N-31 销项(结论沉淀进 §4.3 与 E19)。
2026-10-14 15:57:10 +08:00
wandering1 e95d2be30b docs(任务规划): 新条目改用语义标识——"编号不回收"在实践中不可执行
登记簿原规则写着"编号不回收"(README §0 与 §3 各一处),但销项 = 删行,
删完仓库里就不留任何痕迹 → 该规则要靠人先想起去翻 git log 才成立。

实测撞号:登记簿 N-31(2026-10-11 的 Phase 7 复跑项)销项后,2026-10-14
新建条目按"现存最大值 +1"又取了 N-31,与 CH395F_Test_Guide.md、
自动化测试流程.md 里那两处历史引用同号。

裁定(用户 2026-10-14):新条目 # 列填语义短语(如
"沉降窗 800ms 上限只留痕"),不再新增字母+数字编号;存量编号冻结沿用,
已随销项消失的号一律永久作废、不得作为新条目候选。语义标识自带唯一性
(重名一眼可见),从结构上消除复用可能。

改动:README §0 表首新增"语义标识"行 + 撞号因果注记;§3 原"编号一律
沿用且不回收"整条重写;AGENTS.md 完成即销项条目追加本裁定。
已确认无门禁校验编号格式(check_doc_links 只校 §N.M 与文档路径,
脚本里的 N-23/T-1 是注释性出处)→ 换标识不破任何钩子。
2026-10-14 15:56:54 +08:00
wandering1 f849c79b7a feat(NET): SEND pending 二期落地 + 末块挂起越界缺陷修复(台架复测闭环)
net_pending.c/h 增设第二张挂起表 s_net_send[](与 recv 表完全独立,收发
互不阻塞);net_send_locked 快速路径改为有界自旋,单次等待超出
NET_SEND_SPIN_MS(2ms) 即登记挂起 send,由 net_send_pending_tick 按主循环
节拍分块推进,netTask 最坏停滞由 1s 压到 2ms。net_listener_retry_tick 的
挂起保险扩展到 send 侧;net_close_locked / 网络重建 / 状态对账三路均先
取消再动作(取消必通知,调用方永不挂死)。

台架复测(A/B 对照 + 插桩定位)发现并修复末块挂起越界缺陷:内层"等本块
发完(SENBUF_FREE)"位于写块之后,写完末块时 sent 已 == len,若该次等待越过
2ms 预算便会调用 net_send_pending_register,而登记函数按 sent >= len 拒收
并回 -1,把一次实际已完整交付芯片的发送报成失败。修复为内层等待开头判
sent >= len 即跳出(末块已交付、SENBUF_FREE 等待是纯保守自旋),并置于
超时/自旋判定之前;该守卫同时保证后续登记必伴随 sent < len。

复验:ftp_regression 连续 19 次 11/11;ftp_integrity_test 20 轮 x 64KB
STOR/RETR SHA-256 20/20 一致(两轮),吞吐稳定约 80KB/s;设备日志零
write error;ST-LINK 回读 No difference found。

文档:Net层阻塞模型架构设计.md 补二期设计与新增 9.1 缺陷记录,netTask
栈实测峰值按本次台架 920B 订正为 1116/3840(FTP 传输期 1164);网络自愈
架构设计.md 吸收原监听生命周期文档、新增编号术语导读表,并把 5.2
"实验锚点速查"的 E 编号含义与 E-02 审计编号歧义写在表头(用户反馈该表
E 编号无法读懂)。

门禁:Keil 0 错 0 警;cppcheck / 编码规范 / 乱码零告警;
check_mem_numbers PASS;check_doc_links --all --sections-strict 142 篇 PASS。
2026-10-14 12:05:21 +08:00
wandering1 df13dec479 refactor(net): 挂起 recv 模型拆出 net_pending.c/h + 留痕探针编译门控 + E15 归因修正
CI / L0 静态门禁 (pre-commit) (push) Failing after 2m14s
CI / L0.5 主机侧单测 (MSVC) (push) Successful in 22s
- E15 归因修正:幽灵状态 0x04+旧端口 = 芯片如实报告拆除中的旧连接
  (文档化行为,非芯片故障;bit3=1 为我方设置(ver>=0x46)、
  RFC 9293 §3.3.2 Fig5 拆除顺序、WCH 官方博客方案 = close 完成后重开监听)
- 术语统一:全库"了结"→"结束"(约 45 处);阻塞模型 §4 首次出现处定义"五路"
- 注释清理:删孤儿函数头注释、考古叙事改现在时、去不可检索内部编码"L3"
  (33 处 6 文件)、banner 去重(唯一理由移到分支现场)
- 挂起超时留痕探针:编译期开关 NET_PENDING_TRIPWIRE(默认 0 = 编译剔除,
  省约 150B Flash;排查调用方挂死时置 1,只留痕绝不强制结束)
- 拆模块:net_pending.c/h(363/94 行)承载挂起 recv 模型,
  net_socket.c 4059→3661 行;tick 收控制块表参数、settle_close 双参显式传;
  net_pending_active 声明移配对头(S17 2.2);仅注册 uvprojx +
  check_registration MCU-only 白名单(同 net_listener.c 机制,
  模拟器走 net_socket_sim.c 按外部语义模拟)
- 文档:阻塞模型新增全过程小节(单主干流程图)+ §9 排查辅助;
  NET README / 函数调用关系 / 自愈架构 / BSD 指南同步;引用关系图重生成
- 台架回归:启动闭环 PASS([ERR]/Fault 零命中、回读一致)、
  :7003 重连探针 10/10、FTP 50 连接 STOR 50/50、回归窗口串口日志无异常
- RAM:ER_IROM1 230004B(探针门控后约 -150B),台账已回填
2026-10-14 09:53:38 +08:00
wandering1 a12367981d fix(N34): E14 丢中断复核——芯片不丢事件;listen 排事件挪至 LISTEN 前+全局读收口+全库归因更正
48 轮直读 SINT 矩阵(8 周期×6 变体)复核历史"丢中断"说法:芯片侧事件
丢失 = 0。归类:drain 读清消费 3/48(drain-int 探针现场抓获)、门控
竞态 2/48、主机同步 1/48、幽灵态 0/48 未复现。

根除性修复:net_listen_locked / net_listener_try 的排事件读清从
listen 后挪至 LISTEN 命令之前——新连接 CONNECT 落进该窗即被本方读清
吞掉,即"数据被吞"的生产侧自伤机制(台架 3/48 为同形态放大版)。

全局读收口:全局中断寄存器唯一读者 = net_poll(I7);生产/测试/台架
游离全局读全部删除,ch395f.h 声明处加护栏注释。

归因更正:17 文件约 40 处"丢中断"措辞改为"事件未收到/读清消费竞态"
(机制全部保留,仅归因更正);设计文档 §5.2 新增 E14 锚点;Trap
Records TRAP-NET-17/-20/B3 归因更正段;配图生成器与 SVG 重生成。

台架:事件未收到复核探针保留(drain-int / SINT 补读×3 / 超时归类),
下次跑矩阵自动归类;实验注册(main.c/uvprojx)已完全还原。

验证:@build 0 错误 0 警告;ci_local L0 32/0 + gitlint + L0.5
953/953;doc-links --all --sections-strict 通过;@test PASS(无
[ERR],net init 619ms);回归 :7003 300ms×10 = 10/10、:21 n30×50 =
0/50 失败。
2026-10-14 02:48:50 +08:00
wandering1 1a35b3684c docs(N34): 自愈审计目录 7 份文档合并为单文档,全库引用同步
CI / L0 静态门禁 (pre-commit) (push) Failing after 44s
CI / L0.5 主机侧单测 (MSVC) (push) Failing after 43s
- `docs/网络/N34-自愈审计/` 目录 7 份文档(根因总览 / net 层盘点 /
  驱动层审计 / 主流对照 / 汇总裁决 / 实施方案 / 实验方案)合并为
  `docs/网络/N34-自愈审计.md`(§0~§6),原目录删除;docs/README.md
  索引与变更日志登记归档
- 全库引用同步:4 篇文档 + 驱动/NET/test 代码注释 + 配图生成器与 SVG
- 内容零丢失抽查:E0~E13 实验记录、E6 裁决(命中=0 不立项)、
  提交表(含 `925058a` 收口行)均在位
- 门禁:@build 0/0(注释级路径更新);check_doc_links --all 143 文档
  通过(净 −6 = 删 7 增 1 吻合);ci_local L0+L0.5 全绿
2026-10-13 23:23:55 +08:00
wandering1 491dd031f1 docs(任务规划): N-32 销项——监听生命周期根治已在 N34 全量落地
CI / L0 静态门禁 (pre-commit) (push) Failing after 46s
CI / L0.5 主机侧单测 (MSVC) (push) Failing after 43s
- 登记簿删 N-32 行:P1(`session_dead` 电平)/P2(单一重建所有者)均已
  实施转正;pump 于 N34 阶段 3 并入 `net_reconcile_tick` 形态③④
- 结论沉淀核对齐备:设计文档 §10(已执行)+ D1~D10、N34 实施方案阶段 0~3、
  陷阱记录 B10 行(✅ 已修 + `net_drop_conn` 根治出口)
- 设计文档勾掉两条 N-32 时代遗留清单项:U11~U15 实际落点=N34 机制盘点 +
  E6 观察项;B10 行 2026-10-13 复核在位
- N34 README 提交表补终笔 `925058a` 行
- 正文其余 N-32 引用均为架构溯源名(pump/不变量 I),不动
- 门禁:`check_doc_links --all` 149 文档通过;ci_local L0+L0.5 全绿
2026-10-13 21:50:48 +08:00
wandering1 51472199b4 merge: task/N34-bsd-selfheal-audit 合入 v2-on-ui
任务 N34(24 个提交)经 task-worktree 回收:
- fix(NET)+docs: lftpd 对端地址修复、E6 裁决收口、陷阱编号迁移重排 TRAP-NET-01~21
- docs(问题记录): Trap 12 归档更正——FatFS 议题移入存储架构说明 §10.1
- docs(问题记录): CH395F Trap_Records 重组审计——合并、删误判、主题分章
- docs(N34): 网络不稳根因复盘总览(比喻版)+ 全景图 SVG 生成器
- feat(N34): E6 插桩 NET_U15_PROBE(U15 失配频率,默认关零成本)
- docs(N34): 阶段3 文档同步——reconciler 合并口径+net_drop_conn+Trap 补充
- feat(N34): 阶段3 net层收敛——单一reconciler+忙等统一+镜像降级+E-02收口
- docs(N34): E2/E3/E4 实验结果与定案 + bench 实验区复活
- feat(N34 阶段2): ch395f 五原语只加不接线 + Phase 15 套件 20/20
- docs(N34)+test: E13 僵尸会话根因坐实;Phase 11 判据修正+一次性报告
- feat(NET): N34 阶段 1.5 recv 语义主流化——无限默认+具名非阻塞+模式属性
- chore(scripts): doc-links 检查器在 GBK 代码页下崩溃修复
- feat(net): 服务器侧 KeepAlive 转正(§5.56,E11)+ Phase 11 重开回归
- docs(net): N34 E11/E12 实验记录与台架脚本(KeepAlive 服务器侧缺口、TSL 规格偏离)
- docs(net): E10 补收尾门禁结论(ci_local L0 32/32 + L0.5 951/951)与两处修复留痕
- chore(ram): 同步 RAM 快照/台账受管区至分支当前 .map
- test(time_sync): 单测断言随阶段1契约更新(handle_conn 不再 close)
- docs(net): N34 阶段0/1 实施结果与台架留痕(E10)
- refactor(net)!: N34 阶段1 API 面收敛(对账⑤ + 删 3 个手动自愈 API)
- fix(net): N34 阶段0 零风险清理 9 条(注释债/死码/三处小逻辑门)
- fix(net): N34 M3 矛盾态可疑门,风暴态免疫(E9 实证)
- docs(net): N34 E8 风暴态深查 + T6 核实 + E9 M3 记录
- fix(net): N34 P0 止血包 M1+M2+M4-lite,背靠背 STOR 8%→96.7%
- docs(net): N34 BSD 自愈审计与实施/实验方案(E0-E7b 台架记录)
2026-10-13 20:55:57 +08:00
wandering1 925058a5ae fix(NET)+docs: lftpd 对端地址修复、E6 裁决收口、陷阱编号迁移重排 TRAP-NET-01~21
- lftpd:net_inet_ntoa 段序改 MSB 首 + 新增 net_getpeername,FTP 日志打印
  真实对端地址(真机实证 192.168.1.2:55524,登记 TRAP-NET-21)
- E6:NET_U15_PROBE 命中=0(含压测)→ 阶段 3 项 4 不立项,U15 登记观察项;
  插桩留仓(宏=0 零成本),soak 驱动 test/host/e6_soak.py 入库
- 编号:全库 Trap NN → TRAP-NET-<nn> 迁移并重排连续 01~21(单调映射,
  沿革见 CH395F_Trap_Records.md 头注);死号 12/13/19/21 引用全部清除;
  GD5F 域引用补正为 TRAP-GD5F-NN
- 陷阱文档全新化:索引 21 行行行真陷阱;删误判存档/发现时间/git 考古/
  FTP 附录;台架纪律教训沉淀第六章方法论
- RAM:Code 211348→211456(+108 lftpd 修复),RW+ZI 净增 +4B;
  优化方案/台账受管区/tsv 同笔同步
- ftp_abort_probe.py 挪 test/host/;引用关系图重生成
- 回归:@build 0/0;@test PASS;ftp_abort 10/10;relisten :7003 20/20;
  ci_local L0+L0.5 全绿;E6 窗口零复位,7 条 WD stall 登记压测假象备查
2026-10-13 20:54:31 +08:00
wandering1 74ba7ea61b docs(问题记录): Trap 12 归档更正——FatFS 议题移入存储架构说明 §10.1
- Trap 12 非 CH395F 议题(`CH395F驱动层审计.md` 早已点破;重组时仅就地
  更正未搬家,本次补正)
- 完整内容与根因更正移入 `docs/架构设计/STM32F4-Base存储架构说明.md`
  §10.1 第 14 项——与第 10 项「严格 8.3 短名」通用规则同处,各得其所
- 原址留移档存根(编号保留防旧引用断链,同 Trap 19 惯例);索引行改
  ↦、状态图例补「↦ 已移入他档」;待修清单措辞同步
- 全库确认 Trap 12 无代码引用;check_doc_links 两文件通过
2026-10-13 17:28:53 +08:00
wandering1 b445cbb464 docs(问题记录): CH395F Trap_Records 重组审计——合并、删误判、主题分章
- 合并同根因:Trap 14+17(残留 DISCONNECT 污染下一连接)、Trap 13+21
  (recv_len 归零/接收冻结家族,非缺陷结案);FTP 改造清单表去重入附录 B
- 删当时误判叙述(各留一行误判存档):Trap 07 FIN_WAIT_2/RST 说、
  Trap 18 bit0 迷思、Trap 25「芯片杀连接」解读;B1 KeepAlive 三段翻转
  合并为定案链(E11 转正)
- 规范化:顶部索引表+状态图例;六主题章+附录 A 速查/附录 B 存档;
  条目统一「状态/现象/根因(定案)/修复/回归判据/教训」格式
- 状态刷新:B5 对端 IP 显示已修(代码随收尾批提交)、B10 标 net_drop_conn
  根治出口;Trap 17/20 措辞、Trap 12 根因(按 ff.c)、日期口径就地更正
- 编号永不重排(代码注释 123 处引用);跨文件断链 1 处改条目名引用
  (生命周期设计说明 §877-878 → Trap 25「定案二」)
- 体量 1018 行/102KB → 420 行/64KB;doc-links 两文件通过
2026-10-13 17:12:57 +08:00
wandering1 c7459b393f docs(N34): 网络不稳根因复盘总览(比喻版)+ 全景图 SVG 生成器
- 新增 网络不稳根因总览.md:七个误会(传达室比喻+机制+证据出处)→
  环↔拆法↔落点对照表 → E13 僵尸会话 Mermaid 时序图 → 一句话总结
- 新增 tools/arch_diagram/gen_net_instability_svg.py(draw-diagram 规范,
  纯标准库)与产物 docs/images/网络不稳根因总览.svg(headless Edge 目检两轮)
- N34 README:实施状态表补全阶段 1.5/2/3 与 E6 插桩行(原「阶段 2/3
  未开始」陈旧口径修正);挂复盘总览为第一入口;§5.56 改紧邻写法
- 门禁:check_doc_links --sections-strict 本批 4 文件通过
2026-10-13 17:12:36 +08:00
wandering1 123d80afc7 feat(N34): E6 插桩 NET_U15_PROBE(U15 失配频率,默认关零成本)
实验方案 docs/网络/N34-自愈审计/实验方案.md §E6:验证「RX 非空但
readable=0」(RECV_OK 中断丢失的数据面形态)是否在生产真实发生,
门禁阶段 3 项 4(U15 内化)做不做。

- net_poll 末尾独立探测环:每 32 轮对在用 fd 发 GET_RECV_LEN,
  RX>0 且 readable=0 → 计数 + 低频日志(首次必打,此后每小时 ≤1 条)
- bring_up 尾部 armed 日志(挂机期间核对烧录身份)
- 宏默认 0:产品构建编译剔除,实测体积与上一构建逐字节一致
  (Code=211348 RO=18756 RW=1104 ZI=154232)

判据:24h 常态+E1 压测命中>0 → 项 4 立项;=0 → 盲收保留现状、
U15 登记观察项。
2026-10-13 15:15:22 +08:00
wandering1 f51c0833ae docs(N34): 阶段3 文档同步——reconciler 合并口径+net_drop_conn+Trap 补充
- BSD_Socket_API_使用指南:五层自愈→四层(合一 reconciler 形态①~⑤+U11,
  分级去抖②1/③④⑤2/①4轮+1s冷却);新增 net_drop_conn 小节(拆会话保
  监听/幂等/EOF 不得调);变更记录追加 2026-10-13 行
- BSD_Socket_API_函数调用关系:pump 节点删除、net_drop_conn 链路新增、
  驱动接口表补 sock_reset/cmd_done/缓存行、常量清单更正
- 网络Socket监听生命周期设计说明:新增 §10.10 合并说明,历史文本保留+注记
- Net层阻塞模型架构设计:主循环 3 tick 口径 + 附录 B 追加
- RAM使用分析与优化方案:netTask 链尾改 retry_tick→relisten(1944 B 不变)
- CH395F_Trap_Records:Trap 07 补充(close 无 RST:对端内核存活不 close
  → FIN_WAIT_2 长尾,兜底 E13);Trap 09 补充(LISTEN 态二段关闭)
- 实施方案 §5:项1/2/3/5 ✅、项4 受 E6 暂缓、§5.1 E-02 收口、§5.2 延后项
- 实验方案:E-02 收口台架小节(FIN_WAIT_2/TIME_WAIT ~150ms/双 PASS)
- N34 README 裁决行更正;Test_Guide TC-NET-1101 pump→reconciler 形态③④

历史变更记录与历史事故描述一律原文保留、只追加;check_doc_links
--sections-strict 对改动文件 0 问题;乱码 0、无 BOM 变化。
2026-10-13 15:10:54 +08:00
wandering1 6394853fef feat(N34): 阶段3 net层收敛——单一reconciler+忙等统一+镜像降级+E-02收口
实施方案 docs/网络/N34-自愈审计/实施方案.md §5 项1/2/3/5(项4 U15受E6暂缓):

- 3a 合并reconciler:net_listener_pump删除,与net_reconcile_tick合并为
  单一100ms tick;判据读驱动状态缓存(唯一刷新点=net_poll每轮全量刷新,
  E2背书18.1us);去抖分级②=1/③④⑤=2/①=4轮(M3让位窗400ms保留)+冷却1s;
  链路态订阅留痕(F-DRV-13);探针去抖删除(F-MS-9)
- 3b 忙等统一(P2b):listen/connect open重试与close排空循环改
  net_sock_reset_sync(驱动sock_reset:读空RX→CLOSE→排空事件→等
  byte0=00H,内置LISTEN态二段CLOSE补发);close不再读清全局中断寄存器
  (F-NET-7);net_poll每轮步进活跃复位状态机(驱动契约,防搁浅)
- 3c 镜像降级:net_sock_state_t声明为本层会话投影,芯片事实源=驱动缓存
- E-02收口:新API net_drop_conn(拆会话保监听,QUARANTINE语义,幂等;
  模拟器双端实现;timeSync 30s预算耗尽接入;主机单测TC-TS-027d)
  定案:CH395F close无RST,对内核存活不close的对端停FIN_WAIT_2,
  监听恢复受限于对端close(Trap 07补充),兜底=E13 keepalive/TIMEOUT

台架全绿(Code=211348 RW=1104 ZI=154232):@test PASS;[STACK] net
1116/3840;Trap22 :7003 50/50+:21三档各50/50;Trap23 RST10/10+FIN5/5;
Trap25 n30 11/11;E-02双PASS;iec104 18/18;对时跨会话连续;
ftp_regression 11/11;integrity 15/15 SHA;ci_local L0+L0.5全过。
2026-10-13 15:09:58 +08:00
wandering1 83a70721bd docs(N34): E2/E3/E4 实验结果与定案 + bench 实验区复活
E2:状态回读 18.1us(N=1000x2 逐值一致);LISTEN 可见延迟 100%
<=10ms 无长尾(24 轮)-> "每 poll 全量刷新"成立、reconciler 去抖
可减为 1。
E3:GET_CMD_STATUS 对 OPEN/LISTEN/CLOSE 无判别力(残留假阳性),
定案 cmd_done 用状态回读判据;SET 类命令态永不更新。
E4:排渣序列定案=读空 RX -> CLOSE -> 排空事件(quiescent) ->
轮询 byte0=00H;C 变体(不排渣)0/20 且级联自持,Trap 23 残渣
恰等于单 Socket RX 缓冲整容(rxdrain=2048,19/20)。
E2 补充发现(Phase 15 板测):LISTEN 态 CLOSE_SOCKET 二段关闭
(一次只拆监听 byte0 恒 05,再发一次才落 00)——Trap 09 open
重试环的芯片级原因。

bench:ch395f_reuse_bench.c 复活 N30_CHIP_BENCH 门控实验区
(旧 N-30 矩阵 s_bench_legacy=0 停泊),ch395f_reuse_host.py
增 --mode e4。注册(uvprojx/main.c)实验完已还原不入库。
2026-10-13 12:43:56 +08:00
wandering1 f7f17931c9 feat(N34 阶段2): ch395f 五原语只加不接线 + Phase 15 套件 20/20
实施方案 docs/网络/N34-自愈审计/实施方案.md §4 五原语,形态按
E2/E3/E4 定案(实验方案.md):
1. 类型化状态回读 + 每 Socket 缓存(open=0 时 tcp_state 哨兵
   0xFF;sn>7 边界返 {00,FF} 计 fault);
2. 事件护栏 ch395f_sock_events:只读本 Socket SINT,全局寄存器
   唯一读者=net_poll(F-NET-7 契约);
3. ch395f_sock_reset_begin/poll 非阻塞状态机:读空 RX -> CLOSE
   -> 排空事件(quiescent 2 轮) -> 轮询 byte0=00H;GRACEFUL/
   QUARANTINE 最短等待 100/400ms(Trap 23);WAIT_CLOSE 内置
   LISTEN 态二段 CLOSE 补发(TC1502b 实证 ~180ms 落定);
4. ch395f_cmd_done 状态回读判据(E3:GET_CMD_STATUS 对
   OPEN/LISTEN/CLOSE 无判别力);
5. 链路态缓存 ch395f_glob_event_feed + link_up/变化计数
   (B9 判据 PHY!=DISCONN)。

Phase 15 板测(硬件层模式,Socket 7,无需 PC):20/20 PASS,
含二段关闭语义断言(一段 05/00、二段 byte0=00)。

RAM +56B < 64B(g_sock_state 16B + g_rst 32B + 链路/fault 8B);
产品 Code 与阶段 2 前逐字节同 209780(无调用者被链接器裁剪)。
@test PASS;relisten_stress 20/20、n30 3/3 零回归。
RAM 台账同步:RW_IRAM1 97952B 74.7% / RW_CCM 57376B 87.9%。
2026-10-13 12:43:17 +08:00