Category: backend-contract
来源:票 58 讨论期对真实后端(192.168.110.96:8301,快照 2026-10-19T15:19:25)的实测复核。
GET /api/cockpit/v1/map-snapshot?page=1&pageSize=1000 返回的未关联设备 deviceStatus,与其各自 GET /api/cockpit/v1/equipments/{code}/detail-aggregate 的四轴事实对照:
| 设备 | 未处理报警 | 未解决预警 | 未结束工单 | 后端发布 |
|---|---|---|---|---|
41010500001320000002 |
0 | 2(PENDING/PROCESSING) | 1 | WARNING |
TEST-CBYL5432168 |
0 | 1 | 1(stateCode=4 待验收) | WARNING |
TEST-TCLLJ002215 |
0 | 1 | 1 | WARNING |
860347065467627 |
0 | 0 | 1(stateCode=2 已接单) | WORK_ORDER |
推论:三台设备同时存在「未解决预警 + 未结束工单」,后端判 WARNING → 预警高于工单。860347065467627 无预警、有工单 → WORK_ORDER,说明工单只在无预警时才压过预警。即设备侧序为 未转工单的报警 > 预警 > 工单。
3772220e)实施的是「设备的全部未处理报警都已被未结束工单承接 → WORK_ORDER」,其余维持 alarm → warning → workOrderInProgress 原序。该票自身留档也写明:新规则在今天真实数据上不改变任何读数。alarm_data 只有 90 行、仅涉及设备 21119740;「未处理且已承接」的行数为 0)。因此无法用实测裁定这三者中哪一条是对的,只能记录。2026-10-22
/triage诊断更正:第 1 问的窄三路场景(报警标志为真 + 全部未处理报警已被未结束工单承接)现行代码已判WORK_ORDER;真正未裁的是「无报警时,未解决预警 vs 未结束工单」的二路序(今天 2 台设备可观测)。详见## Comments本轮诊断。
deviceStatus 应为 WORK_ORDER 还是 WARNING?WORK_ORDER:票 52 的 deviceStatus() 实现需要再改(当前实现把 warning 判在 workOrderInProgress 之前),且属已完成票的返工,需评估影响面与测试闸。DEVICE_STATUS_VISUALS.priority(ALARM 1 / WARNING 2 / WORK_ORDER 3)与后端枚举一致,票 52 裁定 4 已确认「零改动、无耦合」;前端只渲染状态字符串(CONTEXT.md「点位状态」/ ADR 0002)。resolve() 语义(票 52 裁定 4 明确「不跟随」)。/map-snapshot、/equipments/{deviceCode}/detail-aggregate(alarms / warnings / workOrders / alarmWarningRelations 四轴)。/triage 诊断完成(只读复核):真实后端复现 2 台设备「预警未解决 + 工单未结束、无报警」发 WARNING;票 52 窄三路规则现行已判 WORK_ORDER,真正未裁的是二路序。证据 verify/artifacts/t71/。ready-for-agent,实施契约见 Agent Brief。a416f4ab:判定序改为「未转工单的报警 > 工单 > 预警」(只动非报警分支)、Q3 注释留档、新增 9 条契约测试;Cockpit*Test,BusinessCockpit*Test 566/566、变异闸 4/4。真实后端未部署,部署后按 verify/artifacts/t71/expected-after-deploy.md 复验(归票 17/18)。Status: resolved Type: bug Blocked by: Labels: wayfinder:task, backend-contract, bug
This was generated by AI during triage.
This was generated by AI during triage.
This was generated by AI during triage.
This was generated by AI during triage.
verify/artifacts/t71/verify-after-deploy.mjs 10/10 通过(快照 2026-10-23T11:19:44+08:00,载荷 verify/artifacts/t71/after-deploy/):
| 项 | 实测 | 结论 |
|---|---|---|
41010500001320000002(2 预警 + 1 未结束工单) |
WORK_ORDER(改前 WARNING) |
改序生效 |
TEST-CBYL5432168(1 预警 + 1 未结束工单) |
WORK_ORDER(改前 WARNING) |
改序生效 |
TEST-TCLLJ002215(1 预警、无工单) |
WARNING |
未被误伤 |
860347065467627 / TEST_001 / TEST-CBLL222222222 |
WORK_ORDER |
不变 |
41010500001320000001 / 8652052334 / TEST-CNXHS0000001 |
NORMAL / OFFLINE |
不变 |
21119740 所在点位 |
ALARM |
票 52 窄三路分支不受影响 |
| 未关联设备业务轴计数 | NORMAL 1 / WARNING 1 / WORK_ORDER 5 / OFFLINE 2 | 预警 3→1、工单 3→5,与部署前预演表逐项一致 |
Q3 对照:monitoring/situation |
410105...002 为 WARNING、TEST-CBYL5432168 为 OFFLINE |
均 ≠ WORK_ORDER → Q3「不跟随」成立 |
两条如实说明
TEST-CBYL5432168 的 situation 状态是 OFFLINE 而非 WARNING:该设备在线态已漂移为离线,situation 先判离线。「不跟随」的判据是不出现 WORK_ORDER,成立。WORK_ORDER(离线 + 未结束工单)—— 这是既有序:工单判断本来就排在 online 之前,本票只调了 warning 与工单的先后,没有引入「离线设备显示处置中」的新行为。复验判据已固化在脚本里(对照部署前预演表逐项 PASS/FAIL),重跑即可回归。至此本票验收项全部闭环:裁定(Q1/Q2/Q3=A)、实施(a416f4ab)、测试 566/566、变异闸 4/4、真实读数复验 10/10。
a416f4ab)裁定依据:维护者 2026-10-22 Q1=A / Q2=A / Q3=A。
改了什么
CockpitMonitoringPointStatusResolver.deviceStatus():非报警分支把 workOrderInProgress 提到 warning 之前;报警分支(票 52 的「全部未处理报警被未结束工单承接 → WORK_ORDER」)原样保留。最终业务序 = 未转工单的报警 > 工单处置 > 预警。BusinessCockpitMonitoringSituationAdapter.metricStatus() 只加注释(Q3:按事实判、不跟随;同一设备「地图=工单处置 / 运行监测异常清单=预警」是裁定结果)。CockpitMonitoringPointStatusOrderTest 9 条:二路压序、票 52 窄三路、查不到≠已承接、NORMAL/OFFLINE、Q2 枚举优先级与点位聚合 min 不变、单设备点位自动跟随。验证
Cockpit*Test,BusinessCockpit*Test 566/566 全绿(rebase 到最新 origin 后复跑)。41010500001320000002、TEST-CBYL5432168 仍 WARNING、21119740 的 ALARM 不变 —— 代码已在 origin/master,生效需后端重启/部署。部署后按 expected-after-deploy.md 对照(预期 2 台翻 WORK_ORDER;业务轴 预警 3→1、工单 3→5),复验归票 17/18 窗口。提交:a416f4ab(rebase 后;本地与 origin/master 0/0),3 个文件 +143/−9。只摘本票 hunks,未动同工作树内他人的 overview/** 在制品与 ApplicationConfig.java。
两条如实留档
3c734fe9 让 zksy-system 测试源码编译不过(WaterSupplyDeviceServiceImplTest 第 190/268 行多一个 )),与本票零交集。因此验证改走「先 install zksy-system(main only)→ 再单独跑 zksy-admin 测试」,变异闸同步改成两步走。建议另开小票修该测试,否则任何 -am 全量闸门都会在这里断。ready-for-agent)Category: bug
Summary: 单设备状态判定序改为「未转工单的报警 > 工单处置 > 预警」;只改单设备判定,枚举 priority、点位聚合语义与 monitoring/situation 一律不跟随。
Current behavior:
非报警设备同时存在「未解决预警」与「未结束工单」时,后端按 warning → workOrderInProgress 发布 WARNING(预警压过工单)。真实后端今天可复现 2 台:41010500001320000002(2 条预警 + 1 张未结束工单)、TEST-CBYL5432168(1 条预警 + 1 张未结束工单),均发 WARNING;而维护者口径是「未转工单的报警 > 工单 > 预警」,这两台应为 WORK_ORDER。
同时注意:现行 deviceStatus() 的报警分支已实现「报警且全部未处理报警都被未结束工单承接 → WORK_ORDER」(票 52),该行为正确、必须保留,不是本次返工对象。
Desired behavior:
单设备 deviceStatus 判定按下列顺序(这是业务处置序,不是枚举优先级序):
WORK_ORDER(票 52 现状保留;工单未结束 = order_status ∈ {0,1,2,3,4,6},5 已结案 / 7 已取消为终态);ALARM(含「查不到未处理报警行」「读失败」的保守降级——查不到 ≠ 已承接)。WORK_ORDER(本次新增:压在预警之前)。WARNING(未解决 = status ∈ {PENDING, PROCESSING, HANDLING, RELEASED})。NORMAL / 离线 OFFLINE(现状不变)。Key interfaces:
CockpitMonitoringPointStatusResolver.deviceStatus() —— 唯一判定单源。顺序调整只在这里做,调用点(resolve() 点位聚合、cards()、statistics()、orderedDevices()、map-snapshot 的 getPublishedDeviceStatus())自动跟随,不要在各处另写一份判定。BusinessCockpitDeviceFactResolver —— 已提供 isAlarm()、isWarning()(hasOpenWarning)、isWorkOrderInProgress()(hasOpenWorkOrder)、isAlarmsCoveredByOpenWorkOrders() 四轴事实,本次不新增第二套事实口径;只消费。CockpitMonitoringPointStatus 枚举 —— priority(ALARM 1 / WARNING 2 / WORK_ORDER 3)不动(Q2=A)。BusinessCockpitMonitoringSituationAdapter.metricStatus() —— 不动(Q3=A),但需在方法注释写明这是裁定结果。Acceptance criteria:
WORK_ORDER;无报警 + 预警 + 仅已结案/已取消工单 → WARNING;无报警 + 无预警 + 未结束工单 → WORK_ORDER;报警 + 全部未处理报警被承接 + 预警仍在 → WORK_ORDER(票 52 行为不变);报警 + 有未处理报警无工单 → ALARM;报警但查不到未处理报警行 → ALARM。priority 与 resolve() 聚合语义零改动(可断言三个优先级数值不变、点位聚合仍取 min(priority))。effectiveDevice() 重建、点位详情归一化 —— 票 52 的 M6/M7 教训)。map-snapshot 中 41010500001320000002、TEST-CBYL5432168 的 deviceStatus 由 WARNING 变 WORK_ORDER;21119740 仍 ALARM;业务轴计数相应变为 预警 3→1、工单 3→5(以复验当时真实数据为准,变了就按实际记录,不改样例)。Cockpit*Test,BusinessCockpit*Test 全绿(基线以当时 HEAD 为准,票 52 时为 512/512)+ 变异闸打红并按字节还原,至少三处:把 warning 判回工单之前;把「无未处理报警行」当已承接;把已结案/已取消当未结束。origin/master,票面记录提交号、测试与变异数字(参照票 52 的交付路径:后端仓库 E:\pipe-ner-server,只读库可直连核对)。situation.metricStatus() 注释与本票写明:改序后同一设备出现「地图/设备卡 = 工单处置、运行监测异常设备清单 = 预警」是裁定结果,不是缺陷。Out of scope:
CockpitMonitoringPointStatus.priority(Q2=A);不改点位聚合语义与点位状态词表。POINT_STATUS_VISUALS/DEVICE_STATUS_VISUALS/t09 闸门零改动)。monitoring/situation 的 metricStatus 新增 WORK_ORDER 桶(Q3=A;那是另一张契约票)。alarm_data 写入与 AlarmClearServiceImpl 清警逻辑。已知影响(不是缺陷,实施时按此记录):
前端无代码改动,但观感与计数会变——planDeviceEffects() 的「N 台异常」口径是 ALARM/WARNING(票 07/58),翻转为 WORK_ORDER 的设备会掉出异常计数、特效由 blink 改 spin(票 58:工单处置不计入降级计数);业务轴计数随之变化。
证据:
verify/artifacts/t71/(README 含复验命令、probe.mjs、probe-alarm-wo.mjs、10 台设备 aggregate 载荷与 map-snapshot 快照);票 52 的库内取证 verify/artifacts/t52/real-data-consequence.md。
已查阅范围:本票正文(无评论、无 Answer)、票 52 全文、票 45(F1)、票 58(来源)、map.md、CONTEXT.md「点位状态/异常点」、前端口径表 domain/deviceStatus.js、domain/pointStatus.js、domain/modeLayerPlan.js、domain/deviceEffects.js,后端 CockpitMonitoringPointStatusResolver、BusinessCockpitDeviceFactResolver、AlarmClearServiceImpl(zksy-system)、BusinessCockpitMonitoringSituationAdapter,票 52 取证 verify/artifacts/t52/real-data-consequence.md,以及真实后端四个只读端点实测。
既有笔记是否够用:够用(票 52 取证 + 票 45 F1 已把事实钉死),故不另做 /research —— 本问题是业务口径拍板,没有可查的外部一手来源;缺的不是外部资料,是维护者裁定。本次新取证落盘 verify/artifacts/t71/(README.md 含复验命令)。
GET /api/cockpit/v1/map-snapshot?page=1&pageSize=1000 → unassociatedEquipment[].deviceStatus;GET /api/cockpit/v1/equipments/{code}/detail-aggregate → warnings[].status、workOrders[].stateCode、alarms[].status;WARNING,与维护者 2026-10-19 口述「未转工单的报警 > 工单 > 预警」冲突。16:45:36)| 设备 | 未处理报警 | 未解决预警 | 未结束工单(stateCode) | 后端发布 | 「工单 > 预警」新序下应为 |
|---|---|---|---|---|---|
41010500001320000002 |
0 | 2(PENDING/PROCESSING) | 1(1 待接单) | WARNING | WORK_ORDER ← 冲突 |
TEST-CBYL5432168 |
0 | 1(PENDING) | 1(4 待验收) | WARNING | WORK_ORDER ← 冲突 |
TEST-TCLLJ002215 |
0 | 1(PENDING) | 0(票面记 1,今日已无) | WARNING | WARNING(数据漂移,不影响结论) |
860347065467627 |
0 | 0 | 1(2 已接单) | WORK_ORDER | WORK_ORDER |
21119740(关联点位) |
2(UNHANDLED) | 6 | 5 | ALARM | ALARM(两种序一致) |
21119740 的 2 条未处理报警逐条查 /events/ALARM/{alarmId}/work-orders → 均 NO_WORK_ORDERS,故票 52 的窄规则不命中、发 ALARM 是对的(与票 52 库内取证一致)。读码 CockpitMonitoringPointStatusResolver.deviceStatus() 现行分支:alarm → (isAlarmsCoveredByOpenWorkOrders() ? WORK_ORDER : ALARM) → warning → workOrderInProgress → online ? NORMAL : OFFLINE。
所以第 1 问的窄三路场景(设备报警标志为真 + 全部未处理报警已被未结束工单承接 + 预警仍在)现在返回 WORK_ORDER,不是 WARNING —— 与维护者口述一致。
真正还没裁的是二路序:报警标志已清(或本来无报警)时,未解决预警与未结束工单谁在前。今天 2 台设备正是这一形态。
| # | 候选 | 置信度 | 说明 |
|---|---|---|---|
| R1 | 规格缺口:口述的「工单 > 预警」从未成文 | 高(0.8) | 票 52 只落地了「报警全承接才抬工单」的窄例外;非报警分支仍是最初序 warning → workOrderInProgress。冲突是「未成文裁定」与「已部署实现」的差,不是实现违背已写规格。 |
| R2 | 票面判据过窄,「无法实测裁定」不成立 | 高(0.8) | 二路样本今天就有 2 台、可判可复验;缺的只是三路样本,而三路在现行代码下已被判 WORK_ORDER。 |
| R3 | 「报警已全部转工单」有两种事实表达 | 中(0.5) | (a) 设备 alarm_status=1 且未处理报警逐条被承接(票 52 口径;AlarmClearServiceImpl 把「有未办结工单」当报警原因的强阻塞项,该态可持续);(b) 报警全部处理完、标志清 0,只剩预警+工单。两读法结论相反((a)=WORK_ORDER、(b)=WARNING),不裁定无法实施。 |
| R4 | 票面表格已过期(数据漂移) | 低(0.2) | TEST-TCLLJ002215 今天 0 张工单;未关联设备 8→9 台。不影响结论,但票面「三台」已变「两台」。 |
| R5 | 已排除 | 观测到的 WARNING 与 52 的规则无关(52 只在报警分支抬工单);52 规则今天仍无样本可观测。 |
CockpitMonitoringPointStatusResolver.deviceStatus() 非报警分支把 workOrderInProgress 提到 warning 之前;票 52 的保守判据(查不到 ≠ 已承接)保留。可写成:非报警时 workOrderInProgress > warning > online?NORMAL:OFFLINE。resolve()(点位聚合 min)、cards()、statistics()、orderedDevices()、map-snapshot 的 getPublishedDeviceStatus()。BusinessCockpitMapSnapshotAdapterTest、CockpitMapSnapshotControllerTest、BusinessCockpitMonitoringDistributionAdapter/ControllerTest、BusinessCockpitMonitoringPointDetailAdapter/Controller/SnapshotContractTest、CockpitPointStatusContractTest、CockpitPointStatusSnapshotSerializationTest、BusinessCockpitDeviceFactResolverTest;闸门 Cockpit*Test,BusinessCockpit*Test(基线以当时 HEAD 为准,票 52 时为 512/512)+ verify/t52-mutations.mjs。priority 不改),但观感/计数会变:DEVICE_STATUS_VISUALS 不变,可 planDeviceEffects() 的「N 台异常」口径是 ALARM/WARNING(票 07/58),那 2 台会掉出异常计数、特效由 blink 改 spin;业务轴计数 预警 3→1、工单 3→5。BusinessCockpitMonitoringSituationAdapter.metricStatus() 按事实判(isWarning() 优先于工单),不看 deviceStatus —— 改序后同一台设备会出现「地图/设备卡=工单处置、运行监测异常设备清单=预警」。CONTEXT.md 的「异常点」定义按设备 WARNING/ALARM 事实判,因此异常点可见范围不变。map-snapshot.deviceStatus 变 WORK_ORDER;21119740 仍 ALARM;分布读数随之变化。category 维持 bug(观测行为与业务口径不符);state 由 needs-triage → ready-for-human:三问都是业务口径/契约范围拍板,不是实现细节,猜不得;Q1 一旦选「改序」,即可转 ready-for-agent 返工(后端仓库 E:\pipe-ner-server 与只读库已具备,参照票 52 的交付路径)。
❓ Q1(决定要不要动)「未转工单的报警 > 工单 > 预警」是否作为正式口径落地?
➡️ 建议 A:落地(维护者 2026-10-19 已两次口述;今天 2 台设备即翻转,代价是一处分支调整 + 测试同步)。
选项:A 落地改序 → 转 ready-for-agent 返工;B 维持现状(承认「预警 > 工单」是正确口径)→ 转 wontfix 并把裁定写进 ## Answer;C 只改文档措辞、代码不动 → wontfix + 票 52 留档更正。
❓ Q2(若 Q1=A) 枚举 priority 与点位聚合是否跟着改(WORK_ORDER 提到 WARNING 之前)?
➡️ 建议 A:不改。差距只在「单设备展示序」,聚合仍表达跨设备严重度;不改则前端两张 priority 表、图例排序、t09 闸门零改动。若选 B,则后端枚举 + 前端 POINT_STATUS_VISUALS/DEVICE_STATUS_VISUALS + t09 38/38 + 契约测试一并改。
❓ Q3(若 Q1=A) monitoring/situation 的 metricStatus/异常设备清单是否跟随改序?
➡️ 建议 A:不跟随(异常点定义与预警处置口径不动,代价是同一设备两处显示不同,需在票面与代码注释留档);B 跟随则要为 metricStatus 新增 WORK_ORDER 桶(改契约 + 前端六态词表),属另一张契约票。
回了哪一项就执行对应标签动作:Q1=A → ready-for-agent + 出实施 brief;Q1=B/C → wontfix;Q2/Q3 的答案写进 brief,不单独流转。
维护者裁定(2026-10-22):Q1=A / Q2=A / Q3=A。 本票由「待裁定」转为「可实施的后端返工」,实施契约见 ## Comments 中的 Agent Brief(2026-10-22T09:30,含判定序、边界、验收与出界)。
| 问 | 裁定 | 含义 |
|---|---|---|
| Q1 | A 落地 | 单设备序正式定为「未转工单的报警 > 工单处置 > 预警」;票 52 的窄三路规则保留(它已判 WORK_ORDER),本次只补二路:非报警设备「有未结束工单」压在「有未解决预警」之前。 |
| Q2 | A 不改 | CockpitMonitoringPointStatus.priority(ALARM 1 / WARNING 2 / WORK_ORDER 3)与点位聚合 min(priority) 语义不动;前端两张词表、图例排序、t09 闸门零改动。 |
| Q3 | A 不跟随 | monitoring/situation 的 metricStatus/异常设备清单继续按设备事实判(isWarning() 优先于工单),不加 WORK_ORDER 桶;改序后「地图/设备卡 = 工单处置、运行监测异常清单 = 预警」是裁定结果,须在代码注释与票面留档。「异常点」可见范围不变。 |
verify/artifacts/t71/)41010500001320000002(2 预警 + 1 未结束工单)、TEST-CBYL5432168(1 预警 + 1 未结束工单),今日均发 WARNING;改序后应为 WORK_ORDER。TEST-TCLLJ002215 今日已无工单(票面记 1 张),只剩预警 → 两种序都是 WARNING。21119740(唯一有报警的设备)2 条未处理报警经 /events/ALARM/{id}/work-orders 核实均无工单承接 → ALARM,两序一致,票 52 规则正确不命中。a416f4ab(rebase 后),已推 origin/master,本地与远端 0/0;3 文件 +143/−9。BusinessCockpitMonitoringSituationAdapter.metricStatus() 注释留档,行为未动。CockpitMonitoringPointStatusOrderTest 9 条;Cockpit*Test,BusinessCockpit*Test 566/566。verify/t71-mutations.mjs 4/4 打红并字节还原(含「偷改枚举优先级」这条 Q2 pin)。verify-after-deploy.mjs 10/10:两台由 WARNING 翻 WORK_ORDER;TEST-TCLLJ002215 仍 WARNING、21119740 点位仍 ALARM;未关联设备业务轴 预警 3→1、工单 3→5,与部署前预演表逐项一致;monitoring/situation 不出现 WORK_ORDER(Q3 成立)。载荷见 verify/artifacts/t71/after-deploy/。3c734fe9 使 zksy-system 测试源码编译不过(WaterSupplyDeviceServiceImplTest 两处多一个 ))。按维护者 2026-10-23 指令直接删除该测试类(提交 a13dcaf5,395 行 / 13 个测试随之移除,内容可从 c654d3f9 取回),-pl zksy-admin -am 闸门恢复,清理后 Cockpit*Test,BusinessCockpit*Test 566/566、变异闸 4/4 复跑通过。resolved(已实施、测试与变异闭环、已推送、真实读数复验已通过)。验收项全部闭环;verify/artifacts/t71/verify-after-deploy.mjs 可随时重跑回归。