Type: task Status: claimed Assignee: codex Label: ready-for-verification Category: frontend-execution
状态:修复已实施并通过离线回归;真机复验(待验证项 1、2)未执行,本票保持开启。
Codex 按本地 tracker 的 Status: claimed 约定认领(deck 的 assignees 写入读回失败,以 Assignee: 字段为准)。核心信封解包由并行改动 ead39442 提供,非本票实施;本轮新实施的是同一条业务错误映射链上的两处白名单继承键缺口,提交 86db4d4。
本票一度被我错误撤销,此处更正。
cockpitApi.js 原实现直接 return { data: payload.data } —— 而 payload.data 是 readJsonPayload 返回的整个 AjaxResult 信封 {code, msg, data},业务载荷从未被解包。后果:
fetchBaseArchives 对真实 /infrastructure/base-archives(facilityCount=1006)返回 state=empty;fetchMapSnapshot 对真实 /map-snapshot(total=13)返回 total=null、snapshotAt=''。/events/current?mode=ALARM 业务 code=500,前端分区判为 success —— 故障被伪装成正常空态。实测证据:.scratch/cockpit-real-data-wayfinding/verify/artifacts/t18/live-audit-results.json(写入时间 10:25),三项检查 frontend-envelope-archive、frontend-envelope-map、frontend-business-error-not-success 均为 failed。
工作区已存在对应修复(src/modules/cockpit/services/cockpitApi.js,文件修改时间 14:38:36):新增信封拆解分支——若载荷含数值型 code,则 code !== 200 判失败(401/403 映射 UNAUTHORIZED,其余 UNAVAILABLE),缺 data 字段判 BAD_PAYLOAD,code === 200 才解包 body.data。
该修复于 14:38 落地,晚于上述 10:25 的失败实测,早于我 15:50 的复核。复核因此在已修复代码上进行并返回正常。
我 15:58 撤销本票时,用修复后的代码复核得到「适配层正常」,据此判定缺陷「不成立」并关闭票据。这是推理错误:修复后的通过不能否定修复前已证实的缺陷。正确处置是标记为「已修复待验证」,而非撤销。相关术语纪律:验证缺陷必须确认被测代码版本与复现时版本一致。
核验已有修复时发现同类缺陷的第二、第三处,都在本票“业务错误映射”范围内:
readBusinessReason(cockpitApi.js)用普通对象下标查 BACKEND_ERROR_CATEGORY。白名单只有一个条目,但下标查找会命中 Object.prototype 的继承键——后端随便回一个 category: "toString",失败原因就成了函数而不是契约值。与文件里既有的注释纪律(「只认白名单里这一个取值……不让后端塞任意原因进结果」)直接冲突。
对抗式自查时用 node 探针确认第二处同源缺陷:sectionStateFromBackend('toString') 与 sectionStateFromFreshness('toString') 返回的是函数,会原样漏进 data-section-state。
修复(提交 86db4d4,两个文件共 5 行):三处改为只认白名单自有键。这是最小改动,不新增抽象,沿用本文件既有的 Object.prototype.hasOwnProperty.call 写法。
离线回归:新增 verify/t22-envelope-frontend.mjs,不联网、注入 fetchImpl,覆盖三项真实失败检查对应的同一批领域出口(fetchBaseArchives / fetchMapSnapshot / fetchCurrentEvents)、HTTP 与业务两级失败、mock 分支、裸载荷、白名单继承键、后端分区状态映射 —— 19/19 通过(修复前 5 项继承键检查为红,已实测复现)。
既有离线回归无回退:t48-real-envelope 5/5、t04-config、t05-adapter 283/283、t07-coordinate 39/39、t08-map-summary 44/44 全绿。
既存失败(与本票无关,已用基线对照排除):t03-pole-probe、t28-fill-container 缺 puppeteer-core;t06-assets JSON import 属性;t11-equipment-detail F7;t17-infrastructure-panels / t18-monitoring-panels 引用已被片区改造删除的 MANAGEMENT_REGION_GAP / REGION_MAP_GAP;t37-area-limits、t38-fog 断言。将两处改动临时还原为基线后复跑,9 项全部同样失败,故与本轮改动无因果关系。
事故记录:批量复跑时误执行了 t20-mutations.mjs(故意改坏源码再还原的变异测试),它在还原阶段 copyfile 失败,把 OVERVIEW_RANGE 留成 '' 并留下 .bak。已从 git 恢复 overviewApi.js(该文件在会话开始时干净)并删除 .bak,工作区已复原为仅含本票改动。
verify/t18-real-audit.mjs,三项 frontend-* 检查应全通过。需要连真实后端 192.168.110.96:8301,属 AGENTS.md 禁止自动执行的调试/联调,须用户在本次对话中明确授权。code=500 的面板显示为失败分区。同上,须明确授权。离线已证到适配层:fetchCurrentEvents 得 state=failed/reason=unavailable,eventList.currentEventsView 据此给「该分区加载失败」占位;但界面呈现仍以真机为准。t22 的 mock 用例证明 mock 处理器返回值不经信封分支(且刻意让 mock 返回 code:500 仍判成功),裸载荷原样透传;t48 第 5 项同证。ead39442(Git 作者 Kazerin),本轮修复 86db4d4(见上节)。待验证项 1、2 都要连真实后端并起浏览器,属 AGENTS.md 明令「不得自动运行」的范围,本轮未获用户授权,因此不凭推理宣布通过、不关闭。
这两项与 票 18 的矩阵复跑(「重新部署并锁定运行实例提交哈希,重跑矩阵」)是同一批真机证据,不另起炉灶:拿到票 18 的复跑窗口时,本票 1、2 随同取证据,取到即关闭。若届时仍不通过,按本票纪律退回 needs-triage 重诊。
即使信封已修好,运行监测-监测点台账仍显示「已列出 0 个点位 · 本端点序列共 undefined 条」—— 缺失值被直接渲染。已另立 票 27。
发现于票 18。与 票 28(后端静默丢弃监测点)分属前后端,修复路径互不依赖。
按用户本次指派认领,进入已有修复的核验阶段。当前状态 fixed-pending-verification,无 needs-triage,无 blockedBy。本轮先核验已提交代码、历史失败证据、mock/裸载荷与业务失败分区路径;遵守 AGENTS.md,不自动运行真实审计、构建或浏览器调试,缺失的真实验收证据会如实保留。
源码核验事实:核心信封解包与业务 code 判断已提交在 ead39442db(Git 作者 Kazerin);本轮 HEAD=777f0614db,cockpitApi.js 无工作区差异。本轮不认领已有修复为新实施。仍有明确缺口:t48-real-envelope 只覆盖地图,不验证档案、事件顶层失败与 mock;readBusinessReason 用普通对象下标查白名单,category=toString/proto/constructor 等继承键会返回非 REQUEST_REASON 值,与只认白名单的既定约束冲突。方案:独立离线回归验证三个实际领域出口、HTTP/业务错误和 mock/裸载荷;以自有键查找修复映射,保留既有真实审计失败证据;真实复验需用户明确授权 build/debug 例外。