34-coordinate-auto-admission.md 22 KB

坐标自动准入(取消人工校核前置)与主场景区边界冲突

Type: implementation Status: resolved Assignee: codex Label: ready-for-agent Blocked by: None Category: backend-coordinate-admission

进度

✅ 2026-10-12 结票:独立复核 + 落库缺口已闭合

结论:本票交付物成立,已关闭。 本轮不是采信既有票面,而是从远端与线上重新取证;过程中发现并跟踪了一处票面未记录的落库缺口,该缺口已由并行会话闭合,我逐位核对无误。

一、独立复核(我自己跑,未采信执行 agent 汇报)

复核项 证据 判定
判据实现 E:\pipe-ner-server 工作区 CockpitCoordinateValidator:MISSING_* → *_OUT_OF_RANGE → ZERO_COORDINATE → OUTSIDE_PRIMARY_AREA → VALID;coordinateVerified 不再参与判定 ✅
线上 map-snapshot 只读 GET 192.168.110.96:8301:renderableCount=12、totalObjectCount=15、invalidCount=3、unverifiedCount=0;3 个 INVALID 全为 MISSING_LONGITUDE ✅
线上 infrastructure/geometry 5272 feature:VALID 5269、INVALID 3(LONGITUDE_OUT_OF_RANGE×2、OUTSIDE_PRIMARY_AREA×1) ✅
零残留 扫 5 个 cockpit 端点(map-snapshot / monitoring distribution / monitoring situation / base-archives / geometry),UNVERIFIED 与 UNVERIFIED_COORDINATE 出现次数均为 0 ✅
被挡几何原值 逐条读线上原值:YL-YJ-001/YL-YJ-002 = 1212,1212(LONGITUDE_OUT_OF_RANGE)、GD-001 = 12,12(OUTSIDE_PRIMARY_AREA)——与票面下表一致 ✅
跨界管线 用 map.primaryArea.bounds 独立重算 5272 条几何:完全在区内 5268、跨边界 0,票面「跨界 0 条」成立 ✅
前端契约 跑 t07-coordinate.mjs → 39/39 通过;t24-pipe-layer.mjs C7(区外专属文案)通过;COORDINATE_REASON_TEXT 含 OUTSIDE_PRIMARY_AREA ✅
文档同步 ADR 0002、ADR 0005、ADR 0009、cockpit-deployment.md 自检步骤均已改为自动准入口径 ✅
管理端零引用 E:\city-life-line 全仓搜 coordinateValidation/coordinateVerified/CockpitCoordinateValidator → 0 命中,反证「既无校核字段也无校核入口」 ✅
后端改动范围 8013a207 触及 15 个文件(13 个测试 + 判据 + docs/cockpit/README.md);1427a67e 触及 6 个适配器注释——全部在 cockpit 包内,无越界改动 ✅
测试名如实改名 3 处方法名按新语义改名(如 invalidEndIsNotMaskedByAnUnverifiedStart… → …ByAValidStart…),不是把断言反过来 ✅

二、本轮发现并跟踪的落库缺口(已闭合)

复核中发现:后端修复提交当时只在 E:\pipe-ner-server 本地 master,未推送任何远端,而 origin/master 上仍是旧的 if (!coordinateVerified) → UNVERIFIED 判据——即「从 origin/master 部署会把整个修复静默回退」。这与本 effort Notes 的基线锚点(「仓库提交(分支+哈希+已推送)」)及票 31/20/12/13 的收口口径都不符,因此票面原先并未记录这一事实。

经维护者裁定后核对,该缺口已由并行会话闭合,我独立确认:

  • 真实远端 refs/heads/master = d81c977b(git ls-remote,非本地跟踪引用);f33ef570 已是 origin/master 祖先。
  • origin/master 上的 CockpitCoordinateValidator 代码体已是新判据(if (!insidePrimaryArea(...)) → OUTSIDE_PRIMARY_AREA),旧的 if (!coordinateVerified) 只剩 javadoc 里描述历史的那一句,代码中无该门槛。
  • rebase 前后 patch-id 逐位相同:8013a207 → f33ef570、1427a67e → d81c977b——证明变基是内容等价的重放,没有夹带改写。
  • 因此票面 8013a20/1427a67 与线上 f33ef570/d81c977b 是同一改动的两个哈希(rebase 重写),后续引用以远端哈希为准。

三、前端落库状态:修复提交 bf8d21b 已是前端 origin/master(5cc5d036…)祖先。本地另有 2 个未推送提交(c4aa10e/21fbbe5)属票 24 几何接线与票 32-构件素材,不触碰坐标准入门径,与本票无关。

