Files
Agent-System/.doc/remediation/2026-09-14-controlled-content-canonical-hash-remediation.md
T
weichenandCursor 50576a2ec5 docs(docgov): record review-blocker fixes and isolated PG gap
W7 must live-apply project 143 before UI acceptance. Isolated
TEST_DATABASE_URL was unavailable; shared env databases were not used.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-14 02:21:57 +00:00

7.4 KiB
Raw Blame History

title, status, created, updated
title status created updated
受控正文 canonical hash 漂移与重复 hydration 整改计划 in_progress 2026-09-14 2026-09-14

受控正文 canonical hash 漂移与重复 hydration 整改计划

背景

现场审计:项目 143 受控文档正文 404。项目 143 的文件含 5 行 Markdown 双空格硬换行;bootstrap 的 canonicalizer 将其删除并把新 SHA 写入数据库/账本,却未同步文件,读取 API 再把完整性冲突误报为 404。双空格具有渲染语义,不能把该漂移当成可丢弃格式。

整改原则

  1. 账本 head snapshot 是已建账本文档的权威正文;output.md 是兼容投影,不再成为并列真源。
  2. canonicalization 只能规范 LF、UTF-8 NFC、单个末尾换行等不改变 Markdown 语义的表示;禁止无条件裁剪行尾空格。
  3. 所有写路径使用同一语义保持的 canonical bytes 计算哈希、入账本、更新 DocGov 记录并投影文件。
  4. legacy 漂移和真实内容分叉均先保全双方;只有明确分类并留审计后才能修复,不得用旧账本 blob 静默覆盖原文件。
  5. 404 仅表示记录不存在;完整性错误必须用结构化错误暴露。
  6. 工程测试可直接查 API/DB;最终产品验收严格只以真实对话与浏览器页面可见结果签字。

实施波次

