diff --git a/.dsh/skills/serial-assistant/scripts/serial_tool.py b/.dsh/skills/serial-assistant/scripts/serial_tool.py
index a47d53e5..d4a18735 100644
--- a/.dsh/skills/serial-assistant/scripts/serial_tool.py
+++ b/.dsh/skills/serial-assistant/scripts/serial_tool.py
@@ -1123,26 +1123,26 @@ def run_selftest():
def check(name, cond, detail=""):
results.append((name, bool(cond), detail))
- # T1 行拆分:CRLF / 多行 / 残行冲刷
+ # 行拆分:CRLF / 多行 / 残行冲刷
sp = LineSplitter()
got = [l for _, l in sp.feed(b"abc\r\n", 1000.0)]
- check("T1a CRLF 行", got == [b"abc"], repr(got))
+ check("行拆分:CRLF 行", got == [b"abc"], repr(got))
got = [l for _, l in sp.feed(b"de\nf\n", 1001.0)]
- check("T1b 多行", got == [b"de", b"f"], repr(got))
- check("T1c 残行不入文件", sp.feed(b"ghi", 1002.0) == [] and sp.buf == b"ghi")
+ check("行拆分:多行", got == [b"de", b"f"], repr(got))
+ check("行拆分:残行不入文件", sp.feed(b"ghi", 1002.0) == [] and sp.buf == b"ghi")
got = [l for _, l in sp.flush_partial()]
- check("T1d 残行冲刷", got == [b"ghi"], repr(got))
+ check("行拆分:残行冲刷", got == [b"ghi"], repr(got))
got = sp.feed(b"\n\n", 1003.0)
- check("T1e 空行忽略", all(not raw for _, raw in got) and sp.buf == b"", repr(got))
+ check("行拆分:空行忽略", all(not raw for _, raw in got) and sp.buf == b"", repr(got))
- # T2 解码回退链
+ # 解码回退链
check("T2a UTF-8", decode_line("中文ok".encode("utf-8")) == "中文ok")
check("T2b GBK", decode_line("中文".encode("gbk")) == "中文")
check("T2c HEX 兜底", decode_line(b"\xff\xfe\x01") == "HEX:fffe01")
- # T3 时间戳格式
+ # 时间戳格式
s = line_at(time.time(), "RX", "x")
- check("T3 行格式", s.startswith("[RX] ") and "T" in s.split(" ")[1], s)
+ check("时间戳行格式", s.startswith("[RX] ") and "T" in s.split(" ")[1], s)
# T4 截头算法(保留尾部 + 截后继续追加)
pat = b"0123456789abcdef"
@@ -1298,8 +1298,8 @@ def run_selftest():
except OSError:
pass
- # T10 端口建议:换 USB 口后 COM 号变了,唯一候选直接给(多候选不猜)
- check("T10 port_hint 唯一候选才给建议",
+ # 端口建议:换 USB 口后 COM 号变了,唯一候选直接给(多候选不猜)
+ check("端口建议:唯一候选才给建议",
port_hint("COM7", ["COM6"]) == "COM6"
and port_hint("COM7", ["COM6", "COM9"]) is None
and port_hint("COM6", ["COM6"]) is None)
diff --git a/MDK-ARM/tcp_reconnect_probe.py b/MDK-ARM/tcp_reconnect_probe.py
index 4cf84feb..4a8fced5 100644
--- a/MDK-ARM/tcp_reconnect_probe.py
+++ b/MDK-ARM/tcp_reconnect_probe.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# TRAP-NET-17 / N-6 trustworthy reproduction probe: rapid reconnect to a device listener.
+# TRAP-NET-17 复现探针:快速重连到设备监听器: rapid reconnect to a device listener.
#
# Failure under test (original report): after a rapid reconnect (<~1s) on a
# relistened socket, the chip completes the handshake but the MCU never gets
diff --git a/docs/测试说明/CH395F_Test_Guide.md b/docs/测试说明/CH395F_Test_Guide.md
index 1ed2e8ee..22215f3b 100644
--- a/docs/测试说明/CH395F_Test_Guide.md
+++ b/docs/测试说明/CH395F_Test_Guide.md
@@ -1095,7 +1095,7 @@ IDLE → ACCEPT → [SEND: 分块发 → DONE] / [RECV: 分块收+校验 → DON
| **标题** | TCP 连接空闲超过 KeepAlive 阈值后自动断开 |
| **前置条件** | 1. `NET_KEEPALIVE_IDLE_MS=60000` / `INTVL=5000` / `CNT=3`(`net_config.h`)
2. 对端须为**死对端**:PC 连接 8080 后**禁用网卡**制造"链路在、对端静默"(存活对端会 ACK 探测 → 永不 TIMEOUT;Windows 防火墙规则对已建立连接无效,E11 实证)
3. 勿与 Phase 6/9/10/13 混选(recv 互抢数据) |
| **测试步骤** | 1. PC 连接 8080,不发数据
2. 立即禁用 PC 网卡(中间有交换机 → 设备侧 PHY 链路保持)
3. 等待芯片报 TIM_OUT(实测判死窗:连接起 **18~31s**,芯片定时语义与手册公式 75s 不符,见 `docs/网络/网络自愈架构设计.md` §5.2 E11/E13)
4. 本层 QUARANTINE → reconciler 形态③④ 重建 → s0 回 LISTEN
5. 恢复网卡,重连 8080 验证端口已恢复 |
-| **通过标准** | recv 返回 0 且耗时落在 **10s~120s 有界窗**(下限防"存活空闲会话被误杀"——T2 实测存活对端静默 90s 不触发;上限防"判死缺位");s0 回 LISTEN 且可接受新连接。报告后测试自动释放 socket 等新连接再测(一次性,防对已死连接 10ms 节奏刷假 FAIL) |
+| **通过标准** | recv 返回 0 且耗时落在 **10s~120s 有界窗**(下限防"存活空闲会话被误杀"——空闲存活场景实测存活对端静默 90s 不触发;上限防"判死缺位");s0 回 LISTEN 且可接受新连接。报告后测试自动释放 socket 等新连接再测(一次性,防对已死连接 10ms 节奏刷假 FAIL) |
---
diff --git a/docs/编号规范.md b/docs/编号规范.md
index 36ff6764..2493a174 100644
--- a/docs/编号规范.md
+++ b/docs/编号规范.md
@@ -74,7 +74,7 @@ P-6 号必须能反查到定义(属主登记处得存在)· P-7 编号不语
- 登记处就是那张表:表首格写短语,**不要再配一个字母号**;跨文档引用写成
`` `docs/任务规划/登记簿.md` 「双转换器无共同采样触发」 ``,同篇后续直接用短语。
- 文档内的实施步骤 / 测试阶段 / 设计原则条目写中文:「步骤 3」「阶段 7」「DMA 边界安全」,
- **不写 `S3` / `TM-PHY-01` / `DP-03` 这种号**。
+ **不写 `S3` / `TM-…` / `DP-…` 这种号**。
---
@@ -128,11 +128,16 @@ P-6 号必须能反查到定义(属主登记处得存在)· P-7 编号不语
元器件位号 `U1`/`C12`/`R3`/`L5`/`D7`(硬件语料按目录整体排除)、数学与协议记号(`N-1`、测频的正序与
负序分量 `S1`/`S2`、`SHA-256`、`RS-485`、`ADC1_IN14`、手册页码)、活表代号 `E0~E19`(网络自愈 §5.2,
**无连字符**,与死号 `E-nn` 只差一个连字符)、Socket 状态组合 `U1~U15`(网络自愈 §1.1)、档位词 `P0~P3`。
-判据只有一条:**带连字符、且能在属主登记表查到定义**才叫编号;查不到的就是普通文本,不是"漏登记的号"。
+判据只有一条:**带连字符、且能在属主登记表查到定义**才叫编号;查不到的就是普通文本,不是「漏登记的号」。
+
+> 2026-10-27 补两条实测口径:① **元器件位号目录整体排除**——`tools/netlist_semantics/` 是硬件知识库
+> (`T1` 在那里是网络变压器位号),已进 `id_registry.json` 的 `excluded_paths`,与 `docs/硬件平台/` 同口径;
+> ② **唯一已知误判**:`docs/算法/傅氏算法详解.md` 里的数学记号 `N-1`(「一个周波 N 个点」的求和上界)会被
+> `N-x` 族命中,属可判定引用、不影响两根护栏,**不清**——清了反而破坏公式。
### 4.5 已删报告的自有族
《项目审查与优化建议报告》2026-10-25 已删除,它自造的六族随之失去定义,且与登记簿同字母不同义。
-看到"报告 N-16"这类写法一律按死号处理:删号留事实——各条目原本指向的设计文档就是现在的出处。
+看到「报告 + 登记簿旧号」这类写法一律按死号处理:删号留事实——各条目原本指向的设计文档就是现在的出处。
---
diff --git a/docs/网络/BSD_Socket_API_函数调用关系.md b/docs/网络/BSD_Socket_API_函数调用关系.md
index 318d6b2f..7ccd062c 100644
--- a/docs/网络/BSD_Socket_API_函数调用关系.md
+++ b/docs/网络/BSD_Socket_API_函数调用关系.md
@@ -50,10 +50,10 @@ flowchart TB
subgraph NT["netTask 主循环 — 1ms/tick;芯片操作唯一执行者"]
NPM["netProcessMessages
先跑 4 个 tick,再排空队列分派"]
NP["netPoll
INT# GPIO 轮询 → 全局中断 → 各 Socket SINT → 状态缓存全量刷新 + sock_reset 步进 → 每轮一批"]
- T1["① netListenerRetryTick
D10 重监听重试:30ms / 2s 时限"]
- T2["② netPendingTick
挂起 recv:①数据 ②到点(仅显式预算) ③断连 ④tripwire 60s 只留痕"]
- T2B["③ netSendPendingTick
挂起 send:①断连 ②推进(每轮≤1块) ③写完 ④无进展超时"]
- T3["④ netReconcileTick
TRAP-NET-17 对账 + 监听重建合一:100ms / 分级去抖 / 冷却
读驱动状态缓存(①②③④⑤ + U11)"]
+ RetryTick["① netListenerRetryTick
D10 重监听重试:30ms / 2s 时限"]
+ PendTick["② netPendingTick
挂起 recv:①数据 ②到点(仅显式预算) ③断连 ④tripwire 60s 只留痕"]
+ PendShimTick["③ netSendPendingTick
挂起 send:①断连 ②推进(每轮≤1块) ③写完 ④无进展超时"]
+ ReconcileTick["④ netReconcileTick
TRAP-NET-17 对账 + 监听重建合一:100ms / 分级去抖 / 冷却
读驱动状态缓存(①②③④⑤ + U11)"]
DISP["队列分派 switch
SEND · RECV · CLOSE
CONNECT · LISTEN · ACCEPT · DROP_CONN"]
subgraph LK["_locked / 内部分派目标(仅 netTask 上下文)"]
LL["netListenLocked
初次监听(open 重试 3× + sock_reset 排渣)"]
@@ -76,24 +76,24 @@ flowchart TB
PUB -->|入队| MQ
MQ --> DISP
DISP --> LL & LN & LS & LR & LA & LC & DC & RLS
- NPM --> T1 & T2 & T2B & T3 & NP
- T1 --> RLS
- T3 -->|"① 已断"| EV
- T3 -->|"② 补 accept"| EV
- T3 -->|"⑤ 静默回收:RESYNC 只修本层 + 取消挂起(不发芯片命令,吸收原 net_resync_listen 语义)"| RSY["reconcile⑤ RESYNC 动作"]
- T3 -->|"③④ 监听失位 / 孤儿监听即重建(原 pump)"| RLS
+ NPM --> RetryTick & PendTick & PendShimTick & ReconcileTick & NP
+ RetryTick --> RLS
+ ReconcileTick -->|"① 已断"| EV
+ ReconcileTick -->|"② 补 accept"| EV
+ ReconcileTick -->|"⑤ 静默回收:RESYNC 只修本层 + 取消挂起(不发芯片命令,吸收原 net_resync_listen 语义)"| RSY["reconcile⑤ RESYNC 动作"]
+ ReconcileTick -->|"③④ 监听失位 / 孤儿监听即重建(原 pump)"| RLS
DC -->|"拆会话后登记重监听"| RLS
NP --> EV
EV --> FE
FE -.-> CB
EV -->|"断连/超时:只置事实"| ST
- ST -.->|"事实 → 由 reconciler 形态③④ 统一重建"| T3
+ ST -.->|"事实 → 由 reconciler 形态③④ 统一重建"| ReconcileTick
LR -->|无数据+阻塞| PR
- PR --> T2
- T2 -->|xTaskNotify| XN
+ PR --> PendTick
+ PendTick -->|xTaskNotify| XN
LS -->|等发送缓冲超预算| SR
- SR --> T2B
- T2B -->|xTaskNotify| XN
+ SR --> PendShimTick
+ PendShimTick -->|xTaskNotify| XN
XN -->|唤醒| PUB
NP --> CH
LL & LN & LS & LR & LA & LC & DC & RLS --> CH
@@ -107,7 +107,7 @@ flowchart TB
2. `net_process_messages()` 开头的 **4 个 tick 是网络层自愈主干**:没有任何应用消息时,重试 / 挂起 recv 完成 / 挂起 send 推进 / 状态对账 + 监听重建照常运转——"断连后即使没人发消息,监听器也能自己活过来"靠的就是它们。
3. 事件处理器**只由 `net_poll` 驱动**,例外是 `net_reconcile_tick`(分级去抖 + 1s 冷却)可再入 `handle_disconnect_event` / `handle_connect_event`——对账是事件未收到的自愈通道(TRAP-NET-17)。**注意职责边界(对账与重建合并后)**:对账与事件处理器**只置事实**(置 CLOSED / 登记沉降),**重建监听的动作统一由 `net_reconcile_tick` 形态③④ 做**(本层唯一重建入口)——"谁先看到 DISCONNECT 就谁重建"的竞争在结构上消失。
4. 回调 `event_cb` 在 **netTask 上下文**执行:回调内不得阻塞、不得发网络操作。
-5. **模块归属**:`T1`(D10 重试)/ `RLS` 的 `net_listener_request` / `ST`(settle)在 `net_listener.c`(真机专属、模拟器不编译);挂起 recv 完成检查(`net_pending_tick`)、挂起 send 推进(`net_send_pending_tick`)与两张挂起表(`PR` / `SR`)在 `net_pending.c`(真机专属);其余 tick(含合并后的 `T3` reconciler)与 `_locked` 在 `net_socket.c`。
+5. **模块归属**:`RetryTick`(D10 重试)/ `RLS` 的 `net_listener_request` / `ST`(settle)在 `net_listener.c`(真机专属、模拟器不编译);挂起 recv 完成检查(`net_pending_tick`)、挂起 send 推进(`net_send_pending_tick`)与两张挂起表(`PR` / `SR`)在 `net_pending.c`(真机专属);其余 tick(含合并后的 `ReconcileTick` reconciler)与 `_locked` 在 `net_socket.c`。
---
diff --git a/docs/网络/网络自愈架构设计.md b/docs/网络/网络自愈架构设计.md
index b34c3660..86a071ab 100644
--- a/docs/网络/网络自愈架构设计.md
+++ b/docs/网络/网络自愈架构设计.md
@@ -858,7 +858,7 @@ accept 走 `handle_connect_event`),且 `NET_RECON_STABLE_DEATH` 两边共用
- 本文引用格式:`docs/网络/网络自愈架构设计.md` §N.M(紧邻写法);E 编号引 §5.2
(如"§5.2 E12"),F 编号引 §7。
- **勿引用已删除的过程章节**。过程考古:
- - N34 自愈审计(T1~T4 三路审计、39 条编号发现全文、E0~E15 原始记录、分阶段实施清单):
+ - N34 自愈审计(三路审计、39 条编号发现全文、E0~E15 原始记录、分阶段实施清单):
`git show 1a35b36^:docs/网络/N34-自愈审计/`(目录合并前 7 份文档)或
`git log --oneline -- docs/网络/N34-自愈审计/`;
- 监听生命周期(本文 §1.1~§1.4 / §4.9 / §9~§11 的来源,含 P0~P3 勾选清单与台架验收记录):
diff --git a/docs/门禁说明/gitlint.md b/docs/门禁说明/gitlint.md
index 76d7ae33..90987ff7 100644
--- a/docs/门禁说明/gitlint.md
+++ b/docs/门禁说明/gitlint.md
@@ -35,7 +35,7 @@
```
gitlint..............................................................Failed
12: BBody line length limit exceeded, lengthy body line (max-line-length: 79)
- 1: T2 Title has trailing whitespace
+ 1: Title has trailing whitespace
```
- 前缀数字是行号(第 1 行是标题)。本仓最常犯的是 `B`(正文行超长)与标题超 100。
diff --git a/scripts/id_registry.json b/scripts/id_registry.json
index ce5028b7..23623e4c 100644
--- a/scripts/id_registry.json
+++ b/scripts/id_registry.json
@@ -59,7 +59,8 @@
".dsh/n31_neg_inject_gen221_form5.log",
"scripts/id_known_backlog.json",
"scripts/rename_maps/",
- "docs/硬件平台/"
+ "docs/硬件平台/",
+ "tools/netlist_semantics/"
],
"excluded_suffixes": [
".svg",
@@ -133,7 +134,8 @@
"^Y[0-9]-[0-9]+$",
"^A-Z0-9$",
"^X-[0-9]+$",
- "^V[0-9A-Z]{2,}-[0-9]+$"
+ "^V[0-9A-Z]{2,}-[0-9]+$",
+ "N-1"
],
"malformed": [
{
diff --git a/test/board/net_test_task.c b/test/board/net_test_task.c
index 8833305c..90828e45 100644
--- a/test/board/net_test_task.c
+++ b/test/board/net_test_task.c
@@ -842,7 +842,7 @@ static int phase11_run(int32_t sockfd) {
* 生产参数实测判死窗口 18~31s(产品验证 连接+30.5s、E11 T5
* 对端失联+30s、T4 短参数 连接+~10s)。本 socket 无在途 TX、
* 对端静默且已失联 → 唯一开枪源是 keepalive,故判据为
- * **有界窗**:>=10s(存活空闲会话 T2 实测 90s 不被杀,10s 下限
+ * **有界窗**:>=10s(存活空闲会话 空闲存活场景实测 90s 不被杀,10s 下限
* 区分"误杀"与"keepalive 判死")且 <=120s(判死必须发生)。
* 勿改回 >=60000——那是对着手册公式写的,会在正确固件上假 FAIL */
TEST_CHECK(elapsed >= 10000U && elapsed <= 120000U,
diff --git a/test/host/e11_keepalive_probe.py b/test/host/e11_keepalive_probe.py
index d8bb11d1..3dc4c178 100644
--- a/test/host/e11_keepalive_probe.py
+++ b/test/host/e11_keepalive_probe.py
@@ -8,18 +8,18 @@ App/ 无任何 net_connect() → 产品上 keepalive 实际关闭。本脚本用
"开启后能否在有界时间内判死静默对端,且不误杀正常空闲会话"。
用法:
- # T2 正常空闲存活:连接后静默 hold 秒,末尾发 KEEPLIVE 验证会话仍在
+ # 场景「正常空闲存活」:连接后静默 hold 秒,末尾发 KEEPLIVE 验证会话仍在
python e11_keepalive_probe.py --mode idle --hold-s 90
- # T1 静默对端:连接后立即装 Windows 防火墙入站 DROP(仅本连接本地端口 +
+ # 场景「静默对端」:连接后立即装 Windows 防火墙入站 DROP(仅本连接本地端口 +
# 设备 IP)→ 芯片 keepalive 探测得不到 ACK → 期望设备在
# IDLE + INTVL×CNT 内判死(本仓 60 + 5x3 = 75s)
python e11_keepalive_probe.py --mode block --hold-s 120
判据(设备侧事件由串口日志核对,本脚本打印 PC 侧时间线):
- T1 期望:串口出现 `[ERR][NET] sockN TIMEOUT`(耗时≈75s),随后
+ 期望:串口出现 `[ERR][NET] sockN TIMEOUT`(耗时≈75s),随后
`sockN pump/relisten` 恢复;本脚本移除规则后新连接必须成功。
- T2 期望:hold 期间**无** TIMEOUT;末尾 KEEPLIVE 必须收到 0xBB 回显。
+ 期望:hold 期间**无** TIMEOUT;末尾 KEEPLIVE 必须收到 0xBB 回显。
需要管理员权限(仅 block 模式装/卸防火墙规则;脚本自行清理)。
"""
diff --git a/test/host/ftp_auth_bench.py b/test/host/ftp_auth_bench.py
index d777d506..9723d033 100644
--- a/test/host/ftp_auth_bench.py
+++ b/test/host/ftp_auth_bench.py
@@ -5,9 +5,9 @@
验证固件侧 lftpd 鉴权集成的完整行为矩阵(主机单测 test/host/ftp_auth 覆盖
不到的"协议接线"部分:命令门、530/331/230/550 响应码、跨会话锁定):
- T1 匿名登录(anonymous) → 期望 530 拒
- T2 未登录直接 NLST → 期望 530(命令门)
- T3 对用户名 + 错口令 ×5 → 期望 530 ×5(并触发锁定)
+ 场景「匿名登录」(anonymous) → 期望 530 拒
+ 场景「未登录直接 NLST」 → 期望 530(命令门)
+ 场景「对用户名 + 错口令 ×5」 → 期望 530 ×5(并触发锁定)
T4 锁定窗内正确口令 → 期望 530(LOCKED,不算哈希)
T5 等待锁定期满后正确口令 → 期望 230(60s + 余量)
T6 登录后 NLST / STOR / RETR / DELE → 期望全通(出厂 write=1)
@@ -83,26 +83,26 @@ def main(argv=None):
if not cond:
fails.append(name)
- # ---- T1 匿名登录被拒 ----
+ # ---- 场景「匿名登录被拒」----
ok, code, conn = _try_login(args.host, args.port, args.timeout, "anonymous", "x@x")
if ok is None:
print("[env] 连不上 %s:%d → %s" % (args.host, args.port, code))
return 2
- expect("T1 匿名登录 → 530", (ok is False) and code.startswith("530"), code)
+ expect("匿名登录 → 530", (ok is False) and code.startswith("530"), code)
if conn:
conn.quit()
- # ---- T2 未登录直接 NLST → 530(命令门)----
+ # ---- 场景「未登录直接 NLST → 530(命令门)」----
time.sleep(0.5) # 单连接 socket:等 auto_relisten 沉降(~50 ms + 余量)
f = FTP()
f.connect(args.host, args.port, timeout=args.timeout)
try:
f.sendcmd("NLST")
- expect("T2 未登录 NLST → 530", False, "居然放行")
+ expect("未登录 NLST → 530", False, "居然放行")
except error_perm as e:
- expect("T2 未登录 NLST → 530", str(e).startswith("530"), str(e))
+ expect("未登录 NLST → 530", str(e).startswith("530"), str(e))
except Exception as e: # noqa: BLE001
- expect("T2 未登录 NLST → 530", False, repr(e))
+ expect("未登录 NLST → 530", False, repr(e))
# ⚠ 必须 close:单连接模型下不关 = 占住 socket,后续步骤全被拒
# (2026-10-11 台架实测:QUIT 后不 close → 芯片视角旧连接仍 ESTABLISHED)
try:
@@ -114,11 +114,11 @@ def main(argv=None):
pass
time.sleep(0.5)
- # ---- T3 错口令 ×5 → 530 ×5 ----
+ # ---- 场景「错口令 ×5 → 530 ×5」----
for i in range(1, 6):
ok, code, conn = _try_login(args.host, args.port, args.timeout,
args.user, "wrong-pass-%d" % i)
- expect("T3.%d 错口令 → 530" % i, (ok is False) and code.startswith("530"), code)
+ expect("错口令 %d → 530" % i, (ok is False) and code.startswith("530"), code)
if conn:
conn.quit()
diff --git a/test/host/iec104_master.py b/test/host/iec104_master.py
index a8dcdf0e..5160c561 100644
--- a/test/host/iec104_master.py
+++ b/test/host/iec104_master.py
@@ -80,11 +80,11 @@ SCAN_COTS = (COT_BG, COT_INIT)
YX_NAMES = {15: "YX15 fault-total", 16: "YX16 OC-I", 17: "YX17 OC-II",
18: "YX18 OC-III", 23: "YX23 overload", 31: "YX31 prot-block"}
-T0 = time.time()
+t_start = time.time()
def log(msg):
- print("[%9.3fs] %s" % (time.time() - T0, msg), flush=True)
+ print("[%9.3fs] %s" % (time.time() - t_start, msg), flush=True)
def hexs(b):