四、未闭合项:3 条脏几何(YL-YJ-001/002 = 1212,1212;GD-001 = 12,12)属业务侧数据订正,非代码问题——判据在如实工作。本票按自身交付物(取消人工校核前置 + 区外自动准入 + 口径裁定)收口,该数据项保留在「待办」并转业务侧,不阻塞本票关闭。


✅ 2026-10-12 维护者重启后端,真实接口闭环复验通过。 后端 8013a20:CockpitCoordinateValidator 改为「结构合法 + 主场景区内」自动准入,新增 OUTSIDE_PRIMARY_AREA,coordinateVerified 不再影响结论;12 个测试文件重基线 + 新增 21 例判据单测。

重启后实测(真实在线接口,非离线复算):

端点 修复前(旧构建) 重启后实测 离线探针预测 一致
/map-snapshot 可上图 0 / 15 12 / 15 12 / 15 ✅
/map-snapshot unverifiedCount 15 0 0 ✅
/map-snapshot invalidCount 0 3(均 MISSING_LONGITUDE) 3 ✅
/infrastructure/geometry 可上图 0 / 5272 5269 / 5272 5269 / 5272 ✅
逐对象 state 全 UNVERIFIED 12×VALID/renderable:true、3×INVALID/MISSING_LONGITUDE — ✅

真实接口结果与重启前用已编译生产判据对同一批数据做的离线预测逐项吻合,说明预测方法与线上行为一致。零 UNVERIFIED 残留。

验证(均由我本人在落盘后独立复跑,非仅采信执行 agent 汇报):

  • 针对性 -Dtest=*Cockpit*Test,*BusinessCockpit*Test → 486 / 0 / 0,BUILD SUCCESS(基线 465 / 15F / 1E)。
  • 全量 -pl zksy-admin -am test → 全 reactor BUILD SUCCESS,zksy-admin 505 / 0 / 0。

前端 bf8d21b:原因词表同步 + t07 39/39。真实数据离线复算可上图 12/15 与 5269/5272。

第二轮补强(非自证式验证 + 文档/注释同步)

  • 真实接口数据 × 已编译生产判据联测(verify/artifacts/t32/LiveCoordinateAdmissionProbe.java,只读):把真实后端导出的 15 个地图对象 + 5272 条几何坐标喂给线上要跑的那一份 CockpitCoordinateValidator(而非另写的复算脚本),四项断言全 PASS:map 12/15、geo 5269/5272、原因码分布 MISSING_LONGITUDE=3 / LONGITUDE_OUT_OF_RANGE=2 / OUTSIDE_PRIMARY_AREA=1、零 UNVERIFIED。
  • 过程中探针自身出过一次解析错误(把经度当编码、只把纬度当载荷,误报 map 3/15);修正后重跑通过。该错误只影响探针读数,不触及生产判据——如实记录以免后来者误读中间结果。
  • 更正一处旧结论:那 3 个被挡的地图对象(41010500001320000001、41010500001320000002、TEST-CBLL222222222)经查响应里 longitude/latitude 是真正的 null(缺坐标),本票早前写的「(0,0) 零坐标」是我的读数误判。结论不变(都该被挡下),新判据下原因是 MISSING_LONGITUDE。
  • 管理端 E:\city-life-line 无需改动,已核实:它对 coordinateValidation / coordinateVerified 零引用——这反过来印证了根因(既无校核字段、也无校核入口)。
  • 同步 6 处会误导后人的注释(后端 1427a67):各适配器 javadoc 原先写着「无校核字段 → 按未校核上报、由契约层判定为不可渲染」——这正是本次 bug 的认知来源,判据改了而注释不改,下一个人会照原路再走一遍。纯注释改动,改后复跑仍 486 / 0 / 0。
  • 同步 4 份文档(f9c89ba):ADR 0002 原句「未通过校验的对象不上图」、ADR 0005、cockpit-deployment.md 的自检步骤与可观察字段表——按项目「代码优先」规则更新为 2026-10-12 自动准入口径。部署文档原先教运维「若真实数据均未校验,记为无可上图样本」,不改会让人把正常状态当缺口上报。
  • 前端 5096454 修正 coordinate.js 头部注释「六取一」→「七取一」。

一处数字纠正如实记录:我最初推算 CockpitMapSnapshotControllerTest 汇总应为 renderableCount=7 是错的——7 个对象里 EQ-FREE-001(181)与 EQ-FREE-004(0,0)仍非法,可上图应为 3 个点位 + 2 个设备 = 5。执行 agent 按实测写 5 / 2 / 0 并纠正了我,票面以实测为准。

