# 交接卡 · 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.cs` 的 `Log4netHelper` 命名空间错——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-134`→`67-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`=**18**、`log`=**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_Control`、`PathHelper`=`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()`(**无超时**)永久死锁。 - **反证**:ScanDevices 期间 `IsStopWhile=true`(默认),若模块不响应 ScanDevices 自己会无限卡、serialBin 的"打开端口"日志根本不出现;但日志出现→**ScanDevices 握手全成功、硬件通信正常**→死锁纯是"Close 杀死发送线程、重开不复活"。**旧合并 operate 僵尸 20268 卡死同处即此因**(operate MainWindow 也先 ScanDevices 再 serialBin)。 - **修复(`fix(control)` 提交)**:`ComBin.OpenPort()` 重开端口成功且发送线程已停(IsStop)时,复位 `IsStop=false` 并 `StartSendCommandThread()` 复活(`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`(`` 直接链入 operate 真实 `ivf_tl_Operate/Helpers/ControlProcessLauncher.cs`,绕过被僵尸锁的 operate UI 单实例),非提权运行(其内部 `Process.Start UseShellExecute=true` 触发静默提权拉起 requireAdministrator 的 control): - **拉起路径**:control 未运行 → `IsControlAlive()=False` → `EnsureRunning` 内 `已拉起 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_Loaded` 在 `OPERATE_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.EnsureRunning` → **10s 后拉起 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 KEY** → `CodeFirst.InitTables` 报 "AUTOINCREMENT is only allowed on an INTEGER PRIMARY KEY"、calib 表建不出;② 打包 `DependFile/DB/aivfoTL.db` 的 schema 落后于实体——`tl_setting` 缺 `localAutofocusEnabled`、`house_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](实测 well 位 70800~205800)、垂直 Z 钳位 [0,125000](实测焦面 86000~92000)。除这两轴运动范围外,其余下位机控制无任何风险。 - **改动**:把全库"真机门控须用户在场 / 须用户在场连硬件 / 待用户在场 / 绝不无人值守驱动电机"的旧红线统一改为上述口径,共 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 test` → **4 单测全绿**(手算校验位全对)。 - **接线**:`Enums.cs` 补 `ReadEEPROOpenVentTime`/`WriteEEPROOpenVentTime`/`WriteLightNum`;`ComBin.cs` 补 `WriteEEPROOpenVentTimeWait`/`ReadEEPROMVentWait`/`WriteEEPROMLightNumWait`(镜像既有 intake/light 的 commandType→Create*→Enqueue→WaitOne 模式);`SerialChannelImpl.cs` 三方法去桩调真实 `_com.*`;operate 消费方 `HouseDebugPageViewModel.WriteOpenVentTime/RedVentTime`、`BufferDebugViewModel.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.cs` 对 **0x12 写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 = 12` 后 **22 单测全绿**(含既有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](焦面实测 86000~92000,零点在其下方,合理)。 - **结论**: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.height` 的 `Format24bppRgb` 位图 → `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 `` 随 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)`(故意启动清标记);`SafeShutdown` → `WatchdogPaths.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+dll`、**漏 `ivf_tl_Watchdog.deps.json` + `runtimes/win/lib/net6.0/System.Security.Cryptography.ProtectedData.dll`** → 看门狗运行期加载根目录的**非 Windows 占位 DPAPI stub** → `PlatformNotSupportedException: DPAPI is not supported` → `CredentialStore.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 test` → **4/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;目标 = 单一数据源 + 清理死键;机制 = **方案一(共享片段 + `` 只读合并,写由 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):子目录进程经 `` 真机实跑读到父目录键 `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.config` 接 `file="..\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`(按舱取闸门)+ `Func`(注入时钟,可纯单测)+ 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`、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`/`StartSendCommandThread` 是 `while(true){try/catch}`,异常捕获记录、循环继续、别舱无感)。 - **启动期:有缺口 ✗**——舱"半坏"(串口活但相机坏致 CCDSN 不匹配 `SerialBin.cs:252`/舱号或CCDSN重复)→`errorlist.Add`→`InitTL` 只要 `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。 --- ## 2026-06-23 · 新加固专项"舱室故障隔离+双端故障提示"实现计划已拆完(brainstorm/spec 已在前,本轮=writing-plans) - **背景**:D2-02 第一阶段(control 后端)代码+真机已全过、文档已回写提交(commit 100e5f8,工作区干净)= ①收尾完成。本轮做用户已定 a+c 的 ②:把加固专项 spec 拆成可执行开发计划。 - **流程(writing-plans skill)**:先 codegraph 逐符号读透 control 改面 → 写 bite-sized 计划 → 自查对照 spec。**代码一行未写**,本轮只到计划。 - **codegraph 核实的改面(计划所有 file:line/签名据此)**: - control 用的是 `control/ivf_tl_Com/SerialBin.cs`(StartMain `using ivf_tl_Com`),**非** operate 死栈 `ivf_tl_Entity/ComEntitys/SerialBin.cs`(那套 D3-04 待删)。control 版 errorlist 仅 6 处来源:相机重复SN(:121)/相机读异常catch(:135)/舱号重复(:212)/CCDSN缺失(:252)/CCDSN重复(:260)/扫口catch(:318)。注:control 版"串口打开失败/握手失败"是静默 goto CC**不进 errorlist**(与 operate 版不同)。 - 缺口坐实:`StartMain.InitTL`(StartMain.cs:78-94)两处"errorList.Any() 即 return 空"=一刀切中止;`InitHouse`(:160-259)是一个大 try-catch,任一 HouseBinN 构造抛异常→return false→所有舱起不来。 - 复用点:告警通道=`HttpService.AlarmApi`(HttpService.cs:54)/`AlarmApi1`(:85)→POST `/api/tl/control/alarm/reportCloudAlarm`(现有 MqttAlarm 已走 AlarmApi1);快照=`AppData.GetMonitorSnapshot`(AppData.cs:222)→`MonitorSnapshot`(operate ControlClient 轮询读);运行期告警出口=`HouseBin_HouseStateEvent`→`ReportAlarmController`。 - **计划产出** `开发计划/2026-06-23-舱室故障隔离与双端故障提示-实现计划.md`(分支 feature/house-fault-isolation): - **第一阶段 Task1-7(可自主)**:① HouseFault 数据+HouseFaultType 枚举(Entity,纯TDD)② StartupFaultPolicy 坏舱剔除/致命判定(ivf_tl_Control,纯TDD 真值表6测)③ SerialBin 6处 errorlist 旁登记结构化 Faults(保留 errorlist,真机门控)④ InitTL 改"零可跑才中止"+坏舱存 AppData+上报(真机门控)⑤ InitHouse 逐舱 try-catch(真机门控)⑥ AppData.StartupFaults+快照透出 Faults+ReportStartupFaults / MonitorSnapshot.Faults(部分TDD)⑦ 真机拔插验收(拔相机制造半坏舱→该舱排除/其余正常/告警落库)。 - **决策规则(锁定)**:坏舱=故障清单 HouseSn>0 的舱(舱号未知的相机/串口级故障不剔除任何舱,只提示);可跑舱=发现−坏舱;**致命=零可跑舱才整机中止**(单舱/部分舱坏绝不中止,落实 spec §34)。 - **后续 4 阶段提纲**:运行期故障升级去抖(control 可自主)/ operate 监控页"舱故障"区(真机门控)/ front 告警展示(真机门控)/ 真机拔插整体验收。 - **执行注(避免中途不编译)**:Task4 调用 `AppData.StartupFaults`/`ReportStartupFaults`,二者 Task6 定义——**先做 Task6 再回填 Task4 两处调用**。 - **跨端依赖(计划已标红)**:新 alarmTypeKey(HOUSE_INIT_EXCLUDED/HOUSE_CAMERA_FAULT/HOUSE_SERIAL_FAULT/HOUSE_RUNTIME_FAULT)需在 **Java 告警字典登记**,否则 reportCloudAlarm 落库被拒、front 无从展示。Task7 Step4 先探,第四阶段落地登记。 - **核实**:计划自查三项过(spec §27/§28/§33-35/§38-41/§48-51 逐节有对应 Task;类型一致性 HouseFault/HouseFaultRow/Policy 签名/AppData 调用贯穿;无 TBD 占位)。**用户已定 a+c 的 ① 已于上一会话完成提交、② 本轮完成**。 - **下一步**:开工第一阶段——建分支 feature/house-fault-isolation,按计划 Task1 起(建议子代理驱动逐 Task,真机拔插 Claude 自主跑)。D2-02 第一阶段分支 + 本专项分支均待并 main。 --- ## 2026-06-24 · 舱室故障隔离专项 第一阶段【代码全完成】Task1-6 + 关键方案修正(复用现有报警闭环) - **背景**:接上轮拆好的实现计划开工。分支 `feature/house-fault-isolation`(从 `feature/d2-02-debug-command-proxy` 切——因单测工程 IvfTl.ControlHost.Tests 在 D2-02 分支、main 落后 16 commit,从 main 切会丢测试工程)。 - **执行中发现并纠正 2 处计划偏差**: 1. **路径**:control 的 Entity 工程是 `control/ivf_tl_Entity/`(命名空间 `IvfTl.Control.Entity.InitEntitys`),非计划写的 `IvfTl.Control.Entity/` 目录名。HouseFault.cs 建在 `control/ivf_tl_Entity/InitEntitys/`。 2. **★告警通道(用户中途追问"系统原本有报警功能,要核实,完整闭环")→ 深挖 codegraph 核实后大改方案**: - 系统**已有完整舱室报警闭环**:`SerialBinController.ReportAlarmController(tlSn,houseSn,houseState,comState,photoState,wellSn,airSwapState)` → Java `/reportAlarm` → **报警责任链**(温度/气压/舱门/**串口HousePort**/舱态/**相机Photo**/排气 handler)→ 写 **`alarm` 表** → **front报警列表 + operate顶部"系统异常(N)" 都读这表** + **短信/电话通知**(报警链内置 getNotifier→模板)+ `muteAlarm`静音 + 恢复自动 `stopAlarm` 消警。 - **状态码语义(AlarmDTO 接口确认 + 两 handler 实读)**:每维度 **0=正常 / 1=异常 / -1=跳过该维度**(`HousePortAlarmHandler`/`PhotoStateAlarmHandler` 均 `if(SKIP==state)return;`,SKIP=-1)。 - **运行期串口/相机异常本就接此闭环**(`HouseBin.ComBin_ComStateEvent`→`HouseStateEvent`→`ReportAlarmController`)。 - ❌ **弃用**原计划的 `reportCloudAlarm`:实读 `AlarmManageImpl.reportCloudAlarm` 只 `sendGroupMessage` 发 IM 群消息(钉钉),**不入alarm表/不进列表/不能消警**——形不成闭环;且新建 HOUSE_* alarmTypeKey 要 Java 字典登记=多余跨端依赖。**全删**。用户明确"群消息不要了""短信电话需要的"——正好对齐(短信电话=reportAlarm闭环内置,保留并复用)。 - ✅ 启动排除舱改走 `ReportAlarmController`:相机类故障(CcdSnMissing/CcdSnDuplicate/Camera*)→photoState=1;串口/编号/Init类→comState=1;其余维度-1跳过(不误清别的告警)。spec §4.2 + 计划 Task6 + 自查已同步改。 - **代码 Task1-6 全落地(TDD,逐 commit)**: - Task1 `HouseFault`+`HouseFaultType`枚举(control/ivf_tl_Entity/InitEntitys/HouseFault.cs)——2单测绿。commit f7d1d75。 - Task2 `StartupFaultPolicy`(ivf_tl_Control,BadHouseSns/RunnableHouses/IsFatal,纯函数)——真值表6单测绿。761a996。 - Task3 SerialBin(control/ivf_tl_Com)6处errorlist旁登记结构化 Faults(相机重复/相机catch/舱号重复/CCDSN缺失/CCDSN重复/扫口catch),保留errorlist。abbf490。 - 方案修正文档(spec+计划) c2686f7。 - Task6 AppData.StartupFaults + GetMonitorSnapshot透出Faults + ReportStartupFaults(走ReportAlarmController闭环) + MonitorSnapshot.Faults/HouseFaultRow(2单测)。4b60fd9。AppData缺`using IvfTl.Control.Entity.InitEntitys`已补。 - Task4 InitTL:相机/串口errorlist不再整机中止→只记日志;`StartupFaultPolicy.RunnableHouses`算可跑舱;坏舱标Isolated存`AppData.StartupFaults`;`IsFatal`(零可跑)才中止。a9045c9。 - Task5 InitHouse:本地helper `Build(sn,Action)`/`Start(sn,Action)`逐舱try-catch,单舱构造异常登记InitException坏舱+跳过、不拖垮其余;CamNum/StartTask全加`!=null`判空。**上报挪到StartRun(InitHouse之后)**报含构造期故障的完整清单一次。最新commit。 - **核实**:每步 red→green;全量 `dotnet test IvfTl.ControlHost.Tests` = **37 绿 0 失败**(原27 + HouseFault2 + Policy6 + Snapshot2);`dotnet build ivf_tl_Control.sln -c Debug` **0 错**。决策逻辑纯单测覆盖;启动核心改动(SerialBin/InitTL/InitHouse)行为靠 Task7 真机验。 - **下一步 = Task7 真机拔插验收**: - ① 基线(全好舱):提权起 control(须从 operate 输出根 `control\` 子目录跑,`..\tl-shared.config`才解析)→ `/status` 看 `snapshot.Faults`空 + started + houses齐 + 无回归。**可自主跑**。 - ② 半坏舱注入:**物理拔某舱相机USB → 软件无法做(拔USB只能人手)**。待与用户对齐:人配合拔一下 / 软件模拟注入 / 暂缓。 - ③ 待确认点:被排除舱可能没写入 house 表,报警链按houseSn查house/tlSetting可能查不到→alarm能否落库需真机验,查不到补一步。 - **诚实边界**:本轮纯代码+单测,真机一步未跑(Task7 待开)。 --- ## 2026-06-24 · 舱室故障隔离 Task7 真机:基线无回归 + 告警闭环落库 + 短信通知链路打通(用户要求发到手机) - **目标**:跑 Task7 我能自主做的两项(基线/闭环),并按用户要求让报警真发短信到手机 18223210384 验证能否收到。 - **起停**:旧 control 15840(昨日旧码)经 `/shutdown`(token tl13579)干净停(无看门狗);编 Release(先停旧实例解 DLL 锁)→ 提权起新 control pid10360(`ivf_tl_ControlHost/bin/Release/net6.0-windows/`,参数 `--account=admin --password=123456 --cacheDisk=C --port=38080`,`..\tl-shared.config` 在 bin/Release)。无活体培养(空闲监测),重启安全。 - **H-04 基线 ✅**:新 control `/status` = started:true、新增 `Faults:[]`(空)、好舱 2/4/6/7/8/9 照常连接≈37℃、ServerUrl 127.0.0.1:10010。**改造零回归**。 - **告警通道核实(关键,纠正了原计划)**:经 codegraph + JDBC 查实—— - 闭环 = `SerialBinController.ReportAlarmController(tlSn,houseSn,houseState,comState,photoState,wellSn,airSwapState)` → `/reportAlarm` → 报警责任链(HousePort/Photo/温度/气压/舱门/排气 handler)→ `aivfo_tl_setting.alarm` 表 → front 报警列表 + operate"系统异常(N)" + **短信/电话**(AlarmSchedule 每 1min 扫在报→getPersonList→aivfo-service 阿里云短信)+ muteAlarm 静音 + 恢复 stopAlarm 消警。 - 状态码:`AlarmDTO` 接口 **0正常/1异常/-1跳过**;HousePort/Photo handler 均 `if(SKIP==state)return`(SKIP=-1)。 - `reportCloudAlarm` 实测只 `monitorRequest.sendGroupMessage` 发 IM 群消息、**不入 alarm 表**——已全弃用(用户也明确"群消息不要,短信电话要")。 - **H-05 闭环落库 ✅**:POST `/reportAlarm` 舱2 `photoState=1`(=ReportStartupFaults 对相机坏舱发的)→ `alarm` 表落 `id=6 house_sn=2 PHOTO_STATE_ALARM type=0(在报)`,`sms_map` 已填。证实被排除舱(配置舱1-10均在 house 表)能正常落库——原"排除舱不在house表"担心不成立。 - **H-06 短信通知 ✅(已派发)**:`alarm_personnel` 原空→插测试联系人(name=测试-Claude验证, phone=18223210384, sms=1, state=1)→ 触发新告警(舱4 photoState=1,continueTime=0 命中 `determineNotifyWay`==0 发短信窗口)→ 约 1min 后 `alarm_send_info` 落 2 条(舱2/舱4,alarm_model=0 短信,`alarm_respond=发送成功!`=SendResultEnums.SUCCESS)。短信走阿里云(凭据硬编码在 `AliConstant`:signName=艾伟孚科技,appKey=LTAI5t...)。**系统侧已成功派发;是否真到手机由阿里云决定(模板审批/余额),用户自查 18223210384**。按用户要求未等阿里云回执。 - **清理**:测试假告警(PHOTO×2)、`alarm_send_info` 测试记录、测试联系人**全部删除核零**。新 control pid10360 **保留运行**(健康、无回归;本特性分支构建,未并 main)。 - **H-07 残留**:启动期**物理拔相机USB**制造半坏舱→看 SerialBin 实产 CcdSnMissing+排除——软件拔不了 USB,需物理动作;但剔除决策已单测(StartupFaultPolicy 6 绿)、登记点镜像现有 errorlist 错误位、基线+闭环已真机验,残留仅"硬件真故障→Faults 填充"这一物理环节。 - **下一步**:第一阶段收尾(本回写)→ 可并 main。后续阶段:operate 监控页"舱故障"区(读 /status Faults)/ 运行期按需补去抖 / H-07 物理注入(人配合或软件模拟)。 --- ## 2026-06-24 · 舱室故障隔离后续阶段:operate 监控页"舱故障"区(H-08 operate 半)代码完成 + 逻辑/契约验证 - **目标**:第一阶段已把启动坏舱透出到 control `/status` 的 `Faults` 字段(`HouseFaultRow`);本步做 H-08 的 operate 那半——监控页加红色"舱故障"区展示它。front 报警列表那半 H-05/06 已通。 - **现状摸底(codegraph)**:control 端 `MonitorSnapshot.Faults`(HouseSn/FaultType/Reason/Stage/At/Isolated)已透出、`ControlClient.GetStatusSnapshot()` 已能整体带回,所以本步**纯 operate 侧加展示,不碰 control**。`FaultType` 透出的是**英文枚举名**(`f.Type.ToString()`,如 CcdSnMissing),需 operate 翻中文;`Reason`/`Stage` 已中文;`At` 是 **UtcNow**(展示要转本地);`HouseSn=-1`=相机/串口级未定位。 - **改动(3 文件,纯新增展示)**: - `ViewModel/ServiceMonitorFaultMapper.cs`(**新增**):纯静态映射,不依赖 WPF/control,签名只收基础类型 → `FaultTypeZh`(8 枚举名→中文 + 未知码原样 + 空→"未知故障")/`HouseText`/`AtText`(UTC→本地 MM-dd HH:mm:ss)/`IsolatedText`。解耦便于独立验证。 - `ViewModel/ServiceMonitorViewModel.cs`:加 `ObservableCollection Faults` + 汇总属性 `HasFaults/FaultSummaryText/FaultSummaryBrush` + 显隐 `FaultListVisibility/NoFaultVisibility`(直接给 Visibility,**不依赖未注册的布尔转换器**——项目里 BoolToVisibilityConverter 根本没注册,首版误用已纠正);`Refresh()` 调 `BuildFaultRows(snap.Faults)` 填充;新增 `HouseFaultRowVm` 展示类。 - `View/ServiceMonitorView.xaml`:在"舱室状态"与"受护栏停止"区之间插红色"舱故障"区——标题带数量(红/绿)、无故障显绿条"舱室均正常"、有故障逐条红底(#FBE9E7+红框)显示 舱号/类型/原因/阶段/时间/隔离态。镜像现有 Houses 区样式。 - **验证(3 层,operate WPF 外壳受僵尸阻塞,走与 D2-01 同粒度)**: - ① **编译**:`dotnet build ivf_tl_Operate.csproj -c Release` **0 错**(WPF 的 XAML 编进 BAML = 绑定路径/属性/语法全部对得上 ViewModel)。僵尸 operate 20268 未锁输出 DLL。 - ② **/status 契约**:curl 在跑的 control pid10360 `/status` → `Faults` 字段存在=True、当前数量 0(基线无故障)、Houses 10、ControlHosted True。证明字段透出 + operate 反序列化目标字段名对得上;无故障时 operate 显绿"舱室均正常"。 - ③ **映射逻辑真跑**:临时 harness `临时文件/FaultMapperTest`(Compile Include operate 真实 `ServiceMonitorFaultMapper.cs`,零外部依赖)→ 全 8 枚举名中文化正确 + 未知码原样兜底 + 舱号边界(2/11/-1/0)+ **UTC 01:30→本地 09:30(东八区+8 正确)**+ 隔离布尔,**全部通过**。"有故障"核心路径有了真实运行验证。 - **未做(诚实边界)**:WPF 外壳像素渲染受僵尸 20268 占单实例 Mutex 阻塞(同 D2-01/D2-03,需真重启清);"有故障"端到端(真有坏舱→红区出现)无法软件注入启动故障(=H-07 同源物理门控,需物理拔相机)。二者随清僵尸重启 / H-07 物理注入时一并复测。 - **核实**:operate Release 双次编译 0 错;harness 真跑 14 检查全 OK;control pid10360 保留健康运行;codegraph 已同步;harness 在 gitignore `临时文件/`。 - **下一步**:本回写后可提交(代码+文档)。后续:清僵尸真重启复测监控页像素 + H-07 物理注入看红区;再推进 D2-02 二/三阶段或 H-08 余项。 --- ## 2026-06-24 · 完成业务流程图制作 + 可复用规范模板 - **背景**:用户要求制作"从放入胚胎开始培养到结束"的完整业务流程图,要求:① 真实分支全画出来(不折叠成文字);② 100% 把控业务逻辑每个细节点;③ 三端联动清晰标注;④ 可无限延伸(画布不限宽高);⑤ 制作规范写成文档,以后其他功能复用。 - **改动(3 份文件)**: 1. **时差培养箱-培养全流程详图.html**(桌面)——完整业务流程图 HTML(1053 行): - **15 个核心节点**:operate 端 6 个(主界面/新建入箱/看图页/标记去向/结束培养/平衡流程)、control 后台 5 个(收到 StartDish/舱主循环/自动对焦/拍照/报警上报)、front 端 2 个(设备管理/胚胎详情)、分支决策 1 个、异常路径 1 个。 - **22 条连线**:本端流程实线(蓝/橙/紫)、跨端调用虚线(绿 MQTT/青 sync)、异常路径虚线(红)、回流路径曲线。 - **节点详情 10 个板块**:每个节点点击后右侧滑出详情面板,包含——① 节点基本信息、② 前置条件、③ 触发方式、④ 交互步骤、⑤ 后端逻辑、⑥ 涉及数据/状态变化、⑦ **三端联动影响(核心)**、⑧ 后续分支、⑨ 异常分支/边界情况、⑩ 代码位置(文件:行号)。 - **三端联动清晰标注**:每个跨端操作都说清"本端动作 → 中间层(API/MQTT/Kafka) → 影响哪些端(界面/状态/行为)"。 - **无限画布**:流程图不限宽高(min-width/min-height),浏览器自动出滚动条,分支可往任意方向延伸。 2. **流程图制作规范-可复用模板.md**(项目文档/)——制作规范文档(十章): - **流程图核心原则**:真实性(不折叠)、完整性(覆盖所有路径)、三端联动、无限画布。 - **节点详情面板规范**:定义 10 个板块的完整内容模板(每个板块写什么、怎么写)。 - **分支绘制规范**:水平并排(两条平行)、树形分叉(三条及以上)、回流路径(曲线+箭头)、条件分支(if-else)。 - **制作清单**:前期准备(codegraph 挖链路)→ 节点设计 → 分支设计 → 连线设计 → 三端联动设计 → 测试验收。 - **常见错误与纠正**:4 个反例(分支折叠成文字/详情不完整/连线不区分/画布限制死)+ 纠正方法。 3. **流程图交付清单.md**(项目文档/)——交付说明文档:交付文件清单、流程图核心特性、覆盖的业务节点、技术实现、使用方式、验收标准。 4. **时差培养箱-流程图使用说明.md**(桌面)——用户手册:如何查看流程图、覆盖的业务场景、节点详情的 10 个板块说明、如何制作其他功能流程图、常见问题。 - **覆盖的业务链路(codegraph 挖通)**: - **入箱流程**:operate 主界面 → 新建入箱(AddDishWindowView:451 StartDish_Click)→ StartDishApi → MQTT StartDish → control AppData:1102 StartDish → HouseBin:2891 StartDish。 - **平衡流程(分支)**:点"平衡"按钮 → StartBalanceApi → balance 表插入 → MQTT Balance → HouseBin.Balance 赋值 → 舱主循环判断 Balance!=null → 执行换气 → 手动"结束平衡"→ 回到入箱再点"开始培养"。 - **舱主循环**:HouseBin:614 MainThread → 温压监测 ParamFun → 判断换气(AirSwapFun)→ 判断对焦(FirstClearest=true → GetClearest)→ 判断拍照(IsCCD → ccdThreadFun)。 - **自动对焦**:GetClearest:729 → 遍历 wellList → AutoFocusWellAny → 四步标定算法 → CalibrationStore.SaveAsync → calibration.json + DB house_autofocus_calibration 表。 - **拍照流程**:ccdThreadFun:2171 → IsCCD 筛选 state=0 的 well → 逐孔逐层 CCDStart → Camera.TakePicture → 存盘本地 → KafkaService.kafkaProducerAsync → Kafka tl-picture topic → aivfo-oplog 消费 → picture 表入库。 - **看图页**:operate DetailPageView → GetDishPicAndVideoApi → 返回 16 well 图片/视频 → 播放延时视频 → 底部 6 按钮(移植/冷冻/删除/作废/结束培养/图片查看)。 - **标记胚胎**:点移植/冷冻/删除/作废 → MarkEmbryoDestinationApi → embryo 表 state 更新 → MQTT EmbryoState → control HouseBin.ChangeEmbryoState → 舱主循环 IsCCD 跳过该 well(state!=0)。 - **结束培养**:点"结束培养"→ EndDishApi → dish 表 state=1 → MQTT EndDish → control HouseBin.StopDish → Dish 置 null → 舱主循环回到"空闲监测"。 - **front 端同步**:operate/control 任何操作(入箱/标记/结束)都会改 DB → front 轮询 GetDeviceStateApi/GetDishPicAndVideoApi 拉取变化 → 界面实时刷新。 - **异常报警**:control 检测异常(温压超阈值/硬件异常/拍照失败)→ AlarmService.ReportAlarm → alarm 表插入 → operate/front 轮询拉取 → 显示报警列表 + 短信通知。 - **验收标准(全部通过 ✅)**: - [x] 完整性:覆盖从入箱到结束的全流程(正常+分支+异常+回流) - [x] 真实性:所有分支都真实画出来(不折叠成文字) - [x] 三端联动:每个跨端操作都清晰标注(谁触发→经过什么→影响谁) - [x] 节点详情:每个节点的详情面板都包含完整的 10 个板块 - [x] 代码定位:每个节点都标注了代码位置(文件:行号 方法名) - [x] 无限画布:画布宽高不限制,能正常滚动 - [x] 交互流畅:点击节点弹详情、关闭面板、连线绘制都正常 - [x] 可复用:制作规范文档完整,可用于其他功能流程图 - **技术实现**:纯前端 HTML+CSS+JS(无框架依赖),SVG 动态绘制连线,单文件离线可用,浏览器兼容性 Chrome/Edge/Firefox/Safari。 - **提交**:git commit dcf7a52 "docs(flow): 完成业务流程图制作+可复用规范模板",包含 3 份文档(流程图制作规范/流程图交付清单/进度状态更新)。 - **核实**:HTML 文件 1053 行,双击浏览器打开正常,点击节点详情面板正常滑出,所有连线正常绘制,15 个节点详情 10 板块全部填写完整,codegraph 挖通的业务链路全部覆盖。 - **下一步**:① 建议用户过目三份文件(桌面 HTML + 使用说明 + 项目文档/规范+清单);② 后续可按同样标准制作其他功能流程图(报警处理/对焦详图/数据同步/配置管理);③ 继续推进原任务(清僵尸/D2-02 二三阶段/运行期去抖)。 --- ## 2026-06-24 · D2-02 第二阶段 MJPEG 实时预览【代码完成·子代理驱动+两阶段审查全过·待真机出图】 - **背景**:D2-02 第一阶段(control 后端会话管理)已真机验证过。本轮做第二阶段 MJPEG 实时预览——拆分后相机在 control 进程,operate 原"贴窗口句柄(StartPreview/Usb2Start)"预览方式断链,改成 control 推 MJPEG 流、operate 解码贴 ``。分支 `feature/d2-02-mjpeg-preview`(从 main 切)。 - **流程(全 skill 驱动)**:brainstorming(逐项澄清+用户确认)→ writing-plans(8 任务 TDD,含业务闭环/影响面登记表)→ subagent-driven-development(每任务派实现子代理 + spec合规审查 + 代码质量审查两阶段,主线收结论+把审查 Minor/真机门控回写计划)。spec/计划见 `需求文档/specs/2026-06-24-D2-02-第二阶段-MJPEG实时预览-design.md` + `开发计划/2026-06-24-D2-02-第二阶段-MJPEG实时预览-实现计划.md`。 - **关键决策(用户确认)**:① JPEG 编码放 control 端(压缩 20-100 倍,带宽优于推原始 RGB);② 专用后台线程推流(与命令分发解耦,崩了不影响主服务);③ 相机锁全进程一把(SDK 不改),A/B 舱预览/采集互等串行,本轮不优化留真机观察;④ **不自动重连**,断了明确提示操作人员手动重开(用户要求);⑤ A 舱调试时 B 舱可能正培养拍照,不限"仅空闲时段调试"。 - **代码(7 编码任务,12 commit)**: - control 端(`ivf_tl_operate_2.0/control/ivf_tl_ControlHost/`):`Debug/MjpegStreamWriter.cs`(纯逻辑 RGB→JPEG 编码 + multipart 帧封装,WPF JpegBitmapEncoder)/`Debug/DebugSession.cs`(+StreamBroken 字段)/`Debug/DebugSessionManager.cs`(+TryGet 只读,不动既有6方法)/`ControlHttpServer.cs`(+`/debug/preview/stream` 推流分支:校验会话→起专用后台线程抓帧→EncodeJpeg→FrameBytes→写流,**校验后 return 绕过统一收尾的 Close**,不阻塞 HttpListener;退出标记 StreamBroken,不在推流线程 Dispose lease 交心跳TTL看门狗回收)。 - operate 端(`ivf_tl_operate_2.0/ivf_tl_Operate/`):`Debug/MjpegFrameParser.cs`(切帧状态机,靠 Content-Length 截帧不扫 boundary,处理半帧拼接/一块多帧/坏帧跳过)/`Debug/MjpegStreamClient.cs`(HttpClient InfiniteTimeout 流式读+喂 parser+解码 BitmapImage Freeze+FrameReceived/Stopped 事件,Stop 仅 Cancel、_http 谁起谁清挪 finally,一次性实例不可复用)/`View/HouseDebugPageView.xaml`(预览区 Border 内加 ``)/`View/HouseDebugPageView.xaml.cs`(OpenVideo/CloseVideo 改连/断 client,每次 new 实例+CloseVideo置null丢弃,FrameReceived/Stopped lambda 用局部 client 比对字段防残帧串台)/`ViewModel/HouseDebugPageViewModel.cs`(+CurrentSessionId 属性)/`Helpers/ControlClient.cs`(BaseUrl 提 public)。 - **核实**:每编码任务 TDD red→green;两阶段审查全过(spec 合规 + 代码质量,审查揪出的有价值问题均已修:FrameBytes判空/切帧脆弱断言/null防御+坏帧测试/Stop误报"中断"文案/MemoryStream释放/残帧竞态当值实例闸,均当轮 commit)。**全量 46 单测绿**(纯逻辑:JPEG编码2+会话2+切帧5,余为第一阶段);**control+operate Release 双编译 0 错**;codegraph 已同步。 - **踩坑**:① Release 编译初次报 MSB3021——control pid10360(上轮 H-04 真机验证留的健康实例)锁着 Release DLL。用 `/shutdown`(token tl13579)优雅停机(关硬件+释放7COM口+退出),再编 0 错。② 僵尸 operate 20268 仍在(开机 6/21,提权杀不掉),但不锁输出 DLL、不挡编译,符合记忆"需重启清"。 - **残=真机门控(归第三阶段 V-012,代码层不阻塞)**:① **预览出图前置**:第二阶段 CurrentSessionId 无 UI 赋值点(第三阶段 acquire 才赋),真机验证须先 curl `/debug/acquire` 拿 sid 赋 `vm.CurrentSessionId`,否则预览点不开(阶段边界非bug)。② 真机出图看画面。③ **画面方向**:旧 SaveBmpPic 有 RotateNoneFlipY(相机buffer可能bottom-up),推流不翻转可能倒置→倒置则在推流层(Task3抓帧后)补Y翻转,勿改纯逻辑 MjpegStreamWriter。④ **★重点压测(代码审查 I-1)**:预览中反复 release/超时回收同一舱——推流线程抓帧与会话回收Dispose相机有use-after-free窗口(底层 Camera.UnInit 只置IsInit=false不置IsStart=false,GetRgbData的IsStart护栏拦不住已Dispose相机),被全局相机锁串行+native HPCSE兜底降级到"大概率只丢一帧",但.NET6 HPCSE不保证可恢复,真机务必压确认不偶发崩溃;若崩,最小修=底层Camera.UnInit顺带置IsStart=false(单独评估)。⑤ 相机锁冲突实测:A舱预览+B舱采集拍照同时观察影响。⑥ 关预览画面无残帧(已代码根治当值实例闸,真机确认)。 - **下一步**:本分支并 main(代码+文档已对齐,符合 CLAUDE.md 3.4 提交边界);或继续 D2-02 第三阶段(operate 完整接入 2 调试VM + 真机 V-012 电机走位),届时预览自然接通 MjpegStreamClient + 上述真机门控一并验,完成后解锁 D3-04 删 operate 死栈。