28-28.md 10 KB

28: 后端执行票 —— 无关联设备监测点被静默丢弃(计数不对称)

Type: task Status: resolved Assignee: codex Labels: ready-for-agent, wayfinder:task Category: backend-execution

进度

已完成并关闭:七文件修复、新增六项契约回归、八模块编译、423项契约测试、12项真实只读验收、提交推送均完成。提交 ba0ce076 已快进合入并推送 origin/master;修复分支同步保留,未混入其他会话未提交改动。

已读全票面/评论/标签/依赖并认领;初始 ready-for-agent,无 needs-triage、无阻塞、无历史实施,根因核验属实。初始后端基线 master=740d896;期间并行会话推进到 0a6b108 且有 workorder 在途改动,本票未触碰其文件。因后端目录在沙箱外,第一次 git apply 被拒绝;随后同一命令经扩展权限成功应用七文件补丁。

交付:distribution 保留无设备未知类型点位为 EMPTY,坐标只控制呈现、不控制统计/分页/筛选;类型排除按对象自身计1;invalidCoordinateCount 保留为统计排除兼容字段0,每对象 coordinateValidation 保留真实不可上图原因。按原始关联事实去除全量设备的关联重复,且筛后才发布 deviceCodes。overview 真实适配器发布去重关联数,兼容旧构造器(-1表示未知),点位计数与pointCodes同源;信封freshness不将空点台账误报无数据,设备在线率分母口径保留。

新增六个契约回归,覆盖六个未知空点、分布分页/筛选/未知桶、坐标独立统计、关联去重与回显、按对象排除对账、overview计数/关联事实。既有越界设备总数8→9、NORMAL1→2及增量预期同步。

验证:git apply --check 与应用后 git diff --check 均通过。双线审查:Standards 无硬性违规,Spec 0项可确认问题;命名建议已落实。用户在本轮明确授权编译、契约测试和现有8301只读复验(未包含服务重启)。Maven八模块 BUILD SUCCESS,Cockpit*Test/BusinessCockpit*Test 合计423项(system 2 + admin 421),Failures/Errors/Skipped均0,含新增六项回归。编译第一次因工作区外target写权限失败,同命令扩展权限重试成功。

真实复验最终通过(2026-10-12 10:05–10:08):维护者确认IDE重启后,map-snapshot与overview点位均6;distribution的EMPTY=6、total=13(6点+7未关联设备),13候选=13纳入+0排除,excluded四字段均0;六点仍renderable=false,freshness=CURRENT/READY。EMPTY、未分区与正式行业筛选边界全部正确,真实断言12/12通过。重启前旧实例曾返回overview0/distribution0,历史证据另存重启前结果,不覆盖为成功结果。完整记录见运行验证记录、当前只读响应与验收断言。

隔离提交快照复验:从已推送master基线894402a建立独立分支,只应用本票补丁;2026-10-12 10:14再次八模块BUILD SUCCESS,契约测试仍423/423。提交仅七文件(242增/62删),已先推独立分支并随后快进推送到 origin/master;远端 master 与修复分支当前均指向 ba0ce076。共享后端工作树中的其他并行改动未被纳入本次快进。

资产:补丁与验收说明、可应用补丁、只读研究笔记。前端现存坐标统计标签、null行业文案、pagination.total标名风险已写入说明,留阶段联调核对。

本票无待验收项,resolution comment已发布,按票面交付要求关闭;ba0ce076已合入远端master。合并后检查发现共享后端本地master由并行会话新提交八桶契约7fb7c2c,与远端master各有一个提交,且存在其在途修改;本轮未覆盖或重置该工作树,后续八桶集成需保留本票master提交。前端既有展示标签风险留阶段联调核对,八桶状态扩展归其独立执行票。

来源

票 18 真实联调实测(2026-10-10 16:15)+ 用户反馈「监测点没有获取到正确的接口,后端一共有六个未关联设备的监测点」。

口径决策(维护者裁定:方案 A,2026-10-10)

采用方案 A:无关联设备的监测点是合法监测点,按其真实 EMPTY(无设备)状态计入总数与状态分布,不得静默丢弃。

依据:CONTEXT.md 的「点位状态」把「无关联设备 / 无设备」列为六个合法状态之一。既然该状态是合法点位状态,无关联设备的点位就不该从统计中消失;否则界面显示「监测点 0 个」是对真实台账的误报。

(未采用的方案 B:按点位自身计 1 记入 excluded 新增的「无类型点位」计数,界面仍显示 0 个。裁定为 B 会继续让合法点位不可见,不采纳。)

现象

后端确有 6 个监测点(GS001/GS002/PS001/PS002/RQ001/RQ002,均 pointStatus=EMPTY、deviceCodes=[]、无关联设备),但运行监测模式的两个端点都报 0:

端点 监测点数
GET /map-snapshot 6(正确返回)
GET /monitoring/overview 0
GET /monitoring/distribution 0(pagination.total=0,pointStatusDistribution.EMPTY=0)