与本次无关的既有失败(已独立复核归因):zksy-system 的 AlarmLifecycleServiceTest.insertWritesLogBeforeCommittingWithoutTrigger —— 断言期望的日志串与实现不一致(alarmContent 已含「实际值/阈值」格式化文本,被再次拼接),单跑复现 same failure;该 alarm 域对 cockpit 零引用,物理上不受本次改动影响。未擅自修它。

待办:① 维护者重启后端加载新构建;② 重启后复验 renderableCount=12 / unverifiedCount=0;③ 对区外口径 A(严格小区块,当前实现)vs B(放宽到影像覆盖范围以保住框外可定位)拍板——本实现与 ADR 0009 的框外定位例外存在冲突;④ 2 条经度越界窨井属真实数据错误,需业务侧订正。

来源

维护者 2026-10-12 实报:真实后端有大量监测点、设备点位与管线数据,但一个都没有上屏,全部显示「坐标未经校验」,且找不到任何校验入口。随后裁定:取消该人工校核步骤(「所有进入数据库中的点位坐标都是已经过校验后的了」),或改为自动规则——只有落在主场景区内的坐标才正常显示。

现象与实测(修复前)

对真实后端 192.168.110.96:8301 只读 GET:

端点 对象数 可上图 未校验 非法
/map-snapshot 15 0 15 0
/infrastructure/geometry 5272 0 5270 2(经度越界)

样本 GS001 坐标 110.399876, 28.458287 数值完全正常,仍被判 UNVERIFIED_COORDINATE / renderable=false。

根因(已确认)

判定链三段,每段都指向同一个缺失:

  1. CockpitCoordinateValidator.validate() 第一道判断是 if (!coordinateVerified) return UNVERIFIED/renderable=false——未校核优先于所有数值检查。
  2. 真实适配器一律传 false:BusinessCockpitMapSnapshotAdapter(监测点、设备)、BusinessCockpitDeviceFactResolver、CockpitFacilityGeometryService(先用 true 做结构检查,通过后再故意用 false 降级成未校核)。
  3. 全后端搜索没有任何一行代码把 coordinateVerified 置为 true;monitor_point、equipment_base、pipe_network_base 都没有校核列;管理端也没有任何校核接口或页面。

前端没有误判:唯一准入判据只认后端 renderable === true,后端给 false 就不画——按原契约是正确行为。后端 docs/cockpit/README.md 自己也写过「可信坐标校核来源需另行排期」,即这是已知契约缺口,不是前端 bug。

维护者裁定

  • 不做人工校核入口(该步骤没有必要,入库坐标即视为可信来源)。
  • 改为自动规则:数值合法 + 落在主场景区内才可上图。
  • 范围选择:只用主场景小区块(map.primaryArea.bounds),不用更大的影像覆盖范围。

实施(已完成)

