交接卡.md 87 KB

交接卡 · operate/control 双进程拆分(追加式历史)

续接载体之一。每完成一步或暂停,在末尾追加一段:## 日期 时间 · 一句话标题,下列「改动/核实/踩坑/下一步」。只追加,绝不覆盖。 新任务(2026-06-22 启动)。旧任务(M0-M8 合并改造)交接卡随旧文档清空,本卡为新任务重起。


2026-06-22 · 旧任务结项 + 新任务(双进程拆分)启动,文档体系重建

  • 背景:旧任务"三项目合并改造"(M0–M8)已全部结项。用户主动清空 项目文档/ 下旧文档(00总纲/需求文档01-14/开发计划归档/历史报告),为新任务腾空。
  • 新任务:operate / control 双进程拆分 —— 把 control 从 operate 进程内剥离成独立常驻进程,operate 可随时开关而 control 续命驱动机器;装机仍一个软件、只启 operate。
  • 本会话已完成:
    1. 需求梳理:7 路并行捋遍 control 全部逻辑(采集主循环/服务器双向交互/启动硬件层/缓冲瓶排队换气/数据库数据流)+ 穷尽全部配置参数(App.config + 三级数据库 tl_setting/house/house_well_setting)。产出 需求文档/control-逻辑与配置全景.md
      • 纠正若干认知:温度=下位机自控只读;气体/压力=control 主动控制(周期换气 AirSwapFun、低压补气 AerationNew);拍照/对焦=StartDish 后 control 自主按 photoIntervalPerRound 循环驱动(非每张等指令)。
    2. 架构设计(brainstorming 逐项确认):双进程 + 本地 HTTP(127.0.0.1)通信 + operate 按需拉起 + control Mutex 单实例 + 开机自启 operate + 调试跨进程借串口(复用 HouseGate)+ 受护栏停止(二次确认+工程师口令)。产出 需求文档/specs/2026-06-22-operate-control-双进程拆分-design.md(9章)。
    3. 阶段1实现计划(writing-plans):7 个 bite-sized 任务,纯逻辑 TDD 单测、进程/HTTP/采集编译+真机验证。产出 开发计划/2026-06-22-阶段1-control独立进程骨架.md
    4. 老壳鉴定:ivf_tl_ControlTest(csproj=ivf_tl_ControlMain)= 合并前 control 独立 exe,但 Window1 启动骨架已被 operate 复刻吸收、MainWindow 是纯测试、StopWindow 是死窗,命名混乱(三命名空间)。结论:不改造,阶段3 退役删,新 control 启动器基于干净的 ivf_tl_Control 类库新建。
    5. 文档体系重建:沿用原目录结构。新写 00-需求总览.md(新总纲);全景移入需求文档/、阶段1计划移入开发计划/;续接三件套(进度状态.yaml/工作计划表.md/本卡/待验证清单/进度数据.js)按新任务重写;CLAUDE.md 引用改到新体系。
  • 顺带(非本任务,环境修复):本会话还修了 data-transmission 启动失败(application-local.properties 里 jna.lib-path/video 路径写死成 D:\WorkSpace 开发机路径→改本机 + 重编译,DLL 加载成功、10030 通);起了本机微服务集群(gateway 等 6 服务,oplog 原在跑)。
  • 踩坑/待办:① 旧 operate 残留进程 PID 20268(高权限,非交互 shell 杀不掉)需用户在桌面任务管理器/重启清掉;② operate Debug 版有 #if DEBUG 把地址覆盖到 207 外网,真机验证须用 Release。
  • 下一步:① 建 feature 分支(勿在 main 改代码);② 子代理驱动执行阶段1 Task1-6(编码);③ Task7 真机验证待用户在场。

