فهرست منبع

docs(house-fault): 第一阶段代码完成(Task1-6,37单测绿)+方案修正回写,剩Task7真机

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
huangjie 1 روز پیش
والد
کامیت
50ae94b05b

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

@@ -457,3 +457,31 @@
 - **跨端依赖(计划已标红)**:新 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 待开)。

+ 7 - 6
项目文档/进度/工作计划表.md

@@ -63,9 +63,10 @@
 - 真机踩坑均已解(僵尸不挡 control / 登录真因=测试目录缺 tl-shared.config 致 BaseUrl 坏 / auth 库本零用户已插 admin/123456 可逆)。
 - 第二阶段(MJPEG 出图)、第三阶段(operate 接入 + V-012 电机真机走位)待拆。
 
-### 新加固专项 · 舱室故障隔离 + 双端故障提示 = ☑ 实现计划已拆 · ☐ 待实现
-- spec `需求文档/specs/2026-06-23-舱室故障隔离与双端故障提示-design.md`;**实现计划已落盘** `开发计划/2026-06-23-舱室故障隔离与双端故障提示-实现计划.md`(7 任务 bite-sized + 4 后续阶段提纲,分支 `feature/house-fault-isolation`)。
-- **结论**:运行期单舱坏已隔离 ✓;**启动期有缺口**——舱"半坏"(串口活相机坏/编号冲突)致 InitTL 整体中止、好舱起不来 ✗。
-- **目标**:① 启动期按舱容错(单舱坏只排除该舱、好舱继续培养)② **用户硬约束:任何舱异常 operate+front 双端都明确提示哪个舱/什么故障/时间**。
-- **第一阶段(计划 Task1-7,可自主)**:HouseFault 数据/枚举 + StartupFaultPolicy 坏舱剔除(纯 TDD)→ SerialBin 登记结构化坏舱 → InitTL 改"零可跑才中止" → InitHouse 逐舱 try-catch → AppData 快照透出 Faults + 复用 reportCloudAlarm 上报 → 真机拔插验收。
-- **后续阶段(提纲)**:运行期故障升级去抖(control)/ operate 监控页"舱故障"区(真机门控)/ front 告警展示 + Java 告警字典登记新 alarmTypeKey(真机门控)/ 真机拔插整体验收。
+### 新加固专项 · 舱室故障隔离 + 双端故障提示 = 🟢 第一阶段代码完成 · ☐ 待 Task7 真机验收
+- spec + 实现计划 + **方案修正**(复用现有 `reportAlarm` 报警闭环,弃用群消息 reportCloudAlarm)均已落盘;分支 `feature/house-fault-isolation`(8 commit)。
+- **结论**:运行期单舱坏已隔离 ✓ 且已接现有报警闭环;**启动期缺口已修** ✓——舱"半坏"只排除该舱、好舱继续培养、零可跑才中止。
+- **目标**:① 启动期按舱容错 ② 双端明确提示(复用现有 alarm 表→front 报警列表 + operate"系统异常" + 短信/电话 + 可消警)。
+- **第一阶段代码 Task1-6 全完成**(37 单测绿、control sln 0 错):HouseFault/StartupFaultPolicy(纯TDD)→ SerialBin 6处登记结构化坏舱 → InitTL 零可跑才中止+坏舱存AppData → InitHouse 逐舱 try-catch → AppData 快照透出 Faults + ReportStartupFaults(走 `ReportAlarmController` 闭环,相机坏photoState=1/串口坏comState=1/其余-1跳过)。
+- **剩 Task7 真机拔插验收**:基线(全好舱无回归)可自主;半坏舱注入需物理拔相机USB(只能人做)→待对齐。待确认:排除舱未写house表时 alarm 能否落库。
+- **后续阶段**:运行期已接闭环(按需补去抖)/ operate 监控页"舱故障"区(读 /status Faults)/ front 复用现有报警列表 —— 真机门控。

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

