Просмотр исходного кода

docs(阶段1): 闭环最终实证回写(operate→control真实代码实跑+数据入库DB铁证+D1-10订正)

- D1-01/D1-05 升级为真实代码实跑(harness 链入 operate ControlProcessLauncher:拉起/复用/续命路径全验证)。
- D1-07 数据入库 DB 铁证:108 库 house_collect(tl_sn=NEO-1-20230411/temperature=37℃真温)+alarm_data 新鲜入库。
- D1-10 订正:control 子树零 OperationLogger 埋点,oplog 收口在 operate 另一套 ComBin/Camera 栈,归阶段3 两栈去重。
- 续接三件套+进度数据.js 全对齐。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
huangjie 3 дней назад
Родитель
Сommit
e382e6d42b

+ 18 - 0
项目文档/进度/交接卡.md

@@ -136,3 +136,21 @@
   3. 完整业务数据入库(胚胎照片)需物理放皿 + operate UI 操作(无皿、operate 被僵尸锁),超当前自主可测范围与 stage1 进程拆分范围;环境数据走 MQTT 管道已连通。
 - **核实**:/status 实测、RunRecord/HouseComRecord 实读、netstat 连接实查、operation_log 直查(最新停在 06-21 23:57 僵尸卡死前,control 自主监控不产 oplog 属正常)。修复提交 + codegraph sync 完成。
 - **下一步**:阶段1 进程拆分 = **代码完成 + 真机闭环打通**(D1-07/08 通过)。剩余:① 清僵尸 20268(需重启)后复测 operate 端完整链路;② D1-09 SQLite schema bug 专项;③ M-01~M-07 合并降级专项;④ 阶段2(监控补全/借串口/受护栏停止)拆计划。建议合并到 main + 推送。
+
+---
+
+## 2026-06-22 · 闭环最终实证:operate→control 真实代码实跑 + 数据入库 DB 铁证
+
+- **背景**:进一步穷尽自主手段补齐两处缺口——operate 端链路此前仅"机制层"、数据入库未实证。不依赖用户重启。
+- **operate→control 真实代码实跑(集成测试)**:建 harness `临时文件/LauncherTest`(`<Compile Include>` 直接链入 operate 真实 `ivf_tl_Operate/Helpers/ControlProcessLauncher.cs`,绕过被僵尸锁的 operate UI 单实例),非提权运行(其内部 `Process.Start UseShellExecute=true` 触发静默提权拉起 requireAdministrator 的 control):
+  - **拉起路径**:control 未运行 → `IsControlAlive()=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 拆计划。

+ 11 - 9
项目文档/进度/待验证清单.md

@@ -10,22 +10,24 @@
 
 | 编号 | 验证项 | 门控 | 状态 |
 |------|--------|------|------|
-| D1-01 | operate 启动后能拉起独立 `ivf_tl_ControlHost.exe`(管理员静默,不弹 UAC) | 运行 | ◑ 机制验证通过 |
+| D1-01 | operate 启动后能拉起独立 `ivf_tl_ControlHost.exe`(管理员静默,不弹 UAC) | 运行 | ☑ 真实代码实跑 |
 | D1-02 | `http://127.0.0.1:38080/ping`、`/status` 返回 JSON | 运行 | ☑ |
 | D1-03 | control 独立进程真机硬件获取(6相机SN读到/7 COM口 True) | **真机** | ☑ |
 | D1-04 | **operate 关闭后 control 进程仍在驱动**(核心目标·结构性独立) | 运行 | ☑ |
-| D1-05 | 重开 operate 复用已在跑的 control(不重复拉起) | 运行 | ◑ 机制验证通过 |
+| D1-05 | 重开 operate 复用已在跑的 control(不重复拉起) | 运行 | ☑ 真实代码实跑 |
 | D1-06 | 单实例:手动起第二个 control 发现 Mutex 已占自退(进程数仍为1) | 运行 | ☑ |