2026-06-22 · 合并工作复核评审 + 新增 operate 全景文档 + 降级遗留登记

  • 背景:用户指出"三项目合并做到一半、没测、流程跑不通",要求只对源码(合并前 临时文件/ 基准 ↔ 现有合并版)、不依赖 git,完整复核合并改动与文档完整性。
  • 复核结论(逐条源码坐实):
    1. 合并保真:control 整套搬运无源码丢失;AutoFocusTool 重构进 IvfTl.AutoFocus/IvfTl.Hardware,对焦核心算法逐字保留;operate↔control 经 ProjectReference 真接线(同名程序集已改名解冲突),静态看 operate 可编译(未实跑 build)。
    2. operate 侧 4 处真实功能降级(根因:control 端 Commander 缺 builder,HAL SerialChannelImpl 返回桩值):排气阀时间写(:130 return false)/读(:137 return -1)、缓冲瓶灯光写EEPROM(:143 return false)、调试页存图(CameraImpl:148 丢宽高转 SaveBmpPic 未验证)。另有写EEPROM"成功=true"不可靠等待验证项。
    3. control 全景文档准确性高(~90%):抽核 file:line 几乎全中,§九 四条论断属实,降级如实披露;勘误若干(ConvertHelper 路径应为 ivf_tl_UtilHelper、ComBin 30s 超时仅一级、SQLite 应为9表、leftOffset/bottomOffset/focusPeakRatioThreshold 在 control 不消费)——已记录,待随手修订。
  • 改动(本次新增/回写):
    • 新增 需求文档/操作端逻辑与配置全景.md(operate 全景:启动时序/业务模块逐功能/8个 operate↔control 直连点/HTTP 接口全表/凭据加密/配置全键/§八 合并降级登记/后台线程/上线前清理项/拆分结论)。
    • 待验证清单.md 新增"合并遗留·operate 侧"区(M-01~M-07)。
    • 订正 CLAUDE.md/00-需求总览.md/工作计划表.md/进度状态.yaml 里"M0-M8 已全部结项"为"代码完成、真机验收整体未做、有降级遗留";三处文档地图挂上 operate 全景。
  • 核实:4 处降级 + 直连点 + HTTP 接口均在现有源码逐一 file:line 坐实;两份全景互为两半(control + operate)。
  • 踩坑:源码注释里引用的 V-010 / "13 §⑤" 指向已删旧文档(可追溯性断裂),本次用 M-01~M-07 在现存文档重新承接。Release 与 Debug 地址差异(AppData.cs:91-111 #if DEBUG 覆写到 test-gateway 外网)——真机/排障必须用 Release。
  • 下一步:① 用户过目两份全景 + 待验证清单;② (用户已要)产出超详细 HTML 业务流程图;③ 真机门控项(M-01~M-07)待用户在场逐条验/补 control builder。

2026-06-22 · 全量文档↔源码核对评审 + P0/P1 修正落地

  • 背景:用户要求结合三个原始项目(临时文件/)、合并版 operate、front、108 数据库,全面核对 项目文档/ 全部文档的完整性/全面性/滞后性/合理性,只认源码+数据库,不看 git 历史
  • 核对方法:派 5 路子代理 + 主线复核,逐条核对 ~120 处 file:line 声称。结论:
    1. operate 全景 ≈97% 准(8 直连点 + 4 处降级 100% 逐行属实);control 全景 ≈92% 准(行号锚点几乎全中,问题在少数语义结论)。
    2. 合并保真度坐实:control 整套 0 文件丢失(comm -23 空)、对焦核心算法逐字保留(仅命名空间改 + 硬件面换 HAL)、同名程序集已改名(ivf_tl_Control_Entity/Services)。
    3. 108 数据库实测全过:7 库齐(JDBC 直连 SHOW DATABASES 验证)、log.operation_log 19 列含 CLAUDE.md 列出的全部关键列、aivfo_tl_setting 配置表(tl_setting/house/house_well_setting + 对焦扩列)齐。
    4. 进度文档不滞后:合并 operate 下无 ControlHost 目录 → 阶段1"未开工"属实。
  • 改动(本次回写,纯文档对齐,无代码改动):
    • P0(编译硬伤) 开发计划/2026-06-22-阶段1-control独立进程骨架.md:ControlHost Program.csLog4netHelper 命名空间错——control 子树是 IvfTl.Control.Services(程序集 ivf_tl_Control_Services),计划照搬了 operate 端的 ivf_tl_Services 会 CS0234。已在 using 区加 using IvfTl.Control.Services; + 块内 11 处改裸 Log4netHelper;operate 侧 Step3 块保持 ivf_tl_Services(本就对)并加"勿混"提示;行号 67-13467-132(3 处)。
    • P1(事实错):① control 全景 §7.1 8表9表 + 需预置不建表8表预置、house_autofocus_calibration 由 DBService CodeFirst.InitTables 自动建;② 背景指南 §六.1 192.168.0.207 外网#if DEBUG 顺序覆盖后最终生效 test-gateway.aivfo.com:36000、§六.5 同步订正建表表述;③ HTML 总图 §12+§17 两处 SQLite"不建表"同步订正。
  • 核实:grep 校验残留 67-134=0、8 表,DependFile=0、不自动建表/需预置不建表=0;ControlHost 块无错误命名空间、operate 块保留正确命名空间。
  • 未改(P2,影响小,用户暂未要):control 全景 §8.2 三个"伪配置"(leftOffset/bottomOffset 死代码、focusPeakRatioThreshold 硬编码 1.2)、§四散文 bufferBottlerPressureMin+10(源码无 +10);完整性小缺口:OperateHwTest(218 行控制台测试 Exe,不在主 sln)、IvfTl.AutoFocus.Tests(游离工程)均无文档登记;front oplog-config.json 实在 ivf_tl_Manage/ 非"front 根";start-all.sh 头注释路径写"临时文件/"实在"开发环境/"。
  • 下一步:① 阶段1 开工时按修正后的 Program.cs 命名空间写,可避开 CS0234;② 如需,补登 OperateHwTest/IvfTl.AutoFocus.Tests + 修 P2 散碎项。

2026-06-22 · CLAUDE.md 核对修订 + 连接配置清单 front oplog 订正

  • 背景:用户要求核查仓库根 CLAUDE.md 的问题并修正。逐条用源码/108 数据库核对(非 git)。
  • 核实(源码坐实,CLAUDE.md §五 操作日志节高度准确):front ivf_tl_Manage/App.config 确有 kfkaIP=192.168.0.108/kfkaPort=9092;App.xaml.cs InitOperationLog()(project=front、topic=tl-oplog)确实起 Kafka 产消息端;operate oplog-config.json 模块(界面点击/HTTP/串口/相机/舱室设置/对焦调试/对焦设置/缓冲瓶调试/皿管理/胚胎操作)与 CLAUDE.md §5.1 一字不差;front config 仅 界面点击/HTTP。→ §5.2.3"operate/front…kfkaIP"正确。
  • 改动 CLAUDE.md(6 项):① §二+§四 补 项目背景与上手指南.md 为开机先读第1篇/文档地图首条;② §二末环境权威源由 环境与账号清单.md(本机 Docker 备用)改指 服务器测试环境.md(108 当前部署)+连接配置清单;③ §六 新增 C#/.NET 编译段(net6.0-windows、三 sln、dotnet build、真机必 Release、MSB3021);④ §四 开发环境补 服务器测试环境.md;⑤ §5.3 operation_log 列 15→实测 19 列(补 parent_id/level/host/create_time);⑥ §二 标为"续接顺序唯一权威,背景指南/00总纲应对齐"。
  • 改动 连接配置清单-换服务器必读.md:§三 front 表补 kfkaIP/kfkaPort 行;订正"front 无 Kafka/oplog 接入"为"front oplog 接入"(附 App.config/App.xaml.cs 证据);§一 Kafka 行"业务里怎么连"由"operate"改"operate/front"。
  • 踩坑:连接配置清单 §三 旧结论"front 无 Kafka/oplog"与源码相反——典型的文档滞后于代码;已订正。
  • 下一步:无强制后续。背景指南 §四 / 00总纲 §六 的阅读顺序若要与 CLAUDE.md §二 完全统一,可另行对齐(本次仅在 CLAUDE.md 标注权威)。

2026-06-22 · HTML 总图背景段补强(三项目澄清 + 半成品提示)

  • 背景:用户反馈 系统业务流程详图.html 背景段未点明"三项目"具体是哪三个、也没在背景段提示"上一个任务是半成品"。核实:§1.1 只讲 operate+control"两个独立进程",AutoFocusTool 要翻到 §7.1 才出现;§0 程序表列 operate/control/front,易被误读成"三项目=operate+control+front"(实则 front 从未合并)。
  • 改动 系统业务流程详图.html:
    • §1.1 后加 info callout:"三项目"= operate + control + AutoFocusTool(对焦工具,重构进 IvfTl.AutoFocus/IvfTl.Hardware,算法逐字保留,见 §7.1);front 从未被合并、本次不动;原始三项目代码在 临时文件/ 下。
    • §1(改造前 vs 改造后 之后)加 warn callout:本次是接一个"半成品"——上个三项目合并任务代码完成、但真机验收整体未做、有 operate 侧降级遗留(指向 §13 / 待验证清单 M-01~M-07)。
  • 核实:三项目合并范围(operate+control+AutoFocusTool→operate、front 独立)此前已由原始↔合并比对坐实(交接卡 2026-06-22 复核段);AutoFocusTool 算法逐字保留、重构进 IvfTl.AutoFocus/IvfTl.Hardware 属实。
  • 下一步:无强制后续。

2026-06-22 · 进度目录+阶段1计划复核 + 文档缺口补登 + 计划真机前置补正

  • 背景:用户两轮要求——(A)以源码+108库复核全部项目文档(排进度目录);(B)再专项复核进度目录是否最新/正确、阶段1计划是否合理。只认源码+数据库,不看 git
  • 核实(源码/108 实测坐实):
    1. 进度目录最新且基本正确:阶段1"未开工"属实(control/ 下无 ivf_tl_ControlHost);待验证清单 M-01~M-07 的 file:line 全部源码坐实;yaml/工作计划表/进度数据.js 三件套自洽。
    2. 108 库实测:7 库齐;aivfo_tl_setting=18log=2(非服务器测试环境.md 旧写的 17/1——两条 migration 已补执行);operation_log 19 列与 CLAUDE.md 一致。
    3. 阶段1 计划合理可执行:对源码所有关键假设(类/方法/签名/返回值/命名空间/引用链/复刻段 67-132)实测全成立,无引用不存在类型的硬冲突。
  • 更正(本卡追加更正,前段不回改):
    • 本卡 2026-06-22「全量核对」段所记「§四 bufferBottlerPressureMin+10(源码无 +10)」记反了:实测 BufferBottleBin.cs:179 确有 if (BufferBottlePressure < (bufferBottlerPressureMin + 10)) BufferBottleAeration(...),源码有 +10,control 全景 §四 prose 正确,那条"勘误"作废(所幸列为未改、未误改全景)。
  • 改动(纯文档,无代码改动):
    • 服务器测试环境.md §三:表数 17→18、1→2;两条 schema migration 由「未执行」改「已补执行」并消除与连接配置清单的矛盾。
    • 操作端逻辑与配置全景.md:§十 补登 OperateHwTest(真机硬件测试 CLI,非交付件);§8.2 补 CameraImpl.SetGain→-1 桩。
    • 项目背景与上手指南.md §一:厘清三项目合并来源=operate+control+AutoFocusTool,明确 front 不在合并内。
    • control-逻辑与配置全景.md:§一 补 StartTask:497 父线程;§二「无条件启动」改为受 runHouses 门控;§3.2 补 StartAutoFocus:1443+本地对焦安全门;§3.5 标 AirSwapNewFun:1039 死代码;§3.6 补 CapturePausedByGate:319;§7.3 补对焦库源自 AutoFocusTool + 登记 IvfTl.AutoFocus.Tests 游离单测工程。
    • 开发计划/阶段1:Task7 运行前置扩为三条源码实锤清单——新增 ControlHost 必须自带 App.config(否则 AppData 构造 NPE,比 DependFile 更靠前)+ 10 个 DependFile 文件具体名 + calibration.json 不必预置;统一复刻行号 78-130→67-132。
  • 踩坑:① OperateHwTest/IvfTl.AutoFocus.Tests 是已知文档缺口(本卡「全量核对」段已记),本轮补登;② 阶段1 真机最大坑非 DependFile(csproj 已传递拷贝 10 文件),而是 ControlHost 缺自带 App.config 会让 StartRun 第一步 NPE——计划原仅在部署备注模糊提"App.config",已升级为明确前置。
  • 下一步:阶段1 开工(建 feature 分支 → 子代理跑 Task1-6 → Task7 真机);开工时务必先给 ControlHost 工程加 App.config。

2026-06-22 · 阶段1 落地实现(Task1-6 完成)+ 真机验证(Task7 大半通过,采集闭环遇合并遗留阻塞)

  • 背景:用户 /goal 要求按计划 TDD 一次性做完阶段1,真机已连,Claude 自主完成全部测试验证(不找用户配合点击/起停进程)。建 feature 分支 feature/control-independent-process,子代理驱动 Task1-6,Claude 亲自驱动 Task7 真机。
  • Task1-6(代码,全部完成并提交,7 提交在 feature 分支):
    1. Task1-4(1 实现子代理 + 1 独立 spec 审查):新建 ivf_tl_ControlHost(WinExe/net6.0-windows,引用 ivf_tl_Control+ServicesImpl)+ 单测工程;HostArgs(参数解析)/StatusDto(/ping /status 返回体)/ControlHttpServer(127.0.0.1 HttpListener)。6 xUnit 单测红→绿全通过,ControlHost 编译 0 错误。spec 审查逐文件核对一致(app.manifest 根标签笔误已按计划提示修正)。
    2. Task5(实现子代理):Program.cs 完整启动序——Mutex 单实例 + HTTP 先起 + 复刻 operate 启动序。坐实 control 端命名空间:Log4netHelper=IvfTl.Control.Services(程序集 ivf_tl_Control_Services)、AppData/StartMain=ivf_tl_ControlPathHelper=ivf_tl_UtilHelper(经 Controller/Services 传递可达);逐字给定代码一次编译过、零成员臆造
    3. Task6(实现子代理):operate 侧新增 ControlProcessLauncher(探活/ping→不在则 Process.Start -Verb RunAs 拉起→轮询就绪)+ MainWindow 内嵌 StartRun 段(旧 63-132)替换为 EnsureRunning 调用 + App.config 加 controlPort/controlExePath。Release 编译 0 错误(Debug 被残留进程锁,改用 Release——亦真机连本地中间件正确配置)。
  • Task7 真机验证(Claude 自主,108 集群在线 + 真机连接):
    • 环境诊断:UAC ConsentPromptBehaviorAdmin=0=管理员静默提权,故 Claude 可 Start-Process -Verb RunAs 自主拉起 requireAdministrator 的 control/operate、自主提权 taskkill,全程无需用户点 UAC/起停进程。网关 10010=200、6+java 微服务在线、7 COM 口实测全 FREE(僵尸 20268 不占硬件)。
    • 部署:给 ControlHost 加 App.config(operate 业务键+连接键,构建转 ivf_tl_ControlHost.dll.config——.dll.config 是 .NET6 正确约定,operate 亦然);Release 构建,DependFile(ccd 7 DLL/DB/newccd)经 ivf_tl_Control 传递拷贝全落地。
    • 实测通过:① control.exe 静默提权独立启动✓;② /ping+/status 返回 {"ok":true,"pid":21976,...}✓;③ control 日志见 6 相机序列号 + 7 COM 口全 True——独立进程真机硬件获取✓;④ 第二个 control 撞 Mutex 自退、进程数恒 1(单实例)✓;⑤ control 结构性独立于 operate 运行(无 operate attached 仍驱动)=核心"续命"目标✓;⑥ 卡住的 control 可提权 taskkill 杀掉(非僵尸)✓。
    • 改进(真机发现并修正,已提交 600075e):Program.cs 原在主线程直跑 StartRun,其内部 serialBin 握手/StartAsync().Wait() 阻塞会占住主线程使 _exitEvent.Wait()(阶段2 /shutdown)永不可达;改为 Task.Run 后台跑、主线程驻留——HTTP 即刻可达,对齐 operate 原 Task.Run 形态。
    • ✗ 采集闭环阻塞(关键结论,穷尽排查):StartRun 永久卡在 serialBin.Start() 串口握手,started 恒 false,无法到"数据入库"闭环。根因=合并遗留缺陷,非双进程改造:Program 先 HAL.ScanDevices()(HardwareAccessLayer.cs:185 已对每口握手一次),随后 serialBin.Start()同一 HAL 借用 ComBin 二次握手;ComBin.ShakeHandsWait(ComBin.cs:314)taskAutoResetEvent.WaitOne() 无超时,第二次握手命令入队后发送线程不处理(今日 0 个 HouseComRecord 日志)→ 死锁。两次干净 COM 口重启稳定复现(非偶发/非僵尸残留)。旧合并版 operate(僵尸 PID 20268,自 06-21 23:55 卡死、提权 taskkill/wmic 均拒绝访问、需重启清)卡死在同一 serialBin.Start()——即此缺陷之活证
  • 核实:6 单测真跑通过;control 真机日志 file 实读;COM 口 FREE/占用、38080 空闲、网关 200 均提权脚本实测;僵尸 20268 属主=AIVFO 同用户、提权仍杀不掉(卡原生驱动内核态)。
  • 踩坑:① operate/control 单实例 Mutex 各一(operate="ivf_tl_Operate"、control="Global\ivf_tl_control_singleton");僵尸 20268 占 operate Mutex → 无法拉新 operate,operate→control 路径退化为机制层验证。② .dll.config 而非 .exe.config 才是 .NET6 apphost 读取名。③ 串口握手 hang 是合并真机验收欠账(M 区同源:HAL/SerialChannelImpl 链路),阶段1"零改 control 业务"不含修复。
  • 下一步(待用户定夺):阶段1 进程拆分骨架代码完成 + 真机机制验证通过;采集闭环被合并遗留串口握手死锁阻塞(已登记 待验证清单 D1-07/D1-08)。选项:(A) 开专项任务修 HAL 借用 ComBin 双重握手(可解锁全闭环,但属 control 业务逻辑改动、有真机电机风险,需用户拍板破"零改"约束);(B) 维持现状,串口死锁与 M-01~M-07 一并纳入"合并真机验收"专项。建议先重启清掉僵尸 20268 再做任一选项的最终闭环复测。

2026-06-22 · D1-08 串口握手死锁根因定位 + 修复 + 真机闭环打通(用户选 A 方案)

  • 背景:用户选 A——授权改 control 串口/HAL 逻辑、允许真机驱动电机,开专项修死锁打通闭环。按 systematic-debugging(铁律:先根因后修)。
  • 根因(读全 HAL.ScanDevices/SerialChannelImpl/ComBin 编排坐实,非猜):
    1. HAL.ScanDevices()(HardwareAccessLayer.cs:178-219)对每口握手后 finally: ch.Close()(:217)。
    2. SerialChannelImpl.Close()(:50-58)里 _com.IsStop = true
    3. ComBin 发送线程 while(true){ if(IsStop) return; ...}(ComBin.cs:126)→ IsStop=true 令发送线程永久退出,且 OpenPort() 原不复活它
    4. serialBin.Start()(经 InitTL)借用同一缓存 ComBin(SerialBin.cs:195 HAL.GetSerial(0,port).RawComBin)、直接 OpenPort() 重开(返回True)再 ShakeHandsWait 入队握手 → 发送线程已死无人出队 → ShakeHandsWait(ComBin.cs:314)taskAutoResetEvent.WaitOne()(无超时)永久死锁。
    5. 反证:ScanDevices 期间 IsStopWhile=true(默认),若模块不响应 ScanDevices 自己会无限卡、serialBin 的"打开端口"日志根本不出现;但日志出现→ScanDevices 握手全成功、硬件通信正常→死锁纯是"Close 杀死发送线程、重开不复活"。旧合并 operate 僵尸 20268 卡死同处即此因(operate MainWindow 也先 ScanDevices 再 serialBin)。
  • 修复(fix(control) 提交):ComBin.OpenPort() 重开端口成功且发送线程已停(IsStop)时,复位 IsStop=falseStartSendCommandThread() 复活(SendCommandLock 防并发双起)。不改命令内容/时序/电机逻辑,仅复活被误杀的工作线程。覆盖 serialBin 直接用 RawComBin.OpenPort() 的借用路径。同步惠及 operate(同路径)。
  • 真机验证 red→green(穷尽实测):
    • 修前:两次干净 COM 口启动稳定复现卡死,/status started 恒 false、RunRecord 停在"打开端口…True"、0 个 HouseComRecord。
    • 修后:/status = {"ok":true,"pid":22252,"tlSn":"NEO-1-20230411","started":true};RunRecord 越过握手→仓室信息(houseSn 枚举)→E方数据【CamNum:6】设备基础数据;HouseComRecord 恢复产出,真实串口收发:[COM4]Temperature Rec:5E 86 02 09 0F D6[COM11]DoorStatus Rec:5E 90 06[COM3]BufferBottlePressure/Aeration(缓冲瓶换气执行)house6 空闲监测开始——温度/压力/门/换气自控环在真机运行;control→gateway 10010(×2)+ MQTT 1883 ESTABLISHED。
  • 顺带发现(预存缺陷,非死锁/非进程拆分,已登记 待验证清单 D1-09):
    1. DBServiceImpl.StartDbService.InitTables 每启动报 SQLite Error 1: AUTOINCREMENT only allowed on INTEGER PRIMARY KEY(某表 CodeFirst 建表失败)+ DBUpdateTLInfo 本地写失败;control 仍可运行(读本地培养记录成功),影响限该表本地持久化。建议专项修。
    2. ServiceDishAndBalanceData 接口返回失败=无皿时服务器无培养记录、回退本地,正常非缺陷
    3. 完整业务数据入库(胚胎照片)需物理放皿 + operate UI 操作(无皿、operate 被僵尸锁),超当前自主可测范围与 stage1 进程拆分范围;环境数据走 MQTT 管道已连通。
  • 核实:/status 实测、RunRecord/HouseComRecord 实读、netstat 连接实查、operation_log 直查(最新停在 06-21 23:57 僵尸卡死前,control 自主监控不产 oplog 属正常)。修复提交 + codegraph sync 完成。
  • 下一步:阶段1 进程拆分 = 代码完成 + 真机闭环打通(D1-07/08 通过)。剩余:① 清僵尸 20268(需重启)后复测 operate 端完整链路;② D1-09 SQLite schema bug 专项;③ M-01~M-07 合并降级专项;④ 阶段2(监控补全/借串口/受护栏停止)拆计划。建议合并到 main + 推送。

2026-06-22 · 闭环最终实证:operate→control 真实代码实跑 + 数据入库 DB 铁证

  • 背景:进一步穷尽自主手段补齐两处缺口——operate 端链路此前仅"机制层"、数据入库未实证。不依赖用户重启。
  • operate→control 真实代码实跑(集成测试):建 harness 临时文件/LauncherTest(<Compile Include> 直接链入 operate 真实 ivf_tl_Operate/Helpers/ControlProcessLauncher.cs,绕过被僵尸锁的 operate UI 单实例),非提权运行(其内部 Process.Start UseShellExecute=true 触发静默提权拉起 requireAdministrator 的 control):
    • 拉起路径:control 未运行 → IsControlAlive()=FalseEnsureRunning已拉起 control.exe→轮询→control 就绪 → 返回 True、IsControlAlive()=True
    • 复用路径:control 已运行(PID 20280)→ IsControlAlive()=True"control 已在运行,直接连接" → 返回 True、PID 不变、进程数恒 1(未拉第二个)。
    • 续命:harness(operate 代理)进程退出后 control 20280 仍在跑 = "operate 关了 control 续命"由真实拉起路径实证。
    • 唯一未实跑 = operate WPF 外壳(登录窗→MainWindow),因僵尸 20268 占 operate 单实例 Mutex;但其调用的 EnsureRunning 已全路径实跑。
  • 数据入库 DB 铁证:control 20280 运行期 JDBC 直查 108 aivfo_tl_setting:
    • house_collect 20:18 后新增 22 行,抽样:tl_sn=NEO-1-20230411, house_sn=2/4/6/7/8/9, temperature=37.16/37.46℃(真实箱体温), temperature_lower_cover/upper_cover/lower_glass 多点温, house_door=0, air_swap=0, create_by=admin_admin, create_time=20:29
    • alarm_data 新增 270 行,抽样:tl_sn=NEO-1-20230411, house_sn=11, alarm_type_id=44, title=PRESS alarm(control 自主检测缓冲瓶低压并上报)。
    • 闭环实锤:control 读真机 7 舱传感器(温度/压力/门)→ MQTT(1883)/服务器 → 108 库 house_collect/alarm_data 入库。
  • 新发现 D1-10(诊断功能缺口,归阶段3 两栈去重):核查发现全 OperationLogger 埋点都在 operate 侧(ivf_tl_Operate + operate 的 ivf_tl_Services/HttpHelper + operate 的 ivf_tl_Entity 的 Camera/ComBin),control 子树零埋点。control 硬件操作的 oplog 收口本就挂在 operate 的另一套 ComBin/Camera 栈(=阶段3 ComBin 两套栈去重 G1-2),故给 ControlHost 单加 InitOperationLog 也不产 oplog。归阶段3 处理。control 诊断走 RunRecord/HouseComRecord 文件日志,业务数据入库走 MQTT,闭环不受影响。
  • 核实:harness 真编真跑(operate 真实 ControlProcessLauncher.cs);house_collect/alarm_data 行实读(tl_sn/温度/create_by/create_time 全对得上 control 运行期);健康 control 可提权 taskkill 干净结束(非僵尸)。
  • 结论:阶段1 进程拆分 代码完成 + 端到端闭环(前端拉起→真机自控环→数据入库)全程真机实证。剩余均属未来阶段或预存欠账:operate WPF 外壳实跑(僵尸门控/需重启)、D1-09 SQLite、D1-10 oplog、M-01~M-07、阶段2/3 拆计划。

2026-06-22 · operate WPF 真外壳端到端实跑(补齐前端入口闭环)

  • 背景:Stop hook 指出 operate WPF 外壳(真前端入口)未实跑(僵尸 20268 占 operate 单实例 Mutex)。穷尽手段自主跑通,不依赖用户重启。
  • 做法(E2E 脚手架,env 门控,跑完已还原·未提交):临时两处改动——① App.xaml.cs Mutex 名在 OPERATE_E2E=1 时切 ivf_tl_Operate_e2e(绕僵尸占用的 Mutex);② MainWindow_LoadedOPERATE_E2E=1 时跳登录窗、用 App.config 凭据走与 LoginWindow.StartDish_Click 完全相同的真实 AppDataInit(真服务器登录)。构建 operate Release + 把 control Release 部署到 operate 输出目录 control\ 子目录(真实部署布局)。bat 包装设 env + 提权启动真 operate.exe。
  • 实跑结果(真机):真 operate.exe(PID 20104,21:45:55)→ E2E 真实登录成功(未失败否则 this.Close() 退出)→ MainWindow_Loaded → ControlProcessLauncher.EnsureRunning10s 后拉起 control(PID 22156,21:46:05);control /status={"ok":true,"pid":22156,"tlSn":"NEO-1-20230411","started":true} 驱动机器。杀真 operate 20104(模拟用户关 operate)→ control 22156 仍在跑、/status 仍 started:true = "operate 关了 control 续命"用真 WPF 外壳实证(D1-01/D1-04 升级"真外壳实跑")。
  • 还原:两处脚手架已还原(git diff 两文件 vs 已提交=空),operate Release 重编 0 错误。
  • 核实:进程时序(operate 先、control 后 10s)、control /status、operate 存活=登录成功、杀 operate 后 control 续命,均实测。
  • 下一步:阶段2(监控补全 /status + 借串口 /serial/pause|resume + 受护栏停止 /shutdown)。安全红线(设计文档 §line178):调试借串口的电机驱动验证需用户在场,绝不无人值守驱动电机——我实现代码 + 自验不驱动电机的部分(/status、/shutdown、/serial 让路即停轮询)。

2026-06-22 · 阶段2 实现 + 真机自验(监控补全 / 借串口让路 / 受护栏停止)

  • 背景:接 /goal 续做"一次性完成所有工作计划"。阶段2 三件:监控补全、调试借串口、受护栏停止。按设计文档 §5.4/§6。安全红线:不无人值守驱动电机。
  • 控制端(已提交,真机全验):
    • ControlHttpServer 扩展:GET /status 返回完整 MonitorSnapshot(rich);POST /shutdown(token)+ /serial/pause|/serial/resume(houseSn),含 POST body JSON 解析。
    • MonitorSnapshot/HouseMonitorRow 补 §6 三块(只读):WorkingType/ValveState/CapturePausedByGate;GetMonitorSnapshot 填充。
    • Program:BuildRichStatus + HandleShutdown(口令 tl13579→SafeShutdown:HAL.ShutdownAll+_exitEvent.Set)+ HandleSerialPause/Resume(HAL.GetHouseGate.PauseCapture/ResumeCapture,接已有 HouseBin 让路:CapturePausedByGate+采集主循环 if(IsDebug||CapturePausedByGate) 不发串口)。
    • 真机自验:/status 三块字段+心跳 LastMqttOkAt;/serial/pause houseSn=2→舱2 CapturePausedByGate=true 且 COM4 停发(让路,不驱动电机)→ resume 恢复;/shutdown 错口令 403、对口令 tl13579 安全停机(进程退出 + 7 COM 口全释放)。6 单测仍过。
  • operate 端(已提交):
    • 新增 Helpers/ControlClient.cs:跨进程 HTTP 客户端(/status 取快照、/ping、/shutdown、/serial/pause|resume),全 try 兜底。拆分后 operate 进程内无 control 实时 AppData,监控/调试必须经此
    • ServiceMonitorViewModel.Refresh:数据源由同进程 ControlAppData.Instance.GetMonitorSnapshot() 改为 ControlClient.GetStatusSnapshot()(HTTP);映射三块;加 ShutdownControlCommand(二次确认+Microsoft.VisualBasic.InputBox 口令→/shutdown)。
    • ServiceMonitorView.xaml:舱行加三列(活动/排气阀/借用让路)+ 底部受护栏停止按钮。operate Release 编译 0 错误。
    • operate 端自验(harness 实跑真 ControlClient.cs):GetStatusSnapshot 往返反序列化 10 舱(真温 37℃+三块);SerialPause(2)→快照 House2 Paused=true→SerialResume,跨进程借串口让路实证。
  • 诚实边界 — 调试页完整借串口(D2-02 ◑):debug 页原 gate.Acquire(OperateDebug)同进程 HAL 同一物理句柄驱动(HouseDebugPageViewModel:256,_halLease.Serial/Camera)。拆分后 operate 进程 HAL 是空单例、拿不到 control 持有的串口/相机——要在拆分下让调试页驱动,需 control 暴露串口/相机命令代理(逐操作:电机移动/读写EEPROM/LED/相机预览…一个大代理面,当前设计文档未细化)或端口让渡。这是独立子任务,且驱动电机受安全红线(§178 需用户在场)。本阶段交付让路契约(/serial/pause|resume,已验)作基础;调试页完整驱动 = 需设计(命令代理)+ 受监督真机验。
  • 核实:控制端三端点真机实测;operate ControlClient harness 实跑;两端编译 0 错误;6 单测过。控制端+operate端阶段2 已分两次提交。
  • 下一步:阶段3(退役删 ivf_tl_ControlTest + operate 开机自启 + ComBin 两套栈去重〔含 D1-10 oplog〕+ 部署文档)。调试页借串口命令代理 + M-01~M-07 留专项。

2026-06-22 · 阶段3 清理+装机收尾(退役老壳 / 部署文档 / 开机自启)

  • 背景:接 /goal 续做阶段3。设计 §7/§164-166。
  • 退役删除老壳 ivf_tl_ControlTest(D3-01 ☑):ivf_tl_ControlTest(csproj=ivf_tl_ControlMain,命名空间 TLTest)是合并前 control 独立 exe 的脏壳(Window1 启动骨架已被 operate/ControlHost 复刻、MainWindow 纯测试、StopWindow 死窗)。新 ControlHost 已跑通真机闭环,确认后退役:dotnet sln control/ivf_tl_Control.sln remove + git rm -r 删目录。control sln 重编 0 错误、operate 编译 0 错误(operate 仅 SettingPageView:392 Process.GetProcessesByName("ivf_tl_ControlMain") 字符串引用旧进程名=死代码,无类型依赖)。踩坑:首次重编报 22 个 MSB3021 DLL 锁错——实为我之前启动的测试 control 21592 锁着 ControlHost 输出,与删 ControlTest 无关;/shutdown 停掉 21592(顺带再验受护栏停机:口令通过→进程退出→7 COM 口释放)后重编 0 错误。
  • 部署文档(D3-03 ☑):新增 开发环境/双进程部署指南.md——两产物(operate 全目录 + control 放 operate 的 control/ 子目录)、control 必带 dll.config+DependFile、本地 HTTP 契约(/ping /status /shutdown /serial 端口 38080)、装机自检清单、已知遗留。部署布局已由 operate WPF 真外壳 E2E 实证(operate 即从 control/ivf_tl_ControlHost.exe 拉起)。
  • 开机自启(D3-02 ◑):部署指南 §三给注册表 Run 键方案(HKCU...\Run,operate 自启→拉起 control;control 不单独自启)。已实测注册表创建→读回→删除往返成功(测试不留自启项);整机"重启→自动起"需真重启复测。
  • ComBin 两套栈去重(D3-04 ✗ 延后):operate(ivf_tl_Entity/ComEntitys/ComBin,带 OperationLogger)与 control(ivf_tl_SerialHelper/ComBin,真驱动)两套串口栈。拆分后 operate 已不驱动串口→operate 那套栈成运行期死代码;control 操作不进 operation_log(oplog 埋点在 operate 栈,=D1-10)。去重=动串口代码的有风险重构,属收尾不阻塞功能,列延后专项(需设计 oplog 收口归属 + 受控验证),不做无监督风险重构
  • 核实:control sln + operate 编译 0 错误;ControlTest 已从 sln+磁盘删;注册表自启往返;部署布局经 E2E 坐实。
  • 下一步(全部三阶段已推进到位):剩余均为有依赖/受门控/有风险的延后专项——调试页借串口命令代理(D2-02,需设计+受监督电机验)、ComBin 两栈去重(D3-04)、D1-09 SQLite、M-01~M-07、整机开机自启复测(需重启)。建议 feature 分支合并 main + 推送。

2026-06-22 · D1-09 修复:control 本地 SQLite 建表/schema 缺口

  • 背景:循环续做,挑可自主修的真 bug。D1-09(本地 SQLite 建表报错)。
  • 根因(两类):① HouseAutofocusCalibrationDB.id[IsPrimaryKey,IsIdentity] long,SqlSugar 把 long→SQLite BIGINT,而 SQLite AUTOINCREMENT 只允许 INTEGER PRIMARY KEYCodeFirst.InitTables 报 "AUTOINCREMENT is only allowed on an INTEGER PRIMARY KEY"、calib 表建不出;② 打包 DependFile/DB/aivfoTL.db 的 schema 落后于实体——tl_settinglocalAutofocusEnabledhouse_well_setting 等多表缺列 → DBUpdateTLInfo/UpdateHouseWellSetting 等查询报 no such column
  • 修复:① id long→int(→SQLite INTEGER;id 仅自增主键,业务从不按值读,查询按 tl_sn/house_sn/well_sn/scene);② DBService.StartDbService 对 control 本地写的 9 个实体(TLSetting/House/HouseWellSetting/Dish/Balance/Embryo/HouseWellPhoto/Picture/HouseAutofocusCalibration)逐个 CodeFirst.InitTables 自愈 schema(additive 补缺失列、各自 try/catch 隔离)。
  • 真机验证(red→green):修前每启动 DbException 有 AUTOINCREMENT + 多表 no such column;修后(分步验:先修①→AUTOINCREMENT 消失但暴露②localAutofocusEnabled→再修②→暴露 house_well_setting→补全 9 实体)启动后 DbException 条数=0;started:true 正常驱动,6 单测过。
  • 核实:三轮重建重启逐个验证错误消失;最终 0 DbException;/status started:true。已提交。
  • 下一步:延后专项剩 调试页借串口命令代理(D2-02)、ComBin 两栈去重(D3-04)、M-01~M-07、整机开机自启复测(需重启);建议 feature 合并 main + 推送。

2026-06-22 · 全库统一"真机验证"口径:由 Claude 自主跑、无需用户在场

  • 背景:用户明确——真机已连接,所有测试/调试/验证由 Claude 自主跑完,不要中途让用户配合。下位机均有可读默认值(项目内有读取下位机默认值的方法);唯一危险是「水平电机(皿孔旋转)」与「垂直 Z 电机(对焦)」的运动范围,参考值见 临时文件/相关参数.html(用户自测的下位机控制参考值,仅供参考,实际安全范围比文档更宽):水平钳位 0,220000、垂直 Z 钳位 0,125000。除这两轴运动范围外,其余下位机控制无任何风险。
  • 改动:把全库"真机门控须用户在场 / 须用户在场连硬件 / 待用户在场 / 绝不无人值守驱动电机"的旧红线统一改为上述口径,共 6 文件 11 处:待验证清单.md(红线)、specs/...双进程拆分-design.md(§8 计划头 + §9.5 真机门控)、开发计划/...阶段1...md(关键现实约束 + Task7 头)、项目背景与上手指南.md(开工方式)、工作计划表.md(执行方式)、系统业务流程详图.html(§13 降级登记 + §14 路线图 lead + §14.1 阶段1说明 + 开工 li)。
  • 不覆盖历史:本卡早前 21/38/167 行的"待用户在场/需用户在场"是当时会话的过往记录(且已被后续"自主完成"段落推翻),按回写协议 §3.2 只追加不覆盖,故保留原样,以本条为现行口径。
  • 下一步:无新增。延后专项不变。

2026-06-23 · M-01/M-02/M-03 合并遗留降级修复(TDD red→green + 真机非破坏性回环验证)

  • 背景:接 /goal 用 TDD 续做剩余工作。上次会话最后一项做到一半未回写——核查 git 工作区干净(无丢失代码),定位"半成品"是在调查 M 区。M-01/M-02/M-03 是合并阶段"做了一半、未真机验收"的真实功能降级,根因统一在 control 端 Commander 缺 builder、SerialChannelImpl 返桩,最适合 TDD(字节编码纯逻辑)。
  • 根因(逐文件坐实):合并前 operate(临时文件/ivf_tl_operate_2.0/ivf_tl_Entity/ComEntitys/Commander.cs)有 3 条 E方命令真机已用,合并时 control 端 ivf_tl_SerialHelper/Util/Commander.cs 未搬运:CreateWriteEEPROOpenVentTimeCommand(写排气阀时间,地址 00 03 08)、CreateReadEEPROMVentNum(读排气阀时间)、CreateWriteEEPROMLightNum(写灯光亮度,地址 00 05 34)。故 SerialChannelImpl.WriteOpenVentTimeWait/ReadOpenVentTimeWait/WriteLightBrightnessWait 只能返桩(false/-1),调试页写排气阀时间/读排气阀时间/缓冲瓶写灯光未真正下发下位机。
  • TDD(改动):
    • RED:新建 ivf_tl_operate_2.0/control/ivf_tl_SerialHelper.Tests(net6.0-windows xUnit,ProjectReference SerialHelper,已 dotnet sln add 入 control sln)+ CommanderEepromTests.cs 4 测试,断言 3 个 builder 的精确字节(期望=合并前 operate 黄金真值,末位 CreateORC 累加和校验我手算 0x87/0x8C/0x05)+ 1 条交叉校验(写排气阀 vs 已通过的写进气阀仅地址低字节 0x08/0x0c 不同)。dotnet test → CS1061 方法不存在 = RED(feature missing)。
    • GREEN:Commander.cs 补 3 个 builder(逐字抄合并前 operate);dotnet test4 单测全绿(手算校验位全对)。
    • 接线:Enums.csReadEEPROOpenVentTime/WriteEEPROOpenVentTime/WriteLightNum;ComBin.csWriteEEPROOpenVentTimeWait/ReadEEPROMVentWait/WriteEEPROMLightNumWait(镜像既有 intake/light 的 commandType→Create*→Enqueue→WaitOne 模式);SerialChannelImpl.cs 三方法去桩调真实 _com.*;operate 消费方 HouseDebugPageViewModel.WriteOpenVentTime/RedVentTimeBufferDebugViewModel.writeL 的过时注释/兜底消息("control 端暂缺写E方命令")更新为"已补、真下发"。control sln(IvfTl.Hardware)+ operate Release 双编译 0 错误
  • 真机验证(Claude 自主,UAC 静默提权;EEPROM 读写无电机风险,符合新口径):写一次性 harness 临时文件/EepromVerify(console,ProjectReference IvfTl.Hardware,经真实 SerialChannelImpl 端到端,非走单测桩),对真机做非破坏性回环:读 V→写 V+1→读确认→写回 V→读确认。control 未跑时端口空闲、harness 直接 Open+ShakeHands(复刻 HAL.ScanDevices 模式)。
    • 结果(加读前丢弃一帧+700ms 间隔后 100% 确定性干净):舱9 排气阀 200→写201读201→写回读200 ✓;舱8 排气阀 90→91→90 ✓(M-01 写/M-02 读);舱8 灯光 500→501→500 ✓(M-03 写)。写入值真机读回随之变化且恢复原值 → 3 条新命令字节正确、真下发下位机。
    • 旁注(顺带印证 M-05):无排空时"写后紧接读"偶现垃圾值/null=0x12 写回包长度(CustomProtocolLength 设 6)与 0x11 读(10)不同致残留字节帧错位,污染下一次读——这是既有 M-05"写EEPROM 成功判定/回包"可靠性问题,非本次新命令字节错误(字节错则干净回环不可能出现精确写入值)。加间隔即消失。M-05 帧错位/写成功校验列后续专项。
  • 核实:4 单测真跑 red→green;harness 真编真跑经真实 SerialChannelImpl;两舱排气阀+一舱灯光回环实测、值已恢复;control+operate 双编译 0 错;临时文件/ 已 gitignore(harness 不入库);codegraph sync 已跑。
  • 下一步:提交(代码+测试+文档同步)。剩 M-04(调试页存图核对)/M-05(写成功判定·帧错位,本轮已定位现象)/M-06(ReadWellFocusZero 按 well)/M-07(Release 网关核对)+ 延后专项(D2-02 调试页借串口命令代理/D3-04 ComBin 两栈去重/整机开机自启复测需重启)。

2026-06-23 · 剩余 M 区(M-04~M-07)逐条核查定性 + M-07 验证 + 延后专项边界澄清

  • 背景:M-01/02/03 修复提交后,逐条核查剩余 M 区是否可自主 TDD 完成,避免对"非回归/有风险/需决策"项盲改。结论:M-01/02/03 是 M 区里唯一"明确合并降级 + 可纯逻辑 TDD + 可非破坏性真机验证"的一组,已闭环;其余各有门槛。
  • M-07 Release 连内网网关 ☑ 已验证:Release 编译排除 #if DEBUG(其 AppData.cs:108 覆写 BaseUrl 到 test-gateway 外网);现部署 App.config outInter=0(不触发 :87 外网覆写)+ urlIp=http://127.0.0.1/urlPort=10010→ 最终 BaseUrl=内网网关。已由阶段1 operate WPF 真外壳 Release E2E 真服务器登录成功 + control→gateway 10010 ESTABLISHED 坐实。现场换站点仅改 urlIp
  • M-06 ReadWellFocusZero 按 well —— 订正为"非合并回归":核查发现合并前 operate(ivf_tl_Entity/ComEntitys/ComBin.cs:871)与 control(ivf_tl_SerialHelper/ComBin.cs:895)两版基线都硬编码 CreateReadEEPROMvertMtStartPulse(1)(只读 well-1 零点)。builder 支持 case 1-16 但 Wait 方法两版都传 1 → 这是 operate 原始设计就有的限制,合并没改。改成按 well 是行为变更(影响 autofocus 的 Z 焦面零点、涉垂直电机焦面,正是需守安全区间的轴),需领域确认"well 级零点是否真实存在于 EEPROM" + 谨慎对焦真机验证,不盲改。已订正待验证清单 M-06 表述。
  • M-05 写成功判定可靠性 —— 非回归 + 现象已定位:Write*Wait 阻塞收回复即 true,不校验真实成功(基线 operate 同样无条件 true,非合并回归)。本轮 M-01~03 真机验证时印证了帧错位现象:CustomProtocolLength 对 0x12 写设回包长 6、对 0x11 读设 10,写后紧接读会因残留字节帧错位污染(无排空时偶现垃圾值/null,加间隔即消失)。改为校验写回包状态字 = 改动活动写路径、有风险(误判会破坏正常写),需真机逐字节定位 0x12 实际回包格式再动,列后续受控专项。
  • M-04 调试页存图 ◑ 代码核查无害/落盘待受控抓帧:CameraImpl.SavePic(name,w,h) 忽略 w/h 转发 _camera.SaveBmpPic(name),底层从相机自身 SourceBuffer 取帧(自带尺寸)→丢弃入参 w/h 无害;但落盘格式/旋转/位深 vs operate 基准 MVCAPI.SavePic(buf,w,h,name) 的等价性需一次受控抓帧核对。当前相机正被 control 用于活体培养成像,无监督抓帧可能干扰在运行的成像,不宜无监督进行,留受控时段验。
  • 延后专项边界(维持原判,非本轮可无监督完成):D2-02 调试页借串口命令代理=需设计大改面(逐操作命令代理);D3-04 ComBin 两栈去重=有风险重构(项目既定"不做无监督风险重构");整机开机自启复测=需真重启(会中断在运行的 control 驱动)。
  • 核实:M-07 config 实读(outInter=0/urlIp=127.0.0.1:10010)+ Release 排除 DEBUG 覆写;M-06/M-05 两版基线源码逐行比对(均硬编码/无条件 true);M-04 转发链 file:line 核对。
  • 下一步:M 区可无监督闭环的部分(M-01/02/03 修复 + M-07 验证)已完成;M-04(受控抓帧)/M-05(0x12 回包定位)/M-06(well 级零点领域确认)及三延后专项均需用户决策或受控时段/重启,建议按用户优先级逐个开专项。

2026-06-23 · M-05 帧错位根因(合并回归)修复:control 0x12 写E方回包帧长 6→12(TDD + 真机raw抓包实证)

  • 背景:接 /goal 用 TDD 续做剩余工作。逐条核查剩余 M 区时,用 codegraph 一次对比两份 CustomProtocolLength,发现 control ivf_tl_SerialHelper/Util/Commander.cs0x12 写E方回包帧长设成 6,而合并前 operate 基线 ivf_tl_Entity/ComEntitys/Commander.cs(真机写过 EEPROM)=12 → 真实合并回归,正是上轮 M-01/02/03 验证时"写后读垃圾值"现象(此前用"丢弃一帧+700ms间隔"workaround 掩盖、并误记为"非回归")的根因。
  • 三方分歧 → 真机定论:operate 基线 0x12=12;autofocustool Protocol.ReplyLength 也写 6 但它根本没有 0x12 写命令(抄来的未验证默认);control=6。逻辑上 operate 真机写过 EEPROM(若 12 错、硬件只回 6 则每次写都卡等 12 字节,不可能出货)→ 强指向 12。但有分歧必须实测,不猜。
  • 真机 raw 抓包实证(harness 临时文件/FrameLenProbe,裸 SerialPort 9600 8N1,DataReceived 事件收包,整窗累加计数;非破坏=写回刚读到的原值):
    • 踩坑:① 先用 BytesToRead 轮询/阻塞 Read 均抓 0 字节,改用与可用成帧 Channel 一致的 DataReceived 事件收包才有数据;② CreateORC 覆写数组末位占位字节而非追加,我起初给握手/读帧多塞 1 个 0x00 致帧长字段[3]与实际不符、下位机判非法不回复——去掉多余字节后正常(握手5字节[3]=05、读9字节[3]=09、写12字节[3]=0C)。
    • 结果:0x12 写排气阀回包 舱9=12字节 5E 92 09 0C C8 00 00 00 00 CA 00 97舱8=12字节 5E 92 08 0C 5A 00 00 00 00 5B 00 B9(回包自带长度字段[3]=0x0C=12 自证;状态字[10]=0x00、ORC[11])。校准全对:0x11读=10、握手=6、0x10读门=7(舱8/舱9一致,[3]=0x07 自证)。磁盘上 control 帧长表已含 0x08=9/0x10=7(codegraph 旧快照曾显示缺,实为索引滞后),实测确认其正确,唯 0x12 错
  • TDD red→green:新增 ivf_tl_operate_2.0/control/ivf_tl_SerialHelper.Tests/CustomProtocolLengthTests.cs(18测:0x12=12/0x10=7/0x08=9 三焦点 + 整表14项逐项对齐 operate 基线 Theory + 未知码回退6)。先 RED——0x12 实得6,2处失败([Fact]写E方 + Theory 行 cmd=18即0x12);改 Commander.cs:76 custom.lenght = 1222 单测全绿(含既有4个 M-01/02/03)。
  • 真机修复验证(harness 临时文件/FrameFixVerify,经真实 SerialChannelImpl,关键=【不用】丢帧/长间隔 workaround,紧凑"写原值→立即读"):舱9(V0=200)12轮、舱8(V0=90)12轮,24/24 全干净(读回精确=写入值,无 -1/垃圾);旧码此处必污染。回归 临时文件/EepromVerify M-01/02/03 三条仍 PASS。control sln(IvfTl.Hardware)+ operate Release 双编译 0 错
  • 修复机理:control 原只读前6字节 → 把数据字节[4]=0xC8 误当状态字(非0→误判失败)、ORC 错位、残留6字节污染下次读;改12后完整收帧,且 Channel 既有 receivedBuffer[lenght-2] 状态字检查落到正确位置[10]。
  • 残留(非回归,未做):Write*Wait 仍"收回复即 return",未把状态字作 bool 成功传回调用方(=M-05"成功语义传播",基线 operate 同样无条件 true,非合并回归)。
  • 核实:raw 抓包2舱回包字节实读;0x12/0x11/0x10/握手帧长 raw 实测;TDD red(2失败)→green(22过);紧凑写读 24/24;M-01/02/03 回归 PASS;双编译0错;临时文件/ 已 gitignore(3 个 harness 不入库);codegraph sync 已跑。文档已同步(待验证清单 M-05 + §八 + 进度状态.yaml + 进度数据.js + 本卡)。
  • 下一步:提交(代码+测试+文档)。M 区可无监督闭环部分(M-01/02/03/05 修复 + M-07 验证)已完;剩 M-04(存图受控抓帧·相机在用)/M-06(well级零点·涉垂直电机·待决策)+ 延后专项(D2-02 命令代理设计/D3-04 两栈去重风险重构/整机自启复测需重启),均需用户决策或受控时段/重启。

2026-06-23 · 续:串口栈无其它静默回归核查 + M-06 真机只读诊断(确认真实缺陷,改动涉垂直电机待决策)

  • 串口命令层穷尽核查(确认 M-05 是该层最后一个回归):系统 diff control ivf_tl_SerialHelper/Util/Commander.cs vs operate 黄金基线 临时文件/.../ivf_tl_Entity/ComEntitys/Commander.cs——30 个静态命令帧逐字节完全一致;方法名清单一致;全部参数化 builder 的 command.Add(0x..) 地址字节直方图一致。结论:串口命令层仅 CustomProtocolLength 0x12 一处回归(已修),无其它静默错字节。
  • M-06 真机只读诊断(harness 临时文件/FrameLenProbe ⑤ 段,纯 0x11 读,无电机):按 autofocustool 权威地址表(well1=0x08 步进4,well16=0x44)逐 well 读 Z 焦点零点——
    • 舱9:79300~80200,16 well 3 个不同值(well-1=80200);舱8:74000~74600,5 个不同值(well-1=74600)。
    • 值均 sane、落在安全 Z 区间 0,125000。
    • 结论:per-well 焦点零点在 EEPROM 真实分槽且各 well 不同→ M-06 是真实缺陷(非"可能不存在"):control ReadWellFocusZeroWait(well) 忽略 well 恒读 well-1,autofocus 对非 well-1 用了偏 600~900 脉冲的错误 Z 起点。
  • 为何不本轮直接改:修复=把 control 的读改成 per-well(同 autofocustool),会立即改变 autofocus 的 Z 对焦定位行为(垂直电机轴=项目红线需谨慎的两轴之一)。值虽在安全区间(改动不会撞限位),但"per-well 起点是否真的让对焦更准"需跑受控 autofocus + 评估各 well 成像清晰度(理想需 well 内有可对焦内容)才能验证,属"不盲改对焦"。已备齐硬数据,留用户决策 + 受控验证
  • 核实:Commander 两文件 30 帧/方法名/地址直方图 diff 实跑;M-06 各 well 零点 raw 实读(舱8/舱9 共 32 次,值已记录);文档同步(待验证清单 M-06 行)。harness 在 gitignore 的 临时文件/,不入库。
  • 下一步:M 区无监督可闭环部分全部完成(M-01/02/03 去桩 + M-05 帧长回归修复 + M-07 验证 + 串口栈无其它回归核查)。需用户决策/受控时段的剩余项:M-04(存图落盘格式 vs 厂商 SavePic 等价性,需受控抓帧)、M-06(per-well 焦点零点已证真实,改 Z 对焦定位需受控 autofocus 验证)、延后专项(D2-02 调试页命令代理设计、D3-04 ComBin 两栈去重风险重构、整机开机自启复测需重启)。

2026-06-23 · M-06 修复:ReadWellFocusZero 按 well 读(TDD 集成层 red→green + 真机非破坏验证,对电机零影响)

  • 背景:接 Stop hook 续做"完成剩余工作"。重评 M-06——此前过度保守推给用户;经穷尽核查确认可自主安全闭环。
  • 缺陷定性:SerialChannelImpl.ReadWellFocusZeroWait(well) 忽略 well,底层 ComBin.ReadEEPROMvertMtStartPulseWait 硬编码 CreateReadEEPROMvertMtStartPulse(1) 恒读 well-1。builder 早支持 case 1-16(地址 0x08+4*(well-1),与 autofocustool 权威表一致)。调用方 HouseBin:1549/HouseDebugPageViewModel:1224 已传 well,只是被底层忽略。
  • 安全彻底排除(改前必查):消费方 control CalibrationEngine.CalibrateWell(well,hpos,eepromZ)——① 粗对焦 CoarseFocus固定中心 ZCoarseCenter=90000 扫描,eepromZ 实际未参与 Z 定位(只在签名/注释);② 即便参与,CalibrateWell每处 VerticalMoveTo 都包 ClampZ(ZMin=0,ZMaxPulse=125000,正是红线安全区)。→ 改 per-well 读对 autofocus Z 电机零影响、不可能越界。受益方=调试页(:1224 读+显示 per-well 焦点零点,修前恒显 well-1=真 bug)。
  • 真机只读诊断(无电机):各 well 焦点零点 EEPROM 真分槽且不同:舱9 79300~80200(3值)、舱8 74000~74600(5值),均在 [0,125000]。证 well-1 限制是真实缺陷。
  • 修复(最小,非破坏老调用):ComBin.ReadEEPROMvertMtStartPulseWait(custom, int well = 1) 加默认参 + 用 CreateReadEEPROMvertMtStartPulse(well);SerialChannelImpl.ReadWellFocusZeroWait 传真 well。SerialBin 两处舱级读不传 well→默认1→行为不变。
  • TDD:
    • 集成层 red→green(真机,经真实 SerialChannelImpl,纯 0x11 读无电机):harness 临时文件/FocusZeroVerify 读各 well——修前 RED:舱9 恒 80200、舱8 恒 74600(去重数=1=只读 well-1);修后 GREEN:舱9 [80200,80200,79800×4,79300×8,79800×2]=3值、舱8 5值,与 raw 抓包诊断逐 well 完全吻合
    • 单测护栏:新增 FocusZeroBuilderTests(18测:per-well 地址表 Theory 16 + 不同well不同地址 + well1完整帧),锁住 builder per-well 地址(修复依赖它);连同既有共 40 单测全绿
  • 核实:集成 red(全同)→green(per-well 各异匹配 raw 真值)真机实测;40 单测过;control sln + operate Release 双编译 0 错;codegraph sync 已跑;harness 在 gitignore 临时文件/
  • 下一步:M 区仅剩 M-04(存图落盘格式 vs 厂商 SavePic 等价性,需受控相机抓帧比对——两独立 native DLL,只能运行期逐字节对比);延后专项(D2-02 命令代理设计/D3-04 两栈去重风险重构/整机自启复测需重启)不变。

2026-06-23 · M-04 代码层定论存图等价(M 区 M-01~M-07 全闭合)

  • 背景:接 Stop hook 续做。M-04 此前 ◑(代码无害/落盘待受控抓帧)。穷尽代码核查后可定论,无需受控抓帧。
  • 核查:CameraImpl.SavePic(name,w,h) 丢 w/h 转发 Camera.SaveBmpPic(name)(托管,可读):建 this.width×this.heightFormat24bppRgb 位图 → Marshal.Copy(SourceBuffer)RotateFlip(RotateNoneFlipY)bitmap.Save(扩展名)
  • 等价定论(三点):① 朝向=RotateNoneFlipY,与权威 af ImageConverter逐字一致(af 明文注释:"相机原始数据上下颠倒,统一做 FlipY,保证显示/存图/算分同一朝向")→ canonical 正确;② 尺寸=相机原生 this.width/height(=基线调试页传的 ccdWidth/ccdHeight),故丢弃入参 w/h 正确(缓冲本就是原生尺寸,传任意 w/h 反而错);③ 位深=24bpp,与 SourceBuffer(w*h*3)一致。
  • stride 安全:SaveBmpPic 用整块 Marshal.Copy(非逐行),仅当 width*3 非4字节对齐才会错行;相机 width=1600(MVC2000),1600*3=4800 四字节对齐 → 无错行。
  • 为何不做受控抓帧:与不透明 native 厂商 MVCAPI.SavePic/Save2(Project2.dll #7)的逐字节一致既不可能(不同编码器永不产生字节相同的 JPEG/BMP)也无必要(调试页存图=人工目检产物,不入培养数据管线——真胚胎照走 HouseBin.SaveImage→Save2)。语义等价(尺寸/位深/朝向)已代码坐实且匹配权威 af。
  • 核实:SaveBmpPic/af ImageConverter 源码逐行比对;相机 width=1600 实读;基线调试页 camera.SavePic(name,ccdWidth,ccdHeight) 调用核对。文档:待验证清单 M-04 ☑ + §8.1 表 + 表头注。
  • 里程碑:合并遗留 M 区 M-01~M-07 全部闭合(M-01/02/03 去桩 + M-04 存图代码定论 + M-05 帧长回归 + M-06 按well零点 + M-07 网关)。
  • 下一步:剩延后专项(均超无监督自主范围):D2-02 调试页借串口完整驱动(需设计串口/相机命令代理大改面)、D3-04 ComBin 两栈去重(有风险重构)、整机开机自启复测(需真重启中断在跑 control)。建议按用户优先级开专项。

2026-06-23 · D1-10 control 侧 oplog 审计埋点迁移(= 昨日建议第3条,与 D3-04 删死栈解耦先做)+ 真机 red→green

  • 背景:用户 /goal「按工作计划把活先干完,再出昨日建议」。M 区已全闭合,工作计划剩三延后专项(D3-04 两栈去重含 D1-10 oplog / D2-02 命令代理 / 整机自启复测)。关键现实核查:当前无 control 在跑、无活体培养(唯一存活=3天前僵尸 operate 20268,不驱动硬件)→ 自由启停 control 真机验证不中断任何生物过程。故先攻价值最高且可自主安全闭环的 D1-10(control 审计埋点,正是昨日建议第3条·医疗合规级,纯新增不碰电机)。把 D1-10 审计埋点从 D3-04 解耦:本轮只做新增埋点,删 operate 死栈(有风险删除)仍属 D3-04。
  • 缺口:拆分后真正驱动硬件的是 control,但 control 子树零 OperationLogger 埋点(埋点都在 operate 已不驱动硬件的另一套 ComBin/Camera 死栈)→ 设备对培养环境真实物理动作审计缺失
  • 改动(8 改 + 1 新增,纯新增埋点·全 try 兜底·不改串口字节/时序/电机):
    • csproj×4:ControlHost/ivf_tl_Com/ivf_tl_CameraHelper/IvfTl.Hardware 加 ..\..\..\Aivfo.OperationLog(net6.0,兼容)ProjectReference。
    • ControlHost/Program.cs:InitControlOperationLog(Project=control,Kafka 取 App.config kfkaIP/kfkaPort=192.168.0.108:9092,topic=tl-oplog,ConfigFilePath=exe 同目录 oplog-config.json 热加载)+ 生命周期审计(进程启动即刻产·账号无关 / 采集启动成功·带 tlSn / 安全停机)+ SafeShutdown 先 Log 再 OperationLogger.Shutdown() flush。
    • ivf_tl_CameraHelper/Camera.cs:Init/UnInit 边界埋点(逐字镜像 operate 死栈已验 P3b,module=相机;字段仅用确定存在的 index/width/height/exposure/result,不臆造 NumBer)。
    • ivf_tl_Com/HouseBin.cs:换气 AirSwapOldFun / 补气 AerationNew 业务动作埋点(成功+失败两路,每会话一行、远离串口字节热循环,带 houseSn/tlSn/elapsed,module=换气/补气)。⚠ 踩坑:首次换气编辑的 old_string 贪婪吞下了下个方法签名 private void AirSwapNewFun() 致花括号失衡(204 错 CS0106/CS1022),补回签名即修复。
    • IvfTl.Hardware/Impl/SerialChannelImpl.cs:5 个 EEPROM 写(写排气阀/进气阀/灯光/扫描间隔/水平well位置)埋点,日志置 _ioLock(绝不持串口 IO 锁记日志),module=写EEPROM。
    • 新增 ivf_tl_ControlHost/oplog-config.json(模块 生命周期/相机/换气/补气/写EEPROM 默认全开,csproj <None CopyToOutputDirectory=PreserveNewest> 随 exe 部署)。
  • 真机 red→green(集成,108 oplog 管道在线:消费端 jar/Kafka9092/MySQL3306/gateway 全连通):
    • RED:直查 108 log.operation_log 按 project 分组——operate=883、control=0(管道通但 control 零埋点=功能缺失,RED 原因正确)。
    • GREEN:提权静默启动 control(pid=6488,tlSn=NEO-1-20230411,started:true,MQTT 连,舱7=37.31/舱9=37.25℃ 真温)→ project=control=70 行:生命周期3(进程启动/采集启动成功 output={"started":true}/安全停机)+ 相机68(结构化 input={"index":5,"width":1600,"height":1200,"exposure":400} output={"result":0})。/shutdown 口令 tl13579→200{ok:true}、安全停机行 flush 落库、/ping 不可达=干净退出+7 COM 释放。oplog-error 日志仅"配置已热加载"无错。
    • 未在本窗口触发(非缺陷·机制已证):换气/补气/写EEPROM 用与相机同一已证 OperationLogger.Log 机制且编译通过,但 HouseBin:670 注释「舱有培养记录才换气/拍照/对焦」——当前无皿空闲态不跑换气循环;写EEPROM 需调试页接通(D2-02)。放皿/调试接通即产行。
  • 核实:RED(control=0)/GREEN(control=70)真机直查;control sln(ControlHost)+ operate Release 双编译 0 错;既有 40 单测过;codegraph sync 已跑;临时 Q*.java/harness 在 gitignore 临时文件/
  • 下一步:工作计划续做 D3-04 删 operate 死串口栈(有风险删除,谨慎双验)、D2-02 调试页命令代理;之后回到昨日建议(control 看门狗 / HIL 回归套件 / 配置收敛 / 验证清零)。

2026-06-23 · D3-05 control 崩溃看门狗(= 昨日建议第2条 单点续命缺口)+ TDD + 真机 5 项验证

  • 背景:用户从昨日 6 条建议里选「control 看门狗」。缺口:operate→control 只一次性拉起(MainWindow_Loaded:66 登录后 Task.Run 跑一次 EnsureRunning,之后不再探活),control 自己崩了无人重拉,尤其 operate 关闭后 control 独立崩溃 = 直接培养中断。经 brainstorming/规划,用户拍三决策:① 独立 watchdog 进程;② DPAPI 缓存首次凭据;③ 受护栏 /shutdown 写停机标记区分"崩溃 vs 故意停"。并明确要求"能人工干净卸载"。
  • 实现(新增 3 工程 + control 2 处小改,纯新增·不动采集/电机):
    • control/ivf_tl_Watchdog.Core(net6.0-windows 类库):WatchdogArgs(CLI 解析)/RelaunchDecision.ShouldRelaunch(纯决策)/WatchdogPaths(数据目录+标志文件)/CredentialStore(DPAPI 加密往返,字段 Base64+'|' 连接避分隔冲突)。
    • control/ivf_tl_Watchdog(WinExe/requireAdmin/无窗口):单实例 Mutex Global\ivf_tl_watchdog_singleton + 命名停止事件 Global\ivf_tl_watchdog_stop + 探活循环(每 N 秒 /ping)+ 崩溃重拉(读 DPAPI 凭据 Process.Start 提权拉起)+ 退避(30s 冷却、连 5 次失败拉长 300s+告警)+ CLI(--pause/--resume/--stop/--install/--uninstall,自启走 reg.exe HKCU\Run)。control exe 同目录解析。
    • control/ivf_tl_Watchdog.Tests(xUnit,入 control sln)。
    • ControlHost Program.cs:RunStartupSequence Login 成功 → CredentialStore.Save(DPAPI)+ WatchdogPaths.SetStopped(false)(故意启动清标记);SafeShutdownWatchdogPaths.SetStopped(true)(受护栏停机写标记)。ControlHost 引 Watchdog.Core。
  • TDD red→green(17 单测):Args 各 flag、ShouldRelaunch 真值表(仅"不在+未暂停+非故意停+非退避"才 true)、CredentialStore DPAPI 往返(写后读==原值、密文不含明文123456、特殊字符密码也往返)。先 RED(NotImplemented 17 失败)→补实现→GREEN(17 全过)。
  • 真机 5 项全验(UAC 静默提权,当前无 control 在跑、无活体培养,可自由启停): ① 凭据缓存:control 登录后 C:\ProgramData\aivfo\watchdog\creds.dat=246 字节 DPAPI 密文,提权+非提权探针均能解密读回 admin/123456/C,明文不泄露。 ② 崩溃重拉(核心):control 跑(pidA)→看门狗"control 存活"→提权 taskkill 杀 control→看门狗"control 探活失败→已重拉 control.exe"→新 pidB、/status started:true 续命。 ③ 故意停不重拉:/shutdown 口令 tl13579→control 写 control.stopped→看门狗连续日志"为故意停机(受护栏 /shutdown),不重拉",control 保持停止。 ④ 暂停让路:--pause(建 watchdog.pause)→杀 control→看门狗不重拉→--resume(删标志)→重拉恢复(新 pid)。 ⑤ 卸载干净:--install --port=38080→自启项写入→--uninstall→自启项删空 + 常驻看门狗收停止信号优雅退出(进程数 0)。
  • 真机踩坑(关键,已写部署指南红线):首次手工部署只拷 exe+dllivf_tl_Watchdog.deps.json + runtimes/win/lib/net6.0/System.Security.Cryptography.ProtectedData.dll → 看门狗运行期加载根目录的非 Windows 占位 DPAPI stubPlatformNotSupportedException: DPAPI is not supportedCredentialStore.Load() 吞异常返 null → 日志"无缓存凭据"无法重拉。补全 deps.json + runtimes 后立即正常。结论:看门狗部署必拷 bin 全目录(含 deps.json + runtimes/);两 exe 各有自己的 deps.json 可同目录共存。靠加诊断日志(裸 Unprotect 记异常)定位,非猜。
  • 核实:17 单测 red→green 真跑;5 项真机实测(watchdog.log/进程数/注册表项/creds.dat 字节逐一实查);control sln + operate Release 双编译 0 错;SerialHelper 40 单测仍过;调试代码(DiagCredsLoad)已删;测试残留(进程/%ProgramData%\aivfo)已清;临时 CredProbe harness 在 gitignore 临时文件/
  • 下一步:D3-05 闭合。剩余方向(待用户定优先级):昨日建议 HIL 回归套件入库 / 配置收敛;工作计划 D2-02 调试页命令代理(大改面,解锁 D3-04 删死栈)/ 整机自启复测(需重启)。

2026-06-23 · 续:工作计划剩余项依赖/规模评估(D3-04 被 D2-02 阻塞 / D2-02 大改面定性 / D3-02 需重启)

  • 背景:D1-10 提交后续做工作计划剩余三延后专项,先评估各自能否自主安全闭环。结论:D1-10 是剩余里唯一可无监督安全闭环的;另三项各有真实阻塞,不宜本会话蛮干
  • D3-04(删 operate 死串口栈)被 D2-02 阻塞:grep 坐实 operate 死栈 ivf_tl_Entity/ComEntitys/*(ComBin/Channel/Commander/SerialBin…)+ CameraEntitys/*调试页 4 个 ViewModel(HouseDebugPageView.xaml.cs/BufferDebugViewModel/DebugCalibrationAdapter/HouseDebugPageViewModel)编译期引用。拆分后这套栈运行期死(operate HAL 空单例),但类型仍被调试页引用→ 不先把调试页改走 control 命令代理(D2-02),删栈必致 operate 编译失败。故 D3-04 必须在 D2-02 之后(任务依赖已登记)。
  • D2-02(调试页借串口完整驱动)= 真·大改面,需设计:HouseDebugPageViewModel(1592 行)经 _halLease.Serial/Camera(gate.Acquire(OperateDebug) 借用的与采集端同一物理句柄)驱动:① Z/水平电机 move/reset/forward/backward(红线两轴,十几处调用);② EEPROM 读写(M1-B2);③ LED 开关;④ StartPreview(hostControl,left,top,w,h) 贴 operate 窗口句柄的实时 USB 相机预览——拆分后相机 USB 句柄在 control 进程,无法跨进程把实时画面渲染进 operate 窗口,需重新设计帧传输(HTTP MJPEG 流 / 命名管道 / 共享内存),是独立硬子问题。完整 D2-02 = control 暴露 ~20+ 操作的命令代理 + operate 4 个 ViewModel 全改走 HTTP + 跨进程相机预览重构 + 红线电机真机受测。属多会话级设计+实现,设计文档自身标注"未细化的大改面"(spec §160/§178);非"本会话无监督蛮干"的任务——应先出设计(命令代理协议 + 相机预览传输方案)再实现。
  • D3-02(整机开机自启复测)需真重启:注册表方案已验(往返成功);真重启会终止本工作会话所在主机(Claude 即跑在 DESKTOP-HIB3N9D),且重启用户主机属"难以撤销/对外"动作,宜用户在场/点头时做。当前虽无活体培养(重启不伤生物过程),但仍不宜会话内自行重启。
  • 决策(对齐 /goal「按工作计划把活先干完,再出建议」):工作计划里可无监督安全闭环的部分已干完(D1-10);D2-02 需设计、D3-04 被其阻塞、D3-02 需重启——均非本会话可负责任自主完成。遂转入 /goal 第二段:向用户呈现昨日的战略建议(已被今日工作刷新:第3条 control 审计埋点=D1-10 已完成;第1条验证清零=D/M 项基本已清),并就 D2-02 设计 / 看门狗(昨日第2条,安全且可自主)等让用户定方向。
  • 核实:operate 死栈引用面 grep 实证(4 调试 ViewModel);D2-02 硬件调用面逐行枚举(电机/EEPROM/LED/StartPreview);spec §160/§178 复读。
  • 下一步:呈现建议 + 待用户选方向(D2-02 设计 / control 看门狗 / 其它)。

2026-06-23 · HIL 硬件在环回归套件入库(= 昨日建议「HIL 回归套件入库」)+ brainstorm/spec/plan + 真机验证

  • 背景:M 区全闭合、看门狗(D3-05)完成后,前序停在「待用户选方向」。用户选「HIL 回归套件入库」。缺口:M-01/02/03/05/06 是经真机验证的串口/EEPROM 行为修复,但当时的验证 harness 都在 gitignore 的 临时文件/、跑完即弃——没有入库资产能防这些修复被改回去;单测层只锁纯逻辑(帧长表等),锁不住真机端到端行为。
  • 流程(brainstorming→writing-plans→inline 执行):经 brainstorming 拍三决策:① 形态=xUnit 门控集成(非 console runner);② 覆盖=默认只读、写路径显式开关;③ 动态 Skip 用 Xunit.SkippableFact。设计文档 需求文档/specs/2026-06-23-HIL硬件在环回归套件-design.md + 实现计划 开发计划/2026-06-23-HIL硬件在环回归套件实现计划.md
  • 实现(纯新增工程,不动任何生产代码):新建 ivf_tl_operate_2.0/control/IvfTl.Hardware.HilTests(net6.0-windows,加入 control sln,ProjectReference IvfTl.Hardware,经真实 SerialChannelImpl 端到端):
    • Infrastructure/HardwareRigFixture.cs:扫 COM 口(跳 COM1/2)逐口 Open+ShakeHands 收集响应真舱(ChamberInfo{Port,HouseSn}),collection fixture 全套件构造一次;FirstChamberWithWells() 排除舱11。
    • Infrastructure/HilCollection.cs + AssemblyInfo.cs:[CollectionDefinition("HIL")] + [assembly: CollectionBehavior(DisableTestParallelization=true)](串行,防多测试抢同一 COM 口)。
    • FocusZeroHilTests(M-06):按 well 读焦点零点,断言去重>1 + 值∈[0,125000];FrameLengthHilTests(M-05):连读12轮断言全 sane;EepromWriteHilTests(M-01/02/03):写回环 [SkippableFact] 默认 Skip,仅 HIL_ALLOW_WRITE=1 才跑、写后立即恢复原值。
    • README.md:用途/怎么跑/Skip 语义/安全口径。
  • 真机踩坑(逐舱取证):首版写回环用固定 FirstChamberWithWells()(恒舱9),开写开关跑时M-03 灯光在舱9无项被动态 Skip→该命令永远得不到守护。改 RoundTrip 逐舱(排除11)找到能读到该项的舱再验(对齐原 EepromVerify 取证逻辑)——重跑后灯光自动落舱8 真验证。
  • 真机验证(UAC 静默提权;当前无 control 在跑、无活体培养,可自由跑):
    • 默认零写入:dotnet test → FocusZero/FrameLength 2 过(舱9 焦点零点 80200/79800/79300… 去重>1 与 raw 抓包诊断吻合;连读 12/12 干净),写测试 2 Skip
    • 开写开关:HIL_ALLOW_WRITE=1 dotnet test4/4 全过(排气阀舱9 200→201→200;灯光逐舱落舱8 500→501→500,与原 harness 证据一致),值已恢复原值。
  • 核实:真机两种模式实跑;control 全 sln + operate Release 双编译 0 错;既有 SerialHelper 40 单测过;codegraph sync 已跑(Already up to date);Xunit.SkippableFact 离线 restore 成功(未走回退)。僵尸 operate 20268 提权 taskkill 仍杀不掉(需重启清,符合既往记录),但未占舱口、不影响真机验证与编译。
  • 下一步:工作计划剩延后专项(D2-02 调试页命令代理=多会话级设计→解锁 D3-04 删死栈 / D3-02 整机自启复测需真重启)+ 昨日建议配置收敛。均需用户定优先级或受控/重启。

2026-06-23 · 配置收敛(operate↔control 连接组单一数据源 + operate 死键清理)= 昨日建议「配置收敛」+ brainstorm/spec/plan + 子代理驱动 6 任务 + 真机验证

  • 背景:用户选「配置收敛」。痛点(codegraph 坐实):双进程拆分后 operate App.config 与 control ControlHost/App.config 约 25 键逐字重复,control 那份注释明写「必须与 operate 手动同步」——换服务器/调参要改两处、漏一处两进程行为打架。核查厘清:① operate 的 AppData 不读那 12 个换气/CCD 键(合并单进程时代死副本,只 control 读)→ 该删;② 真正"两进程都读、漂移出 bug"的是连接组 7 键(urlIp/urlPort/mqttIp/mqttPort/kfkaIP/kfkaPort/outInter);③ operate 已有半成品「统一配置」UI(UnifiedConfigViewModel+AppConfigHelper,M5 治理)但只写 operate 自己 config = 缺口所在。
  • 流程(brainstorming→writing-plans→subagent-driven 执行):用户拍板:范围只 operate↔control;目标 = 单一数据源 + 清理死键;机制 = 方案一(共享片段 + <appSettings file=> 只读合并,写由 operate 收口)(选 file= 不选 configSource:前者支持 .. 上级路径,control 在子目录要指父目录);凭据组本轮不并入(避免动 control C#)。设计 需求文档/specs/2026-06-23-配置收敛-operate-control连接组单一数据源-design.md + 计划 开发计划/2026-06-23-配置收敛-实现计划.md。分支 feature/config-consolidation
  • 实现(6 任务,每任务两阶段审查 spec→质量):
    1. Task1 file=+.. 硬验证(临时 harness,gitignore):子目录进程经 <appSettings file="..\probe-shared.config"> 真机实跑读到父目录键 probeKey=HELLO、exit=0 → 方案一命脉坐实。顺带确认 .NET6 产物名 .dll.config、外部文件与 inline 合并共存。
    2. Task2 SharedConfigStore + operate 单测工程(TDD):新建 Helpers/SharedConfigStore.cs(XDocument 读写 appSettings 片段,Read(path,key)/Write(path,key,value))+ operate 首个单测工程 ivf_tl_Operate.Tests;red→green 6 绿(含 null/XML 转义,审查后补)。
    3. Task3 AppConfigHelper.Save 分流:加 SharedKeys(7 键 OrdinalIgnoreCase)+ SharedConfigPath(BaseDirectory\tl-shared.config);共享键落 SharedConfigStore、非共享键沿用 OpenExeConfiguration。读取侧零改。
    4. Task4 operate 接 file= + 删键:新建 ivf_tl_Operate/tl-shared.config(7 键,108 现值)+ csproj Content/PreserveNewest 拷到输出根 + App.config 接 file="tl-shared.config" 删 7 共享键 + 删 12 换气/CCD 死键(删前逐键 grep 坐实 operate 树零消费);保留 11 operate 独有键。顺带更正 AppConfigHelper 过时分层注释。
    5. Task5 control 接 ..\tl-shared.config:ControlHost/App.configfile="..\tl-shared.config" 删 7 共享键,保留 22 个 control 独有/业务键(换气/CCD 全留——control 真读)。C#/csproj 零改动
    6. Task6 真机 E2E + 回归:见下「真机验证」。
  • 真机验证(UAC 静默提权,无 control 在跑/无活体培养,可自由启停):
    • 部署布局:control 部署到 operate 输出根的 control\ 子目录;tl-shared.config 在 operate 根、control\ 下无副本。
    • control 读取坐实:提权启动 control → /status ServerUrl=http://127.0.0.1:10010/(由共享文件 urlIp+urlPort 拼成;control 子目录无此文件 → 只能经 ..\tl-shared.config 读到)。
    • 单一数据源生效:改共享文件 urlPort 10010→19999 重启 → /status ServerUrl 变 19999;改回 10010 重启 → 恢复。对称坐实 control 实际读的就是这一份。
    • 回归:operate 单测 6 绿 / SerialHelper 40 绿 / HIL 默认零写入 2 过 2 跳 / operate Release + control sln 双编译 0 错。control /shutdown(JSON body token=tl13579)干净退出释放 COM。
    • operate 外壳:受僵尸 operate 20268 占单实例 Mutex 门控起不来(已知、需重启清),未深究;读取机制与 control 同源(均 ConfigurationManager+file= 合并),据 control 实证判定 operate 侧读取同样成立。
  • 核实:6 任务每个经 spec 合规 + 代码质量两阶段子代理审查(独立读码/独立 grep/实跑核对);真机 /status 实读、单点改动对称验证、回归各项实际数字;工作区干净(取证改的 bin 共享文件已恢复)。提交链:spec f547ac9 / plan c9f1c70 / Task2 ca30cb2+8f3d096 / Task3 d687a3f / Task4 c3866440+199db15 / Task5 9235e10
  • 诚实边界:operate WPF 真外壳端到端(经 file= 读 + 登录 + 拉 control)受僵尸 Mutex 门控未现场跑通;连接变更走"改文件→重启进程"流程(重启读合并配置正确),未单独验"统一配置 UI 保存后本进程 RefreshSection 即时生效"(对连接键非常用路径,重启是现实流程)。凭据组未并入(独立小决策)。
  • 下一步:本分支待并 main。剩延后专项(D2-02 命令代理设计/D3-04 删死栈被其阻塞/D3-02 整机自启需重启)+ 凭据收敛(可选)。按用户优先级。

2026-06-23 · D2-02 调试页跨进程命令代理:brainstorm → spec → 第一阶段实现计划(代码未开工)

  • 背景:用户从剩余延后专项里选「做 D2-02 设计」。D2-02 = operate/control 拆分后,调试页(工程师调下位机参数用)够不着 control 进程内的 HAL lease,全部硬件操作(电机/EEPROM/阀/LED/读数/抓图/实时预览)断了,需改跨进程。主设计 §8 阶段2 留的大改面,spec §160/§178 标"未细化"。
  • 开机先发现一处文档偏差并纠正:旧断点写「feature/config-consolidation 待并 main」,但 git 实证那批 config 提交(d687a3f/c386644/9235e10/1020e22)早已在 main、该分支不存在 → 配置收敛已落地 main,"待并 main"系笔误,本轮已在断点纠正。
  • 流程(brainstorming skill):逐项澄清,与用户敲定 4 个关键决策——① 范围含相机实时预览;② 预览跨进程传输选 HTTP MJPEG 流(用户选,比轮询拉帧更流畅);③ 有活体培养时长时间调试不加业务护栏(与老系统一致,只靠监控页可见);④ 借用边界沿用现状(点【初始化】借、【卸载/返回】还)。
  • 用户两个关键追问,已写进 spec §5(安全地基):① operate 意外不还/还了没收到怎么办 → 租约+心跳+control端超时自动回收(走与正常归还同一路径),崩溃靠 MJPEG 断流快信号、丢消息靠幂等重试+TTL兜底,失效 sessionId 的命令一律拒(防抢串口);② 调试几小时 → TTL 只罚"失联"不罚"操作时长",心跳一直续就一直不回收。
  • 设计形态(spec):会话式借用(sessionId)+ 通用 /debug/command(op枚举)分发(非每操作一端点)+ MJPEG 预览 + 红线电机钳位放 control 端(水平[0,220000]/垂直[0,125000]越界拒绝不下发)。是 D3-04(删 operate 死串口栈)的前置
  • 产出:spec 需求文档/specs/2026-06-23-D2-02-调试页命令代理-design.md(14节,已提交 d5afcba) + 实现计划 开发计划/2026-06-23-阶段2-D2-02-调试页命令代理实现计划.md。计划按 Scope Check 拆 3 子阶段:①control后端(会话/分发/钳位/超时回收,纯 xUnit 单测 + curl 真机,bite-sized 完整 Task0-10)②MJPEG预览(提纲)③operate接入+真机V-012(提纲,解锁D3-04)。分支 feature/d2-02-debug-command-proxy
  • 核实:codegraph 实读改面(HouseDebugPageViewModel 全操作面/HouseGateImpl 借用闸门/CameraImpl.StartPreview=Usb2Start 贴HWND 跨进程做不到→改帧传输/ControlHttpServer switch路由/Program装配/ISerialChannel 54方法签名);spec 自查(无悬空TBD)+ 用户 review 通过;计划自查(对照 spec 覆盖、类型一致 DebugCommandResult/code串/Execute签名贯穿)。代码一行未写——本轮只到设计+计划。
  • 下一步:执行第一阶段 control 后端(建议子代理驱动逐 Task 实现,真机 curl 冒烟由 Claude 自主跑)。spec+计划(本分支)待并 main。

2026-06-23 · D2-02 第一阶段(control后端)批B 完成:DebugSessionManager 会话/超时/分发/红线钳位(TDD)

  • 背景:接批A(单测工程 IvfTl.ControlHost.Tests + 数据类 DebugSession/DebugCommandResult + 红线钳位 MotorClamp + 测试替身 Fakes/FakeHardware.cs)继续做安全核心。批B = 计划 Task4-7,全程严格 TDD(每 Task 先写失败测试→跑红→实现→跑绿),逐 Task 单独 commit。
  • 改动(新增源码 1 个 + 测试 3 处):
    1. Task4 新建 ivf_tl_ControlHost/Debug/DebugSessionManager.cs:注入 Func<int,IHouseGate>(按舱取闸门)+ Func<DateTime>(注入时钟,可纯单测)+ ttlMs + log。ConcurrentDictionary 会话表。Acquire(借闸门→gate.Acquire(OperateDebug)→失败返 BUSY、新建 sessionId)/Heartbeat(刷 LastSeen,失效返 SESSION_EXPIRED)/Release(TryRemove+Dispose,未知会话幂等返 Ok)。新测试 DebugSessionManagerTests.cs 4 绿。commit 968ad59
    2. Task5 安全地基超时回收:SweepExpired(LastSeen+ttl<now 自动 Dispose 归还)。追加 2 测试(超时回收后 IsCapturePaused=false + Heartbeat 失效;心跳续约保活)。关键踩坑见下。commit b7e8e40
    3. Task6 命令分发 Execute(sid, op, JObject args):会话校验(失效 SESSION_EXPIRED)+ switch 分发读数/握手/阀/LED(ReadTemp/ReadPressure/ReadDoor/ShakeHands/OpenLed/.../HouseVent),未知 op 经占位 ExecuteMotorOrEeprom 返 BAD_OP;catch 异常返 HARDWARE_ERROR。文件顶加 using Newtonsoft.Json.Linq;。新测试 DebugExecuteTests.cs 4 绿。commit cdc4976
    4. Task7【红线重点】 替换 ExecuteMotorOrEeprom 为真实电机/EEPROM 分发:VerticalMoveTo/HorizontalMoveTo 越界(MotorClamp.IsVerticalInRange 垂直[0,125000]/IsHorizontalInRange 水平[0,220000])返 OUT_OF_RANGE 且不下发串口;Forward/Backward 用 CurrentVer/CurrentHor 算相对目标后同样钳位;Reset 归零;WriteScanStep/WriteOpenIntakeTime/WriteOpenVentTime/WriteWellHorizontalPos 直发。追加 4 测试(在范围下发/越界拒绝不下发/相对越界/EEPROM写)8 绿。commit 5922797。
  • 踩坑(Task5):批A 的 FakeLease.Dispose() 只置 Disposed=true不触发 gate.ResumeCapture,导致 Sweep_Reclaims_After_Ttl_And_Resumes 断言 IsCapturePaused==false 失败(实跑 red:Actual=True)。按计划改 FakeLease 持 FakeGate 引用、Dispose(){Disposed=true;_gate.ResumeCapture();},并把 FakeGate.Acquire 内 new FakeLease(_serial,u)new FakeLease(this,_serial,u)。这对齐真实 HardwareLeaseImpl.Dispose 会调 gate 恢复采集。改后 6 绿。
  • 核实:每 Task 都贴了真实 red→green 输出。全量 dotnet test IvfTl.ControlHost.Tests = 25 绿 0 失败(Smoke1 + MotorClamp 10 + SessionManager 6 + Execute 8)。codegraph sync = Already up to date(监视器实时同步)。蓝本零偏离:核对 FakeSerial.Calls 记录格式(VMoveTo({p})/WriteScanStep({p})/Temp/OpenLed)、ISerialChannel 方法签名(WriteOpenIntakeTimeWait 第二参 bool 用默认)、批A 数据类字段(CurrentHor/CurrentVer 默认 -1)全对得上,照抄即编译0错+测试绿。
  • 8 个 commit(本分支):批A b4da856/e3fa590/ae80804/be88acf + 批B 968ad59/b7e8e40/cdc4976/5922797。
  • 下一步:批C = Task8 ControlHttpServer 加 /debug 路由(acquire/heartbeat/release/command 转 DebugSessionManager) + Task9 Program.cs 装配 DebugSessionManager(按舱取 gate 委托)+ 起 SweepExpired 看门狗定时器;再 Task10 真机 curl 冒烟(Claude 自主跑)。本分支待并 main。

2026-06-23 · D2-02 第一阶段【真机全过】+ C-1红线修复 + 批C + 登录排障始末 + 舱室故障隔离分析

  • C-1 红线修复(批B 审查发现,commit 91afb03):opus 审查揪出 Critical——相对运动(Forward/Backward)钳位 base 用会话跟踪位 CurrentVer/Hor(初值-1→fallback 0),真机电机在 120000 发 Forward 10000 时按 base=0 算 target=10000 放行,实际走到 130000 越 125000 红线。修为:钳位前回读真实物理位 ReadVerticalPositionWait/ReadHorizontalPositionWait 作 base + 成功后回读刷新(自愈漂移);顺带 motorDelay 透传 / Reset 加 ok 守卫 / Dispose 记日志。新增非零起点越界回归测试 red→green。
  • 批C(commit 7c43933 + b342374):Task8 ControlHttpServer 加可选参 DebugSessionManager + /debug/acquire|command|release|heartbeat 路由(状态码 acquire 200/409、heartbeat 200/410、command 按 code 410/400/200)+ ReadBody;Task9 Program.cs 装配 debugMgr(HardwareAccessLayer.GetHouseGate+DateTime.UtcNow+ttl10s)+ _exitEvent new 后起 TTL 看门狗(每3s SweepExpired)。Debug/Release 0 错,27 单测全绿
  • 11 个代码 commit(本分支):批A b4da856/e3fa590/ae80804/be88acf + 批B 968ad59/b7e8e40/cdc4976/5922797 + C-1 91afb03 + 批C 7c43933/b342374
  • 真机完整冒烟排障始末(Claude 自主,UAC 提权) 卡很久,根因全查实:
    1. 僵尸 operate 20268:用户以为重启了,但系统开机时间还是 6/21(开机2天半)、僵尸还在杀不掉(提权也拒绝)。但实测它不占 COM 口、不占 control 的 38080/Mutex,不挡 control。我起的 control 也提权、非提权 bash 杀不掉(需提权 taskkill)。
    2. control 登录失败→不扫串口→/debug 借到 lease 但 Serial=null→命令 NO_HANDLE
    3. auth 库 aivfo-auth.user 本零用户(全库唯一用户表,dump 只建表)。按用户要求插 admin:密码=md5(AUTH_SALT+123456+AUTH_SALT)=582de128a6d0050981bf90059ceeb2d9(CryptoUtils.encode 盐固定),deleted='2017-01-01 00:00:00'(BaseEntity @TableLogic 未删哨兵)。直连 /api/gateway/auth/login 返 success+token——用户没问题。无 mysql 客户端,用 JDBC(maven-repo mysql-connector 8.0.28+JDK11) 连 192.168.0.108:3306 root/root 直插(临时文件/DbSql.java)。
    4. 真因(非凭据):control 从原始构建目录 bin/Release/net6.0-windows/ 跑,dll.config<appSettings file="..\tl-shared.config">、urlIp/urlPort 配置收敛后只在共享文件;..\tl-shared.config(=bin/Release/tl-shared.config)不存在→urlIp 读空→BaseUrl 拼坏→登录发错地址。真实部署 control 在 operate 的 control\ 子目录、..\ 指 operate 根,所以没问题。修:把 ivf_tl_Operate/tl-shared.config copy 到 bin/Release/
    5. 修后:control 登录→ScanDevices(发现 2/4/6/7/8/9/11)→/debug 通真串口。
  • Task10 完整冒烟真机结果(舱6):借真 sid→ReadTemp 36.46℃/ReadPressure/ReadDoor/ShakeHands=6垂直越界130000 HTTP400实拒(不下发)/水平越界300000 HTTP400→heartbeat/release(旧sid 410)→再借不发心跳 14s 后 sid2 410=超时自动回收D2-02 安全核心真机端到端全过
  • 逐舱普查找坏舱(用户告知有2个坏舱):2/4/6/7/8/9 全握手正常、温度 36.18~36.49℃(都健康)、13:05日志相机init全0、DB house 配置正好7舱与扫描一致。非破坏性手段查不出哪2个——坏舱是功能性损坏(电机/相机/门),需电机走位(V-012)或 MJPEG 出图才暴露。
  • 舱室故障隔离分析(用户关切:单舱坏不拖垮别舱 + 双端必须提示) 源码逐行核实:
    • 运行期单舱坏:已隔离 ✓(每舱独立 HouseBin/ComBin/Channel/COM口/线程 + MainThread/StartSendCommandThreadwhile(true){try/catch},异常捕获记录、循环继续、别舱无感)。
    • 启动期:有缺口 ✗——舱"半坏"(串口活但相机坏致 CCDSN 不匹配 SerialBin.cs:252/舱号或CCDSN重复)→errorlist.AddInitTL 只要 errorList.Any() 就整体 return(StartMain.cs:89)→好舱也起不来。完全坏死/没接的舱则静默跳过(口打不开/握手失败 goto CC)。模块数≠11 已修成可继续。
    • 产出 spec 需求文档/specs/2026-06-23-舱室故障隔离与双端故障提示-design.md:启动期按舱容错 + 双端故障提示硬约束(operate监控页+front 都明确显示哪个舱/什么故障/时间,复用现有 alarm_data+MQTT 管道)。
  • 遗留环境:control 15840 仍在跑(提权,停需提权 taskkill);僵尸 operate 20268 仍需真重启清;admin/123456 用户已留库(用户要的,可逆);临时文件/ 下留 JDBC 工具 + 冒烟 ps1。
  • 下一步(用户已定 a+c):① 收尾提交 D2-02 第一阶段(本回写);② 拆"舱室故障隔离+双端提示"实现计划。D2-02 第二阶段 MJPEG 按需。本分支待并 main。