@@ -1,10 +1,10 @@
 // 实时面板数据源(监控面板.html 读 window.PROGRESS_DATA)。每推进一步更新本文件。
 window.PROGRESS_DATA = {
   project: "operate/control 双进程拆分",
-  generatedAt: "2026-06-23 23:30",
-  phase: "三阶段主体完成;M区全闭合;配置收敛真机验证;D2-02 第一阶段 control 后端【代码+真机全过】(27单测绿);新加固专项 舱室故障隔离+双端提示【实现计划已拆完】",
-  currentTask: "新加固专项 舱室故障隔离+双端提示 = 实现计划已拆完落盘(开发计划/2026-06-23-...实现计划.md):第一阶段 Task1-7(HouseFault/StartupFaultPolicy 纯TDD → SerialBin 6处登记结构化坏舱 → InitTL 改'零可跑才中止' → InitHouse 逐舱 try-catch → AppData 快照透出 Faults+复用 reportCloudAlarm 上报 → 真机拔插验收)+ 后续4阶段提纲(运行期升级/operate监控页/front告警/整体验收)。代码一行未写,本轮只到计划。下一步:建分支 feature/house-fault-isolation 开工 Task1。用户定 a+c 的 ①(D2-02收尾提交)②(拆计划)均已完成。",
-  note: "计划基于 codegraph 逐符号核实:control 用 ivf_tl_Com/SerialBin(非operate死栈),errorlist 仅6处来源;InitTL'errorlist非空即整体return'=启动期缺口;InitHouse 大try-catch 单舱构造异常拖垮全体;告警通道=HttpService.AlarmApi→/api/tl/control/alarm/reportCloudAlarm;快照=GetMonitorSnapshot/MonitorSnapshot。决策:坏舱=故障清单HouseSn>0的舱,可跑舱=发现−坏舱,致命=零可跑才中止。跨端依赖(已标红):新alarmTypeKey需Java告警字典登记否则落库被拒,第四阶段落地。环境:僵尸operate 20268需真重启清(不挡control);admin/123456留库可逆。",
+  generatedAt: "2026-06-24 00:30",
+  phase: "三阶段主体完成;M区全闭合;D2-02 第一阶段 control 后端【代码+真机全过】;新加固专项 舱室故障隔离 第一阶段【代码全完成 Task1-6,37单测绿】待真机验收",
+  currentTask: "舱室故障隔离专项 第一阶段代码全完成(8 commit 在 feature/house-fault-isolation):HouseFault/StartupFaultPolicy(纯TDD)→ SerialBin 6处登记结构化坏舱 → InitTL 零可跑才中止+坏舱存AppData → InitHouse 逐舱try-catch → AppData 快照透出Faults+ReportStartupFaults。37单测绿、control sln 0错。【关键方案修正】核实系统已有完整舱室报警闭环=ReportAlarmController→/reportAlarm→报警责任链→alarm表→front/operate列表+短信电话+消警;故弃用reportCloudAlarm(只发IM群消息不入闭环)及新建告警类型,启动排除舱改走ReportAlarmController(相机坏photoState=1/串口坏comState=1/其余-1跳过)。下一步Task7真机拔插:基线可自主;物理拔相机需对齐。",
+  note: "状态码语义0正常/1异常/-1跳过(HousePort/Photo handler对-1跳过已实读确认)。短信电话报警=reportAlarm闭环内置,保留并复用;群消息(reportCloudAlarm)不用。代码改面:SerialBin(+Faults6处)/StartupFaultPolicy(新)/HouseFault(新,路径control/ivf_tl_Entity/)/StartMain(InitTL剔除+InitHouse逐舱兜底+StartRun报完整清单)/AppData(StartupFaults+快照+ReportStartupFaults)/MonitorSnapshot(+Faults)。Task7待确认:排除舱未写house表时alarm能否落库。分支从 feature/d2-02-debug-command-proxy 切(测试工程在该分支,main落后16commit)。",
   milestones: [
     { name: "阶段1 · control 独立进程骨架(完成)", tasks: [
       { id: "Task1-7", name: "全过+D1-08死锁修复+operate真外壳E2E+数据入库DB铁证", status: "☑" }

+ 11 - 10
项目文档/进度/进度状态.yaml

@@ -1,15 +1,16 @@
 # 续接断点状态(机器可解析)。换会话/换电脑后首先读它定位。
 # 状态取值: 未开始 / 进行中 / 完成 / 代码完成待验证
 # 纪律:本字段只存【当前断点】,历史细节进 交接卡.md(见 CLAUDE.md 第三节)。
-更新时间: 2026-06-23 D2-02 第一阶段已收尾(代码+真机全过,11 commit 在 feature/d2-02-debug-command-proxy 待并 main);新加固专项"舱室故障隔离+双端提示"实现计划已拆完落盘(7任务+4阶段提纲)
+更新时间: 2026-06-23 舱室故障隔离专项 第一阶段【代码全完成】Task1-6(6 commit + 2 docs commit 在 feature/house-fault-isolation),37 单测全绿、control sln 0 错;方案已修正为复用现有 reportAlarm 报警闭环(非群消息)。剩 Task7 真机拔插验收
 当前任务: >
-  【新加固专项 舱室故障隔离+双端提示 = 实现计划已拆完,待开工第一阶段(control 坏舱剔除)】(目标分支 feature/house-fault-isolation,尚未建)
-  · D2-02 第一阶段(control 后端)= 代码+真机全过,11 commit 在 feature/d2-02-debug-command-proxy,本分支待并 main
-  · 本轮产出:`开发计划/2026-06-23-舱室故障隔离与双端故障提示-实现计划.md` —— 第一阶段 Task1-7(HouseFault/StartupFaultPolicy 纯 TDD → SerialBin 登记 → InitTL 零可跑才中止 → InitHouse 逐舱 try-catch → AppData 快照透出+reportCloudAlarm 上报 → 真机拔插验收);后续 4 阶段提纲(运行期升级/operate监控页/front告警/整体验收)。
-  · 下一步:开工第一阶段 —— 建分支 feature/house-fault-isolation,按计划 Task1 起(建议子代理驱动逐 Task,真机拔插由 Claude 自主跑)
+  【舱室故障隔离专项 第一阶段 = 代码全完成,待 Task7 真机拔插验收】(分支 feature/house-fault-isolation,从 feature/d2-02-debug-command-proxy 切)
+  · 代码 Task1-6 全落地:HouseFault/StartupFaultPolicy(纯TDD)→ SerialBin 6处登记结构化坏舱 → InitTL 零可跑才中止+坏舱存AppData → InitHouse 逐舱 try-catch → AppData 快照透出 Faults + ReportStartupFaults(走 reportAlarm 闭环)。37 单测绿、0 错
+  · **重要方案修正(本轮)**:核实发现系统已有完整舱室报警闭环 = `ReportAlarmController`→`/reportAlarm`→报警责任链→`alarm`表→front/operate报警列表+短信电话+静音/消警;运行期串口/相机异常本就接此闭环。故**弃用** reportCloudAlarm(只发IM群消息、不入闭环)及新建 alarmTypeKey;启动排除舱改走 ReportAlarmController(相机坏photoState=1/串口坏comState=1/其余-1跳过)。状态码 0正常/1异常/-1跳过(已验 HousePort/Photo handler 对-1跳过)。
+  · 下一步:Task7 真机拔插验收——①基线(全好舱:/status Faults空+started+无回归,可自主)②制造半坏舱→排除/其余正常/alarm落库(**需物理拔相机USB=只能人做**)。**待与用户对齐物理注入怎么弄**
 说明: >
-  实现计划基于 codegraph 逐符号核实:control 版 SerialBin(ivf_tl_Com)有 6 处坏舱来源、StartMain.InitTL"errorlist 非空即整体 return"是启动期缺口、InitHouse 大 try-catch 单舱构造异常会拖垮全体、现有告警通道=HttpService.AlarmApi→/api/tl/control/alarm/reportCloudAlarm、快照=MonitorSnapshot/GetMonitorSnapshot。决策规则:坏舱=故障清单 HouseSn>0 的舱;可跑舱=发现−坏舱;致命=零可跑才中止(单舱/部分舱坏绝不中止)。
-  跨端依赖(计划已标红):新 alarmTypeKey(HOUSE_INIT_EXCLUDED/HOUSE_CAMERA_FAULT/HOUSE_SERIAL_FAULT/HOUSE_RUNTIME_FAULT)需在 Java 告警字典登记否则落库被拒——Task7 Step4 先探、第四阶段落地。
+  代码改面:control/ivf_tl_Com/SerialBin.cs(+Faults登记6处)、ivf_tl_Control/StartupFaultPolicy.cs(新)、IvfTl.Control.Entity/InitEntitys/HouseFault.cs(新,路径修正=control/ivf_tl_Entity/)、StartMain.cs(InitTL剔除坏舱+InitHouse逐舱兜底+StartRun报完整清单)、AppData.cs(StartupFaults+快照透出+ReportStartupFaults)、MonitorSnapshot.cs(+Faults/HouseFaultRow)。8 commit。
+  决策规则:坏舱=故障清单HouseSn>0;可跑舱=发现−坏舱;致命=零可跑才中止(单舱/部分舱坏绝不中止)。短信电话报警保留并复用(报警链内置)。
+  Task7 真机待确认点:①被排除舱可能未写入house表→报警链按houseSn查house/tlSetting可能查不到→alarm能否落库需真机验,查不到补一步;②物理拔相机USB我做不了(软件无法拔USB),需人配合或软件模拟,待对齐。
   环境:僵尸 operate 20268 仍需真重启清(不占串口不挡 control);admin/123456 已留库可逆;后端 108+网关10010 在线。
 阶段概览:
   - id: 阶段1
@@ -30,6 +31,6 @@
     备注: "Task0-9 全落地,27单测绿(含C-1非零起点红线回归)。真机完整冒烟过(借真实舱/读温/越界实拒/超时回收)。第二(MJPEG)/三(operate接入V-012)阶段待拆。"
   - id: 加固-舱室故障隔离
     名称: 舱室故障隔离 + 双端故障提示(新专项)
-    状态: 实现计划已拆·待开工第一阶段
-    备注: "spec + 实现计划(开发计划/2026-06-23-...实现计划.md,7任务+4阶段提纲)已落盘。第一阶段=control 坏舱剔除(HouseFault/StartupFaultPolicy 纯TDD + SerialBin登记 + InitTL零可跑才中止 + InitHouse逐舱兜底 + 快照透出/reportCloudAlarm上报 + 真机拔插)。分支 feature/house-fault-isolation 未建。"
-下一步: 开工舱室故障隔离第一阶段(建 feature/house-fault-isolation,按计划 Task1 起,建议子代理驱动)。D2-02 第一阶段(feature/d2-02-debug-command-proxy)+ 本专项分支均待并 main。D2-02 第二阶段 MJPEG 按需推进
+    状态: 第一阶段代码完成·待Task7真机验收
+    备注: "spec+计划已落盘+方案修正(复用现有reportAlarm报警闭环,非群消息)。第一阶段代码 Task1-6 全完成(8 commit 在 feature/house-fault-isolation):坏舱剔除+逐舱兜底+快照透出+经闭环上报,37单测绿、0错。剩 Task7 真机拔插(基线可自主;物理拔相机需对齐)。后续阶段:运行期已接闭环按需补/operate监控页/front复用现有列表。"
+下一步: Task7 真机拔插验收——基线(全好舱无回归)可自主跑;制造半坏舱需物理拔相机USB(只能人做),待与用户对齐怎么注入。本专项分支 + D2-02 分支均待并 main