判定顺序(唯一一处 CockpitCoordinateValidator):

  1. 缺经度 → INVALID/MISSING_LONGITUDE
  2. 缺纬度 → INVALID/MISSING_LATITUDE
  3. 经度越界 → INVALID/LONGITUDE_OUT_OF_RANGE
  4. 纬度越界 → INVALID/LATITUDE_OUT_OF_RANGE
  5. 零坐标 → INVALID/ZERO_COORDINATE
  6. 数值合法但区外 → INVALID/**OUTSIDE_PRIMARY_AREA**(新增原因码)
  7. 其余 → VALID/reason=null/renderable=true

结构错误优先于区外判定,因此既有的非法坐标拦截一条都没有被削弱。coordinateVerified 入参保留(不改 16 处调用点)但不再参与判定;新流程不再产生 UNVERIFIED。

  • 无数据库改动,无管理端改动,不伪造坐标。
  • 前端 COORDINATE_REASON_TEXT 同步新增 OUTSIDE_PRIMARY_AREA → 「不在主场景区范围内」。
  • 后端文档 docs/cockpit/README.md 的坐标章节已同步改写(原「未验证禁止渲染」表述作废)。

实测效果(真实接口数据 × 已编译生产判据)

用编译好的生产类 CockpitCoordinateValidator 逐条判定从真实接口导出的坐标(探针 verify/artifacts/t32/LiveCoordinateAdmissionProbe.java,只读):

端点 修复前可上图 修复后可上图 被挡下(按原因码)
/map-snapshot 0 / 15 12 / 15 MISSING_LONGITUDE ×3
/infrastructure/geometry 0 / 5272 5269 / 5272 LONGITUDE_OUT_OF_RANGE ×2、OUTSIDE_PRIMARY_AREA ×1

被挡下的 3 个地图对象是 41010500001320000001、41010500001320000002、TEST-CBLL222222222——经核实它们的 longitude/latitude 在响应里是真正的 null(缺坐标),不是零坐标。探针断言 map 12/15、geo 5269/5272、零 UNVERIFIED 三项全部 PASS。

(早前本票一度把这 3 个写成「(0,0) 零坐标」,那是我读数的误判,已在此更正;结论不变——它们本就该被挡下。)

额外核对:没有一条管线跨越主场景区边界(跨界 0 条),所以小区块不会把管线切坏或让整段变 geometry=null。

被挡下的 3 条几何 —— 均为业务侧脏数据(非判据问题)

已逐条读出原值,可直接交业务侧修正;不需要也不应该由代码"顺手"改:

来源 编码 名称 原始坐标 原因码 判读
manhole_base YL-YJ-001 沅陵县窨井001 1212, 1212 LONGITUDE_OUT_OF_RANGE 疑似把 121.2,121.2 的小数点漏了,或占位值未替换
manhole_base YL-YJ-002 沅陵县窨井002 1212, 1212 LONGITUDE_OUT_OF_RANGE 同上
gas_pipe_point GD-001 管点001 12, 12 OUTSIDE_PRIMARY_AREA 数值合法但不在沅陵,明显是占位/测试数据

三者都本该被挡下:判据在如实工作,不是判据误伤。修正归业务侧(equipment_base / 管点表直接改值),或确认为测试数据后清理。

验证

  • 后端针对性测试:mvn -o -pl pipe-network-service/zksy-admin -am test "-Dtest=*Cockpit*Test,*BusinessCockpit*Test" "-DfailIfNoTests=false" → 486 / 0 / 0,BUILD SUCCESS(我自己复跑确认,非仅采信执行 agent 汇报)。
  • 后端全量测试:mvn -o -pl pipe-network-service/zksy-admin -am test → 全 reactor BUILD SUCCESS,zksy-admin 505 / 0 / 0(同样自己复跑确认)。
  • 新增 CockpitCoordinateValidatorTest 21 用例:区内 VALID、东南西北四向区外 OUTSIDE_PRIMARY_AREA、闭区间四角边界命中与边界外一丁点不命中、结构错误优先于区外、数值合法但区外、coordinateVerified 传 true/false 结论完全一致、insidePrimaryArea(null,*) 两个方向 → false。
  • 12 个受影响的既有测试文件已按新契约重基线;非法坐标参数化用例 CsvSource 一行未改(181、-181、91、-91、(0,0)、null 全部保留作结构错误样本),原始坐标保留断言与「被拦对象仍计入统计」断言均保留;3 处语义自相矛盾的方法名已如实改名(不是把断言反过来)。
  • 前端 t07-coordinate.mjs 39/39 通过(原因词表 6 → 7 已同步)。
  • 真实数据 × 已编译生产判据联测(本轮新增,非自证式):LiveCoordinateAdmissionProbe 读取真实接口导出的 15 个地图对象 + 5272 条几何坐标,逐条调用线上要跑的那一份 CockpitCoordinateValidator(不是另写的复算脚本),结果 map 12/15、geo 5269/5272、零 UNVERIFIED 三项断言全部 PASS。过程中探针自身出过一次解析错误(把经度当编码、只喂纬度,误报 map 3/15),已修正并重跑;这类错误只影响探针读数,不影响生产判据。
  • 已确认与本变更无关的既有失败:前端 t17(MANAGEMENT_REGION_GAP 导出缺失)、t05 D1(overviewStore.js 出现 deviceStatistics,并行会话在改);后端 AlarmLifecycleServiceTest 既有失败(还原 validator 到 HEAD 后原样复现)。

✅ 区外口径已裁定:A(严格主场景区)

ADR 0009 与票 37 在 2026-09-28 曾裁定「点选/定位到框外对象是例外」;本次准入规则让区外对象 renderable: false,与此例外存在张力。

2026-10-12 维护者裁定:选 A(严格区块)。 已同步修订 ADR 0009:

  • 准入保持严格主场景区,接受「框外点位不上图、不可定位」。
  • 该例外经产品路径已不可达(mapLocate 对不可上图对象返回 BLOCKED;selectMonitoringPoint 先过 isRenderable),不会再出现"点选框外对象、镜头飞出去"。
  • 相机层的例外实现(cameraControl.js 定位豁免 + outsideArea 读数)保留不删:它是相机层的正确保证,票 37 用例继续有效。
  • 同源警告已写入 ADR:准入矩形在后端是常量、在限位侧是配置 map.primaryArea.bounds,当前两者逐位相同;改配置必须同时改后端常量。

影响面:当前真实数据全部落在区内,所以今天无可见行为差异;差别只在未来接入框外合法点位时——那时按 A 它们不上图、留在清单并显示 OUTSIDE_PRIMARY_AREA 原因。

待办

  • 维护者重启后端实例加载新构建(2026-10-12 已完成)。
  • 重启后复验真实接口:map-snapshot 12/15、unverifiedCount=0;infrastructure/geometry 5269/5272(已完成,见上表)。
  • 区外口径拍板:选 A(严格主场景区),已同步 ADR 0009(2026-10-12)。
  • 独立复核会话重跑取证并结票(2026-10-12,见「进度」与 Comments)。
  • 3 条脏几何数据(YL-YJ-001/002 = 1212,1212;GD-001 = 12,12)需业务侧订正或确认为测试数据后清理——见下表,属数据问题、非代码问题。已转业务侧,不阻塞本票。
  • 本票原与 32-32.md(管线构件 glTF 素材)共用编号 32,属 tracker 重号缺陷;2026-10-12 已改号为 34(34-coordinate-auto-admission.md),重号解除。

Out of scope

  • 前端管线图层接线(/map-facilities → /infrastructure/geometry 路径不匹配)——维护者明确指示「管线先放着,本来也还没开发完全」,归票 24。
  • 人工坐标校核字段、校核人/时间/来源与回填——已被本次裁定取消,不再需要。
  • 后端其它业务路径与写接口。

Comments

local — 2026-10-12T21:05:00.000Z

结票(独立复核会话)。按 wayfinder 规则先把票读全(正文/评论/字段行/父子与阻塞边),再对抗式复核交付物。

复核结论:交付物成立,票关闭。我自己重跑取证而非采信票面——线上只读复验 map-snapshot 12/15、unverifiedCount=0、3×MISSING_LONGITUDE;infrastructure/geometry 5269/5272(LONGITUDE_OUT_OF_RANGE×2 + OUTSIDE_PRIMARY_AREA×1);5 端点扫描 UNVERIFIED 零残留;5272 条几何按 primaryArea.bounds 独立重算跨界 0 条;t07 39/39、t24 C7 通过;ADR 0002/0005/0009 与部署文档均已同步;管理端 E:\city-life-line 零引用;两个后端提交全部落在 cockpit 包内。

本轮新发现(票面原先未记录):后端修复当时只在本机 master、未推送任何远端,origin/master 仍是旧判据——「从远端部署会静默回退整个修复」。经维护者裁定后核对,该缺口已由并行会话闭合:真实远端 master=d81c977b,f33ef570 已是其祖先,远端代码体为新判据(旧 if (!coordinateVerified) 仅存于 javadoc 的历史描述),且 rebase 前后 patch-id 逐位相同(8013a207→f33ef570、1427a67e→d81c977b),证明是内容等价重放。票面旧哈希与新哈希为同一改动。

前端 bf8d21b 已在 origin/master;本地 2 个未推送提交属票 24/32-素材,与坐标准入无关。

未闭合项仅剩 3 条脏几何数据(1212,1212×2、12,12×1),属业务侧订正、非判据问题,已保留在待办并转业务侧,不阻塞本票。

方法论记录:核对「是否已推送」必须用 git ls-remote 读真实远端 + git show origin/master:<file> 读远端内容,不能只看本地跟踪引用或 git status -sb——并行会话会在本地引用滞后期间改变远端。

local — 2026-10-12T11:07:12.071Z

实施已完成并提交:后端 8013a20(判据重写 + 13 个测试重基线 + 新增 16 例 CockpitCoordinateValidatorTest + docs/cockpit/README.md 同步),前端 bf8d21b(原因词表新增 OUTSIDE_PRIMARY_AREA + t07 回归同步,39/39 通过)。自验:mvn -o -pl pipe-network-service/zksy-admin -am test "-Dtest=*Cockpit*Test,*BusinessCockpit*Test" "-DfailIfNoTests=false" → 486/0/0 BUILD SUCCESS(我本人复跑,非仅采信队友汇报)。红线复核:非法坐标参数化 CsvSource 一行未改,原始坐标保留断言与「被拦对象仍计入统计」断言均保留;3 处语义自相矛盾的方法名已如实改名。真实数据离线复算:map-snapshot 可上图 0/15 → 12/15(挡下 3 个 (0,0)),geometry 0/5272 → 5269/5272;跨界管线 0 条。未重启/未构建(遵守 AGENTS.md),真实接口仍是旧构建 renderableCount=0,需维护者重启后复验。临时镜像 268MB 与日志已清理,IDE 文件已还原。