波次 owner 动作 完成判据
W0 现场冻结 Herdr / Cursor 在独立 fix/* worktree 认领 docgov;保存项目 143 DB 行、snapshot/blob 元数据和原文件只读校验清单;不得先覆盖文件 raw/canonical/head 三方 SHA 与 bytes 可复核
W1 语义保持的规范化契约 Cursor 已完成:CanonicalizeMarkdown 只做 LF/NFC/末尾换行;LegacyDestructiveCanonicalizeMarkdown 仅分类。golden + contract 覆盖硬换行 hard-break golden PASS;未合 dev
W2 权威读取与错误语义 Cursor 已完成:ledger head 仅在投影 ALIGNED 时返回;legacy/fork 返回 DOCUMENT_CONTENT_PROJECTION_DRIFT;404 仅记录不存在 handler 契约测试 PASS;前端解析 error_code
W3 原子投影与恢复 Cursor 已完成:fsutil.WriteFileAtomic;ProjectOutputMarkdownIfSafe 拒绝 legacy/fork 静默覆盖 单测覆盖 refuse overwrite
W4 项目 143 定向修复 Cursor 工具已完成、未对 data/dev apply。默认拒绝共享库/路径;--live --environment dev --doc-id --confirm REPAIR_SINGLE_DEV_DOC 才允许单文档 apply。/app/data 可映射到 host data root。goose 00032 允许 migration_repair;repair 不升人工修订号 worktree CLI/单测 PASS;隔离 PG 未跑;真实 143 待 W7 后 live dry-run/apply
W5 前端去重与可诊断错误 Cursor 已完成:lease no-op 返回原数组;hydrate fingerprint + 同 key 在途去重;显式重试;错误区展示 code/message/corr 前端单测 PASS。空闲 30s UI 属 W8
W6 工程门禁 Cursor go vet ./...、go test -short ./...、web npm test、web npm run build PASS。TestReconcile_LegacyRepair_PG 因无隔离 TEST_DATABASE_URL skip,已拒绝用 5433 代替 隔离 PG 仍为 blocker;未跑真实 UI / 共享库
W7 dev 集成 Herdr / Cursor 占 CURRENT 集成槽,merge dev,env-service.sh dev rebuild,确认 /ready schema 31+;不得用 restart 冒充部署新代码 新镜像运行且 smoke PASS
W8 真实 UI 实战 Herdr / Antigravity 使用真实浏览器页面和真实 PI/小队完成下列验收;API/DB 只作旁证,不得替代页面结果 test report 逐项附 UI 可见证据;失败即不签字

Ubuntu Server 无头浏览器方案

优先复用已验证的官方镜像 mcr.microsoft.com/playwright:v1.63.0-noble,以 --network host --ipc host 运行仓库的 Chromium 页面测试,BASE_URL=http://127.0.0.1:3100。该方案无需在 Ubuntu Server 宿主安装浏览器。

仅当 Docker 浏览器镜像不可用时,才在 web/ 执行 npx playwright install --with-deps chromium 安装宿主 Chromium 与系统依赖;安装动作和版本必须写入测试报告,不得静默切换执行环境。

真实 UI 验收矩阵(不得伪造)

A. 项目 143 旧数据恢复

  1. 从登录页真实登录项目 143 的编制用户。
  2. 用页面进入项目对话并打开「用户初始需求收集表」。
  3. 页面须显示完整正文,而不是 loading/error skeleton;标题、正文片段、V/r 徽章均可见。
  4. 页面空闲 30 秒,正文不闪回 loading/error;不得依靠刷新碰运气。
  5. 双击真实正文块,输入唯一 marker,点击页面「保存修改」;页面须立即显示 r+1。
  6. 硬刷新、退出重登后 marker 与 r 均仍可见。
  7. 切换「纯净阅读 / 人工修改 / 全部变更」:纯净模式不着色,人工修改模式能定位本次 marker,对无 agent 变化的范围明确显示“无对应变更”,不能表现为按钮失效。

B. 新项目完整生成链

  1. 全部通过页面创建新项目、选择工作流、配置成员与职责;禁止 DB/API 直建测试对象。
  2. 在项目对话中输入真实业务需求,等待系统真实编排智能体小队并由真实 PI 生成文档。
  3. 页面必须能看到用户消息、助手阶段进度/最终回复、小队完成状态、生成的受控文档全文及 V/r。
  4. 再通过对话要求小队修改该文档;若出现高风险确认,必须在页面真实确认/拒绝,不得直接调 decision API。
  5. 页面必须展示实际 change report:摘要、文档影响、项目影响、风险、开放问题和分析状态;fallback 必须明确标识,不冒充 PI 叙事。
  6. 通过页面做人工块编辑并保存,验证三种 overlay、任意版本比较、通知入口与持久化。

C. 持久性、并发与权限

  1. 两个真实浏览器上下文以同一编制人打开同一修订,A 保存成功、B 后保存必须在页面出现 409 冲突提示且保留草稿。
  2. reviewer 登录后可读/批注但看不到正文保存能力;项目外用户在页面看不到项目和文档。
  3. app 重启后,仅通过页面重登恢复项目 143 与新项目的最终正文、V/r、overlay、报告与通知。
  4. 所有截图、视频、trace、页面可见文本和项目/doc/run 标识归档;不得提交账号密码、token 或 phase-secrets.local.json 内容。

必补工程测试

  • legacy 文件含 Markdown hard-break 双空格:bootstrap 后 hard-break 仍存在、content 200、三方 SHA 一致。
  • human PATCH 输入尾随空格:账本、DocGov、文件一致,重启后仍可读。
  • agent commit / reject / retry:投影幂等,失败不假 200。
  • legacyCanonical(raw)==head:识别 destructive legacy drift,保留 raw 并追加 migration_repair,不得把旧 head 覆盖到文件。
  • 新 canonical 仍不一致:fail closed、保存双方、返回明确错误,绝不自动覆盖。
  • ReadDocumentContent 的 not-found / missing / empty / mismatch 分别映射正确状态码与 error code。
  • lease 列表无变化:React state 引用不变,hydration 不重复发起;显式 retry 单次请求。

发布门槛

  • 项目 143 页面恢复只是定向修复,不足以关闭缺陷。
  • 代码门禁、PG 故障用例、143 旧数据 UI、新项目真实 PI 全链路、并发/权限/restart 全部 PASS 后,才可将 DOC-CONTENT-CANONICAL-HASH-DRIFT 标为 PASS。
  • 任一用例使用 stub、API 直写、伪造助手回复/文档/报告,整轮 UI 验收无效。