续接载体之一。每完成一步或暂停,在末尾追加一段:
## 日期 时间 · 一句话标题,下列「改动/核实/踩坑/下一步」。只追加,绝不覆盖。 新任务(2026-06-22 启动)。旧任务(M0-M8 合并改造)交接卡随旧文档清空,本卡为新任务重起。
项目文档/ 下旧文档(00总纲/需求文档01-14/开发计划归档/历史报告),为新任务腾空。需求文档/control-逻辑与配置全景.md。
需求文档/specs/2026-06-22-operate-control-双进程拆分-design.md(9章)。开发计划/2026-06-22-阶段1-control独立进程骨架.md。ivf_tl_ControlTest(csproj=ivf_tl_ControlMain)= 合并前 control 独立 exe,但 Window1 启动骨架已被 operate 复刻吸收、MainWindow 是纯测试、StopWindow 是死窗,命名混乱(三命名空间)。结论:不改造,阶段3 退役删,新 control 启动器基于干净的 ivf_tl_Control 类库新建。00-需求总览.md(新总纲);全景移入需求文档/、阶段1计划移入开发计划/;续接三件套(进度状态.yaml/工作计划表.md/本卡/待验证清单/进度数据.js)按新任务重写;CLAUDE.md 引用改到新体系。application-local.properties 里 jna.lib-path/video 路径写死成 D:\WorkSpace 开发机路径→改本机 + 重编译,DLL 加载成功、10030 通);起了本机微服务集群(gateway 等 6 服务,oplog 原在跑)。#if DEBUG 把地址覆盖到 207 外网,真机验证须用 Release。临时文件/ 基准 ↔ 现有合并版)、不依赖 git,完整复核合并改动与文档完整性。SerialChannelImpl 返回桩值):排气阀时间写(:130 return false)/读(:137 return -1)、缓冲瓶灯光写EEPROM(:143 return false)、调试页存图(CameraImpl:148 丢宽高转 SaveBmpPic 未验证)。另有写EEPROM"成功=true"不可靠等待验证项。需求文档/操作端逻辑与配置全景.md(operate 全景:启动时序/业务模块逐功能/8个 operate↔control 直连点/HTTP 接口全表/凭据加密/配置全键/§八 合并降级登记/后台线程/上线前清理项/拆分结论)。待验证清单.md 新增"合并遗留·operate 侧"区(M-01~M-07)。CLAUDE.md/00-需求总览.md/工作计划表.md/进度状态.yaml 里"M0-M8 已全部结项"为"代码完成、真机验收整体未做、有降级遗留";三处文档地图挂上 operate 全景。AppData.cs:91-111 #if DEBUG 覆写到 test-gateway 外网)——真机/排障必须用 Release。临时文件/)、合并版 operate、front、108 数据库,全面核对 项目文档/ 全部文档的完整性/全面性/滞后性/合理性,只认源码+数据库,不看 git 历史。comm -23 空)、对焦核心算法逐字保留(仅命名空间改 + 硬件面换 HAL)、同名程序集已改名(ivf_tl_Control_Entity/Services)。log.operation_log 19 列含 CLAUDE.md 列出的全部关键列、aivfo_tl_setting 配置表(tl_setting/house/house_well_setting + 对焦扩列)齐。开发计划/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 处)。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"不建表"同步订正。67-134=0、8 表,DependFile=0、不自动建表/需预置不建表=0;ControlHost 块无错误命名空间、operate 块保留正确命名空间。bufferBottlerPressureMin+10(源码无 +10);完整性小缺口:OperateHwTest(218 行控制台测试 Exe,不在主 sln)、IvfTl.AutoFocus.Tests(游离工程)均无文档登记;front oplog-config.json 实在 ivf_tl_Manage/ 非"front 根";start-all.sh 头注释路径写"临时文件/"实在"开发环境/"。CLAUDE.md 的问题并修正。逐条用源码/108 数据库核对(非 git)。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"正确。项目背景与上手指南.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总纲应对齐"。kfkaIP/kfkaPort 行;订正"front 无 Kafka/oplog 接入"为"front 有 oplog 接入"(附 App.config/App.xaml.cs 证据);§一 Kafka 行"业务里怎么连"由"operate"改"operate/front"。连接配置清单 §三 旧结论"front 无 Kafka/oplog"与源码相反——典型的文档滞后于代码;已订正。系统业务流程详图.html 背景段未点明"三项目"具体是哪三个、也没在背景段提示"上一个任务是半成品"。核实:§1.1 只讲 operate+control"两个独立进程",AutoFocusTool 要翻到 §7.1 才出现;§0 程序表列 operate/control/front,易被误读成"三项目=operate+control+front"(实则 front 从未合并)。系统业务流程详图.html:
临时文件/ 下。aivfo_tl_setting=18、log=2(非服务器测试环境.md 旧写的 17/1——两条 migration 已补执行);operation_log 19 列与 CLAUDE.md 一致。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",已升级为明确前置。/goal 要求按计划 TDD 一次性做完阶段1,真机已连,Claude 自主完成全部测试验证(不找用户配合点击/起停进程)。建 feature 分支 feature/control-independent-process,子代理驱动 Task1-6,Claude 亲自驱动 Task7 真机。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 根标签笔误已按计划提示修正)。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 传递可达);逐字给定代码一次编译过、零成员臆造。ControlProcessLauncher(探活/ping→不在则 Process.Start -Verb RunAs 拉起→轮询就绪)+ MainWindow 内嵌 StartRun 段(旧 63-132)替换为 EnsureRunning 调用 + App.config 加 controlPort/controlExePath。Release 编译 0 错误(Debug 被残留进程锁,改用 Release——亦真机连本地中间件正确配置)。ConsentPromptBehaviorAdmin=0=管理员静默提权,故 Claude 可 Start-Process -Verb RunAs 自主拉起 requireAdministrator 的 control/operate、自主提权 taskkill,全程无需用户点 UAC/起停进程。网关 10010=200、6+java 微服务在线、7 COM 口实测全 FREE(僵尸 20268 不占硬件)。App.config(operate 业务键+连接键,构建转 ivf_tl_ControlHost.dll.config——.dll.config 是 .NET6 正确约定,operate 亦然);Release 构建,DependFile(ccd 7 DLL/DB/newccd)经 ivf_tl_Control 传递拷贝全落地。/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()——即此缺陷之活证。.dll.config 而非 .exe.config 才是 .NET6 apphost 读取名。③ 串口握手 hang 是合并真机验收欠账(M 区同源:HAL/SerialChannelImpl 链路),阶段1"零改 control 业务"不含修复。待验证清单 D1-07/D1-08)。选项:(A) 开专项任务修 HAL 借用 ComBin 双重握手(可解锁全闭环,但属 control 业务逻辑改动、有真机电机风险,需用户拍板破"零改"约束);(B) 维持现状,串口死锁与 M-01~M-07 一并纳入"合并真机验收"专项。建议先重启清掉僵尸 20268 再做任一选项的最终闭环复测。HAL.ScanDevices()(HardwareAccessLayer.cs:178-219)对每口握手后 finally: ch.Close()(:217)。SerialChannelImpl.Close()(:50-58)里 _com.IsStop = true。ComBin 发送线程 while(true){ if(IsStop) return; ...}(ComBin.cs:126)→ IsStop=true 令发送线程永久退出,且 OpenPort() 原不复活它。serialBin.Start()(经 InitTL)借用同一缓存 ComBin(SerialBin.cs:195 HAL.GetSerial(0,port).RawComBin)、直接 OpenPort() 重开(返回True)再 ShakeHandsWait 入队握手 → 发送线程已死无人出队 → ShakeHandsWait(ComBin.cs:314)taskAutoResetEvent.WaitOne()(无超时)永久死锁。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(同路径)。/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。DBServiceImpl.StartDbService.InitTables 每启动报 SQLite Error 1: AUTOINCREMENT only allowed on INTEGER PRIMARY KEY(某表 CodeFirst 建表失败)+ DBUpdateTLInfo 本地写失败;control 仍可运行(读本地培养记录成功),影响限该表本地持久化。建议专项修。ServiceDishAndBalanceData 接口返回失败=无皿时服务器无培养记录、回退本地,正常非缺陷。临时文件/LauncherTest(<Compile Include> 直接链入 operate 真实 ivf_tl_Operate/Helpers/ControlProcessLauncher.cs,绕过被僵尸锁的 operate UI 单实例),非提权运行(其内部 Process.Start UseShellExecute=true 触发静默提权拉起 requireAdministrator 的 control):
IsControlAlive()=False → EnsureRunning 内 已拉起 control.exe→轮询→control 就绪 → 返回 True、IsControlAlive()=True。IsControlAlive()=True → "control 已在运行,直接连接" → 返回 True、PID 不变、进程数恒 1(未拉第二个)。EnsureRunning 已全路径实跑。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 自主检测缓冲瓶低压并上报)。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,闭环不受影响。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。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 错误。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) 不发串口)。/serial/pause houseSn=2→舱2 CapturePausedByGate=true 且 COM4 停发(让路,不驱动电机)→ resume 恢复;/shutdown 错口令 403、对口令 tl13579 安全停机(进程退出 + 7 COM 口全释放)。6 单测仍过。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 错误。GetStatusSnapshot 往返反序列化 10 舱(真温 37℃+三块);SerialPause(2)→快照 House2 Paused=true→SerialResume,跨进程借串口让路实证。gate.Acquire(OperateDebug) 借同进程 HAL 同一物理句柄驱动(HouseDebugPageViewModel:256,_halLease.Serial/Camera)。拆分后 operate 进程 HAL 是空单例、拿不到 control 持有的串口/相机——要在拆分下让调试页驱动,需 control 暴露串口/相机命令代理(逐操作:电机移动/读写EEPROM/LED/相机预览…一个大代理面,当前设计文档未细化)或端口让渡。这是独立子任务,且驱动电机受安全红线(§178 需用户在场)。本阶段交付让路契约(/serial/pause|resume,已验)作基础;调试页完整驱动 = 需设计(命令代理)+ 受监督真机验。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 错误。开发环境/双进程部署指南.md——两产物(operate 全目录 + control 放 operate 的 control/ 子目录)、control 必带 dll.config+DependFile、本地 HTTP 契约(/ping /status /shutdown /serial 端口 38080)、装机自检清单、已知遗留。部署布局已由 operate WPF 真外壳 E2E 实证(operate 即从 control/ivf_tl_ControlHost.exe 拉起)。ivf_tl_Entity/ComEntitys/ComBin,带 OperationLogger)与 control(ivf_tl_SerialHelper/ComBin,真驱动)两套串口栈。拆分后 operate 已不驱动串口→operate 那套栈成运行期死代码;control 操作不进 operation_log(oplog 埋点在 operate 栈,=D1-10)。去重=动串口代码的有风险重构,属收尾不阻塞功能,列延后专项(需设计 oplog 收口归属 + 受控验证),不做无监督风险重构。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 隔离)。临时文件/相关参数.html(用户自测的下位机控制参考值,仅供参考,实际安全范围比文档更宽):水平钳位 0,220000、垂直 Z 钳位 0,125000。除这两轴运动范围外,其余下位机控制无任何风险。待验证清单.md(红线)、specs/...双进程拆分-design.md(§8 计划头 + §9.5 真机门控)、开发计划/...阶段1...md(关键现实约束 + Task7 头)、项目背景与上手指南.md(开工方式)、工作计划表.md(执行方式)、系统业务流程详图.html(§13 降级登记 + §14 路线图 lead + §14.1 阶段1说明 + 开工 li)。SerialChannelImpl 返桩,最适合 TDD(字节编码纯逻辑)。临时文件/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),调试页写排气阀时间/读排气阀时间/缓冲瓶写灯光未真正下发下位机。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)。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 错误。临时文件/EepromVerify(console,ProjectReference IvfTl.Hardware,经真实 SerialChannelImpl 端到端,非走单测桩),对真机做非破坏性回环:读 V→写 V+1→读确认→写回 V→读确认。control 未跑时端口空闲、harness 直接 Open+ShakeHands(复刻 HAL.ScanDevices 模式)。
临时文件/ 已 gitignore(harness 不入库);codegraph sync 已跑。#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。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 表述。Write*Wait 阻塞收回复即 true,不校验真实成功(基线 operate 同样无条件 true,非合并回归)。本轮 M-01~03 真机验证时印证了帧错位现象:CustomProtocolLength 对 0x12 写设回包长 6、对 0x11 读设 10,写后紧接读会因残留字节帧错位污染(无排空时偶现垃圾值/null,加间隔即消失)。改为校验写回包状态字 = 改动活动写路径、有风险(误判会破坏正常写),需真机逐字节定位 0x12 实际回包格式再动,列后续受控专项。CameraImpl.SavePic(name,w,h) 忽略 w/h 转发 _camera.SaveBmpPic(name),底层从相机自身 SourceBuffer 取帧(自带尺寸)→丢弃入参 w/h 无害;但落盘格式/旋转/位深 vs operate 基准 MVCAPI.SavePic(buf,w,h,name) 的等价性需一次受控抓帧核对。当前相机正被 control 用于活体培养成像,无监督抓帧可能干扰在运行的成像,不宜无监督进行,留受控时段验。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 掩盖、并误记为"非回归")的根因。Protocol.ReplyLength 也写 6 但它根本没有 0x12 写命令(抄来的未验证默认);control=6。逻辑上 operate 真机写过 EEPROM(若 12 错、硬件只回 6 则每次写都卡等 12 字节,不可能出货)→ 强指向 12。但有分歧必须实测,不猜。临时文件/FrameLenProbe,裸 SerialPort 9600 8N1,DataReceived 事件收包,整窗累加计数;非破坏=写回刚读到的原值):
BytesToRead 轮询/阻塞 Read 均抓 0 字节,改用与可用成帧 Channel 一致的 DataReceived 事件收包才有数据;② CreateORC 覆写数组末位占位字节而非追加,我起初给握手/读帧多塞 1 个 0x00 致帧长字段[3]与实际不符、下位机判非法不回复——去掉多余字节后正常(握手5字节[3]=05、读9字节[3]=09、写12字节[3]=0C)。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 错。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)。临时文件/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 错。receivedBuffer[lenght-2] 状态字检查落到正确位置[10]。Write*Wait 仍"收回复即 return",未把状态字作 bool 成功传回调用方(=M-05"成功语义传播",基线 operate 同样无条件 true,非合并回归)。临时文件/ 已 gitignore(3 个 harness 不入库);codegraph sync 已跑。文档已同步(待验证清单 M-05 + §八 + 进度状态.yaml + 进度数据.js + 本卡)。ivf_tl_SerialHelper/Util/Commander.cs vs operate 黄金基线 临时文件/.../ivf_tl_Entity/ComEntitys/Commander.cs——30 个静态命令帧逐字节完全一致;方法名清单一致;全部参数化 builder 的 command.Add(0x..) 地址字节直方图一致。结论:串口命令层仅 CustomProtocolLength 0x12 一处回归(已修),无其它静默错字节。临时文件/FrameLenProbe ⑤ 段,纯 0x11 读,无电机):按 autofocustool 权威地址表(well1=0x08 步进4,well16=0x44)逐 well 读 Z 焦点零点——
ReadWellFocusZeroWait(well) 忽略 well 恒读 well-1,autofocus 对非 well-1 用了偏 600~900 脉冲的错误 Z 起点。临时文件/,不入库。SerialChannelImpl.ReadWellFocusZeroWait(well) 忽略 well,底层 ComBin.ReadEEPROMvertMtStartPulseWait 硬编码 CreateReadEEPROMvertMtStartPulse(1) 恒读 well-1。builder 早支持 case 1-16(地址 0x08+4*(well-1),与 autofocustool 权威表一致)。调用方 HouseBin:1549/HouseDebugPageViewModel:1224 已传 well,只是被底层忽略。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)。ComBin.ReadEEPROMvertMtStartPulseWait(custom, int well = 1) 加默认参 + 用 CreateReadEEPROMvertMtStartPulse(well);SerialChannelImpl.ReadWellFocusZeroWait 传真 well。SerialBin 两处舱级读不传 well→默认1→行为不变。临时文件/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 单测全绿。临时文件/。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)一致。SaveBmpPic 用整块 Marshal.Copy(非逐行),仅当 width*3 非4字节对齐才会错行;相机 width=1600(MVC2000),1600*3=4800 四字节对齐 → 无错行。MVCAPI.SavePic/Save2(Project2.dll #7)的逐字节一致既不可能(不同编码器永不产生字节相同的 JPEG/BMP)也无必要(调试页存图=人工目检产物,不入培养数据管线——真胚胎照走 HouseBin.SaveImage→Save2)。语义等价(尺寸/位深/朝向)已代码坐实且匹配权威 af。camera.SavePic(name,ccdWidth,ccdHeight) 调用核对。文档:待验证清单 M-04 ☑ + §8.1 表 + 表头注。/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。..\..\..\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 部署)。log.operation_log 按 project 分组——operate=883、control=0(管道通但 control 零埋点=功能缺失,RED 原因正确)。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 日志仅"配置已热加载"无错。HouseBin:670 注释「舱有培养记录才换气/拍照/对焦」——当前无皿空闲态不跑换气循环;写EEPROM 需调试页接通(D2-02)。放皿/调试接通即产行。临时文件/。MainWindow_Loaded:66 登录后 Task.Run 跑一次 EnsureRunning,之后不再探活),control 自己崩了无人重拉,尤其 operate 关闭后 control 独立崩溃 = 直接培养中断。经 brainstorming/规划,用户拍三决策:① 独立 watchdog 进程;② DPAPI 缓存首次凭据;③ 受护栏 /shutdown 写停机标记区分"崩溃 vs 故意停"。并明确要求"能人工干净卸载"。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)。Program.cs:RunStartupSequence Login 成功 → CredentialStore.Save(DPAPI)+ WatchdogPaths.SetStopped(false)(故意启动清标记);SafeShutdown → WatchdogPaths.SetStopped(true)(受护栏停机写标记)。ControlHost 引 Watchdog.Core。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 记异常)定位,非猜。%ProgramData%\aivfo)已清;临时 CredProbe harness 在 gitignore 临时文件/。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 之后(任务依赖已登记)。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);非"本会话无监督蛮干"的任务——应先出设计(命令代理协议 + 相机预览传输方案)再实现。