chore(编号): 存量编号全量转语义短语,门禁识别面与语料同批重打

登记簿、文档与代码注释里的存量字母加数字编号(N-x / S-x / T-x / E-x / A-x / 卡号)
一律改写为语义短语,净删 2,028 处引用;删除基线与待确认、并行分道方案、排期详述、
采集保护收尾 4 篇(内容已并入 docs/任务规划/README 与登记簿)。

门禁机器与三张账同批重打:check_ids.py 新增变更记录行豁免与第二根护栏
undecidable_total_ceiling;check_test_traceability.py 只加 stdout/stderr UTF-8
reconfigure(TC_RE 未动);check_cubemx_survival.py 的 --write 固定 newline=LF;
id_registry / id_aliases(+19 条 retired-to-phrase)/ id_known_backlog 重打。

test/ 56 个文件同步 TC 标签语义化,其中 18 个 TU 改了 CHECK / printf 里的标签文字,
是本批唯一改变构建产物的文件集合。

为什么合成一笔、不拆四笔(实测撞闸,非偏好):pre-commit 跑钩子前会 stash 未 staged
部分,拆开后中间提交必然是「新规则 + 旧语料」——实跑可判定 85.15% < 基线 86.00%、
不可判定 1,453 > 上限 1,166,编号门禁直接拦下。编号识别面与它描述的语料只能同码移动。

实跑基线(工作区全量):754 文件 / 8,230 处编号字面量 / 可判定 7,079 = 86.01%
(基线 86.0%,容差 0.1pp)/ 不可判定绝对数 1,151(上限 1,166)/ 校验 1-6 错误级 0 /
告警 = 悬空 2(App/algo/freq.c 的 S2,属 §4.4 同号不同义)+ 孤儿 50。

基线从 84.0 抬到 86.0 的理由见 docs/门禁说明/id-check.md §7.6:本批真删了 2,028 处
引用,可判定面随真实内容上升,不是把分母做小。同批新增排除 docs/硬件平台/ 语料,使
识别面少 264 处——芯片手册位号与网表料号不属编号空间(registry 有 excluded_paths_note)。

⚠ 余量只剩 0.11pp(约 10 处)与绝对数 15 处:把「可判定的引用」改成散文会立刻撞第二
根护栏。另遗留一项:id_aliases 里 retired 的 N / S / T / A 别名没有 scope(U1~U5 有),
今后有人新写一个 A-4,校验 3 不会响,只能靠人,建议下批补 scope。

固件不变证据:115 个 .c/.h 剥注释并归一字符串后与 HEAD 逐字节全等,残留代码差异 0;
App / Src / Drivers 的字符串字面量零改动。@build 0 错误 0 警告;40/40 主机套件、2,889
断言全通过;覆盖率 line 89.2% / func 92.6%;pre-commit 48 钩子 --all-files 全绿;
check_doc_links --all 通过(176 文档,章节引用无法判定 0);逐字节卫生核过:14 个带
BOM 文件与 HEAD 一致、0 个 CR、0 个 U+FFFD,字符串字面量纯 ASCII。

.cubemx_survival_baseline.json 的 watchdog-module 哈希 56bf27 变 2bb051 属合法:
Src/freertos.c 的 USER CODE 区内只有注释文字随编号改写,代码未变。

