# Handoff:后端契约缺口复核与交付包 - 生成时间:2026-09-18 10:11(会话内时钟) - 工作目录:`E:\City-Lifeline-Cockpit-TvT`(前端仓库,DSH 沙箱 workspace-write) - 本次目标:执行前端 tracker 的 `25: 后端契约缺口待办(跨领域两项 + 补契约清单)`;核查后端任务完成情况;把仍缺失的后端工作变成可交付给后端项目经理的建票草案。 - 状态:核查完成、台账已更新、交付包已产出。**票 25 未关闭,进度 55%。** --- ## 0. 一句话现状 后端在 2026-09-17 连续交付 `#33`–`#43`,票 25 列的 8 组补契约里 **7/11 判定项已交付**,只剩 **G1/G2/G4**(地图行业筛选、点位摘要字段、设备→点位回联)和 **B 的一处**(`warning-settings` 趋势范围);真正的大坑是**真实数据未接线(22 个读模型里 21 个是空适配器)**。交付包已写好,等人类交给后端 PM。 --- ## 1. 两个仓库、两个 tracker(最容易搞混的地方) | 仓库 | 路径 | 角色 | tracker | | --- | --- | --- | --- | | 前端驾驶舱(本仓库) | `E:\City-Lifeline-Cockpit-TvT` | `/cockpit` 外壳 + 面板实现;本会话的写权限范围 | 本地 Markdown:`.scratch//`(约定见 `docs/agents/issue-tracker.md`) | | 后端 | `E:\pipe-ner-server` | Spring Boot 只读驾驶舱契约 `/api/cockpit/v1/**` | **Gogs**:`http://192.168.110.30:3000/shaoy/pipe-ner-server`(工单在远端,不在本机 Markdown) | - 本会话的 effort 目录:`.scratch/cockpit-shell-panel-layout/`(`map.md` + `spec.md` + `issues/01`–`26` + `research/` + `verify/`)。 - 该 effort **不是** `/wayfinder` 驱动的:`map.md` 第 6–8 行明确说明它只是 `/to-spec` + `/to-tickets` 的产物,`Labels: wayfinder:map` 仅用于让面板按地图视图渲染。推进走 `/implement`。 - 后端**也在用 agent**:`E:\pipe-ner-server\.scratch/implement-33-task.md` … `implement-43-task.md` 是它的执行简报(每张 Gogs 票一个)。说明后端有并行会话在跑,**不要扰动它的工作区**。 --- ## 2. 环境事实与约束(接手前必读) 1. **沙箱**:DSH 文件策略为 `workspace-write`,可写范围只有 `E:\City-Lifeline-Cockpit-TvT`。后端仓库在工作区之外,**写后端需要一次性提权**(`sandbox_permissions`);读是允许的。 2. **凭据**:`~/.git-credentials` 有 `192.168.110.30:3000` 的一条 `user:pass` 记录,git 命令可用(`git ls-remote` 成功)。 3. **但 Gogs API 不可用**:带该凭据走 Basic Auth 调 `/api/v1/repos/.../issues` 返回 **401**,`?token=` 两种变体同样 401。共享浏览器也**没有 Gogs 登录会话**(页面只有"注册/登录")。→ **本会话无法创建 Gogs 工单**。若要建票,需人类在浏览器窗口登录一次,之后可用浏览器或 API 建票。本次刻意选择了 handoff 而非硬闯。 4. **后端 git 状态(关键)**: - 本地 HEAD = `ed0ace5`(`test(cockpit): add contract integration environment and handoff (#43)`)。 - 远端 `origin` HEAD = `e2b4e45`(`#42`)——**`#43` 未推送**。联调前必须确认部署来源提交。 - 工作区有未提交内容:`.planning/`、`.scratch/implement-33..43-task.md`、`PipeNetworkImportDTO.java`、`logs/`、`.gitignore`。这些**不属于**本次工作,不要 stage/commit/stash/clean。 5. **项目规则(AGENTS.md,本仓库)**:修改代码后**不要自动跑** `npm run build/dev/serve/preview`、Vite 命令、本地服务器或浏览器截图——只有用户在当前对话中明确要求才可跑。只读检查(看 diff/源码)允许。本次全部是只读检查 + Markdown 写入,**未跑任何构建/调试命令**。 6. **共享浏览器**:本任务的浏览器会话与人类共用窗口、tab 隔离。Gogs 页面当前未登录。 --- ## 3. 本次产出(详情在这些文件里,本文不重述) | 产出 | 路径 | 内容 | | --- | --- | --- | | 票 25(已更新) | `.scratch/cockpit-shell-panel-layout/issues/25-backend-contract-gaps.md` | 「复核记录(第二轮)」含逐项判定表与证据;进度 30%→55%;AC 标注;下一步 | | **后端交付包(本次核心产出)** | `.scratch/cockpit-shell-panel-layout/handoff/backend-contract-gaps.md` | BT-1…BT-5 五张可直接建票的 Gogs 草案 + 可选 BT-6;每题含背景证据/要做什么/验收标准/解除阻塞的前端票;另有业务口径问题与给 PM 的决策点 | | 后端官方移交手册 | `E:\pipe-ner-server\docs\cockpit\README.md`(`#43`) | 契约总则、字典冻结、端点清单、分页/快照/错误口径、WS 增量、联调检查表、容器化评估、未验证项 | | 字段覆盖调研(前置票 24) | `.scratch/cockpit-shell-panel-layout/research/panel-field-coverage.md` | 16 面板逐项字段覆盖与 A–H 补契约原始建议(第 4 节) | | 上游规格与词典 | `spec.md`、`CONTEXT.md`、`docs/adr/0001`–`0008`、`.scratch/web-cockpit-decision-map/` | `mode`/`panelId` 词典、相机契约、信息架构;本 effort 不再发明这些语义 | **不要重复造**:A–H 的字段级建议在调研第 4 节;本轮状态判定在票 25;建票草案在交付包。三者互链,避免三处各写一份。 --- ## 4. 尚未完成 / 开放决策 ### 4.1 后端缺口(已写成草案,等 PM 建票) - **G4 / BT-1(最高优先)**:设备→监测点回联。四个 WS 增量 DTO 均只有 `deviceCode`,无 `monitoringPointCode`;`CockpitMapSnapshotService.monitoringPoint()` 丢弃 `SourceMonitoringPoint.devices`;事件行也缺 `monitoringPointCode`。阻塞前端票 15/08/19。 - **G1 / BT-2**:行业筛选落图路径**二选一**——给 `map-snapshot` 加 `industry`,或正式声明以 `/monitoring/distribution` 为准(后者已具备入参与逐点 `industry`/`deviceType`)。 - **G2**:`CockpitMonitoringPointSummary` 仍是 7 个字段,缺 `industry`/类型/徽标。 - **B / BT-3**:`/overview/warning-settings` 仍只吃 `mode`,趋势窗口不可声明(其余切片都已支持 range)。 - **BT-4**:事件行缺 `coordinateValidation`(字典已冻结「不可渲染须显式标注」,事件无法判上图)与报警阈值字段。 - **BT-5(程序级,最大差距)**:22 个读模型里 21 个只装配 `Empty*Adapter`(`@Service`,返回 `...Snapshot.empty(...)`),仅 `BusinessCockpitWorkOrderReadAdapter`(`@Primary`)接了真实数据。契约已冻结,数据未接线。 ### 4.2 需要人类/业务方 - 三条业务口径(详见票 25「业务问题」与交付包第四节):**「故障」= `stale`?**(字典里点位六态、指标六态且 `EXPIRED ≠ OFFLINE`);**「处置率」= 已结案工单/事件总数?**(后端已冻结 `basis = CLOSED_WORK_ORDERS_OVER_TOTAL_EVENTS`);**「管理单位」是否等同 `maintainer`?**(`management-information` 用 `organizations` + `ownershipDistribution` + `unmaintained` 建模,与维护单位分开)。 - **票 25 的认领语义**:我没有把 `Status: ready-for-human` 改写成认领态(本地 tracker 的 `Status:` 记的是 triage 角色,改掉会丢票面语义)。若需要认领,建议**新增一行** `Assignee:`,不要动 `Status:`。→ 待用户定夺。 ### 4.3 用户已明确的三项决定(本会话上下文,勿推翻) 1. 本轮只刷新台账 + 更新进度,**不改后端仓库**。 2. G1/G2 的 AC **保留结论**,只标注「实现路径待后端负责人定」,不替后端选路径。 3. 三条业务问题**先挂起**,按推荐口径写入「待业务方确认」。 --- ## 5. 建议的下一步(按优先级) 1. **若人类已把交付包交给后端 PM**:等 PM 建票(BT-1…BT-5)与裁定 G1/G2/G4 路径;裁定结果应回写 `E:\pipe-ner-server\docs\cockpit\README.md` 第 3 节。之后回来更新票 25 的 AC 与进度。 2. **若人类在浏览器窗口登录了 Gogs**:可直接按交付包草案在 `shaoy/pipe-ner-server` 建票(标题用草案里的 `BT-n` 小节标题,正文用其内容)。建完把票号回填交付包与票 25。 3. **若要在后端实现(需人类授权 + 提权)**:BT-1/BT-3/BT-4 是响应层小改动;BT-5 是大工程。注意后端有并行会话与未提交改动,**不要 `git add -A`、不要 push、不要碰非 cockpit 文件**;参考其 `implement-NN-task.md` 的工作方式(TDD、契约测试、`docs/cockpit/*-demo.html`)。 4. **前端侧**:票 06/08/15/17–20 的 mock 阶段不受后端缺口阻塞;只有「接真实接口」环节需要上面结论。 --- ## 6. 如何重新验证「后端当前状态」(只读,约 5 分钟) 后端会继续推进,所以**先重新核对新鲜度再动手**: ```powershell # 1) 后端进展与推送状态 cd E:\pipe-ner-server; git log --oneline -14 --grep='cockpit'; git ls-remote origin HEAD # 2) 端点全量枚举(对比票 25 的判定表是否过期) Select-String -Path 'E:\pipe-ner-server\pipe-network-service\zksy-admin\src\main\java\com\zksy\web\controller\cockpit\*.java' -Pattern '@GetMapping\(' # 3) 两个跨域缺口是否已修 Select-String -Path 'E:\pipe-ner-server\pipe-network-service\zksy-system\src\main\java\com\zksy\cockpit\map\CockpitMonitoringPointSummary.java' -Pattern 'private final' Select-String -Path 'E:\pipe-ner-server\pipe-network-service\zksy-admin\src\main\java\com\zksy\web\controller\cockpit\CockpitMapSnapshotController.java' -Pattern 'RequestParam' # 4) WS 增量是否带上点位(四个 *DeviceStatusDelta) Get-ChildItem -Recurse -File 'E:\pipe-ner-server\pipe-network-service\zksy-system\src\main\java\com\zksy\cockpit' | Where-Object Name -like '*DeviceStatusDelta*' | ForEach-Object { $_.Name; Select-String -Path $_.FullName -Pattern 'private final' } # 5) 真实数据接线状态(非 Empty 的适配器有几个) Get-ChildItem -Recurse -File 'E:\pipe-ner-server\pipe-network-service\zksy-system\src\main\java\com\zksy\cockpit' -Filter '*Adapter.java' | Where-Object Name -notlike 'Empty*' ``` 判定要点:`Empty*Adapter` 之外出现新的 `Business*Adapter`(且带 `@Primary`)=该切片已接真实数据;`CockpitMonitoringPointSummary` 出现 `deviceCodes`/`industry`=G2/G4 部分修复;任一 `*DeviceStatusDelta` 出现 `monitoringPointCode`=G4 的 WS 侧修复。 --- ## 7. 建议加载的技能(下一个 agent 按需调用 Skill 工具) - `wayfinder` — 本会话的票据/地图协议(认领、进度契约、收尾、map 的 Decisions so far 只在关票时追加)。 - `grilling` — 目标不清或需用户定夺时的澄清方式;本会话已用它把「交付到哪一层」问清楚。业务口径三问属 HITL,**agent 不得代替人类回答**。 - `implement` + `tdd` + `code-review` — 若要在后端仓库落地 BT-1/BT-3/BT-4。 - `to-tickets` — 若改成用本地 Markdown 建票而不是 Gogs。 - `tvt-js-plugin-builder` — 涉及 TvT.js 插件/案例/预览元数据时(前端侧基线)。 --- ## 8. 陷阱清单 - 别把后端 Gogs 票与前端 `.scratch/` Markdown 票混为一谈:**票号会撞车**(后端也有 #37/#25 等),引用时带仓库前缀。 - 别假设后端契约手册就是现状:`#43` 本地未推送,且手册第 8 节自己列了未验证项(数据库级联调、生产规模性能、银河麒麟/Docker 实机)。 - 别把 `docs/cockpit/*-demo.html` 当真实数据:那是内嵌 fixtures。 - 别在票 25 里重抄调研第 4 节与交付包的内容——三处保持「一处结论 + 链接」。 - 写 `.scratch/**` 的 Markdown 时:`## 章节` 独占一行、段落间留空行、**不要把换行写成反斜杠加 n 的两个字符**;字段行(`Status:` / `Labels:` / `Blocked by:`)必须行首且不加粗,否则面板解析不到。 - 本会话未向任何远端写入、未关闭任何票、未追加 map 的 Decisions so far(因为票 25 未关闭)。 --- ## 9. 敏感信息 本文档**不含**任何凭据。凭据位于 `~/.git-credentials`(Gogs 主机条目),仅当确实需要访问远端时按需读取,**不要回显、不要写入任何仓库或票面**。