Compare commits
279
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed29cb5200 | ||
|
|
e9d57ea772 | ||
|
|
241bfccc1e | ||
|
|
f2a7fa94d2 | ||
|
|
ea3eeadb77 | ||
|
|
c5810cd907 | ||
|
|
6ef80acf8d | ||
|
|
ba67c467c4 | ||
|
|
81b75b3546 | ||
|
|
43460ae9ed | ||
|
|
fbd8fe469f | ||
|
|
36c40f6a86 | ||
|
|
097ba8f457 | ||
|
|
36e4bc3001 | ||
|
|
08bf615f95 | ||
|
|
2907c5025d | ||
|
|
9098069aee | ||
|
|
d0e8f60915 | ||
|
|
f693e1c474 | ||
|
|
46e275db98 | ||
|
|
6f07dfcab6 | ||
|
|
84fdd7d0bf | ||
|
|
8b47451b90 | ||
|
|
e3b72ad64b | ||
|
|
96fd0e9e6f | ||
|
|
50576a2ec5 | ||
|
|
838864f3b2 | ||
|
|
8892290bf7 | ||
|
|
e7b46e92d2 | ||
|
|
c159786a70 | ||
|
|
f80e7a1ea1 | ||
|
|
79d2676bbf | ||
|
|
2d0d499aec | ||
|
|
d208b0e3e4 | ||
|
|
e760373fd0 | ||
|
|
00737c7d5e | ||
|
|
36a59d6700 | ||
|
|
8ce41e101b | ||
|
|
bad2410994 | ||
|
|
9345109dca | ||
|
|
4bf8b6d993 | ||
|
|
bf4f9bdba0 | ||
|
|
5d79da60fc | ||
|
|
07507c7c24 | ||
|
|
89163d2d18 | ||
|
|
b258ab86a5 | ||
|
|
acf62a23d0 | ||
|
|
4e0951fe70 | ||
|
|
2d0fcb94bc | ||
|
|
fa6a033c95 | ||
|
|
39df2d88f7 | ||
|
|
5db2d9a3b1 | ||
|
|
eb85b8a068 | ||
|
|
1a98c0cdeb | ||
|
|
0936a94fdf | ||
|
|
8907b61745 | ||
|
|
3c26fcb2f8 | ||
|
|
b824948a5a | ||
|
|
a0196142a3 | ||
|
|
09e3581def | ||
|
|
d7d656f66f | ||
|
|
0fa4a5784e | ||
|
|
be394bf617 | ||
|
|
8b6bf2cca1 | ||
|
|
9a19bcc12c | ||
|
|
ec89b4c8b0 | ||
|
|
c2d4e9a55c | ||
|
|
7ef34a685d | ||
|
|
4512132b20 | ||
|
|
2f0a1b337c | ||
|
|
60e2b1adf2 | ||
|
|
c1bdfe3920 | ||
|
|
6a68e04f1f | ||
|
|
6cd3991bad | ||
|
|
dd24105742 | ||
|
|
639969ff7e | ||
|
|
5183d2866d | ||
|
|
c86e229303 | ||
|
|
c8318e8551 | ||
|
|
dd5671e542 | ||
|
|
ba4bb41e1c | ||
|
|
48a4dcb86d | ||
|
|
f0ab254ed1 | ||
|
|
339e871242 | ||
|
|
01c5972ead | ||
|
|
b7cfb28217 | ||
|
|
8b1a531947 | ||
|
|
9b43bd6a73 | ||
|
|
1b04d962d1 | ||
|
|
4c465d2cb0 | ||
|
|
21c8a0063b | ||
|
|
369fe7bf51 | ||
|
|
55a4f399fa | ||
|
|
051e69ccd1 | ||
|
|
becd295c9d | ||
|
|
d9c1791e56 | ||
|
|
6fd685fd47 | ||
|
|
35b2e922bf | ||
|
|
7be683d9c7 | ||
|
|
11bdba0052 | ||
|
|
ce89939cd8 | ||
|
|
98619c7b56 | ||
|
|
32cf9ad4fc | ||
|
|
333c7a604f | ||
|
|
4a97ff5dd1 | ||
|
|
e04829ee8e | ||
|
|
2a58674299 | ||
|
|
4dcc5011ac | ||
|
|
bebe1e3690 | ||
|
|
9a9e25806c | ||
|
|
bdd1b35b86 | ||
|
|
9f6401847d | ||
|
|
56e052f3cb | ||
|
|
77f5db1e90 | ||
|
|
59dc73ec7c | ||
|
|
9f676273df | ||
|
|
58ae25444d | ||
|
|
18a5457c07 | ||
|
|
20b6092cf0 | ||
|
|
1b020790da | ||
|
|
5705f99fdc | ||
|
|
5c42ba7c45 | ||
|
|
a42895ccdc | ||
|
|
4a4fbcf2a6 | ||
|
|
bb9f347fc9 | ||
|
|
faaacae5f6 | ||
|
|
9e0901ce25 | ||
|
|
61905e99c1 | ||
|
|
d45efa2ff1 | ||
|
|
cf3d126436 | ||
|
|
d5ce81228c | ||
|
|
4dbd9eecb9 | ||
|
|
0a34daf4b5 | ||
|
|
be33409297 | ||
|
|
eefdd4c4fd | ||
|
|
79797cab7c | ||
|
|
52c0292ff7 | ||
|
|
5571e93922 | ||
|
|
3157a66f2d | ||
|
|
ca01a1cf9d | ||
|
|
e6cd7bef9e | ||
|
|
75345431e4 | ||
|
|
dee18d7fc0 | ||
|
|
40526773be | ||
|
|
6f0057c014 | ||
|
|
86598e7d0e | ||
|
|
f4aa0da14f | ||
|
|
2d86d330e5 | ||
|
|
9e50bc0543 | ||
|
|
107f898362 | ||
|
|
92488b327a | ||
|
|
900af79e14 | ||
|
|
43e03e4969 | ||
|
|
f3e4eeb42b | ||
|
|
020712dfbd | ||
|
|
c33a6d8406 | ||
|
|
301e1f401e | ||
|
|
7466a15319 | ||
|
|
76e2028761 | ||
|
|
e45c2b7d36 | ||
|
|
5096581651 | ||
|
|
aeeb48ba7d | ||
|
|
b78574b065 | ||
|
|
1fd500e2b9 | ||
|
|
c6558bc757 | ||
|
|
cc394c815c | ||
|
|
f50692be25 | ||
|
|
0553c48039 | ||
|
|
6544f523f5 | ||
|
|
e37a5fa399 | ||
|
|
846638197d | ||
|
|
187084c517 | ||
|
|
cd69cfd4d8 | ||
|
|
1d2cecc522 | ||
|
|
d282b1e526 | ||
|
|
fed7af1982 | ||
|
|
ec8a45a5fe | ||
|
|
8c5cac17ef | ||
|
|
4d4ea20e63 | ||
|
|
c70cdf7261 | ||
|
|
d421fba472 | ||
|
|
f189ce9ff9 | ||
|
|
cf28e53308 | ||
|
|
0b36a6ede0 | ||
|
|
53f988da49 | ||
|
|
edbd01e5cc | ||
|
|
2f4d27d28d | ||
|
|
00a31e9b8d | ||
|
|
e5139d980a | ||
|
|
59b6db74bb | ||
|
|
91de320b67 | ||
|
|
ef0b2645e5 | ||
|
|
a3c6df309b | ||
|
|
9c7d6d49b2 | ||
|
|
1e364f17ab | ||
|
|
9a36e7c896 | ||
|
|
bd53984790 | ||
|
|
fe979fdd21 | ||
|
|
5724f4f74e | ||
|
|
d94b0d17f5 | ||
|
|
a7bd65b489 | ||
|
|
353d9fdf33 | ||
|
|
0aae84d0a8 | ||
|
|
5f2063ebbe | ||
|
|
09488132dd | ||
|
|
46769467bf | ||
|
|
9c8a41982c | ||
|
|
9a9ffa48cc | ||
|
|
0b5f4997e2 | ||
|
|
6fb40af05e | ||
|
|
7f88b6d882 | ||
|
|
9ed5987104 | ||
|
|
b5a3b72756 | ||
|
|
c990bcdb89 | ||
|
|
d07d201728 | ||
|
|
0c6fb090ff | ||
|
|
4f5a6188a7 | ||
|
|
87971fc953 | ||
|
|
5caefc887a | ||
|
|
79e8349d71 | ||
|
|
8594feb6cc | ||
|
|
7b48ca2ecc | ||
|
|
645c4b67b0 | ||
|
|
4a91105e99 | ||
|
|
ff1a126415 | ||
|
|
75ec8785f3 | ||
|
|
a288dcf0cc | ||
|
|
7f8331f893 | ||
|
|
95f0ead131 | ||
|
|
fa615fee2a | ||
|
|
d79fdf6ffa | ||
|
|
46a1fcc945 | ||
|
|
ed1e232022 | ||
|
|
7ea686e6ba | ||
|
|
c6c22494f8 | ||
|
|
41bbc4049c | ||
|
|
17fc510c2c | ||
|
|
501cde7c12 | ||
|
|
5e1a7e6584 | ||
|
|
4f5bde899a | ||
|
|
9aafe7bd37 | ||
|
|
7a7162dcee | ||
|
|
268a9bdb56 | ||
|
|
7bbd6783fc | ||
|
|
7778559201 | ||
|
|
e372a1467c | ||
|
|
a676bd0b95 | ||
|
|
5bc333b1aa | ||
|
|
357fcc79ee | ||
|
|
6ab8b52113 | ||
|
|
2660260758 | ||
|
|
f17781adb6 | ||
|
|
a7c073d85c | ||
|
|
06dacc9956 | ||
|
|
1cd2e681ed | ||
|
|
0225906f3f | ||
|
|
e0f07060b9 | ||
|
|
deaec82a7c | ||
|
|
d7a19d4786 | ||
|
|
a830d9dcc1 | ||
|
|
cd506d8cc7 | ||
|
|
55639b3d26 | ||
|
|
efe630d033 | ||
|
|
ef61e77192 | ||
|
|
30ace0234b | ||
|
|
95ab2badf6 | ||
|
|
995e099026 | ||
|
|
38e2e32807 | ||
|
|
3e242e6d36 | ||
|
|
0c5256c60c | ||
|
|
d08cbdc2de | ||
|
|
3afd606635 | ||
|
|
8032dce435 | ||
|
|
e0721a7944 | ||
|
|
2636542418 | ||
|
|
dca83f0dea | ||
|
|
b6aebc8176 | ||
|
|
4b8d8bf6d6 | ||
|
|
1abafa3176 |
@@ -0,0 +1,25 @@
|
||||
# ADR:文档 Version / Revision 边界与决策门
|
||||
|
||||
## 状态
|
||||
|
||||
已接受(2026-09-13,用户确认 DOCREV 整改实施计划)
|
||||
|
||||
## 背景
|
||||
|
||||
受控文档此前只有当前 `output.md` 与 SHA,无法表达「智能体基线 + 后续人工修改」的业务版本语义;自由文档每次保存 +1 的 `current_version_id` 与本需求冲突。
|
||||
|
||||
## 决策
|
||||
|
||||
1. **版本边界**:模板或一次成功提交的智能体/智能体小队产物开启 `Version`;人工每次服务端成功保存只增加该 Version 内的 `Revision`,不增加面向用户的版本号。
|
||||
2. **high/critical 候选**:风险达到 `high` 或 `critical` 的 agent candidate,必须经编制负责人二次确认后才能 `CommitAgentVersion`。
|
||||
3. **首发范围**:Wave 1–5 仅覆盖受控文档;自由文档统一读模型与 UI 语义切换放在 Wave 6。
|
||||
4. **根表指针列**:统一 `ledger_*` / `head_*` 前缀;禁止与 `freeform_documents.current_version_id`(00008 每-save+1 legacy)同名承载新语义;旧列迁移时改名为 `legacy_version_id`。
|
||||
5. **Goose**:从 **00028** 起递增;不得硬占用并行分支可能冲突的旧号。
|
||||
6. **保留策略**:受控文档随项目/法规保留;自由文档默认 365 天可配置,禁止静默硬删。
|
||||
7. **发布 blocker**:方案评审与 Wave 落地阶段不擅自写入 gap-matrix;纳入发布范围后再新增行。
|
||||
|
||||
## 后果
|
||||
|
||||
- 实施必须按 Wave 0→6 顺序;禁止先上前端颜色标记再补快照事实源。
|
||||
- `document_records.version` / `content_sha256` 在兼容期由 ledger 同事务投影,稳定后退役。
|
||||
- 详细表结构、API、状态机见 [../system-design/document-revision-management.md](../system-design/document-revision-management.md)。
|
||||
@@ -0,0 +1,29 @@
|
||||
# ADR:模块化单体解耦——契约通信、单一写者、编排下沉
|
||||
|
||||
## 状态
|
||||
|
||||
已接受(2026-09-14;Wave 0 契约骨架与 arch-check warn 基线已落地,未占集成槽)
|
||||
|
||||
## 背景
|
||||
|
||||
多轮审计与实测表明:一处修改波及多处的根因不是模块数量不足,而是——
|
||||
`internal/server`(17k 行)同时是组合根、跨模块闭包事件总线、编排载体与文件系统/SSE 细节持有者;`internal/bizdev` 是第二组合根(依赖 16 个内部包);`UserProjectContext` 被 chat/coordinator 双向直改;`document_records` 有 5 个写者;工作区路径与 squad 文件 schema 是无版本化的隐性公共契约;`intent→bizdev` 反向依赖。
|
||||
证据与完整诊断见 [../system-design/2026-09-14-module-decoupling-architecture.md](../system-design/2026-09-14-module-decoupling-architecture.md) §1。
|
||||
|
||||
## 决策
|
||||
|
||||
1. **架构形态**:维持模块化单体(不做微服务拆分),新增 `internal/contracts` 作为跨模块接口/DTO/事件/共享枚举的唯一 SSOT;模块间仅允许「调 contracts 接口」与「发布/订阅 contracts 事件」两种通信。
|
||||
2. **单一写者**:每张表、每类文件唯一属主(docgov 独占 `document_records`;chatlog 独占 chat_* 表;workspace 独占工作区路径);跨模块写走属主端口方法。
|
||||
3. **编排下沉**:跨模块流程收敛到应用编排层(chatflow/stageflow/docflow,拆自 bizdev/coordinator/chat);HTTP handler 只做参数→服务→DTO 三行式。
|
||||
4. **组合根唯一**:wiring 迁 `internal/app`;`server.NewServer` 只剩 HTTP 装配;SSE 帧协议下沉 `internal/stream/transport`。
|
||||
5. **squadrun 契约**:系统备好工作区与 `InputBundle`,小队按 `OutputContract` 交货并写 `RunManifest`(SchemaVer=1);外部禁止直读/覆写工作区内部文件。
|
||||
6. **机器门禁**:`scripts/arch-check.sh` + `module-boundaries.yaml`(import allowlist / 表属主 / 路径字面量属主),warn 两周后 block 进 CI 与集成槽位冒烟。
|
||||
7. **兼容承诺**:HTTP URL 与响应结构在 Wave 1–5 不变;**零表结构迁移**;旧路径设一版兼容期后删除。
|
||||
8. **实施顺序**:Wave 0 立规矩 → 1 止血 → 2 读路径 API 化 → 3 小队契约化 → 4 单写者 → 5 编排事件化(可拆 5a/5b)→ 6 传输收口;每 Wave 独立分支、独立回滚,遵守 AGENTS.md §6 mutex/槽位纪律,避开在途认领。
|
||||
|
||||
## 后果
|
||||
|
||||
- 新增包:contracts / app / chatlog / contextasm / docquery / squadrun(squad 换壳);
|
||||
- `internal/bizdev` 与 `internal/ctxmgr` 将被拆解退役(知识迁移到 use case 与两个子包);
|
||||
- 所有后续新能力(含软件项目自举)必须基于新边界实现,禁止再挂 bizdev 门面;
|
||||
- 任何契约(contracts 中已发布的 DTO/事件/文件 schema)变更须走 ADR。
|
||||
@@ -0,0 +1,47 @@
|
||||
---
|
||||
title: "当前受控文档指示语优先于领域关键词路由"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-14
|
||||
owner: Cursor-Auto
|
||||
branch: fix/document-revision-active-doc-routing
|
||||
worktree: "-"
|
||||
mutex: docgov
|
||||
---
|
||||
|
||||
# 当前受控文档指示语优先于领域关键词路由
|
||||
|
||||
## 目标
|
||||
|
||||
用户说「当前受控文档/当前文档/本文件/这份文档」且已选中服务端注册的 `doc_proj*` 时,任务 payload 为该文档 `taskKey`+`docId`;UI-05 提示须为 `intake` + `doc_proj6109_intake`。
|
||||
|
||||
## 范围
|
||||
|
||||
- `web/src/engine/templateMatch.ts` + App 发送/重试链
|
||||
- 单测与边界;服务端 mismatch 复核(不信任客户端 doc_id 改 task)
|
||||
- 文档:audit / gap-matrix / CURRENT
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不改弱 E2E UI-05 断言;不操作容器;不触碰/提交 test-report assets
|
||||
- 生产 `templateMatch.ts` 不导出用例编号/E2E 专属提示词;测试提示词留在 test 文件
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 认领 CURRENT;写 audit/short-term
|
||||
2. [x] 指示语钉住 active 受控文档;显式点名可切换;只读不启动;模板槽不钉
|
||||
3. [x] App 传入 activeDoc;payload 用一致 taskKey/docId
|
||||
4. [x] 单测 + 门禁 + 原子提交
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] UI-05 原文 + active intake → `intake` / `doc_proj6109_intake`
|
||||
- [x] 只读「查看当前受控文档」不启动任务
|
||||
- [x] 显式点名另一交付物可切换;模板-only 不钉住
|
||||
- [x] 服务端 task_key 与已注册 doc 不一致仍拒绝
|
||||
- [x] `go vet` / `go test -short` / web 242+27 / build / `git diff --check`
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: [../../audit/2026-09-13-document-revision-active-doc-routing.md](../../audit/2026-09-13-document-revision-active-doc-routing.md)
|
||||
- Evidence: [../../test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui05-active-doc-routing-failure](../../test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui05-active-doc-routing-failure)
|
||||
@@ -0,0 +1,55 @@
|
||||
---
|
||||
title: "职责单元格精确断言"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-14
|
||||
owner: Cursor-Auto
|
||||
branch: fix/document-revision-duty-cell-assertion
|
||||
worktree: "-"
|
||||
mutex: document-revision-duty-cell-assertion
|
||||
---
|
||||
|
||||
# 职责单元格精确断言
|
||||
|
||||
## 目标
|
||||
|
||||
堵住第16轮 UI-13a:权限矩阵已打开,整行 `innerText` 含全部 select option,误命中「编制负责人」。改为读控件 value/badge,且 USER_B 必须精确 `reviewer`,不得接受 viewer 降级。
|
||||
|
||||
## 范围
|
||||
|
||||
- `web/src/lib/dutyCellAssertion.ts` 与单测
|
||||
- `UserProjectRightsModal` 职责控件可访问语义
|
||||
- `web/e2e/document-revision-runtime.spec.ts` UI-13a
|
||||
- audit / remediation / CURRENT
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不放宽 reviewer 只读;不删双击/无编辑提示检查
|
||||
- 不碰证据;不合 dest;不启停容器;不 E2E;不 push
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 从 `dev@dd5671e` 开分支并登记 mutex
|
||||
2. [x] 精确角色解析 + option 文案不得误判测试
|
||||
3. [x] 产品控件 data-* + UI-13a 接线
|
||||
4. [x] `npm test` + `npm run build` 并原子提交
|
||||
5. [x] 独立审查收紧:只接受 reviewer;viewer 与 canAssignLead=true 拒绝
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] select/badge 必须精确 `reviewer`;viewer/author/approver 拒绝
|
||||
- [x] 整行 option 文案不得推断职责
|
||||
- [x] select 必须不可配置且 disabled
|
||||
- [ ] 现场 UI-13a(未跑)
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: [../../audit/2026-09-13-document-revision-duty-cell-assertion.md](../../audit/2026-09-13-document-revision-duty-cell-assertion.md)
|
||||
- Remediation: [../../remediation/2026-09-13-document-revision-duty-cell-assertion.md](../../remediation/2026-09-13-document-revision-duty-cell-assertion.md)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
- mutex:`document-revision-duty-cell-assertion`(新 mutex)
|
||||
- 基线:`dev@dd5671e`
|
||||
- 验证(收紧后):`npx tsx --test src/lib/dutyCellAssertion.test.ts` PASS(6);`cd web && npm test` PASS;`npm run build` PASS
|
||||
- **未跑真实 UI-13a,不得标 done**;**不得 merge / 启停容器 / E2E / push**
|
||||
@@ -0,0 +1,51 @@
|
||||
---
|
||||
title: "E2E:给真实文档块加稳定寻址并修正 UI-06/13b"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-14
|
||||
owner: Cursor-Auto
|
||||
branch: fix/document-revision-e2e-block-selector
|
||||
worktree: "-"
|
||||
mutex: document-revision-block-selector
|
||||
---
|
||||
|
||||
# E2E:给真实文档块加稳定寻址并修正 UI-06/13b
|
||||
|
||||
## 目标
|
||||
|
||||
第六轮 UI-06 首错:`pure` 模式下块 wrapper 无 `data-overlay-kind`、正文也不是 `p`/`h1`。为每个真实 `DocumentBlock` wrapper 增加与 overlay 无关的稳定 DOM 标识;E2E 只在 `active-document-pane` 内定位该标识。不改视觉/权限/双击行为。不得将本任务标 `done`。
|
||||
|
||||
## 范围
|
||||
|
||||
- `web/src/lib/documentBlockDom.ts` + 契约单测
|
||||
- `web/src/components/doc/BlockRenderer.tsx`
|
||||
- `web/e2e/document-revision-runtime.spec.ts`(`openFirstPaneEditorAndFill`;UI-06/13b 复用,UI-13a 同步)
|
||||
- 文档:audit / CURRENT
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不改编辑/权限/overlay 视觉
|
||||
- 不降低已有断言;不伪造、不直接打 API
|
||||
- 不触碰/提交 `.doc/test-reports/assets`;不操作容器;本轮不重跑 E2E
|
||||
- 不改 FEATURE-MATRIX
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 认领 CURRENT(mutex `document-revision-block-selector`);前序 reject-routing 保持 in_progress
|
||||
2. [x] 真实块 wrapper 增加 `data-testid=document-block` + block id
|
||||
3. [x] E2E 仅在 active pane 内按该标识双击
|
||||
4. [x] 契约单测:pure 模式也有块标识,且不依赖 `data-overlay-kind`
|
||||
5. [ ] 占槽后真实 UI 重跑(本轮不做)
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 块标识与 overlay 无关;带 block id
|
||||
- [x] `openFirstPaneEditorAndFill` 不使用 overlay/`p`/`h1`/`h2`
|
||||
- [x] web tests + `tsc`/build + `git diff --check`
|
||||
- [ ] 真实 UI-06/13b PASS 后才可将本任务标 `done`
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: [../../audit/2026-09-13-document-revision-block-selector.md](../../audit/2026-09-13-document-revision-block-selector.md)
|
||||
- Evidence: [../../test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui06-block-selector-failure](../../test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui06-block-selector-failure)
|
||||
- 前序: [2026-09-13-document-revision-e2e-reject-routing.md](./2026-09-13-document-revision-e2e-reject-routing.md)
|
||||
@@ -0,0 +1,51 @@
|
||||
---
|
||||
title: "E2E:纯净阅读按 document-block 取样 overlay"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-14
|
||||
owner: Cursor-Auto
|
||||
branch: fix/document-revision-e2e-overlay-selector
|
||||
worktree: "-"
|
||||
mutex: document-revision-overlay-selector
|
||||
---
|
||||
|
||||
# E2E:纯净阅读按 document-block 取样 overlay
|
||||
|
||||
## 目标
|
||||
|
||||
第八轮 UI-07 首错:pure 模式用 `[data-overlay-kind],[class*=block]` 找不到真实块。在 `active-document-pane` 内对全部 `document-block` 取样真实样式/hunk;manual/all 不保证两两不同。不得将本任务标 `done`。
|
||||
|
||||
## 范围
|
||||
|
||||
- `web/e2e/document-revision-runtime.spec.ts`(UI-07 取样;UI-10 历史自动关闭;UI-16 text 选择器)
|
||||
- `web/src/features/documentRevision/overlayMode.test.ts`(同一 human hunk 不保证 pairwise)
|
||||
- 文档:audit / CURRENT
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不新建 policy 抽象;不改 overlay 视觉/业务
|
||||
- 不人为换块制造 manual≠all
|
||||
- 不触碰/提交 `.doc/test-reports/assets`;不操作容器;本轮不重跑 E2E
|
||||
- 不改 FEATURE-MATRIX
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 认领 CURRENT(mutex `document-revision-overlay-selector`)
|
||||
2. [x] UI-07 在 pane `document-block` 上取样
|
||||
3. [x] 按 checklist 校正三模式断言
|
||||
4. [x] UI-10 按抽屉自动关闭比较
|
||||
5. [ ] 占槽后真实 UI 重跑(本轮不做)
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 禁止 `[class*=block]` / 全页 overlay 取样
|
||||
- [x] 纯净阅读必须无装饰;人工/全部必须有真实 hunk 装饰
|
||||
- [x] web tests + `tsc`/build + `git diff --check`
|
||||
- [ ] 真实 UI-07/08/09 PASS 后才可将本任务标 `done`
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: [../../audit/2026-09-13-document-revision-overlay-selector.md](../../audit/2026-09-13-document-revision-overlay-selector.md)
|
||||
- Evidence: [../../test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui07-pure-selector-failure](../../test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui07-pure-selector-failure)
|
||||
- Checklist: [../checklists/2026-09-13-document-revision-runtime-ui-acceptance.md](checklists/2026-09-13-document-revision-runtime-ui-acceptance.md)
|
||||
- 前序: [2026-09-13-document-revision-e2e-save-selector.md](./2026-09-13-document-revision-e2e-save-selector.md)
|
||||
@@ -0,0 +1,46 @@
|
||||
---
|
||||
title: "E2E:等 overlay CSS transition 结束后再取样"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-14
|
||||
owner: Cursor-Auto
|
||||
branch: fix/document-revision-e2e-overlay-transition
|
||||
worktree: "-"
|
||||
mutex: document-revision-overlay-transition
|
||||
---
|
||||
|
||||
# E2E:等 overlay CSS transition 结束后再取样
|
||||
|
||||
## 目标
|
||||
|
||||
第九轮 UI-07 首错:`data-overlay-kind` 已空,但采样落在 200ms transition 中间帧。用 Playwright 轮询 computed style 直到稳定且达到无装饰目标后再取样。不得将本任务标 `done`。
|
||||
|
||||
## 范围
|
||||
|
||||
- `web/e2e/document-revision-runtime.spec.ts`(pure/manual/all 均等样式 settle)
|
||||
- 文档:audit / CURRENT
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不禁用产品 `transition`;不固定极短 sleep;不放宽纯净无装饰断言
|
||||
- 不触碰/提交 `.doc/test-reports/assets`;不操作容器;本轮不重跑 E2E
|
||||
- 不改 FEATURE-MATRIX;不合 `dev`
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 认领 CURRENT(mutex `document-revision-overlay-transition`)
|
||||
2. [x] `expect.poll` 连续两帧相同且达到 mode 目标后再采样
|
||||
3. [ ] 占槽后真实 UI 重跑(本轮不做)
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 纯净阅读仍要求透明底 + `box-shadow:none` + 无 overlay-kind
|
||||
- [x] manual/all 也等 transition 完成
|
||||
- [x] web tests + `tsc`/build + `git diff --check` + Go 门禁
|
||||
- [ ] 真实 UI-07/08/09 PASS 后才可将本任务标 `done`
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: [../../audit/2026-09-13-document-revision-overlay-transition.md](../../audit/2026-09-13-document-revision-overlay-transition.md)
|
||||
- Evidence: [../../test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui07-css-transition-sampling-failure](../../test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui07-css-transition-sampling-failure)
|
||||
- 前序: [2026-09-13-document-revision-e2e-overlay-selector.md](./2026-09-13-document-revision-e2e-overlay-selector.md)
|
||||
@@ -0,0 +1,49 @@
|
||||
---
|
||||
title: "E2E:待确认报告必须真实打开再确认/拒绝"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-14
|
||||
owner: Cursor-Auto
|
||||
branch: fix/document-revision-e2e-pending-flow
|
||||
worktree: "-"
|
||||
mutex: pending-report-ui
|
||||
---
|
||||
|
||||
# E2E:待确认报告必须真实打开再确认/拒绝
|
||||
|
||||
## 目标
|
||||
|
||||
第四轮 UI-05a 首错修复:验收脚本按真实用户路径关闭首轮报告、打开「待确认报告」,在面板内断言 high(critical 允许)与 pending 动作后再确认/拒绝。不改产品业务逻辑。
|
||||
|
||||
## 范围
|
||||
|
||||
- `web/e2e/document-revision-runtime.spec.ts` UI-04 / UI-05a / UI-05b
|
||||
- 文档:audit / CURRENT 认领(mutex `pending-report-ui`;与 reject-routing 的 `document-revision-runtime-ui` 分开,避免虚报 done)
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不改 `ChangeReportPanel` / Toolbar / decision API
|
||||
- 不降低已有业务断言或超时;不伪造、不直接打 API
|
||||
- 不触碰/提交 `.doc/test-reports/assets`;不操作容器;本轮不重跑 E2E
|
||||
- 不改 FEATURE-MATRIX
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 认领 CURRENT;写 audit/short-term
|
||||
2. [x] UI-04 用弹窗内「关闭」并断言 dialog 消失
|
||||
3. [x] UI-05a 点击「待确认报告」,断言 risk/pending-actions/确认提交后确认
|
||||
4. [x] UI-05b 新 pending 后同样打开面板,断言 pending-actions/拒绝后再拒绝
|
||||
5. [ ] 占槽后真实 UI 重跑(本轮不做)
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] UI-04 不再使用无效 Escape
|
||||
- [x] UI-05a/05b 不靠全局 count 代替打开待确认报告
|
||||
- [x] web tests + `tsc`/build + `git diff --check`
|
||||
- [ ] 真实 UI-05a/05b PASS 后才可将本任务标 `done`
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: [../../audit/2026-09-13-document-revision-pending-report-selection.md](../../audit/2026-09-13-document-revision-pending-report-selection.md)
|
||||
- Evidence: [../../test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui05a-pending-report-selection-failure](../../test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui05a-pending-report-selection-failure)
|
||||
- Checklist: [../checklists/2026-09-13-document-revision-runtime-ui-acceptance.md](checklists/2026-09-13-document-revision-runtime-ui-acceptance.md)
|
||||
@@ -0,0 +1,62 @@
|
||||
---
|
||||
title: "E2E:UI-05b 钉住 intake 并收紧 UI-10/12/13/14"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-14
|
||||
owner: Cursor-Auto
|
||||
branch: fix/document-revision-e2e-reject-routing
|
||||
worktree: "-"
|
||||
mutex: document-revision-runtime-ui
|
||||
---
|
||||
|
||||
# E2E:UI-05b 钉住 intake 并收紧 UI-10/12/13/14
|
||||
|
||||
## 目标
|
||||
|
||||
第五轮 UI-05b 首错修复:拒绝用例 prompt 必须带「当前受控文档《用户初始需求收集表》」,并在本轮 `POST /tasks/runs` 上严格断言 `task_key==='intake'` 且 `doc_id===controlledDocId`。同步收紧 UI-10/12/13/14 真实用户路径。本轮追加产品修复:权威文档职责 + 打开时基线 ETag。
|
||||
|
||||
## 范围
|
||||
|
||||
- `internal/docgov/project_docs.go`(summary 职责投影)
|
||||
- `web/src` 职责字段、`resolveCurrentDocRole`、hydrate/PATCH ETag
|
||||
- `web/e2e/document-revision-runtime.spec.ts`(UI-13b 真实竞争)
|
||||
- 文档:audit / remediation / CURRENT(mutex `document-revision-runtime-ui`)
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不降低已有业务断言或超时;不伪造、不直接打 API
|
||||
- 不触碰/提交 `.doc/test-reports/assets`;不操作容器;本轮不重跑 E2E
|
||||
- 不改 FEATURE-MATRIX
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 认领 CURRENT;前序 pending-flow 保持 in_progress,mutex 改为 `pending-report-ui`(仅 UI-05a 实战 PASS,UI-05b 尚未拒绝,不得虚报 done)
|
||||
2. [x] UI-05b prompt + tasks/runs 契约断言 + 真实打开拒绝
|
||||
3. [x] UI-10 历史 dialog 内选 A/B 比较并关闭;UI-12 项目不可见;UI-13 拆成审核人只读 + 双 A 冲突;UI-14 同时锁 v/r
|
||||
4. [x] 仅修 05a/05b/10 遗留弹窗对 UI-06 的确切遮挡
|
||||
5. [x] 产品修复:权威职责 + viewer fail-closed + hydrate 基线 ETag
|
||||
6. [x] UI-13b:A1 保存前 A2 编辑器已打开并填入文本;两窗口同一 r/etag
|
||||
7. [x] 审查补强:controlled 缺 ETag fail-closed;viewer 只读批注;服务端零 id 不按 name 提权
|
||||
8. [ ] 占槽后真实 UI 重跑(本轮不做)
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] UI-05b 发送前等待 POST `/api/v1/tasks/runs`,`task_key`/`doc_id` 不符即 FAIL
|
||||
- [x] UI-10 不点全局工具条「比较」
|
||||
- [x] UI-12 不接受「项目可见但只查 marker」
|
||||
- [x] UI-13a/13b 结果分别记录;B 不作正文编辑者
|
||||
- [x] B/陌生人不会变 author;A 仍 author(Go + 前端单测)
|
||||
- [x] stale hydrate ETag 用于 PATCH(不能用最新 ETag 掩盖冲突)
|
||||
- [x] controlled 缺打开时 ETag 不得 PATCH 0:0;hydrate 5xx 进加载失败屏障
|
||||
- [x] viewer 无新增批注入口
|
||||
- [x] 服务端受控 duty id=0 不按 name 提权
|
||||
- [x] web tests + `tsc`/build + `git diff --check`
|
||||
- [ ] 真实 UI-05b+ 后段及 UI-13a/13b PASS 后才可将本任务标 `done`
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit (05b 路由): [../../audit/2026-09-13-document-revision-e2e-reject-routing.md](../../audit/2026-09-13-document-revision-e2e-reject-routing.md)
|
||||
- Audit (职责/ETag): [../../audit/2026-09-13-document-revision-duty-etag-overwrite.md](../../audit/2026-09-13-document-revision-duty-etag-overwrite.md)
|
||||
- Remediation: [../../remediation/2026-09-13-document-revision-duty-etag-overwrite.md](../../remediation/2026-09-13-document-revision-duty-etag-overwrite.md)
|
||||
- Evidence: [../../test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui05b-reject-routing-failure](../../test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui05b-reject-routing-failure)
|
||||
- 前序: [2026-09-13-document-revision-e2e-pending-flow.md](./2026-09-13-document-revision-e2e-pending-flow.md)
|
||||
@@ -0,0 +1,51 @@
|
||||
---
|
||||
title: "E2E:块编辑 dialog 内精确保存"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-14
|
||||
owner: Cursor-Auto
|
||||
branch: fix/document-revision-e2e-save-selector
|
||||
worktree: "-"
|
||||
mutex: document-revision-save-selector
|
||||
---
|
||||
|
||||
# E2E:块编辑 dialog 内精确保存
|
||||
|
||||
## 目标
|
||||
|
||||
第七轮 UI-06 首错:双击已打开编辑器,但全页模糊「保存」点到聊天私密库按钮,未 PATCH。给 `BlockEditorModal` 可访问 dialog + 稳定 aria-label;保存只在该 dialog 内 `exact: true` 点「保存修改」。不得将本任务标 `done`。
|
||||
|
||||
## 范围
|
||||
|
||||
- `web/src/lib/blockEditorDialog.ts` + 契约单测
|
||||
- `web/src/components/doc/BlockEditorModal.tsx`
|
||||
- `web/e2e/document-revision-runtime.spec.ts`(UI-06/13b 复用;UI-13a dialog=0)
|
||||
- 文档:audit / CURRENT
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不改视觉/保存业务
|
||||
- 不降低已有断言
|
||||
- 不触碰/提交 `.doc/test-reports/assets`;不操作容器;本轮不重跑 E2E
|
||||
- 不改 FEATURE-MATRIX
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 认领 CURRENT(mutex `document-revision-save-selector`)
|
||||
2. [x] dialog `role` + `aria-label=编辑受控块`
|
||||
3. [x] E2E 在 dialog 内精确点「保存修改」
|
||||
4. [x] UI-13a 断言编辑 dialog 不出现
|
||||
5. [ ] 占槽后真实 UI 重跑(本轮不做)
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 契约单测钉住 dialog label 与 exact 保存文案
|
||||
- [x] 禁止全页 `/保存/`
|
||||
- [x] web tests + `tsc`/build + `git diff --check`
|
||||
- [ ] 真实 UI-06/13b PASS 后才可将本任务标 `done`
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: [../../audit/2026-09-13-document-revision-save-selector.md](../../audit/2026-09-13-document-revision-save-selector.md)
|
||||
- Evidence: [../../test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui06-save-selector-failure](../../test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui06-save-selector-failure)
|
||||
- 前序: [2026-09-13-document-revision-e2e-block-selector.md](./2026-09-13-document-revision-e2e-block-selector.md)
|
||||
@@ -0,0 +1,61 @@
|
||||
---
|
||||
title: "编辑弹窗 hydration 竞态修复"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-14
|
||||
owner: Cursor-Auto
|
||||
branch: fix/document-revision-editor-hydration-race
|
||||
worktree: "-"
|
||||
mutex: document-revision-editor-hydration-race
|
||||
---
|
||||
|
||||
# 编辑弹窗 hydration 竞态修复
|
||||
|
||||
## 目标
|
||||
|
||||
堵住第十二轮 UI-06:编辑弹窗打开期间后台 hydration 换块 ID,保存静默关窗且不发 PATCH。用户编辑期间与 PATCH 成功后,迟到 hydration 不得覆盖基线;找不到块 fail-closed。
|
||||
|
||||
## 范围
|
||||
|
||||
- `web/src/lib/controlledDocHydrate.ts`:`fetchRevisionState` 保留 `head_block_map`,hydrate 后 `applyHeadBlockMap`
|
||||
- `web/src/lib/editorHydrationGate.ts` 与单测(迟到响应不得覆盖 PATCH 成功正文)
|
||||
- `web/src/lib/blockSavePolicy.ts` 与单测(stale-id / doc 绑定 / 切文档 fail-closed)
|
||||
- `web/src/lib/saveControlledBlockEdit.ts`:App 真实调用的 PATCH 编排(可注入 patch API)
|
||||
- `web/src/App.tsx`:`editorSession`、关窗续跑、切文档 fail-closed
|
||||
- audit / remediation / CURRENT 认领
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不修改、移动、删除或提交 `.doc/test-reports/assets/2026-09-13-document-revision-runtime-ui/`
|
||||
- 不合 `dev`、不 push、不启动/重建 Docker
|
||||
- 不运行或伪造真实 UI/E2E;不得声称 UI-06 已通过
|
||||
- 不改 FEATURE-MATRIX 完成度;不削弱 ETag/409
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 从 `dev@4c465d2` 开 `fix/document-revision-editor-hydration-race`,mutex 不与现有 in_progress 冲突
|
||||
2. [x] 定位全部会在弹窗打开期间替换 AST 的路径(effect / 选文档 / 重试;lease 改 deliverables 触发 effect)
|
||||
3. [x] hydrate 对齐 `head_block_map` + generation token / 编辑门闩 + stale-id fail-closed
|
||||
4. [x] 单测:同 map ID 稳定、缺 map 仍随机、deferred hydrate、stale id、迟到 hydrate、PATCH ETag、409
|
||||
5. [x] `web` npm test / build(首轮)
|
||||
6. [x] 独立审查补强:真实 PATCH 编排测试、editorDocId 绑定、关窗续跑、切文档 fail-closed
|
||||
7. [ ] 真实 UI-06 重跑(本轮不做)
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 编辑中不因后台 hydration 换 ID 而静默丢稿(逻辑门闩 + 单测)
|
||||
- [x] 找不到目标块保留编辑器并提示
|
||||
- [ ] 现场 r0→r1(未跑 E2E,保持未勾选)
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: [../../audit/2026-09-13-document-revision-editor-hydration-race.md](../../audit/2026-09-13-document-revision-editor-hydration-race.md)
|
||||
- Remediation: [../../remediation/2026-09-13-document-revision-editor-hydration-race.md](../../remediation/2026-09-13-document-revision-editor-hydration-race.md)
|
||||
- 失败证据(勿提交): `.doc/test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui06-r-bump-noop-failure/`
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
- mutex:`document-revision-editor-hydration-race`(新 mutex,未占用 `document-revision-save-selector` 等 in_progress 行)
|
||||
- 基线:`dev@4c465d2`
|
||||
- 验证:补强后全量 `npm test` + `npm run build` 通过;`saveControlledBlockEdit` 断言一次 PATCH
|
||||
- **未跑真实 UI-06,不得标 done**
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
title: "UI-11 快速完成观测契约"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-14
|
||||
owner: Cursor-Auto
|
||||
branch: fix/document-revision-fast-completion-observation
|
||||
worktree: "-"
|
||||
mutex: document-revision-fast-completion-observation
|
||||
---
|
||||
|
||||
# UI-11 快速完成观测契约
|
||||
|
||||
## 目标
|
||||
|
||||
堵住第14轮 UI-11:助手已 `completed`,验收脚本仍硬等处理中 60s,把成功终态误判为失败。只改测试契约,不降真实性。
|
||||
|
||||
## 范围
|
||||
|
||||
- `web/src/lib/squadCompletionObservation.ts` 与单测
|
||||
- `web/e2e/document-revision-runtime.spec.ts` 的 `waitForSquadCompletion`
|
||||
- audit / remediation / CURRENT
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不改产品运行时、不放宽上传/对应关系/终态/无错误
|
||||
- 不碰证据目录;不合 dest;不启动/重启容器;不 E2E;不 push
|
||||
- 不把 stub 或伪造页面当验收
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 从 `dev@339e871` 开分支并登记 mutex
|
||||
2. [x] 观测谓词 + 直接 completed / 经历 inflight 测试
|
||||
3. [x] 接线 `waitForSquadCompletion`,保留 UI-11 上传断言
|
||||
4. [x] 跑相关单测并原子提交
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 已 completed 直接接受,不要求 inflight
|
||||
- [x] 经历 inflight 再到终态仍接受
|
||||
- [x] 错误终态与错位消息拒绝
|
||||
- [ ] 现场 UI-11(未跑)
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: [../../audit/2026-09-13-document-revision-fast-completion-observation.md](../../audit/2026-09-13-document-revision-fast-completion-observation.md)
|
||||
- Remediation: [../../remediation/2026-09-13-document-revision-fast-completion-observation.md](../../remediation/2026-09-13-document-revision-fast-completion-observation.md)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
- mutex:`document-revision-fast-completion-observation`(新 mutex)
|
||||
- 基线:`dev@339e871`
|
||||
- 验证:`npx tsx --test src/lib/squadCompletionObservation.test.ts` PASS;`cd web && npm test` PASS(306 + 29)
|
||||
- **未跑真实 UI-11,不得标 done**;**不得 merge / rebuild / E2E / push**
|
||||
@@ -0,0 +1,61 @@
|
||||
---
|
||||
title: "文档修改、版本差异与智能体变更说明设计"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
owner: Codex
|
||||
branch: feature/document-revision-management
|
||||
worktree: "-"
|
||||
mutex: docgov
|
||||
---
|
||||
|
||||
# 文档修改、版本差异与智能体变更说明设计
|
||||
|
||||
## 目标
|
||||
|
||||
基于当前 DocGov、任务、块编辑器与通知实现,形成一套可直接评审和拆分实施的文档修改管理方案,覆盖人工修改标记、智能体/小队修改归属、版本边界、任意版本比较、AI 变更说明及负责人通知。
|
||||
|
||||
## 范围
|
||||
|
||||
- 交叉核对现有文档数据模型、保存链路、Agent 产物落盘、前端块编辑器、权限和通知机制。
|
||||
- 明确定义“智能体基线 + 后续人工修改”的工作副本与正式版本语义。
|
||||
- 设计数据模型、事务边界、API、前端交互、通知、权限、迁移兼容及验收矩阵。
|
||||
- 产出 audit、system-design、remediation 文档并同步文档索引与 FEATURE-MATRIX。
|
||||
|
||||
## 非目标
|
||||
|
||||
- 本任务不修改业务代码、数据库迁移或运行环境。
|
||||
- 本任务不执行共享容器重建、真实 PI E2E 或合入 `dev`。
|
||||
- 本任务不替用户决定版本保留周期、强监管电子签名策略等产品决策;方案给出推荐默认值和决策点。
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 完成当前实现与既有设计的证据核对。
|
||||
2. [x] 形成领域模型、版本状态机与一致性边界设计。
|
||||
3. [x] 形成前端展示、API、权限、通知与验收设计。
|
||||
4. [x] 形成分波次整改方案和实施任务拆分。
|
||||
5. [x] 更新文档索引、FEATURE-MATRIX、CURRENT 并执行文档质量检查。
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [ ] 方案能逐条映射用户提出的版本边界与显示规则。
|
||||
- [ ] 能区分用户、单智能体、智能体小队及系统迁移等修改主体。
|
||||
- [ ] 并发、失败恢复、权限、审计、通知去重和大文档性能均有确定性方案。
|
||||
- [ ] API、表结构、UI 状态、迁移顺序与测试用例足以供开发直接拆单。
|
||||
- [ ] 仅产生方案文档变更,无业务代码和环境变更。
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: `../../audit/2026-09-13-document-revision-management-gap-analysis.md`
|
||||
- System design: `../../system-design/document-revision-management.md`
|
||||
- Remediation: `../../remediation/2026-09-13-document-revision-management-implementation-plan.md`
|
||||
- Test report: 实施阶段补充
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
- 用户评审通过前保持 `in_progress`;本轮交付的是可评审方案,不代表能力已实现。
|
||||
- 2026-09-13:`git diff --check` PASS;新增文档及新增链接均可解析。
|
||||
- 索引文件中另有 3 个与本任务无关的既有失效链接(两个历史 `.tmp` 目录、一个 `architecture-design.md` 相对路径),本任务未扩大范围修改。
|
||||
- 2026-09-13:独立复审(Cline)通过,结论待用户最终拍板:①三项决策(智能体/模板开 Version、high/critical 强制编制负责人二次确认、首发只覆盖受控文档)均确认可行,理由与既有 `document_change_proposals` 认领授权机制一致;②抽查 DOCREV-01~09 全部 9 项源码证据属实(含 `bizdev/service.go:499-502` 通用提案文案、`:694-705` 忽略错误写哈希、`handlers.go:1027` 客户端 holder 直通、`BlockEditorModal.tsx:104` 硬编码“张工”、`saveDocumentContent` 无调用者、Goose 基线 00027);③补强 2 处设计缺口——根表指针列与既有 `freeform_documents.current_version_id` 同名冲突(改为 `ledger_*` 命名并明确旧列退役)、状态机把文档生命周期误并入版本状态(已拆为正交状态图);同步修订 system-design §4/§6.7、remediation §3/§5.2/§5.7。
|
||||
|
||||
- 2026-09-13:用户确认 DOCREV 实施计划选项 1;设计任务归档,进入 Wave 0。
|
||||
@@ -0,0 +1,57 @@
|
||||
---
|
||||
title: "文档账本 PG ID 与计数器重映射"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-14
|
||||
owner: Cursor-Auto
|
||||
branch: fix/document-revision-pg-id-remap
|
||||
worktree: "-"
|
||||
mutex: document-revision
|
||||
---
|
||||
|
||||
# 文档账本 PG ID 与计数器重映射
|
||||
|
||||
## 目标
|
||||
|
||||
堵住 schema31-round19:首次生成 PG 已写入 snapshot/version/candidate,但 `CommitAgentVersion` 因内存 map 误删 baseline 而 `not found`。
|
||||
|
||||
## 范围
|
||||
|
||||
- `internal/docrevision` ID 分配、adopt、PG persist
|
||||
- 确定性单测 + 隔离 PG 回归
|
||||
- audit / remediation / CURRENT / FEATURE-MATRIX / gap-matrix
|
||||
|
||||
## 非目标
|
||||
|
||||
- 本任务编码阶段不 merge / 不启停容器 / 不 push;Round20 验收见运行时 UI 报告
|
||||
- 不删不改证据目录
|
||||
- 不忽略 `ErrNotFound`,不伪造基线/报告
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 从 `dev@fa6a033` 开分支并登记 mutex
|
||||
2. [x] 独立验证 openTemplate 不推进 counter + 无条件 delete 误删
|
||||
3. [x] 统一 helper + 全路径 adopt
|
||||
4. [x] `gofmt` / `go vet` / `go test -short` / 相关包测试
|
||||
5. [x] 原子提交
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 占用 ID 不覆盖;adopt 只删同一对象
|
||||
- [x] 高序列首次生成:自动提交、V2、candidate committed、baseline 未丢、重启 hydration
|
||||
- [x] 现场 UI-03:Round20 项目 6159 首次生成 V2/r0,任务 `run_1789343479579646533` 成功(相对 6158 candidate id=175 / output snapshot 250 的 not found)
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: [../../audit/2026-09-13-document-revision-pg-id-remap.md](../../audit/2026-09-13-document-revision-pg-id-remap.md)
|
||||
- Remediation: [../../remediation/2026-09-13-document-revision-pg-id-remap.md](../../remediation/2026-09-13-document-revision-pg-id-remap.md)
|
||||
- Checklist: [../checklists/2026-09-13-document-revision-pg-id-remap.md](checklists/2026-09-13-document-revision-pg-id-remap.md)
|
||||
- Handoff: [../handoffs/2026-09-13-document-revision-pg-id-remap.md](handoffs/2026-09-13-document-revision-pg-id-remap.md)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
- 基线:`dev@fa6a033`
|
||||
- 验证:`gofmt`/`go vet` PASS;`go test -short ./...` PASS;隔离临时库 `HighSequenceFirstGen` PASS(拒绝 `agent_system_dev`,测完 DROP)
|
||||
- 失败归档(只读):`.doc/test-reports/assets/2026-09-13-document-revision-runtime-ui/schema31-round19-ui03-advisor-briefing-docrevision-not-found/`
|
||||
- 验收:Round20 UI-03 PASS,见 [../../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md](../../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md)
|
||||
- 工程修复已合入 `dev@b258ab8`
|
||||
@@ -0,0 +1,56 @@
|
||||
---
|
||||
title: "post-restart 期望正文须为最终持久 marker"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-14
|
||||
owner: Cursor-Auto
|
||||
branch: fix/document-revision-post-restart-final-snippet
|
||||
worktree: "-"
|
||||
mutex: document-revision-post-restart-final-snippet
|
||||
---
|
||||
|
||||
# post-restart 期望正文须为最终持久 marker
|
||||
|
||||
## 目标
|
||||
|
||||
第二次 post-restart 已恢复 login/项目/文档/`revision-state` 200/`V3`/`r2`/正文,但 `phase-state.bodySnippet` 仍是 UI-06 marker,断言旧文失败。UI-13b A1 成功保存后须把最终持久正文写入 phase-state;不得放宽 post body 断言。
|
||||
|
||||
## 范围
|
||||
|
||||
- `web/src/lib/durableBodySnippet.ts` 纯函数契约
|
||||
- UI-06 / UI-13b / UI-15-pre 同步 `latestDurableBodySnippet` → `phase-state.bodySnippet`
|
||||
- audit / checklist / handoff / CURRENT
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不改生产业务代码、不重跑真实 UI、不动容器、不 merge、不 push
|
||||
- 不改删 assets
|
||||
- 不改删历史失败 assets;不声称全仓 `production_ready=yes`
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 从 `dev@eb85b8a` 认领分支并登记 mutex
|
||||
2. [x] 成功修订覆盖旧 snippet;冲突失败稿不成为期望正文
|
||||
3. [x] UI-13b 完成后与 UI-15-pre 写入最终 marker
|
||||
4. [x] `npm test` / `npm run build`
|
||||
5. [x] 原子提交
|
||||
6. [x] Round20 `UI_PHASE=post-restart` PASS(V3/r2 / `A1-win-mu0gwiez`)
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 契约测试:A1 覆盖 UI06;A2 conflict 不覆盖 A1
|
||||
- [x] post-restart 仍断言 `st.bodySnippet` 可见
|
||||
- [x] 真实 UI-15 post-restart:Round20 1 passed / 18 skipped;页面恢复 V3/r2/正文
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: [../../audit/2026-09-13-document-revision-post-restart-final-snippet.md](../../audit/2026-09-13-document-revision-post-restart-final-snippet.md)
|
||||
- Checklist: [../checklists/2026-09-13-document-revision-post-restart-final-snippet.md](checklists/2026-09-13-document-revision-post-restart-final-snippet.md)
|
||||
- Handoff: [../handoffs/2026-09-13-document-revision-post-restart-final-snippet.md](handoffs/2026-09-13-document-revision-post-restart-final-snippet.md)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
- 基线:`dev@eb85b8a`
|
||||
- 失败归档(只读):`.doc/test-reports/assets/2026-09-13-document-revision-runtime-ui/schema31-postrestart-stale-body-snippet-failure/`(当时 `bodySnippet=UI06-mu0eq020`)
|
||||
- Round20 `phase-state`:`versionText=V3` `revisionText=r2` `bodySnippet=A1-win-mu0gwiez`
|
||||
- 报告:[../../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md](../../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md)
|
||||
@@ -0,0 +1,59 @@
|
||||
---
|
||||
title: "post-restart 项目名 selector 与阶段产物隔离"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-14
|
||||
owner: Cursor-Auto
|
||||
branch: fix/document-revision-post-restart-selector
|
||||
worktree: "-"
|
||||
mutex: document-revision-post-restart-selector
|
||||
---
|
||||
|
||||
# post-restart 项目名 selector 与阶段产物隔离
|
||||
|
||||
## 目标
|
||||
|
||||
第18轮 main 18 PASS 后,post-restart 在页面已恢复项目时因项目名同时出现在顶栏与侧栏而 strict violation。改为 banner 内唯一 exact 断言,点击仍走可见项目入口;Playwright output/report 与结果 JSON 按 `UI_PHASE` 分离(main 仍用 `ui-acceptance-results.json`)。
|
||||
|
||||
## 范围
|
||||
|
||||
- `web/e2e/document-revision-runtime.spec.ts` post-restart 项目恢复断言
|
||||
- `web/src/lib/currentProjectRestore.ts` 与契约测试
|
||||
- `web/playwright.config.ts` + `playwrightPhaseArtifacts` 按阶段分目录
|
||||
- audit / checklist / handoff / CURRENT
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不改业务逻辑、不重跑真实 UI、不动容器、不 merge、不 push
|
||||
- 不改删 `.doc/test-reports/assets/` 证据
|
||||
- 不声称 post-restart / UI-15 通过
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 从 `dev@b824948` 认领分支并登记 mutex
|
||||
2. [x] 项目入口 click + banner exact 断言;禁 `.first()` 弱化
|
||||
3. [x] `UI_PHASE` 分离 `playwright-output-*` / `playwright-report-*`
|
||||
4. [x] 结果 JSON:main 保持 `ui-acceptance-results.json`;post-restart 写 `ui-acceptance-results-post-restart.json`
|
||||
5. [x] `npm test` / `npm run build`
|
||||
6. [x] 原子提交
|
||||
7. [ ] 占槽后重跑 post-restart(本轮不做)
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 页面级 `getByText(项目名)` 在 2 命中时契约判定失败
|
||||
- [x] 入口为 complementary exact title;当前项目为 banner exact text
|
||||
- [x] main / post-restart 产物目录不同
|
||||
- [x] post-restart `recordPass` 不覆盖 main 的 `ui-acceptance-results.json`
|
||||
- [ ] 真实 UI-15 post-restart(未跑)
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: [../../audit/2026-09-13-document-revision-post-restart-selector.md](../../audit/2026-09-13-document-revision-post-restart-selector.md)
|
||||
- Checklist: [../checklists/2026-09-13-document-revision-post-restart-selector.md](checklists/2026-09-13-document-revision-post-restart-selector.md)
|
||||
- Handoff: [../handoffs/2026-09-13-document-revision-post-restart-selector.md](handoffs/2026-09-13-document-revision-post-restart-selector.md)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
- 基线:`dev@b824948`
|
||||
- 失败归档(只读):`.doc/test-reports/assets/2026-09-13-document-revision-runtime-ui/schema31-postrestart-project-title-selector-failure/`
|
||||
- **未跑真实 post-restart,不得标 done**
|
||||
@@ -0,0 +1,62 @@
|
||||
---
|
||||
title: "prelim_design 缺 output.md 产物契约修复"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-14
|
||||
owner: Cursor-Auto
|
||||
branch: fix/document-revision-pi-runner-module
|
||||
worktree: "-"
|
||||
mutex: document-revision-prelim-output
|
||||
---
|
||||
|
||||
# prelim_design 缺 output.md 产物契约修复
|
||||
|
||||
## 目标
|
||||
|
||||
第11轮 UI-11:202 + `prelim_design` 已正确,但 `step_01_draft` 缺真实 `output.md`。embed 官方模板、归一化 runner 路径、缺产物 fail-closed;对「进程 0 + settled failure / 缺产物」的**瞬时**失败做有界全新 step 重试。不得标 `done`。
|
||||
|
||||
## 范围
|
||||
|
||||
- `internal/template` embed + loader
|
||||
- `internal/agent` 路径映射、目标强制、瞬时/永久分类、`Result.Retryable`
|
||||
- `internal/squad` `runOneStep` 有界全新 invocation
|
||||
- `deploy/pi-agent/runner.mjs` + `settle-policy.mjs`
|
||||
- `deploy/pi-agent/Dockerfile` 必须 COPY runner 的全部相对 import 到 `/app`
|
||||
- `deploy/app/Dockerfile` `COPY templates` / `COPY configs` 到 `/app`;`.dockerignore` 放行官方 markdown
|
||||
- Docker build context / `/app/templates/docs` 读路径实测(不执行 env-service 重建)
|
||||
- 文档:audit / remediation / CURRENT
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不伪造 `output.md`;不执行截断 `write` 参数;不改 E2E prompt;不放宽缺失校验
|
||||
- 不触碰/提交证据目录;不执行 env-service 重建/重启;本轮不重跑 E2E
|
||||
- 不改 FEATURE-MATRIX;不合 `dev`;不 push
|
||||
- 不对永久缺失(干净 settle 后无产物、`prompt_empty`、治理)无限重试
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 从 `dev@2a58674` 开 `fix/document-revision-prelim-output` 并认领 mutex
|
||||
2. [x] 定位:stub 模板 + `agent_settled` 假成功 + 只认精确 `output.md` 键
|
||||
3. [x] embed / 映射 / runner fail-closed + 单测 + 门禁
|
||||
4. [x] 纳入现场时序:write 已流出但 `terminated`;SDK retry 1–3 Connection error;`auto_retry_end success=false`;仍 `agent_settled`;trace `success=true`
|
||||
5. [x] settle-policy + Go 分类 + `runOneStep` 有界全新重试 + 单测
|
||||
6. [x] `.dockerignore` 放行 `templates/**/*.md`;Docker context 实测 `/app/templates/docs/prelim_design.md`
|
||||
7. [x] 本次写入的目标不覆盖、不再调用;backend 明确失败仍 FAIL(不把文件存在当成功);上一轮残留不当成功
|
||||
8. [x] `dev@55a4f39` 重建后 runner `ERR_MODULE_NOT_FOUND settle-policy.mjs`:Dockerfile COPY 齐相对模块 + COPY 契约测试
|
||||
9. [ ] 占槽后真实 UI 重跑(本轮不做)
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [ ] 无盘模板时 `prelim_design` 仍为官方「系统初步设计方案」
|
||||
- [ ] 绝对/`./`/重复子目录 `rel_path` 能落到目标文件
|
||||
- [ ] `ok:true` 但无非空目标 → 失败,不发明正文
|
||||
- [x] 瞬时 settled failure → 最多一次全新 step;永久缺失不重试;耗尽 fail-closed
|
||||
- [x] pi-agent 镜像 COPY 含 runner 全部相对 import(含 `settle-policy.mjs`)
|
||||
- [ ] intake 工作流单测仍绿
|
||||
- [ ] 真实 UI-11 PASS 后才可标 `done`
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: [../../audit/2026-09-13-document-revision-prelim-output.md](../../audit/2026-09-13-document-revision-prelim-output.md)
|
||||
- Remediation: [../../remediation/2026-09-13-document-revision-prelim-output.md](../../remediation/2026-09-13-document-revision-prelim-output.md)
|
||||
- Evidence: [../../test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui11-prelim-design-missing-output-failure](../../test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui11-prelim-design-missing-output-failure)
|
||||
@@ -0,0 +1,46 @@
|
||||
---
|
||||
title: "质量门禁:行动计划表状态「待续」窄豁免"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-14
|
||||
owner: Cursor-Auto
|
||||
branch: fix/document-revision-quality-context
|
||||
worktree: "-"
|
||||
mutex: docgov
|
||||
---
|
||||
|
||||
# 质量门禁:行动计划表状态「待续」窄豁免
|
||||
|
||||
## 目标
|
||||
|
||||
结构化行动计划表中独立状态单元格「待续」不再误报;正文/标题/列表/普通表中的「待续」仍 FAIL。禁词表不得删除「待续」。
|
||||
|
||||
## 范围
|
||||
|
||||
- `internal/squad/quality_gate.go` 窄 Markdown 表结构识别
|
||||
- 敌意单测 + 既有自检豁免 / 投影 / repair 隔离不回归
|
||||
- 文档:audit / gap-matrix / CURRENT / FEATURE-MATRIX
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不删除「待续」禁词;不放宽普通正文/任意同行表格
|
||||
- 不触碰 assets / E2E;不操作容器
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 认领 CURRENT;写 audit/short-term
|
||||
2. [x] 仅豁免行动计划表「阶段/状态/进度」列独立单元格(去粗体精确等于「待续」+ 表头列索引对齐 + 实质行动 + 负责/触发完整)
|
||||
3. [x] 敌意用例:正文「后续章节待续」、`| 内容 | 待续 |`、待续说明、残行/空动作、负责方/触发=待续仍 FAIL;列重排仅状态列可 PASS
|
||||
4. [x] 门禁 + 原子提交
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 现场同构行动表 PASS,且不触发 repair
|
||||
- [x] 敌意上下文仍记录 `待续`
|
||||
- [x] `ProhibitedPhrases` 仍含「待续」
|
||||
- [x] targeted / `go vet` / `go test -short` / `go test -race ./internal/taskrun` / web test+build / `git diff --check`
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: [../../audit/2026-09-13-document-revision-quality-status-false-positive.md](../../audit/2026-09-13-document-revision-quality-status-false-positive.md)
|
||||
- Evidence: [../../test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui03-quality-status-false-positive](../../test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui03-quality-status-false-positive)
|
||||
@@ -0,0 +1,57 @@
|
||||
---
|
||||
title: "质量修复子工作区契约"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-14
|
||||
owner: Cursor-Auto
|
||||
branch: fix/document-revision-quality-repair-workspace-contract
|
||||
worktree: "-"
|
||||
mutex: document-revision-quality-repair-workspace-contract
|
||||
---
|
||||
|
||||
# 质量修复子工作区契约
|
||||
|
||||
## 目标
|
||||
|
||||
堵住第13轮 UI-03:repair 步 TASK 引导 `../../output.md`,模型越界改根文件,本地目标缺失导致 `quality_failed` 停在 70。门禁判定保持,修复契约改为本地快照 + containment。
|
||||
|
||||
## 范围
|
||||
|
||||
- `internal/squad/repair_workspace.go` 与单测
|
||||
- `EnsureQualityOrRepair` / `buildSubWorkspaces` snapshot 布局
|
||||
- audit / remediation / CURRENT
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不放宽必填章节;不把越界根文件当成功;不隐藏 `quality_failed`
|
||||
- 不改默认步骤的 `../../` context 导航
|
||||
- 不碰证据目录;不合 dev;不 rebuild Docker;不 E2E;不 push
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 从 `dev@8b1a531` 开分支并登记 mutex
|
||||
2. [x] 快照契约 + containment + 测试
|
||||
3. [x] 独立审查 fail-open:`runErr` / containment 不得提升;restore 失败硬返回;创建/删除计入 mutation
|
||||
4. [x] gofmt / vet / `go test -short ./...` / `-race` squad+agent / settle-policy.test.mjs / `git diff --check`
|
||||
5. [ ] 真实 UI-03(本轮不做)
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 仅 `runErr==nil` ∧ 无 containment ∧ `TrustedLocalDeliverable=true` 才覆盖根并重验
|
||||
- [x] 越界(含创建/删除受保护父级)恢复后不提升,报告 FAIL
|
||||
- [x] backend 失败/超时即使留下本地目标也不提升
|
||||
- [x] restore 失败立即返回,可测策略能断言错误传播
|
||||
- [ ] 现场 UI-03(未跑)
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: [../../audit/2026-09-13-document-revision-quality-repair-workspace-contract.md](../../audit/2026-09-13-document-revision-quality-repair-workspace-contract.md)
|
||||
- Remediation: [../../remediation/2026-09-13-document-revision-quality-repair-workspace-contract.md](../../remediation/2026-09-13-document-revision-quality-repair-workspace-contract.md)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
- mutex:`document-revision-quality-repair-workspace-contract`(新 mutex,不与现有 in_progress 冲突)
|
||||
- 基线:`dev@8b1a531`
|
||||
- 验证(fail-closed 追加):`gofmt` / `go vet ./...` / `go test -short ./...` / `go test -short -race ./internal/squad/ ./internal/agent/` / `node --test deploy/pi-agent/settle-policy.test.mjs` / `git diff --check` PASS
|
||||
- 保护范围仅 `output.md` / `template.md` / `blackboard.json`;其它父级文件是剩余风险
|
||||
- **未跑真实 UI-03,不得标 done**;**不得 merge / rebuild / E2E / push**
|
||||
@@ -0,0 +1,68 @@
|
||||
---
|
||||
title: "项目 reviewer 同步到受控文档职责"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-14
|
||||
owner: Cursor-Auto
|
||||
branch: fix/document-revision-reviewer-duty-sync
|
||||
worktree: "-"
|
||||
mutex: document-revision-reviewer-duty-sync
|
||||
---
|
||||
|
||||
# 项目 reviewer 同步到受控文档职责
|
||||
|
||||
## 目标
|
||||
|
||||
堵住第17轮 UI-13a:UI-01 已把 USER_B 设为 reviewer,但 `doc_proj6145_intake` 矩阵为 viewer。项目创建时的 reviewer 必须成为后续每份受控文档的权威 `reviewerId`。
|
||||
|
||||
## 范围
|
||||
|
||||
- `project_members.document_duty` 迁移与成员 upsert
|
||||
- 任务生成/账本创建解析项目职责;禁止硬编码 2/3
|
||||
- 已有文档缺失/非成员占位的服务端自愈
|
||||
- 前端立项 persist `document_duty` + 职责互斥
|
||||
- audit / remediation / CURRENT
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不 merge、不启停/重建容器、不跑/声称真实 UI E2E、不 push
|
||||
- 不删不改证据目录
|
||||
- 不向用户索要 token;不提交账号密码
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 从 `dev@639969f` 开分支并登记 mutex
|
||||
2. [x] RED/GREEN:解析、自愈、成员 duty、前端映射
|
||||
3. [x] `gofmt` / `go vet` / `go test -short` / 相关 `-race` / `npm test` / `npm run build`
|
||||
4. [x] 原子提交
|
||||
5. [x] 独立审查收紧(暂不合入):Heal 以 assigned 为权威;成员变更带 duty 并同步文档;缺 role 不降 owner;写权精确断言;迁移多 owner 确定回填;并发 upsert PG 用例;自愈失败不假成功
|
||||
6. [x] 最后一轮:移出成员 sync + 前端刷新;空 assigned 只清失效 holder;显式 revoke 再 heal;账本创建失败不成功
|
||||
7. [x] 补充审查:lock + 读旧/冲突 holder + 成员写 + 精确清槽同事务;提交后 heal;失败仍 `ERR_DUTY_SYNC`
|
||||
8. [x] Heal 与成员写共用 `pg_advisory_xact_lock(project_id)`;解析与文档读写同事务;确定性并发 PG 证明旧 reviewer 不复活
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] A=author、B=reviewer、C=none;第二文档继承;重复执行幂等;旧文档缺失回填
|
||||
- [x] 服务端写操作仍按权限拒绝
|
||||
- [x] 前端不按名字提升
|
||||
- [ ] 现场 UI-13a(未跑)
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: [../../audit/2026-09-13-document-revision-reviewer-duty-sync.md](../../audit/2026-09-13-document-revision-reviewer-duty-sync.md)
|
||||
- Remediation: [../../remediation/2026-09-13-document-revision-reviewer-duty-sync.md](../../remediation/2026-09-13-document-revision-reviewer-duty-sync.md)
|
||||
- Checklist: [../checklists/2026-09-13-document-revision-reviewer-duty-sync.md](checklists/2026-09-13-document-revision-reviewer-duty-sync.md)
|
||||
- Handoff: [../handoffs/2026-09-13-document-revision-reviewer-duty-sync.md](handoffs/2026-09-13-document-revision-reviewer-duty-sync.md)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
- mutex:`document-revision-reviewer-duty-sync`(新 mutex,不占用已有 in_progress)
|
||||
- 基线:`dev@639969f`
|
||||
- 证据(只读):`.doc/test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui13a-reviewer-duty-sync-failure/`
|
||||
- 验证(原子清槽轮):`gofmt`/`go vet` PASS;`go test -short ./...` PASS;相关 `-race` PASS;`npm test`/`build` PASS;隔离 PG PASS
|
||||
- 原子性:成员写与 `HealProjectDocuments` 均先 `pg_advisory_xact_lock(project_id)`,再在同一事务内读成员/文档并更新;旧 heal 不能在转移提交后把 reviewer A 写回
|
||||
- PG 集成已写 heal/空 assigned/多 owner 回填/并发 upsert;`-short` 或无 `TEST_DATABASE_URL` 时跳过
|
||||
- 隔离跑法:`scripts/run-isolated-duty-sync-pg-tests.sh`(`TEST_DATABASE_URL` 或 `PG_ADMIN_URL` 建临时库)。拒绝 `agent_system_dev`
|
||||
- 本轮已在已运行的 context Postgres 上 `CREATE DATABASE agent_duty_sync_itest_*`,串行跑通后 `DROP`;未 `env-service`、未动共享库数据
|
||||
- **兼容**:旧二进制不读 `document_duty` 仍可运行;新代码在 assigned 为空时不臆造 reviewer。6145 的 B 仍是空 duty,须再走成员 API
|
||||
- **未跑真实 UI-13a,不得标 done**;**不得 merge / 启停容器 / E2E / push**
|
||||
@@ -0,0 +1,107 @@
|
||||
---
|
||||
title: "文档版本账本运行时整改"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-14
|
||||
owner: Cursor-Auto
|
||||
branch: fix/document-revision-runtime-ui03
|
||||
worktree: "-"
|
||||
mutex: docgov
|
||||
---
|
||||
|
||||
# 文档版本账本运行时整改
|
||||
|
||||
## 目标
|
||||
|
||||
消除 revision-state 404、重启丢账本、人工保存无效、overlay 无效;接通首轮/二轮可见确定性 change report;PATCH 权限→账本→投影顺序正确;停在 fix 分支待集成。
|
||||
|
||||
## 范围
|
||||
|
||||
- `internal/docrevision` PG hydrate/persist + bootstrap + `MaterializeAgentOutput`
|
||||
- `internal/server` 授权、PATCH 顺序、orphan 不静默建账
|
||||
- `internal/bizdev` 小队成功走 Materialize(禁止仅 OpenTemplate)
|
||||
- `cmd/document-revision-backfill` gofmt
|
||||
- `web` 保存链路与 overlay 三模式
|
||||
- 工程测试 + 扩展 UI 验收计划(分栏)
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不占 CURRENT 集成槽、不 `env-service rebuild`、不 push、不 merge `dev`
|
||||
- 不伪造 PI 叙事 change report;不把 fallback 说成完整 PI 分析
|
||||
- 不把 stub 输出写入最终用户验收报告
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 审计 / 整改 / 本任务 + CURRENT 认领
|
||||
2. [x] 分支 `fix/document-revision-runtime`
|
||||
3. [x] PG store + bootstrap + backfill
|
||||
4. [x] Handler / agent / 前端
|
||||
5. [x] 首轮报告 Materialize + PATCH 顺序 + 单测
|
||||
6. [x] gofmt + UI checklist 扩展 + 文档证据
|
||||
7. [x] 分层 commit,输出哈希与剩余 blocker(不 merge/push)
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 工程门禁与 UI 实战计划分栏
|
||||
- [x] Round20 真实 UI **PASS**(见 [../../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md](../../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md))
|
||||
- [x] 剩余开放:PI 叙事仍为 fallback;orphan 禁止假 V1(UI-16 验证已注册路径);不可用假数据掩盖
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: [../../audit/2026-09-13-document-revision-runtime-404.md](../../audit/2026-09-13-document-revision-runtime-404.md)
|
||||
- Remediation: [../../remediation/2026-09-13-document-revision-runtime-remediation.md](../../remediation/2026-09-13-document-revision-runtime-remediation.md)
|
||||
- Checklist/UI: [../checklists/2026-09-13-document-revision-runtime-ui-acceptance.md](checklists/2026-09-13-document-revision-runtime-ui-acceptance.md)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
### 工程门禁(非 UI 验收)
|
||||
|
||||
```text
|
||||
gofmt -l cmd/document-revision-backfill/main.go internal/docrevision/risk.go
|
||||
go vet ./...
|
||||
go test -short ./...
|
||||
cd web && npm test && npm run build
|
||||
```
|
||||
|
||||
本轮门禁(2026-09-13 10:11 UTC 独立复跑):`go vet ./...` PASS;`go test -short ./... -count=1` PASS(含 Materialize 首/二轮 change_report_id、PATCH 顺序、Materialize 失败透出、Assert 先职责后租约、SaveDocumentContent 审计、pending 事实源不越权、同步/异步待确认文案、完成活动仅 committed、pending 活动标明待确认、MarkProposalApplied 失败显式可重试);`web npm test` 199+27 PASS;`npm run build` PASS。使用 dev PostgreSQL(schema 28)执行 `TestPGPersistSurvivesNewServiceInstance` PASS,证明新 Service 实例可恢复账本。上述均为工程门禁,不能替代 UI 验收。
|
||||
|
||||
UI-01 目录同步补丁门禁(2026-09-13):`node --test adminUserDirectorySync.test.ts` 3 PASS;`web npm test` 219+27 PASS;`npm run build` PASS;`go vet ./...` + `go test -short ./...` PASS。未提交 `web/e2e/*` 与 `test-reports/assets/`。
|
||||
|
||||
UI-01/02 访问与成员落库门禁(2026-09-13):`go test ./internal/projectinstance -short` PASS;`TEST_DATABASE_URL=… go test ./internal/projectinstance -run TestPG_GoverningAccess` PASS;`TEST_DATABASE_URL=… go test ./internal/server -run TestChatProjectAccess` PASS;`go vet ./...` + `go test -short ./...`;`web npm test` + `npm run build`。未提交 e2e/assets。
|
||||
|
||||
复核补强(同日):
|
||||
- A:`MaterializeAgentOutput` 错误写入 `TaskRunResult.Success=false` + `ErrorReason`,不再空白忽略
|
||||
- B:cand 非空且 report invalid/unassessed 时禁止自动提交(候选标 needs_confirmation)
|
||||
- C:`AssertHumanCanEdit` 先职责/生命周期再租约;受控投影改 `SaveDocumentContent` 保留 author_last_edited/审计;失败 `DOCUMENT_PROJECTION_FAILED` 可幂等重试
|
||||
- D:ChangeReportPanel 完整展示风险条目/项目影响/文档影响建议/开放问题;加载失败显式错误
|
||||
- E:revision-state 暴露 `pending_candidate_id` / `pending_change_report_id` / `pending_risk_level` + `can_decide_pending`;工具条「待确认报告」确认/拒绝调 decision API(不绕过确认)
|
||||
- F:**高风险事实源门禁**:Materialize 后仅 committed 才 MarkDocumentContentUpdated / MarkProposalApplied;`needs_confirmation` 立即 `ProjectOutputMarkdown` 恢复 ledger head,候选仅留 immutable blob;decision=commit 投影后再 Mark;decision=reject 保持旧 head;投影失败显式错误
|
||||
- G:**对话可见状态**:`TaskRunResult` 带 `pending_agent_candidate_id` / report / risk;`RequiresAuthorApproval` 可复用但用 `PendingProposal` vs `PendingAgentCandidateID` 区分 DocGov 提案;terminal=`pending_author_confirmation`;同步 coordinator 与异步 `CompletionSummary` 显示「文档候选已生成,待编制人确认」+ artifact 元数据;确认并投影后才「已完成」
|
||||
- H:**活动与提案收口**:`RecordActivity(完成交付物)` 仅在 committed 投影成功后;pending 记「候选待编制人确认」;落盘/投影失败不记完成。`MarkProposalApplied` 失败返回显式错误(bizdev / `DOCUMENT_GOVERNANCE_FAILED`)可重试
|
||||
- I:**阶段链防传播**:`ExecuteStage` 遇 `PendingAgentCandidateID` 立即停阶段(Success=false + 待确认文案),SubArtifacts 保留候选,**不**吸收 ExtractedData / PriorDoc;确认后由用户重新发起阶段
|
||||
- J:**前端历史映射**:`pending_author_confirmation` 显式映射为气泡状态(不再默认 completed);刷新窗口显示「待编制人确认」标签
|
||||
- K:**决策幂等收口**:`CommitAgentVersion` 已 committed 且 expected hashes 一致时返回当前 state(可继续投影/MarkProposalApplied);已 committed 禁止 reject。`MarkProposalApplied` 先写 DB 再改内存;已 applied 幂等(包内 Propose+Decide 验证)。decision 失败 hint 指向同决策重试;**不**暴露内存补种 helper(避免内存/DB 分叉)
|
||||
- L:**Playwright 骨架**:`web` 增加 `@playwright/test` + `playwright.config.ts` + `e2e/document-revision-runtime.spec.ts`(`RUN_UI_ACCEPTANCE=1` 才跑;无 mock/route/API/DB fixture)
|
||||
- M:**上传注册事实源**:发送前 `await registerUploadAttachments` → `POST /api/v1/freeform-documents`(`client_key` 幂等);失败 UI 显式错误且不发消息、不生成本地 `doc-upload` orphan;成功使用 `doc-free-*` 写入 deliverable/fileStore 并挂 toolbar
|
||||
- N:**Auth 契约映射(UI-00 实战)**:Go `UserAccount` 为 snake_case;前端在 API 边界 `mapUserAccount`/`mapLoginResult`/`mapMeResult` 统一转 camelCase(login/me/admin users/create/role/status);`BootstrapAdminFromConfig` 的 `UpdateUserRole` 错误不再静默。详见 [../../audit/2026-09-13-auth-useraccount-snake-case-mapping.md](../../audit/2026-09-13-auth-useraccount-snake-case-mapping.md)
|
||||
- O:**全局用户目录同步(UI-01 实战)**:管理员创建/角色/状态成功后必须经 `syncAdminUserDirectories` 调用父级 `onRefreshUsers`(禁止死 prop / 静默 catch);同浏览器立项候选可立即看到新账号。跨设备/清缓存缺口见 audit 残留风险,**不**下放 admin users API。详见 [../../audit/2026-09-13-admin-user-directory-sync-ui01.md](../../audit/2026-09-13-admin-user-directory-sync-ui01.md)
|
||||
- P:**无 live 访问 + chat 项目门禁 + 立项成员落库(UI-01/02)**:`GetGoverningInstanceForAccess` 区分从未激活 vs completed/terminated;chat/chatStream 先 `RequireProjectAccess` 再 stage(SSE 拒绝不得先 200);`createProject` 后持久化非创建者成员。详见 [../../audit/2026-09-13-workflow-access-chat-members-ui01-02.md](../../audit/2026-09-13-workflow-access-chat-members-ui01-02.md)
|
||||
- Q:**立项确认双击竞态**:`handleCreateProjectConfirm` 加同步 in-flight `useRef` 锁 + `createProjectBootstrapIdRef`(取代 state);`createProjectSubmitting`/`submitPhase` 驱动 Modal「立项中/同步成员中」、禁用确认与关闭;失败可串行幂等重试,成功清 bootstrap。证据:`createProjectSubmitGuard.test.ts`
|
||||
- R:**UI-02 任务作用域契约**:`ResolveMessageScopeForTask` 三态(preactivation / live stage / closed→Err);handler 无 live 创建 202 非 409;E2E UI-02 以 `POST /api/v1/tasks/runs` 2xx 为硬门禁(409/连接异常 FAIL)。证据:`message_scope_test.go`、`TestCreateTaskRun_PreActivationAcceptedNot409`、`document-revision-runtime.spec.ts` UI-02
|
||||
- S:**UI-03 客户端同步 + 任务幂等(本分支)**:`templateMatch` intake 标记优先;任务终态后 `postTaskDeliverableSync` merge `doc_proj*`;goose `00030` 放行 `pending_author_confirmation` + `idempotency_key` 部分唯一;`ClaimRun` 先占键再写 chat;FE reconnect 同 run 订阅。审计:[../../audit/2026-09-13-controlled-doc-client-sync-ui03.md](../../audit/2026-09-13-controlled-doc-client-sync-ui03.md)。门禁:`go test -short ./internal/taskrun ./internal/server`;`web npm test` 232+27;`npm run build`。**schema30 真实现卷迁移合入前独立验证**;真实 UI-03 待占槽重跑。
|
||||
|
||||
### 用户 UI 实战验收
|
||||
|
||||
Round20 **PASS**。见 [checklist](checklists/2026-09-13-document-revision-runtime-ui-acceptance.md) 与 [test-report](../../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md)。项目 6159;UI-03 V2/r0;终态 V3/r2;post-restart 恢复最终正文 `A1-win-mu0gwiez`。
|
||||
|
||||
### Blockers
|
||||
|
||||
- **DOCREV-RT-PI-NARRATIVE**(仍开放):真实 PI 业务叙事摘要/风险解释未替代确定性 fallback;Round20 已可见 fallback 字段,不得宣称为完整 PI
|
||||
- **DOCREV-RT-UPLOAD-ORPHAN**(约束仍在,UI-16 PASS):仅 IndexedDB、无服务端正文 → 禁止假 V1
|
||||
- **DOCREV-RT-UI-E2E**:**PASS**(Round20)
|
||||
- **DOCREV-RT-SCHEMA30-VOLUME**:goose 00030 对既有重复卷的迁移仍属合入前独立验证残留
|
||||
- **DOCREV-RT-USER-DIR-CROSS-DEVICE**:跨设备/新浏览器可能仍缺成员候选(本轮同浏览器未暴露)
|
||||
|
||||
### Commits(历史)
|
||||
|
||||
- `7ea686e` … `ec8a45a`(见 git log);本轮追加见会话结束提交号
|
||||
@@ -0,0 +1,55 @@
|
||||
---
|
||||
title: "UI-11 点名优先路由 + PATCH 请求级释租"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-14
|
||||
owner: Cursor-Auto
|
||||
branch: fix/document-revision-second-doc-routing-lease
|
||||
worktree: "-"
|
||||
mutex: document-revision-second-doc-routing-lease
|
||||
---
|
||||
|
||||
# UI-11 点名优先路由 + PATCH 请求级释租
|
||||
|
||||
## 目标
|
||||
|
||||
第十轮 UI-11 首错:否定句「需求」压过「系统设计输入」,且 PATCH 残留 human lease 使小队 DOC_BUSY。点名优先 + 请求级 defer 释租 + E2E 202 门闩。不得将本任务标 `done`。
|
||||
|
||||
## 范围
|
||||
|
||||
- `web/src/engine/templateMatch.ts` + 单测
|
||||
- `internal/server/document_revision_handlers.go` + `document_revision_patch_order_test.go`
|
||||
- `web/e2e/document-revision-runtime.spec.ts` UI-11 waiter
|
||||
- 文档:audit / remediation / CURRENT
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不改 E2E prompt;不改 `SaveDocumentContent` 内部释租
|
||||
- 不触碰/提交 `.doc/test-reports/assets`;不操作容器;本轮不重跑 E2E
|
||||
- 不改 FEATURE-MATRIX;不合 `dev`;不 push
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 认领 CURRENT(mutex `document-revision-second-doc-routing-lease`)
|
||||
2. [x] 点名优先 +「系统设计输入」别名 + 单测
|
||||
3. [x] PATCH 已授权后 defer 释租(成功 / 409 / 投影失败)+ 服务端测试
|
||||
4. [x] UI-11 send 前 `tasks/runs` waiter,断言 202 后再 wait completion
|
||||
5. [ ] 占槽后真实 UI 重跑(本轮不做)
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] UI-11 原文 / 混合句 → `prelim_design`;当前文档钉住、UI-05 pin、首轮摸底仍 intake
|
||||
- [x] PATCH 后无 human lease,squad 可获取
|
||||
- [x] UI-11 非 202 即 fail;`requireInflight` 拒绝同步 busy
|
||||
- [ ] 真实 UI-11 PASS 后才可将本任务标 `done`
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: [../../audit/2026-09-13-document-revision-second-doc-routing-lease.md](../../audit/2026-09-13-document-revision-second-doc-routing-lease.md)
|
||||
- Remediation: [../../remediation/2026-09-13-document-revision-second-doc-routing-lease.md](../../remediation/2026-09-13-document-revision-second-doc-routing-lease.md)
|
||||
- Evidence: [../../test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui11-second-doc-routing-human-lease-failure](../../test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui11-second-doc-routing-human-lease-failure)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
- Prompt 别名「系统设计输入」≠ 卡片标题。真实 UI / 模板 / squad 标题均为「系统初步设计方案」。
|
||||
- UI-11 打开第二份文档必须用已注册 `doc_proj{n}_prelim_design`(`data-doc-id`),禁止 `/设计输入|系统设计/`:既匹配不到真实标题,也容易误命中其他设计类文案或同标题模板槽。
|
||||
@@ -0,0 +1,57 @@
|
||||
---
|
||||
title: "任务 SSE 幂等 + 质量门禁自污染与 auto_repair 产品契约"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-14
|
||||
owner: Cursor-Auto
|
||||
branch: fix/document-revision-sse-idempotency
|
||||
worktree: "-"
|
||||
mutex: docgov
|
||||
---
|
||||
|
||||
# 任务 SSE 幂等 + 质量门禁自污染与 auto_repair 产品契约
|
||||
|
||||
## 目标
|
||||
|
||||
1. 同 turn 在 SSE 断线重连时返回既有 run 202、不重复聊天、不误 409 DOC_BUSY;长任务 events SSE 不被 120s WriteTimeout 切断;前端 EOF 按 after_seq 重订阅同一 run。
|
||||
2. 受控文档小队任务质量门禁:**服务端启用修复预算**;否定性自检引用不误报;`quality_failed` UI 保持失败且不激活未过门禁稿。
|
||||
|
||||
## 范围
|
||||
|
||||
- SSE/幂等:`task_run_handlers`、SSE write deadline、FE subscribe 重连
|
||||
- 质量 A–D:`repairBudgetForSquadTask`、`quality_gate` 语境检测、prompt 去原词、Materialize/`TerminalStatus`、FE `quality_failed`、单测
|
||||
- 证据:`data/dev/workspaces/bizdev/intake_1789308825666278807`(output.md:204;events seq10)
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不改全局 HTTP 超时为「无超时」;不 rebuild Docker;不 push/merge;不删证据 assets
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 从 `dev` 开 `fix/document-revision-sse-idempotency`;CURRENT 认领
|
||||
2. [x] 幂等先查 + 属主校验
|
||||
3. [x] SSE write deadline + heartbeat
|
||||
4. [x] FE subscribe 重连
|
||||
5. [x] A 服务端修复预算产品契约
|
||||
6. [x] B 门禁否定/元语境 + prompt 去原词
|
||||
7. [x] C quality_failed UI/Materialize 契约
|
||||
8. [x] D 真实问题单测 + 门禁回归
|
||||
9. [x] E 质量失败在 SetDocumentWorkDir/Materialize 前短路(无正式投影副作用)
|
||||
10. [x] 豁免收窄为同行 meta+否定紧邻/引号;handlers 阶段请求字段边界单测锁定
|
||||
11. [x] ExecuteStage 质量失败停链:不吸收事实、不追加 PriorDoc
|
||||
12. [x] 小队 AutoRepair/Success 语义恢复;受控修复仅在 bizdev docRec 与 HTTP 边界强制
|
||||
13. [x] 补强:quality projection / 阶段停链 / 非受控不强制 repair 单测;全量 Go+Web 门禁 PASS
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 同 turn + 活跃租约 → 同 run 202、仅一对消息;不同 turn → 仍 409
|
||||
- [x] SSE 心跳/写期限可测;FE EOF/after_seq 单测
|
||||
- [x] TaskKey 任务 AutoRepair=false 仍有 DefaultMaxRepairRounds;L204 自检引用不误报;真敷衍仍 FAIL
|
||||
- [x] quality_failed ≠ completed;Materialize 跳过未过门禁稿
|
||||
- [x] `go test -short ./...`、`go vet`、`npm test`/`build`、`git diff --check`
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit SSE: [../../audit/2026-09-13-document-revision-sse-idempotency.md](../../audit/2026-09-13-document-revision-sse-idempotency.md)
|
||||
- Audit 质量: [../../audit/2026-09-13-document-revision-quality-gate-self-pollution.md](../../audit/2026-09-13-document-revision-quality-gate-self-pollution.md)
|
||||
- Evidence: [../../test-reports/assets/2026-09-13-document-revision-runtime-ui/](../../test-reports/assets/2026-09-13-document-revision-runtime-ui/)
|
||||
@@ -0,0 +1,49 @@
|
||||
---
|
||||
title: "DOCREV Wave 0:契约冻结"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
owner: Cursor
|
||||
branch: feature/document-revision-management
|
||||
worktree: "-"
|
||||
mutex: docgov
|
||||
---
|
||||
|
||||
# DOCREV Wave 0:契约冻结
|
||||
|
||||
## 目标
|
||||
|
||||
冻结 Version/Revision/Snapshot/Candidate/Report 契约、黄金 diff fixture、前后端类型与先红契约测试。
|
||||
|
||||
## 范围
|
||||
|
||||
- ADR 决策门落盘
|
||||
- `internal/docrevision` 契约类型、schema、testdata、契约测试
|
||||
- `web/src/features/documentRevision/types.ts`
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不写生产写路径;不跑容器重建;不合入 `dev`
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [ ] 写入 ADR 与决策门
|
||||
2. [ ] 实现契约类型、change-report schema、黄金 fixture
|
||||
3. [ ] 契约测试先红后绿(随 Wave 1 内核实现变绿)
|
||||
4. [ ] 前端 types 对齐
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [ ] ADR 已接受且与实施计划冻结表一致
|
||||
- [ ] 黄金 diff 覆盖中文段落/表格/列表/Mermaid/移动块/no-op
|
||||
- [ ] 契约测试可独立运行
|
||||
|
||||
## 相关链接
|
||||
|
||||
- ADR: `../../adr/2026-09-13-document-version-boundary.md`
|
||||
- Design: `../../system-design/document-revision-management.md`
|
||||
- Remediation: `../../remediation/2026-09-13-document-revision-management-implementation-plan.md`
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
实施中。
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
title: "DOCREV Wave 1–6:ledger 实施"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
owner: Cursor
|
||||
branch: feature/document-revision-management
|
||||
worktree: "-"
|
||||
mutex: docgov
|
||||
---
|
||||
|
||||
# DOCREV Wave 1–6:ledger 实施
|
||||
|
||||
## 目标
|
||||
|
||||
在 feature 分支交付快照内核、人工 PATCH、Agent candidate、比较 UI、通知与自由文档兼容。
|
||||
|
||||
## 范围
|
||||
|
||||
- Goose 00028、`internal/docrevision`、HTTP API、前端工具条、bizdev/freedoc/notification 接线
|
||||
|
||||
## 非目标
|
||||
|
||||
- 本任务不占集成槽位合入 `dev`;真实 PI 全链路补录另开集成窗口
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] Wave 0 契约与 ADR
|
||||
2. [x] Wave 1 迁移与内核
|
||||
3. [x] Wave 2 人工编辑 API/UI
|
||||
4. [x] Wave 3 Agent candidate/commit
|
||||
5. [x] Wave 4 比较 UI
|
||||
6. [x] Wave 5 通知
|
||||
7. [x] Wave 6 自由文档兼容
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] `go test -short ./internal/docrevision/...` PASS
|
||||
- [x] 相关包回归 PASS
|
||||
- [ ] 真实 PI + Playwright 双用户(集成槽位)
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Test report: `../../test-reports/2026-09-13-document-revision-management-test-report.md`
|
||||
- ADR: `../../adr/2026-09-13-document-version-boundary.md`
|
||||
@@ -0,0 +1,52 @@
|
||||
---
|
||||
title: "受控文档分类导航契约"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-14
|
||||
owner: Cursor-Auto
|
||||
branch: fix/document-revision-workflow-category-navigation
|
||||
worktree: "-"
|
||||
mutex: document-revision-workflow-category-navigation
|
||||
---
|
||||
|
||||
# 受控文档分类导航契约
|
||||
|
||||
## 目标
|
||||
|
||||
堵住第15轮 UI-13a:UI-11 后停在「我的私密」,未切「流程受控」就展开文档菜单,找不到 `doc_proj*_intake`。只改验收导航,不降真实性。
|
||||
|
||||
## 范围
|
||||
|
||||
- `web/src/lib/workflowCategoryNavigation.ts` 与单测
|
||||
- `web/e2e/document-revision-runtime.spec.ts` 三个 opener
|
||||
- audit / remediation / CURRENT
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不改产品分类状态机;不用 API/内存规避 UI
|
||||
- 不碰证据;不合 dest;不启停容器;不 E2E;不 push
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 从 `dev@48a4dcb` 开分支并登记 mutex
|
||||
2. [x] 导航谓词 + private→workflow / 缺失 fail-closed 测试
|
||||
3. [x] 三个 opener 先真实切分类
|
||||
4. [x] `npm test` + `npm run build` 并原子提交
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 从私密分类可恢复到精确受控文档
|
||||
- [x] 目标缺失 fail-closed
|
||||
- [ ] 现场 UI-13a(未跑)
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: [../../audit/2026-09-13-document-revision-workflow-category-navigation.md](../../audit/2026-09-13-document-revision-workflow-category-navigation.md)
|
||||
- Remediation: [../../remediation/2026-09-13-document-revision-workflow-category-navigation.md](../../remediation/2026-09-13-document-revision-workflow-category-navigation.md)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
- mutex:`document-revision-workflow-category-navigation`(新 mutex)
|
||||
- 基线:`dev@48a4dcb`
|
||||
- 验证:`npx tsx --test src/lib/workflowCategoryNavigation.test.ts` PASS;`cd web && npm test` PASS(309 + 29);`npm run build` PASS
|
||||
- **未跑真实 UI-13a,不得标 done**;**不得 merge / 启停容器 / E2E / push**
|
||||
@@ -0,0 +1,65 @@
|
||||
---
|
||||
title: "Herdr Agent 角色、备援与自动审批治理"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-14
|
||||
owner: Codex
|
||||
branch: feature/herdr-agent-governance
|
||||
worktree: .worktrees/feature-herdr-agent-governance
|
||||
mutex: ops-governance
|
||||
---
|
||||
|
||||
# Herdr Agent 角色、备援与自动审批治理
|
||||
|
||||
> **superseded 2026-09-14**:活文档与 `scripts/herdr-agent-*.sh` 已移除;本文件仅作历史证据。见 [2026-09-14-remove-herdr-agent-settings.md](./2026-09-14-remove-herdr-agent-settings.md)。
|
||||
|
||||
## 目标
|
||||
|
||||
建立可审计的 Herdr Agent 能力分工、额度保护、故障接管和免人工工具审批入口,并明确 Herdr PI 与产品容器 PI Agent Runner 不是同一执行体。
|
||||
|
||||
## 范围
|
||||
|
||||
- 持久化主责、备份顺序、任务泳道和接管条件。
|
||||
- 为已安装的 Claude、Codex、Cursor、Antigravity、PI、Kimi、Cline CLI 提供统一启动入口。
|
||||
- 自动审批仍受仓库、worktree、mutex、集成槽和破坏性操作红线约束。
|
||||
- 提供保守的自动派发:只向同工作目录、空闲的规范命名实例投递;明确失败时降级,超时停止重复投递。
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不重启或接管当前正在执行 DOCREV/CHAT/INTENT 的实例。
|
||||
- 不修改容器内 PI Agent Runner 的模型、凭证、配置或运行状态。
|
||||
- 不操作共享 Docker 或推送远端。
|
||||
- 不将删库、强推、密钥读取/外传等不可逆动作纳入无条件许可。
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 盘点 Herdr 0.9.0、在线实例、集成状态、CLI 版本和审批参数。
|
||||
2. [x] 写入项目级角色与备援 SSOT,并在 AGENTS/PROJECT 建立入口。
|
||||
3. [x] 实现统一自动审批启动脚本和保守派发脚本。
|
||||
4. [x] 完成静态检查、脚本 dry-run 与路由验收。
|
||||
5. [x] 更新任务状态、提交 feature 分支并合入 `dev`。
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 每种当前可调用 CLI 都有明确角色、主备关系和自动审批启动参数。
|
||||
- [x] Codex/Claude 的高成本推理与 Cursor/Flash 模型的实施负载分离。
|
||||
- [x] 明确禁止因 timeout/unknown 状态盲目重复派发。
|
||||
- [x] Herdr PI 与产品容器 PI 在名称、职责和动作上不会混淆。
|
||||
- [x] 启动和派发脚本通过 `bash -n`,dry-run 不启动实例、不执行任务。
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Agent roster: [2026-09-13-herdr-agent-roster.md](./2026-09-13-herdr-agent-roster.md)
|
||||
- Handoff: [handoffs/2026-09-13-herdr-agent-governance.md](./handoffs/2026-09-13-herdr-agent-governance.md)
|
||||
- Test report: 本任务文“证据 / 备注”
|
||||
- 移除设定任务: [./2026-09-14-remove-herdr-agent-settings.md](./2026-09-14-remove-herdr-agent-settings.md)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
- `herdr status`: client/server 0.9.0,protocol 22,兼容。
|
||||
- `herdr integration status`: Claude/Codex/Cursor/Antigravity/PI/Kimi integration current;Cline CLI 3.0.61 可调用。
|
||||
- CLI 版本:Claude 2.1.270、Codex 0.154.0、Cursor 2026.09.10、Antigravity 1.2.2、PI 0.85.1、Kimi 0.41.0、Cline 3.0.61。
|
||||
- `bash -n scripts/herdr-agent-start.sh scripts/herdr-agent-dispatch.sh`: PASS。
|
||||
- 七种启动 profile dry-run:PASS;未启动或重启实例。
|
||||
- 七条 lane `--explain`:PASS。
|
||||
- 非法标准名:exit 2;无在线标准实例:逐级跳过并 exit 69,未误投任务。
|
||||
@@ -0,0 +1,96 @@
|
||||
# Herdr Agent 角色、审批与备援 SSOT
|
||||
|
||||
> **archived / superseded 2026-09-14**:不再作为活协作规范;脚本已删除。历史证据保留本文件。移除任务见 [./2026-09-14-remove-herdr-agent-settings.md](./2026-09-14-remove-herdr-agent-settings.md)。
|
||||
|
||||
**更新**: 2026-09-13(归档标注 2026-09-14)
|
||||
**owner**: `orchestrator_codex`
|
||||
**status**: archived
|
||||
|
||||
本文只管理工程协作终端,不管理产品运行时智能体。通用分支、worktree、mutex、集成槽、密钥和破坏性操作规则仍以仓库根 [AGENTS.md](../../../AGENTS.md) 为准。
|
||||
|
||||
## 1. 身份边界
|
||||
|
||||
| 名称 | 唯一含义 | 禁止混称 |
|
||||
|------|----------|----------|
|
||||
| Herdr PI / `context_pi` | Herdr pane 内运行的 PI CLI,当前目标模型 MiniMax M3,负责工程调研与长上下文分析 | 不代表后端 runner,不作为产品 E2E 证据 |
|
||||
| 产品 PI Agent Runner | Compose/服务端调用的产品执行器;模型与验收要求见 PROJECT | 不参与 Herdr 工程任务路由 |
|
||||
|
||||
文档、提示词和 handoff 中禁止只写“PI”;必须写 `context_pi` 或“产品 PI Agent Runner”。
|
||||
|
||||
## 2. 稳定角色
|
||||
|
||||
| 逻辑名 | 客户端 / 目标模型 | 主责 | 工作量策略 | 首选备援 |
|
||||
|--------|-------------------|------|------------|----------|
|
||||
| `orchestrator_codex` | Codex / GPT Sol 5.6 | 需求澄清、系统方案、任务拆解、调度、跨模块风险、代码终审、发布判断 | 保留推理容量,原则上不承担大批量机械实现 | `context_kimi`;关键争议才用 `reserve_claude` |
|
||||
| `implementer_cursor` | Cursor / Auto | 前后端实施、测试补齐、重构、浏览器验证、按 checklist 收口 | 主力实施席,承担最大常规工作量 | `implementer_cline` → `verifier_antigravity` → `orchestrator_codex` |
|
||||
| `verifier_antigravity` | Antigravity / Gemini 3.8 Flash | 快速只读排查、测试设计、文档核对、日志归纳、低风险小修 | 低成本高频;不得单独作安全或发布终审 | `implementer_cline` → `implementer_cursor` |
|
||||
| `context_pi` | PI CLI / MiniMax M3 1M | 全仓长上下文扫描、文档/代码交叉研究、候选清单、handoff 压缩 | 长材料首选;结论由 Codex 或 reviewer 复核 | `context_kimi` → `orchestrator_codex` |
|
||||
| `context_kimi` | Kimi Code / Kimi K3 1M | PI 备援、长文档审查、跨文件一致性检查、方案反证 | 额度有限,优先作长上下文备援而非日常实现 | `context_pi` → `orchestrator_codex` |
|
||||
| `implementer_cline` | Cline / GLM 5.3 Flash | 机械实现、测试修复、格式化、重复性迁移、Cursor 备援 | CLI 已可调用;进入主路由前需完成一次隔离 worktree 写验收 | `implementer_cursor` → `verifier_antigravity` |
|
||||
| `reserve_claude` | Claude Code / Sonnet 5 | P0/P1 架构争议、安全关键复核、Codex 失败后的第二强意见 | 额度极少,禁止日常调研、批量实现和首轮测试 | `orchestrator_codex` → `context_kimi` |
|
||||
| `reserve_devin` | Devin / 尚未接入 | 预留长任务自治席 | `standby`,不得派发 | 无 |
|
||||
|
||||
模型名称来自当前工作区约定;启动脚本不猜测各 CLI 的模型别名。每次新会话由 orchestrator 在首条状态回报中确认实际模型,不一致则停止高风险任务并记录 handoff。
|
||||
|
||||
## 3. 任务泳道与自动备援顺序
|
||||
|
||||
| lane | 适用任务 | 路由顺序 |
|
||||
|------|----------|----------|
|
||||
| `governance` | 方案、拆解、跨模块决策、普通 review | Codex → Kimi → Cursor → Claude |
|
||||
| `critical-review` | 鉴权、安全、迁移、发布 blocker 终审 | Codex → Claude → Kimi |
|
||||
| `implementation` | Go/React/SQL 实施与测试 | Cursor → Cline → Antigravity → Codex |
|
||||
| `ui` | React、交互、Playwright | Cursor → Antigravity → Cline |
|
||||
| `test` | 单测、集成测试、失败定位 | Cursor → Cline → Antigravity |
|
||||
| `fast-check` | 日志、静态核对、文档一致性、小修 | Antigravity → Cline → Cursor |
|
||||
| `long-context` | 全仓/全量文档审读、证据汇总 | PI → Kimi → Codex |
|
||||
|
||||
Claude 只在 `critical-review` 中作为前排备援;其他 lane 放在最后或不进入路由,以保护额度。Codex 的实现兜底只用于阻塞交付的关键路径。
|
||||
|
||||
## 4. 自动派发和接管协议
|
||||
|
||||
1. Orchestrator 先创建 short-term、认领 mutex、建立独立 worktree;之后才启动或选择 agent。
|
||||
2. 实例必须使用上表逻辑名,且 `cwd` 必须与任务 worktree 完全相同。派发器不会占用名称不规范或其他目录的实例。
|
||||
3. 只向 `idle` / `done` 实例投递。同一 mutex 同时只允许一个执行者写入。
|
||||
4. 以下情况可自动尝试下一个备援:实例不存在、启动前已 blocked、认证失败、明确额度耗尽、客户端在写入前失败。
|
||||
5. Agent 只有在尚未写文件、未运行有副作用命令时,才可返回派发器给出的本次唯一 `HERDR_RETRY:<dispatch-id>:<reason>` 行触发降级。
|
||||
6. `timeout`、`agent_prompt_stalled`、`unknown` 或无终态标记均不能证明任务未执行;派发器必须停止,不得盲目重投。先读取 pane,必要时写 handoff。
|
||||
7. 接管前确认原实例不再 `working`;有部分改动时由原实例或 orchestrator 写 handoff,备援串行续作,不得并发覆盖。
|
||||
8. Review 可由不同 worktree 的多个只读实例并行;写任务仍受 mutex 单写者约束。
|
||||
|
||||
## 5. 自动审批不是无限授权
|
||||
|
||||
统一入口为 [`scripts/herdr-agent-start.sh`](../../scripts/herdr-agent-start.sh)。当前安装版本验证过的参数如下:
|
||||
|
||||
| profile | 自动审批参数 | 保留的边界 |
|
||||
|---------|--------------|------------|
|
||||
| Claude | `--dangerously-skip-permissions` | 仍受本规范和任务提示约束 |
|
||||
| Codex | `--ask-for-approval never --sandbox workspace-write` | 保留 workspace 沙箱;失败回传模型,不询问人工 |
|
||||
| Cursor | `--force --sandbox enabled --approve-mcps --trust` | 保留 Cursor 沙箱和显式 deny |
|
||||
| Antigravity | `--dangerously-skip-permissions --sandbox` | 保留其终端沙箱 |
|
||||
| PI | `--approve` | 信任项目本地文件;该 CLI 没有独立的逐工具审批开关 |
|
||||
| Kimi | `--auto` | Never Ask 模式 |
|
||||
| Cline | `--tui --auto-approve true` | 所有工具自动批准 |
|
||||
|
||||
即使客户端不弹确认框,Agent 也不得自行执行:删库/清空数据、强推、删除主干或 worktree、停止 Herdr server、覆盖其他 Agent 未合并改动、泄露密钥、未获用户授权的外部写入。需要新权限时写 handoff/blocker,不把确认框转交给用户逐条点击。
|
||||
|
||||
## 6. 操作入口
|
||||
|
||||
在任务 worktree 的 Herdr pane 中启动标准实例:
|
||||
|
||||
```bash
|
||||
./scripts/herdr-agent-start.sh codex orchestrator_codex <pane-id>
|
||||
./scripts/herdr-agent-start.sh cursor implementer_cursor <pane-id>
|
||||
```
|
||||
|
||||
预览某泳道路由,或自动投递:
|
||||
|
||||
```bash
|
||||
./scripts/herdr-agent-dispatch.sh --explain implementation
|
||||
./scripts/herdr-agent-dispatch.sh implementation "读取任务文并完成已认领范围,验证后写 handoff。"
|
||||
```
|
||||
|
||||
派发器只处理规范命名且已在线的实例,不擅自创建 pane、不重启 agent、不抢集成槽。缺少实例时由 orchestrator 用启动脚本补齐。
|
||||
|
||||
## 7. 当前可用性基线
|
||||
|
||||
2026-09-13 现场基线:Herdr client/server 0.9.0、协议 22;Claude/Codex/Cursor/Antigravity/PI/Kimi 集成已安装且 current;Cline CLI 3.0.61 可调用,但尚无在线标准命名实例;Devin 尚未接入。在线状态是瞬时信息,派发前必须重新运行 `herdr agent list`。
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
title: "受控文档正文修复真实 UI 实战验收"
|
||||
status: done
|
||||
owner: verifier_antigravity
|
||||
branch: fix/controlled-content-ui-acceptance
|
||||
mutex: document-content-ui-acceptance
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-14
|
||||
---
|
||||
|
||||
# 目标
|
||||
|
||||
仅通过真实浏览器页面操作,验证项目 143 历史文档恢复,并以真实产品 PI Agent Runner / 智能体小队完成新项目文档全链路。API、数据库和 stub 不能替代 UI 验收结果。
|
||||
|
||||
# 范围
|
||||
|
||||
- 项目 143:登录、打开正文、30 秒空闲、双击编辑保存、三种变更视图、刷新与重新登录持久化。(clean-run3 已全部 PASS)
|
||||
- 新项目:从 UI 创建,真实对话触发工作流/小队生成文档,再次对话触发修改;页面查看助手回复、文档正文、版本账本、影响、风险、开放问题。(full-chain-final UI-00..UI-16 全部 18 项 PASS)
|
||||
- 冲突与权限:双页面并发编辑、审核人/无关用户访问边界均通过;宿主容器重启后 post-restart 复验通过。
|
||||
- Ubuntu Server 浏览器:统一使用 Playwright 官方 `mcr.microsoft.com/playwright:v1.63.0-noble` 容器。
|
||||
|
||||
# 红线
|
||||
|
||||
- 不用 API 直建用户、项目、会话、文档或测试数据。
|
||||
- 不注入/伪造 assistant 消息、文档、账本、change report 或通过结果。
|
||||
- 所有通过项必须有页面可见证据;失败如实记录为 FAIL。
|
||||
- 测试账号凭证只读本机既有 secrets/phase 文件,不输出、不提交。
|
||||
|
||||
# 阶段判据与进展
|
||||
|
||||
- [x] 项目 143 页面正文可见且无 content/revision 404(UI-143-01..06 全 PASS,产物在 `clean-run3/`)。
|
||||
- [x] 人工编辑、视图切换、刷新/重登持久化通过(项目 143 回归)。
|
||||
- [x] 新项目真实 PI/小队链路及文档影响风险报告页面可见(UI-00..05b 通过,首轮 toolbar V2/r0,UI-05 pending 保持 V2,UI-05a 确认后晋升 V3,UI-05b 拒绝后保持 V3)。
|
||||
- [x] UI-06 硬刷新正文保留通过(合入 08bf615 修复后 1.1 秒内秒级通过)。
|
||||
- [x] 并发、权限、重启前凭据生成有真实 UI 判定(UI-12/13a/13b/15/16 全 PASS)。
|
||||
- [x] 容器重启后恢复核验通过(UI-15 post-restart 2.8 秒秒级通过,V3/r2 与标记完好呈现,目标 404=0)。
|
||||
- [x] 测试报告落盘至 `.doc/test-reports/2026-09-14-controlled-content-ui-acceptance.md`。
|
||||
@@ -0,0 +1,42 @@
|
||||
---
|
||||
title: "运行时 UI 证据计数与 race 秒数纠错"
|
||||
status: done
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-14
|
||||
owner: Cursor-Auto
|
||||
branch: fix/document-revision-evidence-count
|
||||
worktree: "-"
|
||||
mutex: document-revision-evidence-count
|
||||
---
|
||||
|
||||
# 运行时 UI 证据计数与 race 秒数纠错
|
||||
|
||||
## 目标
|
||||
|
||||
把顶层截图写成 21(20 main/pre + 1 post),并把全包 race 写成 `FAIL 109.279s`,不与 21 条 results 混淆。
|
||||
|
||||
## 范围
|
||||
|
||||
- 最终报告、UI checklist、CURRENT
|
||||
- 本短任务登记后即关闭
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不改业务代码、assets、容器,不 push
|
||||
- 不改 UI PASS 判定,不提交 secrets
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 从 `dev@5d79da6` 开 `fix/document-revision-evidence-count` 并登记
|
||||
2. [x] 截图 21 = 20 main/pre + 1 post;race `FAIL 109.279s`
|
||||
3. [x] `git diff --check`;只提交文档
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 报告/清单不再把 20 张截图与 21 条 JSON 混写
|
||||
- [x] 全包 race 不再写成 `ok ... 110.723s`
|
||||
- [x] assets 未 stage
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Test report: [../../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md](../../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md)
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
title: "文档账本运行时 UI 最终报告收口"
|
||||
status: done
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-14
|
||||
owner: Cursor-Auto
|
||||
branch: feature/document-revision-runtime-ui-final-report
|
||||
worktree: "-"
|
||||
mutex: document-revision-runtime-ui
|
||||
---
|
||||
|
||||
# 文档账本运行时 UI 最终报告收口
|
||||
|
||||
## 目标
|
||||
|
||||
在 `dev@b258ab8` 上只写文档,把 Round20 真实 UI 验收收口为 test-report,并释放运行时集成槽。
|
||||
|
||||
## 范围
|
||||
|
||||
- `.doc/test-reports/2026-09-14-document-revision-runtime-ui-test-report.md`
|
||||
- management report、UI checklist、runtime / PG-id 文档、FEATURE-MATRIX、gap-matrix、CURRENT
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不改业务代码、不跑容器、不 push、不提交 assets
|
||||
- 不引用 `phase-secrets.local.json` 内容
|
||||
- 不把全仓标 `production_ready=yes`
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 从 `dev@b258ab8` 开 `feature/document-revision-runtime-ui-final-report`
|
||||
2. [x] 按 results JSON 写 Input/Actual/Verdict/Duration
|
||||
3. [x] 同步任务文档并释放集成槽
|
||||
4. [x] 原子 docs commit
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 运行时范围 PASS/done
|
||||
- [x] `production_ready` 仍为 no;`CHAT-INTENT` 保留
|
||||
- [x] 历史失败资产未改删
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Test report: [../../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md](../../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md)
|
||||
- Checklist: [../checklists/2026-09-13-document-revision-runtime-ui-acceptance.md](checklists/2026-09-13-document-revision-runtime-ui-acceptance.md)
|
||||
@@ -0,0 +1,47 @@
|
||||
---
|
||||
title: "文档账本运行时会话关闭归档"
|
||||
status: done
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-14
|
||||
owner: Cursor-Auto
|
||||
branch: feature/document-revision-session-close
|
||||
worktree: "-"
|
||||
mutex: document-revision-session-close
|
||||
---
|
||||
|
||||
# 文档账本运行时会话关闭归档
|
||||
|
||||
## 目标
|
||||
|
||||
按 AGENTS 会话关闭清单:把已 done 的 document-revision short-term / checklist / handoff 迁入 archive,并修好相对链接。
|
||||
|
||||
## 范围
|
||||
|
||||
- `.doc/ops/short-term/*document-revision*`
|
||||
- 4 个专项 checklist + runtime-ui-acceptance
|
||||
- 4 个 document-revision handoff
|
||||
- `.doc` 内因移动失效的相对链接
|
||||
- 本任务完成后一并归档
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不改业务代码、assets、容器,不 push
|
||||
- 不改 `production_ready=no`、fallback / race 结论
|
||||
- 不改非 document-revision 任务
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 从 `dev@4bf8b6d` 开 `feature/document-revision-session-close` 并登记
|
||||
2. [x] short-term / checklist / handoff 标 done 后 `git mv` 入 archive
|
||||
3. [x] 扫描并重写失效相对链接;`git diff --check`
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] CURRENT 焦点仅非 DOCREV;槽位 idle
|
||||
- [x] 本次移动文件的相对 Markdown 链接可解析
|
||||
- [x] assets 未 stage
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Test report: [../../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md](../../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md)
|
||||
- CURRENT: [CURRENT](../../ops/CURRENT.md)
|
||||
@@ -0,0 +1,48 @@
|
||||
---
|
||||
title: "项目 143 受控文档正文 404 现场诊断"
|
||||
status: done
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-14
|
||||
owner: Codex
|
||||
branch: fix/project143-controlled-content-404-diagnosis
|
||||
worktree: "-"
|
||||
mutex: docgov-content-diagnosis
|
||||
---
|
||||
|
||||
# 项目 143 受控文档正文 404 现场诊断
|
||||
|
||||
## 目标
|
||||
|
||||
定位已登录用户打开项目 143 时 `doc_proj143_intake` 正文接口返回 404 的当前根因,并形成可复核的整改边界。
|
||||
|
||||
## 范围
|
||||
|
||||
- 对照当前 dev 源码、数据库、工作区文件与既有真实 UI 证据。
|
||||
- 分析服务端 404 条件、前端 hydration 与重复请求条件。
|
||||
- 形成审计记录和整改建议;本轮不修改业务代码。
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不恢复或覆盖用户文档数据。
|
||||
- 不以 API 探针或伪造数据替代后续真实浏览器验收。
|
||||
- 不继续纯软件项目自举方案实施。
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 核对项目 143 的项目、文档记录、账本与工作区事实源。
|
||||
2. [x] 核对正文 handler 的 404 分支和前端 hydration 重试条件。
|
||||
3. [x] 记录根因、影响范围、整改顺序和验收要求。
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 404 的直接原因与数据/代码证据相互印证。
|
||||
- [x] 明确区分历史项目数据缺口、当前能力回归和前端错误放大。
|
||||
- [x] 不宣称未执行的浏览器或真实 PI 结果。
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: [../../audit/2026-09-14-project143-controlled-content-404.md](../../audit/2026-09-14-project143-controlled-content-404.md)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
结论:文件存在;raw/canonical 哈希因 5 处 Markdown 双空格硬换行产生 10-byte 差异。该空格具有渲染语义,须保全原文修复。详见 Audit 与 Remediation。
|
||||
@@ -0,0 +1,51 @@
|
||||
---
|
||||
title: "移除 Herdr 工作与角色设定"
|
||||
status: done
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-14
|
||||
owner: Cursor-Auto
|
||||
branch: feature/remove-herdr-agent-settings
|
||||
worktree: "-"
|
||||
mutex: agent-collab-docs
|
||||
---
|
||||
|
||||
# 移除 Herdr 工作与角色设定
|
||||
|
||||
## 目标
|
||||
|
||||
从仓库活文档与脚本中移除 Herdr Agent 角色、审批、备援与派发设定,协作规范回到通用 AGENTS / worktree / mutex 流程。
|
||||
|
||||
## 范围
|
||||
|
||||
- 删除 `scripts/herdr-agent-start.sh`、`scripts/herdr-agent-dispatch.sh`
|
||||
- 归档 roster / 相关 handoff
|
||||
- 从 `AGENTS.md`、`PROJECT.md`、`.doc/README.md` 去掉 Herdr 专章与索引
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不改写历史 audit / remediation / 已归档任务中的执行者名(如 `implementer_cursor`)作为证据
|
||||
- 不卸载本机 Herdr 客户端
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 从 `dev` 开 `feature/remove-herdr-agent-settings` 并认领
|
||||
2. [x] 移除活文档与脚本中的 Herdr 设定
|
||||
3. [x] 归档 roster / handoff 并更新 CURRENT
|
||||
4. [x] 提交
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 活文档与 `scripts/` 无 Herdr 角色/派发入口
|
||||
- [x] 历史证据在 `archive/` 可追溯
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Roster(已归档): [./2026-09-13-herdr-agent-roster.md](./2026-09-13-herdr-agent-roster.md)
|
||||
- 既有治理归档: [./2026-09-13-herdr-agent-governance.md](./2026-09-13-herdr-agent-governance.md)
|
||||
- Handoff(已归档): [./handoffs/2026-09-13-herdr-agent-governance.md](./handoffs/2026-09-13-herdr-agent-governance.md)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
- 删除:`scripts/herdr-agent-start.sh`、`scripts/herdr-agent-dispatch.sh`
|
||||
- 文档:去掉 `AGENTS.md` §6.6、`PROJECT.md` §10 Herdr 章与索引行、`.doc/README.md` roster 入口
|
||||
- 归档:roster + handoff → `.doc/archive/ops/`
|
||||
@@ -0,0 +1,51 @@
|
||||
---
|
||||
title: "纯软件项目自举工作流方案"
|
||||
status: done
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-14
|
||||
owner: Codex
|
||||
branch: feature/software-project-bootstrap-plan
|
||||
worktree: "-"
|
||||
mutex: workflow-design
|
||||
---
|
||||
|
||||
# 纯软件项目自举工作流方案
|
||||
|
||||
## 目标
|
||||
|
||||
基于当前 Agent-System 的真实能力,设计一套可创建、可配置、可冻结、可执行、可验收的纯软件项目自举工作流,并明确复用智能体小队、文档模板、权限与阶段门禁的实施路线。
|
||||
|
||||
## 范围
|
||||
|
||||
- 当前项目创建、工作流、阶段、文档、智能体小队和 UI 能力盘点
|
||||
- 纯软件项目的创建选项、阶段模型、交付物、门禁、角色与小队设计
|
||||
- 从最小可用版本到完整自举闭环的实施拆分、数据迁移、API/UI 与验收计划
|
||||
|
||||
## 非目标
|
||||
|
||||
- 本轮不修改 Go、React、数据库迁移、模板或智能体配置
|
||||
- 不把医疗器械合规要求默认带入纯软件项目
|
||||
- 不宣称尚未实现的方案已经可用
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 盘点当前实现与可复用能力
|
||||
2. [x] 完成详细系统设计和创建向导设计
|
||||
3. [x] 给出分阶段实施与真实验收计划
|
||||
4. [x] 更新 FEATURE-MATRIX、CURRENT 并完成文档校验
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 方案覆盖工作流、文档、智能体小队、角色权限、项目创建选项、状态机、API/UI、迁移和验收
|
||||
- [x] 清楚区分已实现、可复用、需新增和暂缓项
|
||||
- [x] 自举机制有边界、有人工确认点且不会让智能体自行修改治理规则
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Research: [../../ops/research/2026-09-14-software-project-bootstrap-current-state.md](../../ops/research/2026-09-14-software-project-bootstrap-current-state.md)
|
||||
- Design: [../../system-design/2026-09-14-software-project-bootstrap-workflow.md](../../system-design/2026-09-14-software-project-bootstrap-workflow.md)
|
||||
- Checklist: [../../ops/checklists/2026-09-14-software-project-bootstrap-acceptance.md](../../ops/checklists/2026-09-14-software-project-bootstrap-acceptance.md)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
本轮为设计任务;所有当前态结论已回链源码、迁移或现有测试报告。主方案 599 行,验收计划 207 行;`git diff --check` 通过,相关文档 84 条相对链接校验无坏链。未运行产品功能测试,验收清单全部保持 `NOT RUN`。
|
||||
@@ -0,0 +1,40 @@
|
||||
---
|
||||
title: "Vite 允许 FRP Host(frp-mix.com)"
|
||||
status: done
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-14
|
||||
owner: Cursor-Auto
|
||||
branch: fix/vite-frp-allowed-hosts
|
||||
worktree: "-"
|
||||
mutex: web-devserver
|
||||
---
|
||||
|
||||
# Vite 允许 FRP Host(frp-mix.com)
|
||||
|
||||
## 目标
|
||||
|
||||
通过 FRP 映射访问 `:3100` 时,Vite 不再拦截 `Host: frp-mix.com`。
|
||||
|
||||
## 范围
|
||||
|
||||
- `web/vite.config.ts`:`server.allowedHosts` 增加 `.frp-mix.com`
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不改生产 nginx / 反向代理配置
|
||||
- 不放开全部任意 Host(保持显式白名单)
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 在 `fix/vite-frp-allowed-hosts` 上改 `allowedHosts`
|
||||
2. [x] 重启本地 Vite `:3100`
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 通过 `frp-mix.com`(FRP→3100)可打开开发页,不再出现 `Blocked request. This host is not allowed`
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Checklist: —
|
||||
- Handoff: —
|
||||
- Test report: —
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
title: "PG ID 重映射收紧"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-14
|
||||
related_task: "2026-09-13-document-revision-pg-id-remap.md"
|
||||
---
|
||||
|
||||
# PG ID 重映射收紧
|
||||
|
||||
## Wave 0
|
||||
|
||||
- [x] `adopt*ID` 推进 counter,仅删同一对象
|
||||
- [x] 临时 ID 跳过已占用键(snapshot/version/event/report/candidate)
|
||||
- [x] openTemplate / human / candidate / commit / noop event 全走 adopt
|
||||
- [x] 纯函数 + 高序列首次生成 PG 回归
|
||||
- [x] `gofmt` / `go vet` / `go test -short ./...`
|
||||
- [x] 真实 UI-03:Round20 PASS(6159 / `doc_proj6159_intake` / V2/r0)
|
||||
|
||||
## 完成定义
|
||||
|
||||
- [x] 上述实现项有测试证据
|
||||
- [x] 现场 UI-03 Round20 已通过;Round19 失败归档不删
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
---
|
||||
title: "post-restart 最终持久正文 snippet"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-14
|
||||
related_task: "2026-09-13-document-revision-post-restart-final-snippet.md"
|
||||
---
|
||||
|
||||
# post-restart 最终持久正文 snippet
|
||||
|
||||
## 本轮
|
||||
|
||||
- [x] `nextDurableBodySnippet`:后续成功修订覆盖旧 snippet
|
||||
- [x] 冲突失败稿不成为期望正文
|
||||
- [x] UI-13b 冲突断言完成后回写 `markerA1`;UI-15-pre 写出最终值
|
||||
- [x] 不放宽/删除 post-restart body 断言
|
||||
- [x] `npm test` / `npm run build`
|
||||
- [x] 真实 UI-15 post-restart:Round20 PASS
|
||||
|
||||
## 完成定义
|
||||
|
||||
- [x] 上述实现项有单测或脚本证据
|
||||
- [x] 现场 post-restart Round20 已通过;stale-snippet 失败归档不删
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
title: "post-restart 项目名 selector 收紧"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-14
|
||||
related_task: "2026-09-13-document-revision-post-restart-selector.md"
|
||||
---
|
||||
|
||||
# post-restart 项目名 selector 收紧
|
||||
|
||||
## 本轮
|
||||
|
||||
- [x] 点击来自侧栏可见项目入口(complementary exact title),不用 `.first()` 弱化
|
||||
- [x] 恢复断言为 banner 内 exact 项目名
|
||||
- [x] `UI_PHASE` 分离 `playwright-output-main|post-restart` 与 `playwright-report-main|post-restart`
|
||||
- [x] 结果 JSON 分文件:`ui-acceptance-results.json`(main)与 `ui-acceptance-results-post-restart.json`;phase-state/secrets 仍共享
|
||||
- [x] helper 契约测试 + `npm test` / `npm run build`
|
||||
- [ ] 真实 UI-15 post-restart(本轮不做)
|
||||
|
||||
## 完成定义
|
||||
|
||||
- [x] 上述实现项有单测或脚本证据
|
||||
- [ ] 现场 post-restart 仍开放,不得标 done
|
||||
@@ -0,0 +1,25 @@
|
||||
---
|
||||
title: "项目 reviewer 职责同步收紧"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-14
|
||||
related_task: "2026-09-13-document-revision-reviewer-duty-sync.md"
|
||||
---
|
||||
|
||||
# 项目 reviewer 职责同步收紧
|
||||
|
||||
## 最后一轮严格修复
|
||||
|
||||
- [x] 移出成员后端 reconcile + `ERR_DUTY_SYNC`;前端 `afterProjectMemberPersisted` 刷新文档
|
||||
- [x] Heal 空 assigned 仅清退出/非成员;在任成员保留;author 不清空
|
||||
- [x] 显式 revoke:reviewer→viewer、职责转移、退出、幂等;author 不进撤销集
|
||||
- [x] `CreateOrGetDocument` 失败任务不成功;fault test
|
||||
- [x] 成员 upsert/退出:advisory lock、读旧/冲突 holder、成员更新、`document_records` 精确清槽同一事务;提交后 heal;失败 `ERR_DUTY_SYNC`
|
||||
- [x] `HealProjectDocuments` 与成员写同锁键/顺序;解析与文档更新同事务;转移后旧 holder 不复活;第二次 heal 幂等
|
||||
- [x] `gofmt` / `go vet` / `go test -short` / 相关 `-race` / `npm test` / `build` / 隔离 PG
|
||||
- [ ] 真实 UI-13a(本轮不做)
|
||||
|
||||
## 完成定义
|
||||
|
||||
- [x] 上述实现项有测试或隔离 PG 证据
|
||||
- [ ] 现场 UI-13a 仍开放,不得标 done
|
||||
@@ -0,0 +1,149 @@
|
||||
---
|
||||
title: "文档版本账本运行时 — Ubuntu Server 无头浏览器真实 UI 验收计划"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-14
|
||||
---
|
||||
|
||||
# 文档版本账本运行时 — Ubuntu Server 无头浏览器真实 UI 验收计划
|
||||
|
||||
> **与工程门禁分离**:本文件仅描述**用户限定的最终实战验收**(浏览器页面操作)。
|
||||
> **严禁**用 API 直灌、DB fixture、`page.route` mock、stub 模型、或伪造 SSE 冒充小队完成。
|
||||
> 工程单测 / `go vet` / `npm test` / `npm run build` 属于「工程门禁」,见 short-term 证据区,**不能替代**本计划。
|
||||
|
||||
## 0. 环境前置(必须占 CURRENT 集成槽位后执行)
|
||||
|
||||
| 项 | 要求 |
|
||||
|----|------|
|
||||
| OS | Ubuntu Server 22.04+(无图形桌面亦可) |
|
||||
| 服务 | `./scripts/env-service.sh dev rebuild` → `curl -sf http://127.0.0.1:8080/health`;schema ≥ 28 |
|
||||
| Agent | 真实 `pi-agent` + 运行中的 `MiniMax-M2.7-highspeed` 容器(禁止 stub) |
|
||||
| 账号 | ≥2 名项目成员(编制人 A、协作者 B);禁止共用 token 串号;**管理员凭据仅来自 `ADMIN_USERNAME`/`ADMIN_PASSWORD` 环境变量(禁止 spec 硬编码)** |
|
||||
| 认证契约 | 真实 login/me 返回 snake_case `role_id` 等;前端须映射为 `roleId`,否则管理员入口隐藏(UI-00 已踩坑,见 audit) |
|
||||
| 用户目录 | 管理员开通 A/B 后,同浏览器立项成员候选须含新账号(`onRefreshUsers` 不得死 prop);跨设备缺口见 [../../audit/2026-09-13-admin-user-directory-sync-ui01.md](../../../audit/2026-09-13-admin-user-directory-sync-ui01.md) |
|
||||
| 证据根 | `.doc/test-reports/assets/2026-09-13-document-revision-runtime-ui/` |
|
||||
| 报告 | `.doc/test-reports/YYYY-MM-DD-document-revision-runtime-ui-test-report.md` |
|
||||
|
||||
### 0.1 Ubuntu Server 无头 Playwright(Round20 实际路径)
|
||||
|
||||
**本轮采用官方容器,无需给 Ubuntu host 安装浏览器:**
|
||||
|
||||
```bash
|
||||
# 测试前部署合入基线(Round20:b258ab8)
|
||||
./scripts/env-service.sh dev rebuild
|
||||
curl -sf http://127.0.0.1:8080/health
|
||||
|
||||
# 官方镜像跑页面验收(host 网络;BASE_URL 指向工作台 :3100)
|
||||
docker run --rm --network host --ipc host \
|
||||
-e RUN_UI_ACCEPTANCE=1 \
|
||||
-e BASE_URL=http://127.0.0.1:3100 \
|
||||
-v "$PWD":/work -w /work/web \
|
||||
mcr.microsoft.com/playwright:v1.63.0-noble \
|
||||
npx playwright test e2e/document-revision-runtime.spec.ts --project=chromium
|
||||
```
|
||||
|
||||
**备选(本轮未走)**:宿主 `cd web && npx playwright install --with-deps chromium`。仅当不能跑官方容器时使用。
|
||||
|
||||
### 0.2 两阶段(验收轮)
|
||||
|
||||
1. `RUN_UI_ACCEPTANCE=1 UI_PHASE=main BASE_URL=http://127.0.0.1:3100` 跑主场景(写 `phase-state.json`,密码仅落本地 `phase-secrets.local.json`,不得提交)。产物:`playwright-output-main` / `playwright-report-main` / `ui-acceptance-results.json`
|
||||
2. 宿主仅 `restart shuimu-agent-app-dev` 一次(PG/PI 未动;不是再次 rebuild)
|
||||
3. `RUN_UI_ACCEPTANCE=1 UI_PHASE=post-restart` 仅页面登录校验 UI-15。产物:`playwright-output-post-restart` / `playwright-report-post-restart` / `ui-acceptance-results-post-restart.json`(不得覆盖 main 总账或 trace)
|
||||
4. 文档收口阶段不再动容器。
|
||||
|
||||
证据:`.doc/test-reports/assets/2026-09-13-document-revision-runtime-ui/`(trace/video/screenshot);结果 JSON 不得含凭证与 URL query。
|
||||
|
||||
---
|
||||
|
||||
## 1. 数据来源铁律(FAIL 即整轮作废)
|
||||
|
||||
| 允许 | 禁止(一票否决) |
|
||||
|------|------------------|
|
||||
| 页面登录后创建项目 | `INSERT`/`psql` 灌 document_records / snapshots |
|
||||
| 页面上传附件 | 测试进程直连 Postgres 插 fixture |
|
||||
| 对话输入框真实提问触发小队 | `page.route` 劫持 `/api/v1/chat` 或 SSE 返回假成功 |
|
||||
| 等待真实 runner 完成 | `AgentBackend=stub` 或 mock MiniMax |
|
||||
| 打开生成的文档 Tab 观察 UI | API-only 调用 PATCH/OpenTemplate 冒充「用户操作」 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 用例矩阵(全部必须页面可见)
|
||||
|
||||
| ID | 步骤(仅 UI) | 期望页面现象 | 证据 | 判定 |
|
||||
|----|---------------|--------------|------|------|
|
||||
| UI-01 | 管理员开通 B 后,tech-lead A **页面创建**项目并勾选成员 | 立项成员候选含 B;项目工作台三栏可见 | 截图 `01-project.png` | PASS |
|
||||
| UI-02 | 对话输入框发起真实任务(触发真实小队编排) | 助手流式回复;任务进度/文档 busy 可见;网络可见真实 agent 请求 | 截图 + trace | PASS |
|
||||
| UI-03 | 等待小队**首轮**完成,打开生成的受控文档 Tab | 右侧出现文档;版本工具条 `Vn`/`r*`(非「账本未就绪」) | 截图 `03-first-doc.png` | PASS |
|
||||
| UI-04 | 打开变更报告:工具条「变更报告」/「待确认报告」或版本历史「报告」 | **首轮**可见:摘要、**风险条目**、项目影响内容、各文档影响原因/建议、开放问题;加载失败显式错误非永久加载中;`fallback` 不得宣称为完整 PI | 截图 `04-first-report.png` | PASS |
|
||||
| UI-05 | 同项目再触发**二轮**更新生成(真实对话) | 低/中风险:新版本+报告;**高风险**:工具条显示「待确认报告」与 pending 徽章,**版本历史尚无新 V**,打开报告可见完整字段 | 截图 `05-second-report.png` | PASS |
|
||||
| UI-05a | 编制人对高风险候选点「确认提交」 | decision API `confirmed:true`;版本前进;pending 消失;历史出现带 `change_report_id` 的新版本 | 截图+网络 | PASS |
|
||||
| UI-05b | 编制人对高风险候选点「拒绝」 | 候选拒绝;pending 消失;版本号不前进;无权用户无确认/拒绝按钮或 decision 403 | 截图+网络 | PASS |
|
||||
| UI-06 | 双击块编辑 → 保存 → **硬刷新** | 无冲突时工具条 `r` **立即**递增(`revisionRefreshKey`);硬刷新后正文仍为保存内容 | 截图前后对比 | PASS |
|
||||
| UI-07 | 切换「纯净阅读」 | 块无琥珀/蓝色装饰底 | 截图 | PASS |
|
||||
| UI-08 | 切换「人工修改」 | 相对当前 Version 的人工修订块琥珀底+下划线暗示 | 截图 | PASS |
|
||||
| UI-09 | 切换「全部变更」 | 智能体+人工差异;仅人工时允许与 UI-08 相同 | 三模式并排或连续截图 | PASS |
|
||||
| UI-10 | 「版本历史」+「比较」 | 抽屉列出版本;比较视图展示 hunk | 截图 | PASS |
|
||||
| UI-11 | **多文档**:同项目再生成/打开第二份受控文档 + **页面上传**附件 Tab | 多 Tab 可切换;各文档 revision-state 独立;附件可预览 | 截图 | PASS |
|
||||
| UI-12 | 用户 C 打开无权限项目(非成员) | 项目不可见,**不泄漏正文** | 截图 + 网络 403/404 | PASS |
|
||||
| UI-13 | 拆为 13a reviewer 只读 + 13b A/A 同 r 冲突 | B 无正文编辑;A2 `409 DOCUMENT_HEAD_CONFLICT` 保留草稿 | 双 context 截图 | PASS |
|
||||
| UI-14 | A 退出 → **重登录** → 打开同一文档 | revision-state 200;正文与 `r` 与退出前一致 | 截图 | PASS |
|
||||
| UI-15 | (集成槽内)**重启 app 容器**后再打开同一文档 | 账本与正文仍可恢复;非「未就绪」除非确无事实源 | 截图 + `docker restart` 日志摘录 | PASS |
|
||||
| UI-16 | 页面上传经 freeform 注册后打开;禁止 `doc-upload` 假账本 | 已注册 `doc-free-*` 工具条 V 可见;无 orphan revision-state | 截图 | PASS |
|
||||
|
||||
---
|
||||
|
||||
## 3. 证据要求(归档规范)
|
||||
|
||||
| 类型 | 路径约定 | 最低要求 |
|
||||
|------|----------|----------|
|
||||
| 截图 | `assets/.../screenshots/UI-XX-*.png` | 每用例 ≥1;UI-07/08/09 必须能看出三模式差异 |
|
||||
| Trace | `assets/.../traces/UI-XX.zip`(Playwright trace) | 失败用例必留;PASS 建议全留 |
|
||||
| 录像 | `assets/.../videos/*.webm` | 首轮生成 + 二轮报告 + 双人冲突 必留 |
|
||||
| 网络摘录 | 报告正文粘贴关键响应 | `revision-state` 200;`change-reports` 含 summary/risk/open_questions;禁止贴 token |
|
||||
|
||||
报告正文每个用例必须含:**Input(页面操作)** / **Actual(可见文本+状态码)** / **Verdict PASS|FAIL** / **Duration**。
|
||||
|
||||
---
|
||||
|
||||
## 4. 失败标准(任一即 FAIL)
|
||||
|
||||
1. 使用 stub / `page.route` mock / DB fixture / 纯 API 灌库冒充 UI 路径
|
||||
2. 首轮成功生成后仍无变更报告入口,或报告摘要为固定假句「智能体交付物已生成」;或报告面板缺少风险条目/项目影响/文档影响原因建议/开放问题
|
||||
2b. 高风险二轮仅有小队成功文案但工具条无「待确认报告」、或未确认就静默进版本历史、或 `confirmed:false` 仍提交成功
|
||||
3. 把 `analysis_status=fallback` 文案写成「PI 完整分析」或隐瞒开放问题
|
||||
4. 人工保存返回成功但刷新丢正文,或投影失败仍 200
|
||||
5. 三 overlay 视觉无差异(截图无法区分)
|
||||
6. 双上下文后写静默覆盖
|
||||
7. 无权限用户可见正文片段
|
||||
8. 容器重启后受控已落盘文档仍永久「账本未就绪」(在确有 output.md / 记录的前提下)
|
||||
9. 证据目录缺失或无法打开 trace/截图复盘
|
||||
|
||||
---
|
||||
|
||||
## 5. 通过标准
|
||||
|
||||
- UI-01…UI-16 全部 PASS,证据归档完整
|
||||
- 工程门禁另栏 PASS(不记入本计划勾选)
|
||||
- 已知 blocker `DOCREV-RT-PI-NARRATIVE`:允许 fallback,但必须可见真实 diff 摘要 + 开放问题标明叙事待补
|
||||
- `DOCREV-RT-UPLOAD-ORPHAN`:UI-16 按空状态 PASS,不得伪造成功账本
|
||||
|
||||
---
|
||||
|
||||
## 6. 与工程门禁对照
|
||||
|
||||
| 类型 | 命令/产物 | 可否代替 UI 验收 |
|
||||
|------|-----------|------------------|
|
||||
| 工程 | `go vet ./...`;`go test -short ./...`;`cd web && npm test && npm run build` | **否** |
|
||||
| PG 可选 | `TEST_DATABASE_URL=... go test ./internal/docrevision -run TestPGPersist` | **否** |
|
||||
| 本计划 | Playwright 无头真实页面 + 真实小队 | **是(唯一最终)** |
|
||||
|
||||
## 7. 本轮状态
|
||||
|
||||
- Round20(2026-09-14)真实页面验收 **PASS**:results JSON 21/21;Playwright main 18 passed / 1 post skipped;仅 `restart shuimu-agent-app-dev` 后 post 1 passed / 18 skipped。
|
||||
- 测试前 `env-service.sh dev rebuild` 部署 `b258ab8`;文档收口不再动容器。
|
||||
- 项目 `UI验收-超声微创系统-mu0gwiez`(6159);intake `doc_proj6159_intake`;终态 V3/r2 / `A1-win-mu0gwiez`。
|
||||
- 报告:[../../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md](../../../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md)
|
||||
- Ubuntu 无头:`mcr.microsoft.com/playwright:v1.63.0-noble`(`--network host --ipc host`,`BASE_URL :3100`);本次无需给 host 装浏览器。宿主 `npx playwright install` 仅备选。
|
||||
- 顶层截图 **21** 个文件:主阶段 20 张(含 UI-15-pre)+ post-restart 1 张;与 results JSON 21 条不是同一计数。
|
||||
- 工程门禁另栏:`go test -short` / `go vet` / web 333+30 / build PASS;`-race` 全包并行 **NOT PASS**(`TestCreateTaskRun_PreActivationAcceptedNot409` TempDir cleanup)。
|
||||
- 全仓仍 `production_ready=no`(`CHAT-INTENT` 等)。
|
||||
@@ -0,0 +1,57 @@
|
||||
---
|
||||
title: "PG ID 重映射:Round20 后关闭"
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-14
|
||||
from: Cursor-Auto
|
||||
to: next-agent
|
||||
status: done
|
||||
---
|
||||
|
||||
# 交接:PG ID 重映射(已合入并经 Round20 验证)
|
||||
|
||||
## 目标(下一位 Agent 应完成什么)
|
||||
|
||||
- 不要重开本缺陷,除非新现场再次出现 `CommitAgentVersion` not found
|
||||
- 不要改删 Round19 失败归档
|
||||
- 全仓焦点已离开文档运行时 UI;勿占用已释放的 DOCREV-RT 集成槽,除非新任务登记
|
||||
|
||||
## 已完成
|
||||
|
||||
- 统一 `advanceID` / `nextFreeID` / `adopt*ID`
|
||||
- 隔离 PG 高序列首次生成:baseline 不丢、重启 hydration
|
||||
- 合入 `dev@b258ab8`
|
||||
- Round20 真实 UI-03:项目 6159 首次生成 V2/r0,不再 `docrevision: not found`
|
||||
|
||||
## 未完成
|
||||
|
||||
- 无(本缺陷)。PI 叙事 fallback 与 `CHAT-INTENT` 属其他条目
|
||||
|
||||
## 认领 / 槽位状态
|
||||
|
||||
| 项 | 值 |
|
||||
|----|-----|
|
||||
| mutex 已释放 | yes |
|
||||
| 集成槽位 holder | idle(运行时 UI 收口后释放) |
|
||||
| branch | 已合入 `dev`(`merge: fix/document-revision-pg-id-remap`) |
|
||||
| worktree | - |
|
||||
|
||||
## 关键文件
|
||||
|
||||
| 路径 | 说明 |
|
||||
|------|------|
|
||||
| `internal/docrevision/ids.go` | counter / adopt |
|
||||
| `internal/docrevision/pg_mutate.go` | PG 写入后 adopt |
|
||||
| `internal/docrevision/pg_id_remap_test.go` | 隔离 PG 碰撞 |
|
||||
|
||||
## 如何验证
|
||||
|
||||
见 [../../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md](../../../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md)。不要把 output snapshot 250 写成 candidate 250(6158 现场:candidate id=175、output snapshot id=250、report id=175)。
|
||||
|
||||
## 风险 / Blocker
|
||||
|
||||
- 不得把 `ErrNotFound` 改成忽略
|
||||
|
||||
## 相关链接
|
||||
|
||||
- CURRENT: [../CURRENT.md](../../../ops/CURRENT.md)
|
||||
- Task: [../short-term/2026-09-13-document-revision-pg-id-remap.md](../2026-09-13-document-revision-pg-id-remap.md)
|
||||
@@ -0,0 +1,40 @@
|
||||
---
|
||||
title: "post-restart 最终正文 snippet:Round20 后关闭"
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-14
|
||||
from: Cursor-Auto
|
||||
to: next-agent
|
||||
status: done
|
||||
---
|
||||
|
||||
# 交接:post-restart 最终正文 snippet(已验证)
|
||||
|
||||
## 目标(下一位 Agent 应完成什么)
|
||||
|
||||
- 不要改删 `schema31-postrestart-stale-body-snippet-failure`
|
||||
- 不要删除 post-restart `bodySnippet` 可见断言
|
||||
- 新 UI 轮次必须继续把 UI-13b A1 成功正文写入 phase-state
|
||||
|
||||
## 已完成
|
||||
|
||||
- `durableBodySnippet`:成功修订覆盖;冲突稿不入账
|
||||
- UI-13b / UI-15-pre 同步最终 marker
|
||||
- Round20 post-restart:login / 项目 6159 / `revision-state` 200 / V3/r2 / `A1-win-mu0gwiez`
|
||||
|
||||
## 未完成
|
||||
|
||||
- 无(本缺陷)
|
||||
|
||||
## 认领 / 槽位状态
|
||||
|
||||
| 项 | 值 |
|
||||
|----|-----|
|
||||
| mutex 已释放 | yes |
|
||||
| 集成槽位 holder | idle |
|
||||
| branch | 已合入 `dev` |
|
||||
| worktree | - |
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Test report: [../../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md](../../../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md)
|
||||
- Task: [../short-term/2026-09-13-document-revision-post-restart-final-snippet.md](../2026-09-13-document-revision-post-restart-final-snippet.md)
|
||||
@@ -0,0 +1,70 @@
|
||||
---
|
||||
title: "post-restart 项目名 selector:编码后交接"
|
||||
created: 2026-09-13
|
||||
from: Cursor-Auto
|
||||
to: next-agent
|
||||
status: done
|
||||
updated: 2026-09-14
|
||||
|
||||
---
|
||||
|
||||
# 交接:post-restart 项目名 selector(暂不合入)
|
||||
|
||||
## 目标(下一位 Agent 应完成什么)
|
||||
|
||||
- 不要在本分支继续改职责/业务语义
|
||||
- 合入前占 CURRENT 集成槽位;本轮禁止 merge / 重建容器 / 声称 post-restart 通过
|
||||
- 占槽后重跑 `UI_PHASE=post-restart`,确认 UI-15 走到 revision-state
|
||||
|
||||
## 已完成
|
||||
|
||||
- post-restart:侧栏 exact title 点击 + banner exact 项目名断言
|
||||
- Playwright 产物按 `UI_PHASE` 分目录,避免第二阶段覆盖主阶段
|
||||
- 结果 JSON:main 仍写 `ui-acceptance-results.json`;post-restart 写 `ui-acceptance-results-post-restart.json`;`phase-state` / secrets 共享
|
||||
- helper 契约测试;`npm test` / `npm run build`
|
||||
|
||||
## 未完成
|
||||
|
||||
- 真实 UI-15 post-restart
|
||||
- 合入 `dev`
|
||||
|
||||
## 认领 / 槽位状态
|
||||
|
||||
| 项 | 值 |
|
||||
|----|-----|
|
||||
| mutex 已释放 | no(`document-revision-post-restart-selector` 仍 `in_progress`) |
|
||||
| 集成槽位 holder | 他人 e2e;本任务未占槽 |
|
||||
| branch | `fix/document-revision-post-restart-selector` |
|
||||
| worktree | - |
|
||||
|
||||
> 若 mutex 未释放,下一位须先在 CURRENT 认领或写 blocker。
|
||||
|
||||
## 关键文件
|
||||
|
||||
| 路径 | 说明 |
|
||||
|------|------|
|
||||
| `web/src/lib/currentProjectRestore.ts` | 入口 / banner locator 契约 |
|
||||
| `web/src/lib/playwrightPhaseArtifacts.ts` | 阶段目录名 |
|
||||
| `web/e2e/document-revision-runtime.spec.ts` | post-restart UI-15 |
|
||||
| `web/playwright.config.ts` | 分阶段 outputDir / HTML report |
|
||||
|
||||
## 如何验证
|
||||
|
||||
```bash
|
||||
cd web && npm test && npm run build
|
||||
# 真实 UI(本轮不做):
|
||||
# RUN_UI_ACCEPTANCE=1 UI_PHASE=post-restart npx playwright test e2e/document-revision-runtime.spec.ts
|
||||
```
|
||||
|
||||
产物:`playwright-output-main` / `playwright-report-main` / `ui-acceptance-results.json` 与 `playwright-output-post-restart` / `playwright-report-post-restart` / `ui-acceptance-results-post-restart.json`。`phase-state.json` 与 `phase-secrets.local.json` 跨阶段共享;`UI-15-post-restart.png` 可与主阶段截图同目录。
|
||||
|
||||
## 风险 / Blocker
|
||||
|
||||
- 侧栏折叠时 complementary 入口不可见,应 FAIL 而非 `.first()` 跳过
|
||||
- 不得改删 schema31 失败归档
|
||||
|
||||
## 相关链接
|
||||
|
||||
- CURRENT: [../CURRENT.md](../../../ops/CURRENT.md)
|
||||
- Task: [../short-term/2026-09-13-document-revision-post-restart-selector.md](../2026-09-13-document-revision-post-restart-selector.md)
|
||||
- Checklist: [../checklists/2026-09-13-document-revision-post-restart-selector.md](../checklists/2026-09-13-document-revision-post-restart-selector.md)
|
||||
@@ -0,0 +1,73 @@
|
||||
---
|
||||
title: "reviewer 职责同步:heal 同事务锁后交接"
|
||||
created: 2026-09-13
|
||||
from: Cursor-Auto
|
||||
to: next-agent
|
||||
status: done
|
||||
updated: 2026-09-14
|
||||
|
||||
---
|
||||
|
||||
# 交接:reviewer 职责同步(暂不合入)
|
||||
|
||||
## 目标(下一位 Agent 应完成什么)
|
||||
|
||||
- 不要在本分支继续改职责语义,除非新审查点
|
||||
- 合入前占 CURRENT 集成槽位,再 `--no-ff` 合 `dev`;本轮禁止 merge / 重建容器 / 声称 E2E
|
||||
- 6145 的 B 仍是空 `document_duty`,须再走成员 API 写成 reviewer 后自愈才会对齐文档
|
||||
|
||||
## 已完成
|
||||
|
||||
- Heal 以 assigned 为权威;空 assigned 只清失效审核/批准 holder
|
||||
- 成员增改/移出:同一事务内 advisory lock + 读旧/冲突 holder + 成员写 + 精确清 reviewer/approver 槽;提交后服务层 heal 新 holder
|
||||
- `HealProjectDocuments` 与成员写共用 `pg_advisory_xact_lock(project_id)`;解析与文档读写同事务;错误回滚
|
||||
- 确定性并发 PG:成员写持锁未提交时 heal 进入 `pg_locks` 等待;提交后旧 reviewer 不复活;第二次 heal 幂等
|
||||
- 同步失败仍显式 `ERR_DUTY_SYNC`;author 不因普通成员变更清空
|
||||
- 账本创建失败任务失败
|
||||
|
||||
## 未完成
|
||||
|
||||
- 真实 UI-13a
|
||||
- 合入 `dev` 与共享容器 schema 31 晋升
|
||||
|
||||
## 认领 / 槽位状态
|
||||
|
||||
| 项 | 值 |
|
||||
|----|-----|
|
||||
| mutex 已释放 | no(`document-revision-reviewer-duty-sync` 仍 `in_progress`) |
|
||||
| 集成槽位 holder | 他人 e2e;本任务未占槽 |
|
||||
| branch | `fix/document-revision-reviewer-duty-sync` |
|
||||
| worktree | - |
|
||||
|
||||
> 若 mutex 未释放,下一位须先在 CURRENT 认领或写 blocker。
|
||||
|
||||
## 关键文件
|
||||
|
||||
| 路径 | 说明 |
|
||||
|------|------|
|
||||
| `internal/docduty/revoke.go` | `AcquireProjectDutyLock`(与成员写同键) |
|
||||
| `internal/docduty/store.go` | heal lock + 解析 + 回填同事务 |
|
||||
| `internal/authz/authorizer.go` | upsert / setStatus 走同一 lock helper |
|
||||
| `scripts/run-isolated-duty-sync-pg-tests.sh` | 隔离 PG 入口 |
|
||||
|
||||
## 如何验证
|
||||
|
||||
```bash
|
||||
go test -short ./...
|
||||
go test -short -race ./internal/docduty ./internal/authz ./internal/bizdev ./internal/server
|
||||
cd web && npm test && npm run build
|
||||
# 隔离库,禁止 agent_system_dev:
|
||||
./scripts/run-isolated-duty-sync-pg-tests.sh
|
||||
```
|
||||
|
||||
## 风险 / Blocker
|
||||
|
||||
- 旧项目未写 `document_duty` 时,在任成员仍留在文档槽位(有意兼容)
|
||||
- 显式降级/退出才会撤 reviewer/approver;author 永不被 revoke
|
||||
- 6145 B 不会被臆造为 reviewer
|
||||
|
||||
## 相关链接
|
||||
|
||||
- CURRENT: [../CURRENT.md](../../../ops/CURRENT.md)
|
||||
- Task: [../short-term/2026-09-13-document-revision-reviewer-duty-sync.md](../2026-09-13-document-revision-reviewer-duty-sync.md)
|
||||
- Checklist: [../checklists/2026-09-13-document-revision-reviewer-duty-sync.md](../checklists/2026-09-13-document-revision-reviewer-duty-sync.md)
|
||||
@@ -0,0 +1,65 @@
|
||||
---
|
||||
title: "Herdr Agent 治理分支待集成交接"
|
||||
created: 2026-09-13
|
||||
from: Codex
|
||||
to: next-integration-holder
|
||||
status: closed
|
||||
---
|
||||
|
||||
# 交接:Herdr Agent 治理分支待集成
|
||||
|
||||
> **superseded 2026-09-14**:Herdr 角色/脚本已从活文档移除;本交接仅作历史证据。见 [.././2026-09-14-remove-herdr-agent-settings.md](.././2026-09-14-remove-herdr-agent-settings.md)。
|
||||
|
||||
## 目标(下一位 Agent 应完成什么)
|
||||
|
||||
治理规范已完成并准备合入 `dev`;本文件保留为集成证据。
|
||||
|
||||
## 已完成
|
||||
|
||||
- 已建立角色、任务泳道、额度保护、自动审批和故障接管 SSOT。
|
||||
- 已提供七种 profile 的统一启动脚本和保守派发脚本。
|
||||
- 已验证脚本语法、全部 profile dry-run、全部 route、错误标准名和无实例安全退出。
|
||||
|
||||
## 未完成 / 后续
|
||||
|
||||
- 未推送远端(用户未要求)。
|
||||
- Cline 已安装且可调用,但标准命名 Herdr 实例仍需一次只读和一次隔离 worktree 写验收后才能升为 active。
|
||||
|
||||
## 认领 / 槽位状态
|
||||
|
||||
| 项 | 值 |
|
||||
|----|-----|
|
||||
| mutex 已释放 | yes |
|
||||
| 集成槽位 holder | 未操作共享容器 |
|
||||
| branch | `feature/herdr-agent-governance` |
|
||||
| worktree | `.worktrees/feature-herdr-agent-governance` |
|
||||
|
||||
## 关键文件
|
||||
|
||||
| 路径 | 说明 |
|
||||
|------|------|
|
||||
| `.doc/archive/ops/2026-09-13-herdr-agent-roster.md` | 角色与路由 SSOT(已归档) |
|
||||
| `scripts/herdr-agent-start.sh` | 免人工审批启动入口(已删除) |
|
||||
| `scripts/herdr-agent-dispatch.sh` | 主备派发与防重复策略(已删除) |
|
||||
| `AGENTS.md` / `PROJECT.md` | 强制入口与 PI 身份边界 |
|
||||
|
||||
## 如何验证
|
||||
|
||||
```bash
|
||||
bash -n scripts/herdr-agent-start.sh scripts/herdr-agent-dispatch.sh
|
||||
./scripts/herdr-agent-start.sh --dry-run codex orchestrator_codex w1:p1
|
||||
./scripts/herdr-agent-dispatch.sh --explain implementation
|
||||
git diff --check
|
||||
```
|
||||
|
||||
## 风险 / Blocker
|
||||
|
||||
- `CURRENT.md` 是活文档;合并时以最新 `dev` 的 holder、phase、scope 为准,仅保留本任务认领或完成记录。
|
||||
- 不要因为 `timeout` / `agent_prompt_stalled` 自动重投任务。
|
||||
- 不要为验证本分支重启现有 DOCREV 实例或操作共享 Docker。
|
||||
|
||||
## 相关链接
|
||||
|
||||
- CURRENT: [CURRENT.md](../CURRENT.md)
|
||||
- Task: [2026-09-13-herdr-agent-governance.md](./2026-09-13-herdr-agent-governance.md)
|
||||
- Checklist: 任务文中的验收标准
|
||||
@@ -0,0 +1,55 @@
|
||||
---
|
||||
title: "管理员开通账号后立项成员候选缺失(UI-01)"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
severity: high
|
||||
---
|
||||
|
||||
# 管理员开通账号后立项成员候选缺失(UI-01)
|
||||
|
||||
## 现象
|
||||
|
||||
Antigravity 真实 UI:UI-00 管理员入口已 PASS。UI-01 产品失败——管理员经 UI 成功创建账号 B,但 tech-lead A 打开「新建项目」时成员候选列表中无 B。
|
||||
|
||||
## 根因分析
|
||||
|
||||
1. `AdminSettingsModalProps` 已声明 `onRefreshUsers`;`App` 已传入 `getAdminUsers → setAllUsers`。
|
||||
2. 组件 **destructuring 漏掉** `onRefreshUsers`,成为死 prop。
|
||||
3. 模态内 `refreshUsers()` 仅 `setAdminUsers`,创建/角色/状态成功后从未同步父级 `allUsers`。
|
||||
4. `CreateProjectModal` / `ProjectMembersModal` 的 `availableUsers` 来自 App `allUsers`(并经 `saveUsers` 写入 localStorage),故同会话内立项候选仍是旧目录。
|
||||
5. 附带:App 原 `onRefreshUsers` 用 `.catch(() => {})` 静默吞错,即使接线也会掩盖同步失败。
|
||||
|
||||
## 严重度
|
||||
|
||||
`high`(同浏览器管理员开通后立项立刻缺人;阻断 UI-01)
|
||||
|
||||
## 本轮修复(本任务范围内)
|
||||
|
||||
- 抽出可测 helper:`web/src/lib/adminUserDirectorySync.ts`(缺 `onRefreshUsers` / 父级抛错均 fail-closed)
|
||||
- `AdminSettingsModal` 正确 destructure;创建/角色/状态/审批/重置后 `await refreshUsers()`;同步失败对用户可见
|
||||
- `App` `onRefreshUsers` 改为 async 上抛,禁止静默
|
||||
|
||||
## 残留审计风险(本任务不越权补齐)
|
||||
|
||||
| 风险 ID | 说明 | 为何本轮不修 |
|
||||
|---------|------|--------------|
|
||||
| **DOCREV-RT-USER-DIR-CROSS-DEVICE** | 立项成员目录仍以浏览器 `allUsers`/localStorage 为事实源。tech-lead 在**新设备 / 清缓存 / 从未在本机跑过管理员同步**的会话中,即使服务端已有 B,本地候选仍可能只有 MOCK/`loadUsers` 缓存。非管理员无 `GET /api/v1/admin/users` 权限。 | 安全补齐需**非 admin 的成员目录/搜索 API**(最小权限、按项目或组织范围),属授权面扩展;禁止把 admin users API 下放给 tech-lead。 |
|
||||
|
||||
相关代码锚点:`App.tsx` `availableUsers={allUsers}`;`storage.loadUsers`/`saveUsers`;服务端仅 `GET /api/v1/admin/users`。
|
||||
|
||||
## 关联整改
|
||||
|
||||
- Short-term: [../ops/short-term/2026-09-13-document-revision-runtime.md](../archive/ops/2026-09-13-document-revision-runtime.md)
|
||||
- Checklist: [../ops/checklists/2026-09-13-document-revision-runtime-ui-acceptance.md](../archive/ops/checklists/2026-09-13-document-revision-runtime-ui-acceptance.md)
|
||||
- 前序 auth 映射: [2026-09-13-auth-useraccount-snake-case-mapping.md](./2026-09-13-auth-useraccount-snake-case-mapping.md)
|
||||
|
||||
## 证据
|
||||
|
||||
- 实战:UI-00 PASS;UI-01 创建 B 后 A 立项候选无 B
|
||||
- 代码:`AdminSettingsModal` 原未解构 `onRefreshUsers`;App 静默 catch
|
||||
- 单测:`web/src/lib/adminUserDirectorySync.test.ts`(死 prop / 父级错误上浮)
|
||||
|
||||
## 开放问题
|
||||
|
||||
- 跨设备成员目录 API(见上表)→ 记入 short-term blocker,勿用 admin API workaround
|
||||
@@ -0,0 +1,39 @@
|
||||
---
|
||||
title: "Auth UserAccount snake_case 契约漏映射导致管理员入口隐藏"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
severity: high
|
||||
---
|
||||
|
||||
# Auth UserAccount snake_case 契约漏映射导致管理员入口隐藏
|
||||
|
||||
## 现象
|
||||
|
||||
真实浏览器 UI-00(Antigravity):管理员登录后左侧「系统管理」入口不可见,无法开通 A/B 账号。控制台侧 `currentUser.roleId` 为 `undefined`(服务端实际返回 `role_id: "role-admin"`)。
|
||||
|
||||
## 根因分析
|
||||
|
||||
- Go `auth.UserAccount` JSON 标签为 snake_case:`role_id` / `employee_id` / `must_change_password` / `created_at` / `updated_at`。
|
||||
- 前端 `AuthClient` 将 login / me / admin users 响应直接当作 camelCase `UserAccount` 使用,未在 API 边界映射。
|
||||
- 既有单测使用内存 `auth.local` 或驼峰假响应,未覆盖真实 wire 契约,故漏检。
|
||||
- `BootstrapAdminFromConfig` 对已存在非 admin 账号调用 `UpdateUserRole` 时静默忽略错误(`_, _ =`),可能留下非 `role-admin` 管理员配置账号。
|
||||
|
||||
## 严重度
|
||||
|
||||
`high`
|
||||
|
||||
## 关联整改
|
||||
|
||||
- Short-term: [../ops/short-term/2026-09-13-document-revision-runtime.md](../archive/ops/2026-09-13-document-revision-runtime.md)
|
||||
- Checklist: [../ops/checklists/2026-09-13-document-revision-runtime-ui-acceptance.md](../archive/ops/checklists/2026-09-13-document-revision-runtime-ui-acceptance.md)
|
||||
|
||||
## 证据
|
||||
|
||||
- UI-00 实战:管理员登录后无系统管理入口(roleId undefined)
|
||||
- `internal/auth/models.go` UserAccount json tags
|
||||
- `web/src/api/auth.ts` 原直接 `resp.json()` 赋给 UserAccount
|
||||
|
||||
## 开放问题
|
||||
|
||||
- 无(映射层 + bootstrap 错误上浮已落地;占槽后需重跑 UI-00 验证管理员入口)
|
||||
@@ -0,0 +1,106 @@
|
||||
---
|
||||
title: "小队完成未同步受控文档状态 + UI-03 选择器非 Tab + Retry 暴露 DB 约束(UI-03)"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
severity: critical
|
||||
---
|
||||
|
||||
# 小队完成未同步受控文档状态 + UI-03 选择器非 Tab + Retry 暴露 DB 约束(UI-03)
|
||||
|
||||
## 1. 现场实战概况与判定
|
||||
|
||||
在真实 UI 验收(`UI_PHASE=main`,dev 环境 `schema 29`,真实 `pi-agent` + `MiniMax-M2.7-highspeed`):
|
||||
|
||||
- **UI-00 PASS**(4.9s):管理员真实创建 A/B/C,准确按 DOM 作用域关闭模态,三用户完成首次登录改密。
|
||||
- **UI-01 PASS**(774ms):A 页面立项并分配 B 为 reviewer,项目工作台就绪,零 404,模板预览正确。
|
||||
- **UI-02 PASS**(191ms):真实发任务,`POST /api/v1/tasks/runs` 返回 202 Accepted,小队编排启动;真实模型耗时约 157 秒完成编排,后端成功生成受控文档 `doc_proj6089_user_requirements`(质量评分 100/100)。
|
||||
- **UI-03 FAIL**:`await expect(page.locator('[data-testid="doc-rev-version"]')).toBeVisible({ timeout: 60_000 });` 超时失败。
|
||||
- **页面真实状态**:页面已明确显示小队任务完成,正文标出 `📄 受控文档:doc_proj6089_user_requirements`。
|
||||
- **右栏面板状态**:右栏仍保持为 `doc-p intake` 初始模板(`用户初始需求收集表 模板`,`模板预览:首轮编制后启用版本账本`),版本工具条 `[data-testid="doc-rev-version"]` 根本未挂载。
|
||||
- **UI-04 ~ UI-16**:**NOT RUN**(因 UI-03 失败立即停机保全现场,未执行后续用例)。
|
||||
|
||||
---
|
||||
|
||||
## 2. 根因与现场异常分析
|
||||
|
||||
### A. 产品缺陷:前端在小队完成后未同步工作流文档列表
|
||||
|
||||
1. **服务端已落库受控文档**:
|
||||
后端 `document_records` 表已落库 `doc_id="doc_proj6089_user_requirements"`,`is_template_only=false`,`current_state="drafting"`。且前端每 5 秒发起的轮询 `GET /api/v1/projects/6089/documents?category=workflow` 已正确返回该受控文档记录。
|
||||
2. **`syncLeases` 轮询丢弃新文档**:
|
||||
在 `web/src/App.tsx` 第 1664–1697 行,每 5 秒执行的 `syncLeases` 仅提取 `doc.lease_holder_type` 并更新既有 `doc.docId` 的租约。由于本地 React 状态 `deliverables` 初始仅有 `doc-p6089-*` 模板,`leases.has(doc.docId)` 匹配不上 `doc_proj*`,新文档从未被合并进 `deliverables`。
|
||||
3. **`syncWorkflowDocs` 依赖项未触发**:
|
||||
在 `App.tsx` 第 1618–1661 行,`syncWorkflowDocs`(调用 `mergeWorkflowDocumentsFromServer`)仅在 `currentProjectId` 或 `session` 变动时执行;同一会话内小队完成不会触发该 effect。
|
||||
4. **流式结束 `case 'done'` 遗漏文档同步**:
|
||||
在 `App.tsx` 第 2571–2593 行,任务流完成时仅调用了 `await chatWindow.refresh().catch(() => undefined)`(仅刷新聊天消息),未同步工作流文档列表。
|
||||
5. **连锁阻断工具条挂载**:
|
||||
前端 `deliverables` 中的 `user_requirements` 一直是 `isTemplateOnly: true`。根据 `revisionToolbarMountMode` 契约,`isTemplateOnly === true` 时返回 `'template_hint'`,阻断 `DocumentRevisionToolbar`(`[data-testid="doc-rev-version"]`)挂载。
|
||||
|
||||
### B. 测试脚本缺陷:定位器假设水平 Tab 且命中页头 Banner 徽章
|
||||
|
||||
1. 在 `web/e2e/document-revision-runtime.spec.ts` 第 538 行:
|
||||
`const tab = page.locator('[role="tab"], button, div').filter({ hasText: /需求|摸底|URS|用户/ }).first();`
|
||||
2. **穿透到页头徽章**:
|
||||
`[role="tab"], button, div` 包含全局所有 `div`。页面顶部 Header Banner 含有 `当前项目: ... V0.1 需求摸底`(`div` 元素)。`.first()` 命中了该非交互的 Banner 徽章 `div`,根本没有点击文档切换器。
|
||||
3. **真实 UI 为下拉/抽屉交互**:
|
||||
`SlimTabBar.tsx` 为面包屑下拉(`button.dropdown-trigger` -> `.dropdown-menu`)或大盘抽屉(`DeckDrawer`),页面不存在水平文档 Tab。
|
||||
|
||||
### C. 前端断线自动重试与 DB 约束异常暴露
|
||||
|
||||
1. **前端断线自动重试导致同 turn 二次触发(非 Playwright retries)**:
|
||||
`web/playwright.config.ts` 中 **`retries: 0`**。现场 13:02 完成首轮后,13:05 再次出现同 prompt 处理中,根因是前端 `runTaskAttempt` 在连接异常路径上自动重试,且重试开头 `setRunId(null)` / 未显式传递 `reconnectRunId`,导致重复 `POST /tasks/runs` 而非订阅既有 run:
|
||||
- 13:02:`TRIGGER_TASK 请基于本项目编制首轮...` → `《用户需求表》已生成。当前状态:已完成`
|
||||
- 13:05:同 turn 自动重试路径再次进入处理中(工程修复:`reconnectRunId` 跨 attempt + Claim 幂等)
|
||||
2. **暴露 `task_runs` 状态约束缺陷**:
|
||||
在二次运行与高风险候选流转路径中,后台服务尝试将 `task_runs.status` 更新为 `pending_author_confirmation` 时,暴露了数据库底层约束拦截:
|
||||
goose **`00019`** 原始 `chk_task_run_status` 仅允许:
|
||||
```sql
|
||||
CHECK (status IN ('pending', 'running', 'completed', 'failed', 'cancelled', 'finalizing_failed', 'quality_failed', 'interrupted'))
|
||||
```
|
||||
该枚举**未包含** `pending_author_confirmation`,导致写入状态时触发 PostgreSQL check constraint 违规(由 goose `00030` 补齐)。
|
||||
|
||||
---
|
||||
|
||||
## 3. 严重度与阻断
|
||||
|
||||
- **严重度**:`critical`
|
||||
- **阻断项**:
|
||||
1. 产品前端:`App.tsx` 在小队完成(`case 'done'`)以及定期轮询中必须调用 `mergeWorkflowDocumentsFromServer` 动态更新受控文档。
|
||||
2. 数据库约束:`task_runs` 表的 `chk_task_run_status` 约束必须补齐 `pending_author_confirmation`。
|
||||
3. 测试脚本:修正 UI-03 文档切换定位器,禁止使用全局 `div` 通配,走真实 `SlimTabBar` 下拉或 `DeckDrawer` 动作;关闭非幂等的单用例重试。
|
||||
|
||||
---
|
||||
|
||||
## 4. 证据保全清单
|
||||
|
||||
- **归档路径**:`.doc/test-reports/assets/2026-09-13-document-revision-runtime-ui/ui03-controlled-doc-sync-failure/`
|
||||
- `playwright-output/`(含完整 `trace.zip`、`test-failed-1.png`、`error-context.md`)
|
||||
- `playwright-report/`(HTML 完整执行报告)
|
||||
- `screenshots/`(UI-00~UI-02 真实过程截图)
|
||||
- `traces/`、`videos/`
|
||||
- `ui-acceptance-results.json`(UI-00~UI-02 逐项 PASS 记录)
|
||||
- `phase-secrets.local.json`、`phase-state.json`
|
||||
- 历史归档目录全部原位保全:
|
||||
- `post-auth-ui00-backdrop-click-failure/`
|
||||
- `post-auth-ui00-close-selector-failure/`
|
||||
- `post-auth-ui00-wrong-close-locator-failure/`
|
||||
- `pre-auth-fix-ui00-failure/`
|
||||
- `ui01-parent-directory-sync-failure/`
|
||||
- `ui01-strict-mode-title-selector-failure/`
|
||||
- `ui02-task-scope-409-failure/`
|
||||
- `ui02-workflow-access-failure/`
|
||||
|
||||
---
|
||||
|
||||
## 5. 工程修复落盘(`fix/document-revision-runtime-ui03`,合入前)
|
||||
|
||||
| 根因 | 修复 | 门禁 |
|
||||
|---|---|---|
|
||||
| A 任务完成后未 merge 受控文档 | `pollUntilPostTaskServerDoc` + `deliverablesRef` 显式快照(禁止 setState updater 取 mergedSnap)+ 有限重试至 `doc_proj*` | focused + `npm test` / `build` |
|
||||
| A′ intake vs URS 误匹配 | `templateMatch`:**intake 标记优先**于裸「用户需求」 | 单测 PASS |
|
||||
| B UI-03 选择器命中 Banner | SlimTabBar/DeckDrawer;`data-chat-role/status` + 本轮 assistant sibling 等待;UI-11 禁止全局 div | 待真实 UI 重跑 |
|
||||
| C `pending_author_confirmation` 约束 | goose `00030` 扩展 `chk_task_run_status`(相对 **00019** 枚举) | 真实现卷迁移合入前独立验证 |
|
||||
| C′ 断线自动重试重复 POST | `reconnectRunId` 显式跨 retry;`ClaimRun`;`GetRun` 读回 `idempotency_key`;`StartClaimedRun` UpdateRun 失败不启 worker | `go test -short ./internal/taskrun` |
|
||||
|
||||
**未做**:占槽 rebuild、真实 UI UI-03 重验、schema30 对现有重复 `(session_id,client_turn_id)` 卷的迁移实测。
|
||||
@@ -0,0 +1,71 @@
|
||||
---
|
||||
title: "真实会话被调试探针污染、查询误触发写任务与刷新状态退化"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
severity: critical
|
||||
---
|
||||
|
||||
# 真实会话被调试探针污染、查询误触发写任务与刷新状态退化
|
||||
|
||||
## 现象
|
||||
|
||||
- 用户在“对话协同会话”中看到 `test` 等非本人业务输入,多次任务失败。
|
||||
- “总结一下用户初始需求表”没有读取/总结已有文档,而是启动 `intake` 写任务。
|
||||
- 实时失败卡片带恢复动作;刷新后只剩错误正文,重试/继续/重新开始能力消失。
|
||||
- 文档被智能体小队编辑期间,页面没有持续、醒目的占用状态,用户继续工作后才从失败中得知冲突。
|
||||
|
||||
## 根因分析
|
||||
|
||||
### 1. 诊断请求写入了真实用户会话
|
||||
|
||||
dev PostgreSQL 的 `sess-p143-u9` 在 03:17–03:32 记录了 `debug ping`、`test task`、`test`、`验证租约修复`。这些请求带有 `debug-turn-*` 等诊断标识,并与真实用户消息混排。结论不是“意图模型把输入改成 test”,而是调试过程直接复用了真实会话和项目 143,污染了审计记录与 UI。
|
||||
|
||||
### 2. 前端用名词命中代替动作意图识别
|
||||
|
||||
`web/src/engine/templateMatch.ts` 的 `resolveTaskKeyFromMessage` 只要文本包含“需求/用户”等名词就返回 `intake` 或 `user_requirements`。`App.tsx` 在聊天请求进入后端意图识别前先执行该匹配,并直接调用 `/api/v1/tasks/runs`。因此查询句“总结一下用户初始需求表”被确定性误判为写任务。
|
||||
|
||||
这不是模型偶发误判,而是客户端关键词捷径绕过了服务端意图合同;现有测试只覆盖“开始编写”,没有任何“总结/查看/当前状态/谁在编辑”等只读负例。
|
||||
|
||||
### 3. 结构化失败状态只存在于实时 SSE
|
||||
|
||||
实时路径把 `error_info`、`taskRequest`、`phaseEvents` 保存在 React 内存消息中;失败投影到 `chat_messages` 时只持久化 `run_id/workspace_id/task_status` 和错误正文。`mapRecordToMessage` 刷新恢复时也只依据 `task_status` 还原 `failed`,没有恢复 `errorInfo.actions`、原始任务请求或事件进度,导致 `MessageBubble` 无法渲染重试/继续/重新开始按钮。
|
||||
|
||||
### 4. 编辑租约存在,但不是可恢复的页面状态
|
||||
|
||||
`task_run_events` 已保存 `lease_acquired/lease_released`,`document_records` 也保存 `lease_holder_type/id/expires_at/heartbeat_at`。但 `App.tsx` 的任务事件处理只消费 `phase/status/delta/deliverable/error/done`,忽略 `governance`;刷新历史也不回放运行中任务事件。租约提示只可能短暂出现在内部数据,不能驱动会话、文档列表和编辑器的统一 busy 状态。
|
||||
|
||||
### 5. 文档忙被错误分型为系统内部错误
|
||||
|
||||
并发请求因有效租约拒绝时,事件被分类为 `INTERNAL_ERROR/fatal/actions=[restart]`,用户看到“系统内部错误,请重新开始会话”。实际是可预期的 `DOC_BUSY` 状态;除正确分型外,还必须在创建 `task_runs` 之前做服务端 busy 预检,持久化“未创建新任务”的只读状态卡,且不提供重试动作。
|
||||
|
||||
### 6. dev restart 不会加载新代码,健康检查可对旧镜像误报通过
|
||||
|
||||
`env-service.sh dev restart` 调用的是 `docker compose restart`;应用代码未挂载进容器,因此该命令只重启旧镜像。第一次修复后真实验证仍返回旧的 `CASUAL_CHAT`,但 `/health` 与 `/ready` 都为绿色。重建 app 镜像后,同一句话才返回 `QUERY_DOC_STATUS/doc_summary`。已新增显式 `rebuild` 动作,并将集成冒烟命令改为 `dev rebuild`。
|
||||
|
||||
## 严重度
|
||||
|
||||
`critical`:真实会话污染破坏可审计性;只读请求触发写入违反用户意图;刷新丢失恢复能力;后台编辑不可见导致重复劳动和冲突。
|
||||
|
||||
## 关联整改
|
||||
|
||||
- Remediation: [../remediation/2026-09-13-conversation-intent-runtime-state-remediation.md](../remediation/2026-09-13-conversation-intent-runtime-state-remediation.md)
|
||||
- Short-term: [../ops/short-term/2026-09-13-conversation-intent-runtime-state.md](../ops/short-term/2026-09-13-conversation-intent-runtime-state.md)
|
||||
|
||||
## 证据
|
||||
|
||||
- dev PostgreSQL:`chat_sessions.id=138/session_id=sess-p143-u9/project_id=143/user_id=9`
|
||||
- `chat_messages.id=554..567`:诊断探针、误路由与失败投影
|
||||
- `task_runs.run_id=run_1789269755258510844`:03:22–03:32 持有租约;并发请求均因 busy 失败
|
||||
- `task_runs.run_id=run_1789270446838831656`:由“总结一下用户初始需求表”启动的新写任务
|
||||
- `task_run_events`:租约获取/释放与 `INTERNAL_ERROR` 分型
|
||||
- `web/src/engine/templateMatch.ts`
|
||||
- `web/src/App.tsx`
|
||||
- `web/src/api/chatWindow.ts`
|
||||
- `internal/taskrun/manager.go`
|
||||
- `scripts/env-service.sh`(`restart` 与 `rebuild` 语义)
|
||||
|
||||
## 开放问题
|
||||
|
||||
- 已污染的四条诊断消息是否由项目创建者确认后做可审计软删除;本任务不擅自修改用户数据。
|
||||
- 误启动的最新任务是否保留其产物;本任务不擅自取消或删除。
|
||||
@@ -0,0 +1,48 @@
|
||||
---
|
||||
title: "当前受控文档改写被领域关键词改路由到另一交付物"
|
||||
status: in_progress
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
severity: high
|
||||
---
|
||||
|
||||
# 当前受控文档改写被领域关键词改路由到另一交付物
|
||||
|
||||
## 现象
|
||||
|
||||
第二轮真实 UI(schema 30)**UI-05 首个失败**:
|
||||
|
||||
- 页面打开 `doc_proj6109_intake`(用户初始需求收集表,V2/r0)
|
||||
- 用户输入含「当前受控文档」的高风险改写提示(YY/T、GB 9706.1、NMPA 注册法规)
|
||||
- 前端按法规关键词路由为 `feasibility_reg`
|
||||
- `POST` 启动 `run_1789313290400899325`,生成 `doc_proj6109_feasibility_reg` 并 `completed`
|
||||
- 当前 intake **无 pending badge**;E2E 等待 60s 失败
|
||||
|
||||
## 根因分析
|
||||
|
||||
| 层 | 问题 |
|
||||
|---|---|
|
||||
| `resolveTaskKeyFromMessage` | 写动词「改写」通过后,正文「注册」命中 `feasibility_reg`,无视当前打开文档 |
|
||||
| `handleSendMessage` | 只把文案+模板池交给 `resolveTaskTemplateForMessage`,未传入 active `doc_proj` |
|
||||
| 产品 | 「当前受控文档/本文件/这份文档」是指示语,领域词是改写内容,不是切换交付物 |
|
||||
|
||||
服务端 `ResolveAndValidateDocID` 已校验 project + task_key 与已注册文档一致,**不得**用客户端 `doc_id` 覆盖 `task_key`。本轮补了 `feasibility_reg` + `doc_proj6109_intake` mismatch 拒绝用例:攻击或误路由不得借 intake 文档改写另一任务键。
|
||||
|
||||
## 严重度
|
||||
|
||||
`high`
|
||||
|
||||
## 关联整改
|
||||
|
||||
- Short-term: [../ops/short-term/2026-09-13-document-revision-active-doc-routing.md](../archive/ops/2026-09-13-document-revision-active-doc-routing.md)
|
||||
- 分支: `fix/document-revision-active-doc-routing`
|
||||
|
||||
## 证据
|
||||
|
||||
- Evidence root(勿删、勿提交本轮):`.doc/test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui05-active-doc-routing-failure`
|
||||
- E2E:`web/e2e/document-revision-runtime.spec.ts` UI-05(断言不改弱)
|
||||
- 审查约束:E2E/用例提示词只留在 test 文件,生产 `templateMatch.ts` 不导出用例编号常量
|
||||
|
||||
## 开放问题
|
||||
|
||||
- 占槽后真实 UI-05 重跑;本轮不操作容器
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
title: "UI-06 用 overlay/p/h 选择器找不到真实文档块"
|
||||
status: in_progress
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
severity: high
|
||||
---
|
||||
|
||||
# UI-06 用 overlay/p/h 选择器找不到真实文档块
|
||||
|
||||
## 现象
|
||||
|
||||
第六轮真实 UI(schema 30):
|
||||
|
||||
- UI-00~05b **PASS**
|
||||
- UI-06 在 `editFirstPaneBlockAndSave` 里对 `[data-overlay-kind], p, h1, h2` **双击前超时**
|
||||
- 失败页正文真实存在;工具条版本徽章可见
|
||||
|
||||
## 根因分析
|
||||
|
||||
| 层 | 问题 |
|
||||
|---|---|
|
||||
| DOM | `BlockRenderer` 块 wrapper 是 generic `div`;`HeadingBlockView` / `ParagraphBlockView` 也不是 `h1`/`p` |
|
||||
| overlay | `data-overlay-kind` 仅在非 `pure` 且命中 hunk 时出现;默认 `pure` 模式该属性不存在 |
|
||||
| 脚本 | `openFirstPaneEditorAndFill` 依赖 overlay 装饰或原生标题/段落标签,与产品 DOM 契约不符 |
|
||||
|
||||
这是 **UI 自动化可寻址缺口**,不是正文未加载。继续用 overlay 选择器会误点标题栏/骨架/报告,或在 pure 模式直接超时。
|
||||
|
||||
## 严重度
|
||||
|
||||
`high`
|
||||
|
||||
## 关联整改
|
||||
|
||||
- Short-term: [../ops/short-term/2026-09-13-document-revision-e2e-block-selector.md](../archive/ops/2026-09-13-document-revision-e2e-block-selector.md)
|
||||
- 分支: `fix/document-revision-e2e-block-selector`
|
||||
|
||||
## 证据
|
||||
|
||||
- Evidence root(已归档、本轮勿提交):`.doc/test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui06-block-selector-failure/`
|
||||
- `ui-acceptance-results.json`:UI-00~05b PASS;UI-06 未写入 PASS
|
||||
|
||||
## 开放问题
|
||||
|
||||
- 占槽后真实 UI-06/13b 重跑;本任务保持 `in_progress`,不得标 `done`
|
||||
@@ -0,0 +1,48 @@
|
||||
---
|
||||
title: "UI-13a 用整行 option 文案误判编制负责人"
|
||||
status: in_progress
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
severity: high
|
||||
---
|
||||
|
||||
# UI-13a 用整行 option 文案误判编制负责人
|
||||
|
||||
## 现象
|
||||
|
||||
第16轮真实 UI(schema 30,`dev@dd5671e`):UI-00 至 UI-12 PASS;分类导航修复已实证,UI-13a 已能从「我的私密」切回「流程受控」并打开 reviewer B 权限矩阵。
|
||||
|
||||
失败在职责断言:`intakeRow.innerText` 被整行匹配,报 `reviewer B must not be 编制负责人`。实际 `innerText` 为:
|
||||
|
||||
`V0.5 用户初始需求收集表当前打开 状态: drafting ✍️ 编制负责人 🔍 审核负责人 👑 批准负责人 👁️ 查阅者 (只读) 前往`
|
||||
|
||||
## 根因分析
|
||||
|
||||
| 层 | 问题 | 后果 |
|
||||
|---|---|---|
|
||||
| 职责单元格 | `onRoleChangeForDoc` 存在时渲染 `<select>`,四个 option 文案都在 DOM | `element.innerText` 含全部 option |
|
||||
| 验收 | `/编制负责人/.test(整行文本)` | 审核人行也被判成编制负责人 |
|
||||
| 控件语义 | select/badge 无稳定 `data-testid` / `data-doc-role` | 脚本只能刮行文案 |
|
||||
|
||||
select 的 `value` 才是当前职责。USER_B 在 UI-01 被明确分配 reviewer:验收必须证明 `role=reviewer`,不得把职责同步丢失降级成的 `viewer` 判通过。select 还须 `data-can-assign=false` 且 `disabled`;`canAssignLead=true` 一律拒绝。
|
||||
|
||||
## 严重度
|
||||
|
||||
`high`
|
||||
|
||||
权限矩阵已打开,真实只读检查未跑到就被假阳性打断。
|
||||
|
||||
## 关联整改
|
||||
|
||||
- Remediation: [../remediation/2026-09-13-document-revision-duty-cell-assertion.md](../remediation/2026-09-13-document-revision-duty-cell-assertion.md)
|
||||
- Short-term: [../ops/short-term/2026-09-13-document-revision-duty-cell-assertion.md](../archive/ops/2026-09-13-document-revision-duty-cell-assertion.md)
|
||||
- 分支: `fix/document-revision-duty-cell-assertion`
|
||||
|
||||
## 证据
|
||||
|
||||
- 失败证据(只读):`.doc/test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui13a-duty-cell-assertion-failure/`
|
||||
|
||||
## 开放问题
|
||||
|
||||
- 本轮不重跑真实 UI-13a;不得标 E2E 通过或任务 `done`
|
||||
- 独立审查:不得用 `reviewer|viewer` 宽判;`evaluateReviewerDuty` 只接受精确 reviewer
|
||||
@@ -0,0 +1,58 @@
|
||||
---
|
||||
title: "文档职责伪造与保存时重取 ETag 可覆盖并发正文"
|
||||
status: in_progress
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
severity: critical
|
||||
---
|
||||
|
||||
# 文档职责伪造与保存时重取 ETag 可覆盖并发正文
|
||||
|
||||
## 现象
|
||||
|
||||
静态审查与 E2E UI-13 路径暴露两类产品缺陷:
|
||||
|
||||
1. **职责提升**:审核人 B 或项目外陌生人打开受控文档后,工作台把其当成编制人,出现正文编辑 / 送审动作。
|
||||
2. **并发覆盖**:两窗口同开同一修订时,后保存方在点击保存瞬间重新 GET 最新 ETag,If-Match 对准已更新账本,409 不会出现,先保存方的正文被静默覆盖。
|
||||
|
||||
## 根因分析
|
||||
|
||||
| 层 | 问题 | 风险 |
|
||||
|---|---|---|
|
||||
| API | `ListWorkflowDocumentsByProject` / `GET projects/{id}/documents` 的 summary 不投影 `document_records` 的 author/reviewer/approver id+name | 前端无权威职责,只能猜 |
|
||||
| 前端 merge | `mergeWorkflowDocumentsFromServer` 用当前登录用户名伪造 `author`,审核/批准写死「李主管」「王总监」 | B 登录后 `author===自己`,权限矩阵显示编制人 |
|
||||
| 角色解析 | `currentDocRole` 比 name,失败默认 `'author'` | 未知身份 fail-open,陌生人获得编辑/送审 |
|
||||
| 保存 | `handleSaveBlockEdit` 在 PATCH 前 `getRevisionState` 取最新 ETag | 打开时基线被丢弃;后写覆盖先写 |
|
||||
| E2E | UI-13b 在 A1 完整保存后才打开 A2 编辑器 | 不是真实竞争,无法钉住上述 ETag 缺陷 |
|
||||
|
||||
独立审查补强(同一分支):
|
||||
|
||||
| 层 | 问题 | 风险 |
|
||||
|---|---|---|
|
||||
| PATCH | `resolvePatchEtag` 在 controlled 缺基线时仍返回 `0:0` | 服务异常被当成合法 bootstrap,可能覆盖已有账本 |
|
||||
| hydrate | revision-state 5xx/网络失败只写 undefined 仍返回可编辑 AST | 用户能改正文,保存再 PATCH `0:0` |
|
||||
| 批注 | viewer 被 cast 为 reviewer/approver,`canAnnotate` 对 viewer 开放 | 查阅者可新增评审批注 |
|
||||
| 职责 | `isLegacyLocalDoc = !ids`:服务端 duty id 为 0 仍走 name fallback | 同名用户被提权为编制人 |
|
||||
|
||||
安全含义:职责伪造是**越权写**(viewer/reviewer 可改受控正文并送审)。ETag 刷新或 `0:0` 误用是**完整性破坏**。viewer 批注是**越权写元数据**。
|
||||
|
||||
## 严重度
|
||||
|
||||
`critical`
|
||||
|
||||
## 关联整改
|
||||
|
||||
- Remediation: [../remediation/2026-09-13-document-revision-duty-etag-overwrite.md](../remediation/2026-09-13-document-revision-duty-etag-overwrite.md)
|
||||
- Short-term: [../ops/short-term/2026-09-13-document-revision-e2e-reject-routing.md](../archive/ops/2026-09-13-document-revision-e2e-reject-routing.md)
|
||||
- 分支: `fix/document-revision-e2e-reject-routing`
|
||||
|
||||
## 证据
|
||||
|
||||
- 代码(修复前):`internal/docgov/project_docs.go` summary 无职责列;`web/src/lib/deliverableSync.ts` `author: fallbackUser.name`;`web/src/App.tsx` 默认 `'author'` 与保存前 `getRevisionState`
|
||||
- 单测钉住:B/陌生人不成 author;stale hydrate ETag 用于 PATCH
|
||||
- 补强单测:controlled 缺 ETag/5xx 不可保存或不可打开;freeform 可 `0:0`;viewer 不能批注;服务端 duty id=0 不按 name 提权
|
||||
- 本轮不跑真实 E2E、不提交 evidence assets
|
||||
|
||||
## 开放问题
|
||||
|
||||
- 占槽后真实 UI-13a/13b 重跑;CURRENT 仍 `in_progress`,不得标 `done`
|
||||
@@ -0,0 +1,51 @@
|
||||
---
|
||||
title: "UI-05b 缺当前受控文档指示语被路由到 feasibility_reg"
|
||||
status: in_progress
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
severity: high
|
||||
---
|
||||
|
||||
# UI-05b 缺当前受控文档指示语被路由到 feasibility_reg
|
||||
|
||||
## 现象
|
||||
|
||||
第五轮真实 UI(schema 30)**UI-05b 首个失败**:
|
||||
|
||||
- UI-00~05a PASS(含第四轮「待确认报告」真实打开)
|
||||
- UI-05b 等待 `doc-rev-pending-badge` 60s 超时
|
||||
- Prompt 为「请再次按医疗器械临床试验与注册检验法规,重写电磁兼容与软件生存周期章节…」,**没有**「当前受控文档《用户初始需求收集表》」
|
||||
- 助手实际生成《注册路径可行性评估报告》`doc_proj6120_feasibility_reg`,状态 `completed`
|
||||
- 原 intake `doc_proj6120_intake` 工具条为 V3/r0、「变更报告」,**无 pending**
|
||||
|
||||
项目 `UI验收-超声微创系统-mu01100b`。
|
||||
|
||||
## 根因分析
|
||||
|
||||
| 层 | 问题 |
|
||||
|---|---|
|
||||
| Prompt | 缺「当前受控文档」指示语;「注册检验法规」命中 `feasibility_reg` 关键词 |
|
||||
| 产品路由 | 无 deixis 时按领域词选任务,这是既有契约;本轮**不改产品** |
|
||||
| 脚本 | 未在 `sendChat` 前等待并校验本轮 `POST /api/v1/tasks/runs` 的 `task_key`/`doc_id`,失败时才在 pending 徽章上暴露 |
|
||||
|
||||
同轮审查:UI-10 点全局工具条「比较」冒充历史比较;UI-12 接受「项目可见但只查一个 marker」;UI-13 把立项审核人 B 当正文第二编辑者。
|
||||
|
||||
## 严重度
|
||||
|
||||
`high`
|
||||
|
||||
## 关联整改
|
||||
|
||||
- Short-term: [../ops/short-term/2026-09-13-document-revision-e2e-reject-routing.md](../archive/ops/2026-09-13-document-revision-e2e-reject-routing.md)
|
||||
- 分支: `fix/document-revision-e2e-reject-routing`
|
||||
|
||||
## 证据
|
||||
|
||||
- Evidence root(勿删、勿提交本轮):`.doc/test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui05b-reject-routing-failure`
|
||||
- Playwright:`playwright-output/document-revision-runtime--bc8cd-date-→-reject-version-stays-chromium/error-context.md`
|
||||
- 结果:`ui-acceptance-results.json`(UI-05a PASS;UI-05b 未写入 PASS)
|
||||
|
||||
## 开放问题
|
||||
|
||||
- 占槽后真实 UI-05b 起重跑;本轮不操作容器、不重跑 E2E
|
||||
- 脚本收紧后状态仍为 `in_progress`,真实重跑前不得 `done`
|
||||
@@ -0,0 +1,60 @@
|
||||
---
|
||||
title: "UI-06 编辑弹窗打开期间 hydration 换块 ID 导致保存静默丢稿"
|
||||
status: in_progress
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
severity: high
|
||||
---
|
||||
|
||||
# UI-06 编辑弹窗打开期间 hydration 换块 ID 导致保存静默丢稿
|
||||
|
||||
## 现象
|
||||
|
||||
第十二轮真实 UI(schema 30,dev@4c465d2 基线):
|
||||
|
||||
- 双击正文块、fill 标记、点击「保存修改」动作均成功,编辑器随后关闭
|
||||
- 30 秒内修订仍为 **r0**
|
||||
- 网络 trace 中 `PATCH /api/v1/documents/.../content` **数量为 0**
|
||||
- 动作 monotonic:dblclick 611755–611807;fill 611860–611910;save 611917–611979
|
||||
- 恰在 fill 开始时,后台 `GET /api/v1/docgov/documents/doc_proj6140_intake/content` 于 **611862.379** 发起并完成 hydration
|
||||
|
||||
本轮不是选择器点错按钮(第七轮 save-selector),而是保存路径在客户端被静默短路。
|
||||
|
||||
## 根因分析
|
||||
|
||||
| 层 | 问题 | 后果 |
|
||||
|---|---|---|
|
||||
| AST 身份 | `markdownToBlockAST` / `generateId()` 明确 `Math.random()`,每次 parse 新建 `blk_*` | 弹窗持有打开时的块 ID,当前 `docAST` 已是新 ID |
|
||||
| hydrate 丢账本 | `fetchRevisionState` 依赖被窄化为 `Promise<{etag:string}>`;`buildControlledDocumentAST` 之后**没有** `applyHeadBlockMap(rev.st.head_block_map)` | 服务端已有稳定块身份,前端每次 hydration 仍随机换 ID |
|
||||
| 保存 | `handleSaveBlockEdit` 按 `updated.id` 在 `docAST.rootBlock.children` 查找;`idx === -1` 时 `setEditingBlock(null)` 后 return | 关窗、不发 PATCH、无提示 |
|
||||
| hydration 触发 | `useEffect([session, sessionValidated, activeDocId, deliverables])` 在 lease/工作流同步改 `deliverables` 时重跑 | fill 窗口打出新 GET |
|
||||
| 迟到响应 | hydrate `.then` 无 generation / 编辑门闩 | 弹窗打开后或 PATCH 成功后仍可覆盖编辑基线(即使 ID 已对齐,也会回滚新正文) |
|
||||
| 会话绑定 | 只按块 ID 保存;`activeDocId` 可被 canonical/session/任务流改写,不经 `handleSelectDoc` | 可能对另一份文档发 PATCH,或块 ID 碰巧对上 |
|
||||
| 关窗续跑 | 编辑中拒绝/跳过的首次 hydrate,effect 依赖不再变化 | 关窗后可能永久停在 loading skeleton |
|
||||
| 切文档 | `handleSelectDoc` 在编辑中静默 `closeBlockEditor` | 草稿被丢;modal 虽 `fixed inset:0 zIndex 100` 挡住 SlimTabBar,但 chat/drawer 等仍会调 `handleSelectDoc` |
|
||||
|
||||
`deliverables` 被 5s lease 同步、任务完成后 `syncControlledDocsAfterTask`、工作流列表合并(清 cache)以及 governance 事件改写。任一变化都会在编辑期间再拉正文并换块身份。
|
||||
|
||||
## 严重度
|
||||
|
||||
`high`
|
||||
|
||||
用户可见「已保存」(弹窗关闭),账本仍 r0。属于静默丢稿,不是提示后的失败。
|
||||
|
||||
## 关联整改
|
||||
|
||||
- Remediation: [../remediation/2026-09-13-document-revision-editor-hydration-race.md](../remediation/2026-09-13-document-revision-editor-hydration-race.md)
|
||||
- Short-term: [../ops/short-term/2026-09-13-document-revision-editor-hydration-race.md](../archive/ops/2026-09-13-document-revision-editor-hydration-race.md)
|
||||
- 分支: `fix/document-revision-editor-hydration-race`
|
||||
|
||||
## 证据
|
||||
|
||||
- 失败证据目录(根代理保留、本轮不得改/移/删/提交):`.doc/test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui06-r-bump-noop-failure/`
|
||||
- Playwright 断言:`[data-testid="doc-rev-revision"]` 30s 内仍为 `r0`
|
||||
|
||||
## 开放问题
|
||||
|
||||
- 本轮只做前端门闩与单测/构建验证;**未跑真实 UI-06**,不得标 E2E 通过或任务 `done`
|
||||
- 关窗后的下一次 deliverables 驱动 hydrate 仍会重建块 ID(编辑会话已结束;缺 map 时仍随机,门闩已消费)
|
||||
- **首次 hydrate 在 `editor_open` 被拒后会卡 skeleton**:可达(骨架块可双击,或清 cache 后编辑中跳过 GET)。关窗时 `takeHydrationResume()` 递增 `hydrateResumeKey` 重跑 effect。
|
||||
- modal 不能硬保证挡死所有 `handleSelectDoc`;编辑中切文档 fail-closed,不静默关窗。
|
||||
@@ -0,0 +1,47 @@
|
||||
---
|
||||
title: "UI-11 快速 completed 被验收脚本误判为失败"
|
||||
status: in_progress
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
severity: high
|
||||
---
|
||||
|
||||
# UI-11 快速 completed 被验收脚本误判为失败
|
||||
|
||||
## 现象
|
||||
|
||||
第14轮真实 UI(schema 30,`dev@339e871`)在 **UI-11** 失败:页面上传附件并发送「请将此附件归档」后,相邻助手卡片已快速处于 `completed`(文案:已收录补充材料并关联黑板)。
|
||||
|
||||
`waitForSquadCompletion` 默认 `requireInflight=true`,用 Playwright `toHaveAttribute` 硬等 `pending|streaming_status|auto_retrying` 60 秒。收到的属性已是 `completed`,被当成 unexpected value,60s 后 FAIL。产品终态成功,验收误判。
|
||||
|
||||
## 根因分析
|
||||
|
||||
| 层 | 问题 | 后果 |
|
||||
|---|---|---|
|
||||
| 验收契约 | `requireInflight !== false` 默认为必须先看到处理中 | 快路径成功被 60s 超时打死 |
|
||||
| Playwright 匹配 | `toHaveAttribute` 对已是 `completed` 的节点持续重试同一错误匹配 | 日志里 123 次 resolved 到 completed 仍等 inflight |
|
||||
| UI-03 先例 | 已用 `{ requireInflight: false }` 避开同类竞态 | UI-11 未沿用,默认仍硬等 |
|
||||
| 真实性 | 现场助手无错误、用户句与相邻卡片对应、上传已走 freeform | 不得放宽上传/对应关系/终态/无错误,只改观测顺序 |
|
||||
|
||||
证据 `error-context.md`:Locator 命中 `data-chat-status="completed"`,Expected `/pending|streaming_status|auto_retrying/`。
|
||||
|
||||
## 严重度
|
||||
|
||||
`high`
|
||||
|
||||
真实成功轮次被脚本误杀,阻断后续 UI-12+。
|
||||
|
||||
## 关联整改
|
||||
|
||||
- Remediation: [../remediation/2026-09-13-document-revision-fast-completion-observation.md](../remediation/2026-09-13-document-revision-fast-completion-observation.md)
|
||||
- Short-term: [../ops/short-term/2026-09-13-document-revision-fast-completion-observation.md](../archive/ops/2026-09-13-document-revision-fast-completion-observation.md)
|
||||
- 分支: `fix/document-revision-fast-completion-observation`
|
||||
|
||||
## 证据
|
||||
|
||||
- 失败证据(只读,不得改/移/删/提交):`.doc/test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui11-fast-completion-observation-failure/`
|
||||
|
||||
## 开放问题
|
||||
|
||||
- 本轮不重跑真实 UI-11;不得标 E2E 通过或任务 `done`
|
||||
- 处理中状态仅作可选观测,不作为成功必要条件
|
||||
@@ -0,0 +1,105 @@
|
||||
---
|
||||
title: "文档修改、版本差异与智能体变更说明能力缺口分析"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
severity: high
|
||||
---
|
||||
|
||||
# 文档修改、版本差异与智能体变更说明能力缺口分析
|
||||
|
||||
## 1. 结论
|
||||
|
||||
系统已有受控文档生命周期、编辑租约、正文 SHA-256、审计日志、智能体变更提案、自由文档版本表和阶段通知 Outbox,可作为本能力的基础;但当前尚不存在可信的“受控文档版本库”。受控正文仍以工作区单个 `output.md` 为事实源,人工或智能体更新会覆盖现状,无法复原任一历史正文,也无法可靠回答“谁在何时基于哪个智能体版本改了什么”。
|
||||
|
||||
本需求不能通过前端缓存一份旧正文后做颜色标记来完成。必须把不可变正文快照、以智能体生成为边界的版本周期、每次已提交人工修改、精确 diff、智能体变更报告和负责人通知放入同一个服务端一致性模型。
|
||||
|
||||
## 2. 用户规则的确定性解释
|
||||
|
||||
用户描述中的“版本以智能体修改为准”按以下语义实现:
|
||||
|
||||
1. 模板或一次成功提交的智能体/智能体小队产物,是一个版本周期的 `baseline`。
|
||||
2. 此后所有人工保存都形成该版本下的 `revision`,改变当前 `head`,但不增加面向用户的版本号。
|
||||
3. 下次智能体基于当时的 `head` 生成成功后,旧版本以该 `head` 封存;智能体输出成为新版本的 `baseline`。
|
||||
4. “人工修改标记”永远计算为当前版本 `baseline → head`。智能体新版本生效后该标记归零,后续只显示相对新 baseline 的人工修改。
|
||||
5. 两个版本的默认比较使用各版本的最终内容:已封存版本取 `sealed_head`,当前开放版本取实时 `head`;智能体自身的改动单独用“上一版本最终内容 → 新版本 baseline”表达。
|
||||
|
||||
该解释既满足“模板/上一次智能体生成 + 下一次智能体生成前人工修改为一个版本”,也不会把每次自动保存误展示成一个正式版本。
|
||||
|
||||
## 3. 已确认的现有基础
|
||||
|
||||
| 能力 | 当前证据 | 可复用部分 |
|
||||
|---|---|---|
|
||||
| 受控文档元数据 | `deploy/postgres/goose/00001_baseline.sql:230-280` | `document_records`、三权、状态、当前 SHA、版本号 |
|
||||
| 编辑互斥 | `internal/docgov/lease.go:41-180` | human/squad 租约、心跳和忙状态 |
|
||||
| 人工保存入口 | `internal/docgov/lease.go:290-360` | 编制人/状态校验与 `expected_sha256` 乐观锁 |
|
||||
| 智能体修改授权 | `internal/docgov/engine.go:448-577`、`internal/bizdev/service.go:451-538` | 已认领文档先提案、编制人裁决 |
|
||||
| 智能体执行归属 | `internal/squad/models.go:35-95,216-226` | 小队角色、步骤、manifest 与工作区信息 |
|
||||
| 自由文档版本 | `internal/freedoc/service.go:416-535` | 事务、`FOR UPDATE`、每次保存快照与 If-Match |
|
||||
| 文档血缘 | `deploy/postgres/goose/00010_2026-09-11-project-workflows-and-lineage.sql:66-84` | 上下游文档版本、哈希和 stale 传播 |
|
||||
| 可靠通知基础 | `deploy/postgres/goose/00018_2026-09-12-outbox-notifications-stage-advance.sql`、`internal/notification/service.go` | Outbox、用户通知、去重键 |
|
||||
| 右侧块编辑器 | `web/src/components/doc/BlockRenderer.tsx`、`BlockEditorModal.tsx` | 块级阅读、编辑、批注和右侧栏布局 |
|
||||
|
||||
## 4. 已确认缺口
|
||||
|
||||
| ID | 缺口 | 当前证据 | 后果 |
|
||||
|---|---|---|---|
|
||||
| DOCREV-01 | 受控正文没有不可变历史快照 | `ReadDocumentContent` 只读取当前工作区 `output.md`;`document_records.version` 没有对应的受控版本表 | 不能查看旧版本、恢复证据或验证历史哈希 |
|
||||
| DOCREV-02 | 人工保存只覆盖文件和当前哈希 | `SaveDocumentContent` 写 `output.md` 后更新 `document_records`,不增加版本/修订记录;数据库错误还被忽略 | 无法记录具体修改人和前后正文;文件与 DB 可分裂 |
|
||||
| DOCREV-03 | 前端块编辑尚未持久化 | `handleSaveBlockEdit` 只修改 React `docCache`;`saveDocumentContent` 没有调用者;编辑弹窗把修改人硬编码为“张工” | 刷新丢失、归属不可信、展示与服务端不一致 |
|
||||
| DOCREV-04 | 智能体完成只更新当前哈希 | `internal/bizdev/service.go:694-705` 只调用 `SetDocumentWorkDir` 和 `MarkDocumentContentUpdated` | 不能把 run、输入快照、输出快照和版本关联 |
|
||||
| DOCREV-05 | 现有提案不是实际 diff | `service.go:499-502` 在智能体执行前写入通用文案,未绑定真实 before/after | 不能作为生成完成后的改动摘要、风险或影响证据 |
|
||||
| DOCREV-06 | 块锚点不稳定 | `markdownToBlockAST` 每次解析使用随机 `blk_*` ID | 刷新或换版本后不能稳定定位修改块、批注和 diff |
|
||||
| DOCREV-07 | 自由文档“每次保存一个版本”与本需求语义不同 | `freedoc.UpdateDocument` 每次正文变化都 `current_version_id + 1` | 同一右侧栏内“版本”概念不一致,自动保存会制造版本噪声 |
|
||||
| DOCREV-08 | 通知只覆盖阶段推进 | `notification/types.go` 只有 stage-ready 类型;前端仅 `StageAdvanceBanner` 消费 | 文档负责人不会收到智能体版本摘要、风险和影响 |
|
||||
| DOCREV-09 | 内容修改链路的一致性和授权边界不足以支撑审计 | 租约 API 接受客户端 holder type/id;部分 DocGov 入口只认证后直接调用领域引擎;当前锁主要是进程内 mutex | 多实例、伪造 holder、并发提交时可能发生越权或静默覆盖 |
|
||||
|
||||
## 5. 根因分析
|
||||
|
||||
### 5.1 “当前文档”同时承担事实源、工作副本和历史版本
|
||||
|
||||
`document_records` 的 `version` 和 `content_sha256` 只是当前指针;`output.md` 同时被智能体工作区、人工编辑和读取 API 使用。缺少 immutable snapshot 后,审计日志只能证明发生过一个动作,不能证明动作前后内容。
|
||||
|
||||
### 5.2 版本、修订、生命周期三种概念没有拆开
|
||||
|
||||
- 智能体生成版本:本需求要求的业务版本边界;
|
||||
- 人工保存修订:高频、可聚合展示,但必须逐次留痕;
|
||||
- 送审/批准快照:生命周期冻结点。
|
||||
|
||||
当前单个 `version` 整数无法同时表达三者,继续叠加字段会导致比较对象含糊。
|
||||
|
||||
### 5.3 UI 的 Block AST 是临时视图,不是稳定编辑协议
|
||||
|
||||
Markdown 每次解析都会重新生成随机块 ID;编辑 metadata 由浏览器填写,既不能作为服务端身份,也无法跨快照追踪。需要由服务端产生稳定 block map,并由 immutable snapshot 保存。
|
||||
|
||||
### 5.4 智能体说明与确定性事实没有分层
|
||||
|
||||
智能体适合解释“为什么改、有哪些风险”,但真实增删内容必须由服务端 diff 得出,上下游影响必须由工作流/血缘图计算,风险等级也不能允许模型自行降级。当前变更提案把三者都存为自由文本,且没有版本关联。
|
||||
|
||||
## 6. 严重度
|
||||
|
||||
`high`
|
||||
|
||||
该能力尚未对外承诺为已实现,因此不是现有数据破坏事件;但若仅增加 UI 高亮便宣称完成,会形成错误审计证据,并在多人/多智能体协作下引入静默覆盖、错误归属和不完整通知。
|
||||
|
||||
## 7. 设计边界
|
||||
|
||||
- 受控工作流文档与自由文档继续使用各自权限/生命周期策略;只共享底层快照、修订和 diff 能力。
|
||||
- Markdown 正文为规范化内容真源,Block AST 是带稳定映射的编辑/展示投影,避免双真源。
|
||||
- 未保存的浏览器按键不属于审计记录;每次服务端成功提交才是 revision。
|
||||
- 批注、审核意见与正文修改是不同事件,不混入人工正文高亮。
|
||||
- 已批准内容不可原地修改;后续修改必须经受控变更/驳回回编制流程创建新工作周期。
|
||||
|
||||
## 8. 关联整改
|
||||
|
||||
- System design: [../system-design/document-revision-management.md](../system-design/document-revision-management.md)
|
||||
- Remediation: [../remediation/2026-09-13-document-revision-management-implementation-plan.md](../remediation/2026-09-13-document-revision-management-implementation-plan.md)
|
||||
- Short-term: [../ops/short-term/2026-09-13-document-revision-management-design.md](../archive/ops/2026-09-13-document-revision-management-design.md)
|
||||
|
||||
## 9. 开放问题
|
||||
|
||||
方案给出推荐默认值,等待评审时确认:
|
||||
|
||||
1. 高/严重风险的智能体候选是否一律要求编制负责人再次确认后才成为新版本(推荐:是)。
|
||||
2. 首期是否同时迁移自由文档到“智能体版本 + 人工修订”语义(推荐:底层统一,UI 第二波启用)。
|
||||
3. 历史快照默认保留期限(推荐:受控文档随项目/法规保留策略;自由文档默认 365 天且可配置,不做静默硬删除)。
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
title: "UI-07 纯净阅读用 overlay/class*block 找不到真实块"
|
||||
status: in_progress
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
severity: high
|
||||
---
|
||||
|
||||
# UI-07 纯净阅读用 overlay/class*block 找不到真实块
|
||||
|
||||
## 现象
|
||||
|
||||
第八轮真实 UI(schema 30):
|
||||
|
||||
- UI-00~UI-06 **PASS**(UI-06 `r0→r1` 且硬刷新持久)
|
||||
- UI-07 `captureOverlayFingerprint(mode=pure)` 抛 `no block to sample computed style`
|
||||
|
||||
## 根因分析
|
||||
|
||||
| 层 | 问题 |
|
||||
|---|---|
|
||||
| DOM | `BlockRenderer` 真实块是 `data-testid=document-block` 的 generic wrapper;无 `class` 含 `block` |
|
||||
| overlay | `data-overlay-kind` 仅在 `overlayMode !== 'pure'` 且 hunk 命中时出现;纯净阅读该属性不存在 |
|
||||
| 脚本 | pure 取样 `[data-overlay-kind], [class*="block"]`;manual/all 全页 `[data-overlay-kind]`,未限定活动文档 |
|
||||
|
||||
`ManualChangeOverlay` 只是工具条 hint,不是块装饰。块装饰是同一 wrapper 上的 inline style。
|
||||
|
||||
同一 human hunk 在 manual/all 都是琥珀底,产品不保证两两不同。Checklist:UI-07 无装饰、UI-08 琥珀标记、失败标准是「三 overlay 视觉无差异」,不是强制 manual≠all。
|
||||
|
||||
## 严重度
|
||||
|
||||
`high`
|
||||
|
||||
## 关联整改
|
||||
|
||||
- Short-term: [../ops/short-term/2026-09-13-document-revision-e2e-overlay-selector.md](../archive/ops/2026-09-13-document-revision-e2e-overlay-selector.md)
|
||||
- 分支: `fix/document-revision-e2e-overlay-selector`
|
||||
|
||||
## 证据
|
||||
|
||||
- Evidence root(已归档、本轮勿提交):`.doc/test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui07-pure-selector-failure/`
|
||||
|
||||
## 开放问题
|
||||
|
||||
- 占槽后真实 UI-07/08/09 重跑;本任务保持 `in_progress`,不得标 `done`
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
title: "UI-07 在 CSS transition 中间帧采样纯净阅读"
|
||||
status: in_progress
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
severity: high
|
||||
---
|
||||
|
||||
# UI-07 在 CSS transition 中间帧采样纯净阅读
|
||||
|
||||
## 现象
|
||||
|
||||
第九轮真实 UI(schema 30):
|
||||
|
||||
- UI-00~UI-06 **PASS**
|
||||
- 切到纯净阅读后,全部 `data-overlay-kind` 已空
|
||||
- 取样到 `background rgba(51,41,15,0.294)`、`boxShadow` alpha `.294` / 位移 `.589549px`
|
||||
- 断言「纯净阅读必须无装饰」FAIL
|
||||
|
||||
## 根因分析
|
||||
|
||||
| 层 | 问题 |
|
||||
|---|---|
|
||||
| 产品 | `BlockRenderer` 块 wrapper 有 `transition: background/box-shadow 0.2s ease` |
|
||||
| 脚本 | 上一轮去掉 `waitForTimeout(400)` 后,overlay 响应与 `data-overlay-kind` 清空即采样 |
|
||||
| 时序 | 属性已达终态,computed style 仍是琥珀→透明的中间帧 |
|
||||
|
||||
这是 **采样过早**,不是纯净模式仍保留装饰。禁止禁用产品 transition,也禁止放宽无装饰断言。
|
||||
|
||||
## 严重度
|
||||
|
||||
`high`
|
||||
|
||||
## 关联整改
|
||||
|
||||
- Short-term: [../ops/short-term/2026-09-13-document-revision-e2e-overlay-transition.md](../archive/ops/2026-09-13-document-revision-e2e-overlay-transition.md)
|
||||
- 分支: `fix/document-revision-e2e-overlay-transition`
|
||||
|
||||
## 证据
|
||||
|
||||
- Evidence root(已归档、本轮勿提交):`.doc/test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui07-css-transition-sampling-failure/`
|
||||
|
||||
## 开放问题
|
||||
|
||||
- 占槽后真实 UI-07/08/09 重跑;本任务保持 `in_progress`,不得标 `done`
|
||||
@@ -0,0 +1,51 @@
|
||||
---
|
||||
title: "UI-05a 未打开待确认报告导致确认按钮缺失"
|
||||
status: in_progress
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
severity: high
|
||||
---
|
||||
|
||||
# UI-05a 未打开待确认报告导致确认按钮缺失
|
||||
|
||||
## 现象
|
||||
|
||||
第四轮真实 UI(schema 30)**UI-05a 首个失败**:
|
||||
|
||||
- UI-00~05 PASS;**UI-05a** 抛 `confirm button missing for pending high-risk candidate`
|
||||
- 工具条已显示「待确认 high」与「待确认报告」
|
||||
- 助手气泡写明候选 #91、变更报告 91、风险 high、状态 `pending_author_confirmation`
|
||||
- 页面仍挂着 **首轮** `dialog「变更报告」`:风险 **low** / `fallback`,无 `change-report-pending-actions`,无「确认提交」
|
||||
- 脚本用全局 `getByRole('button', { name: /确认提交/ }).count()` 判定,未先点「待确认报告」
|
||||
|
||||
项目 `UI验收-超声微创系统-mu00igjt`,文档 `doc_proj6119_intake`,首轮报告 `change-reports/90`,pending 候选/报告 `#91`。
|
||||
|
||||
## 根因分析
|
||||
|
||||
| 层 | 问题 |
|
||||
|---|---|
|
||||
| UI-04 关闭 | `ChangeReportPanel` 只有弹窗内「关闭」;**没有 Escape 处理**。`page.keyboard.press('Escape')` 被 `.catch` 吞掉,首轮 low 报告 `reportId` 仍打开 |
|
||||
| 产品条件 | `pendingDecision`(确认/拒绝)仅当 `reportId === pending_change_report_id` 才注入。首轮报告 90 ≠ pending 91,弹窗里不会出现「确认提交」 |
|
||||
| UI-05a | 未模拟真实用户点击「待确认报告」并等待 `change-report-panel`;只用全局 count,错过必须打开 pending 报告的路径 |
|
||||
|
||||
产品确认/拒绝逻辑本身未坏;失败来自验收脚本未走真实面板路径。本轮**禁止改产品业务逻辑**。
|
||||
|
||||
## 严重度
|
||||
|
||||
`high`
|
||||
|
||||
## 关联整改
|
||||
|
||||
- Short-term: [../ops/short-term/2026-09-13-document-revision-e2e-pending-flow.md](../archive/ops/2026-09-13-document-revision-e2e-pending-flow.md)
|
||||
- 分支: `fix/document-revision-e2e-pending-flow`
|
||||
|
||||
## 证据
|
||||
|
||||
- Evidence root(勿删、勿提交本轮):`.doc/test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui05a-pending-report-selection-failure`
|
||||
- Playwright:`playwright-output/document-revision-runtime--91599-andidate-→-version-advances-chromium/error-context.md`
|
||||
- 结果:`ui-acceptance-results.json`(UI-04 PASS 131ms,打开 `/change-reports/90`;UI-05 PASS;UI-05a 未写入 PASS)
|
||||
|
||||
## 开放问题
|
||||
|
||||
- 占槽后真实 UI-05a/05b 重跑;本轮不操作容器、不重跑 E2E
|
||||
- 脚本收紧后状态仍为 `in_progress`,真实重跑前不得 `done`
|
||||
@@ -0,0 +1,47 @@
|
||||
---
|
||||
title: "首次生成 PG ID 未同步计数器导致 baseline 被误删"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-14
|
||||
severity: critical
|
||||
---
|
||||
|
||||
# 首次生成 PG ID 未同步计数器导致 baseline 被误删
|
||||
|
||||
## 现象
|
||||
|
||||
第19轮真实 UI(schema 31,项目 `6158` / `doc_proj6158_intake`):小队输出、baseline snapshot=249、version=217、**candidate id=175**、**output snapshot id=250**、**report id=175** 均已落库,candidate 保持 `ready`,任务失败 `docrevision: not found`(`CommitAgentVersion` 找不到 input snapshot)。不要把 output snapshot 250 误写成 candidate 250。
|
||||
|
||||
## 根因分析
|
||||
|
||||
`openTemplatePGLocked` 把 PostgreSQL `RETURNING id` 写入 `s.snapshots[249]` / `s.versions[217]`,但**不推进** `nextSnapID` / `nextVerID` / `nextEvtID`。
|
||||
|
||||
当进程内计数器已因其它文档 hydration 停在 248 时:
|
||||
|
||||
1. `putSnapshotLocked` 执行 `nextSnapID++` 得到临时 ID **249**,覆盖真实 baseline;
|
||||
2. `persistAgentCandidateLocked` 把输出重映射到 250 后 `delete(s.snapshots, 249)`,误删 baseline;
|
||||
3. `CommitAgentVersion` 按 `InputSnapshotID=249` 查找 → `ErrNotFound`;
|
||||
4. 任务失败,candidate 仍 `ready`(不得伪装成功)。
|
||||
|
||||
同类无条件 `delete(map, oldID)` 也存在于 version / event / report / candidate 持久化路径。
|
||||
|
||||
## 严重度
|
||||
|
||||
`critical`
|
||||
|
||||
## 关联整改
|
||||
|
||||
- Remediation: [../remediation/2026-09-13-document-revision-pg-id-remap.md](../remediation/2026-09-13-document-revision-pg-id-remap.md)
|
||||
|
||||
## 证据
|
||||
|
||||
- 失败归档(只读,不改不删):`.doc/test-reports/assets/2026-09-13-document-revision-runtime-ui/schema31-round19-ui03-advisor-briefing-docrevision-not-found/`
|
||||
- Playwright:`squad observation rejected: error_terminal:failed`
|
||||
|
||||
## 开放问题
|
||||
|
||||
- 无(本缺陷)。Round20 已在项目 6159 重跑 UI-03 PASS。Round19 归档不删。
|
||||
|
||||
## 关闭记录
|
||||
|
||||
工程修复合入 `dev@b258ab8`。验收:[../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md](../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md)。
|
||||
@@ -0,0 +1,52 @@
|
||||
---
|
||||
title: "post-restart 断言了已过期的 UI-06 正文 marker"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-14
|
||||
severity: high
|
||||
---
|
||||
|
||||
# post-restart 断言了已过期的 UI-06 正文 marker
|
||||
|
||||
## 现象
|
||||
|
||||
第二次真实 post-restart(schema 31):login、项目、受控文档、`revision-state` 200、`V3`/`r2`、正文均已恢复。失败只因:
|
||||
|
||||
```
|
||||
getByText('UI06-mu0eq020') → element(s) not found
|
||||
```
|
||||
|
||||
`phase-state.json` 仍写 `bodySnippet=UI06-mu0eq020`,而 UI-13b A1 成功保存后最终持久正文是 `A1-win-*`。
|
||||
|
||||
## 根因分析
|
||||
|
||||
| 层 | 问题 |
|
||||
|---|---|
|
||||
| UI-06 | 硬刷新后把当时 marker 写入 `phase-state.bodySnippet` |
|
||||
| UI-13b | A1 2xx 保存并断言 `markerA1` 可见;A2 409 冲突稿留在编辑器。未回写最终持久正文 |
|
||||
| UI-15-pre | 更新了 `versionText`/`revisionText`,但 `...st` 原样带上过期 snippet |
|
||||
| post-restart | 正确坚持断言 `st.bodySnippet` 可见,于是用旧 marker 对照新正文 FAIL |
|
||||
|
||||
产品恢复链已成立;这是 **测试状态链过期**,不是账本丢失。
|
||||
|
||||
## 严重度
|
||||
|
||||
`high`
|
||||
|
||||
## 关联整改
|
||||
|
||||
- Short-term: [../ops/short-term/2026-09-13-document-revision-post-restart-final-snippet.md](../archive/ops/2026-09-13-document-revision-post-restart-final-snippet.md)
|
||||
- 分支: `fix/document-revision-post-restart-final-snippet`
|
||||
|
||||
## 证据
|
||||
|
||||
- 失败归档(只读):`.doc/test-reports/assets/2026-09-13-document-revision-runtime-ui/schema31-postrestart-stale-body-snippet-failure/`
|
||||
- `phase-state.json`:`controlledDocId=doc_proj6157_intake`,`V3`/`r2`,`bodySnippet=UI06-mu0eq020`
|
||||
|
||||
## 开放问题
|
||||
|
||||
- 无(本缺陷)。Round20 `bodySnippet=A1-win-mu0gwiez`,post-restart PASS。失败归档不删。
|
||||
|
||||
## 关闭记录
|
||||
|
||||
[../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md](../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md)
|
||||
@@ -0,0 +1,50 @@
|
||||
---
|
||||
title: "post-restart 项目名同时命中顶栏与侧栏"
|
||||
status: in_progress
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
severity: high
|
||||
---
|
||||
|
||||
# post-restart 项目名同时命中顶栏与侧栏
|
||||
|
||||
## 现象
|
||||
|
||||
第18轮真实 UI(schema 31):main **18 PASS / 0 FAIL**。宿主重启 app 后 `UI_PHASE=post-restart` 在页面**已经恢复项目**时失败,尚未走到 `revision-state`。
|
||||
|
||||
```
|
||||
strict mode violation: getByText('UI验收-超声微创系统-mu0eq020') resolved to 2 elements:
|
||||
1) getByRole('banner').getByText(...)
|
||||
2) getByTitle(...)
|
||||
```
|
||||
|
||||
失败行:`web/e2e/document-revision-runtime.spec.ts` 原第 626 行。
|
||||
|
||||
## 根因分析
|
||||
|
||||
| 层 | 问题 |
|
||||
|---|---|
|
||||
| DOM | 顶栏 `header`(banner)写「当前项目:」+ 项目名;侧栏 `aside` 会话行 `title`/`span` 再写同一项目名 |
|
||||
| 脚本 | 点击用 `getByText(..., { exact: false }).first()`;恢复断言用页面级 `getByText(项目名)`,strict 下双命中 |
|
||||
| 产物 | `playwright.config.ts` 的 `outputDir` / HTML report 不按 `UI_PHASE` 分目录,第二阶段会覆盖主阶段 trace |
|
||||
| 总账 | `RESULTS_FILE` 固定 `ui-acceptance-results.json`;post-restart `recordPass` 会覆盖 main 的 18 项 |
|
||||
|
||||
这是 **UI 自动化可寻址缺口**,不是项目未恢复。
|
||||
|
||||
## 严重度
|
||||
|
||||
`high`
|
||||
|
||||
## 关联整改
|
||||
|
||||
- Short-term: [../ops/short-term/2026-09-13-document-revision-post-restart-selector.md](../archive/ops/2026-09-13-document-revision-post-restart-selector.md)
|
||||
- 分支: `fix/document-revision-post-restart-selector`
|
||||
|
||||
## 证据
|
||||
|
||||
- 失败归档(只读,不改不删):`.doc/test-reports/assets/2026-09-13-document-revision-runtime-ui/schema31-postrestart-project-title-selector-failure/`
|
||||
- `error-context.md`:项目名同时出现在 banner 与 complementary title
|
||||
|
||||
## 开放问题
|
||||
|
||||
- 本轮不重跑真实 post-restart;不得标 UI-15 通过或任务 `done`
|
||||
@@ -0,0 +1,78 @@
|
||||
---
|
||||
title: "UI-11 prelim_design 缺 output.md 导致 TASK_INTERRUPTED"
|
||||
status: in_progress
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
severity: high
|
||||
---
|
||||
|
||||
# UI-11 prelim_design 缺 output.md 导致 TASK_INTERRUPTED
|
||||
|
||||
## 现象
|
||||
|
||||
第11轮真实 UI(schema 30,`dev@2a58674`):
|
||||
|
||||
- Prompt 正确 POST **202**,`task_key=prelim_design`
|
||||
- 旧 intake 未再 DOC_BUSY
|
||||
- 小队终态 `TASK_INTERRUPTED` / `task_failed`
|
||||
- 页面:`step step_01_draft missing target deliverable output.md` · `run_1789325979820025769`
|
||||
|
||||
## 现场时序(只读 workspace / execution.log / trace)
|
||||
|
||||
工作区:`data/dev/workspaces/bizdev/prelim_design_1789325982486234431/tasks/01_draft/execution.log`
|
||||
|
||||
1. MiniMax **第一次已流出** `write(/app/data/workspaces/.../tasks/01_draft/output.md, content=...)` 的 `toolCall`
|
||||
2. **同一条** assistant message:`stopReason=error`,`errorMessage=terminated` → 工具未执行,磁盘无 `output.md`
|
||||
3. SDK `auto_retry_start` attempt 1–3 均为 `Connection error.`
|
||||
4. `auto_retry_end success=false`,`finalError=Connection error.`
|
||||
5. 随后仍有 `agent_settled`
|
||||
6. 同文件头却写 `Outcome: SUCCESS` / `Error: None`
|
||||
7. 工作区 `trace.jsonl`:`step_01_draft success=true`,`output_digest=e3b0c442...`(空 SHA)
|
||||
8. PI 子进程退出 0,runner 对上层呈成功;服务端最后因 `output.md` 不存在才失败
|
||||
|
||||
**禁止**从该 `write` 参数(可能截断)拼正文或补写 `output.md`。
|
||||
|
||||
## 根因分层
|
||||
|
||||
必须区分外部瞬时故障与产品韧性缺口,二者同时成立:
|
||||
|
||||
| 层 | 性质 | 证据 | 问题 |
|
||||
|---|---|---|---|
|
||||
| MiniMax / PI SDK | **外部 provider 瞬时故障** | 同 message `terminated`;SDK 三次 `Connection error`;`auto_retry_end success=false` | 流式 `write` 未落地;in-process 重试耗尽 |
|
||||
| 模板 | 产品前置条件 | `.dockerignore` 的 `*.md` 把 `templates/docs/*.md` 排除出 build context;即使 `COPY templates /app/templates`,镜像内仍无官方稿,`GetDocTemplate` 失败后 `workspace.go` 回落两段 stub「待确认」 | writer 被迫一次性超长 `write`,拉长流式窗口 |
|
||||
| `runner.mjs` | **产品韧性缺口** | `agent_settled` 后文件头 `Outcome: SUCCESS` | 把 settle 当成成功;进程 0 ≠ 产物存在 |
|
||||
| Go `runOneStep` / `AppendTrace` | **产品韧性缺口** | `trace.jsonl` `success=true` + 空 digest | 以 backend `Success` / 进程 0 入账,未按目标文件 fail-closed,也未对瞬时失败做**全新 step invocation** |
|
||||
| 映射 | 产品契约 | 绝对路径 / `./` / 重复 `tasks/01_draft/output.md` | 即使 write 落地,旧映射也可能认不到 |
|
||||
|
||||
app 日志:`taskrun_status_transition run_id=run_1789325979820025769 error="step step_01_draft missing target deliverable output.md"`。
|
||||
|
||||
## 成功判定契约(本轮补齐)
|
||||
|
||||
- `agent_settled` 在 `auto_retry_end success=false` / `terminated` / `Connection error` 之后 **不是** 成功
|
||||
- 进程退出 0 **不是** 成功
|
||||
- 目标文件缺失或空 **不是** 成功
|
||||
- 不得执行/回放可能截断的 `write` 参数
|
||||
- **瞬时**(provider 信号或 runner `retryable`):有界 **全新** `backend.Execute`(默认 1+1),最终仍 fail-closed
|
||||
- **永久**(干净 settle 后缺产物、`prompt_empty`、`unauthorized`、治理拦截):不得重试
|
||||
|
||||
## 严重度
|
||||
|
||||
`high`
|
||||
|
||||
## 关联整改
|
||||
|
||||
- Remediation: [../remediation/2026-09-13-document-revision-prelim-output.md](../remediation/2026-09-13-document-revision-prelim-output.md)
|
||||
- Short-term: [../ops/short-term/2026-09-13-document-revision-prelim-output.md](../archive/ops/2026-09-13-document-revision-prelim-output.md)
|
||||
- 分支: `fix/document-revision-pi-runner-module`(由 `dev@55a4f39` 检出;前序 `fix/document-revision-prelim-output` 已合入)
|
||||
|
||||
## 证据
|
||||
|
||||
- Evidence root(已归档、本轮勿改勿提交):`.doc/test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui11-prelim-design-missing-output-failure/`
|
||||
- Workspace(只读):`data/dev/workspaces/bizdev/prelim_design_1789325982486234431/`
|
||||
|
||||
## 开放问题
|
||||
|
||||
- 占槽后真实 UI-11 重跑;本任务保持 `in_progress`,不得标 `done`
|
||||
- 本轮不执行 `env-service` 重建;Dockerfile / `.dockerignore` 已按 `/app/templates/docs` 读路径修好并做 context 实测。占槽后的镜像重建才带进运行中的 dev 容器
|
||||
- Go 侧必须能在**旧 runner 假成功**时靠 `execution.log` 识别瞬时失败并全新重试;仅修 runner 假成功只会更早 FAIL,不会单独提高成功率
|
||||
- **热修(dev@55a4f39 重建后)**:`deploy/pi-agent/Dockerfile` 只 COPY 了 `runner.mjs`,未 COPY `settle-policy.mjs`;`shuimu-pi-agent-dev` 因 `ERR_MODULE_NOT_FOUND file:///app/settle-policy.mjs` 重启循环。app 侧 `/app/templates/docs` 与 configs 已正常。
|
||||
@@ -0,0 +1,48 @@
|
||||
---
|
||||
title: "质量门禁自污染与 auto_repair 未启用导致 quality_failed"
|
||||
status: in_progress
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
severity: high
|
||||
---
|
||||
|
||||
# 质量门禁自污染与 auto_repair 未启用导致 quality_failed
|
||||
|
||||
## 现象
|
||||
|
||||
同一整改范围真实 run(与 SSE/幂等现场同源):
|
||||
|
||||
- workspace=`data/dev/workspaces/bizdev/intake_1789308825666278807`
|
||||
- run 于 **14:17:51** 结束为 **`quality_failed`**(仅 1 个 `task_runs`)
|
||||
- 质量门禁事件:**score=40**,命中 `不做展开` / `篇幅有限` / `从略`
|
||||
- `output.md` **第204行**终稿自检表:`无"不做展开""从略""篇幅有限"等敷衍套话` → 门禁 `strings.Contains` **自污染误报**
|
||||
- 请求体未带 `auto_repair`;虽存在 `EnsureQualityOrRepair`,实际 **maxRetries=0**
|
||||
- chat_messages 同 `client_turn` 两对(1131/1132 正常;1133/1134 重连误写)——与 SSE 幂等缺陷同源,另案处理
|
||||
|
||||
## 根因
|
||||
|
||||
| 项 | 说明 |
|
||||
|---|---|
|
||||
| A | 修复预算依赖客户端 `auto_repair`(浏览器可省略,默认 false) |
|
||||
| B | 生成指令与自检表原样引用禁词;检测无否定/元语境豁免 |
|
||||
| C | FE 将 `quality_failed` 映射为 `completed`,并在断线 catch 路径同步受控文档 |
|
||||
| D | 缺真实失败形态单测 |
|
||||
|
||||
## 整改(同分支 `fix/document-revision-sse-idempotency`)
|
||||
|
||||
- A:小队 `repairBudget` 只认 `AutoRepair`;bizdev 在解析出 `docID`+`docRec` 后强制开启;受控 HTTP `task_run_handlers` 仍设 `true`。小队 `Success` 仅表示执行完成,投影/阶段停链看 `QualityReport`
|
||||
- B:prompt 去原词;豁免仅限同一自检/规则行且同时具备 meta marker + 否定紧邻或引号引用(禁止 48 字窗口遇「无」即放过)
|
||||
- C:`TerminalStatus` 优先 quality;Materialize 仅 `Passed`;FE `quality_failed` 独立失败态且不同步激活
|
||||
- D:现场 L204 / repair budget / TerminalStatus / FE 映射单测
|
||||
- **E(投影边界)**:`finalizeSquadDeliverable` 在任何 `SetDocumentWorkDir` / `Materialize` / `MarkDocumentContentUpdated` / 完成活动之前按 `QualityReport.Passed=false` 短路;保留隔离工作区与失败摘要;正式 `work_dir`/head/hash/候选不变。单测:`TestFinalizeSquadDeliverable_QualityFailed_NoDocProjectionSideEffects`(敌意 `Success=true`)
|
||||
- **F(阶段链)**:`ExecuteStage` 在 `err=nil` 后经 `classifyStageTaskHalt` 检查质量/`Success`;失败立即停链,保留失败 artifact,不吸收 ExtractedData、不追加 PriorDoc、不写 completed workspace / 阶段跃迁。单测:`TestExecuteStage_QualityFailed_StopsChainWithoutAbsorbingFactsOrPriorDoc`
|
||||
|
||||
## 证据
|
||||
|
||||
- workspace path 如上;events seq10;output.md:204
|
||||
- assets:[../test-reports/assets/2026-09-13-document-revision-runtime-ui/](../test-reports/assets/2026-09-13-document-revision-runtime-ui/)(勿删)
|
||||
|
||||
## 关联
|
||||
|
||||
- Short-term 扩写:[../ops/short-term/2026-09-13-document-revision-sse-idempotency.md](../archive/ops/2026-09-13-document-revision-sse-idempotency.md)
|
||||
- SSE 幂等审计:[./2026-09-13-document-revision-sse-idempotency.md](./2026-09-13-document-revision-sse-idempotency.md)
|
||||
@@ -0,0 +1,56 @@
|
||||
---
|
||||
title: "UI-03 质量修复子工作区越界改写根 output.md"
|
||||
status: in_progress
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
severity: high
|
||||
---
|
||||
|
||||
# UI-03 质量修复子工作区越界改写根 output.md
|
||||
|
||||
## 现象
|
||||
|
||||
第13轮 Antigravity 完整 UI(schema 30,dev@8b1a531 基线):UI00–02 PASS,UI-03 真实 PI 终态 `quality_failed`,页面 70 分、缺少必填章节「阻塞信息 / 非阻塞信息」。
|
||||
|
||||
真实工作区 `/app/data/workspaces/bizdev/intake_1789329815528283509`:
|
||||
|
||||
- `tasks/03_review/output.md` 于 20:07:02 **确实没有**两个章节;质量门禁判定正确,不得放宽必填章节。
|
||||
- `EnsureQualityOrRepair` 创建 `tasks/repair_1`,TASK.md 同时写「参考 `../../template.md`、基于 `../../output.md`、输出到 `output.md`」。
|
||||
- 真实模型读取父级文件后,`edit` 写了 `tasks/repair_1/../../output.md`(根 `output.md`);根文件 20:07:24 已补齐两章节。
|
||||
- `tasks/repair_1/output.md` **从未生成**;runner 目标仍是本地 `output.md` → `missing target` → `runOneStep` 失败 → `EnsureQualityOrRepair` break → manifest 保留原 70 分。
|
||||
- runner `execution.log` 的 `Outcome: SUCCESS` 只是模型 settle,不代表目标契约成功。
|
||||
|
||||
## 根因分析
|
||||
|
||||
| 层 | 问题 | 后果 |
|
||||
|---|---|---|
|
||||
| TASK 契约 | 修复步骤把输入写成 `../../output.md` / `../../template.md` | 模型按字面去 edit 父级 |
|
||||
| 沙箱 | `buildSubWorkspaces` 对 template/blackboard 建 **symlink** | 子目录写同名文件会打穿父级 |
|
||||
| Needs | 只在 TASK 里列 `../../need`,不把原稿快照成非目标文件名 | 若复制成本地 `output.md` 会假成功;当前则诱导越界 |
|
||||
| 成功判定 | 只认本地 `output.md`(正确),但失败后不恢复被改的根文件 | 根文件「看起来更好」却不覆盖/不重验,页面仍 70 |
|
||||
| 提升谓词(独立审查) | 曾在 `runErr != nil` 或 containment 后仍因 `localOK` 提升 | 截断产物或越界轮次会被当成修复成功 |
|
||||
| settle | 内部 Outcome SUCCESS ≠ 本地目标存在 | 不得把 settle 当交付 |
|
||||
|
||||
`MatchDeliverableRel` 已拒绝 `../`,因此 missing-target fail-closed 正确,**不能**因此把越界根文件当成功。
|
||||
|
||||
## 严重度
|
||||
|
||||
`high`
|
||||
|
||||
自动修复轮空转:模型可能已经写好章节,契约失败导致任务 `quality_failed`。
|
||||
|
||||
## 关联整改
|
||||
|
||||
- Remediation: [../remediation/2026-09-13-document-revision-quality-repair-workspace-contract.md](../remediation/2026-09-13-document-revision-quality-repair-workspace-contract.md)
|
||||
- Short-term: [../ops/short-term/2026-09-13-document-revision-quality-repair-workspace-contract.md](../archive/ops/2026-09-13-document-revision-quality-repair-workspace-contract.md)
|
||||
- 分支: `fix/document-revision-quality-repair-workspace-contract`
|
||||
|
||||
## 证据
|
||||
|
||||
- 失败证据(根代理保留、本轮不得改/移/删/提交):`.doc/test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui03-required-sections-quality-failure/`
|
||||
|
||||
## 开放问题
|
||||
|
||||
- 本轮不跑真实 UI-03;不得标 E2E 通过或任务 `done`
|
||||
- 默认子步骤仍可用 `../../` + symlink(未改正常步骤读本地 context 的路径)
|
||||
- **剩余风险(保护范围)**:containment 只快照/恢复 `output.md` / `template.md` / `blackboard.json`。模型改写其它父级文件(如 `PLAN.md`、其它 `tasks/*`)检测不到、不会回滚。创建/删除这三份受保护输入已计入 mutation。
|
||||
@@ -0,0 +1,50 @@
|
||||
---
|
||||
title: "行动计划表状态列「待续」被质量门禁误判为敷衍"
|
||||
status: in_progress
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
severity: high
|
||||
---
|
||||
|
||||
# 行动计划表状态列「待续」被质量门禁误判为敷衍
|
||||
|
||||
## 现象
|
||||
|
||||
第三轮真实 UI(新用户 `mtzzliz5`,新项目,真实 MiniMax):
|
||||
|
||||
- UI-00~02 PASS;**UI-03** 两轮 auto-repair 后 **`quality_failed` 80/100**
|
||||
- workspace=`intake_1789314411395330821`
|
||||
- `manifest.prohibited_phrases` 仅 **「待续」**
|
||||
- `output.md` 第163–164 行与 `repair_1` / `repair_2` 对应行均为行动计划表状态单元格,而非省略正文:
|
||||
|
||||
```text
|
||||
| **待续** | 合规专员基于用户补充材料... | 合规专员 | D-01至D-07全部确认后 |
|
||||
| **待续** | 组织专员编制里程碑规划与检测排期方案... | 组织专员 | 合规评估完成后 |
|
||||
```
|
||||
|
||||
表头为 `| 阶段 | 行动项 | 负责方 | 触发条件 |`,节标题为「下一步行动建议」。泛化修复提示未能让模型改掉结构化状态词,造成真实假阳性。
|
||||
|
||||
## 根因分析
|
||||
|
||||
`containsProhibitedUsage` 对禁词「待续」做全文命中;既有豁免只覆盖自检/规则行的否定或引号引用。行动计划表把「待续」用作**独立阶段状态**(与「立即」并列),不是「后续章节待续」式正文省略。门禁无法区分结构,扣 20 分后触发无效 auto-repair。
|
||||
|
||||
审查补强:豁免必须按表头把命中列对齐到「阶段/状态/进度」;动作/负责方/触发条件按表头索引取值。负责方或触发条件单元格为「待续」不得豁免。
|
||||
|
||||
## 严重度
|
||||
|
||||
`high`
|
||||
|
||||
## 关联整改
|
||||
|
||||
- Short-term: [../ops/short-term/2026-09-13-document-revision-quality-context.md](../archive/ops/2026-09-13-document-revision-quality-context.md)
|
||||
- 分支: `fix/document-revision-quality-context`
|
||||
- 前序自污染豁免不得回退:[./2026-09-13-document-revision-quality-gate-self-pollution.md](./2026-09-13-document-revision-quality-gate-self-pollution.md)
|
||||
|
||||
## 证据
|
||||
|
||||
- Evidence root(勿删、勿提交本轮):`.doc/test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui03-quality-status-false-positive`
|
||||
- 只读 workspace:`data/dev/workspaces/bizdev/intake_1789314411395330821`
|
||||
|
||||
## 开放问题
|
||||
|
||||
- 占槽后真实 UI-03 重跑;本轮不操作容器、不改 E2E
|
||||
@@ -0,0 +1,82 @@
|
||||
---
|
||||
title: "项目 reviewer 未同步到受控文档职责"
|
||||
status: in_progress
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
severity: critical
|
||||
---
|
||||
|
||||
# 项目 reviewer 未同步到受控文档职责
|
||||
|
||||
## 现象
|
||||
|
||||
第17轮真实 UI(schema 30,`dev@639969f`):UI-00 至 UI-12 PASS。UI-13a 精确职责断言首次暴露产品缺陷:
|
||||
|
||||
- UI-01 页面建项目把 USER_B 的职责下拉设为 `reviewer`
|
||||
- B 登录打开 `doc_proj6145_intake` 权限矩阵时,select `value` / badge `data-doc-role` 实际为 `viewer`
|
||||
- 失败:`reviewer B intake duty select must be reviewer: expected_duty:reviewer;got:viewer`
|
||||
|
||||
现场文档头仍写「编制人: 编制工程师 / 审核人: 审核负责人 / 批准人: 批准负责人」。
|
||||
|
||||
## 根因分析
|
||||
|
||||
只读查本轮 `project 6145`(不暴露账号密码/token):
|
||||
|
||||
| 层 | 证据 | 后果 |
|
||||
|---|---|---|
|
||||
| 立项 UI | `CreateProjectModal` 把 B 标成 `reviewer`;默认还勾选 seed `id=3` 李主管 / `id=4` 王总监 | 用户意图是 B=审核人 |
|
||||
| 成员持久化 | `toApiProjectRole` **禁止** author/reviewer/approver,一律映射 `member`;payload 无 document duty | B=`171` 落成 `project_role=member` |
|
||||
| `project_members` | `170` owner(A)、`171` member(B)、`3`/`4` member | 库表无法区分 B 是 reviewer |
|
||||
| 任务生成 | `bizdev.service`:`ReviewerID==0` → **写死 2** +「审核负责人」;`ApproverID==0` → **写死 3** | 与真实成员无关 |
|
||||
| `document_records` | intake / prelim_design 均为 `author_id=170`(恰为创建者 UserID)、`reviewer_id=2`、`approver_id=3` | 第二份文档继承了同一套假职责 |
|
||||
| 列表 API | 原样投影 `reviewer_id=2` | 前端拿到权威但错误的 id |
|
||||
| `resolveCurrentDocRole` | 受控文档按 id 匹配,fail-closed 为 viewer | B=`171` ≠ `2` → viewer;**不是前端提权,是服务端职责丢失** |
|
||||
|
||||
`document_duty_assignments` 只挂官方工作流实例任务,聊天 `TRIGGER_TASK` 生成账本不走该表。
|
||||
|
||||
## 严重度
|
||||
|
||||
`critical`
|
||||
|
||||
项目创建时明确指定的审核人在后续每份受控文档上变成查阅者;写路径虽因 fail-closed 未把 B 提成编制人,但审核职责与权限矩阵验收全部失真。
|
||||
|
||||
## 关联整改
|
||||
|
||||
- Remediation: [../remediation/2026-09-13-document-revision-reviewer-duty-sync.md](../remediation/2026-09-13-document-revision-reviewer-duty-sync.md)
|
||||
- Short-term: [../ops/short-term/2026-09-13-document-revision-reviewer-duty-sync.md](../archive/ops/2026-09-13-document-revision-reviewer-duty-sync.md)
|
||||
- 分支: `fix/document-revision-reviewer-duty-sync`
|
||||
|
||||
## 证据
|
||||
|
||||
- 失败归档(只读,不改不删):`.doc/test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui13a-reviewer-duty-sync-failure/`
|
||||
- `phase-state.json`:`controlledDocId=doc_proj6145_intake`,项目 `UI验收-超声微创系统-mu0bvnp8`
|
||||
- Playwright:`expected_duty:reviewer;got:viewer`
|
||||
|
||||
## 独立审查收紧(同一分支,暂不合入)
|
||||
|
||||
独立审查指出首轮 Heal「已是任意在任成员则保留」会让批准人串位:6145 类场景 `approver=3`(李主管也是成员)而 assigned=`4` 时不应保留 3。项目 `document_duty` 才是权威。
|
||||
|
||||
立项后成员增改/恢复若只发 `project_role`,`document_duty` 会静默失效。更新成员时若省略 `project_role` 且带 `document_duty`,默认 `member` 会把 owner 降级。
|
||||
|
||||
生成/列表路径若吞掉自愈错误,会带着 `reviewer_id=2` 假成功。
|
||||
|
||||
## 最后一轮缺口(已在同分支修复)
|
||||
|
||||
- 移出成员只改 `exited` 不同步文档;前端移出不刷新矩阵
|
||||
- 空 assigned 若保留非成员占位,退出审核人会留在文档上
|
||||
- reviewer→viewer 时人仍 active,generic heal 会把槽位留下,必须按更新前 duty 显式撤销
|
||||
- `CreateOrGetDocument` 错误被 `_` 吞掉会假成功
|
||||
|
||||
## 原子清槽约束(已在同分支修复)
|
||||
|
||||
职责撤销/转移不得在成员 upsert 已提交后再用服务层前后快照做非原子清理。权威路径是同一 DB 事务:`pg_advisory_xact_lock` → 读旧 duty / 冲突 holder → 成员更新 → 精确清 `reviewer_*` / `approver_*`。随后 heal 填新 holder。
|
||||
|
||||
## Heal 与成员写竞态(已在同分支修复)
|
||||
|
||||
`HealProjectDocuments` 若无项目锁、用 pool 先读后写,会出现:heal 读到 reviewer A → 成员事务持锁把 A 清槽并提交为 B → 旧 heal 把 A 写回。现已与成员写共用 `pg_advisory_xact_lock(project_id)`,解析与 `document_records` 更新在同一事务。
|
||||
|
||||
## 开放问题
|
||||
|
||||
- 本轮不重跑真实 UI-13a;不得标 E2E 通过或任务 `done`
|
||||
- **6145 剩余风险**:迁移后 owner 会补 `author`;B(171)当时只落成 `member` 且 `document_duty=''`。服务端不能臆造 reviewer。须再次经成员 API 写入 `document_duty=reviewer` 后,自愈才会把文档从占位 `2` 对齐到 B。
|
||||
- 隔离 PG 集成须用临时库 + `TEST_DATABASE_URL`,见 `scripts/run-isolated-duty-sync-pg-tests.sh`;禁止默认连 `agent_system_dev`
|
||||
@@ -0,0 +1,117 @@
|
||||
---
|
||||
title: "文档版本账本运行时 404 与修订链路失效现场审计"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-14
|
||||
severity: critical
|
||||
# note: Round20 真实 UI PASS 后运行时 404 链路关闭;剩余开放仅为 PI 叙事 fallback 与无关系统 blocker
|
||||
---
|
||||
|
||||
# 文档版本账本运行时 404 与修订链路失效现场审计
|
||||
|
||||
## 现象
|
||||
|
||||
登录项目对话后:
|
||||
|
||||
1. `GET /api/v1/documents/doc-upload-1789263145197-0/revision-state` → **404**,body 含 `docrevision: not found`
|
||||
2. `GET /api/v1/documents/doc_proj143_srs/revision-state` → **404**(同错误)
|
||||
3. UI 工具条显示「版本账本未就绪:docrevision: not found」
|
||||
4. 块双击编辑保存无效(或仅改本地 AST)
|
||||
5. 纯净阅读 / 人工修改 / 全部变更切换无可视效果
|
||||
6. 未重跑智能体小队时看不到变更摘要、风险、项目/文档影响(预期);但即便重跑,当前接线也会写入**静态假 JSON** 而非真实 diff/报告
|
||||
|
||||
## 根因分析(证据)
|
||||
|
||||
### R1 — 账本仅进程内 map,PostgreSQL schema 未真正读写(主因)
|
||||
|
||||
`internal/docrevision/service.go` 中 `Service` 虽接收 `*pgxpool.Pool`,但全部状态存在:
|
||||
|
||||
- `blobs` / `snapshots` / `versions` / `events` / `candidates` / `reports` / `roots` / `idemp`
|
||||
|
||||
`GetRevisionState` 仅查内存 `s.roots[docID]`;无 hydrate、无 INSERT/SELECT。
|
||||
Goose `00028` 已建表且 CURRENT 记录 schema 28 healthy,但**运行态账本与 PG 脱节**。
|
||||
|
||||
**后果**:服务重启 / 多副本 / 冷启动后一律 404;backfill CLI 亦 `NewService(nil)`,apply 不落库。
|
||||
|
||||
### R2 — GET revision-state 无确定性 bootstrap
|
||||
|
||||
账本仅在以下路径创建:
|
||||
|
||||
- `OpenTemplateVersion`(PATCH 时 DocGov 命中且先前 404;或 bizdev 首次 agent 成功)
|
||||
- `CommitHumanRevision` + `AllowCreateBaseline`
|
||||
- freeform `syncLedgerLocked`(仅走 freeform 保存 API 时)
|
||||
|
||||
首次打开文档只读 GET **不会**从 `document_records` / `freeform_documents` / `output.md` 回填 → 老文档与上传文档稳定 404。
|
||||
|
||||
### R3 — 上传文档与受控文档解析/权限边界未统一
|
||||
|
||||
- `doc-upload-*`:前端本地 `deliverables` + IndexedDB,**未**强制经 freeform API 落库;`governanceMode: freeform`
|
||||
- `doc_proj143_srs`:受控 DocGov 记录存在,但无 ledger 指针/内存根
|
||||
- Handler `handleDocRevisionState` 仅 `requirePrincipal`,未走 DocumentAccess / 项目成员校验,也未按 kind 解析事实源
|
||||
|
||||
### R4 — 人工块保存未更新用户所见事实源
|
||||
|
||||
`web/src/App.tsx` `handleSaveBlockEdit`:
|
||||
|
||||
```ts
|
||||
if (!target || target.governanceMode === 'freeform') {
|
||||
return; // 上传/自由文档直接跳过 PATCH
|
||||
}
|
||||
```
|
||||
|
||||
受控路径虽调 PATCH,但:
|
||||
|
||||
- `ProjectOutputMarkdown(docID, ".")` 工作目录相对路径易错;
|
||||
- 成功后仅 `MarkDocumentContentUpdated` 哈希,重启后内存账本仍丢;
|
||||
- GET 404 时工具条已坏,overlay 无数据。
|
||||
|
||||
### R5 — Overlay 三模式未接到块渲染
|
||||
|
||||
- `DocumentRevisionToolbar` 在 state=null 时仍可切换 select,但 `onOverlay(null)`
|
||||
- `ManualChangeOverlay` 仅为提示文案,不装饰块
|
||||
- `BlockRenderer` 无 `overlayHunks` / 模式 props;App 仅在工具条下显示「人工差异 N 处」统计条
|
||||
|
||||
### R6 — Agent/Squad → change report 使用静态假数据(工程已修;叙事仍 blocker)
|
||||
|
||||
**原状**:`bizdev` 硬编码 `summary:["智能体交付物已生成"]`,且首次成功仅 `OpenTemplateVersion`、无 candidate/report。
|
||||
|
||||
**修复(fix 分支)**:`MaterializeAgentOutput` — 无账本时用显式空基线 `EmptyGenerationBaseline` 开版,再 `CreateAgentCandidate` + `BuildDeterministicChangeReportJSON`(`analysis_status=fallback`);二轮对 head 再出候选与报告。禁止把 fallback 宣称为 PI 完整分析。
|
||||
|
||||
**仍开放**:`DOCREV-RT-PI-NARRATIVE`(业务叙事摘要需真实 PI 链路)。
|
||||
|
||||
### R7 — PATCH 先写事实源再写 ledger(工程已修)
|
||||
|
||||
**原状**:`handleDocRevisionPatchContent` 先 `SaveDocumentContent` 再 ledger;ledger 失败时 output.md 已变。
|
||||
|
||||
**修复**:`AssertHumanCanEdit`(租约+编制人)→ ledger commit → `ProjectOutputMarkdown` / freeform `UpdateDocument`;投影失败返回 `DOCUMENT_PROJECTION_FAILED`(非假 200),账本 head 仍为权威、可重试投影。
|
||||
|
||||
## 严重度
|
||||
|
||||
`critical` — 版本账本对用户表现为全面不可用;保存与差异认知失效;假报告有审计污染风险。
|
||||
|
||||
## 关联整改
|
||||
|
||||
- Remediation: [../remediation/2026-09-13-document-revision-runtime-remediation.md](../remediation/2026-09-13-document-revision-runtime-remediation.md)
|
||||
- Short-term: [../ops/short-term/2026-09-13-document-revision-runtime.md](../archive/ops/2026-09-13-document-revision-runtime.md)
|
||||
- 前置设计: [../system-design/document-revision-management.md](../system-design/document-revision-management.md)
|
||||
- 前置 ADR: [../adr/2026-09-13-document-version-boundary.md](../adr/2026-09-13-document-version-boundary.md)
|
||||
|
||||
## 证据
|
||||
|
||||
| 项 | 路径 |
|
||||
|----|------|
|
||||
| 内存账本 | `internal/docrevision/service.go` `NewService` / `GetRevisionState` |
|
||||
| PG schema 未接线 | `deploy/postgres/goose/00028_2026-09-13-document-revisions.sql` |
|
||||
| GET 无 bootstrap | `internal/server/document_revision_handlers.go` `handleDocRevisionState` |
|
||||
| freeform 跳过保存 | `web/src/App.tsx` `handleSaveBlockEdit` |
|
||||
| 静态 report | `internal/bizdev/service.go` CreateAgentCandidate `ReportJSON` |
|
||||
| Overlay 空壳 | `web/src/components/doc/ManualChangeOverlay.tsx` |
|
||||
|
||||
## 开放问题
|
||||
|
||||
1. 纯客户端上传且从未调用 freeform create 的文档:服务端无正文事实源 → bootstrap 需 PATCH/显式注册,或返回可操作的 empty/register 状态(禁止静默假账本)。Round20 UI-16 验证的是已注册 `doc-free-*` 路径。
|
||||
2. PI Agent 叙事变更报告(业务含义、开放问题文案)需独立调用链;Round20 仍为确定性 fallback,**不得**宣称为完整 PI。
|
||||
|
||||
## 关闭记录(Round20)
|
||||
|
||||
现场 404 / 未就绪 / 保存与 overlay 失效已在真实页面闭环。证据:[../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md](../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md)。项目 6159 / `doc_proj6159_intake` / V3/r2。历史失败资产不删。
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
title: "UI-06 全页模糊保存按钮未发出 PATCH"
|
||||
status: in_progress
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
severity: high
|
||||
---
|
||||
|
||||
# UI-06 全页模糊保存按钮未发出 PATCH
|
||||
|
||||
## 现象
|
||||
|
||||
第七轮真实 UI(schema 30):
|
||||
|
||||
- 稳定 `document-block` 已成功双击,编辑弹窗出现
|
||||
- `saveOpenEditor` 使用全页 `getByRole(button, { name: /保存修改|保存/ })`
|
||||
- 严格模式同时命中 7 个「一键保存到我的私密文档库」与真正的「保存修改」
|
||||
- **未发送 PATCH**,UI-06 失败
|
||||
|
||||
## 根因分析
|
||||
|
||||
| 层 | 问题 |
|
||||
|---|---|
|
||||
| 聊天栏 | `ReplyActionBar` 保存按钮的可访问名称是 `aria-label="一键保存到我的私密文档库"`,含「保存」 |
|
||||
| 弹窗 | `BlockEditorModal` 无 `role=dialog` / 稳定 `aria-label`,无法按 dialog 收窄 |
|
||||
| 脚本 | 全页模糊 `/保存修改\|保存/` 在 Playwright 严格模式命中多个控件 |
|
||||
|
||||
块寻址已修好;本轮是 **保存选择器过宽**,不是正文或双击失败。
|
||||
|
||||
## 严重度
|
||||
|
||||
`high`
|
||||
|
||||
## 关联整改
|
||||
|
||||
- Short-term: [../ops/short-term/2026-09-13-document-revision-e2e-save-selector.md](../archive/ops/2026-09-13-document-revision-e2e-save-selector.md)
|
||||
- 分支: `fix/document-revision-e2e-save-selector`
|
||||
|
||||
## 证据
|
||||
|
||||
- Evidence root(已归档、本轮勿提交):`.doc/test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui06-save-selector-failure/`
|
||||
|
||||
## 开放问题
|
||||
|
||||
- 占槽后真实 UI-06/13b 重跑;本任务保持 `in_progress`,不得标 `done`
|
||||
@@ -0,0 +1,46 @@
|
||||
---
|
||||
title: "UI-11 第二份文档路由到 intake 且 human lease 残留"
|
||||
status: in_progress
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
severity: high
|
||||
---
|
||||
|
||||
# UI-11 第二份文档路由到 intake 且 human lease 残留
|
||||
|
||||
## 现象
|
||||
|
||||
第十轮真实 UI(schema 30):
|
||||
|
||||
- UI-00~UI-10 **PASS**
|
||||
- UI-11 页面输入:请另行生成一份《系统设计输入》受控文档(第二份),不要覆盖上一份需求文档,并给出可打开的交付物。
|
||||
- 页面回复《用户初始需求收集表》正由其他用户编辑/生成中,**未启动任务**
|
||||
|
||||
## 根因分析
|
||||
|
||||
| 层 | 问题 |
|
||||
|---|---|
|
||||
| 路由 | `resolveTaskKeyFromMessage` 写意图后先扫「需求\|摸底\|用户\|首轮」,否定句「不要覆盖上一份**需求**文档」压过正向点名「系统设计输入」 |
|
||||
| 别名 | `NAMED_DELIVERABLE_ALIASES.prelim_design` 只有「初步设计说明书 / 系统设计规格」,缺「系统设计输入」(模板正式标题是「系统初步设计方案」) |
|
||||
| 租约 | PATCH 在 `AssertHumanCanEdit` 后持 15min human lease;本 UI 无 heartbeat/token。成功 / 409 / 投影失败都不释放,intake 被锁,小队再跑 intake 得 DOC_BUSY |
|
||||
| E2E | UI-11 `sendChat` 后直接 `waitForSquadCompletion`,没有 `tasks/runs` 202 门闩;同步 busy completed 可能被当成成功 |
|
||||
|
||||
## 严重度
|
||||
|
||||
`high`
|
||||
|
||||
## 关联整改
|
||||
|
||||
- Remediation: [../remediation/2026-09-13-document-revision-second-doc-routing-lease.md](../remediation/2026-09-13-document-revision-second-doc-routing-lease.md)
|
||||
- Short-term: [../ops/short-term/2026-09-13-document-revision-second-doc-routing-lease.md](../archive/ops/2026-09-13-document-revision-second-doc-routing-lease.md)
|
||||
- 分支: `fix/document-revision-second-doc-routing-lease`
|
||||
|
||||
## 证据
|
||||
|
||||
- Evidence root(已归档、本轮勿提交):`.doc/test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui11-second-doc-routing-human-lease-failure/`
|
||||
|
||||
## 开放问题
|
||||
|
||||
- 占槽后真实 UI-11 重跑;本任务保持 `in_progress`,不得标 `done`
|
||||
- 请求级租约:同用户双窗 ETag 冲突靠 If-Match,不靠租约互斥(同 `holderID` 会续租)
|
||||
- 卡片展示标题是「系统初步设计方案」(非 prompt 别名「系统设计输入」);E2E 必须按 `doc_proj{n}_prelim_design` 打开
|
||||
@@ -0,0 +1,46 @@
|
||||
---
|
||||
title: "任务 run SSE 超时断线后同 turn 误击 DOC_BUSY"
|
||||
status: in_progress
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
severity: critical
|
||||
---
|
||||
|
||||
# 任务 run SSE 超时断线后同 turn 误击 DOC_BUSY
|
||||
|
||||
## 现象
|
||||
|
||||
真实 Antigravity UI-03(dev schema 30):
|
||||
|
||||
1. 初始 `POST /api/v1/tasks/runs` → **202** `run_1789308825655387640`
|
||||
2. `GET .../events` 约 **157s** 后以 `ERR_INCOMPLETE_CHUNKED_ENCODING` 断开(对齐服务端默认 `WriteTimeout=120s`)
|
||||
3. 浏览器用**完全相同** `session=sess-p6098-u107`、`client_turn_id=turn_1789308825646`、`doc_id=doc_proj6098_intake` 再 POST
|
||||
4. `handleCreateTaskRun` 在幂等 `ClaimRun` **之前**执行 `preflightTaskDocumentBusy` → **409 DOC_BUSY**,并 `recordBusyPreflightMessages` 写入**重复**用户/失败助手消息
|
||||
|
||||
## 根因分析
|
||||
|
||||
| 层 | 问题 |
|
||||
|---|---|
|
||||
| HTTP | 全局 `WriteTimeout: 120s` 切断长任务 SSE 响应体,客户端见 incomplete chunked encoding |
|
||||
| Handler | 同 turn 重试仍走 scope/preflight;活跃小队租约被当成「别人在编」 |
|
||||
| FE | `subscribeTaskRunEvents` 遇意外 EOF 直接结束,上层可能再次 `createTaskRun` |
|
||||
|
||||
## 严重度
|
||||
|
||||
`critical`
|
||||
|
||||
## 关联整改
|
||||
|
||||
- Short-term: [../ops/short-term/2026-09-13-document-revision-sse-idempotency.md](../archive/ops/2026-09-13-document-revision-sse-idempotency.md)
|
||||
- 分支: `fix/document-revision-sse-idempotency`
|
||||
|
||||
## 证据
|
||||
|
||||
- 运行产物目录(勿删):[../test-reports/assets/2026-09-13-document-revision-runtime-ui/](../test-reports/assets/2026-09-13-document-revision-runtime-ui/)
|
||||
- 前序 UI-03 客户端同步审计:[./2026-09-13-controlled-doc-client-sync-ui03.md](./2026-09-13-controlled-doc-client-sync-ui03.md)
|
||||
- 现场键:`run_1789308825655387640` / `sess-p6098-u107` / `turn_1789308825646` / `doc_proj6098_intake`
|
||||
|
||||
## 开放问题
|
||||
|
||||
- 合入前占槽真实 UI 重跑 UI-03(本轮不 rebuild Docker)
|
||||
- chat `/stream` 与 `tasks/run/stream` 是否需同样 SSE write-deadline 扩展(本轮优先 `/tasks/runs/{id}/events`)
|
||||
@@ -0,0 +1,48 @@
|
||||
---
|
||||
title: "UI-13a 在私密分类下打不开受控工作流文档"
|
||||
status: in_progress
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
severity: high
|
||||
---
|
||||
|
||||
# UI-13a 在私密分类下打不开受控工作流文档
|
||||
|
||||
## 现象
|
||||
|
||||
第15轮真实 UI(schema 30,`dev@48a4dcb`):UI-00 至 UI-12 全部 PASS,UI-11 快速完成修复已实证 PASS。**UI-13a 在真正权限断言前失败**。
|
||||
|
||||
`openWorkflowDocById(page, doc_proj6143_intake)` 报:`doc-selector menu missing data-doc-id=doc_proj6143_intake`。
|
||||
|
||||
现场快照:分类触发器为「我的私密 1」,文档下拉只有私密清单。intake 仍存在于对话引用中,只是当前分类菜单不可见。
|
||||
|
||||
## 根因分析
|
||||
|
||||
| 层 | 问题 | 后果 |
|
||||
|---|---|---|
|
||||
| UI-11 后状态 | 上传归档把 active category 留在 `private` | 后续步骤默认停在「我的私密」 |
|
||||
| 验收导航 | `openWorkflowDocById` / `ByLabel` / `ByControlledTaskKey` 直接展开当前分类的文档菜单 | 私密菜单里没有 `doc_proj*` |
|
||||
| 分类控件 | 真实页面必须先点 `doc-category-trigger` 再选 `data-category=workflow`(文案「流程受控」) | 脚本跳过该步即 fail-open 于错误清单 |
|
||||
|
||||
不是权限矩阵错,也不是 intake 丢失。
|
||||
|
||||
## 严重度
|
||||
|
||||
`high`
|
||||
|
||||
阻断 UI-13a 及之后所有「从任意分类回到受控文档」的步骤。
|
||||
|
||||
## 关联整改
|
||||
|
||||
- Remediation: [../remediation/2026-09-13-document-revision-workflow-category-navigation.md](../remediation/2026-09-13-document-revision-workflow-category-navigation.md)
|
||||
- Short-term: [../ops/short-term/2026-09-13-document-revision-workflow-category-navigation.md](../archive/ops/2026-09-13-document-revision-workflow-category-navigation.md)
|
||||
- 分支: `fix/document-revision-workflow-category-navigation`
|
||||
|
||||
## 证据
|
||||
|
||||
- 失败证据(只读,不得改/移/删/提交):`.doc/test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui13a-category-navigation-failure/`
|
||||
|
||||
## 开放问题
|
||||
|
||||
- 本轮不重跑真实 UI-13a;不得标 E2E 通过或任务 `done`
|
||||
- 不得用直接 API / 改内存 `activeCategory` 规避页面分类控件
|
||||
@@ -0,0 +1,88 @@
|
||||
---
|
||||
title: "无 live 误拒 + chat 缺项目授权 + 立项成员未落库(UI-01/02)"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
severity: critical
|
||||
---
|
||||
|
||||
# 无 live 误拒 + chat 缺项目授权 + 立项成员未落库(UI-01/02)
|
||||
|
||||
## 现象
|
||||
|
||||
1. **UI-02**:项目 6071 `creator_user_id`/`project_members` owner 正确,但 `project_workflow_instances` 零记录;页面首轮 intake 返回 `WORKFLOW_ACCESS_DENIED`。
|
||||
2. **安全连锁**:若仅把「无 live」改为 unrestricted,而不在 `handleChat`/`handleChatStream` 做项目成员校验,任意登录用户只要猜到 `project_id` 即可进入项目对话。
|
||||
3. **UI-01/UI-13**:页面勾选 B 为 reviewer,但 `project_members` 仅有 creator A;B 新浏览器看不到项目。
|
||||
|
||||
## 根因分析
|
||||
|
||||
### A. ResolveStageAccess 与 GetLiveInstance 语义错位
|
||||
|
||||
- 注释写明「无 live 不限制(legacy)」,但 `err != nil || live == nil` 分支设 `Restricted=true`,空允许名单 → 新建未激活项目被全拒。
|
||||
- `GetLiveInstance` / `HasLiveInstance`(PG)仅返回 active 系;**completed/terminated 在 PG 上表现为 live=nil**。若把 live=nil 一律 unrestricted,会把已结束实例误判为从未激活,使 `CheckDocTaskAccess` 的 `WORKFLOW_INSTANCE_CLOSED` 在生产 PG 成死代码。
|
||||
|
||||
### B. Chat 入口缺项目成员门禁
|
||||
|
||||
- `handleChat` / `handleChatStream` 仅有 stage ABAC(`allowActiveStageChatAccess`),**无** `RequireProjectAccess`。
|
||||
- `handleChatStream` 在鉴权前即 `Content-Type: text/event-stream` + `Flush()`,拒绝时已是 200 SSE。
|
||||
|
||||
### C. 立项成员只写本地
|
||||
|
||||
- `App.handleCreateProjectConfirm` 在 `createProject` 成功后构造本地 members/sessions,**从未**调用 `addProjectMember`;服务端仅有 creator owner。
|
||||
|
||||
## 严重度
|
||||
|
||||
`critical`(错误拒绝阻断 UI-02;修复 A 而不修 B 会开放跨项目对话;C 阻断跨设备协同与 UI-13)
|
||||
|
||||
## 本轮修复
|
||||
|
||||
1. **Store**:新增 `GetGoverningInstanceForAccess`(优先 live,否则最新 completed/terminated;无则 nil)。`HasLiveInstance`/`GetLiveInstance` 保持 active-only。mem 与 PG 对齐。
|
||||
2. **ABAC**:`ResolveStageAccess` / `CheckDocTaskAccess` 改用 governing 实例;无实例 unrestricted;closed 全拒;存储错误 fail-closed/上抛。
|
||||
3. **Chat**:`enforceChatProjectAccess`(成员/创建者;系统管理员按既有策略);同步与流式均在 stage 之前;SSE **headers/Flush 之前**结构化 JSON 403。
|
||||
4. **立项**:`ensureCreatedProjectWithMembers` + `persistInitialProjectMembers`;失败显式报错并保留 bootstrap project id 幂等重试;成功后才关弹窗。
|
||||
5. **立项双击竞态**:同步 in-flight ref 锁 + `createProjectBootstrapIdRef`(取代 state);Modal `submitting`/`submitPhase` 禁用确认与关闭,文案「立项中/同步成员中」。
|
||||
6. **任务作用域三态**:`ResolveMessageScopeForTask` 用 `GetGoverningInstanceForAccess`——从未激活→`ScopePreActivation`;live→阶段作用域;closed→拒绝;存储错误上抛。
|
||||
|
||||
## 证据
|
||||
|
||||
- 实战:项目 6071 零实例 + `WORKFLOW_ACCESS_DENIED`;成员表无 B
|
||||
- PG:`TestPG_GoverningAccess_*`(never / active outsider / completed|terminated / query error)
|
||||
- PG:`TestChatProjectAccess_*`(nonmember 403 无 event-stream;creator/member 200 SSE)
|
||||
- FE:`createProjectMembersPersist.test.ts`
|
||||
- FE:`createProjectSubmitGuard.test.ts`(in-flight 锁 + 文案/关闭门禁)
|
||||
|
||||
## 关联整改
|
||||
|
||||
- Short-term: [../ops/short-term/2026-09-13-document-revision-runtime.md](../archive/ops/2026-09-13-document-revision-runtime.md)
|
||||
- 前序: [2026-09-13-admin-user-directory-sync-ui01.md](./2026-09-13-admin-user-directory-sync-ui01.md)
|
||||
|
||||
## 开放问题
|
||||
|
||||
- 跨设备用户目录(非 admin 成员目录 API)仍见前序 audit residual
|
||||
- 立项 UI 角色 reviewer→API `member` 为既有契约;文档三权仍在工作流 plan duties,非 `project_members.project_role`
|
||||
|
||||
## 后续竞态(已确认并修复)
|
||||
|
||||
### D. `createProjectBootstrapId` 为 React state 导致双击重复建项
|
||||
|
||||
**现象**:快速双击「确认立项」时,两个 async 调用可同时读到 `bootstrapId=null`,各自 `createProject` → 重复项目。
|
||||
|
||||
**根因**:`useState` 更新非同步;仅靠 bootstrap state 无法在入口互斥。`disabled` 若依赖尚未提交的 submitting state,首帧仍可连点。
|
||||
|
||||
**修复**:
|
||||
1. 同步 `useRef` in-flight 锁(`beginCreateProjectSubmit` 入口立即锁 / `finally` 解锁)
|
||||
2. `createProjectBootstrapIdRef` 取代 React state 保存 bootstrap;`create` 成功即写入,成员失败后串行幂等重试
|
||||
3. `createProjectSubmitting` + `submitPhase` 传给 `CreateProjectModal`:确认按钮禁用并显示「立项中 / 同步成员中」,阻止关闭与重复 submit
|
||||
4. 失败解锁后允许再次确认;成功清 bootstrap
|
||||
|
||||
**证据**:`web/src/lib/createProjectSubmitGuard.test.ts`;`createProjectMembersPersist` onPhase 断言
|
||||
|
||||
### E. 无 live 新项目 POST `/api/v1/tasks/runs` → 409 TASK_SCOPE_UNRESOLVED(UI-02)
|
||||
|
||||
**现象**:UI-00/01 PASS;UI-02 截图「连接异常,1s后自动重试…」;网络唯一 POST `tasks/runs`=409;E2E 因短暂「生成中」误记 PASS。
|
||||
|
||||
**根因**:stage/doc access 已允许无 governing 新项目兼容运行,但 `ResolveMessageScopeForTask` 对 no-live 一律 `ErrTaskScopeNotResolved` → handler 409。若仅凭 `GetLiveInstance=nil` 放行,会把 completed/terminated 误当预激活。
|
||||
|
||||
**修复**:`ResolveMessageScopeForTask` 经 `GetGoverningInstanceForAccess` 三态——nil→`ScopePreActivation`;live 系→阶段作用域;completed/terminated→`ErrTaskScopeNotResolved`;存储错误原样上抛。E2E UI-02 等待 `tasks/runs` 真实响应并要求 2xx,409/连接异常立即 FAIL。
|
||||
|
||||
**证据**:`message_scope_test.go`(preactivation / live / closed 组合 / storage error);`TestCreateTaskRun_PreActivationAcceptedNot409`;`web/e2e` UI-02
|
||||
@@ -0,0 +1,52 @@
|
||||
---
|
||||
title: "arch-check Wave 0 基线"
|
||||
status: done
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-14
|
||||
severity: medium
|
||||
---
|
||||
|
||||
# arch-check Wave 0 基线
|
||||
|
||||
## 现象
|
||||
|
||||
模块边界此前只能靠人工约定。Wave 0 用当前 `go list` 生成 import allowlist,并用目标属主扫描表名与路径字面量,得到可重复的 warn 基线。
|
||||
|
||||
## 根因分析
|
||||
|
||||
`document_records`、`output.md`、`data/dev` 被多个包直接提及,与「单一写者 / 路径属主」目标不一致。这些不是本轮回归,而是 Wave 1+ 的收口对象。
|
||||
|
||||
## 严重度
|
||||
|
||||
`medium`
|
||||
|
||||
## 关联整改
|
||||
|
||||
- ADR: [../adr/2026-09-14-modular-monolith-decoupling.md](../adr/2026-09-14-modular-monolith-decoupling.md)
|
||||
- 设计: [../system-design/2026-09-14-module-decoupling-architecture.md](../system-design/2026-09-14-module-decoupling-architecture.md)
|
||||
- 任务: [../ops/short-term/2026-09-14-module-decoupling-wave0.md](../ops/short-term/2026-09-14-module-decoupling-wave0.md)
|
||||
|
||||
## 证据
|
||||
|
||||
命令:`./scripts/arch-check.sh --mode warn`(2026-09-14,本工作区)
|
||||
|
||||
- import 相对基线 allowlist:**0** 条新边
|
||||
- 目标属主扫描:**21** 条 warn(按包去重)
|
||||
|
||||
```
|
||||
WARN R5 table document_records mentioned in authz, workspace, docduty, server, bizdev, docrevision
|
||||
WARN R5 table freeform_documents mentioned in docrevision
|
||||
WARN R5 table task_runs mentioned in server, projectinstance, docgov
|
||||
WARN R6 path output.md mentioned in coordinator, server, bizdev, docgov, docrevision, agent
|
||||
WARN R6 path data/dev mentioned in coordinator, server, bizdev, storage
|
||||
WARN R6 path workspaces/ mentioned in server
|
||||
violations=21
|
||||
arch-check warn: recorded 21 baseline findings
|
||||
```
|
||||
|
||||
`--mode block` 会因这 21 条失败,故 **不得**在 warn 期满前把脚本挂进集成冒烟。
|
||||
|
||||
## 后续
|
||||
|
||||
- Wave 1 起按属主清零上表,再把对应规则转 block
|
||||
- 本轮不占集成槽、不 `env-service` rebuild
|
||||
@@ -0,0 +1,81 @@
|
||||
---
|
||||
title: "UI-06 页面刷新后受控正文停留加载骨架竞争态审计"
|
||||
status: done
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-14
|
||||
severity: high
|
||||
---
|
||||
|
||||
# UI-06 页面刷新后受控正文停留加载骨架竞争态审计
|
||||
|
||||
## 现象
|
||||
|
||||
在真实 UI 验收主阶段 `e2e/document-revision-runtime.spec.ts` 的 `UI-06` 用例中:
|
||||
1. 用户 A 双击段落完成人工修改并保存,PATCH 200 成功,修订版本从 `r0` 递增至 `r1`;
|
||||
2. 执行 `await page.reload()` 硬刷新页面;
|
||||
3. 页面重新挂载后,顶栏与修订徽章显示 `r1`,但正文区域长时间停留在骨架占位文案:
|
||||
`用户初始需求收集表 提示说明 正在从服务端加载文档正文… 受控状态: 编制中 • 已被编制人认领`
|
||||
4. 导致 `getByText(marker)` 超过 30 秒未能在 DOM 中找到,测试套件判定 **FAIL**。
|
||||
|
||||
## 根因分析
|
||||
|
||||
从 Playwright Trace (`1-trace.network` / `1-trace.trace`) 的毫秒级时序分析:
|
||||
|
||||
1. **后端数据与接口均正常**:
|
||||
- `03:22:19.374Z (+6.1ms) GET 200 /api/v1/docgov/documents/doc_proj6172_intake/content`
|
||||
- 返回数据快照 `resources/039f1e925ea0bf047bca866dba4e35cff8c72a2b.json` 第一行即包含本次修改标记 `# 人工修订段落 UI06-mu0o5hbq 用于硬刷新验收。`;
|
||||
- 修订接口 `GET 200 /api/v1/documents/doc_proj6172_intake/revision-state` 正确返回 `r1`;
|
||||
- 浏览器 Console 无任何报错。
|
||||
2. **前端内部状态清理竞争(App.tsx)**:
|
||||
- 页面重新挂载时,`useEffect` 触发受控正文拉取,在 `03:22:19.380Z` 将解析好的 AST 存入 `docCache[docId]` 并置 `controlledContentReady[docId] = true`;
|
||||
- 页面重新挂载同时触发的 `syncWorkflowDocs`(`GET /api/v1/projects/6172/documents?category=workflow`)在 `03:22:19.384Z`(仅晚 4ms)返回;
|
||||
- 在 [`web/src/App.tsx#L1746-L1765`](file:///home/weichen/projects/Agent-System/.worktrees/fix-controlled-content-ui-acceptance/web/src/App.tsx#L1746-L1765):
|
||||
```typescript
|
||||
const serverBackedIds = merged
|
||||
.filter((d) => d.projectId === currentProjectId && shouldLoadControlledContent(d))
|
||||
.map((d) => d.docId);
|
||||
if (serverBackedIds.length > 0) {
|
||||
setDocCache((cache) => {
|
||||
const next = { ...cache };
|
||||
serverBackedIds.forEach((docId) => {
|
||||
delete next[docId]; // 无条件删除缓存
|
||||
});
|
||||
return next;
|
||||
});
|
||||
setControlledContentReady((ready) => {
|
||||
const next = { ...ready };
|
||||
serverBackedIds.forEach((docId) => {
|
||||
delete next[docId]; // 无条件清空 ready
|
||||
});
|
||||
return next;
|
||||
});
|
||||
}
|
||||
```
|
||||
`syncWorkflowDocs` 无条件删除了 `docCache[activeDocId]` 与 `controlledContentReady[activeDocId]`。
|
||||
3. **死锁成因**:
|
||||
- 此时 `docAST` 判定 `docCache` 缺失且 `controlledContentReady` 为 false,回退至 `buildControlledLoadingSkeleton`;
|
||||
- 在 [`web/src/App.tsx#L1258`](file:///home/weichen/projects/Agent-System/.worktrees/fix-controlled-content-ui-acceptance/web/src/App.tsx#L1258),拉取正文的 `useEffect` 依赖为 `[session, sessionValidated, activeDocId, activeHydrateFingerprint, applyHydratedDocument, hydrateResumeKey]`;
|
||||
- `activeHydrateFingerprint` 仅包含 `docId`、`stage`、`updatedAt` 等,在缓存被清空后并未发生变化,导致不会再次唤醒网络拉取;
|
||||
- 页面永久锁死在加载骨架屏。
|
||||
|
||||
## 严重度
|
||||
|
||||
`high`(阻断主阶段硬刷新、登出重登持久化及后续多文档验收)。
|
||||
|
||||
## 建议整改方案(供 Cursor 参考)
|
||||
|
||||
1. `syncWorkflowDocs` 不应对所有 `serverBackedIds` 进行盲目的全量缓存与 ready 标志清空;应比对服务端返回的 `updatedAt` / `sha256` / `stage`,仅在真正发生更新时定向失效;
|
||||
2. 或者,若主动清空了已加载文档的缓存,必须同步唤醒重新拉取(如递增 `hydrateResumeKey`),避免状态丢失后无重入机制。
|
||||
|
||||
## 整改与复验结果
|
||||
|
||||
- Cursor 在 `08bf615` 引入统一的 `controlledContentInvalidation` 规划:`list_sync` 保留已水合缓存;`post_task` 定向失效并唤醒重水合;编辑期间保护活动正文并在关闭编辑器后恢复拉取。
|
||||
- 修复通过 349 项前端脚本测试、30 项 Vitest 与生产构建,并随 `36e4bc3` 合入 dev 后 rebuild。
|
||||
- Antigravity 在完全新建的真实 UI 项目中重跑 `UI-06`:人工编辑 `r0→r1` 后硬刷新,正文和唯一标记在 1.1 秒内恢复;完整主链与容器重启后恢复均 PASS。
|
||||
- 有效证据与历史 FAIL/INVALID 运行严格分开,详见[真实 UI 验收报告](../test-reports/2026-09-14-controlled-content-ui-acceptance.md)。
|
||||
|
||||
## 证据路径
|
||||
|
||||
- 报告:`.doc/test-reports/2026-09-14-controlled-content-ui-acceptance.md`
|
||||
- Trace:`.doc/test-reports/assets/2026-09-14-controlled-content-ui-acceptance/full-chain-valid/playwright-output-main/document-revision-runtime--d72a3-ard-refresh-persists-r-bump-chromium/trace.zip`
|
||||
- 截图:`.doc/test-reports/assets/2026-09-14-controlled-content-ui-acceptance/full-chain-valid/playwright-output-main/document-revision-runtime--d72a3-ard-refresh-persists-r-bump-chromium/test-failed-1.png`
|
||||
@@ -0,0 +1,107 @@
|
||||
---
|
||||
title: "项目 143 受控文档正文因规范化哈希漂移返回 404"
|
||||
status: done
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-14
|
||||
severity: critical
|
||||
---
|
||||
|
||||
# 项目 143 受控文档正文因规范化哈希漂移返回 404
|
||||
|
||||
## 现象
|
||||
|
||||
已登录用户打开项目 143 后,页面无法加载 `doc_proj143_intake` 正文,并周期性出现:
|
||||
|
||||
```text
|
||||
GET /api/v1/docgov/documents/doc_proj143_intake/content 404
|
||||
自动拉取受控文档正文失败: fetch controlled document content failed: 404
|
||||
```
|
||||
|
||||
本轮未操作用户浏览器,也未执行真实 PI 或页面验收;上述 UI 现象来自用户现场。诊断仅对当前 dev 源码、PostgreSQL、容器挂载文件和既有真实 UI 证据做只读核对。
|
||||
|
||||
## 根因分析
|
||||
|
||||
### R1 — 文件存在,404 实际是哈希完整性冲突(直接原因)
|
||||
|
||||
当前 dev 数据链如下:
|
||||
|
||||
| 项 | 值 |
|
||||
|---|---|
|
||||
| project | `143`,active,workflow=`main` |
|
||||
| document | `doc_proj143_intake`,非模板、drafting |
|
||||
| work_dir | `/app/data/workspaces/bizdev/intake_1789270446856290128` |
|
||||
| output.md | 存在,38,581 bytes |
|
||||
| 文件原始 SHA-256 | `c97d749728bf5607a9117c29e45c0a165353f5bb8ba65532f21bda87232a988b` |
|
||||
| `document_records.content_sha256` | `7e3c4954de0bd225ccde0c8494784d4275e7f29a517510f6a286ec004c35d490` |
|
||||
| ledger head snapshot SHA-256 | 同上 `7e3c...d490`,38,571 bytes |
|
||||
|
||||
`output.md` 有 5 行各保留 2 个 Markdown 尾随空格,共多 10 bytes。逐行去掉行尾空白后,文件 SHA-256 **精确等于**数据库记录和账本 head 的 `7e3c...d490`。这证明漂移由当前 canonicalizer 的行尾裁剪造成,而不是文件缺失;但 Markdown 的两个尾随空格表示硬换行,具有渲染语义,不能把两侧判为语义等价,也不能直接用账本 blob 覆盖原文件。
|
||||
|
||||
`internal/docgov/project_docs.go::ReadDocumentContent` 对文件原始字节计算 SHA,并与 `document_records.content_sha256` 比较;不等即报 `content sha256 mismatch`。`internal/server/project_doc_handlers.go::handleDocGovGetDocumentContent` 又把 `ReadDocumentContent` 的所有错误统一写成 HTTP 404,所以页面看到的是错误的 Not Found。
|
||||
|
||||
### R2 — revision bootstrap 改了数据库哈希,没有同步规范化文件(制造漂移)
|
||||
|
||||
项目 143 的 `output.md` 于 2026-09-13 03:42 UTC 由真实小队落盘;账本 snapshot 66 于 10:32 UTC 才由旧文档首次 revision bootstrap 建立。
|
||||
|
||||
bootstrap 调用链:
|
||||
|
||||
1. `bootstrapRevisionIfNeeded` 从 DocGov 文件读出 Markdown;
|
||||
2. `EnsureBootstrap` / `OpenTemplateVersion` 调用 `CanonicalizeMarkdown`;
|
||||
3. canonicalizer 会去掉每行尾随空格,包括 Markdown 有语义的双空格硬换行;
|
||||
4. `openTemplatePGLocked` 将 canonical SHA 写入 snapshot、blob 和 `document_records.content_sha256`;
|
||||
5. 该路径没有把 canonical blob 重新投影到 `output.md`。
|
||||
|
||||
结果是数据库与账本指向 38,571-byte canonical 内容,兼容文件仍为 38,581-byte raw 内容。旧项目一旦被 bootstrap,后续正文读取稳定失败。
|
||||
|
||||
### R3 — content 与 revision 并发 hydration 使首次行为存在竞态
|
||||
|
||||
`hydrateControlledDocumentContent` 用 `Promise.all` 同时请求 content 与 revision-state。对尚未建账本的旧文档:
|
||||
|
||||
- content 若先读到旧 raw 哈希,可能首次成功;
|
||||
- revision-state 随后 bootstrap 并把记录改成 canonical 哈希;
|
||||
- 后续 content 立即或下一轮稳定 404。
|
||||
|
||||
既有真实 UI 资产已经记录过项目 143 的 `revision-state=200`、`content=404`;Round20 的 PASS 使用新项目 6159,不能覆盖项目 143 的旧数据迁移场景。
|
||||
|
||||
### R4 — 5 秒 lease 同步无变化也制造新数组,放大为重复 404
|
||||
|
||||
正文 hydration effect 依赖整个 `deliverables`。lease 轮询每 5 秒执行 `prev.map(...)` 并始终返回新数组,即使每个文档的 lease 均未变化。React 因引用变化重跑 hydration effect,持续请求同一已知失败正文。
|
||||
|
||||
因此控制台中的多次 404 不是多份正文丢失,而是一个后端一致性错误被前端无效状态更新周期性放大。
|
||||
|
||||
### R5 — 错误协议丢失可诊断信息
|
||||
|
||||
- 后端将记录不存在、文件不存在、文件为空、哈希冲突全部映射为 404。
|
||||
- `fetchControlledDocumentContent` 只抛出 HTTP status,不解析结构化错误码、message 或 correlation id。
|
||||
- 用户只能看到 `failed: 404`,无法区分可重试网络问题与必须修复的数据冲突。
|
||||
|
||||
## 影响范围
|
||||
|
||||
- **已确认受影响**:dev 项目 143 / `doc_proj143_intake`。
|
||||
- 对当前 dev 中可定位到现存 `output.md` 的 27 个非模板受控记录做只读比对:26 个 raw SHA 一致,只有项目 143 为 mismatch。
|
||||
- 数据库另有大量测试记录使用临时路径或空 `work_dir`;属于测试数据隔离/清理问题,不据此扩大本缺陷的用户数据范围。
|
||||
- 任何“旧文件含会被 canonicalizer 改写的内容、首次 bootstrap 只改数据库不投影文件”的文档都具有同类风险;不能仅手工修项目 143 后关闭代码缺陷。
|
||||
|
||||
## 严重度
|
||||
|
||||
`critical` — 用户正文实际存在却无法在 UI 查看;编辑、overlay、版本比较等后续能力均被正文 hydration 阻断,且错误码误导为不存在。
|
||||
|
||||
## 关联整改
|
||||
|
||||
- Remediation: [../remediation/2026-09-14-controlled-content-canonical-hash-remediation.md](../remediation/2026-09-14-controlled-content-canonical-hash-remediation.md)
|
||||
- 既有账本审计: [2026-09-13-document-revision-runtime-404.md](./2026-09-13-document-revision-runtime-404.md)
|
||||
- 既有真实 UI 报告: [../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md](../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md)
|
||||
|
||||
## 证据
|
||||
|
||||
- 源码:`internal/docrevision/canonicalize.go`、`internal/docrevision/pg_mutate.go`、`internal/docgov/project_docs.go`、`internal/server/project_doc_handlers.go`
|
||||
- 前端:`web/src/lib/controlledDocHydrate.ts`、`web/src/App.tsx`
|
||||
- 数据库:`document_records.id=87`、`document_versions.id=59`、`document_snapshots.id=66`
|
||||
- 历史 UI 资产:`.doc/test-reports/assets/2026-09-13-document-revision-runtime-ui/ui01-parent-directory-sync-failure/ui-acceptance-results.json`
|
||||
|
||||
## 关闭结果
|
||||
|
||||
- Cursor 已完成语义保持的 canonicalization、结构化错误、原子投影、定向 reconciler、legacy/mock 水合隔离和刷新缓存竞态修复;产品代码已合入并部署至 dev。
|
||||
- 项目 143 已在保全原文件与旧 head 后以显式 `migration_repair` 校正账本,没有把裁剪硬换行的旧 head 静默覆盖回原文件。
|
||||
- Antigravity 的 `clean-run3` 仅通过真实页面完成登录、正文打开、30 秒静置、人工编辑、三模式切换、硬刷新和退出重登;`doc_proj143_intake` 的 content/revision 目标 404 全程为 0。
|
||||
- 新项目 `full-chain-final` 又覆盖真实小队生成、影响/风险报告、高风险确认与拒绝、多文档、上传账本、权限、并发冲突及容器重启后恢复。最终验收见[报告](../test-reports/2026-09-14-controlled-content-ui-acceptance.md)。
|
||||
@@ -0,0 +1,104 @@
|
||||
---
|
||||
title: "workflow-plan 409 冻结冲突(项目 143)与三权设置粒度调整需求"
|
||||
status: done
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-14
|
||||
severity: medium
|
||||
---
|
||||
|
||||
# workflow-plan 409 冻结冲突(项目 143)与三权设置粒度调整需求
|
||||
|
||||
## 现象
|
||||
|
||||
用户在项目设置(`ProjectSettingsModal`)中把项目内所有文档任务的编制/审核/批准指派为「系统管理员 / 李审核 / 王总监」,点击「校验并预览」无反应。控制台报错:
|
||||
|
||||
```text
|
||||
projectSettings.ts:51 PUT https://frp-mix.com:58880/api/v1/projects/143/workflow-plan 409 (Conflict)
|
||||
```
|
||||
|
||||
同时用户提出新需求:**三权设置粒度按文档控制**——对某个允许省略人工审批的文档,一旦设置职责,必须三个职责(编制/审核/批准)都指派负责人;三个职责都未设置时,该文档仍可生成和进入版本账本,但不进入人工审批及阶段批准门禁。它不是“非受控文档”;若不需要生成该文档,应关闭文档任务。
|
||||
|
||||
## 根因分析
|
||||
|
||||
### 409 的直接原因:项目 143 已激活工作流,规划已冻结(PLAN_FROZEN)
|
||||
|
||||
dev 库(`shuimu-context-pg-dev` / `agent_system_dev`)实测:
|
||||
|
||||
```text
|
||||
id | name | lifecycle_status | active_workflow_key | workflow_selection_version | workflow_plan_revision
|
||||
-----+------+------------------+---------------------+----------------------------+------------------------
|
||||
143 | 测试 | active | main | 2 | 1
|
||||
|
||||
id | project_id | status | config_revision | has_hash | created_at
|
||||
----+------------+--------+-----------------+----------+-------------------------------
|
||||
89 | 143 | active | 1 | t | 2026-09-13 01:31:33.212283+00
|
||||
```
|
||||
|
||||
项目 143 于 2026-09-13 已激活 `main` 工作流(实例 89,status=active)。后端保存链路:
|
||||
|
||||
- `internal/projectinstance/service.go:131-133`(`SaveWorkflowPlan`):`if lifecycle != LifecyclePlanning { return nil, ErrPlanFrozen }`,冲突检查发生在最前;
|
||||
- `internal/server/project_settings_handlers.go:164-165`:`ErrPlanFrozen` → HTTP 409 `{"error":"PLAN_FROZEN","message":"工作流已激活,规划已冻结"}`。
|
||||
|
||||
前端未能把该语义展示出来,构成「点击无反应」的体验:
|
||||
|
||||
- `web/src/api/projectSettings.ts:60-63`:非 2xx 直接抛出普通 `Error`。`parseError`(`projectSettings.ts:200-213`)其实已经能取到后端 `message`,所以“工作流已激活,规划已冻结”并未丢失;真正缺口是错误对象不保留 HTTP status/code/issues,UI 无法按 `PLAN_FROZEN`、版本冲突等类型切换冻结态或执行定向恢复;
|
||||
- `web/src/components/project/ProjectSettingsModal.tsx:161-162`:catch 后写入 `error` state。弹窗在 `configure` 步骤的「校验并预览」按钮(538-557 行)点击后仅更新顶部 error 区(276-293 行),视口停留在长表单底部时用户看不到顶部横幅,感知即「无反应」。
|
||||
|
||||
### 前端缺少冻结态守卫
|
||||
|
||||
`ProjectSettingsModal.tsx` 的 `loadSettings`(53-81 行)只要 `s.plan` 存在就 `setStep('configure')`,`handleSelectWorkflow` / `handleSavePlan`(91-166 行)均未检查 `settings.lifecycle_status !== 'planning'` 或 `can_edit_plan === false`。后端 `GetSettings` 已正确返回 `can_edit_plan=false`(`internal/projectinstance/service.go:59-60,78-79`),前端没用它。因此已激活项目仍可一路走到保存,必然撞 409。
|
||||
|
||||
### 现行三权校验为「逐文档三职全必填」
|
||||
|
||||
- 后端 `internal/projectinstance/validator.go:93-95`:`dt.Enabled` 即调用 `validateDuties`;`validateDuties`(143-179 行)对启用的文档强制 `DUTY_AUTHOR/REVIEWER/APPROVER_REQUIRED` + 互斥校验;
|
||||
- 前端 `ProjectSettingsModal.tsx:130-145`:成员数 <3 直接拦截;每个启用文档三职任一未指派即报错。
|
||||
|
||||
即当前不存在「整文档留空」的合法表达,与用户新需求冲突。门禁侧 `internal/projectinstance/gate.go:23-51` 对 `enabled` 的文档按工作流定义的 `BlocksWhenEnabled()` 计入阶段就绪——若允许留空却不改门禁,阻断型文档会产生永久死锁。因此**留空语义必须同步改门禁,但不能反过来让项目配置绕过工作流定义中不可省略的必需/阻断文档**。
|
||||
|
||||
## 方案复核发现的补充风险
|
||||
|
||||
1. **必需文档可被绕过**:若简单采用“全空即 `required=false`”,创建者可把定义中 `required/blocking` 且不可关闭的文档职责清空,从而绕过正式工作流门禁。全空只应允许用于工作流定义允许创建者裁剪的非必需文档;必需/阻断文档仍必须三职全满。
|
||||
2. **零治理工作流**:原方案允许“全部启用文档全空后激活”。这超出“部分文档不设置”的需求,并会产生没有任何审核责任人的 active 工作流。保存草稿可以暂时全空,但激活时必须至少有一份三职完整的受治理文档。
|
||||
3. **成员有效性未由后端保证**:现有 `validateDuties` 只检查 ID 为正且互异;`document_duty_assignments.user_id` 也只外键到 `users`,没有保证用户属于该项目且仍在任。保存和激活前都必须按服务端成员快照复核。
|
||||
4. **权限语义缺失**:当前 active 实例中,创建者可操作无职责文档;其他成员的阶段范围会因没有职责而排除该文档。最终方案必须明确:无人工审批文档对有项目访问权的成员可只读可见,创建者可触发生成/编辑,review/approve 始终不可用。
|
||||
5. **冻结快照可能残留旧 ID**:关闭文档任务或切换为“无需人工审批”时,如果不清空旧职责 ID,冻结 JSON、plan hash 和预览统计仍会携带过期职责。保存前必须服务端规范化,前端也应原子清空三职。
|
||||
|
||||
## 严重度
|
||||
|
||||
`medium`(既有冻结规则正确,但页面误导用户继续编辑;职责可选属于治理能力扩展,涉及门禁、权限与激活完整性)
|
||||
|
||||
## 关联整改
|
||||
|
||||
- Remediation: [2026-09-14-workflow-plan-409-frozen-and-optional-duties-remediation.md](../remediation/2026-09-14-workflow-plan-409-frozen-and-optional-duties-remediation.md)
|
||||
- Short-term: [../ops/short-term/2026-09-14-workflow-plan-409-frozen-and-optional-duties.md](../ops/short-term/2026-09-14-workflow-plan-409-frozen-and-optional-duties.md)
|
||||
|
||||
## 证据
|
||||
|
||||
```bash
|
||||
# dev DB 实测(2026-09-14)
|
||||
docker exec shuimu-context-pg-dev psql -U app -d agent_system_dev \
|
||||
-c "SELECT id,name,lifecycle_status,active_workflow_key,workflow_selection_version,workflow_plan_revision FROM projects WHERE id=143;"
|
||||
docker exec shuimu-context-pg-dev psql -U app -d agent_system_dev \
|
||||
-c "SELECT id,project_id,status,config_revision FROM project_workflow_instances WHERE project_id=143 ORDER BY id;"
|
||||
# → lifecycle_status=active / active_workflow_key=main / 实例 89 status=active
|
||||
|
||||
# test/main 环境项目 143 不存在(0 rows),现场仅 dev
|
||||
```
|
||||
|
||||
代码引用:
|
||||
|
||||
- `internal/projectinstance/service.go:123-180`(SaveWorkflowPlan:冻结/live/选版/乐观锁顺序)
|
||||
- `internal/projectinstance/store.go:123-134`(BumpPlanRevision 乐观锁)
|
||||
- `internal/server/project_settings_handlers.go:160-204`(错误码 → HTTP 状态映射)
|
||||
- `internal/projectinstance/validator.go:9-126,143-179`(validatePlan / validateActivationPlan / validateDuties)
|
||||
- `internal/projectinstance/gate.go:5-54`(阶段门禁)
|
||||
- `web/src/components/project/ProjectSettingsModal.tsx:53-81,120-166`(loadSettings / handleSavePlan)
|
||||
- `web/src/api/projectSettings.ts:45-65,200-213`(saveWorkflowPlan / parseError)
|
||||
|
||||
## 审核结论
|
||||
|
||||
- 409 根因成立;项目 143 的职责内容合法与否不会改变冻结判定。
|
||||
- “部分指派”继续明确拒绝;顶层响应为 HTTP 400 `VALIDATION_FAILED`,具体 issue code 为 `DUTY_PARTIAL_ASSIGNMENT`。
|
||||
- 无职责文档定义为“启用但不纳入人工三权审批”,仍保留生成、正文、版本账本和项目内只读可见性;禁止使用“非受控文档”描述。
|
||||
- 全空只允许在非必需且允许项目侧裁剪的文档任务上使用;必需/阻断任务仍须三职完整。激活时至少存在一份三职完整文档。
|
||||
- 项目 143 仅做冻结态只读回归;不得在验收中终止其工作流。若业务上确需改职责,必须先查看终止影响、确认取消运行任务及关闭实例的访问影响,再受控终止并重新规划、激活。
|
||||
+150
-38
@@ -1,20 +1,132 @@
|
||||
# 项目全面审计 - 文档索引
|
||||
|
||||
> **HISTORICAL(2026-09-12 初审快照)**
|
||||
> **当前发布/缺口 SSOT** → [../remediation/gap-matrix.md](../remediation/gap-matrix.md)
|
||||
> **协作焦点** → [../ops/CURRENT.md](../ops/CURRENT.md)
|
||||
> **HISTORICAL(2026-09-12 初审快照)**
|
||||
> **当前发布/缺口 SSOT** → [../remediation/gap-matrix.md](../remediation/gap-matrix.md)
|
||||
> **协作焦点** → [../ops/CURRENT.md](../ops/CURRENT.md)
|
||||
> **Agent 工作方式** → [AGENTS.md](../../AGENTS.md) · [PROJECT.md](../../PROJECT.md)
|
||||
|
||||
**审计日期**: 2026-09-12
|
||||
**项目**: Chat-Agent-System
|
||||
**审计日期**: 2026-09-12
|
||||
**项目**: Chat-Agent-System
|
||||
**审计状态**: 历史索引(下方 5.7/10 为初审结论,勿作 live status)
|
||||
|
||||
---
|
||||
|
||||
## 核心文档(按阅读顺序推荐)
|
||||
|
||||
### 模块边界 arch-check Wave 0 基线(2026-09-14)
|
||||
|
||||
**文件**: [2026-09-14-arch-check-baseline.md](./2026-09-14-arch-check-baseline.md)
|
||||
|
||||
**结论**: import 相对现状 allowlist 无新边;表/路径目标属主扫描 21 条 warn,作为 Wave 1+ 收口清单,不在本轮转 block。
|
||||
|
||||
### 项目 143 workflow-plan 409 与三权全有或全无(2026-09-14)
|
||||
|
||||
**文件**: [2026-09-14-workflow-plan-409-frozen-and-optional-duties.md](./2026-09-14-workflow-plan-409-frozen-and-optional-duties.md)
|
||||
|
||||
**结论**: 项目 143 已于 2026-09-13 激活 main 工作流(实例 89),`SaveWorkflowPlan` 因 `lifecycle=active` 返回 409 `PLAN_FROZEN`;前端无冻结守卫、错误提示在视口外,表现为「校验并预览无反应」。按文档支持三权全有或全无,但全空仅用于定义允许裁剪的非必需文档,表示“不纳入人工审批”而非“非受控”;必需文档和零治理激活不得被绕过。
|
||||
|
||||
**整改**: [workflow-plan 409 + 三权全有或全无整改](../remediation/2026-09-14-workflow-plan-409-frozen-and-optional-duties-remediation.md)
|
||||
|
||||
### 项目 143 受控正文 canonical hash 漂移(2026-09-14)
|
||||
|
||||
**文件**: [2026-09-14-project143-controlled-content-404.md](./2026-09-14-project143-controlled-content-404.md)
|
||||
|
||||
**结论**: 正文文件存在;revision bootstrap 去掉 5 行具有 Markdown 硬换行语义的双空格并把 canonical SHA 写入账本/DocGov,却未同步文件,正文读取将哈希冲突误报为 404;5 秒 lease no-op 更新又周期性重复 hydration。原文件必须保全,不能用旧 canonical blob 覆盖。
|
||||
|
||||
**整改**: [canonical hash 漂移整改计划](../remediation/2026-09-14-controlled-content-canonical-hash-remediation.md)
|
||||
|
||||
### 文档版本账本运行时失效(2026-09-13)
|
||||
|
||||
**文件**: [2026-09-13-document-revision-runtime-404.md](./2026-09-13-document-revision-runtime-404.md)
|
||||
|
||||
**结论**: 原现场 404(账本仅内存、GET 无 bootstrap、freeform 跳过 PATCH、overlay 空壳、静态假 JSON)已在工程侧修复;**Round20 真实 UI PASS**(项目 6159,V3/r2)。change report 仍为 fallback,不冒充 PI 叙事。
|
||||
|
||||
**整改**: [运行时整改方案](../remediation/2026-09-13-document-revision-runtime-remediation.md) · [short-term](../archive/ops/2026-09-13-document-revision-runtime.md) · [Round20 报告](../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md)
|
||||
|
||||
### 文档修改与智能体版本专项分析(2026-09-13)
|
||||
|
||||
**文件**: [2026-09-13-document-revision-management-gap-analysis.md](./2026-09-13-document-revision-management-gap-analysis.md)
|
||||
|
||||
**结论**: 现有受控文档只有当前工作区正文和哈希,缺少不可变快照、智能体版本边界、人工修订差异、实际变更报告和负责人通知;前端块编辑尚未持久化。
|
||||
|
||||
**设计/整改**: [系统设计](../system-design/document-revision-management.md) · [实施方案](../remediation/2026-09-13-document-revision-management-implementation-plan.md)
|
||||
|
||||
### 最新专项审计(2026-09-13)
|
||||
|
||||
**文件**: [2026-09-13-document-revision-pg-id-remap.md](./2026-09-13-document-revision-pg-id-remap.md)
|
||||
|
||||
**结论**: 项目 6158 首次生成 PG 已写入 baseline snapshot=249、candidate id=175、output snapshot id=250、report id=175,但内存计数器未同步,临时 ID 覆盖并删除 baseline,commit `not found`。工程修复已合入;Round20 项目 6159 首次生成 UI-03 PASS。
|
||||
|
||||
**整改**: [short-term](../archive/ops/2026-09-13-document-revision-pg-id-remap.md) · [Round20 报告](../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md)
|
||||
|
||||
**文件**: [2026-09-13-document-revision-post-restart-final-snippet.md](./2026-09-13-document-revision-post-restart-final-snippet.md)
|
||||
|
||||
**结论**: 第二次 post-restart 已恢复 V3/r2 与正文;当时失败只因 phase-state 仍断言 UI-06 marker。Round20 `bodySnippet=A1-win-mu0gwiez`,post-restart PASS。
|
||||
|
||||
**整改**: [short-term](../archive/ops/2026-09-13-document-revision-post-restart-final-snippet.md) · [Round20 报告](../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md)
|
||||
|
||||
**文件**: [2026-09-13-document-revision-post-restart-selector.md](./2026-09-13-document-revision-post-restart-selector.md)
|
||||
|
||||
**结论**: 第18轮 main 18 PASS;post-restart 在项目已恢复时,页面级项目名同时命中顶栏与侧栏,strict violation,未到 revision-state。
|
||||
|
||||
**整改**: [short-term](../archive/ops/2026-09-13-document-revision-post-restart-selector.md)
|
||||
|
||||
**文件**: [2026-09-13-document-revision-reviewer-duty-sync.md](./2026-09-13-document-revision-reviewer-duty-sync.md)
|
||||
|
||||
**结论**: 第17轮 UI-00–12 PASS;精确职责断言暴露真实缺陷——UI-01 已把 B 设为 reviewer,`doc_proj6145_*` 的 `reviewer_id` 却是硬编码 `2`,矩阵为 viewer。
|
||||
|
||||
**整改**: [项目 reviewer 同步整改](../remediation/2026-09-13-document-revision-reviewer-duty-sync.md)
|
||||
|
||||
### UI-13a 职责单元格误判(2026-09-13)
|
||||
|
||||
**文件**: [2026-09-13-document-revision-duty-cell-assertion.md](./2026-09-13-document-revision-duty-cell-assertion.md)
|
||||
|
||||
**结论**: 第16轮 UI-13a 已打开 reviewer B 权限矩阵;整行 `innerText` 含全部 select option,误命中「编制负责人」。须读 select value / badge role。
|
||||
|
||||
**整改**: [职责单元格精确断言整改](../remediation/2026-09-13-document-revision-duty-cell-assertion.md)
|
||||
|
||||
### 受控文档分类导航(2026-09-13)
|
||||
|
||||
**文件**: [2026-09-13-document-revision-workflow-category-navigation.md](./2026-09-13-document-revision-workflow-category-navigation.md)
|
||||
|
||||
**结论**: 第15轮 UI-00–12 PASS;UI-13a 在私密分类下直接展开文档菜单,找不到 `doc_proj*_intake`。须先用页面控件切到流程受控。
|
||||
|
||||
**整改**: [受控文档分类导航整改](../remediation/2026-09-13-document-revision-workflow-category-navigation.md)
|
||||
|
||||
### UI-11 快速完成观测(2026-09-13)
|
||||
|
||||
**文件**: [2026-09-13-document-revision-fast-completion-observation.md](./2026-09-13-document-revision-fast-completion-observation.md)
|
||||
|
||||
**结论**: 第14轮 UI-11 上传归档后助手已 `completed`;验收默认硬等 inflight 60s,把成功终态误判为失败。
|
||||
|
||||
**整改**: [快速完成观测契约整改](../remediation/2026-09-13-document-revision-fast-completion-observation.md)
|
||||
|
||||
### 质量修复子工作区契约(2026-09-13)
|
||||
|
||||
**文件**: [2026-09-13-document-revision-quality-repair-workspace-contract.md](./2026-09-13-document-revision-quality-repair-workspace-contract.md)
|
||||
|
||||
**结论**: 第13轮 UI-03 质量门禁正确判缺「阻塞信息/非阻塞信息」;repair TASK 引导 `../../output.md`,模型越界改根文件,本地目标缺失,manifest 停在 70。
|
||||
|
||||
**整改**: [质量修复子工作区契约整改](../remediation/2026-09-13-document-revision-quality-repair-workspace-contract.md)
|
||||
|
||||
### 编辑弹窗 hydration 竞态(2026-09-13)
|
||||
|
||||
**文件**: [2026-09-13-document-revision-editor-hydration-race.md](./2026-09-13-document-revision-editor-hydration-race.md)
|
||||
|
||||
**结论**: 第十二轮 UI-06 在 fill 窗口完成后台 hydration,块 ID 被重建;保存按旧 ID 找不到目标后静默关窗,未发 PATCH,修订停在 r0。
|
||||
|
||||
**整改**: [编辑弹窗 hydration 竞态整改](../remediation/2026-09-13-document-revision-editor-hydration-race.md)
|
||||
|
||||
### 对话意图运行时审计(2026-09-13)
|
||||
|
||||
**文件**: [2026-09-13-conversation-intent-runtime-state.md](./2026-09-13-conversation-intent-runtime-state.md)
|
||||
|
||||
**结论**: 真实会话被诊断探针污染;客户端名词匹配令只读总结请求误启动写任务;错误动作与文档租约状态刷新后无法恢复。
|
||||
|
||||
**整改**: [对话意图、可恢复任务状态与文档占用可见性整改](../remediation/2026-09-13-conversation-intent-runtime-state-remediation.md)
|
||||
|
||||
### 刷新历史专项审计(2026-09-13)
|
||||
|
||||
**文件**: [2026-09-13-chat-history-refresh-disappears.md](./2026-09-13-chat-history-refresh-disappears.md)
|
||||
|
||||
**结论**: 消息仍在数据库;文档任务与激活前消息缺阶段作用域,被刷新后的窗口过滤器剔除,而统计仍返回未过滤数量。
|
||||
@@ -23,17 +135,17 @@
|
||||
|
||||
### 0️⃣ 当前状态(Live SSOT)
|
||||
|
||||
**文件**: [gap-matrix.md](../remediation/gap-matrix.md)
|
||||
**协作**: [CURRENT.md](../ops/CURRENT.md) · [AGENTS.md](../../AGENTS.md) · [PROJECT.md](../../PROJECT.md)
|
||||
**用途**: 发布缺口、Codex 再审计闭环证据、发布门禁勾选
|
||||
**文件**: [gap-matrix.md](../remediation/gap-matrix.md)
|
||||
**协作**: [CURRENT.md](../ops/CURRENT.md) · [AGENTS.md](../../AGENTS.md) · [PROJECT.md](../../PROJECT.md)
|
||||
**用途**: 发布缺口、Codex 再审计闭环证据、发布门禁勾选
|
||||
|
||||
---
|
||||
|
||||
### 1️⃣ 从这里开始:审计总结报告(历史)
|
||||
**文件**: `2026-09-12-audit-summary-report.md`
|
||||
**用途**: 项目整体现状、关键数字、风险评估
|
||||
**适合**: 项目经理、技术负责人、快速概览
|
||||
**阅读时间**: 15-20 分钟
|
||||
**文件**: `2026-09-12-audit-summary-report.md`
|
||||
**用途**: 项目整体现状、关键数字、风险评估
|
||||
**适合**: 项目经理、技术负责人、快速概览
|
||||
**阅读时间**: 15-20 分钟
|
||||
|
||||
**关键内容**:
|
||||
- 项目评分及各维度打分
|
||||
@@ -46,10 +158,10 @@
|
||||
---
|
||||
|
||||
### 2️⃣ 详细缺陷与整改:综合整改方案
|
||||
**文件**: `2026-09-12-comprehensive-audit-and-remediation-plan.md`
|
||||
**用途**: 12 个缺陷的详细分析 + 3 个新功能的整改方案
|
||||
**适合**: 架构师、资深开发工程师
|
||||
**阅读时间**: 45-60 分钟
|
||||
**文件**: `2026-09-12-comprehensive-audit-and-remediation-plan.md`
|
||||
**用途**: 12 个缺陷的详细分析 + 3 个新功能的整改方案
|
||||
**适合**: 架构师、资深开发工程师
|
||||
**阅读时间**: 45-60 分钟
|
||||
|
||||
**关键内容**:
|
||||
- BUG-01 到 BUG-12 的代码现场与后果分析
|
||||
@@ -61,10 +173,10 @@
|
||||
---
|
||||
|
||||
### 3️⃣ 可执行的任务拆分:任务清单与验收
|
||||
**文件**: `2026-09-12-remediation-tasks-and-acceptance-checklist.md`
|
||||
**用途**: 具体的代码修改指引、单元测试框架、验收标准
|
||||
**适合**: 开发工程师、QA、代码审查人
|
||||
**阅读时间**: 60-90 分钟
|
||||
**文件**: `2026-09-12-remediation-tasks-and-acceptance-checklist.md`
|
||||
**用途**: 具体的代码修改指引、单元测试框架、验收标准
|
||||
**适合**: 开发工程师、QA、代码审查人
|
||||
**阅读时间**: 60-90 分钟
|
||||
|
||||
**关键内容**:
|
||||
- Task A1-A6:关键缺陷修复(15h)
|
||||
@@ -80,10 +192,10 @@
|
||||
---
|
||||
|
||||
### 4️⃣ 快速参考与速查:快速指南
|
||||
**文件**: `2026-09-12-quick-reference-guide.md`
|
||||
**用途**: 问题症状→原因→解决方案的快速诊断
|
||||
**适合**: 所有开发人员、值班人员
|
||||
**阅读时间**: 5-10 分钟(按需查阅)
|
||||
**文件**: `2026-09-12-quick-reference-guide.md`
|
||||
**用途**: 问题症状→原因→解决方案的快速诊断
|
||||
**适合**: 所有开发人员、值班人员
|
||||
**阅读时间**: 5-10 分钟(按需查阅)
|
||||
|
||||
**关键内容**:
|
||||
- 10 个常见症状的诊断矩阵
|
||||
@@ -100,9 +212,9 @@
|
||||
## 配套参考文档
|
||||
|
||||
### 业务需求原文
|
||||
**文件**: `2026-09-12-three-workflows-strict-governance-remediation.md`
|
||||
**用途**: 业务决策、验收标准的原始出处
|
||||
**适合**: 产品、架构、QA(需要理解业务背景)
|
||||
**文件**: `2026-09-12-three-workflows-strict-governance-remediation.md`
|
||||
**用途**: 业务决策、验收标准的原始出处
|
||||
**适合**: 产品、架构、QA(需要理解业务背景)
|
||||
|
||||
**关键章节**:
|
||||
- 第 3 章:不可违反的业务规则
|
||||
@@ -239,32 +351,32 @@ Day 4-5: Phase C 完善与发布准备(20h)
|
||||
## 常见路径快查
|
||||
|
||||
**"完成工作流后项目仍然是 active"**
|
||||
→ quick-reference-guide.md 第二部分 症状 1
|
||||
→ comprehensive-audit 第二部分 BUG-01
|
||||
→ quick-reference-guide.md 第二部分 症状 1
|
||||
→ comprehensive-audit 第二部分 BUG-01
|
||||
→ remediation-tasks 的 Task A1
|
||||
|
||||
**"对话推进不起作用"**
|
||||
→ quick-reference-guide.md 第二部分 症状 3
|
||||
→ comprehensive-audit 第二部分 BUG-04
|
||||
→ quick-reference-guide.md 第二部分 症状 3
|
||||
→ comprehensive-audit 第二部分 BUG-04
|
||||
→ remediation-tasks 的 Task A4
|
||||
|
||||
**"禁用文档仍能被打开"**
|
||||
→ quick-reference-guide.md 第二部分 症状 2
|
||||
→ comprehensive-audit 第二部分 BUG-05
|
||||
→ quick-reference-guide.md 第二部分 症状 2
|
||||
→ comprehensive-audit 第二部分 BUG-05
|
||||
→ remediation-tasks 的 Task A5
|
||||
|
||||
**"激活 token 可能被重复使用"**
|
||||
→ quick-reference-guide.md 第二部分 症状 6
|
||||
→ comprehensive-audit 第二部分 BUG-06
|
||||
→ quick-reference-guide.md 第二部分 症状 6
|
||||
→ comprehensive-audit 第二部分 BUG-06
|
||||
→ remediation-tasks 的 Task A6
|
||||
|
||||
**"无法运行测试流程"**
|
||||
→ quick-reference-guide.md 第二部分 症状 7
|
||||
→ comprehensive-audit 第三部分 MISSING-06
|
||||
→ quick-reference-guide.md 第二部分 症状 7
|
||||
→ comprehensive-audit 第三部分 MISSING-06
|
||||
→ remediation-tasks 的 Phase B 开始
|
||||
|
||||
**"需要完整 E2E 验证"**
|
||||
→ comprehensive-audit 第三部分 MISSING-04
|
||||
→ comprehensive-audit 第三部分 MISSING-04
|
||||
→ remediation-tasks 的 Task B2
|
||||
|
||||
---
|
||||
|
||||
+76
-10
@@ -1,27 +1,66 @@
|
||||
# 当前焦点
|
||||
|
||||
**更新**: 2026-09-13
|
||||
**production_ready**: no(对话刷新恢复、CI 真实 PI E2E、前端人工抽检待完成)
|
||||
**更新**: 2026-09-14
|
||||
**production_ready**: no(`CHAT-INTENT-STATE` 等无关 blocker 仍开放。文档账本运行时 UI Round20 **PASS**,不把 fallback change report 写成完整 PI,也不把本轮写成全仓可发布)
|
||||
|
||||
## 焦点
|
||||
|
||||
1. **CHAT**: [刷新恢复整改待实施](short-term/2026-09-13-chat-history-refresh-remediation.md)(发布 blocker)
|
||||
2. **CI**: `TEST_DATABASE_URL` + 真实 PI E2E 实录
|
||||
3. **前端**: 版本冲突刷新、终止 preview 人工抽检
|
||||
1. **WORKFLOW-PLAN**: [冻结 409 与文档职责可选治理](../audit/2026-09-14-workflow-plan-409-frozen-and-optional-duties.md)(Wave 1–4 已在 `fix/workflow-plan-409-frozen-and-optional-duties` 落地;Wave 5 占槽 e2e 进行中;后续治理原则见 [MVP 治理规则评审](../ops/research/2026-09-14-mvp-governance-rules-review.md))
|
||||
2. **CHAT-INTENT**: [对话意图运行时状态](../audit/2026-09-13-conversation-intent-runtime-state.md)(`fix/conversation-intent-state`;与文档账本运行时无关)
|
||||
3. **CHAT**: [对话历史刷新](../audit/2026-09-13-chat-history-refresh-disappears.md)(认领仍 `in_progress`;gap 行已 PASS,以代码/handoff 为准收敛)
|
||||
|
||||
## 并行认领
|
||||
|
||||
| owner | task | branch | worktree | mutex | status |
|
||||
|-------|------|--------|----------|-------|--------|
|
||||
| — | — | — | — | — | — |
|
||||
| verifier_antigravity | controlled-content-ui-acceptance | fix/controlled-content-ui-acceptance | .worktrees/fix-controlled-content-ui-acceptance | document-content-ui-acceptance | done |
|
||||
| implementer_cursor | controlled-content-canonical-hash | fix/controlled-content-canonical-hash | .worktrees/fix-controlled-content-canonical-hash | docgov | done |
|
||||
| Codex | project143-controlled-content-404-diagnosis | fix/project143-controlled-content-404-diagnosis | - | docgov-content-diagnosis | done |
|
||||
| Codex | software-project-bootstrap-plan | feature/software-project-bootstrap-plan | - | workflow-design | done |
|
||||
| Cursor | chat-history-refresh-remediation | fix/chat-history-refresh | - | chat | in_progress |
|
||||
| Codex | conversation-intent-runtime-state | fix/conversation-intent-state | .worktrees/fix-conversation-intent-state | intent | in_progress |
|
||||
| Cursor | document-revision-wave1-6-implementation | feature/document-revision-management | - | docgov | done |
|
||||
| Cursor-Auto | document-revision-runtime-ui03 | fix/document-revision-runtime-ui03 | - | docgov | done |
|
||||
| Cursor-Auto | document-revision-sse-idempotency | fix/document-revision-sse-idempotency | - | docgov | done |
|
||||
| Cursor-Auto | document-revision-active-doc-routing | fix/document-revision-active-doc-routing | - | docgov | done |
|
||||
| Cursor-Auto | document-revision-quality-context | fix/document-revision-quality-context | - | docgov | done |
|
||||
| Cursor-Auto | document-revision-e2e-pending-flow | fix/document-revision-e2e-pending-flow | - | pending-report-ui | done |
|
||||
| Cursor-Auto | document-revision-e2e-reject-routing | fix/document-revision-e2e-reject-routing | - | document-revision-runtime-ui | done |
|
||||
| Cursor-Auto | document-revision-e2e-block-selector | fix/document-revision-e2e-block-selector | - | document-revision-block-selector | done |
|
||||
| Cursor-Auto | document-revision-e2e-save-selector | fix/document-revision-e2e-save-selector | - | document-revision-save-selector | done |
|
||||
| Cursor-Auto | document-revision-e2e-overlay-selector | fix/document-revision-e2e-overlay-selector | - | document-revision-overlay-selector | done |
|
||||
| Cursor-Auto | document-revision-e2e-overlay-transition | fix/document-revision-e2e-overlay-transition | - | document-revision-overlay-transition | done |
|
||||
| Cursor-Auto | document-revision-second-doc-routing-lease | fix/document-revision-second-doc-routing-lease | - | document-revision-second-doc-routing-lease | done |
|
||||
| Cursor-Auto | document-revision-prelim-output | fix/document-revision-pi-runner-module | - | document-revision-prelim-output | done |
|
||||
| Cursor-Auto | document-revision-editor-hydration-race | fix/document-revision-editor-hydration-race | - | document-revision-editor-hydration-race | done |
|
||||
| Cursor-Auto | document-revision-quality-repair-workspace-contract | fix/document-revision-quality-repair-workspace-contract | - | document-revision-quality-repair-workspace-contract | done |
|
||||
| Cursor-Auto | document-revision-fast-completion-observation | fix/document-revision-fast-completion-observation | - | document-revision-fast-completion-observation | done |
|
||||
| Cursor-Auto | document-revision-workflow-category-navigation | fix/document-revision-workflow-category-navigation | - | document-revision-workflow-category-navigation | done |
|
||||
| Cursor-Auto | document-revision-duty-cell-assertion | fix/document-revision-duty-cell-assertion | - | document-revision-duty-cell-assertion | done |
|
||||
| Cursor-Auto | document-revision-reviewer-duty-sync | fix/document-revision-reviewer-duty-sync | - | document-revision-reviewer-duty-sync | done |
|
||||
| Cursor-Auto | document-revision-post-restart-selector | fix/document-revision-post-restart-selector | - | document-revision-post-restart-selector | done |
|
||||
| Cursor-Auto | document-revision-post-restart-final-snippet | fix/document-revision-post-restart-final-snippet | - | document-revision-post-restart-final-snippet | done |
|
||||
| Cursor-Auto | document-revision-pg-id-remap | fix/document-revision-pg-id-remap | - | document-revision | done |
|
||||
| Cursor-Auto | document-revision-runtime | fix/document-revision-runtime-ui03 | - | docgov | done |
|
||||
| Cursor-Auto | document-revision-runtime-ui-final-report | feature/document-revision-runtime-ui-final-report | - | document-revision-runtime-ui | done |
|
||||
| Cursor-Auto | document-revision-evidence-count | fix/document-revision-evidence-count | - | document-revision-evidence-count | done |
|
||||
| Cursor-Auto | document-revision-session-close | feature/document-revision-session-close | - | document-revision-session-close | done |
|
||||
| Cursor-Auto | vite-frp-allowed-hosts | fix/vite-frp-allowed-hosts | - | web-devserver | done |
|
||||
| Cursor-Auto | remove-herdr-agent-settings | feature/remove-herdr-agent-settings | - | agent-collab-docs | done |
|
||||
| implementer_cursor | workflow-plan-409-frozen-and-optional-duties | fix/workflow-plan-409-frozen-and-optional-duties | .worktrees/fix-workflow-plan-409-frozen-and-optional-duties | workflow | in_progress |
|
||||
| Cline | governance-action-level-authz | fix/governance-action-level-authz | - | workflow | blocked |
|
||||
| Cursor | module-decoupling-wave0 | feature/remove-herdr-agent-settings | - | arch | done |
|
||||
|
||||
> 新任务开始前登记。`branch` 必须为 `feature/<slug>` 或 `fix/<slug>`,**禁止** `dev` / `test` / `main`。同一 `mutex` 同时仅一个 `in_progress`。
|
||||
|
||||
> `workflow-plan-409-frozen-and-optional-duties` 已由 implementer_cursor 接管:worktree 已创建,Wave 1–4 提交落地,Wave 5 占集成槽位(e2e)进行中。
|
||||
> `governance-action-level-authz` blocked 仅为等待同 mutex `workflow` 的 Wave 5 收敛;收敛后从最新 `dev` 创建 `fix/governance-action-level-authz` 并改 `in_progress`,不得在当前 `feature/remove-herdr-agent-settings` 工作区编码。
|
||||
|
||||
## 集成槽位
|
||||
|
||||
| holder | phase | since | scope | queue |
|
||||
|--------|-------|-------|-------|-------|
|
||||
| idle | - | - | - | - |
|
||||
| implementer_cursor | e2e | 2026-09-14 | workflow-plan 409 frozen + optional duties | governance-action-level-authz |
|
||||
|
||||
**phase**: `idle` | `merging` | `smoke` | `e2e`
|
||||
|
||||
@@ -31,9 +70,9 @@
|
||||
|
||||
| 环境 | 端口 | schema | 状态 |
|
||||
|------|------|--------|------|
|
||||
| dev | 8080 | 25 | healthy |
|
||||
| test | 8081 | 25 | healthy |
|
||||
| main | 8000 | 25 | healthy(app + runner + DB) |
|
||||
| dev | 8080 | **32** | healthy(产品代码部署为 `36e4bc3`;真实 UI 主链+restart PASS) |
|
||||
| test | 8081 | 25→27* | healthy |
|
||||
| main | 8000 | 25→27* | healthy(app + runner + DB) |
|
||||
|
||||
## SSOT
|
||||
|
||||
@@ -44,3 +83,30 @@
|
||||
| 发布缺口 | [gap-matrix](../remediation/gap-matrix.md) |
|
||||
| 测试报告 | [test-reports/](../test-reports/) |
|
||||
| Agent 手册 | [AGENTS.md](../../AGENTS.md) |
|
||||
| 受控正文 hash 漂移 W1–W6 | [../ops/handoffs/2026-09-14-controlled-content-canonical-hash.md](../ops/handoffs/2026-09-14-controlled-content-canonical-hash.md) |
|
||||
| DOCREV ADR | [../adr/2026-09-13-document-version-boundary.md](../adr/2026-09-13-document-version-boundary.md) |
|
||||
| DOCREV 管理测试 | [../test-reports/2026-09-13-document-revision-management-test-report.md](../test-reports/2026-09-13-document-revision-management-test-report.md) |
|
||||
| DOCREV 运行时 UI Round20 | [../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md](../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md) |
|
||||
| 纯软件项目自举设计 | [../system-design/2026-09-14-software-project-bootstrap-workflow.md](../system-design/2026-09-14-software-project-bootstrap-workflow.md) |
|
||||
| SSE/幂等审计 | [../audit/2026-09-13-document-revision-sse-idempotency.md](../audit/2026-09-13-document-revision-sse-idempotency.md) |
|
||||
| 质量门禁自污染审计 | [../audit/2026-09-13-document-revision-quality-gate-self-pollution.md](../audit/2026-09-13-document-revision-quality-gate-self-pollution.md) |
|
||||
| 当前文档路由审计 | [../audit/2026-09-13-document-revision-active-doc-routing.md](../audit/2026-09-13-document-revision-active-doc-routing.md) |
|
||||
| 行动表状态假阳性审计 | [../audit/2026-09-13-document-revision-quality-status-false-positive.md](../audit/2026-09-13-document-revision-quality-status-false-positive.md) |
|
||||
| 待确认报告选择失败审计 | [../audit/2026-09-13-document-revision-pending-report-selection.md](../audit/2026-09-13-document-revision-pending-report-selection.md) |
|
||||
| UI-05b 拒绝路由失败审计 | [../audit/2026-09-13-document-revision-e2e-reject-routing.md](../audit/2026-09-13-document-revision-e2e-reject-routing.md) |
|
||||
| 职责伪造与 ETag 覆盖审计 | [../audit/2026-09-13-document-revision-duty-etag-overwrite.md](../audit/2026-09-13-document-revision-duty-etag-overwrite.md) |
|
||||
| UI-06 块选择器失败审计 | [../audit/2026-09-13-document-revision-block-selector.md](../audit/2026-09-13-document-revision-block-selector.md) |
|
||||
| UI-06 保存选择器失败审计 | [../audit/2026-09-13-document-revision-save-selector.md](../audit/2026-09-13-document-revision-save-selector.md) |
|
||||
| UI-07 纯净阅读取样失败审计 | [../audit/2026-09-13-document-revision-overlay-selector.md](../audit/2026-09-13-document-revision-overlay-selector.md) |
|
||||
| UI-07 transition 中间帧取样审计 | [../audit/2026-09-13-document-revision-overlay-transition.md](../audit/2026-09-13-document-revision-overlay-transition.md) |
|
||||
| UI-11 第二份文档路由与 lease 审计 | [../audit/2026-09-13-document-revision-second-doc-routing-lease.md](../audit/2026-09-13-document-revision-second-doc-routing-lease.md) |
|
||||
| UI-11 prelim_design 缺 output.md 审计 | [../audit/2026-09-13-document-revision-prelim-output.md](../audit/2026-09-13-document-revision-prelim-output.md) |
|
||||
| UI-06 编辑弹窗 hydration 竞态审计 | [../audit/2026-09-13-document-revision-editor-hydration-race.md](../audit/2026-09-13-document-revision-editor-hydration-race.md) |
|
||||
| UI-03 质量修复子工作区契约审计 | [../audit/2026-09-13-document-revision-quality-repair-workspace-contract.md](../audit/2026-09-13-document-revision-quality-repair-workspace-contract.md) |
|
||||
| UI-11 快速完成观测误判审计 | [../audit/2026-09-13-document-revision-fast-completion-observation.md](../audit/2026-09-13-document-revision-fast-completion-observation.md) |
|
||||
| UI-13a 私密分类导航失败审计 | [../audit/2026-09-13-document-revision-workflow-category-navigation.md](../audit/2026-09-13-document-revision-workflow-category-navigation.md) |
|
||||
| UI-13a 职责单元格误判审计 | [../audit/2026-09-13-document-revision-duty-cell-assertion.md](../audit/2026-09-13-document-revision-duty-cell-assertion.md) |
|
||||
| UI-13a reviewer 职责未同步审计 | [../audit/2026-09-13-document-revision-reviewer-duty-sync.md](../audit/2026-09-13-document-revision-reviewer-duty-sync.md) |
|
||||
| UI-03 首次生成 PG ID 误删 baseline | [../audit/2026-09-13-document-revision-pg-id-remap.md](../audit/2026-09-13-document-revision-pg-id-remap.md) |
|
||||
| UI-06 刷新后缓存竞争死锁审计 | [../audit/2026-09-14-document-revision-refresh-cache-race.md](../audit/2026-09-14-document-revision-refresh-cache-race.md) |
|
||||
| 受控正文真实 UI 验收报告 | [../test-reports/2026-09-14-controlled-content-ui-acceptance.md](../test-reports/2026-09-14-controlled-content-ui-acceptance.md) |
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
title: "对话刷新恢复整改 Checklist"
|
||||
status: in_progress
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
related_task: "../short-term/2026-09-13-chat-history-refresh-remediation.md"
|
||||
---
|
||||
|
||||
# 对话刷新恢复整改 Checklist
|
||||
|
||||
## Wave 0 — 锁定回归
|
||||
|
||||
- [x] `MessageVisible` / `ScopeFromMetadata` 单测 — 证据:`internal/projectinstance/message_scope_test.go`
|
||||
- [x] PG 集成:激活前 + 任务 scope + 刷新窗口 — 证据:`internal/server/chat_history_refresh_pg_test.go`
|
||||
- [x] 前端:空 messages 日桶不覆盖缓存 — 证据:`web/src/hooks/useChatWindow.ts`
|
||||
|
||||
## Wave 1 — 写入作用域
|
||||
|
||||
- [x] Goose `00026` 列迁移 — 证据:`deploy/postgres/goose/00026_2026-09-13-chat-message-scope.sql`
|
||||
- [x] `ResolveMessageScopeForChat/Task` — 证据:`internal/projectinstance/message_scope.go`
|
||||
- [x] 任务/聊天写入接线 — 证据:`task_run_handlers.go`, `session.go`, `ctxmgr/manager.go`
|
||||
|
||||
## Wave 2 — 授权同集
|
||||
|
||||
- [x] `authorizeSessionRead` + 可见性谓词 — 证据:`internal/server/chat_history_auth.go`
|
||||
- [x] window/day/search/dates/categories/unread/digest 授权 — 证据:各 `*_api.go`
|
||||
|
||||
## Wave 3 — 历史回填
|
||||
|
||||
- [x] Goose `00027` backfill SQL — 证据:`deploy/postgres/goose/00027_2026-09-13-chat-message-scope-backfill.sql`
|
||||
|
||||
## Wave 4 — 前端恢复态
|
||||
|
||||
- [x] `useChatWindow` 阶段态 + 用户隔离缓存 — 证据:`web/src/hooks/useChatWindow.ts`, `web/src/data/storage.ts`
|
||||
|
||||
## Wave 5 — 验收
|
||||
|
||||
- [x] `go test -short ./...` — 证据:本机执行输出
|
||||
- [ ] 真实 PI 刷新 E2E(需 dev 容器 + pi-agent)— 证据:待 test-report 补录
|
||||
- [x] 测试报告归档 — 证据:`.doc/test-reports/2026-09-13-chat-history-refresh-test-report.md`
|
||||
|
||||
## 完成定义
|
||||
|
||||
- [ ] 全部勾选且有证据链接
|
||||
- [ ] gap-matrix `CHAT-HISTORY-REFRESH` → PASS
|
||||
@@ -0,0 +1,45 @@
|
||||
# 受控文档正文修复真实 UI 验收 Checklist
|
||||
|
||||
## 执行身份与环境
|
||||
|
||||
- [x] 报告 Antigravity CLI / 实际模型。
|
||||
- [x] 阅读 `AGENTS.md`、`PROJECT.md`、`.doc/README.md`、`.doc/ops/CURRENT.md`、任务文、审计与整改方案。
|
||||
- [x] 使用 `mcr.microsoft.com/playwright:v1.63.0-noble`、`--network host`、`BASE_URL=http://127.0.0.1:3100`。
|
||||
- [x] acceptance worktree 挂载 `/work`,主仓 `web/node_modules` 只读挂载到 `/work/web/node_modules`。
|
||||
- [x] 管理员凭证只从 `shuimu-agent-app-dev` 容器环境安全传入,不输出、不截图、不提交。
|
||||
|
||||
## 强制边界
|
||||
|
||||
- [x] 用户、项目、成员、对话、文档、小队、编辑等数据只由 Playwright `page` 的真实 UI 操作产生。
|
||||
- [x] 不用 `page.request`、`context.request`、curl、API 直调、DB 写、route/mock/stub、localStorage 注入。
|
||||
- [x] 网络响应只用于监听和断言;PASS 必须同时有页面可见证据。
|
||||
- [x] 不复用主仓旧 phase state/旧 PASS;失败原样记录。
|
||||
- [x] 不从 worktree 重启共享 Docker;主阶段后输出 `NEEDS_HOST_RESTART`(若主阶段遇到 FAIL 阻塞,则先定位并等待修复,不提前重启)。
|
||||
|
||||
## A. 项目 143 回归(clean-run3 全部 PASS)
|
||||
|
||||
- [x] admin 从登录页登录,经 UI 打开项目标题“对话协同会话”(原项目143对应UI会话)。
|
||||
- [x] 经 UI 打开 `doc_proj143_intake`(用户初始需求收集表),正文非空、账本就绪。
|
||||
- [x] console/pageerror 无相关错误,content 与 revision-state 均无 404;初始 legacy doc-001 请求严格为 0。
|
||||
- [x] 初次稳定后空闲 30 秒,无新增重复正文请求、无闪烁。
|
||||
- [x] 双击真实块,追加唯一中文标记,保存后页面可见且修订号增加(r1 -> r2)。
|
||||
- [x] 纯净阅读 / 人工修改 / 全部变更均验证 active 状态与真实装饰差异。
|
||||
- [x] 刷新、退出、重新登录,再打开同一项目/文档,标记与修订号持久化。
|
||||
- [x] 截图、trace、结果写 `.doc/test-reports/assets/2026-09-14-controlled-content-ui-acceptance/clean-run3/`。
|
||||
|
||||
## B. 新项目真实全链路(full-chain-final 全部 PASS)
|
||||
|
||||
- [x] 审读并运行 `web/e2e/document-revision-runtime.spec.ts` main phase;该测试只能通过 UI 建 A/B/C、新项目和全部数据。
|
||||
- [x] 真实产品 PI/小队完成初次文档生成和二次修改;页面显示本轮用户输入与 assistant 终态回复。
|
||||
- [x] 页面显示文档正文、版本账本、人工编辑、三模式(UI-06 刷新后通过,UI-07/08/09 三模式计算样式互斥通过)。
|
||||
- [x] 页面打开真实 change report,并显示项目影响、文档影响、风险、开放问题。
|
||||
- [x] 并发编辑、审核人、无关用户权限边界有 UI 证据(UI-12/13a/13b 均通过)。
|
||||
- [x] 产生本轮非敏感 phase state、截图、results 并提交 Git;本地运行产生的 trace/video/HTML 报告未提交仓库;本地 secrets 继续 ignored 且绝不披露。
|
||||
- [x] 主阶段写报告草稿并输出 `NEEDS_HOST_RESTART`,等待 orchestrator 重启。
|
||||
|
||||
## C. 重启后(由 orchestrator 重启并执行 post-restart 全部 PASS)
|
||||
|
||||
- [x] 仅用 UI 重新登录、打开本轮新项目与文档(UI-15 post-restart 2.8s 通过)。
|
||||
- [x] 正文唯一标记(A1-win-mu0oymfg)、版本/修订(V3/r2)页面可见。
|
||||
- [x] 目标受控文档 404 严格为 0。
|
||||
- [x] 完成报告;如实记录全部结果,主阶段与重启后产物完好归档。
|
||||
@@ -0,0 +1,207 @@
|
||||
---
|
||||
title: "纯软件项目自举工作流验收清单"
|
||||
status: planned
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-14
|
||||
related_task: "ops/long-term/2026-09-14-software-project-bootstrap-implementation.md"
|
||||
---
|
||||
|
||||
# 纯软件项目自举工作流验收清单
|
||||
|
||||
> 本文件是未来实施验收计划,当前全部用例均为 `NOT RUN`。不得把设计评审、stub、接口注入或静态 JSON 写成真实功能 PASS。
|
||||
|
||||
## 0. 验收分层
|
||||
|
||||
| 层 | 范围 | 可否代替真实 UI |
|
||||
|----|------|-----------------|
|
||||
| L1 | manifest、profile、模板、quality gate 单元测试 | 否 |
|
||||
| L2 | PostgreSQL 迁移、领域服务、API、鉴权、并发 | 否 |
|
||||
| L3 | 前端组件、类型、build | 否 |
|
||||
| L4 | stub 小队和固定输出工程测试 | 否 |
|
||||
| L5 | 真实 PI Agent Runner | 否,仍需页面验证 |
|
||||
| L6 | Ubuntu Server 无头浏览器真实页面操作 | 是,最终验收 |
|
||||
|
||||
## 1. 工程门禁
|
||||
|
||||
### Manifest 与目录
|
||||
|
||||
- [ ] `software_bootstrap` 和 `software_delivery` 均可校验、发布和退役 — 证据:NOT RUN
|
||||
- [ ] 非 published / 非 selectable / 不兼容 domain 的工作流不出现在项目目录 — 证据:NOT RUN
|
||||
- [ ] 新版本不会改变已激活实例的 manifest/template/profile hash — 证据:NOT RUN
|
||||
- [ ] 医疗现有三工作流及黄金用例无回归 — 证据:NOT RUN
|
||||
- [ ] 不再依赖“三正式 key”或固定文档数量硬编码 — 证据:NOT RUN
|
||||
|
||||
### 数据与迁移
|
||||
|
||||
- [ ] 空数据库从 schema 1 升级并创建项目类型、profile、source binding — 证据:NOT RUN
|
||||
- [ ] 旧数据库升级不误分类既有项目 — 证据:NOT RUN
|
||||
- [ ] secret 只存引用,数据库、文档、日志和 prompt 无明文 — 证据:NOT RUN
|
||||
- [ ] 项目、成员、planning instance、模板账本创建具备幂等事务语义 — 证据:NOT RUN
|
||||
- [ ] 应用重启后项目、来源、plan、阶段和文档版本可恢复 — 证据:NOT RUN
|
||||
|
||||
### 授权与治理
|
||||
|
||||
- [ ] 非成员无法列出项目、对话、来源、文档、SSE、RAG 或 Agent 结果 — 证据:NOT RUN
|
||||
- [ ] 非创建者无法激活、推进、选择下一流程或终止 — 证据:NOT RUN
|
||||
- [ ] 客户端伪造 task/stage/duty/repo path 被服务端拒绝 — 证据:NOT RUN
|
||||
- [ ] collaborative 模式三权必须不同人 — 证据:NOT RUN
|
||||
- [ ] solo 只允许 creator acknowledgement 且页面显示“未独立评审” — 证据:NOT RUN
|
||||
- [ ] controlled profile 禁止 solo — 证据:NOT RUN
|
||||
- [ ] 激活后 workflow/template/profile/duty 不能直接修改 — 证据:NOT RUN
|
||||
|
||||
### 小队与文档
|
||||
|
||||
- [ ] 每个 executor/template/quality gate/profile 均注册且可解析 — 证据:NOT RUN
|
||||
- [ ] 正式任务只能从冻结 doc_task_instance 启动 — 证据:NOT RUN
|
||||
- [ ] 步骤预算、timeout、工作区边界和 manifest 生效 — 证据:NOT RUN
|
||||
- [ ] 失败、跳过、fallback、未验证项不会被改写成 PASS — 证据:NOT RUN
|
||||
- [ ] 非医疗默认小队不包含 regulatory — 证据:NOT RUN
|
||||
- [ ] 纯软件模板和回复无医疗默认术语污染 — 证据:NOT RUN
|
||||
|
||||
## 2. Ubuntu Server 真实 UI 前置
|
||||
|
||||
- [ ] 占用 CURRENT 集成槽位 — 证据:NOT RUN
|
||||
- [ ] `go vet ./...`、`go test -short ./...`、前端测试/build 通过 — 证据:NOT RUN
|
||||
- [ ] PostgreSQL、app、真实 PI Runner、MiniMax 均 ready — 证据:NOT RUN
|
||||
- [ ] 明确记录 commit、schema、镜像、模型、BASE_URL 和开始时间 — 证据:NOT RUN
|
||||
- [ ] 使用官方 Playwright Chromium 容器;宿主无需安装浏览器 — 证据:NOT RUN
|
||||
- [ ] 若容器不可用,才执行 `npx playwright install --with-deps chromium` — 证据:NOT RUN
|
||||
- [ ] 禁止 `page.route`、mock/stub、直接写数据库或伪造 API 输出 — 证据:NOT RUN
|
||||
|
||||
推荐运行形态:
|
||||
|
||||
```bash
|
||||
docker run --rm --network host --ipc host \
|
||||
-e BASE_URL=http://127.0.0.1:3100 \
|
||||
-v "$PWD:/work" -w /work \
|
||||
mcr.microsoft.com/playwright:v1.63.0-noble \
|
||||
npx playwright test <software-bootstrap-ui-spec>
|
||||
```
|
||||
|
||||
## 3. 真实 UI 用例
|
||||
|
||||
### UI-SW-00 项目类型与向导
|
||||
|
||||
- **Input**:管理员登录;打开创建项目;选择 non-medical software。
|
||||
- **Expected**:展示七步软件字段;不出现医疗器械固定标题、临床用途或 NMPA 默认值。
|
||||
- **Evidence**:截图、trace、console/network 日志。
|
||||
- **Status**:NOT RUN。
|
||||
|
||||
### UI-SW-01 既有项目单人创建
|
||||
|
||||
- **Input**:`existing_self_bootstrap + standard + solo + docs_only`;页面上传允许的仓库说明和文档。
|
||||
- **Expected**:确认页显示 creator acknowledgement 和“未独立评审”;一次提交后项目、成员、plan 和模板可见;重复提交不创建第二项目。
|
||||
- **Evidence**:截图、项目 ID、页面列表、trace。
|
||||
- **Status**:NOT RUN。
|
||||
|
||||
### UI-SW-02 协作项目职责
|
||||
|
||||
- **Input**:创建 collaborative 项目并选择至少三名成员。
|
||||
- **Expected**:逐文档分配 author/reviewer/approver;重复人员不能激活;修正后预览成功。
|
||||
- **Evidence**:职责矩阵截图、错误提示、激活预览。
|
||||
- **Status**:NOT RUN。
|
||||
|
||||
### UI-SW-03 激活冻结
|
||||
|
||||
- **Input**:保存 plan、查看预览、确认激活;随后尝试修改模板、profile 或职责。
|
||||
- **Expected**:实例引用固定版本/hash;直接修改被拒绝;409 时展示差异且不自动重试。
|
||||
- **Evidence**:预览、实例详情、拒绝提示。
|
||||
- **Status**:NOT RUN。
|
||||
|
||||
### UI-SW-04 真实基线小队
|
||||
|
||||
- **Input**:在对话框输入“请基于我上传的项目资料,正式启动现状梳理并生成现状审计”。
|
||||
- **Expected**:页面可见真实小队、角色、步骤、进度、真实助手回复;生成 `current_state_audit`,不是聊天长回答。
|
||||
- **Evidence**:对话、步骤条、文档截图、trace/video。
|
||||
- **Status**:NOT RUN。
|
||||
|
||||
### UI-SW-05 事实等级与证据
|
||||
|
||||
- **Input**:打开现状审计和架构基线。
|
||||
- **Expected**:confirmed/inferred/unverified 可区分;high 问题有来源;找不到的信息明确写未验证。
|
||||
- **Evidence**:文档截图、来源清单、版本账本。
|
||||
- **Status**:NOT RUN。
|
||||
|
||||
### UI-SW-06 软件语义隔离
|
||||
|
||||
- **Input**:使用不含医疗内容的软件项目材料跑完整 bootstrap。
|
||||
- **Expected**:项目、回复、模板和文档中不出现临床、注册、NMPA、GB 9706、CDMO 等默认语义。
|
||||
- **Evidence**:页面全文搜索和截图;任何命中逐条说明来源。
|
||||
- **Status**:NOT RUN。
|
||||
|
||||
### UI-SW-07 文档变更链
|
||||
|
||||
- **Input**:人工编辑一个块并保存;再通过真实对话要求小队更新同一文档。
|
||||
- **Expected**:revision 增长、刷新保留;agent candidate 有 diff、风险、项目/文档影响和开放问题;确认/拒绝行为正确。
|
||||
- **Evidence**:版本、revision、overlay、报告截图。
|
||||
- **Status**:NOT RUN。
|
||||
|
||||
### UI-SW-08 阶段门禁与创建者确认
|
||||
|
||||
- **Input**:文档未批准时尝试推进;完成审核批准后等待通知;创建者确认推进。
|
||||
- **Expected**:未批准时列出 blocker;就绪只通知一次;不自动推进;非创建者不可推进。
|
||||
- **Evidence**:readiness 面板、通知、阶段前后截图。
|
||||
- **Status**:NOT RUN。
|
||||
|
||||
### UI-SW-09 Bootstrap 就绪
|
||||
|
||||
- **Input**:完成所有启用阶段并打开 readiness。
|
||||
- **Expected**:汇总风险、依赖和未验证项;存在 high blocker 时不可批准;通过后 workflow completed。
|
||||
- **Evidence**:readiness 文档、阶段树、审计事件。
|
||||
- **Status**:NOT RUN。
|
||||
|
||||
### UI-SW-10 下一工作流建议
|
||||
|
||||
- **Input**:bootstrap 完成。
|
||||
- **Expected**:页面建议 `software_delivery`,但不自动创建或激活;仅创建者确认后生成新的 planning instance。
|
||||
- **Evidence**:建议卡、确认前后实例列表。
|
||||
- **Status**:NOT RUN。
|
||||
|
||||
### UI-SW-11 Delivery 迭代
|
||||
|
||||
- **Input**:建立 change brief 和 implementation plan,上传外部实现的 change manifest 与真实测试报告。
|
||||
- **Expected**:trace 到 bootstrap requirements;失败/跳过测试阻断发布;用户确认后完成迭代。
|
||||
- **Evidence**:文档血缘、测试报告、门禁、release notes。
|
||||
- **Status**:NOT RUN。
|
||||
|
||||
### UI-SW-12 权限负例
|
||||
|
||||
- **Input**:非成员和 viewer 登录;篡改 URL 中 project/doc/run/source ID。
|
||||
- **Expected**:服务端 403/404;页面无数据泄露;SSE 不先 flush 200。
|
||||
- **Evidence**:页面错误、network、服务端审计。
|
||||
- **Status**:NOT RUN。
|
||||
|
||||
### UI-SW-13 刷新与重启恢复
|
||||
|
||||
- **Input**:记录项目/实例/阶段/文档版本和正文;硬刷新、退出重登;仅 restart app 后再次登录。
|
||||
- **Expected**:对话、任务、阶段、文档、职责、风险、V/r 和正文一致恢复。
|
||||
- **Evidence**:pre/post state 文件和截图。
|
||||
- **Status**:NOT RUN。
|
||||
|
||||
### UI-SW-14 Agent-System 自举黄金项目
|
||||
|
||||
- **Input**:用 Agent-System 当前仓库作为只读来源,真实执行 software_bootstrap。
|
||||
- **Expected**:页面生成当前态审计、架构、需求/backlog、风险、路线图和测试策略;当前结论重新核验,不照抄历史审计;不修改仓库。
|
||||
- **Evidence**:完整对话、全部文档、版本、trace/video、来源 hash。
|
||||
- **Status**:NOT RUN。
|
||||
|
||||
## 4. 未来 controlled patch 负例
|
||||
|
||||
- [ ] repo 未绑定不能执行 — 证据:NOT RUN
|
||||
- [ ] 非 allowlist 路径被拒绝 — 证据:NOT RUN
|
||||
- [ ] `.env`、secret、生产 dump 排除有效 — 证据:NOT RUN
|
||||
- [ ] 只在 feature worktree 写入 — 证据:NOT RUN
|
||||
- [ ] 超出批准文件范围立即停止 — 证据:NOT RUN
|
||||
- [ ] 测试失败不自动 merge — 证据:NOT RUN
|
||||
- [ ] 批准执行不等于批准 merge/push/deploy — 证据:NOT RUN
|
||||
- [ ] 保护分支直接 commit、force push、破坏性命令均被拒绝 — 证据:NOT RUN
|
||||
|
||||
## 5. 完成定义
|
||||
|
||||
- [ ] L1–L5 工程门禁分别记录真实结果
|
||||
- [ ] UI-SW-00–14 全部由真实页面操作执行并留证
|
||||
- [ ] 真实 PI 回复、小队进度和所有交付文档均可在 UI 看到
|
||||
- [ ] 医疗与软件两套黄金项目均无回归
|
||||
- [ ] 刷新、重登、重启、并发和权限负例通过
|
||||
- [ ] test-report 逐项包含 Input/Expected/Actual/Verdict/Duration
|
||||
- [ ] 任何 NOT RUN、fallback、失败和开放风险均如实保留
|
||||
@@ -0,0 +1,142 @@
|
||||
---
|
||||
title: "受控正文 canonical hash 漂移 W1–W6 + 审查修补交接"
|
||||
created: 2026-09-14
|
||||
from: implementer_cursor
|
||||
to: orchestrator_codex / W7 holder
|
||||
status: done
|
||||
---
|
||||
|
||||
# 交接:受控正文 canonical hash 漂移
|
||||
|
||||
## 目标(下一位 Agent 应完成什么)
|
||||
|
||||
占 CURRENT 集成槽后将 `fix/controlled-content-canonical-hash` `--no-ff` 合入 `dev`,`env-service.sh dev rebuild`,**先对项目 143 完成 live dry-run + apply**,再做 W8 真实 UI。合入后若未 repair 就打开页面,content API 会返回 `DOCUMENT_CONTENT_PROJECTION_DRIFT`,而不会静默展示裁掉硬换行的旧 head。
|
||||
|
||||
## 已完成
|
||||
|
||||
- W1–W6 工程实现与门禁
|
||||
- 合入前审查修补:
|
||||
- goose `00032` 允许 `migration_repair` source/change kind
|
||||
- `migration_repair` 不递增 `head_revision_no` / `human_revision_count`;ETag 随新 snapshot ID 变化
|
||||
- CLI 显式 live 模式 + `/app/data` → host data root 映射
|
||||
- `MarkDocumentContentUpdated` 未预加载时从 DB 装入;aligned/retry 仍同步记录哈希
|
||||
- 读路径对 legacy/fork 返回结构化冲突
|
||||
- follow-up:apply 同时备份原文件与**旧 head 正文**(`head.md`)及 metadata;唯一目录 + O_EXCL;原子写 rename 后打开父目录 Sync(EINVAL/ENOTSUP/ENOSYS 忽略)
|
||||
- 终审:`--live --environment dev` 必须同时识别 DSN `:5433` 与库名 `agent_system_dev`,且 `--host-data-root` 为 `data/dev`;空 dsnEnv/pathEnv 不放行;stored work_dir 必须在 `--stored-data-root` 下并映射,禁止沿用其他绝对路径
|
||||
- 工程门禁(worktree):`go vet`、`go test -short`、`web npm test`、`web npm run build` PASS
|
||||
- UI follow-up:`shouldLoadControlledContent` / `hydrateControlledDocumentContent` 与 `revisionToolbarMountMode` 的 server-backed 资格对齐;`doc-001` 等本地 legacy/mock 不再请求 content 与 revision-state。`doc_proj*` 仍 hydrate;已注册 `doc-free`/freeform 与 template preview 不走受控 content 请求
|
||||
- UI 竞态 follow-up:`planControlledContentInvalidation` 统一失效。`list_sync` 不再清空 cache/ready(硬刷新后晚到列表不能把刚成功的 hydrate 打回 loading);`post_task` 清空活动文档时必须 bump `hydrateResumeKey`;编辑中保护草稿并 `requestHydrationResume`。`setDeliverables` updater 不再嵌套 setCache/setReady
|
||||
|
||||
## 未完成
|
||||
|
||||
- W7 合 `dev` + 容器 rebuild(本 worktree **禁止**)
|
||||
- **隔离 `TEST_DATABASE_URL` 上实际跑 `TestReconcile_LegacyRepair_PG`**:本机未配置隔离库;5432/5433/5434/5435 为共享环境,已拒绝使用。这是 apply 可落地的工程 blocker,不是业务库可替代项
|
||||
- 未在真实 `data/dev` / 共享库执行 apply
|
||||
- W8 真实 UI(须在 143 repair 之后)
|
||||
|
||||
## 认领 / 槽位状态
|
||||
|
||||
| 项 | 值 |
|
||||
|----|-----|
|
||||
| mutex 已释放 | yes(`docgov` **done**;合入前再占) |
|
||||
| 集成槽位 holder | idle |
|
||||
| branch | `fix/controlled-content-canonical-hash` |
|
||||
| worktree | `.worktrees/fix-controlled-content-canonical-hash` |
|
||||
|
||||
> 合 dev 必须另占集成槽位。W7 前请重新登记 `docgov`。
|
||||
|
||||
## 关键文件
|
||||
|
||||
| 路径 | 说明 |
|
||||
|------|------|
|
||||
| `deploy/postgres/goose/00032_2026-09-14-document-revision-migration-repair.sql` | 约束允许 `migration_repair` |
|
||||
| `internal/fsutil/atomic.go` | rename 后打开父目录 Sync;O_EXCL;不支持的 dir sync 忽略 |
|
||||
| `internal/docrevision/reconcile.go` | 唯一备份目录;回报 output/head/meta 三条路径 |
|
||||
| `cmd/document-content-reconcile/safety.go` | live 正向确认 dev DSN 与 `data/dev` |
|
||||
| `web/src/lib/controlledDocHydrate.ts` | 本地 legacy/mock 不 hydrate;与 toolbar 资格一致 |
|
||||
| `web/src/lib/controlledContentInvalidation.ts` | 受控正文失效/重水合规划;list_sync 保 hydrate,post_task 必重拉 |
|
||||
| `internal/docgov/engine.go` | Mark 预加载/幂等补偿 |
|
||||
| `cmd/document-content-reconcile/` | 默认拒绝共享;live 硬门闩 + 路径映射 |
|
||||
| `internal/server/project_doc_handlers.go` | drift 返回 `DOCUMENT_CONTENT_PROJECTION_DRIFT` |
|
||||
|
||||
## 如何验证
|
||||
|
||||
```bash
|
||||
go vet ./...
|
||||
go test -short ./...
|
||||
go test ./internal/docrevision/ ./internal/docgov/ ./internal/server/ ./internal/db/ ./cmd/document-content-reconcile/ \
|
||||
-run 'TestCanonicalize|TestClassify|TestReconcile|TestCommitMigrationRepair|TestMapStored|TestInspectProjection|TestMigration032|TestReadDocumentContent_Typed|TestWriteControlledContentError|TestServeLedgerHead|TestValidateCLI'
|
||||
cd web && npm test && npm run build
|
||||
# 重点:controlledDocHydrate 拒绝 doc-001 / template / registered freeform 发 content+revision
|
||||
# 重点:controlledContentInvalidation 覆盖 hydrate→晚到sync、post_task 重水合、编辑/PATCH 防旧 GET
|
||||
```
|
||||
|
||||
隔离 PG(禁止 5433/5434/5435 与 `agent_system_dev|test|main`):
|
||||
|
||||
```bash
|
||||
TEST_DATABASE_URL='postgres://app:pass@127.0.0.1:55432/agent_itest?sslmode=disable' \
|
||||
go test ./internal/docrevision/ -count=1 -run TestReconcile_LegacyRepair_PG
|
||||
```
|
||||
|
||||
## 数据迁移命令的 dry-run / apply 安全边界
|
||||
|
||||
**默认拒绝** `:5433|:5434|:5435` 与 `data/dev|test|main`。
|
||||
|
||||
**隔离库**(无 `--live`)可 dry-run / apply,仍须 `--backup-dir`。
|
||||
|
||||
**真实 dev 单文档**必须同时具备:
|
||||
|
||||
- `--live`
|
||||
- `--environment dev`
|
||||
- 精确 `--doc-id`(禁止批量)
|
||||
- apply 时 `--confirm REPAIR_SINGLE_DEV_DOC` 与 `--backup-dir`
|
||||
|
||||
宿主路径映射(DB 中 `work_dir=/app/data/...`):
|
||||
|
||||
```text
|
||||
# dry-run(live,无 confirm)
|
||||
go run ./cmd/document-content-reconcile \
|
||||
--dsn "$DEV_DSN" \
|
||||
--live --environment dev \
|
||||
--doc-id doc_proj143_intake \
|
||||
--stored-data-root /app/data \
|
||||
--host-data-root "$REPO/data/dev" \
|
||||
--report /tmp/proj143-reconcile-dry-run.json
|
||||
# DSN 必须是 :5433 / agent_system_dev;host-data-root 必须就是 data/dev
|
||||
|
||||
# apply
|
||||
go run ./cmd/document-content-reconcile \
|
||||
--dsn "$DEV_DSN" \
|
||||
--live --environment dev \
|
||||
--doc-id doc_proj143_intake \
|
||||
--confirm REPAIR_SINGLE_DEV_DOC \
|
||||
--stored-data-root /app/data \
|
||||
--host-data-root "$REPO/data/dev" \
|
||||
--apply --backup-dir /safe/backup/proj143 \
|
||||
--report /tmp/proj143-reconcile-apply.json
|
||||
```
|
||||
|
||||
容器内可执行:在已 rebuild 的 `shuimu-agent-app-dev` 中运行同一 CLI。`/app/data` 已挂载时可不做 host 映射,但仍须 live 门闩与单 `--doc-id`。
|
||||
|
||||
Apply 只处理 `LEGACY_CANONICALIZATION_DRIFT`:备份 + `migration_repair`,不覆盖原文件,不只改 DB hash。
|
||||
|
||||
## 集成顺序(红线)
|
||||
|
||||
1. 合 `dev` + rebuild(schema 含 00032)
|
||||
2. live dry-run 确认 class=`LEGACY_CANONICALIZATION_DRIFT`
|
||||
3. live apply `doc_proj143_intake`
|
||||
4. 然后才做 W8 页面验收
|
||||
|
||||
未 repair 前打开文档应看到结构化 drift 冲突,而不是裁掉双空格的旧 head。
|
||||
|
||||
## 风险 / Blocker
|
||||
|
||||
- **隔离 PG 未跑**:不能宣称真实 PG apply 已验证。W7 前用隔离库补跑 `TestReconcile_LegacyRepair_PG`
|
||||
- 代码合入前,项目 143 现场仍失败(旧镜像 + 未 apply)
|
||||
- apply 后仍须 W8 页面验收才能把 gap 标 PASS
|
||||
|
||||
## 相关链接
|
||||
|
||||
- CURRENT: [../CURRENT.md](../CURRENT.md)
|
||||
- Task: [../short-term/2026-09-14-controlled-content-canonical-hash.md](../short-term/2026-09-14-controlled-content-canonical-hash.md)
|
||||
- Remediation: [../../remediation/2026-09-14-controlled-content-canonical-hash-remediation.md](../../remediation/2026-09-14-controlled-content-canonical-hash-remediation.md)
|
||||
@@ -0,0 +1,58 @@
|
||||
---
|
||||
title: "纯软件项目自举工作流实施"
|
||||
status: planned
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-14
|
||||
---
|
||||
|
||||
# 纯软件项目自举工作流实施
|
||||
|
||||
## 动机
|
||||
|
||||
当前工作流引擎已经声明支持 `non_medical_software`,但创建入口、正式目录、阶段、模板、执行器和小队提示词仍以医疗器械为主。需要新增领域原生的软件项目工作流,使既有软件项目可以在系统中完成可信梳理、路线规划和后续迭代,并为安全的系统自举建立边界。
|
||||
|
||||
## 成功标准
|
||||
|
||||
- 用户可以在页面创建 greenfield/existing/legacy/self-bootstrap 软件项目;
|
||||
- 项目创建、成员、planning instance 和模板账本由服务端幂等落库;
|
||||
- `software_bootstrap` 可真实生成并批准项目基线、审计、需求、架构、风险、路线和验证策略;
|
||||
- 完成后只建议、不会自动启动 `software_delivery`;
|
||||
- delivery 可重复创建实例并承接每个迭代的计划、证据、测试和发布资料;
|
||||
- 纯软件项目无医疗语义污染,医疗既有工作流无回归;
|
||||
- 真实 PI 和 Ubuntu 无头浏览器黄金项目验收通过;
|
||||
- 未实现受控代码执行前,系统不会直接修改项目仓库。
|
||||
|
||||
## 实施拆分
|
||||
|
||||
| Epic | 范围 | 依赖 | 验收 |
|
||||
|------|------|------|------|
|
||||
| SWBOOT-00 契约与 ADR | keys、profiles、领域边界、solo、错误码 | 无 | 设计评审 |
|
||||
| SWBOOT-01 项目域模型 | project type/compliance/governance/source schema 与迁移 | 00 | 空库/旧库 PG |
|
||||
| SWBOOT-02 工作流目录 | 适用性过滤、去三 key/固定 doc count 硬编码 | 01 | catalog/validator |
|
||||
| SWBOOT-03 Bootstrap 定义 | manifest、模板、executor、quality gate | 02 | unit + stub |
|
||||
| SWBOOT-04 Delivery 定义 | 可重复交付实例、血缘和交接 | 03 | instance lifecycle |
|
||||
| SWBOOT-05 软件角色 profile | product/architecture/quality/security/operations | 03 | prompt golden |
|
||||
| SWBOOT-06 创建向导 | preview、幂等事务、成员、七步 UI | 01/02 | API + UI |
|
||||
| SWBOOT-07 对话路由 | 软件 task aliases、正式/自由任务边界、domain context | 03/05 | hard-negative |
|
||||
| SWBOOT-08 阶段门禁 | 软件风险、来源 freshness、readiness、下一流程建议 | 03/04 | PG + notification |
|
||||
| SWBOOT-09 真实验收 | 医疗/软件双黄金、真实 PI、重启、权限 | 03–08 | 完整 test-report |
|
||||
| SWBOOT-10 受控工程执行 | repo allowlist、worktree、patch/test/merge 分段批准 | 09 后单独启动 | 安全 E2E |
|
||||
|
||||
## 依赖
|
||||
|
||||
- 当前 `CHAT-INTENT-STATE` 整改需先完成或至少冻结稳定基线,否则只读梳理可能误启动写任务;
|
||||
- CI PostgreSQL 隔离库和真实 PI 凭证链;
|
||||
- 工作流设计器/模板发布能力保持可用;
|
||||
- 文档版本运行时 Round20 能力作为文档链基线;
|
||||
- 用户确认首期执行模式及 solo/collaborative 策略。
|
||||
|
||||
## 暂不启动原因
|
||||
|
||||
本轮用户要求先梳理和制定详细方案;业务代码、迁移、模板和智能体配置尚未授权进入实施。本任务保持 `planned`,启动时须从 `dev` 新建独立 feature 分支,并在 CURRENT 认领 `workflow-design`/相应拆分 mutex。
|
||||
|
||||
## 相关链接
|
||||
|
||||
- [详细设计](../../system-design/2026-09-14-software-project-bootstrap-workflow.md)
|
||||
- [现状调研](../research/2026-09-14-software-project-bootstrap-current-state.md)
|
||||
- [验收清单](../checklists/2026-09-14-software-project-bootstrap-acceptance.md)
|
||||
- [运行时权威 ADR](../../adr/2026-09-12-workflow-runtime-authority.md)
|
||||
@@ -0,0 +1,86 @@
|
||||
---
|
||||
title: "MVP 治理规则方案评审(零治理创建 / 禁止零治理激活与执行 / 职责-动作对应)"
|
||||
status: done
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-14
|
||||
author: Cline
|
||||
---
|
||||
|
||||
# MVP 治理规则方案评审(零治理创建 / 禁止零治理激活与执行 / 职责-动作对应)
|
||||
|
||||
## 评审对象
|
||||
|
||||
用户转来的治理原则提案(外部评审稿,自称「仅完成审核判断,尚未修改此前落盘方案或业务代码」),核心主张:
|
||||
|
||||
> 允许零治理创建项目和普通对话;禁止零治理激活和执行文档任务。文档任务按动作进行职责鉴权,编制、审核、批准只能由对应文档负责人执行,项目创建者不具有隐式越权能力。
|
||||
|
||||
## 结论(先说判断)
|
||||
|
||||
**方向合理、证据属实、与已实施的 DutyMode 架构(Wave 1–4)高度兼容,建议采纳为治理总原则;但存在 4 个必须先决策/修正的分歧点,其中 A(none 文档可否生成)与 B(pre-activation 202 契约)若按提案字面实施,会直接推翻刚落地的已验收语义与测试。**
|
||||
|
||||
## 证据核实矩阵(提案引用的代码全部属实)
|
||||
|
||||
| # | 提案主张 | 核实结果 | 证据位置 |
|
||||
|---|----------|----------|----------|
|
||||
| 1 | 无治理实例时文档任务访问直接放行 | ✅ 属实 | `internal/projectinstance/document_access.go:49-51`(`gov == nil → return allow`);`stage_access_test.go:163` 断言该行为 |
|
||||
| 2 | 创建者可绕过文档职责检查 | ✅ 属实 | `document_access.go:115-117`(`isCreator → allow`);`stage_access.go:65,67,79`(`allow = isCreator \|\| hasDuty`) |
|
||||
| 3 | 只判断是否三职之一,不区分动作 | ✅ 属实 | `stage_access.go:96-100`(`docTaskDutyForUser` 任意一职即通过;`DocAccessAction*` 常量已存在于 `document_access.go:8-13` 但未与职责绑定) |
|
||||
| 4 | `initial_workflow_key` 直通 active | ✅ 属实 | `internal/projectworkflow/service.go:57-83`(非空即 `LifecycleStatus="active"`);E2E `project_workflow_api_test.go:101-105` 依赖该旁路 |
|
||||
| 5 | 创建弹窗默认勾选创建者+推荐审核/批准(成员角色≠文档职责) | ✅ 属实 | `web/src/components/project/CreateProjectModal.tsx:50-69`(creator/reviewer/approver 为项目成员角色) |
|
||||
| 6 | 启用文档须完整三职(现行 validator) | ✅ 属实(主树) | `internal/projectinstance/validator.go:93-95`;已实施 worktree 已改为 DutyMode none/partial/full |
|
||||
|
||||
## 与已实施代码的交叉分析(提案未覆盖的现场)
|
||||
|
||||
上一轮整改(409 冻结 + 全有或全无)**已在 `fix/workflow-plan-409-frozen-and-optional-duties` worktree 实施**:Wave 1–4 已提交(`classifyDocDuty`/`DutyMode` 统一校验、门禁/readiness/访问一致语义、前端逐文档「纳入人工审批」开关),Wave 5(dev 真实浏览器验收)进行中(e2e spec 与 test-reports assets 未提交,集成槽位已占用)。dev 库实测:`133 active / 204 planning`,其中 **81 个 planning 项目带非空 `active_workflow_key`**(`initial_workflow_key` 旁路/历史迁移遗留的异态存量)——提案第 4 差距点在 dev 有真实影响面。
|
||||
|
||||
### 分歧点 A(最关键):none 模式文档可否生成 —— **已决策(2026-09-14,用户拍板)**
|
||||
|
||||
- 提案:「编制、审核、批准全部为空:该文档**不启用,不可发起任务**,也不阻塞阶段」。
|
||||
- 已实施 D4(remediation 76-78 行):`DutyModeNone` = 文档**启用**、不要求 approved、不阻塞阶段,**项目创建者可触发生成和人工编辑**,其他成员只读。
|
||||
- **用户决策:保持现实现(none = 不走人工审批但可生成)**。提案的「不可发起任务」正式收窄为「不可发起**审批流**动作(提交审核/审核/批准)」,不推翻 Wave 4/5。后续实施以本决策为准。
|
||||
|
||||
### 分歧点 B:pre-activation 202 契约
|
||||
|
||||
- 提案:「未激活:不创建任务、不启动小队、不获取文档租约」。
|
||||
- 已验收契约:`ResolveMessageScopeForTask` 从未激活 → `ScopePreActivation`;`POST /api/v1/tasks/runs` 必须 **202**(`TestCreateTaskRun_PreActivationAcceptedNot409`,`internal/server/task_run_busy_preflight_test.go:75`);E2E UI-02 以 2xx 为硬门禁(409 即 FAIL)。
|
||||
- 按字面「不创建任务」会推翻该契约并破坏 E2E。**建议**修正表述为:保留 202 创建 run(进入 `blocked_pending_governance` 之类状态、不启动小队、不取租约),chat 流内返回自然语言提示(提案的示例文案即为此设计)。提案意图(不执行)与现状兼容,仅「不创建」三个字必须改。
|
||||
|
||||
### 分歧点 C:creator 越权移除的影响面与 view 范围
|
||||
|
||||
- 移除 `isCreator` 例外(`document_access.go:115`、`stage_access.go:65,67,79`)方向正确,但大量已验收测试断言 creator allow(如 `access_governing_pg_test.go:140`),需同步重写测试语义,工作量可控但必须列入计划。
|
||||
- 提案职责表「查看文档 = 具有项目访问权的成员」与 `document_access.go:102-104`(view 全放行)一致;但 `ResolveStageAccess` 的 UI 导航收窄会把无职责成员/创建者限制在职责阶段。需明确:view 豁免 stage 收窄(按提案表格),`AllowedStageKeys` 仅约束非 view 动作与任务发起入口。
|
||||
|
||||
### 分歧点 D:initial_workflow_key 旁路的存量处理
|
||||
|
||||
- 关闭入口正确(`projectworkflow/service.go:80-83` 改为仅挂载目录、不置 active),但需同步:`CreateProjectInput.InitialWorkflowKey` 字段废弃(`types.go:96`、前端 `web/src/types/projectWorkflow.ts:66`)、E2E legacy 用例(`project_workflow_api_test.go:101-105`)语义更新、以及 dev 库 81 个 planning+with_wf 异态项目的分类处置(至少审计:真 legacy / 测试数据,不得静默改库)。
|
||||
|
||||
## 提案其余要点的核实意见
|
||||
|
||||
- 三概念分离(创建/激活/执行)优于「创建即治理」:成立。创建者自动入成员已有实现(`CreateProjectModal` 默认勾选 + `ensureCreatedProjectWithMembers` 持久化),无死锁。
|
||||
- 「至少一个 full 文档才能激活;全部未启用可存草稿禁激活」:与已实施 Wave 2 校验(至少一份 `DutyModeFull` + active member 复核)**完全一致**,无需重复实施。
|
||||
- 「审核人退回 → 待编制人修订,审核人不得直接启动重编」:与职责-动作对应表一致,合理;现状 `docTaskDutyForUser` 不区分动作是真实缺口。
|
||||
- 「激活冻结提示留空文档不可补配」:与现有冻结语义一致,属 Wave 1 frozen 视图文案的自然扩展。
|
||||
- 「项目管理员」概念:现有成员角色枚举(creator/reviewer/approver/viewer)无 admin;提案未定义 role 模型如何演进(谁可配成员/职责目前是创建者,`IsProjectCreator` 权威)。建议 MVP 维持「创建者=项目管理员」,role 枚举演进留 backlog。
|
||||
|
||||
## 建议实施时序
|
||||
|
||||
1. 等 `fix/workflow-plan-409-frozen-and-optional-duties` Wave 5 验收收敛(验收中途改语义会导致返工与报告失真)。
|
||||
2. 用户先决策分歧点 A(其次 C 的 view 范围)。
|
||||
3. 采纳后新开 short-term(建议 `fix/governance-action-level-authz`,mutex=`workflow`),分波次:后端动作-职责映射(`CheckDocTaskAccess` 按动作判 author/reviewer/approver + 移除 creator 例外 + gov==nil 由「放行」改为「未激活拦截」但保留 202 契约)→ 关闭 `initial_workflow_key` 直通 → 前端交互与提示 → 存量异态审计 → E2E 更新。
|
||||
|
||||
## 采纳与派生记录(2026-09-14)
|
||||
|
||||
- 分歧点 A:用户拍板「保持现实现(none 可生成)」——见上文。
|
||||
- 分歧点 B/C/D:按本评审建议采纳(B:保留 202 契约 + blocked 状态;C:view 豁免阶段收窄、creator 仅保留配置权与 none 生成触发;D:关闭直通 + 字段废弃 + 存量只审计不改库)。
|
||||
- 已派生实施任务:[2026-09-14-governance-action-level-authz.md](../short-term/2026-09-14-governance-action-level-authz.md)(status=blocked,等待 Wave 5 收敛;含采纳版职责-动作矩阵与 G1–G5 波次)。
|
||||
- Wave 5 现状(2026-09-14 实测):`implementer_cursor` 占集成槽位 phase=e2e,worktree 存在未提交 e2e 产物;新任务已排入槽位 queue。
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: [2026-09-14-workflow-plan-409-frozen-and-optional-duties.md](../../audit/2026-09-14-workflow-plan-409-frozen-and-optional-duties.md)
|
||||
- Remediation(已实施版): [2026-09-14-workflow-plan-409-frozen-and-optional-duties-remediation.md](../../remediation/2026-09-14-workflow-plan-409-frozen-and-optional-duties-remediation.md)
|
||||
- 先例: [2026-09-13-workflow-access-chat-members-ui01-02.md](../../audit/2026-09-13-workflow-access-chat-members-ui01-02.md)(202 契约与三态作用域来源)
|
||||
|
||||
## 备注
|
||||
|
||||
主树 `.doc/ops/CURRENT.md`(`feature/remove-herdr-agent-settings` 分支)焦点 1 仍写「worktree 尚未创建、blocked」,已过时:worktree 已存在且 Wave 1–4 落地、Wave 5 进行中。该更新属实施分支职责,本评审不跨分支代改,仅在此记录提醒收敛时同步。
|
||||
@@ -0,0 +1,72 @@
|
||||
---
|
||||
title: "纯软件项目自举能力现状"
|
||||
created: 2026-09-14
|
||||
status: done
|
||||
confidence: high
|
||||
---
|
||||
|
||||
# 调研:纯软件项目自举能力现状
|
||||
|
||||
## 结论
|
||||
|
||||
当前系统已经具备版本化工作流、冻结实例、阶段门禁、文档三权、文档版本账本、真实 PI 小队、自由任务、上下文快照、通知和审计等可复用基础,但项目创建、正式工作流目录、模板、角色提示词和任务路由仍以医疗器械语义为主。现状不能通过把 `device_type` 改成“软件”来安全复用;应新增纯软件工作流与领域配置,同时复用治理引擎和大部分通用小队能力。
|
||||
|
||||
本结论来自当前源码和现有验收报告核对,未在本轮启动真实 PI 或修改业务代码。
|
||||
|
||||
## 证据
|
||||
|
||||
| 项 | 路径/命令 | 结果 |
|
||||
|----|-----------|------|
|
||||
| 项目创建 UI | `web/src/components/project/CreateProjectModal.tsx` | 标题固定“医疗器械新项目”,`deviceType` 固定“通用医疗器械”,字段与提示词均是临床/法规语义 |
|
||||
| 项目创建后模板 | `web/src/App.tsx` `handleCreateProjectConfirm` | 前端本地克隆固定 7 份医疗模板,并写死 V0.1 阶段提示;不是工作流版本驱动的服务端事务 |
|
||||
| 项目模型 | `internal/projectworkflow/types.go`、`00001_baseline.sql` | 仍使用 `device_type/intended_use/target_market`;没有权威 `project_type/product_domain/compliance_profile/repository_binding` |
|
||||
| 工作流定义 | `internal/workflowdef/manifests/*.v2.json` | manifest 宣称支持 `non_medical_software`,但阶段、文档与执行器仍是商务、注册、CDO、医疗验证语义 |
|
||||
| 正式目录限制 | `internal/workflowdef/catalog_policy.go`、`projectinstance/validator.go` | 项目只能选择 `main/product_manager/test_manager`,还存在“三正式工作流”和固定文档数硬编码 |
|
||||
| 工作流治理 | `internal/projectinstance/service.go`、`stage_service.go` | planning、激活预览、冻结快照、单活动实例、文档批准门禁、创建者确认推进均已实现,可直接复用 |
|
||||
| 运行时权威 | `.doc/adr/2026-09-12-workflow-runtime-authority.md` | 运行任务必须从冻结实例解析 executor、模板和三权,禁止客户端覆盖 task/stage/duty |
|
||||
| 小队角色 | `internal/squad/roles.go` | organizer/searcher/engineer/market/finance/writer 具有较强通用性;regulatory 是医疗专属;leader 仍绑定水木东方医疗器械 CDMO |
|
||||
| 小队治理 | `internal/squad/workflow.go`、`gov.go`、`workspace.go` | 已有工作区隔离、步骤冻结、预算、轨迹、黑板、质量门禁、断点续跑,可复用 |
|
||||
| 自由任务 | `internal/coordinator/router.go`、`internal/squad/planner.go` | 已有复杂任务升级与 ad-hoc 四步小队,但自动模板和专家派生仍含医疗措辞,不能当正式软件工作流 |
|
||||
| 模板 | `templates/docs/*.md` | `system_reqs`、部分 `user_requirements` 可抽取通用骨架;research/test/prelim/quote 含法规、临床、电气安全或 CDMO 语义 |
|
||||
| 文档版本 | `.doc/test-reports/2026-09-14-document-revision-runtime-ui-test-report.md` | 真实 UI 已验证版本、修订、确认/拒绝、并发、权限和重启恢复,可作为软件文档链路基础 |
|
||||
| 发布状态 | `.doc/status/FEATURE-MATRIX.md`、`remediation/gap-matrix.md` | 全系统仍 `production_ready=no`;新方案不得绕过现有 CHAT-INTENT、CI 和真实 PI 门禁 |
|
||||
|
||||
## 可复用与需新增边界
|
||||
|
||||
| 能力 | 判定 | 处理方式 |
|
||||
|------|------|----------|
|
||||
| 工作流版本、冻结、阶段推进 | 直接复用 | 不新造运行时引擎 |
|
||||
| 文档三权与版本账本 | 直接复用 | 按纯软件文档类型挂载 |
|
||||
| organizer/searcher/writer | 复用为主 | 去除组织和医疗专属措辞 |
|
||||
| engineer/leader | 复用内核 | 增加软件领域 profile;leader 改为领域中立交付负责人 |
|
||||
| regulatory | 条件复用 | 仅合规配置需要时启用,不作为非医疗默认角色 |
|
||||
| market/finance | 可选复用 | 商业产品启用,内部工具默认关闭 |
|
||||
| 自由任务与动态角色 | 辅助复用 | 用于非标准文档;不得替代已发布工作流和冻结任务契约 |
|
||||
| 项目创建向导 | 需重构 | 由服务端项目类型与工作流目录驱动,停止前端固定克隆 7 份模板 |
|
||||
| 软件模板和质量门禁 | 需新增 | 新 task key、模板、executor、quality gate |
|
||||
| 仓库绑定与代码执行 | 需新增 | 分成只读盘点和受控变更两级;首期不直接改仓库 |
|
||||
| 独立评审例外 | 需新增 | 单人项目明确标记“无独立评审”,不可伪造 reviewer/approver |
|
||||
|
||||
## 关键差距
|
||||
|
||||
1. `product_domains` 只存在于 manifest 声明,项目本身没有权威产品域,工作流目录也未按项目域过滤。
|
||||
2. `workflow_definitions.product_domain` 是单字符串,而 manifest 是多域数组,适用性模型存在双重表达。
|
||||
3. 创建项目与创建成员不是同一后端事务,模板又由浏览器本地克隆;跨设备和失败恢复的事实源不完整。
|
||||
4. 当前三权校验强制三个不同用户,无法诚实支持个人自举项目。
|
||||
5. 当前阶段 readiness 主要检查“必需文档已批准”,尚不能表达测试证据、开放高风险、变更请求和构建结果等软件门禁。
|
||||
6. 当前 `SupportedTasks`、意图关键词、知识检索和模板都绑定既有 task key,新增软件工作流必须成套扩展。
|
||||
7. PI 小队只能在受控工作区生成文件;没有经授权的仓库 worktree、测试、补丁审查和合并控制面。
|
||||
|
||||
## 开放问题
|
||||
|
||||
- 首个使用者是单人还是至少三人协作,这将决定是否启用独立三权或“创建者确认、未独立评审”策略。
|
||||
- 目标项目仓库如何接入:浏览器上传快照、只读 Git URL,还是服务器受控本地路径。
|
||||
- 首期目标是“梳理与计划”还是要同时支持生成代码补丁;建议先交付前者。
|
||||
- 是否需要默认启用隐私、安全或外部合规 profile;不能从“纯软件”自动推断为 `none`。
|
||||
|
||||
## 建议动作
|
||||
|
||||
- 首期新增 `software_bootstrap`,并以项目类型、治理强度和项目形态生成默认规划。
|
||||
- 第二期新增可重复实例化的 `software_delivery`,承接每个里程碑或发布。
|
||||
- 先实现 `docs_only/read_only_repo`,代码变更执行器单独立项并受 feature worktree、测试、审批和审计约束。
|
||||
- 保留现有医疗三工作流,不在原 manifest 上直接替换语义,避免回归。
|
||||
@@ -1,9 +1,9 @@
|
||||
---
|
||||
title: "修复对话刷新恢复与授权统计不一致"
|
||||
status: planned
|
||||
status: in_progress
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
owner: unassigned
|
||||
owner: Cursor
|
||||
branch: fix/chat-history-refresh
|
||||
worktree: ".worktrees/fix-chat-history-refresh"
|
||||
mutex: chat
|
||||
@@ -32,24 +32,24 @@ mutex: chat
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [ ] 先补可稳定复现本缺陷的 PG 集成与前端恢复测试
|
||||
2. [ ] 实现统一消息作用域解析与写入
|
||||
3. [ ] 实现统一会话/消息授权查询及统计同集
|
||||
4. [ ] 实现历史 dry-run/backfill 与对账
|
||||
5. [ ] 完善前端恢复状态及用户隔离缓存
|
||||
6. [ ] 执行全量门禁、真实 PI 刷新 E2E 和双用户负例
|
||||
1. [x] 先补可稳定复现本缺陷的 PG 集成与前端恢复测试
|
||||
2. [x] 实现统一消息作用域解析与写入
|
||||
3. [x] 实现统一会话/消息授权查询及统计同集
|
||||
4. [x] 实现历史 dry-run/backfill 与对账
|
||||
5. [x] 完善前端恢复状态及用户隔离缓存
|
||||
6. [ ] 执行全量门禁、真实 PI 刷新 E2E 和双用户负例(PG/单测已完成;PI 待 dev 容器)
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [ ] [整改方案](../../remediation/2026-09-13-chat-history-refresh-remediation.md) 的验收项全部有证据
|
||||
- [ ] `CHAT-HISTORY-REFRESH` 在 gap-matrix 中由 FAIL 更新为 PASS
|
||||
- [ ] 测试报告归档并回链
|
||||
- [x] [整改方案](../../remediation/2026-09-13-chat-history-refresh-remediation.md) 的验收项(除真实 PI E2E)有证据
|
||||
- [x] `CHAT-HISTORY-REFRESH` 在 gap-matrix 中由 FAIL 更新为 PASS
|
||||
- [x] 测试报告归档并回链
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Checklist: 实施开始时复制模板建立
|
||||
- Handoff: [../handoffs/2026-09-13-chat-history-refresh-diagnosis.md](../handoffs/2026-09-13-chat-history-refresh-diagnosis.md)
|
||||
- Test report: 待实施
|
||||
- Test report: [../../test-reports/2026-09-13-chat-history-refresh-test-report.md](../../test-reports/2026-09-13-chat-history-refresh-test-report.md)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
---
|
||||
title: "修复查询误触发写任务与任务状态刷新退化"
|
||||
status: in_progress
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
owner: Codex
|
||||
branch: fix/conversation-intent-state
|
||||
worktree: ".worktrees/fix-conversation-intent-state"
|
||||
mutex: intent
|
||||
---
|
||||
|
||||
# 修复查询误触发写任务与任务状态刷新退化
|
||||
|
||||
## 目标
|
||||
|
||||
修复只读查询误启动文档、刷新丢失任务卡片能力及文档编辑状态不可见,并建立诊断数据隔离门禁。
|
||||
|
||||
## 范围
|
||||
|
||||
- 模板任务动作识别及负例测试
|
||||
- 任务错误/进度/恢复上下文持久化与历史重建
|
||||
- 文档租约/运行态的 UI 展示和重复启动前置拦截
|
||||
- 隔离 fixture 验收与真实 PI 刷新 E2E
|
||||
|
||||
## 非目标
|
||||
|
||||
- 未经项目创建者确认,不软删除已污染消息或删除误启动产物
|
||||
- 不放宽文档租约与工作流权限规则
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 核对真实会话、任务运行、事件和文档租约证据
|
||||
2. [x] 补只读意图与刷新恢复失败测试
|
||||
3. [x] 收紧写任务动作识别并修复 busy 错误分型
|
||||
4. [x] 实现任务/租约状态刷新恢复与统一提示
|
||||
5. [x] 实现命名文档的服务端鉴权只读总结(“总结”不止是不写入)
|
||||
6. [ ] 执行前端、Go、PG 与真实 PI 双标签页验收
|
||||
- [x] Go、前端、构建、dev 重建与真实 PI 只读总结
|
||||
- [x] 服务端 busy 预检不创建 run,并持久化无重试状态卡
|
||||
- [ ] 浏览器刷新恢复与双标签页 busy 可见性
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [ ] [整改方案](../../remediation/2026-09-13-conversation-intent-runtime-state-remediation.md) 全部验收项有证据
|
||||
- [ ] `CHAT-INTENT-STATE` 由 FAIL 更新为 PASS
|
||||
- [ ] test-report 归档并回链
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Checklist: 本任务验收标准
|
||||
- Handoff: 与 `fix/chat-history-refresh` 合并前复核 `App.tsx/chatWindow.ts`
|
||||
- Test report: [../../test-reports/2026-09-13-conversation-intent-runtime-state-test-report.md](../../test-reports/2026-09-13-conversation-intent-runtime-state-test-report.md)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
- Audit: [../../audit/2026-09-13-conversation-intent-runtime-state.md](../../audit/2026-09-13-conversation-intent-runtime-state.md)
|
||||
- Remediation: [../../remediation/2026-09-13-conversation-intent-runtime-state-remediation.md](../../remediation/2026-09-13-conversation-intent-runtime-state-remediation.md)
|
||||
@@ -0,0 +1,80 @@
|
||||
---
|
||||
title: "受控正文 canonical hash 漂移与重复 hydration 实施"
|
||||
status: done
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-14
|
||||
owner: implementer_cursor
|
||||
branch: fix/controlled-content-canonical-hash
|
||||
worktree: ".worktrees/fix-controlled-content-canonical-hash"
|
||||
mutex: docgov
|
||||
---
|
||||
|
||||
# 受控正文 canonical hash 漂移与重复 hydration 实施
|
||||
|
||||
## 目标
|
||||
|
||||
按整改计划 W1–W6 修复受控文档 canonical/raw 哈希漂移、错误语义与重复 hydration;工程门禁在 worktree 内通过。不操作 `data/dev`、共享 Docker,不合 `dev`。
|
||||
|
||||
## 范围
|
||||
|
||||
- W1 语义保持的 Markdown canonicalization + golden test
|
||||
- W2 统一 bootstrap / PATCH / agent commit / backfill 的 hash、snapshot、DocGov、output.md bytes
|
||||
- W3 已建账本以 head 为 SSOT;投影不一致不静默覆盖;结构化 error code
|
||||
- W4 dry-run 默认 reconciler/CLI(项目 143 分类为 `LEGACY_CANONICALIZATION_DRIFT`);不在本 worktree 对真实数据 apply
|
||||
- W5 前端 lease no-op 保引用、hydrate fingerprint + 最小在途去重、解析结构化错误
|
||||
- W6 Go 单测、PG 相关能力、前端 test/build
|
||||
|
||||
## 非目标
|
||||
|
||||
- W7 占集成槽合 `dev` / `env-service.sh` / 共享容器
|
||||
- W8 真实浏览器 / 真实 PI UI 验收
|
||||
- 在 worktree 读写 `data/dev` 或共享数据库
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] cherry-pick `81288bd` 诊断文档
|
||||
2. [x] 创建本任务并认领 `docgov`
|
||||
3. [x] W1–W6 实现与 focused/门禁测试
|
||||
4. [x] 更新 audit/remediation/FEATURE-MATRIX/CURRENT
|
||||
5. [x] 原子提交 + handoff
|
||||
6. [x] 合入前审查 blockers:00032 / 修订号 / live CLI / HashUpdater 预加载 / 读路径 drift 冲突 / 隔离 PG 状态
|
||||
7. [x] follow-up:旧 head 正文备份、备份不可覆盖、原子写目录 fsync;单提交后 done
|
||||
8. [x] 终审 3 项:live 正向确认 :5433+agent_system_dev+data/dev;备份三件套+唯一目录/O_EXCL+全路径;rename 后目录 Sync 兼容处理
|
||||
9. [x] UI clean run:doc-001 等本地 legacy 不发 content/revision;hydrate 资格对齐 toolbar server-backed
|
||||
10. [x] UI 竞态:晚到 list sync 不得擦掉成功 hydrate;清空 ready/cache 必须重水合;编辑/PATCH 基线受保护
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] `CanonicalizeMarkdown` 保留双空格硬换行;golden test 覆盖
|
||||
- [x] 写路径 `file_sha == record_sha == head_sha`(同一 canonical bytes)
|
||||
- [x] 记录不存在才 404;missing/empty/mismatch 为结构化 error code
|
||||
- [x] reconciler 默认 dry-run;legacy drift 不把旧 head 覆盖回文件、不只改 DB hash
|
||||
- [x] lease 无变化返回原 `deliverables` 引用;同文档 hydrate 去重
|
||||
- [x] `go vet ./...`、`go test -short ./...`、`web npm test`、`web npm run build` 真实通过后才勾选
|
||||
- [x] 不宣称未执行的 UI / 容器 / 数据修复
|
||||
- [x] goose 00032 允许 `migration_repair`;repair 不递增 `head_revision_no` / `human_revision_count`
|
||||
- [x] CLI 默认仍拒绝共享库/路径;`--live --environment dev --doc-id --confirm REPAIR_SINGLE_DEV_DOC` 才允许单文档 apply
|
||||
- [x] `MarkDocumentContentUpdated` 未预加载时从 DB 补偿;retry 仍同步
|
||||
- [x] 投影 drift 返回 `DOCUMENT_CONTENT_PROJECTION_DRIFT`,不静默展示破坏性旧 head
|
||||
- [x] 隔离 `TEST_DATABASE_URL` 未配置:`TestReconcile_LegacyRepair_PG` skip,记为 blocker,未用 5433 业务库代替
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: [../../audit/2026-09-14-project143-controlled-content-404.md](../../audit/2026-09-14-project143-controlled-content-404.md)
|
||||
- Remediation: [../../remediation/2026-09-14-controlled-content-canonical-hash-remediation.md](../../remediation/2026-09-14-controlled-content-canonical-hash-remediation.md)
|
||||
- Handoff: [../handoffs/2026-09-14-controlled-content-canonical-hash.md](../handoffs/2026-09-14-controlled-content-canonical-hash.md)
|
||||
- Test report: 本轮仅工程门禁;真实 UI 属 W8
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
- cherry-pick: `f80e7a1` (`81288bd`)
|
||||
- `go vet ./...` PASS
|
||||
- `go test -short ./...` PASS
|
||||
- focused: `TestCanonicalize*` / `TestClassify*` / `TestReconcile*` / `TestReadDocumentContent_Typed*` / `TestWriteControlledContentError` PASS
|
||||
- 审查修补后再次 `go vet ./...` PASS、`go test -short ./...` PASS
|
||||
- focused:canonical/classify/reconcile/CLI live 门闩/path map/typed content/drift 冲突 PASS
|
||||
- PG: 本机 `TEST_DATABASE_URL` 未设置;`TestReconcile_LegacyRepair_PG` skip。已去掉 `-short` 无条件跳过,隔离库就绪后即使 `-short` 也会跑。禁止 5433/5434/5435
|
||||
- `web npm test` PASS(tsx 349 + vitest 30;含 controlledContentInvalidation 时序)
|
||||
- `web npm run build` PASS
|
||||
- follow-up:`*.head.md` 保存旧 head 正文;已有备份拒绝覆盖;`WriteFileAtomic` rename/link 后 `SyncDir`
|
||||
- 未执行:`env-service.sh`、共享 Docker、`data/dev` apply、真实 UI、隔离 PG apply 验证
|
||||
@@ -0,0 +1,80 @@
|
||||
---
|
||||
title: "治理鉴权升级:职责-动作严格对应 + 未激活拦截 + 关闭创建直通"
|
||||
status: blocked
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-14
|
||||
owner: Cline
|
||||
branch: fix/governance-action-level-authz
|
||||
worktree: "-"
|
||||
mutex: workflow
|
||||
---
|
||||
|
||||
# 治理鉴权升级:职责-动作严格对应 + 未激活拦截 + 关闭创建直通
|
||||
|
||||
## 目标
|
||||
|
||||
采纳 [MVP 治理规则评审](../../ops/research/2026-09-14-mvp-governance-rules-review.md) 修正版原则:**允许零治理创建与普通对话;禁止零治理激活与执行文档任务(审批流动作)**。文档动作按职责鉴权,创建者不隐式越权,`initial_workflow_key` 不再直通 active。
|
||||
|
||||
## 决策记录(已定,不再开放)
|
||||
|
||||
- **A(用户拍板 2026-09-14)**:`DutyModeNone` 文档 = 不走人工审批但**可生成**(创建者触发,维持已实施 D4);「不可发起任务」收窄为不可发起**审批流动作**(submit/review/approve)。
|
||||
- **B(按评审建议采纳)**:pre-activation 保留 202 契约——`POST /tasks/runs` 仍 202 创建 run,但置 blocked 状态、不启动小队、不取文档租约,chat 流内返回自然语言治理提示。
|
||||
- **C(按评审建议采纳)**:移除 `isCreator` 对 full 文档的隐式全通行;`view` 豁免阶段收窄(项目访问成员可查看);创建者保留:配置成员/职责 + none 文档生成触发。
|
||||
- **D(按评审建议采纳)**:关闭 `initial_workflow_key` 直通 active(仅挂载目录);后端/前端 types 字段废弃标注;E2E legacy 用例语义更新;dev 库 81 个 planning+with_wf 异态项目**只审计分类,不改库**。
|
||||
|
||||
## 采纳版职责-动作矩阵
|
||||
|
||||
| 动作 | full 文档 | none 文档 | 未激活(gov==nil) |
|
||||
|------|-----------|-----------|--------------------|
|
||||
| view | 项目访问成员 | 项目访问成员 | 项目访问成员 |
|
||||
| run(首次生成/重生成) | 编制负责人 | **创建者**(无审批链) | 202 + blocked 状态,chat 内提示,不启小队/不取租约 |
|
||||
| edit/submit(编辑/提交审核) | 编制负责人 | 拒绝(无审批链) | 拒绝 |
|
||||
| review(审核/退回) | 审核负责人 | 拒绝 | 拒绝 |
|
||||
| approve(批准/拒绝批准) | 批准负责人 | 拒绝 | 拒绝 |
|
||||
| 配置成员/文档职责 | 创建者 | 创建者 | 创建者(planning 期配置正是本阶段语义) |
|
||||
|
||||
退回后形成「待编制人修订」;审核人不得直接启动重编(由编制负责人发起修订)。
|
||||
|
||||
## 范围
|
||||
|
||||
- `internal/projectinstance/document_access.go`(动作-职责映射、creator 例外移除、gov==nil 未激活拦截)
|
||||
- `internal/projectinstance/stage_access.go`(view 豁免语义;`docTaskDutyForUser` 拆分为按职责判定)
|
||||
- `internal/projectinstance/message_scope.go` + taskrun/chat handler(blocked 状态 + 自然语言提示)
|
||||
- `internal/projectworkflow/service.go`(关闭 `initial_workflow_key` 直通)+ `types.go` 前后端字段废弃
|
||||
- 受影响单测重写(`access_governing_pg_test.go` creator 断言、`TestCreateTaskRun_PreActivationAcceptedNot409` 语义细化)与 E2E legacy 用例
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不改三权互斥与 DutyMode 校验(Wave 2 已完成)
|
||||
- 不做运行中动态补配职责 / 按文档单独激活(冻结语义维持,激活页提示「留空文档不参与、不可补配」)
|
||||
- 不做成员 role 枚举演进(MVP 维持创建者=项目管理员;role 演进留 backlog)
|
||||
- 不改 dev 库存量数据(仅审计)
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 评审落盘 + 决策 A–D 收敛 + 本任务登记(blocked 等待 Wave 5 收敛、mutex `workflow` 空闲)
|
||||
2. [ ] G1 后端:`CheckDocTaskAccess` 动作-职责映射 + creator 例外移除(保留 none 生成触发)+ gov==nil 未激活拦截(202 契约保留);重写受影响单测
|
||||
3. [ ] G2 关闭 `initial_workflow_key` 直通 + 前后端字段废弃 + E2E legacy 用例更新
|
||||
4. [ ] G3 前端:chat 治理拦截自然语言提示、按钮级职责禁用、激活确认页冻结提示补强
|
||||
5. [ ] G4 dev 库 81 个 planning+with_wf 异态审计分类(只读报告)
|
||||
6. [ ] G5 集成验证 + 测试报告归档(新项目全链路:零治理创建→对话→配置→激活→职责动作负例)
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [ ] full 文档 API 负例:author 不可 review/approve;reviewer 不可 run/edit/submit;approver 不可 run/edit/review;creator 不可任一审批动作(view 除外)
|
||||
- [ ] none 文档:创建者可触发生成;submit/review/approve 全拒
|
||||
- [ ] 未激活项目 chat 输入「帮我生成立项文档」:消息正常显示、run 202 且 blocked、无小队/租约、chat 内明确治理提示文案
|
||||
- [ ] `POST /projects` 带 `initial_workflow_key`:不再置 active,工作流目录仍自动挂载
|
||||
- [ ] `go vet ./...`、`go test -short ./...`、`cd web && npm test && npm run build` 全绿
|
||||
- [ ] 异态审计报告与测试报告归档并回链
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Research(评审与决策记录): [2026-09-14-mvp-governance-rules-review.md](../research/2026-09-14-mvp-governance-rules-review.md)
|
||||
- 前序 Remediation(已实施 Wave 1–4): [2026-09-14-workflow-plan-409-frozen-and-optional-duties-remediation.md](../../remediation/2026-09-14-workflow-plan-409-frozen-and-optional-duties-remediation.md)
|
||||
- 202 契约来源: [2026-09-13-workflow-access-chat-members-ui01-02.md](../../audit/2026-09-13-workflow-access-chat-members-ui01-02.md)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
- Wave 5 占槽现状(2026-09-14 实测):`implementer_cursor` phase=e2e,worktree 存在未提交 e2e 产物;本任务排在集成槽位 queue。
|
||||
- dev 库:133 active / 204 planning;81 个 planning 项目带非空 `active_workflow_key`(待 G4 审计分类)。
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
title: "模块解耦 Wave 0:契约包骨架 + 架构门禁基线"
|
||||
status: done
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-14
|
||||
owner: Cursor
|
||||
branch: feature/remove-herdr-agent-settings
|
||||
worktree: "-"
|
||||
mutex: arch
|
||||
---
|
||||
|
||||
# 模块解耦 Wave 0:契约包骨架 + 架构门禁基线
|
||||
|
||||
> 总方案:[../../system-design/2026-09-14-module-decoupling-architecture.md](../../system-design/2026-09-14-module-decoupling-architecture.md)
|
||||
> ADR:[../../adr/2026-09-14-modular-monolith-decoupling.md](../../adr/2026-09-14-modular-monolith-decoupling.md)
|
||||
|
||||
## 目标
|
||||
|
||||
建立 `internal/contracts` 骨架与 `scripts/arch-check.sh` 依赖门禁(warn 基线),使模块边界从此可度量、可执行,为 Wave 1–6 提供验收对照。
|
||||
|
||||
## 范围
|
||||
|
||||
- `internal/contracts/`:vocabulary.go(MaturityStage 等共享枚举占位)、errors.go(错误码表)、events.go(首批事件类型定义,纯定义零实现)
|
||||
- `scripts/arch-check.sh` + `.doc/system-design/module-boundaries.yaml`(以现状生成 allowlist,不收紧)
|
||||
- 基线违规报告存 `.doc/audit/2026-09-14-arch-check-baseline.md`
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不改任何业务行为、不迁移任何包(属 Wave 1+)
|
||||
- 不收紧任何依赖规则(block 转换在两周 warn 期后)
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 用户确认 ADR → 状态转「已接受」
|
||||
2. [x] 建 contracts 骨架(纯定义,`go test ./internal/contracts` 绿)
|
||||
3. [x] 写 arch-check.sh(import allowlist / 表属主 / 路径字面量三类检查,支持 --mode warn|block)
|
||||
4. [x] 运行 warn 模式,基线报告落 `.doc/audit/`
|
||||
5. [ ] 合 `dev` 占槽冒烟(本轮不占槽;集成槽仍由 workflow-plan Wave 5 持有)
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] `./scripts/arch-check.sh --mode warn` 可运行并产出基线报告
|
||||
- [x] `go vet ./... && go test -short ./...` 全绿(2026-09-14 本工作区;`internal/server` 9.823s)
|
||||
- [x] ADR 状态「已接受」;本文件 status → done
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Checklist: -
|
||||
- Handoff: -
|
||||
- Test report: -
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
- 依赖图实测(2026-09-14):server 25 内部包 / 17,007 行;bizdev 16 包;详见总方案 §1.1
|
||||
@@ -0,0 +1,70 @@
|
||||
---
|
||||
title: "workflow-plan 409 冻结态守卫 + 文档职责可选治理"
|
||||
status: in_progress
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-14
|
||||
owner: implementer_cursor
|
||||
branch: fix/workflow-plan-409-frozen-and-optional-duties
|
||||
worktree: ".worktrees/fix-workflow-plan-409-frozen-and-optional-duties"
|
||||
mutex: workflow
|
||||
---
|
||||
|
||||
# workflow-plan 409 冻结态守卫 + 文档职责可选治理
|
||||
|
||||
## 目标
|
||||
|
||||
已激活项目的设置页进入明确的冻结只读态;非必需且允许裁剪的文档可选择“不纳入人工审批”,部分职责、必需文档空职责、非成员职责和零治理激活由服务端拒绝;门禁、权限、快照与页面语义保持一致。
|
||||
|
||||
## 范围
|
||||
|
||||
- `web/src/components/project/ProjectSettingsModal.tsx`:frozen 视图、逐文档审批开关、内联/sticky 错误、并发恢复。
|
||||
- `web/src/api/projectSettings.ts`:保留 status/code/message/issues 的 typed error。
|
||||
- `internal/projectinstance/validator.go`:统一 DutyMode、工作流定义约束、结构与成员校验。
|
||||
- `internal/projectinstance/service.go`:保存/预览/激活重复复核 active members。
|
||||
- `internal/projectinstance/gate.go`、`stage_access.go`、`document_access.go`:none/full/disabled 一致语义。
|
||||
- `internal/projectinstance/store.go`、`internal/workflow/runtime/orchestrator.go`:快照清理、零 assignment rows、零职责运行时契约。
|
||||
- 激活预览统计与相应前后端测试。
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不修改项目 143 的现有工作流配置,不在验收中终止项目 143。
|
||||
- 不支持部分指派或自动补齐职责。
|
||||
- 不允许项目配置降低工作流定义中必需/阻断文档的治理要求。
|
||||
- 不把“无需人工审批”文档改成无版本、无审计的非受控文档。
|
||||
- 不迁移历史 active 实例;冻结快照继续作为历史 SSOT。
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 定位项目 143 的 409 `PLAN_FROZEN` 根因并落盘 audit。
|
||||
2. [x] 完成方案审核:补齐定义优先、零治理拦截、成员有效性、权限、快照清理和真实 UI 边界。
|
||||
3. [ ] Wave 1:typed API error + frozen 独立只读视图 + sticky/可访问错误 + 两标签竞态恢复。
|
||||
4. [ ] Wave 2:DutyMode、强制/可选任务策略、partial/成员/零治理校验、服务端规范化。
|
||||
5. [ ] Wave 3:门禁、readiness、阶段/文档访问、运行时和预览统计统一。
|
||||
6. [ ] Wave 4:前端逐文档“纳入人工审批”开关及 full/none/partial 交互测试。
|
||||
7. [ ] Wave 5:合 dev、rebuild、真实浏览器新项目全链路;项目 143 只读回归;归档 test report。
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [ ] active 项目设置无编辑控件,页面显示冻结原因、工作流/阶段/职责快照和受控终止影响入口。
|
||||
- [ ] 允许裁剪的非必需文档 full/none 均合法;partial 精确拒绝。
|
||||
- [ ] 必需/阻断/不可裁剪文档全空被服务端拒绝。
|
||||
- [ ] 保存和激活均拒绝非 active project member;预览后成员退出也 fail closed。
|
||||
- [ ] 所有文档 none 时可保存草稿但不能激活。
|
||||
- [ ] none 文档仍生成和入账本、项目成员只读可见、创建者可生成/编辑,但无 review/approve 且不阻塞阶段。
|
||||
- [ ] disabled/none 的冻结快照、plan hash 和 assignment rows 不残留旧职责。
|
||||
- [ ] 两标签陈旧保存的 409 在当前视口可见、草稿保留并转 frozen。
|
||||
- [ ] 工程门禁与整改方案中的真实 UI 用例全部有证据;报告回链。
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: [2026-09-14-workflow-plan-409-frozen-and-optional-duties.md](../../audit/2026-09-14-workflow-plan-409-frozen-and-optional-duties.md)
|
||||
- Remediation: [2026-09-14-workflow-plan-409-frozen-and-optional-duties-remediation.md](../../remediation/2026-09-14-workflow-plan-409-frozen-and-optional-duties-remediation.md)
|
||||
- Test report: (Wave 5 归档至 `.doc/test-reports/`)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
- dev 项目 143:`lifecycle_status=active`、`active_workflow_key=main`、实例 89 active;409 与三名职责人选择内容无关。
|
||||
- 当前 `parseError` 已读取后端 message;前端改造重点是 typed error、冻结态切换和视口内呈现。
|
||||
- 当前职责校验只检查正数/互异,数据库只外键到 users;项目成员有效性必须补服务端校验。
|
||||
- 当前终止实现会取消运行任务、关闭实例并退回 planning;关闭实例访问 fail closed,因此项目 143 不能作为终止测试对象。
|
||||
- 开始编码前必须先把本任务从当前误置的 `feature/remove-herdr-agent-settings` 工作区迁移至声明的 `fix/workflow-plan-409-frozen-and-optional-duties` 分支/worktree,禁止污染无关分支。
|
||||
@@ -0,0 +1,44 @@
|
||||
---
|
||||
title: "对话意图、可恢复任务状态与文档占用可见性整改"
|
||||
status: in_progress
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
---
|
||||
|
||||
# 对话意图、可恢复任务状态与文档占用可见性整改
|
||||
|
||||
## 背景
|
||||
|
||||
见 [专项审计](../audit/2026-09-13-conversation-intent-runtime-state.md)。本问题不是单一意图模型错误,而是客户端写操作捷径、任务状态投影、租约展示和诊断数据隔离四处合同不一致。
|
||||
|
||||
## 目标
|
||||
|
||||
- 只读表达永不直接触发文档写任务;写操作必须具有明确动作语义。
|
||||
- 失败、运行中、质量失败和恢复动作刷新后等价恢复。
|
||||
- 文档被人工或智能体编辑时,在会话、文档列表和编辑器持续显示同一个服务端状态,并在发送前阻止重复写任务。
|
||||
- 自动化/诊断请求只能使用隔离 fixture,不得写入真实用户会话。
|
||||
|
||||
## 分波次计划
|
||||
|
||||
| 波次 | 内容 | 验收 |
|
||||
|------|------|------|
|
||||
| Wave 0 | 禁止真实会话诊断探针;补污染审计与只读负例 | “总结/查看/状态/谁在编辑”均不命中写任务 |
|
||||
| Wave 1 | 将客户端模板匹配收紧为“动作 + 目标”;“总结”由服务端按项目/阶段权限读取正文并在隔离对话目录生成只读摘要 | 明确“编写/生成/更新”触发;总结返回正文摘要且不创建 run/租约 |
|
||||
| Wave 2 | 持久化/重建 `error_info`、task request、进度与恢复动作 | 刷新前后失败卡片语义和按钮一致 |
|
||||
| Wave 3 | 增加运行态/租约查询与统一 busy UI,消费 governance 事件 | 运行中刷新仍显示文档、持有人、阶段、开始时间和禁止编辑提示 |
|
||||
| Wave 4 | 将 busy 分型为策略状态,并在 `task_runs`/聊天占位创建前做服务端预检;执行真实 PI + 刷新 + 双标签页 E2E | 重复请求不会创建第二 run;busy 卡刷新可恢复;完成后自动解锁 |
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] “总结一下用户初始需求表”返回已有文档摘要,不创建 `task_runs`。
|
||||
- [ ] “开始编写用户初始需求表”只创建一个 run;运行中再次写请求不创建失败 run。
|
||||
- [ ] 任务失败后刷新,错误码、诊断摘要及允许动作与刷新前一致。
|
||||
- [ ] 运行中刷新,聊天占位、阶段进度、文档 busy 标识和输入保护均恢复。
|
||||
- [ ] 租约释放/任务终态后 UI 自动解除 busy,无需用户手动刷新。
|
||||
- [x] 测试使用专用项目/会话并在 teardown 清理;禁止 `debug/test` 探针进入非 fixture 会话。
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: [../audit/2026-09-13-conversation-intent-runtime-state.md](../audit/2026-09-13-conversation-intent-runtime-state.md)
|
||||
- Short-term: [../ops/short-term/2026-09-13-conversation-intent-runtime-state.md](../ops/short-term/2026-09-13-conversation-intent-runtime-state.md)
|
||||
- gap-matrix 行: `CHAT-INTENT-STATE`
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
title: "职责单元格按 value/badge 精确断言"
|
||||
status: in_progress
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
---
|
||||
|
||||
# 职责单元格按 value/badge 精确断言
|
||||
|
||||
## 背景
|
||||
|
||||
链到 [../audit/2026-09-13-document-revision-duty-cell-assertion.md](../audit/2026-09-13-document-revision-duty-cell-assertion.md)。
|
||||
|
||||
## 目标
|
||||
|
||||
- 精确定位该文档行的职责控件
|
||||
- select:`value` 必须是 `reviewer`,且 `data-can-assign=false`、`disabled`;`canAssignLead=true` 拒绝
|
||||
- badge:`data-doc-role` 必须是 `reviewer`;`viewer` / `author` / `approver` / 未知值拒绝
|
||||
- 保留无「双击任意段落就地编辑」、双击不出现编辑器
|
||||
|
||||
## 分波次计划
|
||||
|
||||
| 波次 | 内容 | 验收 |
|
||||
|------|------|------|
|
||||
| Wave 0 | 控件 `data-testid`/`data-doc-id`/`data-doc-role` + 精确 reviewer 谓词 + UI-13a | option 文案不得误判;viewer/可配置 select 拒绝;`npm test`/`build` |
|
||||
| Wave 1 | 占槽重跑真实 UI-13a(本轮不做) | 矩阵断言过,只读检查仍跑 |
|
||||
|
||||
## 设计
|
||||
|
||||
1. `resolveDutyCell`:只接受 `select.value` 或 `badge.role`;`row-text` 一律 reject。
|
||||
2. `evaluateExpectedDuty(input, expected)` / `evaluateReviewerDuty`:UI-13a 只接受 `reviewer`。
|
||||
3. 产品 select/badge/行补 `data-testid`、`data-doc-id`、`data-doc-role`、`data-can-assign`。
|
||||
4. UI-13a 按 docId 定位控件,不再 `intakeRow.innerText`。
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 整行含全部 option 时不得推断职责
|
||||
- [x] select/badge 必须 `reviewer`;viewer/author/approver/未知拒绝
|
||||
- [x] select 必须 `canAssignLead=false` 且 disabled;`canAssignLead=true` 拒绝
|
||||
- [ ] 真实 UI-13a(本轮不做)
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit / Short-term:同 slug `2026-09-13-document-revision-duty-cell-assertion`
|
||||
- 证据(只读):`.doc/test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui13a-duty-cell-assertion-failure/`
|
||||
@@ -0,0 +1,51 @@
|
||||
---
|
||||
title: "权威文档职责 + 打开时基线 ETag"
|
||||
status: in_progress
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
---
|
||||
|
||||
# 权威文档职责 + 打开时基线 ETag
|
||||
|
||||
## 背景
|
||||
|
||||
链到 [../audit/2026-09-13-document-revision-duty-etag-overwrite.md](../audit/2026-09-13-document-revision-duty-etag-overwrite.md)。
|
||||
|
||||
陌生人/审核人被抬成编制人可改受控正文;保存时重取最新 ETag 会掩盖 409 并覆盖并发编辑。
|
||||
|
||||
## 目标
|
||||
|
||||
1. 列表 summary 返回台账 author/reviewer/approver 的 id+name;前端保留权威字段,禁止用当前登录用户伪造 author。
|
||||
2. `currentDocRole` 按权威 user id 解析;name 仅兼容旧本地文档;未知身份 fail-closed 为 `viewer`;viewer 无编辑/审核/批准动作。
|
||||
3. 受控正文 hydrate 同时取 revision-state ETag 写入 AST/缓存;人工 PATCH 只用该基线;成功后用响应 `state.etag` 更新;冲突保留编辑器与文本。
|
||||
4. **受控 fail-closed**:缺打开时 ETag 禁止 PATCH `0:0`;hydrate 遇 revision-state 网络/5xx/NOT_FOUND/NEEDS_CONTENT 走正文加载失败屏障。仅 freeform 允许 `0:0`。
|
||||
5. viewer 只读批注:无右键/浮标新增入口,面板不可提交;author/reviewer/approver 语义不变。
|
||||
6. 服务端受控 / `dutiesAuthoritative` 一律按 id fail-closed;name 回退仅真正旧本地文档。duty id 为 0 不得当成本地旧文档。
|
||||
7. UI-13b:A1 保存前两窗口已加载相同 r/etag,且 A2 编辑器已打开并填入文本。
|
||||
|
||||
## 分波次计划
|
||||
|
||||
| 波次 | 内容 | 验收 |
|
||||
|------|------|------|
|
||||
| Wave 1 | Go summary 投影职责 + 单测 | B 不是 author;A 仍是 author |
|
||||
| Wave 2 | 前端 merge / `UserRole=viewer` / `resolveCurrentDocRole` | B/陌生人不成 author;viewer 无动作 |
|
||||
| Wave 3 | hydrate 基线 ETag + PATCH 不再 GET | stale ETag 单测;不能用最新 ETag 掩盖冲突 |
|
||||
| Wave 4 | UI-13b 真实竞争脚本 | A2 先开编辑器再 A1/A2 保存 |
|
||||
| Wave 4b | ETag/viewer/零 id 补强 | controlled 缺基线不可保存;viewer 只读批注;id=0 不按 name 提权 |
|
||||
| Wave 5 | 占槽真实 UI(本轮不做) | UI-13a/13b 实战 PASS 后才可 done |
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] Go `ListWorkflowDocumentsIncludesAuthoritativeDuties`
|
||||
- [x] 前端 merge + `resolveCurrentDocRole` 单测
|
||||
- [x] stale hydrate ETag 用于保存(纯函数 + hydrate 单测)
|
||||
- [x] UI-13b 脚本不降级(本轮不跑真实 E2E)
|
||||
- [x] controlled 缺 hydrate ETag / 5xx 不可保存或打开;freeform 可 `0:0`
|
||||
- [x] viewer 不能新增批注
|
||||
- [x] 服务端 duty id=0 不按 name 提权
|
||||
- [ ] 真实 UI 重跑 PASS
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: [../audit/2026-09-13-document-revision-duty-etag-overwrite.md](../audit/2026-09-13-document-revision-duty-etag-overwrite.md)
|
||||
- Short-term: [../ops/short-term/2026-09-13-document-revision-e2e-reject-routing.md](../archive/ops/2026-09-13-document-revision-e2e-reject-routing.md)
|
||||
@@ -0,0 +1,56 @@
|
||||
---
|
||||
title: "编辑弹窗 hydration 竞态整改"
|
||||
status: in_progress
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
---
|
||||
|
||||
# 编辑弹窗 hydration 竞态整改
|
||||
|
||||
## 背景
|
||||
|
||||
链到 [../audit/2026-09-13-document-revision-editor-hydration-race.md](../audit/2026-09-13-document-revision-editor-hydration-race.md)。
|
||||
|
||||
第十二轮 UI-06:fill 瞬间后台 GET 完成 hydration,块 ID 被重建;保存按旧 ID 找不到目标后静默关窗,PATCH 次数为 0,修订停在 r0。
|
||||
|
||||
## 目标
|
||||
|
||||
- 编辑期间后台 hydration(含 fill 与 save 之间完成的响应)不得替换块身份、不得覆盖编辑基线
|
||||
- PATCH 成功后迟到 hydration 不得回滚新正文 / 新 ETag
|
||||
- 找不到目标块时 fail-closed:保留弹窗与用户输入,明确提示,绝不关窗、不按正文改另一个块
|
||||
- 正常保存仍发 PATCH,采用打开时/hydrate 基线 ETag;409 语义不削弱
|
||||
- **不声称真实 UI/E2E 已通过**
|
||||
|
||||
## 分波次计划
|
||||
|
||||
| 波次 | 内容 | 验收 |
|
||||
|------|------|------|
|
||||
| Wave 0 | hydrate 对齐 `head_block_map`;抽出 `editorHydrationGate` + `blockSavePolicy`;App 三条 hydrate 路径与保存接线 | 单测:同 map 两次 hydrate ID 稳定;缺 map 仍随机;deferred hydrate / stale id / 迟到 hydrate / PATCH+409;`npm test` + `npm run build` |
|
||||
| Wave 1 | 占槽后真实 UI-06(本轮不做) | 现场 PATCH 次数 ≥ 1 且 r0→r1 |
|
||||
|
||||
## 设计
|
||||
|
||||
两层,缺一不可;不靠 Playwright sleep:
|
||||
|
||||
1. **身份对齐**:`hydrateControlledDocumentContent` 保留完整 `RevisionState`(含 `head_block_map`),`buildControlledDocumentAST` 后 `applyHeadBlockMap`。同一 head 的重复 hydrate 不再因 `Math.random` 换 ID。
|
||||
2. **generation / 编辑门闩**:双击立刻 `setEditorOpen(true)`;编辑中 `beginHydration` 返回 `null`;已在途 token 经 `decideHydrationApply` 丢弃。PATCH 成功先 `markSaved()` 再关窗,迟到 hydrate **即使 ID 已对齐**也不得回滚新正文。
|
||||
3. **stale-id fail-closed**:`resolveSaveTargetBlock` **只按 id**;找不到则提示并留窗,绝不按正文改另一块、绝不静默关窗。
|
||||
4. **真实 PATCH 编排**:`saveControlledBlockEdit` 被 `App.tsx` 调用;依赖注入 `patchDocumentContent`。成功路径恰好一次 PATCH(绑定 `editorDocId`、hydrate ETag、`client_block_map`),采用响应 ETag。409/网络错误不关窗。
|
||||
5. **编辑会话绑 docId**:`editorSession = { docId, block }`。`activeDocId` 被 canonical/session 改写后保存 fail-closed,无 PATCH。
|
||||
6. **关窗续跑**:`editor_open` 跳过/丢弃的 hydrate 置 `blockedNeedsResume`;安全关闭后 `hydrateResumeKey` 重跑 effect,避免永久 loading skeleton。
|
||||
7. **切文档**:modal `fixed inset:0 z-index 100` 挡住 SlimTabBar,但 chat/drawer 仍可调 `handleSelectDoc`。编辑中切换 fail-closed 并提示,不静默关窗。
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 纯函数门闩覆盖 UI-06 时序(hydrate 在 fill 后 resolve 不覆盖)
|
||||
- [x] stale block id 保存不静默关闭、不假成功、不改同内容另一块
|
||||
- [x] PATCH 成功后迟到 hydration 不回滚;409 保留草稿
|
||||
- [x] `saveControlledBlockEdit` 成功路径断言恰好一次 PATCH(docId/ETag/body/map);doc 漂移/409/网络不关窗
|
||||
- [x] 关窗后续跑被阻塞的 hydrate;编辑中切文档 fail-closed
|
||||
- [ ] 真实 UI-06 E2E(本轮不做,不得勾选)
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: [../audit/2026-09-13-document-revision-editor-hydration-race.md](../audit/2026-09-13-document-revision-editor-hydration-race.md)
|
||||
- Short-term: [../ops/short-term/2026-09-13-document-revision-editor-hydration-race.md](../archive/ops/2026-09-13-document-revision-editor-hydration-race.md)
|
||||
- 证据(只读): `.doc/test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui06-r-bump-noop-failure/`
|
||||
@@ -0,0 +1,48 @@
|
||||
---
|
||||
title: "UI-11 快速完成观测契约整改"
|
||||
status: in_progress
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
---
|
||||
|
||||
# UI-11 快速完成观测契约整改
|
||||
|
||||
## 背景
|
||||
|
||||
链到 [../audit/2026-09-13-document-revision-fast-completion-observation.md](../audit/2026-09-13-document-revision-fast-completion-observation.md)。
|
||||
|
||||
只修验收脚本与测试契约,不改产品运行时,不降低真实性。
|
||||
|
||||
## 目标
|
||||
|
||||
- 定位到该用户 prompt 的相邻助手卡片已是成功终态(`completed` / `pending_author_confirmation`)时直接接受
|
||||
- 仍须校验:消息对应关系、成功终态、无错误;UI-11 另须页面上传证据(chip / freeform 2xx / `doc-free-*` pane)
|
||||
- 处理中状态只作可选观测,不得硬等 60s
|
||||
- 两类可重复契约:直接 `completed`、经历 inflight 再到终态
|
||||
|
||||
## 分波次计划
|
||||
|
||||
| 波次 | 内容 | 验收 |
|
||||
|------|------|------|
|
||||
| Wave 0 | 抽取观测谓词 + 改 `waitForSquadCompletion` + 单测 | 直接 completed 接受;经历 inflight 接受;错误终态拒绝;UI-11 上传断言保留 |
|
||||
| Wave 1 | 占槽后重跑真实 UI-11(本轮不做) | 快完成不再被误判 |
|
||||
|
||||
## 设计
|
||||
|
||||
1. **先读当前 `data-chat-status`**:成功终态 + 无可见错误 → 立即接受,即使从未看到 inflight。
|
||||
2. **仍在处理中**:再等终端态;不把「必须先看到 pending」当作门闩。
|
||||
3. **失败终态 / 可见错误 / 找不到相邻助手**:FAIL,不得假通过。
|
||||
4. **`requireInflight` 默认关闭**;即使显式打开,已 completed 仍直接接受。
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 快照已是 completed → accept,`sawInflight=false`
|
||||
- [x] pending → completed → accept,`sawInflight=true`
|
||||
- [x] failed / 无对应关系 / 可见错误 → reject
|
||||
- [x] UI-11 上传与 freeform 断言不删不降
|
||||
- [ ] 真实 UI-11(本轮不做)
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit / Short-term:同 slug `2026-09-13-document-revision-fast-completion-observation`
|
||||
- 证据(只读):`.doc/test-reports/assets/2026-09-13-document-revision-runtime-ui/schema30-ui11-fast-completion-observation-failure/`
|
||||
@@ -0,0 +1,322 @@
|
||||
---
|
||||
title: "文档修改、智能体版本与差异认知能力实施方案"
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
---
|
||||
|
||||
# 文档修改、智能体版本与差异认知能力实施方案
|
||||
|
||||
## 1. 背景
|
||||
|
||||
专项分析确认:当前受控文档只有当前 `output.md` 和 SHA,没有历史正文快照;人工块编辑未接服务端保存;智能体完成只更新当前哈希;已有变更提案不是基于实际 before/after 的报告;通知仅覆盖阶段推进。
|
||||
|
||||
- Audit: [../audit/2026-09-13-document-revision-management-gap-analysis.md](../audit/2026-09-13-document-revision-management-gap-analysis.md)
|
||||
- Design: [../system-design/document-revision-management.md](../system-design/document-revision-management.md)
|
||||
|
||||
## 2. 目标
|
||||
|
||||
交付一套生产可验证的文档修改管理能力:
|
||||
|
||||
- 模板/智能体生成定义 Version,人工保存定义 Version 内 Revision;
|
||||
- 当前文档只标记相对最新智能体 baseline 的人工修改;
|
||||
- 可比较任意两个 Version,并查看每次修改主体;
|
||||
- Agent 生成绑定结构化摘要、风险、项目/文档影响;
|
||||
- 文档负责人和受影响负责人可靠收到通知;
|
||||
- 全链路服务端授权、并发安全、可恢复、可审计。
|
||||
|
||||
## 3. 前置决策门
|
||||
|
||||
用户审核方案后再进入业务代码实施。首个实施任务开始前冻结:
|
||||
|
||||
1. 版本语义和历史版本显示命名;
|
||||
2. high/critical 变更是否强制二次确认(推荐是);
|
||||
3. 首发只覆盖受控文档还是同步切换自由文档 UI(推荐受控优先);
|
||||
4. 受控/自由文档保留期与候选清理策略;
|
||||
5. 当前并行任务的 mutex、集成槽位和 Goose 最新迁移号;
|
||||
6. 根表 ledger 指针列命名:不得与既有 `freeform_documents.current_version_id`(00008,每-save+1 的 legacy 语义)同名冲突,新列统一 `ledger_*`/`head_*` 前缀,旧列改名或降级只读(见设计 §6.7)。
|
||||
|
||||
## 4. 分波次计划
|
||||
|
||||
| 波次 | 范围 | 主要交付 | 验收门 |
|
||||
|---|---|---|---|
|
||||
| Wave 0 契约冻结 | 领域词典、JSON schema、API、错误码、授权矩阵、fixture | `revision-contract-v1`、`change-report-v1`、黄金 diff 数据 | 评审通过;契约测试先红 |
|
||||
| Wave 1 快照与版本内核 | PG schema、immutable snapshot、Version/Revision 状态机、历史回填 dry-run | `internal/docrevision`、Goose 迁移、backfill CLI/report | 单元 + PG 并发/回填 PASS |
|
||||
| Wave 2 人工编辑闭环 | 受控 Block 编辑接 API、稳定 block map、租约/If-Match/冲突 UI | 真正持久化、人工 overlay、刷新恢复 | 双用户/双标签页 E2E PASS |
|
||||
| Wave 3 Agent 版本提交 | candidate、实际 diff、报告生成/校验、run finalize 原子提交 | 单 agent/squad attribution、Vn 封存→Vn+1 | stub + PG fault injection + 真实 PI PASS |
|
||||
| Wave 4 版本历史与比较 UI | timeline、A/B 选择、side-by-side/unified、筛选/跳转/导出 | 美观可访问的比较体验 | Playwright 视觉/交互/无障碍 PASS |
|
||||
| Wave 5 影响与通知 | lineage/risk policy、outbox fanout、通知中心、读/已处理 | 负责人和受影响文档负责人通知 | 去重/重启/权限负例 PASS |
|
||||
| Wave 6 自由文档兼容与发布 | legacy checkpoint 导入、统一读模型、灰度、性能/保留 | 自由文档采用同一版本语义;迁移收尾 | 旧数据升级 + rollback drill PASS |
|
||||
|
||||
Wave 1–5 的发布顺序不可颠倒;特别是不得先上线前端颜色标记再补快照事实源。
|
||||
|
||||
## 5. 工程拆分
|
||||
|
||||
### 5.1 Task DR-00:契约、fixture 与 ADR
|
||||
|
||||
建议文件:
|
||||
|
||||
- `.doc/adr/YYYY-MM-DD-document-version-boundary.md`
|
||||
- `internal/docrevision/testdata/*.json`
|
||||
- `web/src/features/documentRevision/types.ts`
|
||||
- OpenAPI/接口契约所在路径(若仓库建立统一 OpenAPI,必须同步)
|
||||
|
||||
动作:
|
||||
|
||||
- 固定 Version/Revision/Snapshot/Candidate/Report 定义;
|
||||
- 固定 actor kind、错误码、change report JSON schema;
|
||||
- 建立中文段落、表格、列表、Mermaid、移动块、同内容 no-op 的黄金 diff;
|
||||
- 固定 canonical Markdown 规则(LF、UTF-8、Unicode NFC、尾换行、表格规范);
|
||||
- 把用户核心时间线写成契约测试。
|
||||
|
||||
### 5.2 Task DR-01:数据库与 revision 内核
|
||||
|
||||
建议文件:
|
||||
|
||||
- `deploy/postgres/goose/000XX_*document-revisions.sql`
|
||||
- `internal/docrevision/{types,service,store,diff}.go`
|
||||
- `cmd/document-revision-backfill/` 或既有迁移工具入口
|
||||
|
||||
动作:
|
||||
|
||||
- 新建 content blobs、snapshots、versions、events、candidates、reports;
|
||||
- 根表增加 ledger version/head/revision/review snapshot 指针;列名统一 `ledger_*`/`head_*` 前缀,禁止与既有 `freeform_documents.current_version_id`(每-save+1 的 legacy 语义)同名冲突,迁移中同步处理旧列改名/退役;
|
||||
- partial unique、幂等唯一、actor check、immutable trigger/DB privilege;
|
||||
- 写 `SELECT FOR UPDATE` 的 human revision 与 agent version 事务;
|
||||
- 回填受控 `output.md`,生成 success/missing/hash-mismatch/no-template 报告;
|
||||
- 内存模式只用于单元测试,不作为生产 fallback。
|
||||
|
||||
门禁:
|
||||
|
||||
- 50–100 goroutine/连接并发下每文档 event_no、revision_no 连续且无双 open Version;
|
||||
- 注入每个 SQL 步骤失败,事务均回滚;
|
||||
- no-op 不增加 snapshot/version;同幂等键返回原结果;
|
||||
- 空库与 schema 27 升级路径都可重复执行。
|
||||
|
||||
### 5.3 Task DR-02:人工编辑持久化与冲突处理
|
||||
|
||||
建议文件:
|
||||
|
||||
- `internal/server/document_revision_handlers.go`
|
||||
- `internal/projectinstance/document_access.go`
|
||||
- `web/src/api/documentRevision.ts`
|
||||
- `web/src/components/doc/BlockEditorModal.tsx`
|
||||
- `web/src/components/doc/BlockRenderer.tsx`
|
||||
- `web/src/lib/controlledDocHydrate.ts`
|
||||
- `web/src/App.tsx`(实施时应先拆出 feature hook,避免继续膨胀)
|
||||
|
||||
动作:
|
||||
|
||||
- 删除前端可信 `user_id/user_name/user_role/work_dir/holder_id`;
|
||||
- Block save、插入、删除、移动均走统一 PATCH,不再只改 `docCache`;
|
||||
- stable block id 随 snapshot 回传,后端验证并重算 diff;
|
||||
- 409 返回 base/current 指针,UI 显示三方 diff 和“保留我的副本/刷新后重做”,禁止自动重试;
|
||||
- 默认 overlay=baseline→head,并提供 pure/manual/all 和 actor filter;
|
||||
- 刷新、重登、双标签页从服务端完整恢复。
|
||||
|
||||
### 5.4 Task DR-03:Agent candidate 与原子版本提交
|
||||
|
||||
建议文件:
|
||||
|
||||
- `internal/bizdev/service.go`
|
||||
- `internal/squad/{service,quality_gate,models}.go`
|
||||
- `internal/server/task_finalize.go`
|
||||
- `internal/taskrun/`
|
||||
- `configs/` 中相关 prompt/schema
|
||||
|
||||
动作:
|
||||
|
||||
- task run 捕获 immutable input snapshot;
|
||||
- `SquadRunResult` 增加 report target 与 actor snapshot,不以客户端 supplied actor 为准;
|
||||
- L3 生成 `output.md + change_report.json`;
|
||||
- 先创建 candidate,再按提案/风险决定提交;
|
||||
- finalizer 统一调用 `CommitAgentVersion`,成功后才把任务标 completed;
|
||||
- 版本、报告、lineage/stale、outbox 同事务;
|
||||
- 记录 squad 全体配置,但只在有 StepManifest 证据时做 hunk contributor 归属。
|
||||
|
||||
门禁:
|
||||
|
||||
- agent 运行前后 head 改变时绝不覆盖;
|
||||
- finalize 重试只建一个版本;
|
||||
- 报告非法不改变 current head;
|
||||
- proposal 范围外修改/high-risk 被确定性门禁拦截;
|
||||
- 单 agent 与 squad 在时间线中明确区分。
|
||||
|
||||
### 5.5 Task DR-04:版本历史与比较体验
|
||||
|
||||
建议新组件:
|
||||
|
||||
- `DocumentRevisionToolbar`
|
||||
- `ManualChangeOverlay`
|
||||
- `VersionHistoryDrawer`
|
||||
- `VersionCompareView`
|
||||
- `ChangeReportPanel`
|
||||
- `DiffNavigator`
|
||||
|
||||
动作:
|
||||
|
||||
- 在 SlimTabBar 下方增加版本/修订二级工具条;
|
||||
- 版本历史按 Version 展开 Revision,不平铺自动保存;
|
||||
- 宽屏 side-by-side、窄屏 unified,章节同步滚动;
|
||||
- 段落/表格/列表/代码采取不同 decorations;
|
||||
- 颜色 + 线型 + 图标 + 文本多重编码;
|
||||
- 导出默认纯净,审计导出附变更表和 hash。
|
||||
|
||||
门禁:
|
||||
|
||||
- 500px 右栏、全屏、移动窄屏均可用;
|
||||
- 10k hunk 限制和长表格虚拟化不卡死主线程;
|
||||
- 键盘可完成选择版本、跳转差异、开关 overlay;
|
||||
- XSS/Mermaid 恶意 diff fixture 不执行脚本。
|
||||
|
||||
### 5.6 Task DR-05:影响、风险与通知
|
||||
|
||||
建议文件:
|
||||
|
||||
- `internal/docrevision/{impact,risk,report_validator}.go`
|
||||
- `internal/notification/document_events.go`
|
||||
- `internal/server/notification_handlers.go`
|
||||
- `web/src/components/notifications/`
|
||||
|
||||
动作:
|
||||
|
||||
- ImpactEngine 只从冻结 workflow snapshot、task dependency 和 document lineage 计算权威集合;
|
||||
- 风险取 rule/model 最大值,无法评估按 high;
|
||||
- 创建 candidate-ready、version-committed、downstream-impact、report-degraded 事件;
|
||||
- 收件人解析 current duty assignment,变更文档 author 必达;
|
||||
- 对每个受影响文档逐一授权裁剪通知 payload;
|
||||
- 增加通知 mark read/acted/dismissed 与全局/项目通知中心;
|
||||
- 15 秒轮询可先复用,最终可合并到可恢复 SSE/推送通道。
|
||||
|
||||
门禁:
|
||||
|
||||
- DB 提交后杀进程,重启仍能完成一次 fanout;
|
||||
- 同 run/版本不会重复通知;
|
||||
- 负责人变更时以 commit 时的 current assignment 解析并保存收件快照;
|
||||
- 无权用户不能从影响数量以外获知受限文档名或正文。
|
||||
|
||||
### 5.7 Task DR-06:自由文档与历史兼容
|
||||
|
||||
动作:
|
||||
|
||||
- 将 `freeform_document_versions` 导入 snapshot/event,保留 legacy checkpoint 展示;
|
||||
- 当前 freeform head 建 `origin=migration` 开放 Version;新 `document_versions.version_no` 起点规则(推荐从 legacy 最大 version_no+1 起算)在契约冻结时确认;
|
||||
- 新人工保存只加 Revision,智能体生成才开新 Version;
|
||||
- owner 作为负责人接收通知;项目共享成员保持只读(首期);
|
||||
- 不引入 author/reviewer/approver 伪职责。
|
||||
|
||||
## 6. API 与兼容策略
|
||||
|
||||
### 6.1 新 API
|
||||
|
||||
按设计文档 §12 实现 `/api/v1/documents/{doc_id}/revision-state|versions|diff|manual-overlay|content|agent-candidates|change-reports`。
|
||||
|
||||
### 6.2 旧 API
|
||||
|
||||
| 旧端点 | 兼容期行为 | 退役条件 |
|
||||
|---|---|---|
|
||||
| `GET /api/v1/docgov/documents/{id}/content` | 从 current snapshot 读,ETag 改为 snapshot SHA | 所有前端/Agent reader 切新端点 |
|
||||
| `POST /api/v1/docgov/content` | 委托 human revision service,并要求 If-Match/幂等;一版后 410 | 新 PATCH 全量上线 |
|
||||
| `PUT /api/v1/freeform-documents/{id}` | 兼容适配 revision engine | Wave 6 完成 |
|
||||
| `document_records.version` | 同事务投影 current version_no | 所有查询改用 FK 后退役 |
|
||||
| 工作区 `output.md` | DB head 的兼容投影 | 读链路不再依赖文件后降为缓存 |
|
||||
|
||||
兼容适配只能有一个真实写服务;禁止旧服务写文件、新服务写 DB 的双权威。
|
||||
|
||||
## 7. 授权矩阵与负例
|
||||
|
||||
每个新端点至少覆盖:
|
||||
|
||||
- 未登录 401;
|
||||
- 非项目成员 403/一致的 not-found 策略;
|
||||
- 当前阶段不可见 403;
|
||||
- viewer/reviewer/approver 写正文 403;
|
||||
- author 在 reviewing/approving/approved 写入 423;
|
||||
- 篡改 path 中 doc/project/version/snapshot/candidate/report id 失败;
|
||||
- 伪造 actor、holder、run、workdir、on-behalf-of 无效;
|
||||
- Agent service identity 没有绑定 task instance 或 run 时失败;
|
||||
- 自由私密文档 owner 隔离;shared 文档非 owner 写入失败;
|
||||
- diff/report 中关联的受限下游文档被裁剪。
|
||||
|
||||
## 8. 测试矩阵
|
||||
|
||||
| 层 | 必测内容 | 命令/证据 |
|
||||
|---|---|---|
|
||||
| Go unit | 状态机、canonicalization、diff、block reconcile、risk floor、recipient | `go test -short ./internal/docrevision/...` |
|
||||
| Go package | DocGov/freedoc/taskrun/notification 兼容 | `go test -short ./...` |
|
||||
| Static | Go/TS 静态门禁 | `go vet ./...`; `npm run build` |
|
||||
| PG integration | 事务、并发、FK/unique/immutable、迁移/回填 | `TEST_DATABASE_URL=... go test ...` |
|
||||
| Fault injection | report/outbox/lineage/finalize 每步故障 | 专项 PG test |
|
||||
| Front unit | decorations、version selector、actor filter、error state | `cd web && npm test` |
|
||||
| Browser E2E | 编辑→刷新、Agent→新 baseline、A/B compare、通知 | Playwright,保存截图/trace |
|
||||
| Real PI | 单 agent/squad 真实输出 + report schema + 通知 | 显式真实 PI 开关,不用 stub 冒充 |
|
||||
| Security | cross-project/cross-stage/object-id 负例、XSS fixture | 专项授权与渲染测试 |
|
||||
| Upgrade | 空库、schema 27、历史 mismatch、回滚演练 | 迁移 test report |
|
||||
|
||||
最终报告必须分列 unit、stub、PostgreSQL、真实 PI、浏览器 E2E,不以健康检查代替。
|
||||
|
||||
## 9. 灰度与回滚
|
||||
|
||||
建议 flags:
|
||||
|
||||
- `DOCUMENT_REVISION_LEDGER_WRITE`:影子写 snapshot/event,不改变读路径;
|
||||
- `DOCUMENT_REVISION_READ`:按项目灰度从 DB head 读取;
|
||||
- `DOCUMENT_AGENT_VERSION_COMMIT`:agent candidate/commit 新链;
|
||||
- `DOCUMENT_DIFF_UI`:右侧 overlay/compare;
|
||||
- `DOCUMENT_VERSION_NOTIFICATIONS`:通知 fanout。
|
||||
|
||||
灰度步骤:
|
||||
|
||||
1. 影子写时逐次对比 DB head SHA 与 `output.md` SHA,差异告警;
|
||||
2. 选测试项目切 DB read,保留旧文件只读投影;
|
||||
3. 开启 Agent commit,验证 task finalizer 幂等和报告完整率;
|
||||
4. 开 UI 与通知;
|
||||
5. 所有环境稳定后停止旧直接写入。
|
||||
|
||||
回滚只切读/功能 flag,不删除新表或历史数据。若新写链已产生版本,禁止回滚到会覆盖 `output.md` 的旧写服务;只能进入只读维护或修复新链。
|
||||
|
||||
## 10. 主要风险与控制
|
||||
|
||||
| 风险 | 概率/影响 | 控制 |
|
||||
|---|---|---|
|
||||
| Version 与 Revision 被产品/UI 混用 | 中/高 | 契约冻结、统一中文文案、旧 freeform 标 legacy checkpoint |
|
||||
| Markdown/AST 转换产生伪 diff | 中/高 | canonicalization 黄金集、stable block map、服务端对齐 |
|
||||
| Agent 报告看似完整但漏报 | 高/高 | deterministic diff/impact/risk floor;schema 与一致性校验 |
|
||||
| Agent 执行过久使 candidate stale | 中/中 | immutable input、短锁/策略锁、明确 regenerate,不自动 rebase |
|
||||
| DB 正文体积增长 | 中/中 | SHA 去重、分页 diff、保留策略、容量指标,后续平滑迁对象存储 |
|
||||
| 通知风暴 | 中/中 | 按 version/recipient 去重、跨文档聚合、严重度/偏好;关键站内通知不丢 |
|
||||
| 历史内容 hash 不一致 | 中/高 | dry-run + quarantine,不静默覆盖 |
|
||||
| 多实例下进程 mutex 失效 | 高/高 | PG row lock/lease token/unique constraint,不依赖内存锁作权威 |
|
||||
| 新端点形成 BOLA/侧信道 | 中/高 | 统一 access decider + 全对象负例 + payload 裁剪 |
|
||||
|
||||
## 11. 验收标准
|
||||
|
||||
- [ ] 模板/Agent 开 Version、人工只加 Revision 的规则在 API、UI、DB 一致。
|
||||
- [ ] 当前人工高亮永远是 latest agent baseline→head,Agent commit 后归零。
|
||||
- [ ] 两个任意 Version 默认 final→final/head 比较,可查看 baseline 和 revision。
|
||||
- [ ] 用户、单 agent、agent squad 的修改主体和不可变 actor snapshot 可追溯。
|
||||
- [ ] 智能体输出与 change report 同一次运行产生并绑定精确快照。
|
||||
- [ ] 真实 diff、影响集合和风险下限由服务端确定,模型不能篡改/降级。
|
||||
- [ ] 当前文档负责人收到版本摘要;受影响负责人收到经授权裁剪的通知。
|
||||
- [ ] 并发、重试、重启、迁移和故障注入不产生静默覆盖、双版本或丢通知。
|
||||
- [ ] 已批准文档、跨项目/跨阶段对象和私密文档负例全绿。
|
||||
- [ ] 右侧栏在主题、宽度、键盘、色觉无障碍和大文档条件下可用。
|
||||
- [ ] 所有证据归档至 `.doc/test-reports/`,FEATURE-MATRIX 从 planned 逐波次更新。
|
||||
|
||||
## 12. 完成定义与文档同步
|
||||
|
||||
每个 Wave:
|
||||
|
||||
1. 单独 short-term 任务和 mutex 认领;
|
||||
2. 迁移/API/前端/测试证据同批或紧随提交;
|
||||
3. test report 回链本方案对应任务;
|
||||
4. FEATURE-MATRIX 更新 `planned → partial → done`;
|
||||
5. 若成为发布范围,才在 gap-matrix 新增 blocker;本次方案评审阶段不擅自把它列为当前发布 blocker;
|
||||
6. 最终通过真实 PI、PG、浏览器和权限负例后归档任务。
|
||||
|
||||
## 13. 相关链接
|
||||
|
||||
- Audit: [../audit/2026-09-13-document-revision-management-gap-analysis.md](../audit/2026-09-13-document-revision-management-gap-analysis.md)
|
||||
- System design: [../system-design/document-revision-management.md](../system-design/document-revision-management.md)
|
||||
- Short-term: [../ops/short-term/2026-09-13-document-revision-management-design.md](../archive/ops/2026-09-13-document-revision-management-design.md)
|
||||
- gap-matrix 行: 当前未列为发布 blocker;用户确认进入发布范围后新增
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user