Commit Graph

937 Commits

Author SHA1 Message Date
super_agent_bot f979b39474 fix(nand-ftl): 传输失败不再误标坏块 + format 不再被脏缓存挡死(#79)
根因(真机定案,问题 #79):旧 dhara_nand_erase/prog() 把一切失败一律
mark_bad,而 mark_block_bad 每次**立即持久化**板级 BBT(不可撤销)——
一次传输层/等忙抖动就把好块永久记成坏块。台架 129 个好块(1016–1142
连续段)被固化,journal prepare_head() 连续 8 次撞 is_bad → TOO_BAD →
Cache flush FAIL → reformat 又被同一页挡住 → 整卷禁用、重启不恢复。

- 修复①:只有芯片明确回 E_FAIL/P_FAIL(状态位证据)才标坏;
  传输/超时失败只报 DHARA_E_BAD_BLOCK 让 dhara 重试,不标坏
- 修复②:nand_ftl_format() 尽力刷一次脏缓存,失败即丢弃并继续
  dhara_map_clear()(格式化语义本就是销毁映射;旧实现第一步返回,
  恢复动作在同一页死锁,f_mkfs 全在旧映射上必失败)
- C4 还债:新增跨调用失败类快照 nand_ftl_fault_get/clear(20 B,
  resume/读/刷/同步四点位记账);defaultTask 探针按类分流,
  BSP_ERR_NO_SPACE 跳过重格式化(容量问题不该用 mkfs 解)
- 哨兵与诊断:init 解锁块保护(A0h)后补回读校验(与 B0h ECC 同族
  缺口,实测本板 A0h=0,非本次根因,留作哨兵);gd5f_bbt_load()
  合并后坏块数 > 出厂扫描时打「BBT after merge」,现场可区分
  真坏与误标固化
- 测试:主机单测 149→178 全绿;新增 format 死锁(TC-NANDPORT-800..
  813b)、传输失败不标坏(207 语义翻转 + 208/505);牙齿检查过——
  把修复回退即见红
- 真机:恢复动作 A 重建 BBT 清除已固化误标(3/3 PASSED,BBT
  version=71);产品镜像复烧 [FS] FATFS mounted、配置出厂模板
  落盘、0 条 flush FAIL——#79 真机闭环(旧卷内容随 map clear
  作废,台架卷为可弃数据)
- 文档:存储架构说明 §10.4 口径修正 + 新增 §10.4.1/§10.4.2(页级
  失败升级链与误标持久化机理),存储维护与容量恢复 §2 补板级 BBT
  独立持久化注记 + §2.1(动作 A 此前静默失效),登记簿 C4 销项
- Keil 0 错 0 警(Code=255552,与烧录验证镜像一致);doc-links 213
  文档通过
2026-11-04 18:16:36 +08:00
wandering1 2b848c4a0b Merge pull request 'feat(sntp): 板端 SNTP 校时接入——coreSNTP 序列化器 + [sntp] 段 + 设置页(#73)' (#77) from impl-sntp-sync-ca4c69f49d3e into master
CI / 静态门禁 (pre-commit) (push) Failing after 5m45s
CI / 主机侧单测 (MSVC) (push) Failing after 44s
Reviewed-on: #77
2026-11-04 16:46:30 +08:00
super_agent_bot ad7338365c feat(sntp): 板端 SNTP 校时接入——coreSNTP 序列化器 + [sntp] 段 + 设置页(#73)
CI / 静态门禁 (pre-commit) (push) Failing after 6m14s
CI / 主机侧单测 (MSVC) (push) Successful in 54s
CI / 静态门禁 (pre-commit) (pull_request) Failing after 4m35s
CI / 主机侧单测 (MSVC) (pull_request) Successful in 47s
- vendored coreSNTP v2.0.0 序列化器(MIT,仅 serializer+LICENSE,零堆),
  48 字节报文编解码在库,节奏与准入判据在本方(RFC 4330 §10 调研口径)
- App/sync/time_sntp.c 挂 timeSyncTask 的 8888 事件循环,等待切片 ≤50 ms,
  不饿任务狗与 IWDG;懒建 UDP socket,代际变化/禁用/死错误码即关闭归还
- 防伪 = OriginTimestamp 逐位等于发出时 T1(含低 16 位随机小数位);
  mode/stratum/闰秒指示/KoD 按 RFC 拒收;DENY·RSTR 换服务器、RATE 只退避
- 主备轮换 + 失败指数退避(5 s 起、60 s 封顶)+ 首轮 1~5 分钟随机错峰;
  成功恢复 poll_min 周期(1~1440 分,出厂默认 60,默认不启用不发包)
- 钟面 = 本地时间:UTC+8 固定偏移落 sys_clock_set_unix(§1.1 时基裁定,
  第三个写入口,装置仍不存时区);|offset|<2 s 只记日志不步进,冷启动或
  更大偏差步进并回写 SD2506,留痕 [SNTP] step 与 syslog OPER
- 首个校验通过的同步置 SYS_EVT_TIMESYNC_READY(就绪位,消费方按需 NoClear)
- [sntp] 配置段(enable/server1/server2/poll_min)属主 sntp_cfg.c,
  注册在 net_cfg_load();UI 页 31「SNTP 设置」(密码叶):启用开关 +
  主/备服务器 octet 编辑 + 周期(分) + 保存,复用 net_cfg_save_request 链
- 测试与门禁:test/host/sntp 新套件(报文/防伪/KoD/退避周期/阶跃域/配置
  注册表)、net_cfg 与 time_sync 套件补 fake、黄金参考 66→74 张零漂移、
  字符集 228 字、Keil 0 错 0 警(RO +5,848 B 含字体)、覆盖率基线回填
- 文档:墙钟维护说明 §16、网络配置说明 [sntp] 节、配置文件设计说明变更记录、
  产品需求 FR-TIME-3 与 8.3/9.1.2 台账、UI 补齐规划/UI补齐 31 叶口径、
  登记簿销项并登记「SNTP 校时真机判据」等台架(PC 时间源 192.168.31.161/.13)
2026-11-04 16:20:22 +08:00
wandering1 c1beec50e7 Merge pull request 'fix(serial-assistant): daemon 重启自动重开口 + 自动重连 + 日志缺口标记(#75)' (#76) from improve-serial-assistant-8e959e85113d into master
CI / 静态门禁 (pre-commit) (push) Failing after 45s
CI / 主机侧单测 (MSVC) (push) Failing after 43s
Reviewed-on: #76
2026-11-04 11:39:09 +08:00
super_agent_bot dfd1528409 fix(serial-assistant): daemon 重启自动重开口 + 自动重连 + 日志缺口标记(#75)
CI / 静态门禁 (pre-commit) (pull_request) Failing after 4m19s
CI / 主机侧单测 (MSVC) (pull_request) Successful in 44s
CI / 静态门禁 (pre-commit) (push) Failing after 4m51s
CI / 主机侧单测 (MSVC) (push) Failing after 43s
按 Gitea issue #75 R1–R5 修采集层「daemon 死了采集静默停摆」族问题:
旧行为下 daemon 崩溃/被杀/读错丢口后,新实例起得来但口不开
(run() 先 _save_meta 把现场覆成 null,且无任何重开路径),
serial.log 缺口无边界,wait-idle 计满还良性返回 no_data,
把「采集器死」伪装成「板子静默」。

- R1 启动自动重开:meta.json 的 port 字段升格为「开口意图」现场
  (缺口期不清空,显式 close/stop 清除);run() 先读旧 meta 再覆写;
  重开在串口线程内执行(串口对象唯一持有者不变量),首次 = 出生 +1.5s。
  restart 特判:cmd_start(force) 在 stop 前抓 /status 现场、新 daemon
  就绪后 POST /open 开回来(stop 语义不变,结果进返回 JSON 的 reopen 键)。
- R2 失败自动重连:_port_error 后退避重试(REOPEN_SETTLE_S=1.5 起步、
  倍增、REOPEN_BACKOFF_MAX_S=30 封顶)直到成功或显式 close;
  逐次失败原文进 daemon.log(dlog=stderr),不刷 serial.log。
- R3 缺口标记:serial.log 落 [SYS] 行——daemon started(新旧 pid +
  重开现场)/ GAP-START(丢口与崩溃恢复两种,窗口起点下限声明)/
  GAP-END(窗口秒数 + 尝试次数 + 字节不可找回)/ GAP-RETRY(退避期
  仅首次 + 之后每分钟 ≤1 条,口径定死并写入设计说明 §6.1)。
- R4 状态可见:status 新增 auto_reopen{enabled,pending,attempts,
  last_error,next_retry_in_ms};port 新增 desired(意图)与 ready
  (实际)并列,缺口期 name/baud 显示待重开参数;wait-idle 入口加
  无口门:口未开秒回 ok:false + 现场,不再计满返回良性 no_data。
- R5:VERSION=1.2.0-skill;selftest 新增 T10–T15 共 22 项无头用例
  (重开意图判定 / 退避倍增封顶 / 缺口行格式 / 无口门 / auto_reopen
  三态 / restart 捕获),合计 45 项全绿;SKILL.md 与使用指南、
  设计说明 §6.1+§13 同步(机理只在设计说明详述一处)。

兼容性:JSON 只增字段、退出码形状不变;run_boot_test.py 正常路径
不受影响,其 wait-idle 撞无口时按采集错误 exit 2 归因(正是工单
要的区分)。

验证:selftest 45/45 PASS;COM3 台架三场景全过(崩溃恢复自动重开
+ GAP 标记、显式 close 后 restart 不重开、wait-idle 快速失败),
transcript 见工单汇报。
2026-11-04 11:10:04 +08:00
wandering1 f8c9296392 Merge pull request 'feat(net/udp): UDP 数据面并入 netMsgQueue 串行执行(#73)' (#74) from udp-queue-impl-ddb7c192c16e into master
CI / 静态门禁 (pre-commit) (push) Failing after 5m10s
CI / 主机侧单测 (MSVC) (push) Failing after 43s
Reviewed-on: #74
2026-11-04 10:11:24 +08:00
super_agent_bot c9c9dc8b0d docs(测试): 阶段 16 按两轮镜像分别登记尺寸,产品 Code 对齐 249,120(#73)
CI / 静态门禁 (pre-commit) (pull_request) Failing after 5m3s
CI / 主机侧单测 (MSVC) (pull_request) Failing after 43s
恒剥改造让产品构建 `Code` 从 249,124 变成 249,120,`docs/测试说明/板级测试/CH395F_Test_Guide.md`
§12.6 里两处跟着真机重算:

- 构建实测段不再只写一个镜像——第一轮的 `phase16c.hex`(836,489 B,Code 259,768 / RO 37,244)与
  全绿那轮的 `phase16d.hex`(836,608 B,Code 259,764 / RO 37,288 / RW 2,060 / ZI 151,596)分开登记,
  并写明第二轮与前一轮的差异来源:生产代码少一次形态比较(−4 B)+ 断言文案改写(RO +44);
  产品态那行改成 `Code 249,120`,并说明与 249,124 的 −4 B 属生产代码变化、与阶段 16 无关。
- 「实测结果」那行补上板端串口原文里的构建戳 `Nov  4 2026 08:40:28`。
- 2026-11-03 夜那条进度里的「1603 之后仍未测」改成「当时未测(次日已补全)」,避免读起来像现状。
- `docs/测试说明/单元测试/主机单测覆盖率口径.md` 第 4 轮的真机回归条目,把「head `1b5e5d4` + 剥头修正」
  改成剥头修正实际所在的提交 `b5671e8`。
2026-11-04 09:45:34 +08:00
super_agent_bot fe4f0db01c chore(台账): 恒剥修正让 Code 少 4 B,机器回填内存台账与同码凭证(#73)
CI / 静态门禁 (pre-commit) (push) Failing after 4m45s
CI / 主机侧单测 (MSVC) (push) Successful in 44s
CI / 静态门禁 (pre-commit) (pull_request) Failing after 5m16s
CI / 主机侧单测 (MSVC) (pull_request) Successful in 43s
剥头判据简化(去掉一次形态判断与一次比较)之后,产品构型 `Code` 从 249,124 变到
249,120,`ER_IROM1` 278,960 → 278,956、ROM 合计 281,012 → 281,008;`RW` / `ZI`
一字未动。台账里那些数字是受管区,按仓库约定不手改:

- `python scripts/check_mem_numbers.py --write` 回填 `docs/内存管理/RAM使用分析与优化方案.md`,
  `--scan` 复跑 exit 0;
- `python scripts/ram_baseline.py --write` 回填 `docs/内存管理/RAM预算台账.md`,
  `--gate` 现在 **PASS:RW_IRAM1 72.2 % / RW_CCM 87.9 %(阈值 92 %)**;
- `python scripts/ram_baseline.py --update` 追加 2026-11-04 趋势行,并写出本轮
  体积同码凭证 `scripts/size_attestation.json`(索引指纹 2f112c1679d6…,1468 个文件)。
2026-11-04 09:25:49 +08:00
super_agent_bot f10bb8df65 docs(net/udp): TRAP-NET-22 追加真机定案,网络与测试文档同步(#73)
CI / 静态门禁 (pre-commit) (push) Failing after 5m30s
CI / 主机侧单测 (MSVC) (push) Successful in 50s
CI / 静态门禁 (pre-commit) (pull_request) Has been cancelled
CI / 主机侧单测 (MSVC) (pull_request) Has been cancelled
- `docs/问题记录/CH395F_Trap_Records.md`:TRAP-NET-22 追加 2026-11-04 段——现象
  (客户端形态 48 B 读成 56 B、首字节 0x38)、根因(**帧格式在 OPEN_SOCKET 那一刻
  由 DesIP 定死**,运行时改 DesIP 不改它)、修法(恒剥 + 源地址一律取信息头),以及
  这条最该记的教训:手册一句话读错,就写错一层契约,而且主机侧 240 轮随机长跑会
  照着同一个错模型绿过去。
- `docs/网络/BSD_Socket_API_使用指南.md` §6.0/§6.3:形态表与"客户端不剥头"条款
  按定案重写,`sendto` 显式目的地址 = 切发送去向,不再承诺帧格式变化。
- `docs/网络/BSD_Socket_API_函数调用关系.md` §4.11:`net_udp.c` 一表的收包路径
  说明同步。
- `docs/测试说明/单元测试/主机单测覆盖率口径.md` 第 4 轮:26 组 UDP-1~26、全套
  677/677、UDP-26 的来由(覆盖率门禁照出兜底路径没人走,补测试而不是降基线)、
  以及真机第一轮 33/47 到第二轮 77/77 的经过。
- `docs/测试说明/板级测试/CH395F_Test_Guide.md` §12.6:阶段 16 的实测结果表
  (2026-11-04 08:42,板端 `77/77`、PC 端 `27/27`,台架必验 ①~⑤ 全部成立)+
  关键串口原文 + 唯一未量项(等待期 CPU 占用 / IWDG 余量的定量读数)如实留白。

登记簿销项按仓库约定不进本分支(分支不动 `docs/任务规划/**`)。
2026-11-04 09:15:53 +08:00
super_agent_bot 66725c0fa3 test(net/udp): 阶段 16 判据文字按真机定案改写,PC 对端不再被 ICMP 拒收打爆(#73)
板级 1603 的标题写的是 "48-byte reply, no header strip in client mode",判据本身
(读回 48 字节且逐字节等于发出去的载荷)在真机上就是对的——错的是那句解释。标题
与两处注释按定案改写,判据一字不动:改判据等于把测出来的事实抹掉。

PC 对端 `test/host/udp_queue_bench.py` 修了一条会把台架自己打死的毛病:Windows 上
对端端口没人听时,发出去的 UDP 会收回 ICMP port-unreachable,CPython 把它变成
`ConnectionResetError [WinError 10054]` 挂在下一次 recv 上(3.14 既没有
`socket.SIO_UDP_CONNRESET` 也拒绝那个数字 ioctl,只能接住这个异常)。原来的写法是
一接到就立刻重发,run #3 从第 148 秒起以约 100 包/秒灌进 CH395F,日志刷出
940,949 字节的「TC 0x02: 无回显,重发」——**板子的真实行为被自己的对端淹掉了**,
看起来却像板子不回包。现在一轮之内跑满预算、按次数限流打印。

回路自检 `test/host/udp_queue_bench_loopback.py` 改后 **27/27 PASSED**。
2026-11-04 09:15:52 +08:00
super_agent_bot 0d469a835a test(net/udp): 主机单测按真机改写 UDP-4/17/22/24,补残包组 UDP-26(#73)
剥头判据改了,测试就得跟着改——但这一条提交里真正值钱的是"为什么会错到":
UDP-4 当时写的是"客户端形态整包都是载荷、源地址取对端记账",UDP-24 的 240 轮
定种子随机长跑也照同一个模型脚本报假件。**随机长跑全绿恰恰不能证明模型对**:
它扫的是我自己写的那套模型,模型错了它一样绿。只有真机那次 48→56 的读数把这件事
钉死。

- UDP-4 改写为"客户端形态同样剥头",源地址来自信息头(脚本里特意让头里的源
  `119.28.220.215` ≠ 记账对端 `119.28.220.214`,这样"取错地方"就必然失败),
  并补 UDP-4h 断言 `addrlen`/family 与服务器形态一字不差——一条读路径就该一个契约。
- UDP-17h/m、UDP-22c、UDP-24 的客户端轮同样按定案重写(先 `reset_recv_len` 再
  宣布长度,假件的收包脚本必须可重排,这是长跑教过的第二条)。
- 改完判据后覆盖率门禁照出 `net_udp_src_from_peer()` 一行没人走了。**没有把基线
  调低**,而是补 UDP-26(9 条)钉住"`<8` 字节残包"那一侧:整包原样交付、一个字
  节都不许剥、源地址退到对端记账;没记账时交出全零这个"我不知道",而不是包里的
  字节——它是记账那本账如今唯一的读者。

全套 **677/677 绿**(改造前 470);`net_udp.c` 回到 237/239 行、14/14 函数,
`net_socket.c` 966/969 行、59/59 函数,全仓 8372/9290(90.1 %)、47/47 套,
`scripts/test_coverage_baseline.json` 与改动前一字未变(即无回退)。
2026-11-04 09:15:52 +08:00
super_agent_bot b5671e8c02 fix(net/udp): 收包剥头只看芯片宣布的字节数,与 udp_mode 无关(#73)
真机第一轮(2026-11-04 08:16,阶段 16 台架)把本轮最大的一条设计错误照了出来:
TC-NET-1603 在客户端形态下发 48 字节应答,板子读到的是 `n=56`、首字节 `0x38`
——56 正是信息头的长度字段,也就是**头还在**,而我把它的 8 字节当成了载荷。

设计时按手册 §9.2.4 读出一句"客户端模式不带信息头",就以为运行时把 DesIP 从
全 F 改成具体对端会让头消失。真机给的定案是:**加不加 8 字节信息头,是在
OPEN_SOCKET 那一刻由当时的 DesIP 定死的**,之后再改 DesIP 只改发送去向与芯片
的收包源过滤,不改收包帧格式。本层 `net_bind` 一律以 DesIP=0xFFFFFFFF 开
Socket,所以对本层的 UDP socket 而言头恒在、恒剥。

- `net_udp_datagram_read` 的剥头条件由 `udp_mode == SERVER && avail >= 8` 改为
  **只看 `avail >= 8`**;源地址一律从信息头里取——头里的源 IP/端口是本包的真实
  来源,比"我把包发给了谁"这本账更准(NAT 后的时间服务器就是两种地址不一致的
  那种)。
- 不足 8 字节的残包保持既有定案(TC-NETSOCK-440o):无从判头,整包按载荷交付,
  源地址退到对端记账。这也是 `net_udp_src_from_peer()` 如今唯一的读者。
- `udp_mode` 语义收窄为"芯片的对端过滤 + 发送去向",**不描述收包帧格式**;
  `net_types.h` 的 UDP 形态块、两个模式宏的注释、`net_sendto` / `net_recvfrom`
  的函数说明一并按定案改写。字段本身没动,仍复用原有的 2 字节 padding,RAM 零增长。

产品构型 Keil 构建 0 Error 0 Warning,`Code=249120 RO=29836 RW=2052 ZI=149996`,
与改造前的产品基线同尺寸。判据文字与真机证据见同批的测试、文档提交。
2026-11-04 09:15:17 +08:00
super_agent_bot 1b5e5d424c test(net/udp): 主机单测补 UDP-25 两条 socket 并存的隔离(#73)
CI / 静态门禁 (pre-commit) (push) Failing after 45s
CI / 主机侧单测 (MSVC) (push) Failing after 50s
CI / 静态门禁 (pre-commit) (pull_request) Failing after 45s
CI / 主机侧单测 (MSVC) (pull_request) Failing after 45s
前 24 组全都只用一条 UDP socket,漏掉的正是队列化真正要保的那半句承诺:
**等待是一条 socket 自己的事**——串行的是命令,不是等待者。

UDP-25 用 13 条断言钉住两条并存 socket 的四件事:fdB 来包不得结算也不得通知
fdA 的 parked 收包(连它的调用缓冲都不许被写一个字节);fdA 自己的包到达时按
自己那一包的表头结算并恰好通知一次;fdB parked 时 fdA 自己 recvfrom 照常拿到
数据;关停在等的 fdB 必须当场结算、槽位与出参槽都不残留。

写这组时踩到假件的一个真坑,值得记下来:假件的 get_recv_len 是"每次读消耗一格、
最后一格永远重复"的脚本队列,本组前面给同一 fd 留过旧长度,不清就会拿**旧长度配
新内容**(现象是 UDP-25j 读出 12 字节而不是 7 字节),所以每条用例前用
ch395f_fake_reset_recv_len(fd) 归零再宣布——这是测法问题,不是被测代码的问题。

全套 667/667 绿(改造前 470,本次 +13);net_udp.c 仍 237/239 行 14/14 函数,
net_socket.c 966/969 行 59/59 函数,模块级覆盖率无回退。
2026-11-04 01:28:01 +08:00
super_agent_bot f4ed8a4db2 test(net/udp): 阶段 16 补 TC-NET-1610 免对端自检,断线时也有板端证据(#73)
CI / 静态门禁 (pre-commit) (push) Failing after 4m18s
CI / 主机侧单测 (MSVC) (push) Successful in 44s
CI / 静态门禁 (pre-commit) (pull_request) Failing after 3m49s
CI / 主机侧单测 (MSVC) (pull_request) Successful in 45s
第一次上台架就是被「没有对端」卡住的:peer 脚本被 Windows 的 ICMP 10054 打死、
梯子错位,TC-NET-1601 之后一步都测不到,整趟真机证据直接归零。板子的 10 pin 杜邦线
又断了(#73 讨论区已记),台架短期内还会反复断,所以把「不需要 PC 发一个包也能确认」
的那一半补进阶段 16。

板端 test/board/net_test_task.c 新增 udp_bench_peer_free_check(),17 条断言
(TC-NET-1610a~q),执行位置在 1601 之前、编号留在段尾:编号是给台账用的,不该因为
断线重跑而漂。四类判据:

- 形态记账:新建 DGRAM socket 与 bind :6003 之后都读 NET_UDP_MODE_SERVER;
- 参数与出参守卫:未 bind 的 net_sendto 报 -5 NOTCONN、流式 net_recv 读 DGRAM 报
  -3 INVAL(绕开剥头就会静默吃 8 字节)、to_ms==0 报 -3 INVAL、src_addr 缺 addrlen
  或容量只有 4 字节报 -3、空缓冲 DONTWAIT 当场报 -7 WOULDBLOCK(不登记挂起);
- 「阻塞收包已改成挂起登记」:net_recvfrom_to(2000) 返回 -2,实测睡眠落在
  2000~4500 ms——等待睡在任务通知上,不在 SPI 总线上自旋。预算取 2 s,压在产品
  IWDG(2.5 s)与 netTask 喂狗窗口之下,万一退回旧版自旋,会先被看门狗抓到;
- 关闭与复用:net_close 后同一槽重新 bind :6003 不被上一条命毒化(DONTWAIT 仍 -7),
  set_peer(fd, NULL) 在本就是 SERVER 时是无副作用的 0 返回(不许重开芯片 socket)。

代价只有 flash:bench 态 Code 257,388 → 259,768、RO 34,136 → 37,244(全是断言字符串),
RW/ZI 一字未增(复用那块 1,600 B 收发缓冲),RW_IRAM1 仍 96,232 B / 73.4%。
产品态(四行宏回默认重新构建)Code=249,124 / RW=2,052 / ZI=149,996,与本阶段之前
逐字节一致,阶段 16 在产品里被预处理干净。两态均 0 error 0 warning(2026-11-04 01:06)。

文档同步:CH395F_Test_Guide §12.6 用例表补 TC-NET-1610 行与「没有对端也要有证据」一段;
ch395f_test.h 的 RAM 台账补这轮增减数字与其来源;主机单测覆盖率口径 第 4 轮记明这半
「已编过、仍未在真机上跑过」——断线期间它一条也测不到,不能算证据。
2026-11-04 01:11:01 +08:00
super_agent_bot 9608b7a8ea test(net/udp): 加 240 轮定种子随机长跑 UDP-24,配套假件补可重排收包脚本(#73)
CI / 静态门禁 (pre-commit) (push) Failing after 45s
CI / 主机侧单测 (MSVC) (push) Failing after 44s
CI / 静态门禁 (pre-commit) (pull_request) Failing after 46s
CI / 主机侧单测 (MSVC) (pull_request) Failing after 44s
真机台架被断电和断线卡住,这一段只推进纯软件侧:把 UDP 数据面的随机序列
扫起来,并修掉随机长跑逼出的两条"测法自误"。

- ns_s7_udp.c 新增 UDP-24:固定种子 20261104 的 240 轮随机交互,每轮随机
  载荷长度 1~112(112 = 假件收包流 128 B 上限减 8 字节信息头)、源端口、
  源 IP、SERVER/CLIENT 形态、显式对端 sendto 与按记账对端 sendto,每 17 轮
  close + 重 bind 一次。断言收在六族不变量上(长度等于芯片宣布值、既不吞
  信息头也不丢真字节、源地址按形态分别取自表头/对端记账、udp_mode 与命令
  一致、close/重 bind 后出参槽与挂起槽不残留、每次 sendto 交给芯片恰好 len
  字节),并要求 ≥90% 轮次端到端干净(实测 240/240)。
- 长跑逼出的两处都是测法问题,不是被测码 bug,但只有长跑才逼得出:
  1) 连续 sendto 不注入 SENBUF_FREE 时,第二次发送会合法转挂起,而本套的
     挂起 send 替身从不完成,于是 FATAL 掐死整套件(连汇总行都没有)。改法
     照 440i/440j:set_sint_sticky(SENBUF_FREE) + push_glob + g_ns_int_pin_set=0,
     注释点名 TRAP-NET-04,背靠背发送的真机面留给 TC-NET-1609。
  2) 假件 ch395f_get_recv_len 是"按调用序号取、耗尽后重复最后一个"的脚本且
     容量有限,240 轮只追加不清空,序号撞满容量后每轮读到同一个陈旧长度
     (症状:len 在随机而 n 恒为 28,前 24 轮全绿,最容易误判成产品 bug)。
     补加法助手 ch395f_fake_reset_recv_len(sock),只归零该 sock 的脚本长度与
     序号,既有单轮用例不调用它、行为一字未变。
- 覆盖率口径第 4 轮同步:用例面记到 24 组、全套 654/654(改造前 470),
  新增一条"随机长跑逼出两条测法自误"的教训(长跑对假件的第一要求是
  状态可重排,不是能追加)。

验证:net_socket 套件 654/654 绿;全量覆盖率 47/47 退出码 0,net_udp.c
237/239 行 99.2%、14/14 函数,net_socket.c 966/969 行 99.7%、59/59 函数,
总行 8372/9290(90.1%),无 REGRESS;cppcheck(--hook-stage manual)退出码 0;
check_doc_links --all 通过(213 个文档,无法判定 0);pre-commit 对本批文件
全绿。基线 JSON 无变化(本轮只加测试,未动生产码),故不随本提交改动。
2026-11-04 00:46:08 +08:00
super_agent_bot fc0d3e4b5c test(net/udp): 阶段 16 台架加固 + 真机首跑证据回填(#73)
CI / 静态门禁 (pre-commit) (push) Failing after 5m39s
CI / 主机侧单测 (MSVC) (push) Successful in 30s
CI / 静态门禁 (pre-commit) (pull_request) Failing after 4m15s
CI / 主机侧单测 (MSVC) (pull_request) Successful in 47s
第一次上真机把台架的两处软肋照出来了,都不是被测代码的问题:

- peer 死在 Windows 的 ICMP 10054:板子还没 bind 时那一下端口不可达会被记在套接句上,
  下一次 recvfrom 才抛出来。本机 CPython 3.14.7 既没有 socket.SIO_UDP_CONNRESET 也不接受
  它的数值形式,所以主力防线改成把 10054 当「这一轮没收到」继续重试,并在回路自检里加
  冷端口探针——探针走脚本真正在用的 _recv_maybe,另拿裸套接句证明这台机器确实会回 ICMP,
  否则那条判定就没有牙。
- 单步预算错位:板端每步等 25 s,peer 每步只等 8 s,一步超时后整条梯子全灭。现在 peer
  每步都重发、单步预算 --step-budget 默认 35 s(小于 26 s 打警告);板端 udp_bench_expect
  按载荷第 0 字节的步号自愈,比本步小的旧包丢掉继续等(上限 UDP_BENCH_STALE_MAX = 8),
  比本步大的直接报出来。DBG_WARN 在本工程不存在、字符串字面量必须纯 ASCII,两处已改。

真机已拿到的证据:TC-NET-1601a/b/c(建 socket、bind :6001、net_udp_get_mode 回 SERVER)与
TC-NET-1602(服务端形态收到 20 B、addrlen/sin_family/源端口全对、逐字节回显、形态翻成
CLIENT)全绿——剥 8 字节信息头与源地址回填在真芯片上成立;②③④⑤ 因板子当晚两次失电
(19:19、21:0x,SWD No target connected + ping 不通)未测,指南 §12.6 与覆盖率口径第 4 轮
的状态条据此改写。产品态(宏回默认)重新构建 0 Error 0 Warning,Code 249,124 / RO 29,836 /
RW 2,052 / ZI 149,996 与本阶段之前逐字节一致,阶段 16 在产品里被预处理干净。
2026-11-03 21:28:36 +08:00
super_agent_bot b0a6394aa1 fix(test/udp): peer 换源端口上报方式并补 PC 回路自检(#73)
CI / 静态门禁 (pre-commit) (push) Failing after 5m4s
CI / 主机侧单测 (MSVC) (push) Successful in 44s
CI / 静态门禁 (pre-commit) (pull_request) Failing after 4m48s
CI / 主机侧单测 (MSVC) (pull_request) Failing after 44s
- test/host/udp_queue_bench.py:Windows 上未 connect 的 UDP socket 调 getsockname()
  直接抛 WinError 10022(请求一个未连接套接句的名称),脚本在第一条用例就崩。
  源端口改为首次收到回显时打印——它本来就是「板端剥头/源地址判定对不对」的直接读数。
- 新增 test/host/udp_queue_bench_loopback.py:不用板子的 peer 自检,在 127.0.0.1 上放
  一个按板端阶段 16 同样三条规矩说话的假板子(原样回显、tag 0x04 只回 64 B、>1KB 按
  1024 拆片),先把步骤表 / 模式函数 / 分片预期验掉。2026-11-03 首跑 27/27 绿,
  实测拆片形状 [1024, 1] 与 [1024, 448]。
- CH395F_Test_Guide.md §12.6:运行方法补「先跑自检」这一步;>1024 B 的 UDP 拆片从
  「多收到一片就 FAIL」改成「实测观测量」(拼接后逐字节一致才算绿),并说清这是既有
  NET_SEND_CHUNK_MAX 行为、不是本轮引入;脚本表补一行。
- 板子自 19:19 起未再上电(ping 不通、SWD No target、串口静默),阶段 16 真机那一趟
  仍未跑,PR #74 的合并前提不变。
2026-11-03 20:46:15 +08:00
super_agent_bot 8a81fa9e41 test(net/udp): 阶段 16 UDP 数据面真机回归台架(板端 + PC peer),台账补实测数字(#73)
CI / 静态门禁 (pre-commit) (push) Failing after 5m27s
CI / 主机侧单测 (MSVC) (push) Successful in 33s
CI / 静态门禁 (pre-commit) (pull_request) Failing after 7m6s
CI / 主机侧单测 (MSVC) (pull_request) Successful in 48s
- 板端 net_layer_udp_bench_test_main:TC-NET-1601~1609,逐步覆盖主机测替代不了的
  5 条台架必验——形态切换与 bind 后首包、48 B 应答在客户端形态的载荷完整(TRAP-NET-22
  的真机对照)、截断包排空、挂起等待期间的 IWDG 余量、DesIP 先于 OPEN_SOCKET 的顺序。
  每步都有 25 s 预算,PC 缺席时报 [FAIL] 而不是把 testTask 钉死。
- PC peer test/host/udp_queue_bench.py:板端先 bind 当服务端,对端地址从收到的包里学
  (PC 是 DHCP,TEST_PC_PEER_IP 那个固定地址不在本机上);对 >1024 B 的回显额外监听
  第二片,把 net_send_locked 分块在 UDP 上的后果量出来。
- ch395f_test.h:阶段 16 宏默认关(与其它阶段一致),RAM 台账补 2026-11-03 实测——
  台架镜像 RW_IRAM1 96,232 B / 73.4%,阶段 16 自身代价 1,600 B;产品镜像 RW+ZI 与改造前逐字节相同。
- 文档:CH395F_Test_Guide §12.6 跑法与判据 + Python 脚本表加一行;覆盖率口径第 4 轮
  「台架必验」指向本阶段的可执行形态,并写明尚未在真机上跑过。
2026-11-03 20:18:24 +08:00
super_agent_bot fff961d803 feat(net/udp): UDP 数据面并入 netMsgQueue 串行执行(#73)
CI / 静态门禁 (pre-commit) (push) Failing after 49s
CI / 主机侧单测 (MSVC) (push) Failing after 30s
CI / 静态门禁 (pre-commit) (pull_request) Failing after 45s
CI / 主机侧单测 (MSVC) (pull_request) Failing after 44s
前置来自 #57 SNTP 调研:旧 net_sendto / net_recvfrom 由调用方直调
SPI 且无限自旋收包,既违约「netTask 是芯片唯一访问者」,又把 IWDG
预算吃在自旋里。

改造面
- 新增 Drivers/BSP/NET/net_udp.c/.h(真机专属,模拟器不编译):
  bind/set_peer/sendto/recvfrom 四条执行体 + 挂起收包表 + tick;
  net_msg_type_t 加四型,公开 API 一律「入队 → 睡在通知上」。
- 源地址出参不搭 net_msg_t(按值拷贝,AGENTS 禁加回传字段):改住
  net_udp.c 的 per-fd 槽,netTask 就地写回调用方内存,通知值只带
  结果码;每条出口都清槽,泄漏 = 该 fd 永久 BUSY。
- 发送复用 net_send_locked,不写第二份分块逻辑;「会话是否已死」
  收成一条判据 net_send_state_down()(TCP 看 ESTABLISHED、UDP 看
  UDP_OPEN),原先 4 处各写一遍。
- 顺带修掉真缺陷(新条 TRAP-NET-22):旧 sendto 把 DesIP 写成具体
  IP,芯片静默切 UDP Client,而旧 recvfrom 无条件剥 8 字节 → SNTP
  这类 48 B 应答丢载荷前 8 字节并交出垃圾源地址。加 udp_mode(塞进
  原有 padding,sizeof 不变)、bind 恒 SERVER、显式对端 sendto 切
  CLIENT、set_peer(fd, NULL) 轻量回 SERVER,仅 SERVER 且 avail >= 8
  才剥头。
- 截断定案:一次调用交付一个数据报,buf 装不下的尾巴用 64 B 栈上
  scratch 排空(不用 clear_recv_buf——它连后面已到达的包一起丢)。
- 取消点接齐:net_init 重建 cancel_all、net_socket 分配 fd clear、
  net_close settle_close + clear、重 bind 前先结算等包者,
  net_process_messages 第 5 个 tick 位挂 net_udp_tick。
- 收紧两处契约(原实现无生产调用者):UDP 未 bind 一律 -5;
  net_recv / _nb / _to 拒 DGRAM(绕过剥头就是静默吃 8 字节);
  NET_ERR_NOT_IN_NETTASK(-12) 退役为历史常量并写明原因。

验证
- 主机单测 test/host/net_socket 全套 616/616 绿(改造前 470):新
  分片 ns_s7_udp.c 20 组,改写 440 / 555 / 560 组;覆盖率
  net_udp.c 234/236(99.2%)、net_socket.c 956/969(98.7%),
  scripts/test_coverage_baseline.json 随本提交登记新文件。
- 测试抓到 4 个被测码真 bug:自等守卫误用调用侧谓词、芯片长度被读
  两次、槽指针取在 fd 合法性检查之前、重 bind 静默作废等待者。
- Keil ARMCC 0 Error(s) 0 Warning(s);net_udp.o Code 1,358 / ZI 224
  (8 fd × 28 B,其余模块零增长),全仓 RW_IRAM1 72.2%;内存台账
  受管区按门禁提示用 --write / --update 机器回填,未手改数字。
- pre-commit 全量钩子(含 doc-links、coding-standard、mem-budget、
  generated-fresh、bsp-err、registration、nested-comment)全绿。

限度
- 本轮无板子:真机回归 5 条(两端互通、set_peer(NULL) 能否恢复收
  广播、截断排空后下一包完整性、挂起 recv 期间 IWDG 余量、bind 写
  DesIP 与 open 先后的真芯片效果)已写进覆盖率口径「台架必验」。
- scripts/stack_report.py 退出码 1 是 10-26 起挂在账上的 iec104Task
  栈债(margin 1,016 < 1,024,见 docs/代码规范/pre-commit使用说明.md:
  122);本轮只让 net_bind 的 UDP 分支多一层静态帧(1,544 → 1,600),
  netTask margin 1,888 与 timeSyncTask 1,152 不受影响。抬栈要过
  mem-budget 台账,不在本分支自行处理。
- 登记簿销项按仓库约定留给主工作树,本分支不动 docs/任务规划/**。
2026-11-03 18:44:01 +08:00
wandering1 2b5eb1c0db Merge pull request 'docs(serial-tool): 清理过时的「待 CH340」说法,A1–A8 编号改语义短语,销登记簿跟踪行' (#71) from issue-52-serial-tool-doc-cleanup into master
Reviewed-on: http://100.123.83.113:3001/wandering1/STM32F4-Base/pulls/71
2026-11-03 06:53:03 +08:00
super_agent_bot b45f50569b docs(serial-tool): 清理过时的「待 CH340」说法,A1–A8 编号改语义短语,销登记簿跟踪行
依据 Issue #52:CH340 一直都在、/serial-boot-test 已跑通(boot_log_data 有 2026-10 大批日志),
「等 CH340 接入」是 2026-09 建档时的过时状态;字母+数字编号按 docs/编号规范.md §0 已废。

- 串口助手设计说明.md:§5 状态改 CH340 已接入(COM3)+ 正路径已具备验收条件;
  §9.2 验收表 A1–A8 全部换语义短语;§10 步骤 4/5 同步。
- 登记簿.md §7:销掉「串口助手正路径补验」跟踪行(CH340 一直在、流程已跑通,无需再等)。
2026-11-02 23:58:18 +08:00
wandering1 1078b554f5 Merge pull request 'feat(ui/nav): 7003 STATUS 身份回读 + 台架 GOTO 直开 + 排帧流落地(#69 五项实施)' (#70) from agent-nav-research-34ef765e6757 into master
CI / 静态门禁 (pre-commit) (push) Failing after 5m5s
CI / 主机侧单测 (MSVC) (push) Successful in 42s
Reviewed-on: #70
2026-11-02 23:06:42 +08:00
super_agent_bot be16669564 docs(ui/nav): 台架复核落地——收列键语义、回根按 depth、限度取证结论(#69)
CI / 静态门禁 (pre-commit) (push) Failing after 4m56s
CI / 主机侧单测 (MSVC) (push) Successful in 47s
CI / 静态门禁 (pre-commit) (pull_request) Failing after 4m4s
CI / 主机侧单测 (MSVC) (pull_request) Failing after 42s
台架实机会话 2026-11-02(bench 档 fw 22:25:12 / 产品档
22:29:56,均经 /serial-boot-test 闭环:身份戳匹配 + 回读
no-difference):

- 复核② 收列键语义:菜单态按 s 与按 l 同走 menu_back、均收
  一级且父列选中留在原地(depth 1→0、sel 不变)——旧断言
  「菜单态按 s 不收列」是把待机态 s 无效(task-24 实证)误
  读成菜单行为。to_root() 据此在 STATUS depth>0 时按 s 逐级
  收(弹框被屏裁时像素 n_cols 漏计、固件 depth 不漏),老固
  件像素路径保留 l 兜底仪式。§7.2 纪律与 board-ui-nav skill
  恢复配方同步改写。
- 复核① 被裁弹框两叶:菜单步进依旧吃不到(枚举落同胞页,
  落点由 STATUS 如实报出、不再谎称到达);GOTO 直开两叶到
  达且完整渲染(自检记录 ink 4073 / 运行记录 ink 3559)→
  KNOWN_UNREACHABLE 对 --to 保留,绕行路径 --goto。§7.4 改写。
- 产品档(未加宏)实测:STATUS 照常应答(不设闸)、GOTO 回
  status=4——生产/bench 行为差异真机钉死;§7.6 增实机验证记
  录段。回归:--selftest-quick 66/66+闸 7/7;--selftest 闭环
  失败集与 master 基线逐项一致(6 存量像素 + 2 执行类拒绝)。
2026-11-02 22:39:48 +08:00
super_agent_bot bbfb47ebd0 docs(ui): 新增 board-ui-nav 唯一入口技能并在 AGENTS 布防(#69)
CI / 静态门禁 (pre-commit) (pull_request) Failing after 6m26s
CI / 主机侧单测 (MSVC) (pull_request) Failing after 43s
板端交互看图/注键/开页一律走 scripts/board_ui_nav.py,禁止另写
一次性注键脚本:#38 调试中因临时脚本盲注 d*9 走错页复犯(#69),
盲走事故当时已立"不猜步数"铁律但入口没布防。技能写明 --where/
--to/--goto/--selftest-quick 用法、STATUS/GOTO 语义与拒绝码、
恢复配方、台架锁边界与 GOTO 权限边界。

UI_自动化测试流程.md:§7.1 记 #69 复犯案例与像素路径存量误判基线
(记录查询 6 叶在 selftest 闭环里恒红是存量,勿当 #69 回归);
§7.3 补 --where/--goto;§7.4 记 #69 收口(剪贴弹窗依赖已由
STATUS depth 顶掉,KNOWN_UNREACHABLE 销项待台架复核);
新增 §7.6 STATUS/GOTO 契约、判稳改造与门控说明。
2026-11-02 22:22:15 +08:00
super_agent_bot aaf75f7992 feat(scripts): board_ui_nav 接入 STATUS/GOTO 并落实排帧流规则①(#69)
- 每键后先读 KEY 回执,再等帧流静默 ≥900ms、双帧一致才判稳取帧:
  docstring 规则①此前代码只 sleep 300ms 单帧,本次补实(#38 调试
  复盘的主错源之一);判稳超上限记 unstable,禁止再基于此盲补键
- STATUS 客户端(字节契约以 ui_net_sink.h 为唯一真源,解析做防御):
  --where 固件身份 + 像素双口径报"现在在哪";--to 到位判定固件身份
  为主、像素为佐,不一致只记账不盲补(不一致=判据或固件有问题,
  先 dump 现场);UNKNOWN 恢复先问 STATUS 定分支——菜单态关列用 l
  不用 s(菜单不响应 s 的历史判据存疑,待台架复核后收口);
  STATUS depth=0 直接判回根,剪贴弹窗不再挡 to_root
- --goto 直达页(仅台架/模拟器固件,产品恒拒),主机侧同步拒绝
  执行类页 id;旧固件(无 STATUS 应答)自动退回纯像素路径,
  向后兼容
- WALK_DIR 与 --walk 默认目录并一(原 ci-artifacts/uiwalk 使
  BOARD_TRUTH 复核看不到新 walk 帧,10-31 记过)

无板端到端:窗口态 lvgl_sim(UI_REMO_ALLOW_GOTO)11 步全绿,含
待机→e 唤醒重开最近页的实锤复现。--selftest-quick 66/66、门 7/7。
2026-11-02 22:22:10 +08:00
super_agent_bot 493fa6ba0e feat(ui/remo): 7003 总线新增 STATUS 身份查询与 GOTO 直达页(#69)
STATUS(命令 4)一帧回答"现在在哪个画面":kind(MENU/PAGE/STANDBY)
+ 菜单路径/选中 + 页 id,布局契约与字节序见 ui_net_sink.h。由 uiTask
轮询驱动,同上下文读静态导航状态:零画面副作用、免锁、不发日志。
新增只读接口 ui_menu_get_nav_state / ui_content_page_current_desc。

GOTO(命令 5)按页 id 查生成表直开内容页,以 VIEW 权限进入(与
"已过查看密码"同档,不代输任何密码)。编译期门控
DTU_BENCH || UI_REMO_ALLOW_GOTO:产品构建恒拒(status=4),模拟器
构建默认开启便于无板验证;执行类页(clear/reset)固件侧同样拒绝
(status=2,与主机 EXEC_PAGE_IDS 同一事实源);待机中拒绝(status=5),
由主机按键唤醒后再来。成功应答带回目标叶节点下标便于对账。

ui_sink 主机单测补导航侧链接假件 + 最小 lvgl 桩(仅本测试目录)。
产品构建 Keil 0 Error 0 Warning;ui_sink 单测 17/17。
2026-11-02 22:19:58 +08:00
wandering1 b8e1de5f2e Merge pull request 'fix(ui/wave): 回放页段表枚举恒空根因修复(seg_path 返回值判错 + 键处理缺重绘)' (#67) from fix-replay-enum-0e52b1963afa into master
CI / 静态门禁 (pre-commit) (push) Failing after 4m17s
CI / 主机侧单测 (MSVC) (push) Failing after 40s
Reviewed-on: http://100.123.83.113:3001/wandering1/STM32F4-Base/pulls/67
2026-11-02 19:52:16 +08:00
super_agent_bot 364b163663 docs(wave): 回放页枚举恒空修复闭环入档并销项
CI / 静态门禁 (pre-commit) (push) Failing after 44s
CI / 主机侧单测 (MSVC) (push) Failing after 45s
CI / 静态门禁 (pre-commit) (pull_request) Failing after 40s
CI / 主机侧单测 (MSVC) (pull_request) Failing after 42s
- 故障录波设计说明 §10 新增「回放页枚举恒空缺陷修复记录」:四步证据链
  (失败不钉表+FR 埋点 → 诊断加强 → 根因 = 读侧用反 seg_path 返回契约 →
  同页键处理缺失效)、串口实录 `scan done cnt=7` / `head path fail idx=6`、
  修复前后板级对拍图与复现口令;10-31 那段「拿不到目录条目」的定性就地
  标注被推翻(保留为推理起点留痕);§10 表「板级·回放页」行与文首状态行
  同步为「测试面已开、坏段/空态画面仍待到场地拍」。
- 到场轮执行手册 §3 第一幕标注「已完成(2026-11-02)」,表 §1 与幕间
  依赖同步;历史三步保留但注明到场时不用再跑。
- 登记簿 §2 按「完成即销项」删除该行;任务规划 README 独立行同步。
- 证据入库 `docs/测试说明/测试数据/wave_enum_20261102/`:修复前/后回放页、
  切段、切道四帧 + README(含串口实录与复现口令)。Before = `7efa58d9`
  构建(身份戳 Nov 2 2026 14:21:24),After = 本分支构建(Code=247,288 B)。

Refs #38
2026-11-02 18:33:18 +08:00
super_agent_bot 046097918d fix(ui/wave): 回放页切通道/切段后不重绘——key_cb 接管键后补失效
回放页 v1.0 建的键处理返回 true(接管全部键),但从未调
ui_content_page_invalidate():框架只在 key_cb 返回 false 时才替页面
失效,于是「键送达、状态已切、屏上纹丝不动」。该病被枚举缺陷完全
遮住(整页恒空、没有可切的画面),随本波枚举修复首次上板才暴露:
真机按 ←/→/↑/↓ 帧字节完全不变(同帧哈希),布局与状态机无问题。

- 上/下切通道、左/右切段成功路径、空态再探路径,各补一次
  ui_content_page_invalidate()(与 ui_page_clock / ui_page_password
  等已接管键的页面同纪律);
- 切段失败仍保持「按了没动」的诚实语义(不重绘、不把忙态清成空);
- 修改记录 v1.1。

/keil-build 0 错误 0 警告(Code 247,288 B,+4 B),RAM 不变;
台账 / 同码凭证同批刷新。

Refs #38
2026-11-02 18:21:34 +08:00
super_agent_bot d6253aa974 fix(ui/wave): 钉死并修复回放页恒空根因——读侧用反 seg_path 返回契约
FR 埋点构建上板判读(本 boot 串口实录,临时诊断构建 = 上一提交):

    [UI_TASK] ui wave scan #1 done cnt=7 np=0 tt=0 ac=407
    [ERR][UI_TASK] ui wave head #1 path fail idx=6

- 目录枚举一直是好的(cnt=7 = 盘上七段全数入表,锁也拿到,tt=0):
  10-31「唯独 ui_task_wave_scan 拿不到目录条目」的定性被推翻。
- 真正坏的在 load_head / seg_win 的拼路径判错:契约
  (App/algo/wave_store.h:458)是「成功 = 写入字符数(本形态恒 16),
  失败才是负码」,读侧自建成功能起写成 != 0 判失败——每次成功都被
  判死,f_open 永远走不到,盘上有段也恒显「无录波段」。写侧
  default_task.c 同函数用 <= 0,一直是对的,所以「FTP 六段全见、
  写侧枚举正常、唯独回放恒空」的怪象全线得解。
- 模拟器走桩、不编译本文件读侧,黄金参考图与主机单测因此从未覆盖
  这条链,此病从建成存活至今(板端首张真机波形图见 PR #67)。
- 两处口径改 <= 0(与写侧一致);表列着的段 f_open 失败补带 FR 码
  的永久留痕——该失败态页面无视觉面,10-31 误定性的教训就是静默。
- 临时诊断(#N 序号 / try 闸日志 / 无条件 done 行)收敛删除,留
  最小永久集:scan opendir/readdir FR、零条目 INFO、head/win 开档
  失败 FR。try 闸恢复静默(看门狗设计说明 §4.3 口径)。
- /keil-build 0 错误 0 警告:Code 247,284 B(较临时诊断构建
  −368 B,较修复前 +236 B),RAM 不变;台账 / 同码凭证 / 数字回填
  同批刷新。

Refs #38
2026-11-02 18:07:52 +08:00
super_agent_bot 3e01e9d98e diag(ui/wave): 枚举扫描诊断留痕第二组(临时构建,随根因修复收敛)
第一组埋点烧后开回放页串口零留痕(既无 FR 失败也无零条目
行),剩余唯一静默分支 = try 闸取锁失败直接返回/扫描成功但有条目
不打印/段头与窗口读取失败不打印。本组补齐:

- scan:每次尝试编号 #N;try 闸失败行带 vol_lock_get_stats 计数(消费方
  观测,不取锁,符合看门狗设计说明 §4.3 口径);完成行改为无条件打印
  cnt/np/tt/ac(排除「成功但页面仍空」歧义)
- load_head / seg_win:try 闸、路径构造、开档 FR 码与读失败出口全部留痕

临时诊断构建,判性后随根因修复收敛到最小永久集。
/keil-build 0 错误 0 警告(Code +604 B,RAM 不变)。

Refs #38
2026-11-02 17:39:58 +08:00
super_agent_bot ee002d7ead fix(ui/wave): 回放页枚举扫描失败不再钉「无段」缓存并补 FR 码留痕
真机回放页恒显「无录波段」而 FTP 六段全在盘上(登记簿同名条目,
见 #38 §5)。本提交按执行手册 §3 步骤 1 落两件事:

- ui_task_wave_scan:f_opendir/f_readdir 失败本轮返 -1(「本轮无完整
  事实」语义),不再无条件钉 s_wave_scanned——原实现把卷忙/FR_DENIED
  一类失败钉成「0 段」假空态,直到下一次 manual_req 才重试;失败不
  钉表后下一次进页/按键自然重试,与 soe_store 读者同纪律。
- FR_NO_PATH(从未录过波)仍归「0 段」并钉表,设计原口径不动。
- 失败分支补带 FR 码的留痕(opendir/readdir 各一条 DBG_ERROR),
  「FR_OK 但零条目」加一条 DBG_INFO(留痕行正文以
  「ui wave scan」前缀区分,tag 用本文件既有的 [UI_TASK])
  ——根因判读表见执行手册 §3,
  板级远程开一次回放页即可定性,不必猜。
- DBG_TAG 定义 + dbg_log.h 包含上收到包含区(原在 s_wave_ops 之后的
  文件中部;同标签同宏,不构成行为改动,本文件既有留痕照常)。
- 体积/RAM 同码凭证随 /keil-build(0 错误 0 警告)同批刷新:
  Code +8 B,RAM 不变;台账受管区水位按门禁要求随本次 .map 同步
  (台账此前落后 master 既有 flash 漂移 +320 B,--write 一并拉齐)。

Refs #38
2026-11-02 17:07:21 +08:00
wandering1 7efa58d9a1 network: 台架 IP 迁到 192.168.31.100,并把重复写死的值收进单一真源
CI / 静态门禁 (pre-commit) (push) Failing after 25s
CI / 主机侧单测 (MSVC) (push) Successful in 48s
分两段(用户裁定 2026-11-02):先做地址迁移,再把同类字面量收敛成
单一真源,以后再改地址只动一处。

一、IP 迁移 192.168.1.100 → 192.168.31.100(gw 同步 → .31.1)
- 工厂默认:Drivers/BSP/NETCFG/net_cfg.c 的 NET_CFG_DEF_IP/_GW
- 注释/文档示例、主机与板级测试、台架 py 脚本、两份 sim_config.ini
- 字节序教学点同步换算 hex:0x6401A8C0 → 0x641FA8C0(内存
  C0 A8 1F 64),旧版示例引文与历史 Trap 记录按冻结纪律不动
- UI 黄金基准:网口设置 4 态 + shot_info 共 5 张 .bin 由
  check_content_pages.py --update 重刷(渲染值 IP 变了,属预期变更)
- 保留判定:客户点表引用(IEC104/继电保护规划)、芯片手册摘录、
  日期冻结的变更记录行、已退役台架档案 MDK-ARM/retracted_bench_*

二、单一真源收口(A+B+C+D,用户批准全做)
- 新建 test/host/bench_defaults.py:台架 py 默认值唯一定义点
  (DEVICE_IP/DEVICE_GW/PC_IP/NET_BCAST),22 个脚本改为引用;
  MDK-ARM 两探针与 scripts/board_ui_nav.py 经 sys.path shim 引入
- test/board/net_test_task.h 新增 TEST_PC_PEER_IP,板测三处
  PHASE*_REMOTE_IP 改引该宏(保留 -D 覆盖);Phase1 断言改
  memcmp 数组比较,数组各只出现一次
- simulator/tests/check_content_pages.py 从 net_cfg.c 正则解析
  NET_CFG_DEF_* 推导期望值(解析失败即报错、不静默兜底),
  脚本内台架 IP 字面量清零
- 装饰性注释去具体值(net_cfg.h/net_socket.h/net_socket.c/
  net_socket_sim.c);字节序教学 hex 对刻意保留为唯一写值点
- 刻意不动:主机单测夹具 IP(逐文件钉住的任意值是正确测试
  实践)、文档正文 IP(那是文档内容本身)

顺带:scripts/gen_task_table.py 规范串清掉「,B5」——编号清退提交
72b4b094 改了受管区没重跑生成器,task-table 门禁因此一直红

验证:产品 @build 0/0;CH395F 套件开关构建 0/0 后还原产品态;
6 套主机单测 rc=0;content_pages(含宏推导路径)/菜单 8 态/
推流位比对全 PASS;bom-drift 99 无漂移;doc-links/coding-standard/
cppcheck 绿;py_compile 23 文件 + --help 冒烟(含 shim 绝对路径)
2026-11-02 14:46:42 +08:00
super_agent_bot 9a71265f41 docs: move kanban instructions into the agent deployment config 2026-11-02 14:04:24 +08:00
super_agent_bot 0b1e10f254 docs: add kanban sync instructions for the agent 2026-11-02 13:30:40 +08:00
super_agent_bot 770b76d4e4 remove probe
CI / 静态门禁 (pre-commit) (push) Failing after 44s
CI / 主机侧单测 (MSVC) (push) Failing after 43s
2026-11-02 13:12:50 +08:00
super_agent_bot 6fab68fa63 probe
CI / 静态门禁 (pre-commit) (push) Failing after 44s
CI / 主机侧单测 (MSVC) (push) Failing after 44s
2026-11-02 13:11:15 +08:00
wandering1 e63abb919a Merge pull request 'v2-on-ui' (#4) from v2-on-ui into master
CI / 静态门禁 (pre-commit) (push) Failing after 43s
CI / 主机侧单测 (MSVC) (push) Failing after 43s
Reviewed-on: #4
2026-11-02 04:07:09 +08:00
wandering1 32f7e2e5d9 Merge branch 'master' into v2-on-ui
CI / 静态门禁 (pre-commit) (pull_request) Failing after 45s
CI / 主机侧单测 (MSVC) (pull_request) Failing after 43s
2026-11-02 04:06:35 +08:00
wandering1 48326c90ed Merge pull request 'docs: clear task and layer shorthand IDs' (#3) from create-project-wiki-06e6e4ae750a into v2-on-ui
CI / 静态门禁 (pre-commit) (pull_request) Failing after 43s
CI / 主机侧单测 (MSVC) (pull_request) Failing after 43s
Reviewed-on: #3
2026-11-02 04:00:43 +08:00
super_agent_bot 4000bb73cf docs: clarify frozen evidence exception 2026-11-02 03:50:27 +08:00
super_agent_bot 72b4b0943c docs: clear task and layer shorthand IDs
Replace task/batch shorthand IDs and residual layer labels in
human-facing docs with semantic phrases. Add the new cleanup
policy to docs/编号规范.md and update the entry docs.

Machine keys (TC/CODE-RULE/MENU-STATE/TRAP/FR), hardware
designators/pins/MAC, protocol/version numbers and frozen
historical evidence are intentionally kept.

Docs only; no code behavior change. Verified with
check_doc_links.py --all and git diff --check.
2026-11-02 03:33:51 +08:00
wandering1 f81bb38b64 docs(测试说明): 录波远程半轮收尾回写并新增到场执行手册
CI / 静态门禁 (pre-commit) (push) Failing after 5m21s
CI / 主机侧单测 (MSVC) (push) Successful in 29s
- 故障录波设计说明 §10 新增「板级远程半轮记录」:真 FAT 落盘、触发
  时序三样本、冷却恢复、轮转同号覆盖、PC 侧坏段拒收、104 并发
  (参考主站 16/18 绿,两条 COV = 标定闭锁腿物理预期)六项 PASS;
  drop 400–640 点/窗入账为纯观察项(丢样本不丢采集实测面)。
- 新缺陷「回放页段表枚举恒空(板级)」登记登记簿 §2:五面判别钉死
  唯 ui_task_wave_scan() 在 uiTask 拿不到目录条目;伴生纪律缺陷
  f_opendir 失败仍钉 s_wave_scanned=1(修复方向同记录)。
- 新增 docs/测试说明/专项验证/故障录波板级到场轮执行手册.md:剩余
  人到场判据拆成四幕,逐步写清谁出手/做什么/会看到什么,含到场
  检查清单、现场记录表、两个用户决定点、收工还原清单与分诊;
  索引挂行 docs/README.md 与 测试说明/README.md(专项 5→6 篇)。
- scripts/board_ui_nav.py 文件头补三条 7003 驱动纪律(ACK 与推流
  同 TCP 须 drain 静默、home 首 e 是重开最近页捷径、级联光标记忆)。
- 自我更正入档:起草台架计划时带入的「≤15 s 判据」全仓无属主,
  已溯源改指 WAVE_SEAL_TIMEOUT_MS 2 s 封存窗(真锚);「§1.2 两个
  待台架核数值」为错引,改指 §4.2 兜底行与 wave_ring.h 冷却时长。

bench 锁已 release、设备未改烧;证据包在 ci-artifacts/wavebench/。

gate: doc-links --all --sections-strict rc=0(218 篇 3103 处 无法判定
0);mermaid 预检新发 0;py_compile 过;七文件 BOM/CR/U+FFFD 全零。
2026-11-01 14:10:53 +08:00
wandering1 c373e2e97d chore(台账): waveclose 合并后回填体积同码凭证
主干合并 docs(任务规划) 录波卡片登记簿销项(51ce5900)后
git-index 指纹变为 80504df8;全量重建 /keil-build -r 0 错
0 警,测量与本码:Code=246,720 B / RW_IRAM1=94,336 B (72.0%)
RW_CCM=57,376 B (87.9%),均 ≤92%。本笔仅重写凭证,无代码改动。
2026-10-30 18:28:46 +08:00
wandering1 51ce59006b merge: task/waveclose-plan-close 合入 v2-on-ui
任务 waveclose(1 个提交)经 task-worktree 回收:
- docs(任务规划): 故障录波卡片登记簿销项——判据并入设计说明后删除
2026-10-30 18:21:36 +08:00
wandering1 4ceb5b41e6 docs(任务规划): 故障录波卡片登记簿销项——判据并入设计说明后删除
用户指令(2026-10-30):确认录波任务完成度,把除实际操作之外的所有
步骤做完,然后删除规划文件,避免已完成的工作被误读为未做。

审计结论:代码面确已全部收口——wave_read.py --selftest 92/92、
三套主机单测 113/170/110 复跑全 rc=0、bench 自抓与 PC 读段脚本在仓、
数据可信/复刻明细/短板评测/UI 两处回写均已做过。**唯一未跑的是
板级台架那一轮(实际操作)**,判据不得丢,故先迁后删:

- 设计说明 §9 承接落盘道失败留痕名全清单(13+1 条,打印点现值
  default_task.c:816/:831 实测核对)
- 设计说明 §10 承接原卡 2/卡 3 的板级段(触发来路一行、回放页
  一行)与本波执行顺序图(mermaid,原规划 §3 逐字迁)
- §4/§11 头部定位、§11 尾注、§14 关系行改属主口径
- 全库 32 处引用改挂设计说明 §10/§9(18 文件):任务规划 README
  独立行(顺带订正单测数 100→113 为实测)、登记簿、数据可信 ×2、
  复刻明细、产品需求 ×2、ADC 注入 ×3、短板评测 ×2、页面补齐规划、
  App/algo README、配图生成器注释、录波三套单测注释 ×6
- git rm docs 该规划文件;人类索引任务规划 6→5 个文件(沿革注照
  屏板链路先例走裸句,不留反引号死引用)

验证:残留两形态(任务规划/故障录波、裸文件名)全树扫描 0;
mermaid 预检新发 0;doc-links 11 个被改文件逐文件 PASS;生成器
注释改动重跑产物逐字节不变(svg 60a0dd39e4);三套单测与
wave_read selftest 复跑全绿;18 文件 BOM/CR/U+FFFD 全零。

本笔不含固件编译单元(test/host 仅注释行与文档),构建留待合并
轮统一跑;板级轮启动判据与顺序见设计说明 §10。
2026-10-30 18:20:37 +08:00
wandering1 0d62a4a777 merge: task/chipdoc-chip-manual-img-and-svg-preview 合入 v2-on-ui
任务 chipdoc(1 个提交)经 task-worktree 回收:
- docs(芯片手册/配图流程): 剥 16 处从未入库的死图引用,SVG→PNG 改成 headless 实测
2026-10-30 17:26:25 +08:00
wandering1 e18e52ef7e docs(芯片手册/配图流程): 剥 16 处从未入库的死图引用,SVG→PNG 改成 headless 实测
两条存量收口(genlist 交付报告点名的那两条,用户裁定「收这两条」)。

一、docs/芯片手册/TPAFE5160.md:16 处 `![](images/<sha256>.jpg)` 的图
从未随文档入库——13 篇手册共 701 处引用,只有这篇缺;这些引用是
ad154b2f 把转录稿连正文一起入库时就带着的,16 个 hash 在全库 git
历史里一处都没有,与 a6cdebde 那次删 1069 张孤儿图片无关(那批里
一张都不包含)。本仓未入库厂商 PDF,无从重新提取,故剥成统一标记
并在文件头留痕:图题(`Figure N.` / 小节名)与紧邻 `<details>` 的
文字描述都保留,要看图按图题查手册对应页;补图须先装 git-lfs
(`*.jpg` 走 LFS 跟踪)。`doc-links` 对 `docs/芯片手册/` 整体豁免,
这类死链门禁永不报,自查方法是数标记行(应为 16)。

二、docs/架构设计/图形绘制流程.md:§3.1 第 4 步与 §四 原先写的
「浏览器打开 SVG」与「给 `.venv` 装 cairosvg 转 PNG」在本机走不通
(cairosvg 不在 `.venv` 也不在 `requirements.txt`,`rsvg-convert` /
`inkscape` / `magick` 都不存在),改成 headless Edge/Chrome 全路径
调用,并把两条实测坑写死:`--screenshot` 必须给绝对 Windows 路径、
`--window-size` 要跟画布一致。PNG 不入库的口径按 `.gitignore` 里
实际那三条目录规则列出,不再笼统写成「已含 `*.png`」。

`draw-diagram` skill 侧同步:撤掉「口径未与权威文档同步」那条挂账
说明,陷阱条目改指已对齐的命令,并写明改渲染命令时文档与 skill 两处
一起改(命令只在 §四 详述,skill 留判据指针)。

自查:`check_doc_links --sections-strict` 三篇 rc=0;skill-size
18841/65536 安全;`check_generated_fresh` PASS(26 生成器 / 22 一致
/ 4 存量基线);`check_mermaid --all`、`check_bom_drift --all` 均
rc=0;三篇字节卫生干净(LF / 无 BOM / 无 U+FFFD / 无行尾空格 /
末行单 LF)。本笔纯文档与 skill,未碰代码与生成器。
2026-10-30 17:26:05 +08:00
wandering1 48becbfa48 merge: task/genlist-generator-registry-merge 合入 v2-on-ui
任务 genlist(1 个提交)经 task-worktree 回收:
- docs(配图): 生成器与产物清单并成一张唯一真值表,挂载列改由实测反推
2026-10-30 16:55:36 +08:00
wandering1 f48208f1c5 docs(配图): 生成器与产物清单并成一张唯一真值表,挂载列改由实测反推
两张清单各自登记同一批生成器,2026-10-30 实测各漏各的:
`tools/arch_diagram/README.md`「脚本一览」21 行缺 5 个(adc_health 三张、
net_instability、net_pending),`docs/架构设计/图形绘制流程.md` 的三列表 18 行
缺 9 个(多出的还在 `docs/架构设计/图形绘制流程.md` §2.1 另立一张表登记例外面)。
同一条事实两处登记必然漂,现并成一张:

- 唯一真值表 = `tools/arch_diagram/README.md`「产物清单」:按图逐行,32 张入库
  `docs/images/*.svg` 全量(26 个本目录生成器 + refgraph 2 张 + 无生成器的手工
  级联框 2 张),列 = 图 / 生成器 / 这张图答什么 / 顶部数据区(改这里 → 重跑)/
  挂在(`文档:行号`)。
- `docs/架构设计/图形绘制流程.md` §二 的逐脚本表换成指针(只留选型判据与流程),
  §2.1 保留「钩子扫不到的图」的维护口径、去掉与主表重复的表。
- 级联框两张的绘制日期按 `git log --follow` 改对:原写「2026-10-26 手画」与 git 史
  不符,实测 2026-09-08 `891c9ef0` 入库、2026-09-11 `2429955d` 随配图规范收拢进
  `docs/images/`,此后未再改动。
- `docs/门禁说明/generated-fresh.md` §8 旧口径「加生成器 = `GENS` 加一项」对
  `docs-svg` 不实:该条目声明 `dir` + `pattern = gen_*.py`,实跑 `glob.glob` 现扫
  (`scripts/check_generated_fresh.py`:146-150 与 :452)→ 新增生成器自动进扫描面,
  要同批改的是产物清单不是门禁。已拆成「加新类别」与「`docs-svg` 不必登记」两条。
- 「挂在」列由扫描 `![]()` 反推,并跳过 ``` 围栏与行内反引号里的示例写法——
  `docs/文档规范.md`:83、`draw-diagram` SKILL.md:155、本文档 §3.1 第 5 步
  那三处是教学示例、不是真挂载,先前手写表时误计进去过。
- 三张零内嵌图(`内存布局_RAM.svg`、`引用关系图.svg`、`引用关系图_模块.svg`)
  在表里明写「零内嵌」并给出被文字提到的位置。

`draw-diagram` skill 的落库义务同批改指:§二第 6 步与验证清单都指向「产物清单」,
并写明「全仓只此一张逐脚本清单」,避免下一个人再另起第二张。

自查:`check_doc_links.py --sections-strict` 三篇 rc=0;`check_generated_fresh.py`
PASS(26 生成器 / 22 一致 / 4 存量基线);`check_skill_size.py` 17 个 SKILL.md ok;
`check_mermaid.py --all` 31 文件 62 围栏新发 0;`check_bom_drift.py --all` 99 文件
无漂移;产物清单核对器(一次性,不入库)重写挂载列后复跑归零、再跑幂等。
纯文档与 skill 文案,未改任何生成器与代码,未 commit。
2026-10-30 16:54:53 +08:00