同批带上体积同码凭证与 RAM 台账行(@build 之后盖戳):RW_IRAM1 79,008 B / 60.3%,
RW_CCM 57,376 B / 87.9%,阈值 92%。
This commit is contained in:
2026-10-26 12:28:14 +08:00
parent 7635480e06
commit 0f7b5a87fb
253 changed files with 2234 additions and 4541 deletions
+3 -3
View File
@@ -154,7 +154,7 @@ CH395F 以太网驱动与 NET 层的实证陷阱:现象、定案根因、修
2. **C 模式真因**:`FUN_PARA` bit3 `SOCKET_CLOSE=1`(§5.52 ②)下产生 DISCONNECT 后**芯片不关 Socket、不清缓冲**,长期停在 `05H/00H`;此时直接 `open_socket` 必返 `0x20` FAIL——**把 Socket 拉回 CLOSED 的动作是 `close`**;
3. **做法**:直接 `ch395f_close_socket()`;`disconnect` 纯属多余且会**制造** DISCONNECT 事件(bit3=1 下必须被消费/预清,否则污染下一条连接,TRAP-NET-12/23 实证);
4. **观测口径**:§5.22 第 1 字节只有 `00H/05H`,第 2 字节(TCP 态)**仅在 byte0=OPEN 时有意义**——关闭后轮询**第 1 字节**等 `00H` 再 open,别拿 byte1 当"卡住"判据。
- **边界(E-02 台架)**:`close` 无 RST 的适用条件——对端配合(收到 FIN 后其内核 close):芯片走 `TIME_WAIT` ~150ms → relisten → 新连接接入;**对端内核存活但不 close**:芯片停在 **`FIN_WAIT_2`(byte0=05H/byte1=06H)长尾**——没有 RST 就拆不掉,**监听恢复受限于对端 close**。不配合场景的兜底 = 芯片自身 TIMEOUT/KeepAlive 拆僵尸会话(判死窗 30~90s,`docs/网络/网络自愈架构设计.md` §5.2 E13)——**不是**应用可加速的路径。
- **边界(台架定案)**:`close` 无 RST 的适用条件——对端配合(收到 FIN 后其内核 close):芯片走 `TIME_WAIT` ~150ms → relisten → 新连接接入;**对端内核存活但不 close**:芯片停在 **`FIN_WAIT_2`(byte0=05H/byte1=06H)长尾**——没有 RST 就拆不掉,**监听恢复受限于对端 close**。不配合场景的兜底 = 芯片自身 TIMEOUT/KeepAlive 拆僵尸会话(判死窗 30~90s,`docs/网络/网络自愈架构设计.md` §5.2 E13)——**不是**应用可加速的路径。
- **应用侧出口 = `net_drop_conn(fd)`**:netTask 侧走驱动 `sock_reset` QUARANTINE(FIN+排渣+排空事件+等 byte0=00H,400ms 底)+ 本层收口 CLOSED + `auto_relisten` 登记重监听(≤1ms 后 `net_listener_tick` 执行);**保监听不毁**(单连接模型不得 `net_close` 监听 fd)。对端不 close 时复位机等在 `net_poll` 步进里(`ch395f_sock_reset_poll`),对端 FIN 到达即自动走完——**不搁浅**。
## TRAP-NET-09 · 沉降窗:PHY link up 后 / close 后不能立即 open
@@ -189,7 +189,7 @@ CH395F 以太网驱动与 NET 层的实证陷阱:现象、定案根因、修
1. **异常释放(TIMEOUT/RST)隔离**:`handle_timeout_event` 置 per-fd 隔离标记;`net_relisten_locked` 隔离期内持续排空芯片 RX(`net_drain_chip_rx()`)+ 主动 close + 排空该 socket 中断 + 等 `CLOSED/TCP_CLOSED`,满 `NET_RELISTEN_QUARANTINE_MS`(400ms) 才 open+listen;上限 `NET_RELISTEN_SETTLE_MS`(800ms) 强制放行——**必须小于** `NET_RELISTEN_DEADLINE_MS`(2000ms):取 2000ms 会耗尽重试预算 → give up → **监听器死亡**;
2. **正常释放(FIN)沉降**:`handle_disconnect_event` 登记(仅 `recv_bytes != 0` 时——纯连接即关与只发不收免沉降保复连时序),relisten 前最短等 `NET_RELISTEN_GRACEFUL_MS`(**100ms**,实测悬崖:0/30ms 无效、100ms 稳定通过);日志区分 `relisten settle`/`relisten quarantine`;
3. **应用侧硬化**:`net_sock_t.released_abnormal` 标记(TIMEOUT 置 1/DISCONNECT 置 0,新 fd 与新监听清零——新连接不得继承上一条的释放原因);`net_pending_tick` 断连结束时按标记以 `NET_ERR_CONNRESET` 或 EOF(0) 回传;`lftpd receive_file` 错误路径 **unlink 截断文件** + STOR 回 **450**。
- **收口尝试与边界(2026-10-14,E16)**:曾把上面修复 1 的排渣序列收口进驱动复合复位原语 `ch395f_sock_reset_*`(去重复实现与参数副本),**实测回退**:`ftp_abort_probe` RST **0/10**、FIN **0/5**(首笔复连仍被截断到 ≤2048B),并新增 `sock_reset_sync timeout (600ms)` / `close: sock_reset not done` 两条 `[ERR]`;同场 net 层自建序列 **10/10 + 5/5**(快复连 50/50、背靠背 30/30 两版都过 → 失效面精确落在"中止后首笔复连")。结论 = 原语缺**隔离窗内持续排空/关闭**与**复用让位**两条语义,补齐前 **net 层保留自建序列**,勿再直接把监听重建接进原语。前置语义与 A/B 数据 → `docs/网络/网络自愈架构设计.md` §8 延后项 1、§5.2 E16;登记 **N-30**。
- **收口尝试与边界(2026-10-14,E16)**:曾把上面修复 1 的排渣序列收口进驱动复合复位原语 `ch395f_sock_reset_*`(去重复实现与参数副本),**实测回退**:`ftp_abort_probe` RST **0/10**、FIN **0/5**(首笔复连仍被截断到 ≤2048B),并新增 `sock_reset_sync timeout (600ms)` / `close: sock_reset not done` 两条 `[ERR]`;同场 net 层自建序列 **10/10 + 5/5**(快复连 50/50、背靠背 30/30 两版都过 → 失效面精确落在"中止后首笔复连")。结论 = 原语缺**隔离窗内持续排空/关闭**与**复用让位**两条语义,补齐前 **net 层保留自建序列**,勿再直接把监听重建接进原语。前置语义与 A/B 数据 → `docs/网络/网络自愈架构设计.md` §8 延后项 1、§5.2 E16;登记条目「relisten 沉降段原语化受阻」。
- **协议边界(不可判定,留痕)**:FTP STOR 无长度声明,"在途 FIN 关闭"与"正常完成"**逐字节不可区分** → 优雅中止仍回 226;仅 RST/掉链(芯片 TIMEOUT)可识别 → 450。FIN 边界由客户端长度校验(SIZE/RETR 往返)兜底。
- **回归基线**:`--check-abort` RST **5/5**(450)+ FIN **5/5**(226 边界不变);followup 全过;正常往返 freeze SHA-256 全 MATCH;`:7003` sink 复用 RST×4/FIN×4 全过;`:8888` 真实收包写 RTC 成功。
- **与 TC-NET-604 的关系**:本条是独立、已可信复现并已修复的真实缺陷;TC-NET-604 已结案为非缺陷(判读教训见第六章台架纪律)。现场"上传失败/文件不完整/像卡死"类报告优先用本条判据复核。
@@ -295,7 +295,7 @@ CH395F 以太网驱动与 NET 层的实证陷阱:现象、定案根因、修
## 主机侧测试工具过期
- **`test/host/ftp_abort_probe.py` 已修**:原用匿名登录,N-19 后匿名被 530 拒 → TRAP-NET-18 两条腿**假 0/5**(round 1 `PASV failed`,且半认证会话占死 FTP 唯一会话,后续轮全变 `ConnectionRefused`)。改 `admin/admin` 后 RST 5/5、FIN 5/5。**教训:跑既有回归腿前先确认凭据仍有效,否则会把工具过期读成固件回归。**
- **`test/host/ftp_abort_probe.py` 已修**:原用匿名登录,FTP 鉴权落地后匿名被 530 拒 → TRAP-NET-18 两条腿**假 0/5**(第 1 轮 `PASV failed`,且半认证会话占死 FTP 唯一会话,后续轮全变 `ConnectionRefused`)。改 `admin/admin` 后 RST 5/5、FIN 5/5。**教训:跑既有回归腿前先确认凭据仍有效,否则会把工具过期读成固件回归。**
- **同族未修**:`test/host/ftp_up_dl_test.py`、`ftp_speed_test.py`、`ftp_test.py` 仍用匿名登录 → 对当前固件必挂登录步;`docs/测试说明/FTP_Test_Guide.md` 推荐的这几个入口因此已失效(现行可用入口是 `test/host/ftp_regression.py`,默认 `admin/admin`)。
## 文档侧待修清单