PASS A1-frame-shape-from-backend — 帧类型名照抄后端 handleAuthenticate/handleCockpitSubscribe/cockpitDeltaMessage PASS A2-delta-carries-point-code — 顶层 monitoringPointCode=MP-001(点位联动的唯一依据) PASS A3-null-point-code-normalised — 未关联设备的 monitoringPointCode 归一为 ""(不会误当成点位码 "null") PASS A4-subscribed-has-no-device-array — 订阅回帧只有 scope/serverUpdatedAt —— 不假装它带了初始状态(初始快照归 REST) PASS B1-connecting-first — 建连后状态 connecting PASS B2-subscribe-directly-without-authenticate — 客户端发出的帧:cockpitSubscribe(免鉴权:open 后直接订阅 all,无 authenticate 帧) PASS B3-stale-token-never-sent — 传入的旧 token 不进任何帧(ADR 0005 修订:WS 免鉴权) PASS B4-open-after-subscribed — 握手完成后状态 open PASS B5-silent-push-stays-subscribing-or-open — 订阅成功但无增量:只发 1 帧 cockpitSubscribe,状态 open(不伪造 open,也不崩) PASS C1-newer-accepted-older-rejected — 严格更新才采纳:更晚 → true;更早/相同 → false PASS C2-compares-instants-not-strings — 同一时刻的不同偏移写法判为"不更新"(按 epoch 比,不按字符串) PASS C3-unparsable-timestamp-rejected — 时间认不出的帧不采纳(宁可漏一次,也不让乱序旧值盖掉新值) PASS C4-merge-rejects-stale-without-copy — 旧帧被丢弃(reason=STALE),状态表仍是 ALARM 且引用未变 PASS C5-rejects-without-device-or-status — 缺设备编码/缺状态的帧各有明确丢弃原因(不把已知状态抹成"未发布") PASS D1-only-affected-object-changes — 只有 MP-002 改状态(MP-002);MP-001/MP-003 原样 PASS D2-untouched-keep-identity — 未命中的元素**保持同一引用**(消费方据此只重画变动的那几个),顺序与长度不变 PASS D3-does-not-touch-geometry — 坐标/名称/关联设备一概不动(推送不带这些字段,凭空补就是编数据) PASS D4-same-status-is-noop — 状态没变时不产生新数组(同值推送不引起无谓重渲染) PASS D5-unknown-point-is-ignored — 推送指名了不在已加载范围的点位 → 不改任何对象(不是错误,可能还没翻到那一页) PASS E1-point-status-updated-in-place — MP-002 就地变 ALARM,MP-001 仍是 NORMAL PASS E2-open-detail-status-updated — 已打开的详情状态随之更新为 ALARM,其余字段保持快照里的值 PASS E3-selection-mode-panel-scroll-untouched — 当前模式/展开面板/选中对象/滚动位置全部原样(模式=warningResponse、选中={"level":"none","pointCode":"","deviceCode":""}) PASS E4-detail-not-refetched — 推送更新**不触发取数**(不重新拉详情、不换层级,浮层因此不闪) PASS E5-unrelated-point-untouched — 指名别的点位时,已打开的这个详情不动 PASS E6-unassociated-updates-device-only — 未关联设备只落设备维度(对象数组引用未变 → 地图不重画) PASS E7c-later-page-gets-cached-push-status — 第 1 页 ["MP-001:NORMAL","MP-002:ALARM"] → 推 MP-003=ALARM(当时还没翻到,图上不变)→ 第 2 页 ["MP-001:NORMAL","MP-002:ALARM","MP-003:ALARM","EQ-FREE-001:"]:MP-003 显示推送值 ALARM(不是快照里的 WARNING) PASS E7d-refresh-lets-snapshot-win — 刷新后对象 ["MP-001:NORMAL","MP-002:ALARM","MP-003:WARNING","EQ-FREE-001:","EQ-FREE-004:"] → MP-003=WARNING(快照值 WARNING、无 push 标记)= 显式重新取数以快照为准 PASS F1-disabled-when-no-url — 未配地址 → disabled(「状态推送未配置」) PASS F2-retrying-state-observed — 连接状态序列:connecting → subscribing → open → retrying → connecting → subscribing → open(含重连中) PASS F3-reconnect-actually-happens — 工厂建了 2 个连接,重连后状态 open(真的重连了,不是只改文案) PASS F4-deltas-delivered-before-drop — 掉线前收到 5 条增量(每条都有设备编码) PASS G1-backoff-grows-and-caps — 退避 1000/2000/5000/10000/15000 毫秒,末档封顶(长跑后重连间隔不无限增长) PASS G2-disconnect-cancels-reconnect — 断开前还有 1 个待触发定时器,disconnect 后剩 0 个、状态 idle PASS H1-shell-knows-no-protocol — 外壳只读 runtimeStore 的状态与文案,不认识帧类型与 socket PASS H2-shell-shows-state — 外壳把连接状态画出来(data-ws-state 是走查断言面) PASS H2b-shell-knows-no-mock-socket — 外壳不认识脚本化假连接(mock/real 的连接方式归 store) PASS H3-store-has-no-socket — runtimeStore 只调运行时服务,不自己建连/发帧 PASS H4-domain-pure — domain/statusPush.js 是纯函数(不发请求、不 import service) PASS H5-shell-no-credential — 外壳不碰凭据(连 ws.token 这个字段名都不出现) PASS H5-store-no-token-plumbing — runtimeStore 不再转交 token(免鉴权后 WS 只从 ws.token 读——且仅由 store 旧路径兼容保留) PASS H5-domain-no-credential — domain/statusPush.js 不碰凭据 PASS H6-subscribe-directly-no-authenticate-send — 服务里只有 cockpitSubscribe 一个发送点,不再发送 authenticate 帧 PASS H7-runtime-service-knows-no-data-store — 运行时服务不认识任何数据 store —— 推送异常在结构上不可能牵连数据分区 T15 状态推送检查:43/43 项通过。 T15 状态推送全部通过。