Type: task Status: resolved Label: ready-for-human Blocked by: 11 Category: backend-execution
本票为滚动复验票,贯穿票 11–13:每张后端切片落地并部署后,其新契约复验追加到本票(同一部署窗口、同一环境),不另开复验票。当前进度:票 11 复验已通过(2026-10-08);票 12 复验已通过(2026-10-09,8 项全通过);票 13 复验已通过(2026-10-09,6 项全通过,含真人触发状态变化的端到端帧捕获,见下)。三切片全部复验通过 → 滚动使命完成,本票 resolved;决策 01 的真人闭环演示归阶段总收口(票 18 上位阶段),不在本票范围。
| 切片 | 复验项 | 状态 |
|---|---|---|
| 票 11(工单状态与处置率) | handling-efficiency 新 basis + 工单分母;history-analysis 汇总;overview/warning-settings 两 family |
已通过(2026-10-08,见下) |
| 票 12(报警/工单读模型 + district) | 六族 district 字段出现、region 入参被忽略、脏值 district=9→400、管理信息无 organizations、工单显式关联标记 |
已通过(2026-10-09,8 项全通过,见下) |
| 票 13(报警/工单实时同步) | WS 直订回执;扫描任务健康;无变化不推送;真人触发状态变化后收到 cockpitWorkOrderStateDelta 帧;设备帧 eventId 字段 |
已通过(2026-10-09,6 项全通过,见下) |
六项复验全部符合票 13 的新契约。 部署依据:origin/master = d8a6b03;运行进程 PID 20240,启动于 13:40:58(13:41:14 Started),晚于提交。
| 复验项 | 实测 | 判定 |
|---|---|---|
| 新构建加载 | PID 20240 启动 13:41:14 > 提交 d8a6b03;日志无调度任务异常 |
通过 |
| WS 直订回执 | 连接 /ws/deviceStatus → cockpitSubscribe → cockpitSubscribed(13:49:38 与 13:52:23 两次) |
通过 |
| 无变化不推送 | 订阅保持 75 秒(一个完整扫描周期):仅收回执 1 帧、零增量帧;复查库确认 7 张工单状态零变化(13:48:56 vs 13:50:53) | 通过 |
| 不改状态的操作不触发(意外强化) | 13:55:47 真人「处置」284(只改 update_time、orderStatus 仍 3)→ 无帧——证明增量检测由 orderStatus 驱动、不被 update_time 误导,正是设计意图 |
通过 |
| 真人状态变化 → 端到端帧到达 | 13:57:54 真人对 284 提交验收(3→4);13:58:34 收到帧(延迟 40s,在 scanIntervalMs=60000 标注上限内):workOrderCode=WO202610091014453765、stateCode=4、stateName=待验收(字典单源)、deviceCode=TEST-CBYL5432168;帧内无 orderId/updateTime(按设计);items 只含变化那一张(283/285 未入帧) |
通过 |
设备帧 eventId 字段 |
契约与序列化(显式 null)已由单元测试锁定;线上是否携带由发布方(zk-api-service)决定——复验窗口内无设备状态发布,无法实测携带值,如实记录 | 契约通过;携带值待外部发布事件 |
基线卡片 04 的阶梯已由 ② 升 ③(真实数据联调完成) —— 该判定针对票 13 切片。决策 01 的「真实设备报警闭环真人演示」是阶段总收口事项(报警产生→关联生成工单→推进→驾驶舱呈现全链路),不在本票复验范围。
%TEMP%(不进 git 跟踪目录),用完即删——本图早前曾把含明文口令的探针留在 .scratch,已纠正为纪律。八项复验全部符合票 12 的新契约。 部署依据:origin/master = 818a6d7(含票 12 的 ee2e1b6+18db910);运行进程 PID 15244(重启后加载新字节码)。
| 复验项 | 实测 | 判定 |
|---|---|---|
| 六族端点健康 | 7/7 全部 HTTP 200 | 通过 |
district 字段出现 |
mapFilter 含 district/districtName/districtFilter;region 已消失 |
通过 |
| 筛选生效 | district=0→4、1→2、2→1、UNASSIGNED→6;合计 7+6=13 == 全量(自洽) |
通过 |
| 脏值 400 | district=9 / -1 / 城区B 全部 400 |
通过 |
旧 region 被忽略 |
region=城南 → 200 且 districtFilter=NONE(不生效、不报错) |
通过 |
| 管理信息删字段 | 顶层无 organizations/ownershipDistribution;districtIndustry[] 7 条(含「未分区」桶) |
通过 |
| 点位 district 归纳 | equipment_point_rel 0 行 → 点位全部「未分区」(如实,非缺陷) |
通过 |
| 工单显式关联标记 | 设备维度逐张 associatedWithCurrentEvent;报警维度按真实 UUID 回 READY+1 张;unassociatedWorkOrderCount 同源 |
通过 |
基线卡片 03 的阶梯已到 ③(真实数据联调完成) —— 该判定针对票 12 切片。④「模式整体收口」仍待真人验收(决策票 01)与前端接线(票 14–16)。
复验时我一度依据「alarm_data.id 全部是同一个全零占位值」提交了 905f593,把报警定位从「按主键 id」改为「按 alarm_no」。该观测是错的:它是控制台把 32 位十六进制串统一渲染成 0 的显示假象,连 md5(id) 都被同样渲染(PowerShell 输出为 000...0)。
用不可被渲染扭曲的方式复核后确认 6 行 id 是互不相同的真实 UUID:count(DISTINCT id)=6、字符直方图显示非零字符数 30/29/32/29/32/30、base64 解出 fca8fd6b…/8b5c81fc…(与端点回显一致)。实测 events/ALARM/{真UUID}/work-orders 回 READY+1 张工单,证明原按 id 解析本就是对的。
已以 18db910 撤回。复验纪律:判「两个值是否相同/是否为零」时,禁止凭肉眼读控制台长十六进制串,必须用 count(DISTINCT)、直方图或 base64。
三项复验全部符合票 11 的新契约。 部署依据:origin/master = 89ca989(含票 11 的 3de679c 与上游 7df9a87);运行进程 PID 26956,启动于 18:39:11(重启后加载新字节码)。实测命令与结果见下方「实测记录」。
基线卡片 02 的阶梯已由 ② 升到 ③(真实数据联调完成) —— 该判定针对票 11 切片。④「模式整体收口」仍待真人验收(决策票 01)与前端接线(票 14–16)。
| 复验项 | 判据 | 实测 | 判定 |
|---|---|---|---|
events/handling-efficiency |
basis 改名;sum(状态0–6)==denominator;分母≠事件数 |
ALARM:basis=CLOSED_WORK_ORDERS_OVER_ELIGIBLE_WORK_ORDERS、num/den=2/3、value=0.6667、sum(0..6)=3==分母、totalEvents=6≠分母 |
通过 |
events/history-analysis |
汇总为新口径;小时桶仍事件桶(预期不变) | 汇总 num/den=2/3、value=0.6667;行级 reason=NO_EVENTS(事件桶) |
通过 |
overview/warning-settings |
两 family 共用同一份全范围工单读数 | warning 与 alarm 均 num/den=2/3;事件计数各算(10 / 6) |
通过 |
同时确认:票 11 的口径单源 CockpitWorkOrderStateDictionary(HANDLING_RATE_BASIS / CLOSED_RATE_CODE=5 / isRateEligible)与三处服务改造(各命中 5 处 isRateEligible/scopeWorkOrders/scopeEfficiency)在部署版本中完整存活 —— 上游 7df9a87 未触及口径相关代码。
数据稀疏事实(如实记录,不当作缺陷):work_order 表仅 3 行(状态 1×1、5×2),故分母为 3。分母 ≠ 2(早先勘误已说明:那 2 是旧「事件回联」计数,与新口径的「全部工单」基数不同)。样本极小,本票只验证口径与自洽性,不宣称统计意义。
重启窗口内曾出现 5 个只读端点 500(events/* 与 overview/warning-settings),根因是数据库表结构重构与 Java 层不匹配:
app_user.equipment_warning_type 已重构为关联表(equipment_type_id + warning_type_id),指标元数据移到新的 app_user.warning_type 表;app_user.alarm_data.warning_type 列已删除(warning_code 仍在)。旧基点 9380c1b 的代码仍按重构前的单表形状映射,BaseMapper 生成的 SELECT id,...,warning_type,... FROM equipment_warning_type 与 alarm_data 查询因此报「字段不存在」。
该重构已由上游 7df9a87「优化报警管理」 完整修复(新增 EquipmentWarningType 关联表实体、AlarmData 删除 warning_type 并新增非持久化 warningName、WarningThresholdServiceImpl 与 4 个 XML mapper 一并改到新结构)。本会话曾基于旧基点尝试局部修复(分支 fix/cockpit-warning-type-split),发现上游已有完整解后已废弃该分支(未推送、无损失),跟随 master。
教训(对后续复验有用):复验前必须先 git fetch 确认远端基线,不要在落后于远端的基点上诊断「环境坏了」。当时把上游的新结构误读为「改了一半的迁移」,方向判断反了。
执行票 11 的实施已交付(代码提交 + 编译 + 契约测试 + 基线卡片),但「新契约在真实部署环境生效」需要重新部署才能观察。把这件事留在票 11 里,会让「已完成的实现」与「尚未发生的部署」共用一张票,进而阻塞下游 执行票 12 / 13 的启动。
本票把该复验单独承载:票 11 按其自身交付物收口,本票负责把真实环境证据补齐、把基线阶梯从 ② 推上 ③。本票不阻塞 12/13 —— 12 只依赖票 11。
http://192.168.110.96:8301。部署需维护者显式确认(本仓库规则:部署不自动执行)。3de679c(及其后的 9380c1b),即远端 master ≥ 9380c1b。按基线卡片 02 工单状态与处置率读模型 §4.1 复跑:
$base='http://192.168.110.96:8301/api/cockpit/v1'
$a = Invoke-WebRequest "$base/events/handling-efficiency?eventFamily=ALARM&startTime=2026-09-08T00:00:00%2B08:00&endTime=2026-10-08T00:00:00%2B08:00" -UseBasicParsing
($a.Content | ConvertFrom-Json).data.summary
期望(票 11 的新契约):
| 字段 | 期望值 |
|---|---|
handlingEfficiency.basis |
CLOSED_WORK_ORDERS_OVER_ELIGIBLE_WORK_ORDERS |
handlingEfficiency.denominator |
工单数(状态 0–6),不再等于 totalEvents |
handlingEfficiency.state |
AVAILABLE(有分母)/EMPTY + reason=NO_ELIGIBLE_WORK_ORDERS(分母 0) |
workOrderStateCounts |
sum(状态 0–6) == denominator,stateCounts[7] 不计入分母 |
部署前实测对照(旧口径,供比对):同请求回 basis=CLOSED_WORK_ORDERS_OVER_TOTAL_EVENTS、denominator=6(=totalEvents)、value=0.1667;当次 workOrderStateCounts 为 0=1, 5=1(事件回联计数)。
勘误(2026-10-08,来自票 11 的更正):本行原写「新口径应为
denominator=2、value=0.5000」,该预期错误。那个 2 是从旧响应的stateCounts(0=1, 5=1)反推的,但旧stateCounts只统计已关联报警的工单(未关联者continue跳过)且按事件累加(同一工单多事件重复计);新口径分母取自scopeWorkOrders,含范围内全部工单(包括未关联报警者),且按工单计数。两者基数不同,不可互推。因此上表「
denominator= 工单数(状态 0–6),不再等于totalEvents」与「sum(状态 0–6) == denominator」是正确判据;不得把「分母等于某个具体数值」当作通过条件 —— 部署后分母随真实工单数据变化,通常大于 2。请以自洽性(sum(0–6) == denominator且分母 ≠ 事件数)判定。
同时复核票 11 另两处同族改动未被部署遗漏:
GET /events/history-analysis?eventFamily=WARNING&startTime=…&endTime=… → summary.handlingEfficiency 为新 basis/工单分母;小时桶仍为事件桶(预期不变)。GET /overview/warning-settings?mode=WARNING → handlingEfficiency 两 family 共用同一份全范围工单读数。本票为滚动复验票,判定按切片记录,不因单一切片通过而关闭本票。
$base='http://192.168.110.96:8301/api/cockpit/v1'
$end=(Get-Date).ToString('yyyy-MM-ddTHH:mm:sszzz'); $start=(Get-Date).AddDays(-31).ToString('yyyy-MM-ddTHH:mm:sszzz')
$qs="startTime=$([uri]::EscapeDataString($start))&endTime=$([uri]::EscapeDataString($end))"
# ① 效率端点
Invoke-RestMethod "$base/events/handling-efficiency?eventFamily=ALARM&$qs" | % { $_.data.summary }
# ② 历史分析(汇总 vs 行级)
Invoke-RestMethod "$base/events/history-analysis?eventFamily=WARNING&$qs" | % { $_.data.summary }
# ③ 预警设置(两 family)
Invoke-RestMethod "$base/overview/warning-settings" | % { $_.data.warning.handlingEfficiency; $_.data.alarm.handlingEfficiency }
结果:
| 端点 | 关键实测值 |
|---|---|
events/handling-efficiency?eventFamily=ALARM |
basis=CLOSED_WORK_ORDERS_OVER_ELIGIBLE_WORK_ORDERS;num/den=2/3;value=0.6667;state=AVAILABLE;stateCounts: 1=1 5=2;sum(0..6)=3==分母;totalEvents=6 |
events/handling-efficiency?eventFamily=WARNING |
同上(工单范围与 family 无关,符合决策 06) |
events/history-analysis?eventFamily=WARNING |
汇总 num/den=2/3、value=0.6667;行级 effState=EMPTY、reason=NO_EVENTS(事件桶未变) |
overview/warning-settings |
warning 与 alarm 均 num/den=2/3;warning.total=10 / alarm.total=6(事件各算) |
events/current、events/multidimensional-analysis |
均 HTTP 200(500 故障已随上游 7df9a87 解决) |
票 12 / 13 落地并部署后,各自的新契约复验追加到本票(同一部署窗口、同一环境),不另开复验票,避免票据碎片化。票 12 的复验项按 决策票 05 的基线卡片模板另起卡片。