dfd1528409
按 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 见工单汇报。