静默丢弃:excluded 里 unknownTypeCount=0、typeKindMismatchCount=0、invalidCoordinateCount=7(仅 7 台未关联设备),6 个监测点既未计入总数,也未计入任何排除计数,完全消失。

自相矛盾之处:后端自己在 map-snapshot 已判定这 6 个点位为 EMPTY,而 monitoring/distribution 的 EMPTY 桶却是 0。

补充事实:这 6 个点位有真实经纬度(如 GS001 为 110.399876, 28.458287),只是缺可信坐标校核来源而 renderable=false。因此它们「可统计、暂不上图」是两件独立的事,不应互相阻断。

根因(已定位到行)

CockpitMonitoringDistributionService 点位循环(约 258–270 行):

String mismatch = classify(type);
List<CockpitMonitoringPointDeviceSnapshot> devices = safeDevices(point.getDevices());
if (mismatch != null) {
    int amount = devices.size();        // ← 这 6 个点位 devices.size() = 0
    if (UNKNOWN_TYPE.equals(mismatch)) {
        unknownTypeCount += amount;     // ← 加 0,等于没记录
    } ...
    continue;                           // ← 被丢弃
}

这 6 个点位无关联设备,typeCode 不可推导而 mismatch != null,于是进入排除分支;但排除计数按「设备数」累加,而它们设备数为 0,所以既没进 marker 列表,也没进任何 excluded 桶。

对比同文件设备循环(约 326–334 行):设备走同样分支时是 unknownTypeCount += 1(按设备自身计 1)。点位按设备数计、设备按自身计,两侧口径不对称,无设备点位因此被抹掉。

连锁效应:hasResolved = !deviceCodes.isEmpty()(约 444 行),而 deviceCodes 只在坐标校验通过后收集;坐标未校验 → freshness=EMPTY / NO_RESOLVED_DEVICES,把「设备坐标未校验」误报成「无设备」。

适配器层(BusinessCockpitMonitoringDistributionAdapter)正确构建了这 6 个点位,丢失发生在 Service 层。

范围

  1. 按方案 A 落实口径:无关联设备的点位按 EMPTY 计入 monitoring/distribution 的状态分布与 pagination.total;不得因设备数为 0 而丢弃。
  2. 坐标未校验与「无设备」是两件事:统计不因坐标未校验而排除,只是不上图。坐标校验只作用于「能否上图」,不得影响「是否计入统计」。
  3. 修正排除计数口径:点位按点位本身计(或显式区分「无类型点位」计数),消除点位/设备两侧不对称。
  4. 修正 hasResolved / NO_RESOLVED_DEVICES 语义:区分「确实无设备」与「设备坐标未校验」。
  5. monitoring/overview 的 monitoringPointCount 同源核对:修复后应与 map-snapshot 的监测点数一致(6)。
  6. 补契约测试:无关联设备点位必须可见(计入 EMPTY 桶),且统计不受坐标未校验影响。

验收

真实环境复验:monitoring/overview 的 monitoringPointCount = 6 且与 map-snapshot 一致;monitoring/distribution 的 EMPTY 桶 = 6、pagination.total ≥ 6;excluded 各计数之和与「总数 − 纳入数」可对账(6 个点位不再凭空消失);NO_RESOLVED_DEVICES 不再误报。编译 + Cockpit*Test 全绿 + 提交推送。

关联

发现于票 18;与 票 20(管网编码漏计)同族——均为「未分类对象被静默丢弃而非如实计数」。坐标未校验导致的不可上图属另一问题,归 票 24。

Comments

local — 2026-10-12T02:21:28.625Z

Resolution:无设备未知类型监测点按 EMPTY 保留,坐标校验仅控制上图;排除计数按点位/独立设备自身计1,分布按原始关联事实去重并只回显筛后设备。overview补显式关联事实且点位数与pointCodes同源,台账freshness与设备在线率空态分离。

验收完成:本票新增六项契约回归;共享工作树和隔离提交快照均八模块BUILD SUCCESS,Cockpit*Test/BusinessCockpit*Test合计423/423通过(system2 + admin421),0失败/错误/跳过。维护者IDE重启后,真实只读复验12/12通过:map与overview点位均6;distribution EMPTY=6、total=13(6点+7未关联设备);13候选=13纳入+0排除,六点仍renderable=false,freshness=CURRENT/READY;EMPTY/UNASSIGNED/GAS边界均通过。

交付提交:ba0ce076f3,已推 origin/fix/cockpit-empty-monitoring-points。因共享后端有八桶契约并行改动,使用独立工作树提交,仅包含本票七文件,未改动/切换其master工作树;未声称已合入master。

证据:运行验证记录、12项真实断言、补丁说明。本票交付与验收全部完成,关闭;前端既有展示标签风险和八桶扩展不纳入本票。