-| D1-07 | **control 完整采集闭环(started:true / tlSn / 真机自控环运行)** | **真机** | ☑(修死锁后) |
+| D1-07 | **control 完整采集闭环 + 数据入库(started:true / 真机自控环 / 落库)** | **真机** | ☑(修死锁后·DB实证) |
 | D1-08 | **serialBin/HAL 借用ComBin重开不复活发送线程致串口握手死锁** 修复 | **真机** | ☑ 已修复并真机验证 |
-| D1-09 | control 本地 SQLite 建表 schema bug(预存,非死锁) | 运行 | ✗ 待修(见下) |
+| D1-09 | control 本地 SQLite 建表 schema bug(预存,非死锁) | 运行 | ✗ 待修 |
+| D1-10 | control 硬件操作不进 operation_log(oplog 埋点在 operate 的另一套栈) | 运行 | ✗ 归阶段3(两栈去重) |
 
 > **2026-06-22 真机验证实测说明(D1-xx 详情见交接卡同日段)**:
-> - ☑ 项均在 108 微服务集群在线、真机连接下,由 Claude **静默提权(UAC `ConsentPromptBehaviorAdmin=0`)自主拉起 control.exe** 实测,全程无需用户配合点击/起停进程。
-> - **D1-07/D1-08 闭环达成(修死锁后)**:修复 `ComBin.OpenPort` 复活发送线程(提交见交接卡)后,control 独立进程 `/status` = `{"ok":true,"pid":22252,"tlSn":"NEO-1-20230411","started":true}`;RunRecord 越过握手→仓室信息→E方数据→设备基础数据;`house*-HouseComRecord` 恢复产出,真实串口收发:`[COM4]Temperature Rec:5E 86 02 09 0F D6`、`[COM11]DoorStatus`、`[COM3]BufferBottlePressure/Aeration`——温度/压力/门/缓冲瓶换气**自控环在真机运行**;control→gateway 10010 + MQTT 1883 连接 ESTABLISHED。
-> - ◑ D1-01/05:operate 单实例 Mutex(`App.xaml.cs:36` "ivf_tl_Operate")被遗留僵尸 operate(PID 20268,卡死不可杀,需重启清)占着,无法拉起全新 operate;故 operate→control 路径以**机制层**验证(`EnsureRunning`:`/ping` 探活返回真→"直接连接"不重拉;`Process.Start -Verb RunAs` 静默提权拉起已实证)。**死锁修复同样惠及 operate**(operate MainWindow 走同一 ScanDevices→serialBin 路径;清僵尸+重编 operate 后即享修复)。
-> - ✗ **D1-09 预存 SQLite schema bug(非死锁、非进程拆分引入)**:control `DBServiceImpl.StartDbService.InitTables` 每次启动报 `SQLite Error 1: 'AUTOINCREMENT is only allowed on an INTEGER PRIMARY KEY'`(某表 CodeFirst 建表失败),连带 `DBUpdateTLInfo` 本地写失败(SqliteErrorCode:1)。control 仍可运行(读"本地培养记录"成功),影响限于该表本地持久化。属 control DBService 合并遗留,建议专项修(定位带 AUTOINCREMENT 的实体列改为 INTEGER PRIMARY KEY)。
-> - 旁注:`ServiceDishAndBalanceData 接口返回失败`=无皿时服务器无培养记录,control 回退本地,属正常(非缺陷)。
+> - **D1-01/D1-05 真实代码实跑(非机制层)**:编译运行 operate 端真实 `ControlProcessLauncher.EnsureRunning`(集成测试 harness `临时文件/LauncherTest`,`<Compile Include>` 链入真文件):① control 未运行时 `IsControlAlive=False → 已拉起 control.exe → 轮询就绪 → True`(拉起路径);② control 已运行时 `IsControlAlive=True → "已在运行,直接连接" → True、PID 不变、进程数恒 1`(复用路径)。harness(operate 代理)退出后 control 仍在 = **续命**亦由真实拉起路径实证。**唯一未跑** = operate WPF 外壳(登录窗→MainWindow),因僵尸 20268 占 operate 单实例 Mutex,但其调用的拉起逻辑已实跑验证。
+> - **D1-07 数据入库闭环 DB 实证**:control 运行期(20:19 起)直查 108 `aivfo_tl_setting` 库:`house_collect` 20:18 后新增 22 行、`alarm_data` 新增 270 行;抽样实读:`house_collect` = `tl_sn=NEO-1-20230411, house_sn=2..9, temperature=37.16/37.46℃(真实箱体温), 多点温度, house_door=0, create_by=admin_admin, create_time=20:29`;`alarm_data` = `house_sn=11 PRESS alarm`(control 自主检测缓冲瓶低压上报)。**闭环:control 读真机传感器 → MQTT/服务器 → 108 库入库,实锤。**
+> - ☑ 项均 108 集群在线 + 真机连接、Claude **UAC 静默提权**自主完成,全程无需用户配合点击/起停进程。死锁修复同样惠及 operate(同 ScanDevices→serialBin 路径)。
+> - ✗ **D1-09 预存 SQLite schema bug**(非死锁/非拆分):`InitTables` 报 `AUTOINCREMENT only allowed on INTEGER PRIMARY KEY`,某表建表失败,control 仍运行(读本地培养记录成功),影响限该表本地持久化。
+> - ✗ **D1-10 oplog 缺口(归阶段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(control 自己串口栈无埋点)。归阶段3 两栈去重一并处理。control 诊断走 `RunRecord/HouseComRecord` 文件日志(本次定位全程靠它),业务数据入库走 MQTT,**闭环不受影响**。
+> - 旁注:`ServiceDishAndBalanceData 接口返回失败`=无皿时服务器无培养记录、回退本地,正常非缺陷。
 
 ## 阶段2 · 监控补全 + 调试借串口 + 受护栏停止(待阶段2拆计划后补全)
 

+ 12 - 11
项目文档/进度/进度数据.js

@@ -1,10 +1,10 @@
 // 实时面板数据源(监控面板.html 读 window.PROGRESS_DATA)。每推进一步更新本文件。
 window.PROGRESS_DATA = {
   project: "operate/control 双进程拆分",
-  generatedAt: "2026-06-22 20:10",
-  phase: "阶段1 · control 独立进程骨架(代码完成·真机闭环打通,待并 main)",
-  currentTask: "Task1-7 全过;D1-08 串口握手死锁已修复,真机 started:true、温压门换气自控环运行、闭环打通",
-  note: "用户选A方案,修复 ComBin.OpenPort 复活发送线程死锁(HAL借用ComBin重开不复活),真机 red→green 验证通过。剩:清僵尸20268后复测operate端+D1-09 SQLite专项+M区降级专项+阶段2拆计划。",
+  generatedAt: "2026-06-22 20:35",
+  phase: "阶段1 · control 独立进程骨架(代码完成·端到端闭环全实证,待并 main)",
+  currentTask: "Task1-7全过+D1-08死锁修复;operate→control真实代码实跑(拉起/复用/续命)+数据入库DB铁证(house_collect/alarm_data)",
+  note: "用户选A修死锁打通闭环。harness跑operate真实ControlProcessLauncher验证拉起/复用/续命;108库house_collect(37℃真温)+alarm_data新鲜入库实证。剩:operate WPF外壳实跑(僵尸门控/重启)+D1-09 SQLite+D1-10归阶段3两栈+M区+阶段2/3拆计划。",
   milestones: [
     { name: "阶段1 · control 独立进程骨架", tasks: [
       { id: "Task1", name: "新建 ivf_tl_ControlHost 项目骨架", status: "☑" },
@@ -13,24 +13,25 @@ window.PROGRESS_DATA = {
       { id: "Task4", name: "内嵌 HttpListener(/ping /status)", status: "☑" },
       { id: "Task5", name: "Program.cs 完整启动序(Mutex+启动序+HTTP驻留)", status: "☑" },
       { id: "Task6", name: "operate 改为拉起独立 control", status: "☑" },
-      { id: "Task7", name: "[真机]端到端验证(起/连/续命/单实例/采集自控环)全过", status: "☑" }
+      { id: "Task7", name: "[真机]端到端验证(起/连/续命/单实例/采集自控环/数据入库)全过", status: "☑" }
     ]},
     { name: "阶段2 · 监控补全+借串口+受护栏停止", tasks: [
       { id: "阶段2", name: "待阶段1合并后拆计划", status: "☐" }
     ]},
     { name: "阶段3 · 清理老壳+装机收尾", tasks: [
-      { id: "阶段3", name: "退役ControlTest+开机自启+ComBin去重+部署文档", status: "☐" }
+      { id: "阶段3", name: "退役ControlTest+开机自启+ComBin两栈去重(含D1-10 oplog)+部署文档", status: "☐" }
     ]}
   ],
   pending: [
-    { id: "D1-01", rel: "Task7", point: "operate 拉起独立 ControlHost.exe(静默不弹UAC)", env: "运行", risk: "中", status: "◑机制过" },
+    { id: "D1-01", rel: "Task7", point: "operate拉起control(真实ControlProcessLauncher实跑:探活→拉起→轮询)", env: "运行", risk: "中", status: "☑实跑" },
     { id: "D1-02", rel: "Task7", point: "/ping、/status 返回JSON", env: "运行", risk: "低", status: "☑" },
     { id: "D1-03", rel: "Task7", point: "control 独立进程真机硬件获取(6相机SN/7COM口True)", env: "真机", risk: "高", status: "☑" },
-    { id: "D1-04", rel: "Task7", point: "operate 关闭后 control 续命(结构性独立)", env: "运行", risk: "高", status: "☑" },
-    { id: "D1-05", rel: "Task7", point: "重开 operate 复用已在跑的 control", env: "运行", risk: "中", status: "◑机制过" },
+    { id: "D1-04", rel: "Task7", point: "operate关闭后control续命(harness退出control仍跑)", env: "运行", risk: "高", status: "☑" },
+    { id: "D1-05", rel: "Task7", point: "复用已在跑的control(真实代码:已在运行直接连接,PID不变)", env: "运行", risk: "中", status: "☑实跑" },
     { id: "D1-06", rel: "Task7", point: "单实例 Mutex:第二个 control 自退", env: "运行", risk: "低", status: "☑" },
-    { id: "D1-07", rel: "Task7", point: "完整采集闭环(started:true/tlSn/真机自控环运行)", env: "真机", risk: "高", status: "☑修死锁后" },
+    { id: "D1-07", rel: "Task7", point: "完整闭环+数据入库(house_collect 37℃真温/alarm_data 落108库)", env: "真机", risk: "高", status: "☑DB实证" },
     { id: "D1-08", rel: "合并遗留", point: "serialBin/HAL借用ComBin重开不复活发送线程致握手死锁 修复", env: "真机", risk: "高", status: "☑已修复验证" },
-    { id: "D1-09", rel: "合并遗留", point: "control本地SQLite InitTables AUTOINCREMENT建表失败(不阻塞运行)", env: "运行", risk: "中", status: "✗待修" }
+    { id: "D1-09", rel: "合并遗留", point: "control本地SQLite InitTables AUTOINCREMENT建表失败(不阻塞)", env: "运行", risk: "中", status: "✗待修" },
+    { id: "D1-10", rel: "阶段3", point: "control硬件操作不进operation_log(埋点在operate另一套栈,归两栈去重)", env: "运行", risk: "低", status: "✗归阶段3" }
   ]
 };