Compare commits
256
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8c9a12d996 | ||
|
|
50f800a409 | ||
|
|
0743fb90ec | ||
|
|
895d5f002a | ||
|
|
4f997a9438 | ||
|
|
ef84d1d8f7 | ||
|
|
4298701b2a | ||
|
|
28d1512e6e | ||
|
|
4d048cc4a3 | ||
|
|
1027026e7a | ||
|
|
8dae227f8c | ||
|
|
05a84e6677 | ||
|
|
23a5f6f589 | ||
|
|
1f35593dcd | ||
|
|
736857a292 | ||
|
|
64ac437a90 | ||
|
|
3b80582123 | ||
|
|
3b56816f4e | ||
|
|
56c85bba11 | ||
|
|
eaffe3eb31 | ||
|
|
c8052c8882 | ||
|
|
511012cede | ||
|
|
c741d26eeb | ||
|
|
0917f39f80 | ||
|
|
765a418df1 | ||
|
|
66c56324ad | ||
|
|
53bb71adae | ||
|
|
fbda195b7f | ||
|
|
a44df9280c | ||
|
|
1e19f5c52f | ||
|
|
8a8197a4f2 | ||
|
|
bdc6415944 | ||
|
|
855363fd60 | ||
|
|
2005a4ca0c | ||
|
|
8b228e2101 | ||
|
|
50cf271b53 | ||
|
|
bf55278740 | ||
|
|
2e99ee3661 | ||
|
|
aec374c5dc | ||
|
|
ad3d10b72d | ||
|
|
276ceb42b3 | ||
|
|
fb19b63baf | ||
|
|
702cf6f949 | ||
|
|
5c4caa375e | ||
|
|
c7677b09f6 | ||
|
|
b94873ab18 | ||
|
|
ba713c266b | ||
|
|
29bb63f766 | ||
|
|
4044b68c9e | ||
|
|
0dd7a412c2 | ||
|
|
741089eca3 | ||
|
|
e16fb7eff2 | ||
|
|
3d444fa5e4 | ||
|
|
08aa56b16c | ||
|
|
f35d265721 | ||
|
|
131c86a919 | ||
|
|
839368198a | ||
|
|
46ee9fe647 | ||
|
|
2755d916f4 | ||
|
|
c36d891b05 | ||
|
|
cf063f5727 | ||
|
|
1afd39c9e8 | ||
|
|
0f656638eb | ||
|
|
223b2841d7 | ||
|
|
26f1632a21 | ||
|
|
4cfe6ff59d | ||
|
|
b6956003d5 | ||
|
|
1385002350 | ||
|
|
da0b3d812b | ||
|
|
7dfd6d6f33 | ||
|
|
a75aa45129 | ||
|
|
53c0722925 | ||
|
|
86f25b26c4 | ||
|
|
53d4077f06 | ||
|
|
91edeccb26 | ||
|
|
c2e79c8a1d | ||
|
|
932ba87daf | ||
|
|
9005766b62 | ||
|
|
475134802b | ||
|
|
8ac3d3fbc6 | ||
|
|
3171e4f0e5 | ||
|
|
29d9c65603 | ||
|
|
42c8ae2ccd | ||
|
|
3d326ad81e | ||
|
|
9364da4974 | ||
|
|
aefb1e45a6 | ||
|
|
bdccb4dbfe | ||
|
|
dd30e061d8 | ||
|
|
987423794f | ||
|
|
8919ca9842 | ||
|
|
2e826e7f58 | ||
|
|
5a79752ebe | ||
|
|
68755862f1 | ||
|
|
067cf8be18 | ||
|
|
035d8594a6 | ||
|
|
fa5955be07 | ||
|
|
69d1203593 | ||
|
|
c1a2bcc26b | ||
|
|
05550f3558 | ||
|
|
3d39ee0589 | ||
|
|
ecba6f3b14 | ||
|
|
a3fa7c137b | ||
|
|
0a61cfbe90 | ||
|
|
4dbe6a431c | ||
|
|
f6813cc272 | ||
|
|
39dc68d15c | ||
|
|
7a9d0d850d | ||
|
|
ad9027fe8f | ||
|
|
9b1a94c5bc | ||
|
|
4a662ec2d3 | ||
|
|
a20760953a | ||
|
|
8400427c24 | ||
|
|
1c04f17c8c | ||
|
|
3a6d4f45dd | ||
|
|
9811ae3841 | ||
|
|
425c8ba776 | ||
|
|
20fc82c485 | ||
|
|
6a9e3fb51a | ||
|
|
2a75abb39e | ||
|
|
3f42149457 | ||
|
|
92a9c6783d | ||
|
|
acb443e949 | ||
|
|
110c2e810c | ||
|
|
6f541feac0 | ||
|
|
23d0cfb10f | ||
|
|
525047b841 | ||
|
|
0a2ea2477d | ||
|
|
7728339d08 | ||
|
|
9ddc673eb8 | ||
|
|
2771a1ed04 | ||
|
|
71502c7ce0 | ||
|
|
a1316e39cb | ||
|
|
97028c33b5 | ||
|
|
51bf791ef0 | ||
|
|
dab3e1a355 | ||
|
|
d645eaa1f7 | ||
|
|
aa2f31dc0f | ||
|
|
92f31ffa6a | ||
|
|
21d7692c94 | ||
|
|
1b1d0a1cba | ||
|
|
7d1b7e736b | ||
|
|
0ebaaaed87 | ||
|
|
965e288d36 | ||
|
|
28bb0b8356 | ||
|
|
ebf16aa094 | ||
|
|
ff713ff790 | ||
|
|
a5e46eeb5f | ||
|
|
16a31f8aa5 | ||
|
|
6702b16249 | ||
|
|
06b824ad7c | ||
|
|
d926f64c2e | ||
|
|
6bee7630bd | ||
|
|
d5968ad4ba | ||
|
|
5fd5588a3f | ||
|
|
5f3b117c00 | ||
|
|
0f2f8d30e5 | ||
|
|
0f2057765a | ||
|
|
504058debf | ||
|
|
bcb122ac53 | ||
|
|
97305d699e | ||
|
|
3d2a1defd8 | ||
|
|
15af018734 | ||
|
|
7647215513 | ||
|
|
5cef85670a | ||
|
|
a3392e3e06 | ||
|
|
9edd6c8190 | ||
|
|
edb7411474 | ||
|
|
347c5f54a6 | ||
|
|
8a8f64a931 | ||
|
|
f5d32cddd1 | ||
|
|
111ab6786e | ||
|
|
bf59cceef2 | ||
|
|
934c0596ea | ||
|
|
717162e701 | ||
|
|
84c0841acb | ||
|
|
652cea1605 | ||
|
|
ef9a162314 | ||
|
|
6601583cbe | ||
|
|
3c9e6d214d | ||
|
|
6e744d3717 | ||
|
|
65bdda8aae | ||
|
|
18d40fa8a9 | ||
|
|
3944856b0a | ||
|
|
af51e74076 | ||
|
|
42f356ccd7 | ||
|
|
be0c1e843f | ||
|
|
b5337d5c77 | ||
|
|
5ac14d649b | ||
|
|
e81e7a1bcc | ||
|
|
367473730b | ||
|
|
f4dfada9ae | ||
|
|
ac302fb78f | ||
|
|
3997a04bdb | ||
|
|
2ddaf769ca | ||
|
|
7be873073c | ||
|
|
eb75f855a5 | ||
|
|
2234af476a | ||
|
|
b8f33b5c55 | ||
|
|
da21911e30 | ||
|
|
b1ce9b5c41 | ||
|
|
0872d8fbb3 | ||
|
|
425338be9e | ||
|
|
c7e3e99303 | ||
|
|
f27059b453 | ||
|
|
18ddd0f862 | ||
|
|
b0d9153e52 | ||
|
|
88b37b60da | ||
|
|
3e4abc51cd | ||
|
|
f34bec40f5 | ||
|
|
cb8eacac61 | ||
|
|
7f8ad76d12 | ||
|
|
3772193747 | ||
|
|
9d6594a31c | ||
|
|
f0f57a0755 | ||
|
|
c754f7743d | ||
|
|
ade618b854 | ||
|
|
ec22843297 | ||
|
|
f8b21ecd7c | ||
|
|
158ce2586d | ||
|
|
312578ccd1 | ||
|
|
2269cabf43 | ||
|
|
a8f9451410 | ||
|
|
05d2154d66 | ||
|
|
68640e4de1 | ||
|
|
1d366fd38e | ||
|
|
aec166ea41 | ||
|
|
68fee06da4 | ||
|
|
1dcffb7d11 | ||
|
|
5ee898e2e4 | ||
|
|
c048060bae | ||
|
|
ab9fccded4 | ||
|
|
9baf3c83f8 | ||
|
|
22f65e5f24 | ||
|
|
2e586c99b8 | ||
|
|
295ad89860 | ||
|
|
8384136989 | ||
|
|
66d2a1837f | ||
|
|
b4699e9cbe | ||
|
|
19f6df58dd | ||
|
|
ed4a3e53de | ||
|
|
bb1927f23b | ||
|
|
840b5be94f | ||
|
|
5d40f5938a | ||
|
|
354e573f37 | ||
|
|
f86a44acd4 | ||
|
|
e1ed561917 | ||
|
|
a0904fdd69 | ||
|
|
708b735eea | ||
|
|
1dd1cc039e | ||
|
|
ea97a658c6 | ||
|
|
de66558736 | ||
|
|
0689ac77c3 | ||
|
|
1b0f99a455 | ||
|
|
94065976a5 | ||
|
|
b01af96045 | ||
|
|
15f52cb14e |
@@ -0,0 +1,62 @@
|
||||
# ADR:以纵向绞杀方式实施模块化单体解耦
|
||||
|
||||
## 状态
|
||||
|
||||
提议(2026-09-14;架构与实施计划已修订,等待用户确认后进入首个实现里程碑)
|
||||
|
||||
## 背景
|
||||
|
||||
`internal/server`、`internal/bizdev`、共享 `UserProjectContext`、工作区路径和多表写入形成隐式耦合。
|
||||
历史受控正文 404/409、刷新后投影缺失和任务终态不完整说明,单纯搬包不会修复事实源、事务与恢复边界。
|
||||
|
||||
## 决策
|
||||
|
||||
1. **保持模块化单体**:不拆微服务;进程内调用使用窄端口,跨进程可靠性只用于持久事件和 FAV。
|
||||
2. **纵向绞杀**:先在现有包边界插入端口和适配器,迁完一条业务链并验证后再移动或重命名包;禁止“先全量搬包、以后再接口化”。
|
||||
3. **契约分层**:外部 API DTO 归 `server/api`;持久 schema、公共事件和稳定共享词汇进入按领域划分的 contracts;一对一内部接口由消费者拥有。
|
||||
4. **命令与事务同属一个应用用例**:一个业务命令只有一个事务 owner;跨表属主通过同一不透明事务作用域协作,业务状态、账本、当前指针、staging 和 outbox 原子提交。
|
||||
5. **单一写者不等于单独事务**:表属主控制 SQL 和不变量;应用 UnitOfWork 控制跨属主提交边界。属主端口不得私自嵌套提交。
|
||||
6. **并发正确性以数据库为准**:用户编辑使用乐观版本/ETag;状态转换使用行锁和条件更新;项目级不变量可使用事务级 advisory lock;进程内 mutex 只能优化,不能作为多副本正确性依据。
|
||||
7. **锁顺序固定**:同一事务按 project/workflow instance → document record → document version/snapshot → task run → outbox/staging 的顺序取锁;事务内禁止 LLM、对象存储、网络调用和长文件 I/O。
|
||||
8. **可靠事件采用 transactional outbox**:事件按至少一次投递设计,具有稳定 ID、schema version、环境/项目范围、聚合序号、因果链和幂等键;逐消费者记录 delivery、重试、租约和死信。
|
||||
9. **工作区是可清理投影**:跨模块只传不可伪造 Workspace ID 和受限 artifact key;物理路径只在 workspace/squadrun 适配器内解析和校验。
|
||||
10. **最终成果进入 FAV**:PostgreSQL 保存业务关系和授权,FAV 只保存已确认终态的精确 payload、manifest、回执和删除状态,workspace 不承担最终成果事实源。
|
||||
11. **授权逐动作校验**:认证适配器构造不可由请求覆盖的 Principal;HTTP、CLI、后台订阅者和恢复流程都按 action/resource/current state fail closed。
|
||||
12. **先完成文档可靠性试点**:只有受控正文刷新、重启、并发提交、投影缺失降级和授权负例通过后,才批准 chat、squad、编排层和传输层扩展。
|
||||
13. **迁移采用 expand/migrate/contract**:允许新增 Goose migration;不得修改已发布迁移;回滚只保证回到最近的兼容阶段,不能任意独立 revert 早期依赖。
|
||||
14. **协议改造独立立项**:统一错误信封和 PI Runner `result.json` 不作为核心模块解耦前置条件;它们使用独立兼容与 E2E 验收。
|
||||
|
||||
## 并发与失败语义
|
||||
|
||||
- 普通聚合状态转换默认 `READ COMMITTED` + 明确行锁/条件更新;涉及跨聚合唯一不变量时才使用 Serializable,并对 `40001`/`40P01` 重跑完整事务。
|
||||
- outbox worker 使用小批次 `FOR UPDATE SKIP LOCKED` 认领,处理发生在事务外;完成、续租和失败回填使用 fencing token 防止过期 worker 覆盖新 owner。
|
||||
- 每个写命令必须同时有 idempotency key、expected version 或两者;相同 key 不同 payload 返回 typed conflict。
|
||||
- 锁等待、事务时长、重试次数、队列积压和死信必须可观测;超过预算时失败返回,不无限等待。
|
||||
|
||||
## 授权与恢复语义
|
||||
|
||||
- Principal 至少携带 actor、环境、认证来源和请求关联 ID;项目、会话、文档、阶段与 duty 从数据库权威关系重新解析。
|
||||
- 持久事件中的 actor 只用于审计,不能替代订阅者对当前资源状态的授权检查。
|
||||
- FAV 降级读取要求运行库授权图完整;授权图缺失时禁止面向用户返回内容。
|
||||
- 恢复只允许进入 scratch identity;promotion 需要系统管理员与数据责任人确认,并通过各属主端口提交,禁止恢复 CLI 直写运行表。
|
||||
|
||||
## 后果
|
||||
|
||||
- 首个实现里程碑的改动面小于原 Wave 1–6,但会先增加 UnitOfWork、事件投递和授权基础设施。
|
||||
- “单表唯一写者”检查改为生产 SQL 写权限检查,并允许 migration、测试和经批准运维脚本存在表名。
|
||||
- `feature/final-artifact-vault` 是候选依赖,不直接假定可合入;必须先按当前 dev 重放测试、迁移和权限审计。
|
||||
- 包物理移动、错误信封、SSE 和 PI Runner 协议可延后,不阻塞文档一致性整改。
|
||||
|
||||
## 替代方案
|
||||
|
||||
- **一次性横向搬包**:拒绝。冲突面大,不能先证明用户故障减少。
|
||||
- **仅增加 arch-check**:拒绝。门禁不能替代事务、锁和授权契约。
|
||||
- **拆微服务**:拒绝。当前问题是模块边界和数据一致性,不需要引入分布式事务与跨服务部署成本。
|
||||
- **继续把 workspace 作为恢复来源**:拒绝。工作区属于可清理计算现场,不能成为最终事实源。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [模块解耦架构](../system-design/2026-09-14-module-decoupling-architecture.md)
|
||||
- [模块解耦整改与重构计划](../remediation/2026-09-14-module-decoupling-refactor-plan.md)
|
||||
- [方案复核](../audit/2026-09-14-module-decoupling-plan-review.md)
|
||||
- [文档版本边界 ADR](./2026-09-13-document-version-boundary.md)
|
||||
@@ -0,0 +1,30 @@
|
||||
---
|
||||
title: "事件连续性采用 consumer checkpoint + 首事件 bootstrap"
|
||||
status: accepted
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
---
|
||||
|
||||
# ADR:事件连续性采用 consumer checkpoint + 首事件 bootstrap
|
||||
|
||||
## 状态
|
||||
|
||||
接受(E0A)。在独立 FAV 审计或明确的无缺口 event sequence 迁移完成前不得改为 gap blocking。
|
||||
|
||||
## 背景
|
||||
|
||||
`event_envelopes` 已有 `UNIQUE (aggregate_type, aggregate_id, aggregate_version)`。受控文档的首次持久事件常常从较高 `aggregate_version`(账本 version_no)开始,中间版本从未发事件。若把领域版本号当成无缺口事件序号并在缺号时等待,会永久阻塞 delivery。MemoryBus 的 `TestGapDoesNotSkipVersion` 只是 characterization,不得搬到 PostgreSQL dispatcher。
|
||||
|
||||
## 决策
|
||||
|
||||
1. Track E 选择 **consumer checkpoint + 首事件 bootstrap**。
|
||||
2. 每个 `(consumer, aggregate_type, aggregate_id)` 记录已成功处理的 `event_id` 与可选 `aggregate_version`。该 aggregate 上的第一件 **safe** 事件即为 bootstrap,不要求 version=1。
|
||||
3. 同一版本多个不同类型事件:当前唯一约束禁止。E0A 审计后保持该约束;需要同版本多事件时另立 additive 迁移,把序号改到独立 `event_seq`,不在本 ADR 启用。
|
||||
4. **禁止** 在 dispatcher 启用 gap wait / `ErrGapWait` 阻塞,直到另有 ADR 选择独立无缺口 event sequence 且完成回填。
|
||||
5. 未知 schema、project 0、错误 environment、未知 consumer 的记录进入 inventory,不得 live claim。
|
||||
|
||||
## 后果
|
||||
|
||||
- E0B checkpoint 表随 dispatcher migration 增加。
|
||||
- Projection 以 `document_id + source_snapshot_id + digest` no-replace,不依赖连续 version。
|
||||
- poison 事件 quarantine 后不静默跳号;其他 aggregate 继续。
|
||||
+4
-3
@@ -1,8 +1,8 @@
|
||||
---
|
||||
title: "修复对话刷新恢复与授权统计不一致"
|
||||
status: in_progress
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
updated: 2026-09-15
|
||||
owner: Cursor
|
||||
branch: fix/chat-history-refresh
|
||||
worktree: ".worktrees/fix-chat-history-refresh"
|
||||
@@ -37,7 +37,7 @@ mutex: chat
|
||||
3. [x] 实现统一会话/消息授权查询及统计同集
|
||||
4. [x] 实现历史 dry-run/backfill 与对账
|
||||
5. [x] 完善前端恢复状态及用户隔离缓存
|
||||
6. [ ] 执行全量门禁、真实 PI 刷新 E2E 和双用户负例(PG/单测已完成;PI 待 dev 容器)
|
||||
6. [x] 执行全量门禁、真实 PI 闲聊刷新 E2E 和双用户负例(编制任务激活链 save 400 未纳入本轮)
|
||||
|
||||
## 验收标准
|
||||
|
||||
@@ -55,3 +55,4 @@ mutex: chat
|
||||
|
||||
- Audit: [../../audit/2026-09-13-chat-history-refresh-disappears.md](../../audit/2026-09-13-chat-history-refresh-disappears.md)
|
||||
- Remediation: [../../remediation/2026-09-13-chat-history-refresh-remediation.md](../../remediation/2026-09-13-chat-history-refresh-remediation.md)
|
||||
- Live: [../../test-reports/assets/2026-09-15-chat-history-refresh-live/live.json](../../test-reports/assets/2026-09-15-chat-history-refresh-live/live.json)(项目 6252,window=categories=2,guest 403)
|
||||
+13
-11
@@ -1,11 +1,11 @@
|
||||
---
|
||||
title: "修复查询误触发写任务与任务状态刷新退化"
|
||||
status: in_progress
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
owner: Codex
|
||||
branch: fix/conversation-intent-state
|
||||
worktree: ".worktrees/fix-conversation-intent-state"
|
||||
updated: 2026-09-15
|
||||
owner: Cursor
|
||||
branch: docs/conversation-intent-dual-tab
|
||||
worktree: "-"
|
||||
mutex: intent
|
||||
---
|
||||
|
||||
@@ -34,24 +34,26 @@ mutex: intent
|
||||
3. [x] 收紧写任务动作识别并修复 busy 错误分型
|
||||
4. [x] 实现任务/租约状态刷新恢复与统一提示
|
||||
5. [x] 实现命名文档的服务端鉴权只读总结(“总结”不止是不写入)
|
||||
6. [ ] 执行前端、Go、PG 与真实 PI 双标签页验收
|
||||
6. [x] 执行前端、Go、PG 与真实 PI 双标签页验收
|
||||
- [x] Go、前端、构建、dev 重建与真实 PI 只读总结
|
||||
- [x] 服务端 busy 预检不创建 run,并持久化无重试状态卡
|
||||
- [ ] 浏览器刷新恢复与双标签页 busy 可见性
|
||||
- [x] 浏览器刷新恢复与双标签页 busy 可见性(项目 6275;禁止项目 143)
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [ ] [整改方案](../../remediation/2026-09-13-conversation-intent-runtime-state-remediation.md) 全部验收项有证据
|
||||
- [ ] `CHAT-INTENT-STATE` 由 FAIL 更新为 PASS
|
||||
- [ ] test-report 归档并回链
|
||||
- [x] [整改方案](../../remediation/2026-09-13-conversation-intent-runtime-state-remediation.md) 全部验收项有证据
|
||||
- [x] `CHAT-INTENT-STATE` 由 FAIL 更新为 PASS
|
||||
- [x] test-report 归档并回链
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Checklist: 本任务验收标准
|
||||
- Handoff: 与 `fix/chat-history-refresh` 合并前复核 `App.tsx/chatWindow.ts`
|
||||
- Handoff: [../../ops/handoffs/2026-09-15-conversation-intent-dual-tab.md](../../ops/handoffs/2026-09-15-conversation-intent-dual-tab.md)
|
||||
- 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)
|
||||
- 双标签活验:项目 **6275** / `sess-p6275-u10` / `run_1789452602295343365`;产物 `.doc/test-reports/assets/2026-09-15-conversation-intent-dual-tab/`
|
||||
- 未改写项目 143,未删除 `sess-p143-u9` 探针
|
||||
@@ -0,0 +1,61 @@
|
||||
---
|
||||
title: "可靠事件与 FAV 集成 M2–M3"
|
||||
status: cancelled
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-15
|
||||
owner: TBD
|
||||
branch: refactor/durable-event-fav-integration
|
||||
worktree: "-"
|
||||
mutex: event-delivery
|
||||
---
|
||||
|
||||
# 可靠事件与 FAV 集成 M2–M3
|
||||
> 2026-09-15:本任务把 durable event 与未审计 FAV 绑成同一关闭条件,且步骤状态已与 U8/U9 后续交付漂移。任务停止使用;持久事件由 [Track E](../../ops/short-term/2026-09-15-durable-event-track-e.md) 接续,FAV subscriber 继续走独立审计,不把本条已勾选步骤视为生产 dispatcher 验收。
|
||||
|
||||
## 目标
|
||||
|
||||
完成 U5–U9,使投影、通知、RunManifest 和最终成果在多 worker、崩溃、重放和 workspace 清理后仍可恢复且不越权。
|
||||
|
||||
## 范围
|
||||
|
||||
- opaque workspace capability、lease 和 fencing。
|
||||
- durable outbox、逐消费者 delivery/inbox、重试和 dead letter。
|
||||
- 审计并集成 `feature/final-artifact-vault` 的适用实现。
|
||||
- taskrun finalize、RunManifest 持久化、FAV coverage 和迁移 corpus。
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不盲目整分支 cherry-pick FAV。
|
||||
- 不启用跨授权图的 vault 读取。
|
||||
- 不自动销毁 dev/main 数据。
|
||||
- 不执行 U10–U12。
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 读取 M1 test report,确认继续 M2 的 go/no-go 已通过。
|
||||
2. [x] 重新分配 Goose 序号并审计 U6/FAV schema 组合。
|
||||
3. [x] 实现 U5–U6,多 app/worker 和 crash matrix 先通过。
|
||||
4. [x] 逐文件审计 FAV 分支,按 U7 边界迁移合格实现。
|
||||
5. [ ] 实现 U8,收敛 taskrun terminal finalize 与 RunManifest。
|
||||
6. [ ] 实现 U9 的 checkpoint backfill、corpus、quarantine 和 cleanup gates。
|
||||
7. [ ] 完成真实 PI、浏览器、workspace 清理、scratch recovery 和 rebuild 演练。
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [ ] 多订阅者有独立 delivery,失败者不阻塞其他订阅者。
|
||||
- [ ] worker crash/retry/replay 不造成重复可见副作用。
|
||||
- [ ] workspace 清空后,verified 最终文档/回复仍可定位并校验。
|
||||
- [ ] 授权图缺失、跨项目、tombstone、坏 digest 和 stale fencing 全部拒绝。
|
||||
- [ ] clean/oldest/previous/hazard/import/reload/rollback/artifact recovery 八轨有独立证据。
|
||||
- [ ] 任何数据销毁仍需完整备份、corpus、FAV coverage 和用户批准。
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Checklist: [../checklists/2026-09-14-module-decoupling-refactor-acceptance.md](../../ops/checklists/2026-09-14-module-decoupling-refactor-acceptance.md)
|
||||
- Handoff: 实施时创建
|
||||
- Test report: 实施后按 M2、M3 分开创建
|
||||
- Plan: [../../remediation/2026-09-14-module-decoupling-refactor-plan.md](../../remediation/2026-09-14-module-decoupling-refactor-plan.md)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
本任务依赖 M1,不得与 M1 同时修改 docgov/docrevision 的事务主链。
|
||||
@@ -0,0 +1,81 @@
|
||||
---
|
||||
title: "治理鉴权升级:职责-动作严格对应 + 未激活拦截 + 关闭创建直通"
|
||||
status: done
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-14
|
||||
owner: implementer_cursor
|
||||
branch: fix/governance-action-level-authz
|
||||
worktree: ".worktrees/fix-governance-action-level-authz"
|
||||
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 收敛 + 本任务登记(Wave 5 已合入本地 `dev@19f6df5`,G0 已开工)
|
||||
2. [x] G1 后端:`CheckDocTaskAccess` 动作-职责映射 + creator 例外移除(保留 none 生成触发)+ gov==nil 未激活拦截(202 契约保留);重写受影响单测
|
||||
3. [x] G2 关闭 `initial_workflow_key` 直通 + 前后端字段废弃 + E2E legacy 用例更新
|
||||
4. [x] G3 前端:chat 治理拦截自然语言提示、按钮级职责禁用、激活确认页冻结提示补强
|
||||
5. [x] G4 dev 库 planning+with_wf 异态审计分类(只读报告,现测 83 条均为测试夹具)
|
||||
6. [x] G5 集成验证 + 测试报告归档(新项目全链路:零治理创建→对话→配置→激活→职责动作负例)
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] full 文档 API 负例:author 不可 review/approve;reviewer 不可 run/edit/submit;approver 不可 run/edit/review;creator 不可任一审批动作(view 除外)
|
||||
- [x] none 文档:创建者可触发生成;submit/review/approve 全拒
|
||||
- [x] 未激活项目编制类输入:消息正常显示、run 202 且 blocked、无小队/租约、chat 内明确治理提示文案(页面用「请编制用户初始需求收集表」命中任务 API)
|
||||
- [x] `POST /projects` 带 `initial_workflow_key`:不再置 active,工作流目录仍自动挂载
|
||||
- [x] `go vet ./...`、`go test -short ./...`、`cd web && npm test && npm run build` 全绿
|
||||
- [x] 异态审计报告与测试报告归档并回链
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Research(评审与决策记录): [2026-09-14-mvp-governance-rules-review.md](../../ops/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 已合入本地 `dev@19f6df5`;本任务 worktree 已从该 `dev` 创建,mutex `workflow` 进入 `in_progress`。
|
||||
- G4 只读复测:141 active / 209 planning;**83** 个 planning 带非空 `active_workflow_key`,全部为 `PROJ_MGR_*`/`TEST_PROJ_*` 夹具。见 [audit](../../audit/2026-09-14-planning-with-workflow-key-anomaly.md)。
|
||||
- G5 验收:[2026-09-14-governance-action-level-authz-test-report.md](../../test-reports/2026-09-14-governance-action-level-authz-test-report.md)。
|
||||
@@ -0,0 +1,55 @@
|
||||
---
|
||||
title: "模块解耦架构与重构计划修订"
|
||||
status: done
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-14
|
||||
owner: Codex
|
||||
branch: feature/module-decoupling-remediation
|
||||
worktree: .worktrees/feature/module-decoupling-remediation
|
||||
mutex: architecture-docs
|
||||
---
|
||||
|
||||
# 模块解耦架构与重构计划修订
|
||||
|
||||
## 目标
|
||||
|
||||
把模块解耦方案修订为可以分段实施、验证和回滚的架构与重构计划,补齐事务、并发互斥、授权、可靠事件、FAV、数据迁移和真实页面验收。
|
||||
|
||||
## 范围
|
||||
|
||||
- 修订模块化单体架构设计与 ADR。
|
||||
- 新增详细整改与重构计划。
|
||||
- 建立首个文档可靠性纵向试点及后续里程碑任务。
|
||||
- 更新 CURRENT、FEATURE-MATRIX 和相关索引。
|
||||
|
||||
## 非目标
|
||||
|
||||
- 本任务不修改业务代码、数据库迁移或部署配置。
|
||||
- 本任务不合并 `feature/final-artifact-vault`,只定义其集成依赖和边界。
|
||||
- 本任务不执行共享容器验证,也不占用集成槽位。
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 对照当前源码、已接受 ADR、FAV 分支和外部权威资料复核原方案。
|
||||
2. [x] 修订架构设计与 ADR。
|
||||
3. [x] 编写详细整改计划、里程碑任务和验收清单。
|
||||
4. [x] 更新协作 SSOT 与索引并完成文档一致性检查。
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 计划明确事务所有权、锁顺序、事件投递语义、授权主体和恢复边界。
|
||||
- [x] 首个独立交付边界直接覆盖受控文档刷新、重启、投影缺失和授权负例。
|
||||
- [x] 每个后续里程碑有依赖、文件范围、并发风险、测试矩阵、停走门和回滚边界。
|
||||
- [x] FAV、迁移语料库和完整备份的职责不重叠,工作区不再承担最终成果事实源。
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Checklist: [../../ops/checklists/2026-09-14-module-decoupling-refactor-acceptance.md](../../ops/checklists/2026-09-14-module-decoupling-refactor-acceptance.md)
|
||||
- Handoff: 不需要;实现阶段使用两个 planned short-term 接续
|
||||
- Test report: 本任务仅产出计划,不生成业务验收报告
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
- 原方案位于主工作区未跟踪文件;本任务在独立 worktree 重建并修订,未覆盖原工作区。
|
||||
- `feature/final-artifact-vault` 已有实现与测试证据,但尚未合入本任务基线,实施前必须重新审计分支差异。
|
||||
- 文档校验:本地相对链接、R/KTD/U ID 唯一性、Mermaid fence 和 `git diff --check` 均通过。
|
||||
@@ -0,0 +1,71 @@
|
||||
---
|
||||
title: "workflow-plan 409 冻结态守卫 + 文档职责可选治理"
|
||||
status: done
|
||||
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 边界。
|
||||
2b. [x] 用户批准最终方案,开工登记(Wave 0)
|
||||
3. [x] Wave 1:typed API error + frozen 独立只读视图 + sticky/可访问错误 + 两标签竞态恢复。
|
||||
4. [x] Wave 2:DutyMode、强制/可选任务策略、partial/成员/零治理校验、服务端规范化。
|
||||
5. [x] Wave 3:门禁、readiness、阶段/文档访问、运行时和预览统计统一。
|
||||
6. [x] Wave 4:前端逐文档“纳入人工审批”开关及 full/none/partial 交互测试。
|
||||
7. [x] Wave 5:合 dev、rebuild、真实浏览器设置页矩阵;项目 143 只读回归;归档 test report。真实 PI 生成/审批长链路未跑,见报告。
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] active 项目设置无编辑控件,页面显示冻结原因、工作流/阶段/职责快照和受控终止影响入口。
|
||||
- [x] 允许裁剪的非必需文档 full/none 均合法;partial 精确拒绝。
|
||||
- [x] 必需/阻断/不可裁剪文档全空被服务端拒绝(单测 + 定义优先)。
|
||||
- [x] 保存和激活均拒绝非 active project member;预览后成员退出也 fail closed(单测)。
|
||||
- [x] 所有文档 none 时可走预览拒绝「至少一份纳入人工审批」(页面 C)。
|
||||
- [ ] none 文档仍生成和入账本、项目成员只读可见、创建者可生成/编辑,但无 review/approve 且不阻塞阶段(**本轮未跑真实 PI,单测已覆盖门禁/权限**)。
|
||||
- [x] disabled/none 的冻结快照、plan hash 和 assignment rows 不残留旧职责(Wave 3 单测)。
|
||||
- [x] 两标签陈旧保存的 409 在当前视口可见、草稿保留并转 frozen。
|
||||
- [x] 设置页真实 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: [2026-09-14-workflow-plan-409-frozen-and-optional-duties-test-report.md](../../test-reports/2026-09-14-workflow-plan-409-frozen-and-optional-duties-test-report.md)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
- dev 项目 143:`lifecycle_status=active`、`active_workflow_key=main`、实例 89 active;409 与三名职责人选择内容无关。
|
||||
- 当前 `parseError` 已读取后端 message;前端改造重点是 typed error、冻结态切换和视口内呈现。
|
||||
- 当前职责校验只检查正数/互异,数据库只外键到 users;项目成员有效性必须补服务端校验。
|
||||
- 当前终止实现会取消运行任务、关闭实例并退回 planning;关闭实例访问 fail closed,因此项目 143 不能作为终止测试对象。
|
||||
- 方案已迁移至基于最新 dev 的 `fix/workflow-plan-409-frozen-and-optional-duties` 独立 worktree;用户已批准实施。
|
||||
@@ -0,0 +1,63 @@
|
||||
---
|
||||
title: "M5/M6 组合根与传输门禁 U11–U12"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
owner: Cursor
|
||||
branch: feature/app-composition-u11-u12
|
||||
worktree: "-"
|
||||
mutex: app
|
||||
---
|
||||
|
||||
# M5/M6 组合根与传输门禁 U11–U12
|
||||
|
||||
## 目标
|
||||
|
||||
按整改计划四个子切片完成组合根、文档通知闭包迁出、stageflow 用例、UserProjectContext CAS;再收口 SSE 编码与已清零规则的 arch-check block。用户已明确授权继续 U11/U12(推翻 U10 报告的停止扩面)。
|
||||
|
||||
## 范围
|
||||
|
||||
- U11a:`internal/app` 唯一 composition root;幂等 Start/Stop
|
||||
- U11b:文档 `OnOutbox` 通知迁到 `internal/app/docnotify`
|
||||
- U11c:`internal/app/stageflow` 拥有 ExecuteTask / ExecuteStage
|
||||
- U11d:`ContextUpdate` 版本 CAS,禁止跨模块字段级直改
|
||||
- U12:SSE 中性 frame 编码;`import`/`event` 转 block;不改错误信封与 PI Runner 协议
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不碰 `intent` 包行为(编码阶段 mutex 仍由 Codex 占用;合入后浏览器门另开 handoff)
|
||||
- 不整支 merge `feature/final-artifact-vault`;不启用 `FAV_DEGRADED_READ`
|
||||
- 不终止或改写项目 143
|
||||
- 不删除未到期的 sql_write/path 例外(U3/U5 残留)
|
||||
- 不在 worktree 内 `env-service`
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 认领 CURRENT + 本任务
|
||||
2. [x] U11a composition root
|
||||
3. [x] U11b docnotify
|
||||
4. [x] U11c stageflow
|
||||
5. [x] U11d ContextUpdate
|
||||
6. [x] U12 SSE + arch-check block_kinds
|
||||
7. [x] 短测 / 目标包 race / 报告
|
||||
8. [x] 占槽 `--no-ff` 合入 `dev` + 主仓 `dev rebuild`
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 重复 Start 不重复注册 subscriber;Stop 后再 Start worker 仍在
|
||||
- [x] server 生产代码不再赋值 `OnOutbox`
|
||||
- [x] HTTP 与 CLI 走同一 stageflow 用例
|
||||
- [x] ContextUpdate 并发 stale version 不丢更新赢家
|
||||
- [x] `arch-check --mode block` 对已清零的 import/event 通过
|
||||
- [x] 测试报告回链 U11/U12
|
||||
- [x] 合入后 `/health` `/ready` schema 38、`pi-agent`、新镜像 digest
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Checklist: [../../ops/checklists/2026-09-14-module-decoupling-refactor-acceptance.md](../../ops/checklists/2026-09-14-module-decoupling-refactor-acceptance.md)
|
||||
- Plan: [../../remediation/2026-09-14-module-decoupling-refactor-plan.md](../../remediation/2026-09-14-module-decoupling-refactor-plan.md)
|
||||
- Test report: [../../test-reports/2026-09-15-app-composition-u11-u12-test-report.md](../../test-reports/2026-09-15-app-composition-u11-u12-test-report.md)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
用户口头授权:「继续解耦到 U11、U12」。合入 `dev@bf59cce`。rebuild 镜像 `sha256:a8e3e940f01111c4298c67947ae9f4cd6105f13cf58134672f4a87daa19e27ab`。health/ready:`.doc/test-reports/assets/2026-09-15-app-composition-u11-u12/rebuild-health-ready.txt`。
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
title: "D4 bizdev locator 最终移除"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
owner: Cursor
|
||||
branch: fix/bizdev-locator-removal
|
||||
worktree: "-"
|
||||
mutex: bizdev
|
||||
---
|
||||
|
||||
# D4 bizdev locator 最终移除
|
||||
|
||||
## 目标
|
||||
|
||||
删除 bizdev 上 8 个 locator getter;组合根一次性 Snapshot 后由 Runtime/Server 持有端口。
|
||||
|
||||
## 范围
|
||||
|
||||
- `Pool` `DocGov` `DocRevision` `ContextManager` `CAS` `ProjectWorkflow` `FreeformDoc` `KB`
|
||||
- Runtime / Server 字段
|
||||
- archtest 禁止把 getter 加回去
|
||||
- 调用方迁移
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不删 SchemaVersion / DatabaseReady
|
||||
- 不切事件 live
|
||||
- 不实现 Track P
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] Snapshot + Runtime 端口
|
||||
2. [x] 迁移 server/cmd/tests
|
||||
3. [x] 同批删除 8 getter
|
||||
4. [x] 报告合入
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 生产无 8 个 getter
|
||||
- [x] [S1 报告](../../test-reports/2026-09-15-bizdev-locator-removal-test-report.md)
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Phase 2 D4
|
||||
@@ -0,0 +1,39 @@
|
||||
---
|
||||
title: "D7b chat 编排剩余批次"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
owner: Cursor
|
||||
branch: fix/chatflow-orchestration-boundary
|
||||
worktree: "-"
|
||||
mutex: chat
|
||||
---
|
||||
|
||||
# D7b chat 编排剩余批次
|
||||
|
||||
## 目标
|
||||
|
||||
`internal/chat` 生产代码不再 import bizdev;任务请求走 stageflow 类型别名。
|
||||
|
||||
## 范围
|
||||
|
||||
- action_executor 去掉 Bizdev 字段
|
||||
- 收紧 chat import allowlist
|
||||
- 表征测试保留
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不搬空测试 import
|
||||
- 不把 taskrun 签名从 bizdev 别名拷成独立结构
|
||||
- 不切事件 live
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] action_executor 改 stageflow 类型
|
||||
2. [x] 收紧 yaml
|
||||
3. [x] 报告合入
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] chat 生产无 bizdev import
|
||||
- [x] [S4b 报告](../../test-reports/2026-09-15-chatflow-orchestration-boundary-test-report.md)
|
||||
@@ -0,0 +1,59 @@
|
||||
---
|
||||
title: "U10 chatlog/contextasm 原地端口化"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
owner: Cursor
|
||||
branch: feature/chatlog-contextasm-u10
|
||||
worktree: "-"
|
||||
mutex: chat
|
||||
---
|
||||
|
||||
# U10 chatlog/contextasm 原地端口化
|
||||
|
||||
## 目标
|
||||
|
||||
在不物理拆包的前提下,为对话读取与 prompt 装配建立带 Principal 的消费者端口,使正文、分类、计数、导出、摘要和恢复使用同一授权可见集合。
|
||||
|
||||
## 范围
|
||||
|
||||
- `internal/app/chatflow` ChatLog / ContextAssembler 端口
|
||||
- ctxmgr 表所有权不变;adapter 内做可见性过滤
|
||||
- server 历史读取 handler 改走 ChatLog;忽略 query/body 中的 user_id 身份
|
||||
- 会话 restore / 记忆召回只注入允许集合
|
||||
- 不碰 `intent` mutex,不物理搬到 `chatlog`/`contextasm` 包
|
||||
|
||||
## 非目标
|
||||
|
||||
- U11–U12
|
||||
- 整支 merge `feature/final-artifact-vault`
|
||||
- 启用 `FAV_DEGRADED_READ`
|
||||
- 纯搬包
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 核实 `chat` mutex:`fix/chat-history-refresh` 已是 `dev` 祖先;剩余真实 PI 刷新与 U10 同批收口
|
||||
2. [x] 从最新 `dev` 开 `feature/chatlog-contextasm-u10` 并登记 CURRENT
|
||||
3. [x] 定义 chatflow 端口与 ctxmgr adapter
|
||||
4. [x] 迁移 window/day/stats/search/unread/export/digest/history/restore/memory
|
||||
5. [x] 合同测试:同集计数、非 owner 403、restore/digest 不放大不可见消息
|
||||
6. [x] 验收报告;最后一句 **停止扩面**
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 刷新前后同一授权集合的正文与分类计数一致(adapter 合同测试)
|
||||
- [x] 跨用户负例 fail closed(guest 非 owner)
|
||||
- [x] context assembly / digest 只使用允许集合
|
||||
- [x] 真实 PI 闲聊刷新 E2E 证据(与对话刷新活验同批;编制任务链 save 400 未纳入停走)
|
||||
- [x] 未物理拆包;DTO 转换为 0,拆包收益不成立
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Checklist: [../checklists/2026-09-14-module-decoupling-refactor-acceptance.md](../checklists/2026-09-14-module-decoupling-refactor-acceptance.md)
|
||||
- Plan: [../../remediation/2026-09-14-module-decoupling-refactor-plan.md](../../remediation/2026-09-14-module-decoupling-refactor-plan.md)
|
||||
- Chat refresh: [../../test-reports/2026-09-13-chat-history-refresh-test-report.md](../../test-reports/2026-09-13-chat-history-refresh-test-report.md)
|
||||
- Test report: [../../test-reports/2026-09-15-chatlog-contextasm-u10-test-report.md](../../test-reports/2026-09-15-chatlog-contextasm-u10-test-report.md)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
U9 最后一句 **继续 U10** 只批准进入 M4。禁止 U11–U12。`intent` 认领仍 `in_progress`,本单元不改意图分类。活验项目 6252 / `sess-p6252-u10`;产物 `.doc/test-reports/assets/2026-09-15-chat-history-refresh-live/live.json`。未占槽 rebuild。
|
||||
@@ -0,0 +1,59 @@
|
||||
---
|
||||
title: "M3 U9 存量回填、migration corpus 与数据生命周期"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
owner: Cursor
|
||||
branch: feature/dataset-lifecycle-u9
|
||||
worktree: "-"
|
||||
mutex: dataset
|
||||
---
|
||||
|
||||
# M3 U9 存量回填、migration corpus 与数据生命周期
|
||||
|
||||
## 目标
|
||||
|
||||
只保留可解释的演示/回归数据,并持续验证旧数据迁移、重载和受控恢复。backfill 可暂停续跑,异常进 quarantine;八条轨道可重复;销毁默认 fail closed。
|
||||
|
||||
## 范围
|
||||
|
||||
- dataset registry(pinned / demo / regression / migration_baseline / ephemeral / quarantine)
|
||||
- checkpoint 分批 backfill:只枚举 snapshot、approved/commit event、completed chat turn
|
||||
- SKIP LOCKED 多 worker;禁止扫描 workspace
|
||||
- 销毁门禁:FAV coverage + 完整备份 restore + corpus + 精确 manifest + 双人批准 + quarantine 观察窗
|
||||
- restore 拒绝共享 env DSN;只允许 scratch
|
||||
- 八轨:clean / oldest-supported / previous / hazard / import / reload / rollback / artifact recovery
|
||||
|
||||
## 非目标
|
||||
|
||||
- U10–U12;不碰 `chat` / `intent` mutex
|
||||
- 不整支 merge `feature/final-artifact-vault`;不启用 `FAV_DEGRADED_READ`
|
||||
- 不修改历史 Goose;不销毁 `agent_system_dev/test/main`
|
||||
- 不终止或改写项目 143;worktree 内禁止 `env-service`
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] CURRENT 认领 `mutex=dataset`;从 `dev` 开 `feature/dataset-lifecycle-u9`
|
||||
2. [x] Goose 00038 + `module-boundaries.yaml`
|
||||
3. [x] `internal/artifactvault/backfill.go` + `internal/dataset` + `cmd/dataset`
|
||||
4. [x] 硬化 `scripts/restore-system-db-drill.sh`
|
||||
5. [x] 隔离库 + 八轨 + 目标包 `-race` + 占槽 rebuild
|
||||
6. [x] 验收报告;最后一句 **继续 U10**
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] backfill 中断、重复、并发新终态时分母/分子可复算且不重复 artifact
|
||||
- [x] legacy-v0 / 旧 schema / 高 ID / projection fork / 缺 snapshot → quarantine 或升级
|
||||
- [x] restore 拒绝共享 DSN、错误 storage identity、篡改 manifest、缺权限
|
||||
- [x] coverage / backup / corpus 任一失败阻止 destroy
|
||||
- [x] 批准 dataset 导入后关系、SHA、sequence 可复算
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Checklist: `.doc/ops/checklists/2026-09-14-module-decoupling-refactor-acceptance.md`
|
||||
- Plan: `.doc/remediation/2026-09-14-module-decoupling-refactor-plan.md` U9
|
||||
- Test report: `.doc/test-reports/2026-09-15-dataset-lifecycle-u9-test-report.md`
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
见验收报告。Goose 00038。dev schema 38。
|
||||
@@ -0,0 +1,46 @@
|
||||
---
|
||||
title: "D6 doccontent canonical 边界"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
owner: Cursor
|
||||
branch: fix/doccontent-canonical-boundary
|
||||
worktree: "-"
|
||||
mutex: docgov
|
||||
---
|
||||
|
||||
# D6 doccontent canonical 边界
|
||||
|
||||
## 目标
|
||||
|
||||
Markdown canonicalization 与 SHA 抽到 `internal/doccontent`;生产 `docgov` 不再 import `docrevision`。
|
||||
|
||||
## 范围
|
||||
|
||||
- `internal/doccontent`
|
||||
- `docgov/lease.go` 改走 doccontent
|
||||
- `docrevision` 薄封装保持旧调用方
|
||||
- golden + wrapper 对账
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不改 hash 语义
|
||||
- 不碰项目 143 数据
|
||||
- 不删 `docrevision.CanonicalizeMarkdown` 导出(兼容)
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 分支与 CURRENT
|
||||
2. [x] 提取模块与切断 docgov→docrevision
|
||||
3. [x] golden / arch-check
|
||||
4. [x] 报告并合入
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 生产 docgov 不 import docrevision
|
||||
- [x] project143 hard-break golden 仍过
|
||||
- [x] [S3 报告](../../test-reports/2026-09-15-doccontent-canonical-boundary-test-report.md)
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Phase 2: [../../remediation/2026-09-15-module-decoupling-ipc-phase2-remediation-plan.md](../../remediation/2026-09-15-module-decoupling-ipc-phase2-remediation-plan.md)
|
||||
@@ -0,0 +1,53 @@
|
||||
---
|
||||
title: "Track E 持久事件交付"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
owner: Cursor
|
||||
branch: fix/event-e2-hook-guard
|
||||
worktree: "-"
|
||||
mutex: events
|
||||
---
|
||||
|
||||
# Track E 持久事件交付
|
||||
|
||||
## 目标
|
||||
|
||||
按 E0A→E0B→E1A→E1B→E1C 完成 notify、workflow advance、projection 的 PG 持久交付,并用授权页面刷新/重启恢复证据关闭 `DOC-RELIABILITY-PILOT` 的事件部分。
|
||||
|
||||
## 范围
|
||||
|
||||
- E0A:生产入口/UoW、event contract、runtime registry、历史数据与 sequence 门。
|
||||
- E0B:PG dispatcher、attempt audit、独立进程、并发与故障注入。
|
||||
- E1A/B/C:三个消费者独立 shadow、switch、rollback 和真实恢复验收。
|
||||
|
||||
## 非目标
|
||||
|
||||
- FAV consumer 激活、bizdev/chat/intent 结构重构、HTTP 错误信封、PI typed result。
|
||||
- 删除或覆盖历史事件;在 E0A 通过前启动 dispatcher。
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] E0A 单独建 short-term/分支,dispatcher 保持 off。
|
||||
2. [x] E0A 报告通过后再认领 E0B。
|
||||
3. [x] 依次交付 E1A notify、E1B workflow advance、E1C projection;每步独立 go/no-go。
|
||||
4. [x] E2 兼容守卫:live 时闭包停写;hook API 待 live 窗口后删除。
|
||||
5. [x] 同步 test report、CURRENT、FEATURE-MATRIX、gap-matrix、[复盘](../research/2026-09-15-track-e-retrospective.md)。
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [ ] 满足 [Phase 2 Track E Definition of Done](../../remediation/2026-09-15-module-decoupling-ipc-phase2-remediation-plan.md#track-e-definition-of-done)(共享 live 与删除 hook API 仍开放)。
|
||||
- [x] 每个波次拥有独立 owner、mutex、分支、报告和回滚证据。
|
||||
- [x] 未把计划、MemoryBus、stub 或日志冒充生产 PG/browser/restart 验收。
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Checklist: 按每个波次建立
|
||||
- Audit: [Phase 2 方案审阅](../../audit/2026-09-15-module-decoupling-phase2-plan-review.md)
|
||||
- Remediation: [Phase 2 修订计划](../../remediation/2026-09-15-module-decoupling-ipc-phase2-remediation-plan.md)
|
||||
- Test report: [E2](../../test-reports/2026-09-15-event-e2-hook-guard-test-report.md)
|
||||
- 复盘: [./research/2026-09-15-track-e-retrospective.md](../research/2026-09-15-track-e-retrospective.md)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
本条只建立执行入口,不代表已批准 E0A 或已认领 mutex。实施前必须按 CURRENT 检查冲突并从当时最新 dev 建分支。
|
||||
@@ -0,0 +1,49 @@
|
||||
---
|
||||
title: "E0A 事件生产、契约与历史数据门"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
owner: Cursor
|
||||
branch: fix/event-production-scope-contract
|
||||
worktree: "-"
|
||||
mutex: events
|
||||
---
|
||||
|
||||
# E0A 事件生产、契约与历史数据门
|
||||
|
||||
## 目标
|
||||
|
||||
组合根注入唯一 `docflow.Commands`;candidate-ready、downstream-impact、approved 三条链在同一 UoW 写 envelope/delivery;缺 env/project fail closed;FAV 不写入;allowlist 与 runtime registry parity;历史 inventory 分类且不删数据;dispatcher 保持 off。
|
||||
|
||||
## 范围
|
||||
|
||||
- D3 生产入口与作用域
|
||||
- D10 既有 event allowlist 补全与 registry parity
|
||||
- D11 inventory、sequence ADR、repair/quarantine/expire、replay 骨架、service principal 表
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不实现/启动 PG dispatcher
|
||||
- 不激活 FAV,不写 staging/artifact/publication
|
||||
- 不删除历史事件
|
||||
- 不开始 Track S/P
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 从最新 `dev` 开 `fix/event-production-scope-contract` 并登记 CURRENT
|
||||
2. [x] 唯一 Commands、三条链同 UoW、FAV 隔离
|
||||
3. [x] allowlist + registry parity + 动态 FAV 注册失败
|
||||
4. [x] inventory/repair/replay/principal additive schema 与用例
|
||||
5. [x] 连续性模型 ADR;gap blocking 关闭
|
||||
6. [x] 隔离库 PG 证据与 test-report
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 见 [E0A 测试报告](../../test-reports/2026-09-15-event-e0a-production-scope-contract-test-report.md)
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Remediation: [../../remediation/2026-09-15-module-decoupling-ipc-phase2-remediation-plan.md](../../remediation/2026-09-15-module-decoupling-ipc-phase2-remediation-plan.md)
|
||||
- Track E: [./2026-09-15-durable-event-track-e.md](./2026-09-15-durable-event-track-e.md)
|
||||
- Report: [../../test-reports/2026-09-15-event-e0a-production-scope-contract-test-report.md](../../test-reports/2026-09-15-event-e0a-production-scope-contract-test-report.md)
|
||||
- ADR: [../../adr/2026-09-15-event-consumer-checkpoint.md](../../adr/2026-09-15-event-consumer-checkpoint.md)
|
||||
@@ -0,0 +1,43 @@
|
||||
---
|
||||
title: "E0B PG dispatcher 基座"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
owner: Cursor
|
||||
branch: feature/events-dispatcher-pg
|
||||
worktree: "-"
|
||||
mutex: events
|
||||
---
|
||||
|
||||
# E0B PG dispatcher 基座
|
||||
|
||||
## 目标
|
||||
|
||||
原子 lease/attempt/heartbeat/fencing、独立 `cmd/events`、默认 mode=off、1/2/4 worker 与崩溃注入。
|
||||
|
||||
## 范围
|
||||
|
||||
- Goose 00040、ClaimLeases、cmd/events、compose events 服务
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不把任何 consumer 切 live
|
||||
- 不激活 FAV
|
||||
- 不删除历史
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 从 E0A 后 `dev` 开 `feature/events-dispatcher-pg`
|
||||
2. [x] additive schema + atomic claim
|
||||
3. [x] worker/heartbeat/fencing/shadow scan
|
||||
4. [x] cmd/events + compose
|
||||
5. [x] 隔离库 PG + race + 报告
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] [E0B 测试报告](../../test-reports/2026-09-15-event-e0b-dispatcher-pg-test-report.md)
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Track E: [./2026-09-15-durable-event-track-e.md](./2026-09-15-durable-event-track-e.md)
|
||||
- Report: [../../test-reports/2026-09-15-event-e0b-dispatcher-pg-test-report.md](../../test-reports/2026-09-15-event-e0b-dispatcher-pg-test-report.md)
|
||||
@@ -0,0 +1,48 @@
|
||||
---
|
||||
title: "E1A notify shadow 与切换"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
owner: Cursor
|
||||
branch: fix/event-notify-cutover
|
||||
worktree: "-"
|
||||
mutex: events
|
||||
---
|
||||
|
||||
# E1A notify shadow 与切换
|
||||
|
||||
## 目标
|
||||
|
||||
notify 消费者具备 shadow 覆盖门、live 唯一可见结果与显式 rollback;生产集群保持 off。
|
||||
|
||||
## 范围
|
||||
|
||||
- Goose 00041、`EmitVisibleDocumentEvent`、`docnotify.EventConsumer`、Handler 与 Ack 同事务
|
||||
- cmd/events 注册 notify(mode=off 时不 claim)
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不把共享环境 notify 切 live
|
||||
- 不删除 OnOutbox 闭包
|
||||
- 不激活 FAV / workflow advance / projection live
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 从 E0B 后 `dev` 开 `fix/event-notify-cutover`
|
||||
2. [x] additive `source_event_id` 与可见结果唯一索引
|
||||
3. [x] shadow dry-run + live 同事务 ack
|
||||
4. [x] fixture N=30、quarantine、correlation、rollback
|
||||
5. [x] 隔离库 PG + race + 报告
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] [E1A 测试报告](../../test-reports/2026-09-15-event-e1a-notify-cutover-test-report.md)
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Track E: [./2026-09-15-durable-event-track-e.md](./2026-09-15-durable-event-track-e.md)
|
||||
- Report: [../../test-reports/2026-09-15-event-e1a-notify-cutover-test-report.md](../../test-reports/2026-09-15-event-e1a-notify-cutover-test-report.md)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
隔离库 `agent_rel_e1a` 测完已 DROP。共享 `event_consumer_modes.notify=off`。
|
||||
@@ -0,0 +1,44 @@
|
||||
---
|
||||
title: "E1B workflow advance shadow 与切换"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
owner: Cursor
|
||||
branch: fix/event-workflow-advance
|
||||
worktree: "-"
|
||||
mutex: events
|
||||
---
|
||||
|
||||
# E1B workflow advance shadow 与切换
|
||||
|
||||
## 目标
|
||||
|
||||
workflow_advance 具备 shadow/live/rollback;并发或重放批准只产生一次阶段可推进可见结果。生产集群保持 off。
|
||||
|
||||
## 范围
|
||||
|
||||
- Goose 00042、`docadvance.EventConsumer`、`EmitVisibleStageReady`、MarkDocTaskApproved 走 fenced tx
|
||||
- cmd/events 注册 workflow_advance
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不把共享环境 workflow_advance 切 live
|
||||
- 不删除 AddOnApprovedHook
|
||||
- 不激活 FAV / projection live
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 从 E1A 后 `dev` 开 `fix/event-workflow-advance`
|
||||
2. [x] additive source_event_id on stage_advance_requests
|
||||
3. [x] consumer 重读文档并同事务 ack
|
||||
4. [x] 隔离库并发/重放/quarantine/rollback
|
||||
5. [x] 报告
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] [E1B 测试报告](../../test-reports/2026-09-15-event-e1b-workflow-advance-test-report.md)
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Track E: [./2026-09-15-durable-event-track-e.md](./2026-09-15-durable-event-track-e.md)
|
||||
- Report: [../../test-reports/2026-09-15-event-e1b-workflow-advance-test-report.md](../../test-reports/2026-09-15-event-e1b-workflow-advance-test-report.md)
|
||||
@@ -0,0 +1,41 @@
|
||||
---
|
||||
title: "E1C projection no-replace"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
owner: Cursor
|
||||
branch: fix/event-projection-cutover
|
||||
worktree: "-"
|
||||
mutex: events
|
||||
---
|
||||
|
||||
# E1C projection no-replace
|
||||
|
||||
## 目标
|
||||
|
||||
projection 消费者幂等只前进;共享集群保持 off。
|
||||
|
||||
## 范围
|
||||
|
||||
- Goose 00043、ProjectHeadNoReplace、docproject.EventConsumer
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不把共享 projection 切 live
|
||||
- 不激活 FAV
|
||||
- 不删除闭包
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 分支与 additive schema
|
||||
2. [x] no-replace SQL + consumer
|
||||
3. [x] 隔离库 + race + worker 重启
|
||||
4. [x] 报告
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] [E1C 测试报告](../../test-reports/2026-09-15-event-e1c-projection-test-report.md)
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Track E: [./2026-09-15-durable-event-track-e.md](./2026-09-15-durable-event-track-e.md)
|
||||
@@ -0,0 +1,48 @@
|
||||
---
|
||||
title: "E2 闭包 live 停写与 Track E 复盘"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
owner: Cursor
|
||||
branch: fix/event-e2-hook-guard
|
||||
worktree: "-"
|
||||
mutex: events
|
||||
---
|
||||
|
||||
# E2 闭包 live 停写与 Track E 复盘
|
||||
|
||||
## 目标
|
||||
|
||||
在 dispatcher 仍默认 off 时保留 `OnOutbox` / `AddOnApprovedHook` 接线,使对应消费者切 `live` 后闭包立即停写,避免双写;并写 Track E 复盘。不关闭 `DOC-RELIABILITY-PILOT`。
|
||||
|
||||
## 范围
|
||||
|
||||
- `events.WriterLive`
|
||||
- `docnotify.Subscriber.SkipWrite`
|
||||
- Runtime / 遗留 HTTP hook 在 `workflow_advance` live 时 no-op
|
||||
- 复盘与 E2 测试报告
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不删除 hook API(须等 live 发布窗口)
|
||||
- 不把共享 notify/advance/projection 切 live
|
||||
- 不激活 FAV
|
||||
- 不关闭 Track E 发布 blocker
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 从最新 `dev` 开 `fix/event-e2-hook-guard` 并登记 CURRENT
|
||||
2. [x] WriterLive + 闭包守卫 + 单测
|
||||
3. [x] 隔离库 mode 矩阵
|
||||
4. [x] 复盘与报告
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] live 时闭包不写;off/shadow 仍写
|
||||
- [x] 生产仍保留 Bind / AddOnApprovedHook(mode=off 必需)
|
||||
- [x] [E2 报告](../../test-reports/2026-09-15-event-e2-hook-guard-test-report.md)
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Track E: [./2026-09-15-durable-event-track-e.md](./2026-09-15-durable-event-track-e.md)
|
||||
- 复盘: [../research/2026-09-15-track-e-retrospective.md](../research/2026-09-15-track-e-retrospective.md)
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
title: "共享环境事件消费者 live 切换"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
owner: Cursor
|
||||
branch: feature/event-shared-live-cutover
|
||||
worktree: "-"
|
||||
mutex: events
|
||||
---
|
||||
|
||||
# 共享环境事件消费者 live 切换
|
||||
|
||||
## 目标
|
||||
|
||||
在共享 `agent-dev` 上按 notify → workflow_advance → projection 完成 shadow → drain → live → 回滚演练,再删除生产 hook 注册。
|
||||
|
||||
## 范围
|
||||
|
||||
- `scripts/event-consumer-mode.sh` + `cmd/eventmode`
|
||||
- 共享 `agent_system_dev` inventory / quarantine
|
||||
- 逐消费者 live 与授权页纵切(项目 6275;143 只读)
|
||||
|
||||
## 非目标
|
||||
|
||||
- FAV live
|
||||
- test/main 环境
|
||||
- 编辑 Phase 2 计划原文
|
||||
- Track P(独立波次)
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] L0 受控 SetMode 与 inventory
|
||||
2. [x] L1 notify
|
||||
3. [x] L2 workflow_advance
|
||||
4. [x] L3 projection + 授权页
|
||||
5. [x] L4 删除生产 hook 注册
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] fav / test / main 切模式失败
|
||||
- [x] 每消费者独立 live 报告
|
||||
- [x] 生产代码无 `OnOutbox =` / `AddOnApprovedHook(`
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Long-term: [.doc/archive/ops/2026-09-15-event-shared-live-cutover.md](../../archive/ops/2026-09-15-event-shared-live-cutover.md)
|
||||
- Notify: [.doc/test-reports/2026-09-15-event-notify-shared-live-test-report.md](../../test-reports/2026-09-15-event-notify-shared-live-test-report.md)
|
||||
- Advance: [.doc/test-reports/2026-09-15-event-workflow-advance-shared-live-test-report.md](../../test-reports/2026-09-15-event-workflow-advance-shared-live-test-report.md)
|
||||
- Projection: [.doc/test-reports/2026-09-15-event-projection-shared-live-test-report.md](../../test-reports/2026-09-15-event-projection-shared-live-test-report.md)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
已合入 `dev@39dc68d`。生产 hook 注册已删;方法本体保留一个窗口。
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
title: "共享环境事件消费者 live 切换"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
---
|
||||
|
||||
# 共享环境事件消费者 live 切换
|
||||
|
||||
## 动机
|
||||
|
||||
Track E 已在隔离库证明 notify / workflow_advance / projection 的 exactly-one visible outcome 与 E2 闭包守卫。共享集群仍为 `off`,HTTP 闭包仍是唯一真实写者。未 live 则不能删 hook API,也不能关闭 `DOC-RELIABILITY-PILOT`。
|
||||
|
||||
## 成功标准
|
||||
|
||||
- 按消费者独立:shadow coverage → drain → 原子 live;E2 守卫使对应闭包停写。
|
||||
- 授权页刷新/重启正文与 head digest 一致;未授权不泄露。
|
||||
- 回滚开关保留一个发布窗口后再删 `OnOutbox` / `AddOnApprovedHook`。
|
||||
- FAV 保持 disabled;项目 143 只读。
|
||||
|
||||
## 依赖
|
||||
|
||||
- E0A–E2 已合入;隔离库报告已归档。
|
||||
- 需要明确授权:动共享 `agent-dev` 消费者 mode。
|
||||
|
||||
## 暂不启动原因
|
||||
|
||||
已完成共享 live 与生产去注册。方法本体保留一个窗口。
|
||||
|
||||
## 相关链接
|
||||
|
||||
- [Track E 复盘](../research/2026-09-15-track-e-retrospective.md)
|
||||
- [E2 报告](../../test-reports/2026-09-15-event-e2-hook-guard-test-report.md)
|
||||
- [gap-matrix DOC-RELIABILITY-PILOT](../../remediation/gap-matrix.md)
|
||||
@@ -0,0 +1,39 @@
|
||||
---
|
||||
title: "D7a intent 与 bizdev 解绑"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
owner: Cursor
|
||||
branch: fix/intent-bizdev-boundary
|
||||
worktree: "-"
|
||||
mutex: intent
|
||||
---
|
||||
|
||||
# D7a intent 与 bizdev 解绑
|
||||
|
||||
## 目标
|
||||
|
||||
intent 只依赖成熟度词汇叶子包,不再 import bizdev。
|
||||
|
||||
## 范围
|
||||
|
||||
- `internal/maturity`
|
||||
- intent 生产与表征测试
|
||||
- bizdev 类型别名保持兼容
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不改识别规则
|
||||
- 不迁 coordinator / chatflow(D5/D7b)
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 叶子包与别名
|
||||
2. [x] intent 切断 bizdev
|
||||
3. [x] 表征测试与 arch-check
|
||||
4. [x] 报告
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] intent 生产 import 无 bizdev
|
||||
- [x] [S4a 报告](../../test-reports/2026-09-15-intent-bizdev-boundary-test-report.md)
|
||||
@@ -0,0 +1,50 @@
|
||||
---
|
||||
title: "清点旁支并收口已合入本地分支"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
owner: Cursor
|
||||
branch: chore/leftover-branch-cleanup
|
||||
worktree: "-"
|
||||
mutex: ops
|
||||
---
|
||||
|
||||
# 清点旁支并收口已合入本地分支
|
||||
|
||||
## 目标
|
||||
|
||||
删除 tip 已是 `dev` 祖先的本地旁支与对应 worktree;不整支合入会回归或触红线的 5 条未合并分支;主仓跑一次 short 冒烟。
|
||||
|
||||
## 范围
|
||||
|
||||
- 拆 7 个已合入 worktree
|
||||
- `git branch -d` 已 `--merged` 旁支
|
||||
- CURRENT 记录故意保留的 FAV / herdr-removal / diagnosis / data-root / `dev-old-linear`
|
||||
- vet / short / arch-check / health+ready
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不整支 merge `feature/final-artifact-vault`;不启用 `FAV_DEGRADED_READ`
|
||||
- 不合入 `feature/remove-herdr-agent-settings`(会回归 U12 arch-check、删 Herdr 脚本)
|
||||
- 不合入 `fix/project143-controlled-content-404-diagnosis`(会回退审计关闭结果)
|
||||
- 不合入 `fix/dev-runtime-data-root-guard`、`dev-old-linear`
|
||||
- 不 push;不删 `origin/*`;不从 worktree 起 docker;不碰项目 143
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 占 CURRENT 集成槽
|
||||
2. [x] 拆已合入 worktree
|
||||
3. [x] 删除已 merged 本地旁支
|
||||
4. [x] 冒烟并写报告
|
||||
5. [x] 槽位 idle + archive
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 已合入旁支 worktree 只剩 FAV 错名目录
|
||||
- [x] `--merged dev` 旁支已删(31 条)
|
||||
- [x] 5 条未合入分支仍在
|
||||
- [x] 测试报告 + health/ready schema 38
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Test report: [../../test-reports/2026-09-15-leftover-branch-cleanup-test-report.md](../../test-reports/2026-09-15-leftover-branch-cleanup-test-report.md)
|
||||
@@ -0,0 +1,57 @@
|
||||
---
|
||||
title: "审阅并修订模块解耦 Phase 2 方案"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
owner: Codex
|
||||
branch: docs/module-decoupling-ipc-assessment
|
||||
worktree: "-"
|
||||
mutex: architecture-docs
|
||||
---
|
||||
|
||||
# 审阅并修订模块解耦 Phase 2 方案
|
||||
|
||||
## 目标
|
||||
|
||||
以当前代码、migration、ADR 和 Phase 1 计划为证据,修正调研与 Phase 2 方案,并补齐高并发、互斥、权限、历史数据、灰度和回滚设计;不实施业务代码。
|
||||
|
||||
## 范围
|
||||
|
||||
- 复核调研报告与原 Phase 2 方案的事实、依赖和完成边界。
|
||||
- 将事件可靠性、结构解耦、HTTP/PI 协议拆成独立轨道。
|
||||
- 补充 PG 状态机、fencing、幂等、顺序、连接预算、权限、replay、脱敏、迁移和 browser/restart 验收。
|
||||
- 同步 audit、remediation、CURRENT、FEATURE-MATRIX 与 gap-matrix。
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不实现 dispatcher、consumer、migration 或协议代码。
|
||||
- 不合并、部署、重启容器、删除数据或审计/合入 FAV 分支。
|
||||
- 不把文档完成写成系统能力完成。
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 完成仓库启动链和上位 ADR/Phase 1 证据复核。
|
||||
2. [x] 完成一致性、可行性、范围、安全、产品与对抗视角审阅。
|
||||
3. [x] 修正调研报告中的 PG、依赖方向、allowlist 与进程边界事实。
|
||||
4. [x] 重写 Phase 2 为 Track E/S/P,补齐详细实施和停走门。
|
||||
5. [x] 同步索引与状态 SSOT。
|
||||
6. [x] 执行文档链接、diff、冲突标记和术语检查。
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 调研不再把 SELECT-only Claim、MemoryBus 测试或 allowlist 基线写成生产闭环。
|
||||
- [x] Track E 可独立关闭,FAV/D8/D9 不阻塞。
|
||||
- [x] 方案明确 at-least-once 与 exactly-one visible outcome、最终提交点 fencing、集群级切换和授权模型。
|
||||
- [x] 历史脏数据只分类/隔离/修复,不授权删除。
|
||||
- [x] 文档状态一致且没有实施或发布声明。
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: [方案审阅](../../audit/2026-09-15-module-decoupling-phase2-plan-review.md)
|
||||
- Remediation: [Phase 2 修订计划](../../remediation/2026-09-15-module-decoupling-ipc-phase2-remediation-plan.md)
|
||||
- Research: [IPC/RPC 现状评估](../../ops/research/2026-09-15-module-decoupling-ipc-assessment.md)
|
||||
- Test report: 不适用(文档审阅,无业务实现)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
本任务沿用用户已创建的 `docs/module-decoupling-ipc-assessment` 分支。该分支名早于当前 `feature/*|fix/*` 规则;未改写或重命名用户分支。起点提交为 `a3392e3` 与 `5cef856`,本轮未获授权 commit/push。
|
||||
@@ -0,0 +1,47 @@
|
||||
---
|
||||
title: "PI typed-result-v1 P1–P4"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
owner: Cursor
|
||||
branch: feature/pi-typed-result
|
||||
worktree: "-"
|
||||
mutex: pi-agent
|
||||
---
|
||||
|
||||
# PI typed-result-v1 P1–P4
|
||||
|
||||
## 目标
|
||||
|
||||
Runner additive 输出 `result_v1`;Go typed-first fail-closed;共享 dev 真实 PI 双轨对账;去掉 stderr/legacy 明文错误。
|
||||
|
||||
## 范围
|
||||
|
||||
- `configs/schemas/pi-run-result-v1.json`
|
||||
- `deploy/pi-agent/result-v1.mjs` + runner 接线
|
||||
- `internal/agent` parser / 负例 / `RUN_PI_E2E=1` 双轨
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不把 member 正文搬进 `result_v1`(仍走 `patches[]`)
|
||||
- 不改 HTTP 状态码;不启用 FAV;不写项目 143
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] Schema + Runner additive
|
||||
2. [x] Go typed-first + handshake
|
||||
3. [x] 真实 PI 双轨
|
||||
4. [x] 删 stderr/隐式 legacy;报告与合入
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] typed-present-invalid 永不 fallback
|
||||
- [x] handshake downgrade 负例 PASS
|
||||
- [x] `RUN_PI_E2E=1` 成功/失败/取消/超时对账
|
||||
- [x] test-report 归档
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Test report: `.doc/test-reports/2026-09-15-pi-typed-result-v1-test-report.md`
|
||||
- Remediation: `.doc/remediation/2026-09-15-pi-typed-result-v1-remediation.md`
|
||||
- P0: `.doc/ops/research/2026-09-15-pi-typed-result-p0-matrix.md`
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
title: "晋升 dev → test 并部署测试环境"
|
||||
status: in_progress
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
owner: Cursor
|
||||
branch: feature/promote-dev-to-test-2026-09-15
|
||||
worktree: "-"
|
||||
mutex: infra
|
||||
---
|
||||
|
||||
# 晋升 dev → test 并部署测试环境
|
||||
|
||||
## 目标
|
||||
|
||||
把已完成的 Phase 2 代码从本地 `dev` 合入 `test`,重建并冒烟测试环境,供人工实测。不实施多意图 HITL。
|
||||
|
||||
## 范围
|
||||
|
||||
- `test` 分支 `--no-ff` 合入当前 `dev`
|
||||
- `./scripts/env-service.sh test rebuild`
|
||||
- test 库 notify/workflow_advance/projection 切 live(L4 去 hook 后 off 会停写);FAV 保持 off
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不实施多意图 HITL U1+
|
||||
- 不合入 `main`、不启用 FAV
|
||||
- 不写项目 143
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 确认 Phase 2 已在本地 `dev`
|
||||
2. [ ] occupy 集成槽并合入 `test`
|
||||
3. [ ] rebuild 测试服务
|
||||
4. [ ] health/ready + schema 冒烟
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [ ] `:8081` health/ready PASS
|
||||
- [ ] events `:8089` health PASS
|
||||
- [ ] FAV 仍 off
|
||||
|
||||
## 相关链接
|
||||
|
||||
- CURRENT: `.doc/ops/CURRENT.md`
|
||||
@@ -0,0 +1,40 @@
|
||||
---
|
||||
title: "D5 stageflow 类型归属与 D7b chatflow 首批"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
owner: Cursor
|
||||
branch: fix/stageflow-type-ownership
|
||||
worktree: "-"
|
||||
mutex: stageflow
|
||||
---
|
||||
|
||||
# D5 stageflow 类型归属与 D7b chatflow 首批
|
||||
|
||||
## 目标
|
||||
|
||||
coordinator 生产代码不再 import bizdev;task/stage 请求走 stageflow 类型;chatflow assembler 改用 maturity。
|
||||
|
||||
## 范围
|
||||
|
||||
- stageflow 类型别名与状态常量
|
||||
- coordinator 构造改为 StageTaskRunner + ContextServices
|
||||
- chatflow 去掉 bizdev import
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不复制行为方法成 DTO(身份别名 + token golden)
|
||||
- 不删除 bizdev 八个 getter(D4)
|
||||
- 不搬空 chat 包
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 类型边界与 coordinator 解绑
|
||||
2. [x] chatflow assembler
|
||||
3. [x] 表征测试与 arch-check
|
||||
4. [x] 报告
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] coordinator 生产 import 无 bizdev
|
||||
- [x] [S2/S4b 报告](../../test-reports/2026-09-15-stageflow-type-ownership-test-report.md)
|
||||
@@ -0,0 +1,60 @@
|
||||
---
|
||||
title: "M3 U8 TaskRun 终态与 RunManifest"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
owner: Cursor
|
||||
branch: feature/taskrun-runmanifest
|
||||
worktree: "-"
|
||||
mutex: taskrun
|
||||
---
|
||||
|
||||
# M3 U8 TaskRun 终态与 RunManifest
|
||||
|
||||
## 目标
|
||||
|
||||
TaskRun 终态在同一 UoW 内 CAS 写入唯一合法状态,并持久化类型化 RunManifest;重复 finalize / cancel race / SSE 断线不得产生第二条助手消息或第二份 artifact;workspace 清理仅在 verified receipt 之后。
|
||||
|
||||
## 范围
|
||||
|
||||
- Goose 00037 `task_run_manifests` + `finalizing` 状态
|
||||
- `internal/taskrun` RunManifest 规范字节 / SHA / members
|
||||
- `taskrun.Commands.Finalize` 唯一 finalize 命令;server 变薄
|
||||
- `ctxmgr.FinalizeAssistantTaskMessage` 仅此写路径加入 UoW
|
||||
- workspace 清理门禁;`ReadArtifact` 替代 `Join(workDir, "output.md")`
|
||||
- BackendRef 服务端 policy;隔离库并发测试;占槽 rebuild;U8 报告
|
||||
|
||||
## 非目标
|
||||
|
||||
- U9 backfill / corpus / 八轨 / 销毁
|
||||
- M4–M6;整支 merge FAV;启用 `FAV_DEGRADED_READ`
|
||||
- 终止或改写项目 143
|
||||
- 动 `chat` / `intent` 刷新任务
|
||||
- worktree 内 `env-service`
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] CURRENT 认领 `mutex=taskrun`;从本地 `dev` 开 `feature/taskrun-runmanifest`
|
||||
2. [x] Goose 00037 Up+Down;`module-boundaries.yaml` 表属主
|
||||
3. [x] Finalize 同 UoW:CAS + 助手 turn + manifest + envelope/staging
|
||||
4. [x] 清理门禁与 server 去路径、BackendRef
|
||||
5. [x] 隔离库双 pool / race;占槽 rebuild;报告最后一句只能「继续 U9」或「停止扩面」
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 重复 finalize:同一 status、同一 manifest SHA、助手消息 1 条、envelope/staging 不加倍
|
||||
- [x] finalize ∥ cancel:恰好一个合法终态
|
||||
- [x] SSE `done` 不出现在 TX 失败路径;commit 前断线重试不第二 turn
|
||||
- [x] 无 verified receipt 则 cleanup FAIL;有 receipt 则可清 workspace 且 staging 仍能取出原 SHA
|
||||
- [x] 报告最后一句为「继续 U9」或「停止扩面」;U9 清单项保持未勾
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Checklist: [2026-09-14-module-decoupling-refactor-acceptance.md](../checklists/2026-09-14-module-decoupling-refactor-acceptance.md)
|
||||
- Remediation: [2026-09-14-module-decoupling-refactor-plan.md](../../remediation/2026-09-14-module-decoupling-refactor-plan.md)
|
||||
- 权威停走门: [2026-09-14-document-reliability-m2-test-report.md](../../test-reports/2026-09-14-document-reliability-m2-test-report.md)(继续 M3)
|
||||
- Test report: [2026-09-15-taskrun-runmanifest-u8-test-report.md](../../test-reports/2026-09-15-taskrun-runmanifest-u8-test-report.md)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
未签字前禁止 U9–U12。合入 + 容器测占集成槽,主仓 `./scripts/env-service.sh dev rebuild`。
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
title: "Track P 协议实施(信封与 typed-result)"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
---
|
||||
|
||||
# Track P 协议实施(信封与 typed-result)
|
||||
|
||||
## 动机
|
||||
|
||||
H0/P0 盘点后独立实施 HTTP 信封与 PI typed-result,不回退事件 live。
|
||||
|
||||
## 成功标准
|
||||
|
||||
已关闭:
|
||||
|
||||
- [HTTP 信封 H1–H3](../../test-reports/2026-09-15-http-error-envelope-h1-h3-test-report.md)
|
||||
- [PI typed-result P1–P4](../../test-reports/2026-09-15-pi-typed-result-v1-test-report.md)
|
||||
|
||||
## 依赖
|
||||
|
||||
mutex `server`/`web`/`pi-agent` 已释放。
|
||||
|
||||
## 暂不启动原因
|
||||
|
||||
已完成。
|
||||
|
||||
## 相关链接
|
||||
|
||||
- [Phase 2 计划](../../remediation/2026-09-15-module-decoupling-ipc-phase2-remediation-plan.md)
|
||||
+6
-6
@@ -1,9 +1,9 @@
|
||||
---
|
||||
title: "对话刷新恢复整改 Checklist"
|
||||
status: in_progress
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
related_task: "../short-term/2026-09-13-chat-history-refresh-remediation.md"
|
||||
updated: 2026-09-15
|
||||
related_task: "../2026-09-13-chat-history-refresh-remediation.md"
|
||||
---
|
||||
|
||||
# 对话刷新恢复整改 Checklist
|
||||
@@ -36,10 +36,10 @@ related_task: "../short-term/2026-09-13-chat-history-refresh-remediation.md"
|
||||
## Wave 5 — 验收
|
||||
|
||||
- [x] `go test -short ./...` — 证据:本机执行输出
|
||||
- [ ] 真实 PI 刷新 E2E(需 dev 容器 + pi-agent)— 证据:待 test-report 补录
|
||||
- [x] 真实 PI 刷新 E2E(需 dev 容器 + pi-agent)— 证据:`.doc/test-reports/assets/2026-09-15-chat-history-refresh-live/live.json`(项目 6252 闲聊刷新同集 + guest 403;编制任务链未通过)
|
||||
- [x] 测试报告归档 — 证据:`.doc/test-reports/2026-09-13-chat-history-refresh-test-report.md`
|
||||
|
||||
## 完成定义
|
||||
|
||||
- [ ] 全部勾选且有证据链接
|
||||
- [ ] gap-matrix `CHAT-HISTORY-REFRESH` → PASS
|
||||
- [x] 全部勾选且有证据链接
|
||||
- [x] gap-matrix `CHAT-HISTORY-REFRESH` → PASS
|
||||
@@ -0,0 +1,47 @@
|
||||
---
|
||||
title: "发布门禁闭环 → production_ready"
|
||||
status: done
|
||||
created: 2026-09-16
|
||||
updated: 2026-09-16
|
||||
owner: Cursor-Auto
|
||||
branch: docs/production-ready-flip
|
||||
worktree: "-"
|
||||
mutex: ci
|
||||
---
|
||||
|
||||
# 发布门禁闭环 → production_ready
|
||||
|
||||
## 目标
|
||||
|
||||
按 gap-matrix 发布门禁勾选 B1–B4,对齐环境 schema 后翻 `production_ready=yes`。
|
||||
|
||||
## 范围
|
||||
|
||||
- B1 CI TEST_DATABASE_URL + 治理 PG(已完成)
|
||||
- B2 真实 PI 三工作流 E2E(已完成)
|
||||
- B3 对话全链路恢复(已完成)
|
||||
- B4 版本冲突/终止 preview(已完成)
|
||||
- B5 SSOT 翻旗 + main schema 对齐(已完成)
|
||||
|
||||
## 非目标
|
||||
|
||||
- 多意图 U9–U12、软件项目自举、FAV、完整 PI change-report 叙事
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] B1 BUG-08
|
||||
2. [x] B2 PI E2E
|
||||
3. [x] B3 chat refresh + restart
|
||||
4. [x] B4 conflict + termination-preview + envelope unwrap
|
||||
5. [x] B5 merge/smoke、main rebuild 迁库、翻旗
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] gap 门禁四框可勾(含对话与前端)
|
||||
- [x] FEATURE-MATRIX / gap / CURRENT `production_ready: yes`
|
||||
- [x] main/dev/test health schema_version=47
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Test reports: `2026-09-16-ci-governance-pg-bug08`、`pi-three-workflow-e2e`、`chat-refresh-gate`、`frontend-gate-b4`
|
||||
- gap-matrix / FEATURE-MATRIX / CURRENT
|
||||
@@ -76,7 +76,7 @@ severity: high
|
||||
## 关联整改
|
||||
|
||||
- Remediation: [../remediation/2026-09-13-chat-history-refresh-remediation.md](../remediation/2026-09-13-chat-history-refresh-remediation.md)
|
||||
- Short-term: [../ops/short-term/2026-09-13-chat-history-refresh-remediation.md](../ops/short-term/2026-09-13-chat-history-refresh-remediation.md)
|
||||
- Short-term: [../archive/ops/2026-09-13-chat-history-refresh-remediation.md](../archive/ops/2026-09-13-chat-history-refresh-remediation.md)
|
||||
- Gap matrix: [../remediation/gap-matrix.md](../remediation/gap-matrix.md)
|
||||
|
||||
## 证据
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
---
|
||||
title: "arch-check U1 可重放基线"
|
||||
status: done
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-14
|
||||
severity: medium
|
||||
---
|
||||
|
||||
# arch-check U1 可重放基线
|
||||
|
||||
## 现象
|
||||
|
||||
Wave 0 的全仓 grep 会把 Goose、`*_test.go` 和路径字面量一视同仁,无法作为生产写者门禁。U1 用 `go list` + AST/正则拆成四类规则,并给每条既有债写明 owner、原因、截止里程碑和到期日。
|
||||
|
||||
## 根因分析
|
||||
|
||||
- `document_records` 的生产写者不止 `docgov`:`docrevision.projectRootPointersTX` 与 `docduty` 职责槽位仍直接 `UPDATE`。
|
||||
- `output.md` / `data/dev` / `workspaces/` 仍被 agent、bizdev、coordinator、docgov、docrevision、server、storage 用 `filepath.Join`、字符串字面量或间接常量构造。
|
||||
- Goose 与测试夹具大量出现同样表名,不能算生产写者债。
|
||||
|
||||
## 严重度
|
||||
|
||||
`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)
|
||||
- 边界: [../system-design/module-boundaries.yaml](../system-design/module-boundaries.yaml)
|
||||
- 任务: [../ops/short-term/2026-09-14-document-reliability-pilot.md](../ops/short-term/2026-09-14-document-reliability-pilot.md)
|
||||
|
||||
## 证据
|
||||
|
||||
命令(2026-09-14,`refactor/document-reliability-pilot` worktree):
|
||||
|
||||
```
|
||||
./scripts/arch-check.sh --mode warn
|
||||
go test ./internal/archtest -count=1
|
||||
```
|
||||
|
||||
可重放计数(只含生产 Go;Goose/`*_test.go` 不计):
|
||||
|
||||
| 规则 | 计数 | 处理 |
|
||||
|------|------|------|
|
||||
| import | 0 | 相对 2026-09-14 production `go list` allowlist,无新边 |
|
||||
| sql_write | 5 | 例外,U3/U8 到期 |
|
||||
| path | 17 | 例外,U4/U5/U8 到期 |
|
||||
| event | 0 | `OnOutbox` 生产者属主为 docrevision,server/notification 为消费者 |
|
||||
|
||||
验证:
|
||||
|
||||
- `deploy/postgres/goose` 与 `*_test.go` 出现 `document_records` 不报生产写者违规。
|
||||
- 迷你仓 `internal/server/rogue_write.go` 新增 `UPDATE document_records` 时 `go test ./internal/archtest` 失败并指出文件。
|
||||
- `filepath.Join`、字符串拼接、间接常量构造 `output.md` 均可检出。
|
||||
- 无到期日例外、过期例外立即 block。
|
||||
- `baseline_counts` 锁定现有计数,只能下降。
|
||||
|
||||
`--mode block` 在例外清零前会失败,不得挂进集成冒烟。
|
||||
|
||||
## 开放问题
|
||||
|
||||
- U3 收口 `document_records` / `freeform_documents` 跨属主写。
|
||||
- U4/U5 收口 handler 与投影路径构造。
|
||||
- U8 收口 `task_runs` 终止写与 finalize `output.md`。
|
||||
@@ -0,0 +1,98 @@
|
||||
---
|
||||
title: "模块解耦方案复核"
|
||||
status: done
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-14
|
||||
scope: architecture, transactions, concurrency, authorization, events, artifact recovery
|
||||
---
|
||||
|
||||
# 模块解耦方案复核
|
||||
|
||||
## 结论
|
||||
|
||||
模块化单体、单一写者、瘦传输层和应用编排层的方向成立,但原方案不能直接批准 Wave 1–6。
|
||||
原方案把事务、事件、工作区和最终成果四条边界拆开设计,可能在包依赖减少后产生新的数据不一致、跨租户授权旁路和不可恢复投影。
|
||||
整改应先打通一条真实文档纵向链路,再按证据决定是否扩展到 chat、squad、SSE 和 PI Runner。
|
||||
|
||||
## 已确认问题
|
||||
|
||||
### A1. 单一写者拆分会破坏跨表原子性
|
||||
|
||||
`internal/docrevision/pg_mutate.go` 当前在一个事务中写版本账本并投影 `document_records` 根指针。
|
||||
原方案要求 docrevision 改调 docgov/freedoc 普通端口,却没有定义跨属主事务或命令所有权。
|
||||
如果各端口各自提交,会出现版本账本、正文 head、治理状态和 outbox 部分成功。
|
||||
|
||||
### A2. 现有 outbox 不是可泛化的可靠事件总线
|
||||
|
||||
`internal/docrevision/service.go` 在版本事务完成后调用 `OnOutbox`,并忽略回调错误。
|
||||
`outbox_events` 只有全局 `published_at`,没有逐消费者确认、租约、重试、死信和幂等收件箱。
|
||||
拟议的 `Publish(ctx, event)` 也没有事务作用域,不能兑现“与业务同事务”。
|
||||
|
||||
### A3. 工作区仍被当成事实源
|
||||
|
||||
原 `WorkspaceRef` 暴露 `Root`、`OutputDir` 和 `ManifestPath`,`OutputContract` 继续接受裸路径。
|
||||
这不能从类型上阻止路径拼接、跨工作区访问或链接逃逸。
|
||||
docquery 若继续在运行时从 `output.md` 选择正文,会保留导致历史 404/409 的 split-brain 根因。
|
||||
|
||||
### A4. 最终成果保险库未进入模块边界
|
||||
|
||||
`feature/final-artifact-vault` 已设计并实现终态归档、只读降级和 scratch 恢复,但尚未合入当前 dev 基线。
|
||||
原解耦方案没有为 artifactvault 分配端口、事件、授权和恢复边界,后续容易由 docquery 或 CLI 重建旁路。
|
||||
|
||||
### A5. contracts 可能成为新的高扇入万能包
|
||||
|
||||
原方案把内部接口、HTTP DTO、事件、错误码和共享枚举集中到一个包,并要求所有 DTO 版本化。
|
||||
这会把语义耦合搬到 `contracts` 和 `app`,使普通内部调整承担不必要的 ADR 成本。
|
||||
|
||||
### A6. 并发控制只覆盖了进程内互斥
|
||||
|
||||
当前代码同时存在 `sync.Mutex`、行锁、乐观 ETag、唯一幂等键和 `pg_advisory_xact_lock`。
|
||||
原方案没有规定哪些锁用于正确性、锁顺序、超时、重试边界和多副本行为。
|
||||
进程内锁只能优化单实例竞争,不能作为跨实例正确性条件。
|
||||
|
||||
### A7. 授权主体和后台执行边界缺失
|
||||
|
||||
“在应用层入口统一授权”没有定义可信 Principal 的来源,也没有覆盖 CLI、事件订阅者、恢复工具和后台任务。
|
||||
若端口继续接受调用方填写的 `UserID`、`ProjectID` 或裸 `DocRef`,可能形成 confused-deputy 或跨项目访问。
|
||||
|
||||
### A8. 横向 Wave 缺少最小可交付边界
|
||||
|
||||
原方案先物理搬包,再接口化,最后才处理单写者和事件语义。
|
||||
这会重复修改高扇出代码,并在真正验证边界之前冻结大量无消费者契约。
|
||||
错误信封和 PI Runner 协议与文档一致性解耦没有直接依赖,不应阻塞核心路线。
|
||||
|
||||
### A9. 迁移与回滚承诺不成立
|
||||
|
||||
可靠多消费者 outbox、FAV 集成和必要的状态字段需要增量 migration,因此“数据零迁移”不成立。
|
||||
后续里程碑会依赖前序契约,不能任意独立 revert;只能按 expand/migrate/contract 阶段和兼容窗口回退。
|
||||
|
||||
### A10. 架构检查范围会产生误报
|
||||
|
||||
表名和路径字面量合法存在于 Goose migration、fixture、测试和运维脚本。
|
||||
R5/R6 应检查生产运行时的越权写入和路径解析,不应以全仓 grep 的零出现作为完成条件。
|
||||
|
||||
## 外部规则核对
|
||||
|
||||
- PostgreSQL 行锁和事务级 advisory lock 会在事务结束时释放,适合短期业务互斥;session 级 advisory lock 不跟随回滚,不用于本方案的业务锁。[PostgreSQL explicit locking](https://www.postgresql.org/docs/17/explicit-locking.html)
|
||||
- `SKIP LOCKED` 适合多消费者队列表,不适合作为普通一致性查询语义。[PostgreSQL SELECT](https://www.postgresql.org/docs/current/sql-select.html)
|
||||
- Serializable 或 deadlock 重试必须重跑完整事务,包括决定 SQL 和参数的业务逻辑。[PostgreSQL serialization failure handling](https://www.postgresql.org/docs/16/mvcc-serialization-failure-handling.html)
|
||||
- 授权必须默认拒绝,并在每次请求或后台动作上重新校验,不能信任客户端传入的身份和资源归属。[OWASP Authorization Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Authorization_Cheat_Sheet.html)
|
||||
|
||||
## 整改结论
|
||||
|
||||
1. 暂停批准原 Wave 1–6,保留只读架构基线。
|
||||
2. 先定义事务、锁、授权、事件和持久成果契约。
|
||||
3. 首个交付只覆盖受控文档读取与终态提交纵向链。
|
||||
4. FAV、迁移语料和完整备份作为三个互补层接入。
|
||||
5. 通过真实页面刷新、重启、并发、权限和恢复停走门后,再批准其他模块拆分。
|
||||
|
||||
## 证据入口
|
||||
|
||||
- `internal/docrevision/pg_mutate.go`
|
||||
- `internal/docrevision/service.go`
|
||||
- `internal/workspace/resolver.go`
|
||||
- `internal/docduty/revoke.go`
|
||||
- `internal/taskrun/manager.go`
|
||||
- `deploy/postgres/goose/00018_2026-09-12-outbox-notifications-stage-advance.sql`
|
||||
- `.doc/adr/2026-09-13-document-version-boundary.md`
|
||||
- `feature/final-artifact-vault` 分支中的 FAV ADR、整改方案与测试报告
|
||||
@@ -0,0 +1,56 @@
|
||||
---
|
||||
title: "planning 项目残留 active_workflow_key 异态审计"
|
||||
status: done
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-14
|
||||
severity: low
|
||||
---
|
||||
|
||||
# planning 项目残留 active_workflow_key 异态审计
|
||||
|
||||
## 现象
|
||||
|
||||
dev 库存在 `lifecycle_status='planning' AND active_workflow_key <> ''` 行。评审时记为 81;本轮只读复测为 **83**(相对评审 +2)。这些行看起来像「已选工作流但未走设置激活」。
|
||||
|
||||
## 根因分析
|
||||
|
||||
关闭 `initial_workflow_key` 直通前,`CreateProject` 在键非空时会写 `lifecycle=active` + `ActiveWorkflowKey`。本异态是 **planning 却带 key**,更符合自动化测试夹具成对插入(`PROJ_MGR_*` / `TEST_PROJ_*`),而不是真实用户走创建旁路后的 active 项目。
|
||||
|
||||
本轮 **未** `UPDATE`/`DELETE`。
|
||||
|
||||
## 严重度
|
||||
|
||||
`low`
|
||||
|
||||
创建旁路已在 `fix/governance-action-level-authz` 关闭。存量 83 行全部无 live 实例、无创建人,不影响项目 143,也不阻塞 G1 鉴权矩阵。
|
||||
|
||||
## 关联整改
|
||||
|
||||
- Short-term: [2026-09-14-governance-action-level-authz](../archive/ops/2026-09-14-governance-action-level-authz.md)
|
||||
- Research: [2026-09-14-mvp-governance-rules-review](../ops/research/2026-09-14-mvp-governance-rules-review.md)
|
||||
|
||||
## 证据
|
||||
|
||||
只读查询(`shuimu-context-pg-dev` / `agent_system_dev`,2026-09-14):
|
||||
|
||||
| 指标 | 数量 |
|
||||
|------|------|
|
||||
| `lifecycle=active` | 141 |
|
||||
| `lifecycle=planning` | 209 |
|
||||
| `planning AND active_workflow_key <> ''` | **83** |
|
||||
|
||||
分类(禁止改库,仅标注):
|
||||
|
||||
| 分类 | 数量 | 判定 |
|
||||
|------|------|------|
|
||||
| 测试夹具 | **83** | `code` 为 `PROJ_MGR_YYYYMMDDHHMMSS`(名「智能微创内窥镜」)或 `TEST_PROJ_*`(名「测试内窥镜系统」);`active_workflow_key=main`;`workflow_selection_version=1`;`creator_user_id` 空;`has_live_instance=false`;时间戳成对出现于 2026-09-12~09-14 |
|
||||
| 历史直通(真实用户创建旁路) | **0** | 无非夹具命名、无创建人、无 live 实例的业务项目 |
|
||||
| 不明 | **0** | — |
|
||||
|
||||
样本 id(完整 83 行均属上表夹具模式,不逐条展开):61–62、122–128、6015–6021、6160–6161、6192/6195。项目 **143 不在此集合**。
|
||||
|
||||
相对评审 81 的 +2:`6192` / `6195`,创建于 2026-09-14 07:26 UTC,仍是同一对夹具命名。
|
||||
|
||||
## 开放问题
|
||||
|
||||
- 是否在后续专项清理夹具行(需单独任务与备份,不在本治理鉴权波次)。
|
||||
@@ -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 仅做冻结态只读回归;不得在验收中终止其工作流。若业务上确需改职责,必须先查看终止影响、确认取消运行任务及关闭实例的访问影响,再受控终止并重新规划、激活。
|
||||
@@ -0,0 +1,85 @@
|
||||
---
|
||||
title: "前端 mock 交付物污染真实项目:幻影受控文档伪造终审已生效态与法定职责"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
severity: critical
|
||||
---
|
||||
|
||||
# 前端 mock 交付物污染真实项目:幻影受控文档伪造终审已生效态与法定职责
|
||||
|
||||
## 现象
|
||||
|
||||
用户在 **test 环境**(127.0.0.1:8081)新建测试项目「测试项目」(test 库 `projects.id=1`,唯一项目),工作台立即显示 11 份「受控文档」,其中包括与该项目毫无关系的:
|
||||
|
||||
- 《4K超高清荧光内窥镜系统立项与可行性报告》
|
||||
- 《微创外科内窥镜全球竞品技术与临床深度调研报告》
|
||||
- 神经外科双频超声吸引(NeuroPulse)系列
|
||||
- CUSA 超声手术吸引系统系列
|
||||
|
||||
这些文档:
|
||||
|
||||
1. 显示**伪造的生命周期状态**(`reviewing` / `approved`——`DeckDrawer.tsx` 将 `approved` 渲染为「**终审已生效**」),即用户所称「生效区」出现从未经过任何 docgov 生命周期流转的"已生效"文档;
|
||||
2. 带有**伪造的法定职责人**(author 张工 / reviewer 李主管 / approver 王总监——均非真实用户);
|
||||
3. 带有伪造版本号(V1.0)、伪造更新时间、伪造正文全文;
|
||||
4. 在项目成员视角按真实受控文档参与 RBAC 可见性过滤与工作流槽位合并,**与真实服务端文档混排**。
|
||||
|
||||
而 test 库 `document_records` 为 **0 行**——服务端受控文档台账完全为空,这 11 份文档**全部来自前端硬编码 mock 数据**。
|
||||
|
||||
## 根因分析
|
||||
|
||||
### 1. mock 交付物硬编码绑定 projectId 1/2/3/5201/6001–6010
|
||||
|
||||
`web/src/App.tsx:267` `INITIAL_DELIVERABLES` 硬编码 7 份 mock 交付物 `projectId: 1`(doc-001~004、doc-shared-001、doc-private-001/002);`P2_INITIAL`(projectId 2)、`CUSA_INITIAL_DELIVERABLES`(projectId 3)、`NEUROPULSE`(5201)、`TEN_PROJECTS`(6001+)同理。`ALL_INITIAL_DELIVERABLES` 聚合后作为 `loadDeliverables()` 的默认值(App.tsx:621),并经 `saveDeliverables` **写入 localStorage 持久化**。
|
||||
|
||||
### 2. 项目过滤按数字 ID 匹配,新建项目与 mock 项目 ID 撞车
|
||||
|
||||
`App.tsx:1014`:`currentProjectDeliverables = deliverables.filter(doc => doc.projectId === currentProjectId)`。
|
||||
|
||||
- test 库为全新库,用户新建的第一个项目得到 `id=1` → 与 mock 的 `projectId: 1` **精确撞车**,7 份幻影文档全部"归属"该项目;
|
||||
- 新建项目时 `createProjectTemplateDeliverables`(App.tsx:3844)再克隆 7 份模板骨架(`doc-p1-*`,`lifecycleState: 'template'`,合规)→ 7 mock + 4~7 模板/私有,构成用户看到的 11 份;
|
||||
- **dev 库同样中招**:`agent_system_dev.projects` 存在真实项目 id 1–8(智能微创内窥镜/测试内窥镜系统等),id 1/2/3 的真实项目同样被 mock 文档污染。
|
||||
|
||||
### 3. mock 正文与 mock 用户/权限无环境门控,已进生产构建产物
|
||||
|
||||
- `mockDocuments.ts` 无任何 `import.meta.env` 门控;`App.tsx` 中 `MOCK_USERS`(含伪造 `projectPermissions: {doc-001: approver...}`)作为 `loadUsers()` 默认值与 `currentUser` 初始身份兜底(App.tsx:610/617);
|
||||
- **构建产物已验证污染**:`web/dist/assets/index-DogUjae5.js` 中 grep 命中「4K超高清荧光」字符串——dev/test/main 三环境共用同一前端构建,main 生产环境同样受影响。
|
||||
|
||||
### 4. 既有防线只挡"正文请求",不挡"清单展示"
|
||||
|
||||
团队已知悉 legacy mock ID(`revisionToolbarMount.ts:24 isLegacyLocalMockDocId`:`doc-\d{3}` / `doc-shared-*` / `doc-private-*` / `doc-cusa-*`),并禁止它们发起 content/revision 请求(`controlledDocHydrate.ts:shouldLoadControlledContent` 排除)。但这只防住了「幻影文档冒充服务端正文」,**没有防住幻影文档出现在交付物清单、生命周期徽章(终审已生效)、职责栏与项目文档统计中**——用户看到的正是后者。
|
||||
|
||||
### 5. 服务端权威清单未做前端对账
|
||||
|
||||
`GET /api/v1/projects/{id}/documents`(`docgov/project_docs.go`,`WHERE project_id=$1 AND task_key<>''`,服务端已正确按项目隔离)返回空数组时,`mergeWorkflowDocumentsFromServer`(`deliverableSync.ts:41`)**直接 `return prev`,不删除本地多余项**——本地幻影文档无任何下架机制。
|
||||
|
||||
## 严重度
|
||||
|
||||
`critical`:
|
||||
|
||||
1. **治理完整性破坏**:空项目展示「终审已生效」受控文档 + 三级法定职责人,在医疗器械合规语境下(ISO 13485 / 21 CFR Part 11 电子记录可靠性)构成"记录失实";
|
||||
2. **跨环境广泛影响**:dev 真实项目 id 1–8、test 新建项目、main 生产同构建产物全部受影响;
|
||||
3. **权限视图失真**:伪造职责人/权限映射混入 RBAC 过滤链,用户对"谁可审批什么"产生错误认知;
|
||||
4. 既有防线(isLegacyLocalMockDocId)证明团队已两次踩坑(本审计为同域第三类症状),说明 mock 数据保留策略系统性不足。
|
||||
|
||||
## 关联整改
|
||||
|
||||
- Remediation: [2026-09-15-mock-deliverables-pollution-remediation.md](../remediation/2026-09-15-mock-deliverables-pollution-remediation.md)
|
||||
|
||||
## 证据
|
||||
|
||||
- test 库(`shuimu-system-pg-test`,127.0.0.1:5434):`projects` 仅 id=1「测试项目」(通用医疗器械);`document_records` 0 行;全库 87 张业务表除 projects/users/auth_sessions/chat_sessions/project_workflows 外全部为空
|
||||
- dev 库(`shuimu-context-pg-dev`,127.0.0.1:5433):真实项目 id 1–8(智能微创内窥镜 / 测试内窥镜系统)→ 与 mock projectId 1/2/3 撞车
|
||||
- `web/src/App.tsx:267-498`(INITIAL_DELIVERABLES/P2/CUSA/ALL_INITIAL_DELIVERABLES)、`621`(loadDeliverables)、`1014`(projectId 过滤)、`3844`(新建克隆模板)
|
||||
- `web/src/data/mockDocuments.ts:32-505`(mock 文档全文与伪造 lifecycleState/职责人)、`web/src/data/seeds/neuropulseSeed.json`(projectId 5201)、`tenProjectsSeed.json`(6001–6010)
|
||||
- `web/dist/assets/index-DogUjae5.js`:grep 命中「4K超高清荧光」(生产构建含 mock 数据)
|
||||
- `web/src/features/documentRevision/revisionToolbarMount.ts:24-32`(isLegacyLocalMockDocId 既有防线)
|
||||
- `web/src/lib/deliverableSync.ts:41-45`(serverDocs 空时不回收本地项)
|
||||
- `web/src/components/doc/DeckDrawer.tsx:87-103`(approved → 「终审已生效」渲染)
|
||||
- `web/src/api/projectDocuments.ts:46-58`(服务端清单 API,服务端隔离正确)
|
||||
|
||||
## 开放问题
|
||||
|
||||
- mock 数据的保留意图(demo 演示模式?)需要在整改方案中决策:彻底移除 vs 环境门控(`import.meta.env.MODE` / 构建期注入 `VITE_ENABLE_DEMO_SEEDS`)
|
||||
- localStorage 中已被 `saveDeliverables` 持久化的 mock 项,需要一次性迁移清理(对齐既有 `dropRecordKeys`/ControlledInvalidationPlan 机制)
|
||||
- main 环境是否已有真实用户看过幻影文档(`document_access_audit` 为 0 行,无服务端读取痕迹,风险主要在前端展示层)
|
||||
@@ -0,0 +1,111 @@
|
||||
---
|
||||
title: "模块解耦 Phase 2 方案审阅"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
severity: high
|
||||
---
|
||||
|
||||
# 模块解耦 Phase 2 方案审阅
|
||||
|
||||
## 结论
|
||||
|
||||
模块化单体、消费者端口、组合根和持久事件的方向成立,但原 Phase 2 方案不能直接进入实施。它把事件可靠性、结构整理和两个外部协议绑成一个完成目标,并基于数项不成立的代码事实设计切换门。修订版已把 Track E(持久事件)、Track S(结构解耦)、Track P(外部协议)拆开,Track E 必须先完成生产者与历史数据门,再启动 dispatcher。
|
||||
|
||||
## 高优先级发现
|
||||
|
||||
### A1. PG delivery 尚未形成生产闭环
|
||||
|
||||
`internal/events/pg.go` 的 `ClaimIDs` 只做 SELECT + `FOR UPDATE SKIP LOCKED`,没有在同一事务写 lease owner/token/until;也没有 PG ack/fail/retry/dead-letter 的完整生产实现。`internal/events/dispatcher_test.go` 验证的是 MemoryBus。原方案把这些能力写成“已有”,会低估 D1 的 migration、状态机和故障测试范围。
|
||||
|
||||
整改:D1 增加 additive migration、原子 lease、heartbeat、fenced side-effect/ack、retry/dead/quarantine、不可变 attempt 表和独立 `cmd/events` 进程。
|
||||
|
||||
### A2. “恰好一次投递”不可由当前算法保证
|
||||
|
||||
副作用成功后、ack 前崩溃会导致重放。Fencing 若只拦 ack,也拦不住租约过期的旧 worker 提交副作用。
|
||||
|
||||
整改:契约改为 at-least-once delivery + exactly-one visible outcome。Token 进入 consumer command 和最终提交点;数据库副作用与 inbox/token 校验同事务,projection 使用 expected version、digest 和单调 marker。
|
||||
|
||||
### A3. 原 shadow 定义会双写,且按天零差异可空跑通过
|
||||
|
||||
旧方案同时写闭包和消费者结果,却又称“不产生可见变化”;两者矛盾。三天 dev 流量也可能没有低频文档事件或失败分支。
|
||||
|
||||
整改:闭包是 shadow 期间唯一真实写者。消费者只计算 normalized intended outcome 并写 reconciliation。停走门同时要求预登记样本、分支覆盖、最短时间和零未解释 diff;生产入口未证明出事件前不开始计时。
|
||||
|
||||
### A4. 文档事件源与作用域尚不可信
|
||||
|
||||
部分生产 HTTP 路径临时构造 `docflow.Commands`,没有稳定注入 EventSink/UoW。`Environment:"dev"`、`ProjectID:0` 和 FAV stage project 0 会使跨环境/项目 delivery 失真。
|
||||
|
||||
整改:E0A 先由组合根注入唯一命令对象;领域变化、envelope、delivery 同一 UoW;缺 project/env fail closed;旧数据先 inventory。
|
||||
|
||||
### A5. AggregateVersion 不能直接当无缺口事件序号
|
||||
|
||||
当前只在部分领域转换发事件。历史文档首次事件可能从较高版本开始;按缺号等待会永久阻塞。
|
||||
|
||||
整改:D11 在独立 event sequence 与 consumer checkpoint/bootstrap 中二选一,审计现有 aggregate/version 唯一约束并迁移。未决前禁止开启 gap blocking。
|
||||
|
||||
### A6. docgov/docrevision 不是双向 import
|
||||
|
||||
生产方向为 `docgov → docrevision`,用途集中在 canonical Markdown 与 SHA helper。原方案“提升无行为类型到 vocabulary”不能承载 canonicalization 行为。
|
||||
|
||||
整改:D6 改为提取内聚 `doccontent` 行为模块和 golden vectors;D6 可独立执行,不依赖 bizdev/stageflow。
|
||||
|
||||
### A7. event allowlist 已存在
|
||||
|
||||
`module-boundaries.yaml` 已有 `event_producers`/`event_consumers`。问题是映射稀疏,且运行时注册没有与静态清单做 parity 检查。
|
||||
|
||||
整改:D10 提升到 E0A,补 payload schema/version、enabled state 与 registry parity;FAV 标记 disabled。
|
||||
|
||||
### A8. FAV、HTTP、PI 不应阻塞核心
|
||||
|
||||
FAV 分支未完成独立审计。ADR 已把 HTTP 错误信封和 PI result protocol 定义为独立工作。把三者放入 Track E DoD 会延迟最有价值的刷新恢复闭环。
|
||||
|
||||
整改:Track E 只激活 notify、workflow advance、projection。FAV 只预留 disabled 契约;D8/D9 分别另建 remediation。
|
||||
|
||||
### A9. Replay、后台权限与日志脱敏不足
|
||||
|
||||
延迟事件不能沿用历史用户权限;当前 replay 校验不足以支持生产 apply。Raw payload/error 进入 dead-letter 或 reconciliation 会泄露正文、路径或凭证。
|
||||
|
||||
整改:每 consumer 独立 service principal,处理时重读资源和当前权限。Replay 采用 capability + 精确范围 + dry-run digest/apply exact digest + 审计;多项目/批量 apply 两人批准。日志只存 ID/digest/typed code/sanitized summary。
|
||||
|
||||
### A10. 滚动切换缺少集群级权威写者
|
||||
|
||||
删除新版本 hook 不会阻止旧实例继续执行。若 dispatcher 同时 live,滚动部署会双写。
|
||||
|
||||
整改:`off|shadow|live` 使用带 revision 的集群级状态;先部署兼容代码、drain 全部旧实例、记录 backlog 水位,再原子切换。回滚先暂停 claim并核对 receipt/backlog。
|
||||
|
||||
### A11. Locator 门禁原文过宽
|
||||
|
||||
全局禁止 `*pgxpool.Pool`/`pgx.Tx` 会拦截组合根注入与登记表属主的合法 UoW unwrap。
|
||||
|
||||
整改:只禁止领域/用例 API 暴露、返回、转发 pool/tx;明确允许 app/cmd 构造注入和登记属主 unwrap。
|
||||
|
||||
## 范围修订
|
||||
|
||||
| 轨道 | 内容 | 关闭条件 |
|
||||
|---|---|---|
|
||||
| Track E | D1/D2/D3/D10/D11 | PG + browser + restart + auth/replay 证据完成后独立关闭 |
|
||||
| Track S | D4/D5/D6/D7a/D7b | 各单元独立 go/no-go 与报告 |
|
||||
| Track P | HTTP error、PI typed result | 各自独立 remediation,不阻塞 Track E/S |
|
||||
|
||||
## 关联整改
|
||||
|
||||
- [修订后的 Phase 2 计划](../remediation/2026-09-15-module-decoupling-ipc-phase2-remediation-plan.md)
|
||||
- [修订后的现状调研](../ops/research/2026-09-15-module-decoupling-ipc-assessment.md)
|
||||
|
||||
## 审阅方法与证据
|
||||
|
||||
- 代码证据:`internal/events/pg.go`、`bus.go`、`dispatcher_test.go`、`replay.go`、`internal/app/docflow/commands.go`、`internal/docgov/lease.go`、`internal/bizdev/service.go`。
|
||||
- Schema:`deploy/postgres/goose/00035_2026-09-14-durable-event-delivery.sql`。
|
||||
- 边界:`.doc/system-design/module-boundaries.yaml`。
|
||||
- 上位决策:模块化单体 ADR 与 Phase 1 U6。
|
||||
- 审阅视角:一致性、可行性、范围、安全、产品价值、对抗失败预演;外部 reviewer 的有效结论仅用于交叉验证,不替代仓库证据。
|
||||
|
||||
## 开放问题
|
||||
|
||||
以下问题必须由 E0A 的代码/数据审计回答,不能在计划阶段猜测:
|
||||
|
||||
- projection consumer 的最终 owner 与 no-replace 提交接口。
|
||||
- event sequence 或 checkpoint/bootstrap 的选择及迁移成本。
|
||||
- 每类事件前 7 天基线流量、shadow 样本 N 和 worker 连接预算。
|
||||
- 现存错误 scope/schema delivery 的数量和 repair/quarantine/expire 分类。
|
||||
@@ -0,0 +1,122 @@
|
||||
---
|
||||
title: "多意图与 HITL 方案复核"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
severity: high
|
||||
---
|
||||
|
||||
# 多意图与 HITL 方案复核
|
||||
|
||||
## 结论
|
||||
|
||||
提案方向合理,且可复用现有 IntentFrameV2、ActionRegistry、PendingExpectation、交互卡和可靠事件骨架。但初稿不能直接实施:它会让 LLM backend 进入 `internal/intent`、把跨模块执行继续堆入 coordinator,并以不足以抵御多实例竞态的 PlanID+StepID 代替状态机和动作幂等,存在解耦回退、越权和双执行风险。
|
||||
|
||||
已按审阅结果重写[系统设计](../system-design/2026-09-15-multi-intent-hitl-plan.md)与[任务总览](../ops/short-term/2026-09-15-multi-intent-hitl.md)。本次仅修改文档,没有实施业务代码。
|
||||
|
||||
## 已确认问题
|
||||
|
||||
### P1:原 LLM 接线破坏 intent 纯模块边界
|
||||
|
||||
初稿要求在 `internal/intent/segmenter.go` 经既有 `agent.Backend` 分段;当前边界只允许 `intent -> maturity`。照此实施必然新增 intent 到 agent/coordinator 的依赖。
|
||||
|
||||
**整改:** 规则分段留在 intent;可选 LLM 仅作为 `app/intentflow` 外围 adapter,返回不可信分段建议,每段重新走确定性识别、安全扫描和 ActionRegistry。任何阶段都禁止 intent import agent、PG、storage 或 coordinator。
|
||||
|
||||
### P1:计划持久化缺少权威状态机与并发协议
|
||||
|
||||
初稿两表只有宽泛 status/payload,PlanID+StepID 只是标识,不能防重复确认、确认/取消/过期竞态、两个 worker 同时执行,也不能处理业务成功而步骤 receipt 未落库的崩溃窗口。
|
||||
|
||||
**整改:** 增加 plan revision/digest、append-only decisions、expected revision、decision nonce、步骤 CAS、lease/fencing、动作级幂等 receipt 和恢复对账。PG 是唯一权威;UserProjectContext/消息只保存 plan 引用。
|
||||
|
||||
### P1:确认未与当前授权绑定
|
||||
|
||||
持久化 user/role 或用户曾经确认都不能证明执行时仍有权。原稿没有要求恢复、读取和每步执行重新检查当前项目成员、duty、资源生命周期与版本。
|
||||
|
||||
**整改:** 确认只记录意愿;所有读取/决策验证 user/session/project 四元作用域;每步由动作 owner 按当前 principal 和 expected resource version 重新授权。失败 fail closed,不以系统身份代执行。
|
||||
|
||||
### P1:执行器方案会让 coordinator 再次成为 service locator
|
||||
|
||||
初稿拟扩展 `coordinator/action_planner.go` 的分发表来执行写动作,会把 docgov/taskrun/workflow 等具体实现重新聚集到 coordinator,抵消已完成的 chatflow/stageflow/bizdev 解耦。
|
||||
|
||||
**整改:** 新增深模块 `internal/app/intentflow` 作为计划生命周期 owner,通过消费者拥有的窄端口调用动作属主;coordinator/chat 仅保留兼容入口,组合根唯一装配。
|
||||
|
||||
### P1:事件与 SSE 被混为一条通道
|
||||
|
||||
现有 Track E 只处理注册的 PG 事件,不会自动把任意 delivery 变成 SSE。若只发 SSE,刷新丢失;若只写 outbox,浏览器不会自动得到状态。
|
||||
|
||||
**整改:** 计划状态同步落库;outbox 只发布版本化状态事实并驱动消息/read model 投影;SSE 是提交后的提示。刷新总是 GET PlanView。事件先登记 YAML、StaticContracts 和 payload allowlist。
|
||||
|
||||
### P1:不确定分段会退回单意图执行
|
||||
|
||||
“置信下降/指代补全失败就合并回单意图”与“不确定必须澄清、未确认零副作用”矛盾,仍可能执行 TopIntent 并丢弃其余任务。
|
||||
|
||||
**整改:** 只有确定为完整单意图连动时才合并;低置信、指代失败或无法证明完整一律澄清,保留候选理解但不执行。
|
||||
|
||||
### P1:数据复制与步骤传递缺少信任边界
|
||||
|
||||
初稿可能把原文、槽位、结果复制到 JSONB、日志、事件、SSE,再把查询摘要直接注入 task brief,扩大敏感数据面和提示注入路径。
|
||||
|
||||
**整改:** 计划保存消息引用/digest/allowlist display snapshot;事件和日志仅传 scope、状态与安全摘要引用;步骤间使用带 provenance/type/digest/sensitivity 的 ResultReference。结果只能进入隔离材料区,不能修改 action、target、tool 或 capability。
|
||||
|
||||
### P1:灰度开关顺序错误
|
||||
|
||||
现有 MULTI_INTENT_ENABLED 默认 true;初稿到最后一阶段才新增 tier,会让中间合入的行为缺少默认关闭门。
|
||||
|
||||
**整改:** U1 先建立默认 legacy 的新 tier;U2 只 shadow;auto_read 先维持两个查询的当前上限;确认和每个动作 adapter 分档开放。回滚必须继续支持已有计划读取/取消/收口。
|
||||
|
||||
## 重要产品修订
|
||||
|
||||
- 无活动写计划时单意图生成行为保持不变;多意图 generate 的确认/tier/adapter 能力由 intentflow BatchActionPolicy 管理,静态风险仍引用 ActionRegistry;
|
||||
- 计划卡默认显示一句摘要和主动作,详细风险/步骤折叠展开,降低认知负担;
|
||||
- 自然语言“确认”只有在当前会话恰有一个活动可见计划时才绑定;多计划或混入新任务时澄清;
|
||||
- 聚合澄清不承诺一次自由文本必然填满所有槽位;只接受可唯一映射值,槽位依赖/冲突继续追问;
|
||||
- 部分确认默认是分批批准,未选项保留待确认;只有显式排除才取消,部分完成提供重试/继续/关闭;
|
||||
- 单意图生成兼容承诺只适用于当前没有活动写计划;有活动计划时统一冲突视图,避免双任务;
|
||||
- 多意图价值必须用采用率、确认放弃率和拆单回退率证明;价值不足时停止写动作扩面,但保留“不静默丢任务”的安全改进。
|
||||
- 批量确认、tier 和 adapter 策略归 intentflow 的 BatchActionPolicy;ActionRegistry 只保留动作身份与静态风险,避免编排政策回灌 L1;
|
||||
- 计划卡折叠态仍显示目标、最高风险、不可撤销副作用和非原子语义;技术元数据才可折叠;
|
||||
|
||||
## 并发与权限检查表
|
||||
|
||||
- 同 turn 同 digest 返回原计划;同 turn 异 digest 冲突;
|
||||
- decision 带 expected revision、nonce 与 digest;
|
||||
- plan/step CAS 与单调 fencing;
|
||||
- fencing 和幂等占位必须进入动作属主事务,只锁计划行不足以阻止旧 worker 副作用;
|
||||
- confirm/cancel/expiry/edit 只有一个胜者;
|
||||
- 部分确认必须依赖闭包;
|
||||
- 双标签、双实例、worker 接管最多一次副作用;
|
||||
- 跨 user/project/session 不可读、不可确认且不泄露存在性;
|
||||
- 确认后成员/职责/资源状态变化仍会拒绝执行;
|
||||
- SSE 重复、乱序、缺失由 GET reconcile;
|
||||
- CSRF/Origin 沿用服务端认证策略,nonce 不冒充 CSRF。
|
||||
- active-plan discovery 是刷新必需入口,不能依赖消息投影中恰好保存 plan_id。
|
||||
|
||||
## 范围与任务修订
|
||||
|
||||
原 T1–T5 被重拆为核心 U1–U8、可选实验 U9 和属主扩面 U10–U12:契约门禁、纯规则 shadow、持久计划、事件投影、决策/授权、Web、只读执行、task generate 首版、LLM adapter、mutate/docgov/workflow-run 分项扩面。每个单元有独立依赖、文件范围、测试、停走门与真实 mutex。总览不长期占用 `intent`;每个 action 仍需独立 short-term。
|
||||
|
||||
## 评审覆盖
|
||||
|
||||
- 本地视角:coherence、feasibility、security、scope、product、design、adversarial;
|
||||
- 独立 cross-model:Claude Opus 5/high 的 security、product、adversarial 与 whole-document sweep;
|
||||
- cross-model 审的是初稿,其关于 LLM 输入、plan ACL、结果传递、幂等、产品价值和确认负担的有效意见已纳入修订;其余由当前代码与边界事实校正。
|
||||
|
||||
## 关联整改
|
||||
|
||||
- System design: [2026-09-15-multi-intent-hitl-plan.md](../system-design/2026-09-15-multi-intent-hitl-plan.md)
|
||||
- Short-term: [2026-09-15-multi-intent-hitl.md](../ops/short-term/2026-09-15-multi-intent-hitl.md)
|
||||
|
||||
## 证据
|
||||
|
||||
- `internal/intent/plan_builder.go`:首连接词、两段、写意图返回 nil;
|
||||
- `internal/coordinator/action_planner.go`:pending confirm 仅文字提示;
|
||||
- `internal/intent/registry.go`:task.run/adhoc 为 medium 且当前不全局 RequiresConfirm;
|
||||
- `internal/intent/flags.go`:MULTI_INTENT_ENABLED 默认 true;
|
||||
- `.doc/system-design/module-boundaries.yaml`:intent 只依赖 maturity,Track E/table owners 已登记;
|
||||
- `internal/events/registry.go`:事件须静态注册;
|
||||
- `internal/app/uow/uow.go`:不透明 TxScope;
|
||||
- `web/src/App.tsx`:现有 card action 含前端本地业务状态路径。
|
||||
|
||||
## 开放问题
|
||||
|
||||
无阻塞性架构问题。各放量阈值必须在 U2 shadow 基线形成后预注册;这属于实施期量化,不授权跳过停走门。
|
||||
@@ -0,0 +1,44 @@
|
||||
---
|
||||
title: Demo/测试数据污染系统性审计
|
||||
status: done
|
||||
created: 2026-09-16
|
||||
updated: 2026-09-16
|
||||
owner: Cursor-Auto
|
||||
---
|
||||
|
||||
# Demo / 测试数据污染系统性审计
|
||||
|
||||
## 前序
|
||||
|
||||
本审计在 [2026-09-15 mock 交付物污染真实项目](./2026-09-15-mock-deliverables-pollute-real-projects.md)(及对应 [整改](../remediation/2026-09-15-mock-deliverables-pollution-remediation.md))之上收敛为全栈系统性排查:前端门控、goose 演示项目/会话、stub API。
|
||||
|
||||
## 背景
|
||||
|
||||
空项目展示「终审已生效」受控文档 + 伪造三级职责人。初判怀疑 docgov 隔离失败;实锤为前端 mock/seed 与 DB goose 演示种子污染。
|
||||
|
||||
## 结论
|
||||
|
||||
| 面 | 判定 | 说明 |
|
||||
|----|------|------|
|
||||
| 服务端 `document_records` / project_docs | **正常** | 按 `project_id` 隔离;空项目台账为 0 |
|
||||
| 前端 `ALL_INITIAL_DELIVERABLES` / mockDocuments | **critical** | 无门控进生产包;projectId 1/2/3 撞车 |
|
||||
| 前端 DEFAULT_PROJECTS / sessions / MOCK_USERS | **critical/high** | NeuroPulse 5201、CUSA id=3、6001–6010 |
|
||||
| `deliverableSync` 空清单 `return prev` | **critical** | 权威空列表不回收本地 mock |
|
||||
| `isLegacyLocalMockDocId` 覆盖不全 | **critical** | 未覆盖 neuropulse / ten-projects |
|
||||
| Goose `00011`/`00012` | **critical** | 全环境写入 6001–6010 + 聊天 |
|
||||
| API `backend=stub` | **high** | main 仍可请求 stub |
|
||||
| `BootstrapDevSeedUsers` | **OK** | 已有 env 门控 |
|
||||
|
||||
## 证据路径
|
||||
|
||||
- `web/src/App.tsx`(整改前 INITIAL_*)
|
||||
- `web/src/data/mockDocuments.ts` / `neuropulseDemo.ts` / `tenProjectsDemo.ts`
|
||||
- `web/src/lib/deliverableSync.ts`
|
||||
- `deploy/postgres/goose/00011_*.sql` / `00012_*.sql`
|
||||
- `internal/taskrun/backend.go`
|
||||
- 产物扫描:`scripts/check-prod-bundle.sh`
|
||||
|
||||
## 整改回链
|
||||
|
||||
- [remediation](../remediation/2026-09-16-demo-seed-pollution-remediation.md)
|
||||
- [test-report](../test-reports/2026-09-16-demo-seed-pollution-test-report.md)
|
||||
@@ -13,6 +13,46 @@
|
||||
|
||||
## 核心文档(按阅读顺序推荐)
|
||||
|
||||
### 多意图与 HITL 方案复核(2026-09-15)
|
||||
|
||||
**文件**: [2026-09-15-multi-intent-hitl-plan-review.md](./2026-09-15-multi-intent-hitl-plan-review.md)
|
||||
|
||||
**结论**: 多意图方向可行,但必须以 `app/intentflow` 深模块、PG 权威状态机、逐动作即时授权和分波 mutex 防止 intent/coordinator 再耦合;确认、卡片和 SSE 均不能替代授权或权威状态。
|
||||
|
||||
**设计/计划**: [多意图持久计划与 HITL](../system-design/2026-09-15-multi-intent-hitl-plan.md) · [核心 U1–U8 与扩面 U9–U12](../ops/short-term/2026-09-15-multi-intent-hitl.md)
|
||||
|
||||
|
||||
### 模块解耦 Phase 2 方案复核(2026-09-15)
|
||||
|
||||
**文件**: [2026-09-15-module-decoupling-phase2-plan-review.md](./2026-09-15-module-decoupling-phase2-plan-review.md)
|
||||
|
||||
**结论**: PG delivery 尚未形成生产闭环;原计划把事件、结构和协议三轨绑成一次交付,并误判 docgov/docrevision 依赖方向。修订版先完成事件生产与历史数据门,再以 PG dispatcher、逐消费者 shadow 和真实刷新/重启恢复收口。
|
||||
|
||||
**整改**: [Phase 2 持久事件交付与后续解耦路线](../remediation/2026-09-15-module-decoupling-ipc-phase2-remediation-plan.md)
|
||||
|
||||
|
||||
### arch-check U1 可重放基线(2026-09-14)
|
||||
|
||||
**文件**: [2026-09-14-arch-check-baseline.md](./2026-09-14-arch-check-baseline.md)
|
||||
|
||||
**结论**: 四类规则(production import / SQL write / path / event)可重放。import=0,sql_write=5,path=17,event=0。Goose 与测试不计生产写者。新违规与过期例外立即 block。
|
||||
|
||||
### 模块解耦方案复核(2026-09-14)
|
||||
|
||||
**文件**: [2026-09-14-module-decoupling-plan-review.md](./2026-09-14-module-decoupling-plan-review.md)
|
||||
|
||||
**结论**: 模块化单体方向成立,但原横向 Wave 缺少跨属主事务、可靠事件、多副本互斥、逐动作授权和 FAV 边界;应先完成受控文档可靠性纵向试点,再按证据扩面。
|
||||
|
||||
**整改**: [模块解耦与文档可靠性重构计划](../remediation/2026-09-14-module-decoupling-refactor-plan.md)
|
||||
|
||||
### 项目 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)
|
||||
|
||||
+79
-13
@@ -1,24 +1,44 @@
|
||||
# 当前焦点
|
||||
|
||||
**更新**: 2026-09-14
|
||||
**production_ready**: no(`CHAT-INTENT-STATE` 等无关 blocker 仍开放。文档账本运行时 UI Round20 **PASS**,不把 fallback change report 写成完整 PI,也不把本轮写成全仓可发布)
|
||||
**更新**: 2026-09-16
|
||||
**production_ready**: yes(门禁 B1–B4 已签;dev/test/main `schema_version=47`。不把 fallback change report 写成完整 PI)
|
||||
|
||||
## 焦点
|
||||
|
||||
1. **DOC-CONTENT**: [受控正文 canonical hash 漂移](../audit/2026-09-14-project143-controlled-content-404.md)(真实 UI 验收已 PASS:项目 143 clean-run3 + 新项目 full-chain-final 主链及 restart 均全部通过)
|
||||
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 为准收敛)
|
||||
1. **MATRIX 深度测试 + 晋升 test**:`feature/matrix-deep-test-promote-test` → `rc-v1.0.0-beta.2`
|
||||
2. **首发后 backlog**:多意图 U9–U12、软件项目自举、FAV、完整 PI change-report 叙事
|
||||
3. **MULTI-INTENT HITL**:核心 U1–U8 已合入;U9–U12 不阻塞首版
|
||||
|
||||
## 并行认领
|
||||
|
||||
| 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 |
|
||||
| Cursor-Auto | 2026-09-16-matrix-deep-test-promote-test | feature/matrix-deep-test-promote-test | - | infra | in_progress |
|
||||
| Cursor-Auto | 2026-09-16-production-ready-gates | docs/production-ready-flip | - | ci | done |
|
||||
| Cursor-Auto | 2026-09-16-demo-seed-pollution | fix/demo-data-pollution-web | - | web | done |
|
||||
| Cursor | 2026-09-16-multi-intent-u8-task-generate | feature/multi-intent-u8-task-generate | - | intent-plan | done |
|
||||
| Cursor | 2026-09-16-multi-intent-u7-auto-read | feature/multi-intent-u7-auto-read | - | intent-plan | done |
|
||||
| Cursor | 2026-09-16-multi-intent-u6-web-cards | feature/multi-intent-u6-web-cards | - | web | done |
|
||||
| Cursor | 2026-09-16-multi-intent-u5-decision-api | feature/multi-intent-u5-decision-api | - | intent-plan | done |
|
||||
| Cursor | 2026-09-16-multi-intent-u4-outbox-projection | feature/multi-intent-u4-outbox-projection | - | events | done |
|
||||
| Cursor | 2026-09-15-multi-intent-u3-intentflow-pg | feature/multi-intent-u3-intentflow-pg | - | intent-plan | done |
|
||||
| Cursor | 2026-09-15-multi-intent-u2-segmenter | feature/multi-intent-u2-segmenter | - | intent | done |
|
||||
| Cursor | 2026-09-15-multi-intent-u1-contracts | feature/multi-intent-u1-contracts | - | architecture-docs | done |
|
||||
| Cursor | app-composition-u11-u12 | feature/app-composition-u11-u12 | - | app | done |
|
||||
| Cursor | chatlog-contextasm-u10 | feature/chatlog-contextasm-u10 | - | chat | done |
|
||||
| Cursor | chat-history-refresh-remediation | fix/chat-history-refresh | - | chat | done |
|
||||
| Cursor | dataset-lifecycle-u9 | feature/dataset-lifecycle-u9 | - | dataset | done |
|
||||
| Cursor | taskrun-runmanifest-u8 | feature/taskrun-runmanifest | - | taskrun | done |
|
||||
| Cursor | document-reliability-m1-live-and-m2 | refactor/document-reliability-pilot | - | workspace | done |
|
||||
| Codex | module-decoupling-remediation-plan | feature/module-decoupling-remediation | - | architecture-docs | done |
|
||||
| Codex | module-decoupling-phase2-plan-review | docs/module-decoupling-ipc-assessment | - | architecture-docs | done |
|
||||
| Cursor | module-decoupling-phase2-docs | feature/module-decoupling-phase2-docs | - | architecture-docs | done |
|
||||
| verifier_antigravity | controlled-content-ui-acceptance | fix/controlled-content-ui-acceptance | - | document-content-ui-acceptance | done |
|
||||
| implementer_cursor | controlled-content-canonical-hash | 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 |
|
||||
| Codex | conversation-intent-runtime-state | fix/conversation-intent-state | - | intent | done |
|
||||
| Cursor | conversation-intent-runtime-state | docs/conversation-intent-dual-tab | - | intent | done |
|
||||
| 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 |
|
||||
@@ -46,14 +66,36 @@
|
||||
| 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 |
|
||||
| implementer_cursor | workflow-plan-409-frozen-and-optional-duties | fix/workflow-plan-409-frozen-and-optional-duties | - | workflow | done |
|
||||
| implementer_cursor | governance-action-level-authz | fix/governance-action-level-authz | - | workflow | done |
|
||||
| Cursor | leftover-branch-cleanup | chore/leftover-branch-cleanup | - | ops | done |
|
||||
| Cursor | event-e0a-production-scope-contract | fix/event-production-scope-contract | - | events | done |
|
||||
| Cursor | event-e0b-dispatcher-pg | feature/events-dispatcher-pg | - | events | done |
|
||||
| Cursor | event-e1a-notify-cutover | fix/event-notify-cutover | - | events | done |
|
||||
| Cursor | event-e1b-workflow-advance | fix/event-workflow-advance | - | events | done |
|
||||
| Cursor | event-e1c-projection-cutover | fix/event-projection-cutover | - | events | done |
|
||||
| Cursor | event-e2-hook-guard | fix/event-e2-hook-guard | - | events | done |
|
||||
| Cursor | doccontent-canonical-boundary | fix/doccontent-canonical-boundary | - | docgov | done |
|
||||
| Cursor | intent-bizdev-boundary | fix/intent-bizdev-boundary | - | intent | done |
|
||||
| Cursor | stageflow-type-ownership | fix/stageflow-type-ownership | - | stageflow | done |
|
||||
| Cursor | bizdev-locator-removal | fix/bizdev-locator-removal | - | bizdev | done |
|
||||
| Cursor | chatflow-orchestration-boundary | fix/chatflow-orchestration-boundary | - | chat | done |
|
||||
| Cursor | phase2-closeout-inventories | feature/phase2-closeout-inventories | - | architecture-docs | done |
|
||||
| Cursor | event-shared-live-cutover | feature/event-shared-live-cutover | - | events | done |
|
||||
| Cursor | pi-typed-result | feature/pi-typed-result | - | pi-agent | done |
|
||||
| Cursor | promote-dev-to-test-2026-09-15 | feature/promote-dev-to-test-2026-09-15 | - | infra | done |
|
||||
|
||||
> 新任务开始前登记。`branch` 必须为 `feature/<slug>` 或 `fix/<slug>`,**禁止** `dev` / `test` / `main`。同一 `mutex` 同时仅一个 `in_progress`。
|
||||
|
||||
> workflow-plan 409 与治理鉴权 G1–G5 已收口(见 [test-report](../test-reports/2026-09-14-governance-action-level-authz-test-report.md))。禁止终止或改写项目 143。
|
||||
> `document-reliability-pilot` U11–U12 已合入 `dev@bf59cce` 并 rebuild。`CHAT-INTENT-STATE` 双标签 busy 已 PASS(项目 6275)。禁止 worktree 内 `env-service`。项目 143 只读,禁止终止。
|
||||
> 2026-09-15 旁支清理:[报告](../test-reports/2026-09-15-leftover-branch-cleanup-test-report.md)。已合入本地旁支 31 条已 `git branch -d`;7 个对应 worktree 已拆。extra worktree 仅余 `.worktrees/fix-dev-runtime-data-root-guard`(目录名是 guard,检出的是 `feature/final-artifact-vault`)。**故意不合入、不删**:`feature/final-artifact-vault`、`feature/remove-herdr-agent-settings`、`fix/project143-controlled-content-404-diagnosis`、`fix/dev-runtime-data-root-guard`、`dev-old-linear`。不删 `origin/*`。不整支 merge FAV;不启用 `FAV_DEGRADED_READ`。
|
||||
|
||||
## 集成槽位
|
||||
|
||||
| holder | phase | since | scope | queue |
|
||||
|--------|-------|-------|-------|-------|
|
||||
| idle | idle | - | - | - |
|
||||
| Cursor-Auto | merging | 2026-09-16T13:20Z | matrix deep test → promote rc-v1.0.0-beta.2 + test rebuild | - |
|
||||
|
||||
**phase**: `idle` | `merging` | `smoke` | `e2e`
|
||||
|
||||
@@ -63,9 +105,9 @@
|
||||
|
||||
| 环境 | 端口 | schema | 状态 |
|
||||
|------|------|--------|------|
|
||||
| dev | 8080 | **32** | healthy(产品代码部署为 `36e4bc3`;真实 UI 主链+restart PASS) |
|
||||
| test | 8081 | 25→27* | healthy |
|
||||
| main | 8000 | 25→27* | healthy(app + runner + DB) |
|
||||
| dev | 8080 | **47** | healthy(`pi-agent` typed-result-v1;events worker `:8088`;notify/advance/projection live、fav off;health+ready PASS;demo 6001–6010 retired) |
|
||||
| test | 8081 | **47** | healthy(`rc-v1.0.0-beta.1`;pi-agent `:18866`;events `:8089`;notify/advance/projection live、fav off;health+ready PASS;schema 与 dev 对齐 47) |
|
||||
| main | 8000 | **47** | healthy(app + events + runner + DB;与 dev/test 对齐) |
|
||||
|
||||
## SSOT
|
||||
|
||||
@@ -76,11 +118,35 @@
|
||||
| 发布缺口 | [gap-matrix](../remediation/gap-matrix.md) |
|
||||
| 测试报告 | [test-reports/](../test-reports/) |
|
||||
| Agent 手册 | [AGENTS.md](../../AGENTS.md) |
|
||||
| 意图双标签 busy 交接 | [./handoffs/2026-09-15-conversation-intent-dual-tab.md](./handoffs/2026-09-15-conversation-intent-dual-tab.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) |
|
||||
| 模块化单体解耦架构 | [../system-design/2026-09-14-module-decoupling-architecture.md](../system-design/2026-09-14-module-decoupling-architecture.md) |
|
||||
| 模块解耦整改计划 | [../remediation/2026-09-14-module-decoupling-refactor-plan.md](../remediation/2026-09-14-module-decoupling-refactor-plan.md) |
|
||||
| Phase 2 方案审阅 | [../audit/2026-09-15-module-decoupling-phase2-plan-review.md](../audit/2026-09-15-module-decoupling-phase2-plan-review.md) |
|
||||
| Phase 2 修订计划 | [../remediation/2026-09-15-module-decoupling-ipc-phase2-remediation-plan.md](../remediation/2026-09-15-module-decoupling-ipc-phase2-remediation-plan.md) |
|
||||
| 多意图 HITL 复核方案 | [../system-design/2026-09-15-multi-intent-hitl-plan.md](../system-design/2026-09-15-multi-intent-hitl-plan.md) |
|
||||
| 多意图 HITL U1 契约 | [../test-reports/2026-09-15-multi-intent-u1-contracts-test-report.md](../test-reports/2026-09-15-multi-intent-u1-contracts-test-report.md) |
|
||||
| 多意图 HITL U2 分段 | [../test-reports/2026-09-15-multi-intent-u2-segmenter-test-report.md](../test-reports/2026-09-15-multi-intent-u2-segmenter-test-report.md) |
|
||||
| 多意图 HITL U3 PG | [../test-reports/2026-09-15-multi-intent-u3-intentflow-pg-test-report.md](../test-reports/2026-09-15-multi-intent-u3-intentflow-pg-test-report.md) |
|
||||
| 多意图 HITL U4 投影 | [../test-reports/2026-09-16-multi-intent-u4-outbox-projection-test-report.md](../test-reports/2026-09-16-multi-intent-u4-outbox-projection-test-report.md) |
|
||||
| 多意图 HITL U5 API | [../test-reports/2026-09-16-multi-intent-u5-decision-api-test-report.md](../test-reports/2026-09-16-multi-intent-u5-decision-api-test-report.md) |
|
||||
| 多意图 HITL U6 Web | [../test-reports/2026-09-16-multi-intent-u6-web-cards-test-report.md](../test-reports/2026-09-16-multi-intent-u6-web-cards-test-report.md) |
|
||||
| 多意图 HITL U8 generate | [../test-reports/2026-09-16-multi-intent-u8-task-generate-test-report.md](../test-reports/2026-09-16-multi-intent-u8-task-generate-test-report.md) |
|
||||
| 多意图 HITL U7 只读 | [../test-reports/2026-09-16-multi-intent-u7-auto-read-test-report.md](../test-reports/2026-09-16-multi-intent-u7-auto-read-test-report.md) |
|
||||
| 文档可靠性 M1 报告 | [../test-reports/2026-09-14-document-reliability-pilot-test-report.md](../test-reports/2026-09-14-document-reliability-pilot-test-report.md) |
|
||||
| 文档可靠性 M1 活验 | [../test-reports/2026-09-14-document-reliability-pilot-live-test-report.md](../test-reports/2026-09-14-document-reliability-pilot-live-test-report.md) |
|
||||
| 文档可靠性 M2 | [../test-reports/2026-09-14-document-reliability-m2-test-report.md](../test-reports/2026-09-14-document-reliability-m2-test-report.md) |
|
||||
| 文档可靠性 M3 U8 | [../test-reports/2026-09-15-taskrun-runmanifest-u8-test-report.md](../test-reports/2026-09-15-taskrun-runmanifest-u8-test-report.md) |
|
||||
| 文档可靠性 M3 U9 | [../test-reports/2026-09-15-dataset-lifecycle-u9-test-report.md](../test-reports/2026-09-15-dataset-lifecycle-u9-test-report.md) |
|
||||
| 文档可靠性 M4 U10 | [../test-reports/2026-09-15-chatlog-contextasm-u10-test-report.md](../test-reports/2026-09-15-chatlog-contextasm-u10-test-report.md) |
|
||||
| 文档可靠性 M5/M6 U11–U12 | [../test-reports/2026-09-15-app-composition-u11-u12-test-report.md](../test-reports/2026-09-15-app-composition-u11-u12-test-report.md) |
|
||||
| Track E E2 闭包守卫 | [../test-reports/2026-09-15-event-e2-hook-guard-test-report.md](../test-reports/2026-09-15-event-e2-hook-guard-test-report.md) |
|
||||
| Track E 复盘 | [./research/2026-09-15-track-e-retrospective.md](./research/2026-09-15-track-e-retrospective.md) |
|
||||
| 旁支清点收口 | [../test-reports/2026-09-15-leftover-branch-cleanup-test-report.md](../test-reports/2026-09-15-leftover-branch-cleanup-test-report.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) |
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
---
|
||||
title: "模块解耦重构验收清单"
|
||||
status: in_progress
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-15
|
||||
owner: Cursor
|
||||
---
|
||||
|
||||
# 模块解耦重构验收清单
|
||||
|
||||
## M0 架构与基线
|
||||
|
||||
- [x] contracts 分类、事务 owner、表属主、锁顺序、事件信封、Principal 和 FAV 边界均有唯一规范来源。
|
||||
- [x] arch-check 分离 production import、SQL write、path 和 event registration;例外有 owner 与到期日。
|
||||
- [x] 当前违规基线可重复生成,新违规立即阻断。
|
||||
|
||||
## M1 文档可靠性
|
||||
|
||||
- [x] 人工编辑、agent commit、approve/reject 的跨表写入同事务(U3;隔离库双会话编辑已测)。
|
||||
- [x] fault injection 任一点失败均无部分提交(U2 隔离库)。
|
||||
- [x] 同 ETag 并发写只有一个赢家(内存 + 双会话)。
|
||||
- [x] 1、2、4 app replicas 结果一致。
|
||||
- [x] GET 服务端零写入 + typed consistency(U4 单测)。refresh/reload 真页面 PASS([活验报告](../../test-reports/2026-09-14-document-reliability-pilot-live-test-report.md))。
|
||||
- [x] 项目 143 等价 hazard 与新项目真实页面刷新、重登、restart、rebuild PASS。
|
||||
- [x] 服务端负例 fail closed;浏览器跨用户 401/404 PASS。
|
||||
|
||||
## M2 事件与 FAV
|
||||
|
||||
- [x] 业务终态、staging 和 outbox 同事务。
|
||||
- [x] 每个 consumer 有独立 delivery/inbox/attempt/lease/dead-letter。
|
||||
- [x] 1、2、4 dispatcher 无重复可见副作用和永久饥饿。
|
||||
- [x] crash-before/after-side-effect/ack 全部可恢复。
|
||||
- [x] stale fencing、跨项目事件、错误 producer、坏 digest 均拒绝。
|
||||
- [x] FAV 中间结果、Prompt、工具轨迹和 secret 准入率为零。
|
||||
- [x] DB 授权成功后才允许 degraded read;授权图缺失 fail closed。
|
||||
- [x] tombstone/删除账本 union-deny PASS。
|
||||
|
||||
## M3 TaskRun、workspace 与数据生命周期
|
||||
|
||||
- [x] RunManifest 规范字节、SHA、成员和 storage identity 持久化。
|
||||
- [x] 重复 finalize、SSE 断线和 cancel race 不重复消息或 artifact。
|
||||
- [x] WorkspaceRef 无物理路径,路径遍历和链接逃逸负例 PASS。
|
||||
- [x] 旧 lease writer 被 fencing token 拒绝。
|
||||
- [x] workspace 清空后最终成果仍可定位和校验。
|
||||
- [x] backfill 可暂停、续跑和重放;异常进入 quarantine。
|
||||
- [x] 八条 migration/reload/recovery 轨道 PASS。
|
||||
- [x] 数据销毁前完整备份、corpus、FAV coverage 和人工批准全部满足。
|
||||
|
||||
## M4–M6 选择性扩展
|
||||
|
||||
- [x] 每个子切片在原包边界先获得行为收益,再决定物理搬包。
|
||||
- [x] chatlog/contextasm 保持授权可见集合和计数一致。
|
||||
- [x] app 是唯一组合根,subscriber 重复启动不重复注册。
|
||||
- [x] UserProjectContext 跨模块写路径走类型化 ContextUpdate + 版本 CAS(coordinator 作为 owner 仍可改 Project 字段)。
|
||||
- [ ] server 无 SQL、路径拼接和业务闭包。(OnOutbox 已迁出;生产 SQL 无新增;path 例外 `workspaces/` / `output.md` 未到期,未删)
|
||||
- [ ] 对应架构规则全部 block,过期例外和 flags 已删除。(`import`/`event` 已 block;sql_write/path 基线例外仍在)
|
||||
|
||||
## 证据分层
|
||||
|
||||
- [x] Unit/stub 证据。
|
||||
- [x] PostgreSQL integration 证据(隔离库,非共享 env 库)。
|
||||
- [x] race/concurrency 目标包证据(非全仓 race)。
|
||||
- [x] fault injection 证据(U2)。
|
||||
- [x] 真实 PI 证据。
|
||||
- [x] 真实浏览器证据。
|
||||
- [x] restart/rebuild 证据。
|
||||
- [x] cross-user/project authorization negative 服务端证据。
|
||||
- [x] scratch recovery 与完整 DB restore 证据。
|
||||
|
||||
## 关闭条件
|
||||
|
||||
- [x] test report 回链具体 U-ID、commit、环境 identity 和 fixture/dataset。([U11–U12 报告](../../test-reports/2026-09-15-app-composition-u11-u12-test-report.md);合入 `dev` 后补 rebuild 镜像)
|
||||
- [x] CURRENT、FEATURE-MATRIX、gap-matrix 与任务状态一致。
|
||||
- [x] 未实施后续仍为 planned/deferred,不用局部测试冒充全计划完成。
|
||||
@@ -0,0 +1,22 @@
|
||||
---
|
||||
title: "多意图 HITL U1 契约冻结 checklist"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
related_task: "2026-09-15-multi-intent-u1-contracts"
|
||||
---
|
||||
|
||||
# 多意图 HITL U1 契约冻结 checklist
|
||||
|
||||
## Wave 0
|
||||
|
||||
- [x] YAML `app/intentflow` allowlist + 三表 owner + unwrap_owners — 证据:`.doc/system-design/module-boundaries.yaml`
|
||||
- [x] 三条 `intent.plan.*` YAML ↔ StaticContracts parity — 证据:`go test ./internal/events -run RegistryParity`
|
||||
- [x] archtest 扫描 `intent.plan.*` — 证据:`go test ./internal/archtest`
|
||||
- [x] intentflow 状态/错误码/Service/政策/legacy tier — 证据:`go test ./internal/app/intentflow`
|
||||
- [x] CSRF/Bearer 结论落盘 — 证据:U1 short-term
|
||||
- [x] `go test -short ./...` — 证据:[U1 报告](../../test-reports/2026-09-15-multi-intent-u1-contracts-test-report.md)
|
||||
|
||||
## 完成定义
|
||||
|
||||
- [x] 全部勾选且有证据链接
|
||||
@@ -0,0 +1,22 @@
|
||||
---
|
||||
title: "多意图 HITL U2 规则分段 checklist"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
related_task: "2026-09-15-multi-intent-u2-segmenter"
|
||||
---
|
||||
|
||||
# 多意图 HITL U2 规则分段 checklist
|
||||
|
||||
## Wave 1
|
||||
|
||||
- [x] characterization 锁定 legacy IntentPlan — 证据:`internal/intent/plan_builder_test.go`;[报告 §5.1](../../test-reports/2026-09-15-multi-intent-u2-segmenter-test-report.md)
|
||||
- [x] 分段器 golden(连接词/句号/序号/先再最后) — 证据:[proposal-verbose.txt](../../test-reports/assets/2026-09-15-multi-intent-u2-segmenter/proposal-verbose.txt)
|
||||
- [x] 查询并总结不拆;写段进入提案;5 段拒绝;红线整体拒绝;指代澄清 — 证据:同上
|
||||
- [x] digest 稳定;shadow 不改 TopIntent — 证据:`TestPlanProposal_DigestStable` / `TestPlanProposal_WriteNotDroppedAndLegacyUnchanged`
|
||||
- [x] 反事实 auto_read 错误自动执行 = 0 — 证据:`plan-proposal eval denom=8 false_auto_execute=0`
|
||||
- [x] `go test -short ./internal/intent ./internal/coordinator ./internal/app/intentflow` — 证据:[unit.txt](../../test-reports/assets/2026-09-15-multi-intent-u2-segmenter/unit.txt);[short.txt](../../test-reports/assets/2026-09-15-multi-intent-u2-segmenter/short.txt)
|
||||
|
||||
## 完成定义
|
||||
|
||||
- [x] 全部勾选且有证据链接
|
||||
@@ -0,0 +1,22 @@
|
||||
---
|
||||
title: "多意图 HITL U3 intentflow PG checklist"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
related_task: "2026-09-15-multi-intent-u3-intentflow-pg"
|
||||
---
|
||||
|
||||
# 多意图 HITL U3 intentflow PG checklist
|
||||
|
||||
## Wave 2
|
||||
|
||||
- [x] Goose 00044 三表 + unique/CAS/lease 列 — 证据:`deploy/postgres/goose/00044_2026-09-15-intent-plans.sql`;`TestGooseU3_00044_HasUpAndDown`
|
||||
- [x] 创建幂等与同 turn 异 digest — 证据:[plans-verbose.txt](../../test-reports/assets/2026-09-15-multi-intent-u3-intentflow-pg/plans-verbose.txt)
|
||||
- [x] 决策 nonce / revision CAS / 过期 — 证据:同上
|
||||
- [x] 两 worker 无双 owner;租约接管;旧 fence 拒绝 — 证据:`TestTwoWorkersOneOwnerAndLeaseTakeover`
|
||||
- [x] receipt 对账不盲跑;环境隔离;legacy HandleTurn 不落盘 — 证据:`TestReceiptWritebackFailureDoesNotRerun` / `TestHandleTurnLegacyDoesNotPersist`
|
||||
- [x] Assemble 接线且 chat 不调用;arch-check 无新例外 — 证据:[short.txt](../../test-reports/assets/2026-09-15-multi-intent-u3-intentflow-pg/short.txt)
|
||||
|
||||
## 完成定义
|
||||
|
||||
- [x] 全部勾选且有证据链接
|
||||
@@ -0,0 +1,19 @@
|
||||
---
|
||||
title: "多意图 HITL U4 outbox checklist"
|
||||
status: done
|
||||
created: 2026-09-16
|
||||
updated: 2026-09-16
|
||||
related_task: "2026-09-16-multi-intent-u4-outbox-projection"
|
||||
---
|
||||
|
||||
# 多意图 HITL U4 outbox checklist
|
||||
|
||||
- [x] 同 UoW Append intent.plan.* — 证据:[emit-verbose.txt](../../test-reports/assets/2026-09-16-multi-intent-u4-outbox-projection/emit-verbose.txt)
|
||||
- [x] golden payload 无敏感字段 — 证据:`testdata/intent-plan-awaiting-v1.json`
|
||||
- [x] 重复/乱序/伪造 producer — 证据:`TestProjectionOnlyForwardAndForgedRejected`
|
||||
- [x] 投影只前进;跨用户隔离 — 证据:同上
|
||||
- [x] dispatcher 语义未改;arch-check 绿 — 证据:[short.txt](../../test-reports/assets/2026-09-16-multi-intent-u4-outbox-projection/short.txt)
|
||||
|
||||
## 完成定义
|
||||
|
||||
- [x] 全部勾选且有证据链接
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
title: "多意图 HITL U5 decision API checklist"
|
||||
status: done
|
||||
created: 2026-09-16
|
||||
updated: 2026-09-16
|
||||
related_task: "2026-09-16-multi-intent-u5-decision-api"
|
||||
---
|
||||
|
||||
# 多意图 HITL U5 decision API checklist
|
||||
|
||||
- [x] 冻结 REST 路径挂到认证 mux — 证据:[http-verbose.txt](../../test-reports/assets/2026-09-16-multi-intent-u5-decision-api/http-verbose.txt)
|
||||
- [x] Principal 不从 body 复制 — 证据:`TestIntentPlanHTTP_IgnoresBodyPrincipalAndSameReceipt`
|
||||
- [x] 非成员/跨作用域/管理员负例 — 证据:`TestIntentPlanHTTP_ScopeNegatives` / `AdminDoesNotBypassMembership`
|
||||
- [x] StepAuthorizer 在 confirm 与 execute 前调用 — 证据:[authorize-verbose.txt](../../test-reports/assets/2026-09-16-multi-intent-u5-decision-api/authorize-verbose.txt)
|
||||
- [x] stale/nonce/edit/非法部分确认 — 证据:同上
|
||||
- [x] arch-check / short 绿 — 证据:[short.txt](../../test-reports/assets/2026-09-16-multi-intent-u5-decision-api/short.txt)
|
||||
|
||||
## 完成定义
|
||||
|
||||
- [x] 全部勾选且有证据链接
|
||||
@@ -0,0 +1,19 @@
|
||||
---
|
||||
title: "多意图 HITL U6 Web checklist"
|
||||
status: done
|
||||
created: 2026-09-16
|
||||
updated: 2026-09-16
|
||||
related_task: "2026-09-16-multi-intent-u6-web-cards"
|
||||
---
|
||||
|
||||
# 多意图 HITL U6 Web checklist
|
||||
|
||||
- [x] PLAN_CONFIRM 类型与 PlanView 映射 — 证据:`web/src/engine/planCard.test.ts`
|
||||
- [x] 决策走 REST,不改 AST — 证据:`planCardTouchesLocalAST` + App early-return
|
||||
- [x] 409/过期/submitting 状态 — 证据:同上
|
||||
- [x] App early-return — 证据:`web/src/App.tsx`
|
||||
- [x] 单元测试绿;Playwright 门控 skip — 证据:[npm-test.txt](../../test-reports/assets/2026-09-16-multi-intent-u6-web-cards/npm-test.txt)
|
||||
|
||||
## 完成定义
|
||||
|
||||
- [x] 全部勾选且有证据链接
|
||||
@@ -0,0 +1,14 @@
|
||||
---
|
||||
title: "U7 auto_read checklist"
|
||||
status: done
|
||||
created: 2026-09-16
|
||||
related_task: "2026-09-16-multi-intent-u7-auto-read"
|
||||
---
|
||||
|
||||
# U7
|
||||
|
||||
- [x] legacy HandleTurn 不落盘
|
||||
- [x] auto_read 查询创建并执行
|
||||
- [x] 写话语不落盘
|
||||
- [x] QueryGuard 拒绝 task.run
|
||||
- [x] chat 调用 HandleTurn;arch 绿
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
title: "U8 task generate checklist"
|
||||
status: done
|
||||
created: 2026-09-16
|
||||
updated: 2026-09-16
|
||||
related_task: "2026-09-16-multi-intent-u8-task-generate"
|
||||
---
|
||||
|
||||
# U8
|
||||
|
||||
- [x] confirm 话语落盘 awaiting,确认前不执行 — 证据:`TestHandleTurnConfirmPersistsAwaitingWithoutExecute`
|
||||
- [x] 第二活动写计划冲突 — 证据:`TestHandleTurnConfirmRejectsSecondActiveWritePlan`
|
||||
- [x] OwnerMux 路由 + nil Task fail closed — 证据:`TestOwnerMuxRoutesGenerateToTask` / `TestOwnerMuxNilTaskFailClosed`
|
||||
- [x] 确认后 generate 一次、重放不双跑 — 证据:`TestConfirmThenMuxExecutesGenerateOnce`
|
||||
- [x] adapter 幂等 / 拒查询 / 撤销 — 证据:`TestTaskRunAdapter*`
|
||||
- [x] LiveTaskStarter 同键重放 — 证据:`TestLiveTaskStarterReplaysIdempotencyKey`
|
||||
- [x] QueryGuard 仍拒 task.run;auto_read 写话语不落盘 — 证据:U7 回归 + `TestQueryGuardRejectsGenerate`
|
||||
- [x] 真实 PI stop-gate — 证据:`TestTaskGenerateRealPIStopGate` SKIP
|
||||
- [x] arch-check block 绿 — 证据:[报告](../../test-reports/2026-09-16-multi-intent-u8-task-generate-test-report.md)
|
||||
|
||||
## 完成定义
|
||||
|
||||
- [x] 全部勾选且有证据链接
|
||||
@@ -0,0 +1,67 @@
|
||||
---
|
||||
title: "意图 mutex 从 Codex 转 Cursor:仅剩浏览器双标签门"
|
||||
created: 2026-09-15
|
||||
from: Codex
|
||||
to: Cursor
|
||||
status: closed
|
||||
---
|
||||
|
||||
# 交接:对话意图运行时状态 — 浏览器双标签门
|
||||
|
||||
## 目标(下一位 Agent 应完成什么)
|
||||
|
||||
在 U11–U12 已合入并 rebuild 的 `:8080` 上,用**新建项目**补齐真实 PI + 双标签 busy / 刷新恢复证据。通过则关 `CHAT-INTENT-STATE` 并 archive;失败则从最新 `dev` 新开 `fix/conversation-intent-dual-tab`,**不要**在已合入的 `fix/conversation-intent-state` 上追加。
|
||||
|
||||
## 已完成
|
||||
|
||||
- Wave 0–4 服务端/单测已在 `dev`(`fix/conversation-intent-state` 是祖先)。
|
||||
- 前端 5s 租约轮询:`web/src/App.tsx`。
|
||||
- `DOC_BUSY` 预检:`internal/server/task_run_handlers.go`(不创建第二 run,`error_info.actions=[]`)。
|
||||
- UI busy 文案:`BlockRenderer` / `DeckDrawer`「编辑中」。
|
||||
- 只读总结真实 PI(用例 H)已签;项目 143 诊断污染未删。
|
||||
|
||||
## 未完成
|
||||
|
||||
- 浏览器刷新恢复与双标签租约可见性(报告用例 E)。
|
||||
- 整改 Wave 3–4 未勾项:运行中刷新、busy 自动解除、并发写不新增 run 的**活验证据**。
|
||||
|
||||
## 认领 / 槽位状态
|
||||
|
||||
| 项 | 值 |
|
||||
|----|-----|
|
||||
| mutex 已释放 | no(`intent` 转 Cursor `in_progress`) |
|
||||
| 集成槽位 holder | idle(U11–U12 已释放;本门禁不占槽,除非要合入 UI 补丁) |
|
||||
| branch | 编码已在 `dev`;活验文档用 `docs/conversation-intent-dual-tab` |
|
||||
| worktree | `.worktrees/fix-conversation-intent-state` **禁止** `env-service` |
|
||||
|
||||
> 用户已要求关掉 CURRENT 两行 `in_progress`,授权 Cursor 接管剩余验收。不覆盖 Codex worktree 未合并代码。
|
||||
|
||||
## 关键文件
|
||||
|
||||
| 路径 | 说明 |
|
||||
|------|------|
|
||||
| `.doc/ops/short-term/2026-09-13-conversation-intent-runtime-state.md` | 任务文 |
|
||||
| `.doc/test-reports/2026-09-13-conversation-intent-runtime-state-test-report.md` | 用例 E 待补 |
|
||||
| `.doc/remediation/2026-09-13-conversation-intent-runtime-state-remediation.md` | Wave 3–4 |
|
||||
| `web/src/App.tsx` | 5s lease 轮询 |
|
||||
| `internal/server/task_run_handlers.go` | DOC_BUSY 预检 |
|
||||
|
||||
## 如何验证
|
||||
|
||||
```bash
|
||||
# 主仓已 rebuild 的 dev,禁止 worktree 内 env-service
|
||||
curl -sf http://127.0.0.1:8080/ready
|
||||
# 新建项目 + 隔离 session;禁止项目 143;禁止 sess-p143-u9 探针
|
||||
```
|
||||
|
||||
## 风险 / Blocker
|
||||
|
||||
- 项目 143 只读:不终止、不改写、不打探针。
|
||||
- 客户端在 lease 已投影后会本地拦截写请求(不发 POST);HTTP 409 须在轮询窗口内或走 API 第二通道取证。
|
||||
- 诊断污染消息仍不擅自删除。
|
||||
|
||||
## 相关链接
|
||||
|
||||
- CURRENT: [CURRENT.md](../CURRENT.md)
|
||||
- Task: [../short-term/2026-09-13-conversation-intent-runtime-state.md](../short-term/2026-09-13-conversation-intent-runtime-state.md)
|
||||
- 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)
|
||||
@@ -0,0 +1,47 @@
|
||||
---
|
||||
title: "选择性模块解耦 M4–M6"
|
||||
status: planned
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-14
|
||||
owner: TBD
|
||||
mutex: architecture
|
||||
review_cycle: milestone
|
||||
---
|
||||
|
||||
# 选择性模块解耦 M4–M6
|
||||
|
||||
## 目标
|
||||
|
||||
在文档可靠性、可靠事件和 FAV 已证明收益后,按 U10–U12 分别收敛 chatlog/contextasm、应用组合根、共享上下文和传输层。
|
||||
|
||||
## 为什么是长期任务
|
||||
|
||||
这些改动不直接修复当前受控正文事实源问题,且会触及仍在进行的 chat/intent 工作。
|
||||
M1–M3 未通过前执行会扩大冲突面,并提前冻结未经真实消费者验证的契约。
|
||||
|
||||
## 触发条件
|
||||
|
||||
- M1–M3 的 test report 全部 PASS。
|
||||
- 同类缺陷触达文件数和运行故障率表明继续解耦具有收益。
|
||||
- `chat`、`intent`、`bizdev/coordinator`、`server/stream` mutex 按子切片释放。
|
||||
- 每个子切片有独立 owner、回滚点和行为验收,不批准一个巨型 Wave。
|
||||
|
||||
## 候选子任务
|
||||
|
||||
1. U10 chatlog/contextasm 原地端口化。
|
||||
2. U11a 唯一 app composition root。
|
||||
3. U11b 按事件逐个替换闭包桥。
|
||||
4. U11c 逐 use case 迁移 ExecuteTask/executeStageInternal。
|
||||
5. U11d UserProjectContext snapshot/update 收权。
|
||||
6. U12 server/SSE 边界和架构门禁收口。
|
||||
|
||||
## 不包含
|
||||
|
||||
- 错误信封统一。
|
||||
- PI Runner result.json 协议。
|
||||
- 微服务拆分。
|
||||
|
||||
## 相关链接
|
||||
|
||||
- [模块解耦整改与重构计划](../../remediation/2026-09-14-module-decoupling-refactor-plan.md)
|
||||
- [模块化单体解耦架构](../../system-design/2026-09-14-module-decoupling-architecture.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,55 @@
|
||||
---
|
||||
title: "H0 HTTP/SSE 公开错误信封盘点"
|
||||
created: 2026-09-15
|
||||
status: done
|
||||
confidence: high
|
||||
---
|
||||
|
||||
# 调研:H0 HTTP/SSE 公开错误信封盘点
|
||||
|
||||
## 结论
|
||||
|
||||
`Server.Routes()` 现有 **122** 条公开路由。错误响应至少三种并存:纯文本 `http.Error`、`{"error","message"}` JSON、以及 SSE `error_info`(`user_message/code/class/request_id`)。前端设置页已按 `error` code 分支,聊天流走 `error_info`;大量文档/任务路由仍回传 `err.Error()`,H1 必须 additive 统一,不能先改状态码。
|
||||
|
||||
## 证据
|
||||
|
||||
| 项 | 路径/命令 | 结果 |
|
||||
|----|-----------|------|
|
||||
| 路由清单 | `internal/server/server.go` `Routes()` | 122 条 `mux.HandleFunc` |
|
||||
| 纯文本/拼接 error | `handlers.go`、`task_run_handlers.go`、`asset_handlers.go`、`sse.go` | `http.Error(w, err.Error(), …)` 会泄露内部原因 |
|
||||
| JSON `{error,message}` | `project_settings_handlers.go`、`project_members_handlers.go`、`auth_helpers.go`、`chatflow_http.go` | 已有 `ERR_*` / `PLAN_FROZEN` 等稳定 code |
|
||||
| SSE | `internal/stream/types.go` `ErrorInfo`;`classify.go` 固定 `UserMessage` | 有 `request_id`;`error` 字符串与 `error_info.user_message` 并存 |
|
||||
| 前端 code 分支 | `web/src/api/projectSettingsError.ts` | `PLAN_FROZEN` / `PLAN_REVISION_CONFLICT` / `ERR_CONCURRENT_SWITCH` |
|
||||
| 前端文案匹配 | `web/src/App.tsx` `detail.includes('无权访问该项目')` | 未知 code 仍靠 substring |
|
||||
|
||||
## 兼容风险
|
||||
|
||||
| 家族 | 代表路由 | 现状 | H1 风险 |
|
||||
|------|----------|------|---------|
|
||||
| 纯文本 | `POST /api/v1/chat`、`POST /api/v1/tasks/runs` | `Content-Type` 非 JSON,正文即 message | 前端若按 JSON 解析会失败;须 additive 保留旧正文或双写 |
|
||||
| JSON error+message | 设置/成员/鉴权 | `error` 当 code | 与目标 `code` 字段同义;H1 应同时输出 `code` 与 `error` |
|
||||
| SSE error_info | `/api/v1/chat/stream`、task stream | 已有 code/class/request_id | 与 HTTP 信封字段名不完全对齐(`user_message` vs `message`) |
|
||||
| 授权拒绝 | `ERR_UNAUTHENTICATED` / `ERR_FORBIDDEN` | 部分 JSON、部分纯文本 | 统一后仍须不泄露资源存在性 |
|
||||
|
||||
## 建议映射(领域 → 目标 wire code)
|
||||
|
||||
| 领域情况 | 目标 code | 备注 |
|
||||
|----------|-----------|------|
|
||||
| 未登录 | `AUTHZ` | 不区分用户是否存在 |
|
||||
| 项目/文档无权 | `AUTHZ` | 与 404 策略保持现有授权选择 |
|
||||
| 参数/校验 | `VALIDATION` | details 只允许公开字段名 |
|
||||
| 版本/修订冲突 | `VERSION_CONFLICT` | 现 `PLAN_REVISION_CONFLICT` 映射 |
|
||||
| 幂等/重复提交 | `IDEMPOTENCY_CONFLICT` | 任务 run 已有 idempotency |
|
||||
| 规划冻结 | `VALIDATION` 或保留 `PLAN_FROZEN` | H3 前不得改状态码 |
|
||||
| 内部错误 | `INTERNAL` | 仅 `request_id`;禁止 SQL/路径/凭证 |
|
||||
|
||||
## 开放问题
|
||||
|
||||
- H1 是否把 SSE `user_message` 与 HTTP `message` 做成别名双写,需实施时定,不阻塞立项。
|
||||
- 状态码 breaking 必须另写 ADR(H3)。
|
||||
|
||||
## 建议动作
|
||||
|
||||
- H1:envelope registry + request ID 中间件;旧 `error` 字段 additive 保留。
|
||||
- 负例:XSS、路径、SQL、token、prompt、跨租户 ID 不得进入 `message`/`details`。
|
||||
- 实施见 [HTTP 信封整改](../../remediation/2026-09-15-http-error-envelope-remediation.md)。
|
||||
@@ -0,0 +1,149 @@
|
||||
---
|
||||
title: "模块解耦与 IPC/RPC 交互现状评估(复核修订版)"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
author: Cline
|
||||
confidence: high
|
||||
---
|
||||
|
||||
# 调研:模块解耦与 IPC/RPC 交互现状评估
|
||||
|
||||
## 结论
|
||||
|
||||
1. 系统采用模块化单体,不应把所有模块调用改成 IPC/RPC。当前已运行的外部传输边界有两条:Web 与 server 的 HTTP/SSE、Go server 与 PI Agent Runner 的 HTTP。`cmd/events` 和 FAV worker 是计划中的独立进程,不是已运行事实。
|
||||
2. 端口、组合根、事件信封、RunManifest、幂等键和 arch-check 提供了可执行的边界基础;`import=0/event=0` 只表示没有超出现有 allowlist/baseline 的新违规,不能证明语义解耦已经完成。
|
||||
3. 首要可靠性缺口是事件“部分生产、没有生产级消费闭环”。`internal/events/pg.go` 尚无原子 lease、ack/fail、retry/dead-letter 的完整实现;现有 dispatcher 测试覆盖 MemoryBus,不是 PostgreSQL 运行证据。
|
||||
4. 最大结构扩散源仍是 bizdev service locator。另有 `docgov → docrevision` 单向 canonical/hash 工具依赖、chat/coordinator 扇出和 `intent → bizdev` 依赖。此前“docgov↔docrevision 双向 import”的结论不成立。
|
||||
5. HTTP 错误信封与 PI Runner typed result 是独立协议债,不应阻塞持久事件链关闭。FAV 分支也不应成为 notify/projection 交付的前置条件。
|
||||
|
||||
## 1. 通信边界
|
||||
|
||||
| 边界 | 机制 | 当前状态 |
|
||||
|---|---|---|
|
||||
| Web ↔ server | `/api/v1/*` HTTP + SSE | 已运行;错误信封仍未统一 |
|
||||
| Go ↔ PI Agent Runner | HTTP + Bearer;health/run/cancel/search | 已运行;结果仍依赖 legacy stdout/result.json 路径 |
|
||||
| 单体内模块 | 消费者端口 + `internal/app` 组合根 | 已运行;bizdev locator 和部分直依赖仍扩大改动面 |
|
||||
| 领域事件 | PG envelope/delivery schema | 写侧部分存在;生产 dispatcher 未闭环 |
|
||||
| `cmd/events` | 计划中的独立 worker | 尚未实现/部署 |
|
||||
| FAV worker | 独立审计轨道 | 分支未整支合入;不得作为本轮验收前置 |
|
||||
|
||||
不建议把单体内端口改成 RPC。那会增加序列化、延迟、部分失败与运维成本,却不消除当前 locator、授权、幂等和事件消费缺口。
|
||||
|
||||
## 2. 已有契约与真实边界
|
||||
|
||||
### 已有且可校验
|
||||
|
||||
- `.doc/system-design/module-boundaries.yaml` 与 `internal/archtest` 管理 import、SQL write、path 和 event 规则。
|
||||
- `events.Envelope` schema 1 包含 event/aggregate/correlation/causation/idempotency/digest/producer 等字段,并校验 digest 与敏感字段。
|
||||
- `taskrun.RunManifest` schema 1 使用 canonical JSON 与 SHA-256。
|
||||
- TaskRun 同 idempotency key 异 request digest 返回冲突;文档写使用 expected head/ETag。
|
||||
- backend 选择由服务端 allowlist 控制,出站数据经过 secret stripping。
|
||||
- `module-boundaries.yaml` 已有 `event_producers` 与 `event_consumers` 段。后续工作是补全并校验 runtime registry parity,不是新建段落。
|
||||
|
||||
### 尚未闭合
|
||||
|
||||
- `PGSink.Append`/`InsertEnvelope` 已存在,但 `ClaimIDs` 仍是 SELECT-only claim;没有生产级 lease 获取、heartbeat、fenced ack/fail、retry、dead-letter 和 immutable attempt audit 闭环。
|
||||
- `event_deliveries` 每个 event/consumer 一行,只保存当前状态和累计 attempt;无法还原每次 lease/attempt 历史。
|
||||
- `internal/events/replay.go` 只检查 dry-run 与 consumer/operator/reason 等基础字段,尚未形成带认证主体、env/project/event scope、plan digest 和 apply 审计的应用用例。
|
||||
- `docflow` envelope 仍存在 `Environment:"dev"`、`ProjectID:0`,且 `Fav.StageAgentCommit(ctx, 0, ...)` 使用错误项目作用域。
|
||||
- 部分 server 路径临时构造 `docflow.Commands`,没有稳定注入 EventSink/UoW;不能假设 candidate-ready、downstream-impact、approved 三条链已经产生可供 shadow 的事件。
|
||||
- 闭包 hook 没有版本、重试、delivery 或 replay 记录。
|
||||
|
||||
## 3. 耦合点
|
||||
|
||||
### 3.1 bizdev service locator
|
||||
|
||||
`bizdev.Service` 暴露 `Pool()/CAS()/DocGov()/DocRevision()/ProjectWorkflow()/FreeformDoc()/KB()/ContextManager()`。调用方可以绕过端口取得数据库池和其他模块实现,令签名或构造变化向多包扩散。
|
||||
|
||||
整改应先加 no-new-callers 门禁,再逐调用方迁移,最后在一个 contract 提交删除 8 个 getter。门禁应禁止领域/用例 API 暴露或转发 pool/tx,同时允许 app/cmd 组合根向表属主构造器注入 pool,并允许登记属主从 opaque TxScope 解出 tx。
|
||||
|
||||
### 3.2 docgov 到 docrevision 的单向工具依赖
|
||||
|
||||
生产依赖方向是 `docgov → docrevision`。直接用途集中在 Markdown canonicalization 与 SHA helper;`docrevision` 不生产 import `docgov`。
|
||||
|
||||
目标不是“破双向环”,而是把 canonical Markdown + digest 提取为有行为、内聚、带 golden vectors 的共享模块,例如 `internal/doccontent`。它不应进入只放无行为值对象的 vocabulary。
|
||||
|
||||
### 3.3 chat、coordinator 与 intent
|
||||
|
||||
- coordinator 仍以 `bizdev.TaskRunRequest/Result` 为词汇。
|
||||
- chat 编排跨多个模块,需按用例逐批迁入 chatflow。
|
||||
- intent 与 bizdev 的解绑是较小且独立的迁移,不应和 chat 大迁移绑成一个分支。
|
||||
|
||||
### 3.4 闭包桥与未接线事件
|
||||
|
||||
当前批准后的推进与通知仍可通过 `docrevision.OnOutbox`、`docgov.AddOnApprovedHook` 及组合根闭包执行。闭包在提交后的进程内调用不能提供 durable delivery、重试、dead-letter、replay 或 attempt audit。
|
||||
|
||||
不能直接删除闭包。正确顺序是:
|
||||
|
||||
1. 证明生产入口在同一 UoW 写入领域变化、envelope 和目标 delivery。
|
||||
2. 对历史事件做 dry-run inventory,隔离 scope/schema/sequence 异常。
|
||||
3. 完成真实 PG dispatcher。
|
||||
4. shadow 只计算 intended outcome,不执行业务副作用。
|
||||
5. 以时间、样本和状态分支覆盖作为切换门。
|
||||
6. 按 notify、workflow advance、projection 独立切换和回滚。
|
||||
|
||||
## 4. 并发、数据与权限风险
|
||||
|
||||
### 并发
|
||||
|
||||
- `FOR UPDATE SKIP LOCKED` 只有在 claim 事务同时更新 lease owner/token/until 并 RETURNING 时才完成所有权转移;当前 SELECT-only `ClaimIDs` 不够。
|
||||
- Fencing 不能只保护 ack。token 必须进入 consumer command,并在数据库副作用或 projection marker 的最终提交点校验。heartbeat 失败应取消 handler。
|
||||
- 同一 consumer/aggregate 最多一个 inflight;不同 aggregate 并行。领域版本可能稀疏,不能直接当无缺口事件序号。
|
||||
- at-least-once delivery 通过 inbox/唯一键/CAS/no-replace 得到 exactly-one visible outcome;不能声称 delivery 本身 exactly once。
|
||||
|
||||
### 历史数据
|
||||
|
||||
旧记录可能含 project 0、错误 environment、未知 consumer、未知 payload schema 或稀疏 aggregate version。启用 live claim 前必须生成 manifest,并分类 safe/repair/quarantine/expire。任何修复保留 old/new digest、operator、reason、approval;本计划不删历史数据。
|
||||
|
||||
### 权限
|
||||
|
||||
后台 consumer 使用按 env/consumer/action 约束的 service principal。处理事件时按 ProjectID/DocID 重读资源归属、成员/duty、workflow config revision、活动 stage 和当前状态。事件 actor 只用于审计,不能把历史用户权限带到延迟执行时。
|
||||
|
||||
Replay 必须是应用用例:管理员 capability、精确范围、reason/approval、dry-run plan digest、apply exact digest 和不可变审计。多项目或批量 apply 需要操作者与批准人分离。
|
||||
|
||||
日志、dead-letter 和 reconciliation 只能保存 ID、digest、typed error code 与字段 allowlist 生成的摘要,不能保存原始 payload、正文、SQL error、绝对路径、token 或 prompt。
|
||||
|
||||
## 5. 优先级建议
|
||||
|
||||
### P0:Track E 持久事件交付
|
||||
|
||||
1. 修正 docflow 生产入口、env/project 作用域和 UoW 原子写。
|
||||
2. 补全既有 event allowlist 与 runtime registry parity。
|
||||
3. 审计历史事件、sequence/checkpoint 模型和现有唯一约束。
|
||||
4. 实现 `cmd/events` 的 PG lease/heartbeat/fencing/attempt/dead-letter。
|
||||
5. notify、workflow advance、projection 逐个 shadow、live、回滚。
|
||||
6. 用真实 browser + PG + worker restart 证明刷新后正文恢复,无 projection-missing。
|
||||
|
||||
### P1:Track S 结构解耦
|
||||
|
||||
- D4:bizdev locator 调用方迁移与最终 getter 原子删除。
|
||||
- D5:stageflow 自有 use-case 类型,coordinator 解绑 bizdev DTO。
|
||||
- D6:提取 doccontent canonical 行为模块,移除单向工具依赖。
|
||||
- D7a:intent 单独解绑 bizdev。
|
||||
- D7b:chat 按用例迁入 chatflow。
|
||||
|
||||
这些单元分别 go/no-go,不作为事件可靠性 blocker 的关闭条件。
|
||||
|
||||
### P2:Track P 独立协议
|
||||
|
||||
- HTTP/SSE 错误信封另立 remediation;公开 details 必须按 code allowlist 并脱敏。
|
||||
- PI Runner 任务命名为 typed-result-v1 rollout,不混称“协议 v2”。typed 字段存在但无效时 fail closed;只有字段缺失且握手声明旧 Runner 时才允许 legacy。
|
||||
|
||||
## 6. 证据索引
|
||||
|
||||
| 事实 | 证据 |
|
||||
|---|---|
|
||||
| 模块化单体决策 | `.doc/adr/2026-09-14-modular-monolith-decoupling.md` |
|
||||
| PG delivery 当前实现 | `internal/events/pg.go`、`deploy/postgres/goose/00035_2026-09-14-durable-event-delivery.sql` |
|
||||
| MemoryBus 测试边界 | `internal/events/dispatcher_test.go`、`internal/events/bus.go` |
|
||||
| replay 当前校验 | `internal/events/replay.go` |
|
||||
| 事件字段硬编码 | `internal/app/docflow/commands.go` |
|
||||
| 闭包桥 | `internal/app/docnotify/subscriber.go`、`internal/docgov/engine.go`、`internal/app/app.go` |
|
||||
| bizdev locator | `internal/bizdev/service.go:229-260` |
|
||||
| 单向 canonical 依赖 | `internal/docgov/lease.go`、`internal/docrevision` canonical helper |
|
||||
| allowlist 已存在 | `.doc/system-design/module-boundaries.yaml` |
|
||||
|
||||
## 建议动作
|
||||
|
||||
下一项只立 Track E 的 E0A:事件生产、契约与历史数据门。Dispatcher 必须保持 off,直到 PG 测试证明事件源和旧数据分类正确。完整执行计划见 [Phase 2 持久事件交付与后续解耦路线](../../remediation/2026-09-15-module-decoupling-ipc-phase2-remediation-plan.md)。
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
title: "P0 PI Runner typed-result 兼容矩阵"
|
||||
created: 2026-09-15
|
||||
status: done
|
||||
confidence: high
|
||||
---
|
||||
|
||||
# 调研:P0 PI Runner typed-result 兼容矩阵
|
||||
|
||||
## 结论
|
||||
|
||||
当前 `/v1/run` 远程响应与本地 bridge stdout **都不是** `result_v1`。Go 只解析 `ok/fallback_reason/stderr/retryable/patches[]`;成功路径再 `MaterializeTargets`。仓库里没有 `configs/schemas/pi-run-result-v1.json`。typed 字段一旦出现但非法必须 fail closed;本盘点确认 legacy 窗口仍是默认路径。
|
||||
|
||||
## 证据
|
||||
|
||||
| 项 | 路径/命令 | 结果 |
|
||||
|----|-----------|------|
|
||||
| 远程调用 | `internal/agent/piagent.go` `executeRemote` | `POST {runnerURL}/v1/run`;Bearer via `ApplyRunnerAuth` |
|
||||
| 远程解码 | 同上 `remoteResp` | `ok`, `fallback_reason`, `stderr`, `retryable`, `patches[].rel_path/content` |
|
||||
| 本地 bridge | `PiAgentBackend.Execute` | stdin JSON payload;stdout **最后一行** JSON;失败把 `stderr` 拼进 `ErrorReason` |
|
||||
| 产物 | `MaterializeTargets(workDir, req.Targets, incoming)` | 默认 target `output.md` |
|
||||
| 既有 schema | `configs/schemas/` | 仅 `change-report-v1.json`,无 run-result |
|
||||
| 取消/超时 | `CommandContext` + `http.Client{Timeout}` | 超时进 `ErrorReason`;无单调终态结构体 |
|
||||
| Handshake | 无 | 未声明 typed capability,故今日全部算旧 Runner |
|
||||
|
||||
## 兼容矩阵
|
||||
|
||||
| Runner 形态 | 成功输出 | 失败输出 | Go 行为 | P1/P2 约束 |
|
||||
|-------------|----------|----------|---------|------------|
|
||||
| 远程 HTTP `/v1/run` | `ok=true` + patches | `ok=false` + fallback/stderr | 解码失败即失败;不读 `result_v1` | P1 additive 加 `result_v1`;P2 typed-present-invalid 禁止 fallback |
|
||||
| 本地 bridge 二进制 | stdout 末行 `{ok}` | `ok=false` 或进程 err | 整段 stdout 进 `Logs` | Logs 不得含 prompt/token;P1 后 Logs 只留 digest |
|
||||
| stub | 内存产物 | 分类失败 | 测试夹具 | 不作为真实 PI 证据 |
|
||||
| 未知 major / 缺 schema | — | — | 今日不会发生 | P2 fail closed |
|
||||
|
||||
## 体积与路径风险
|
||||
|
||||
- patches `Content` 无 body/member 上限;P1 必须在分配前限制。
|
||||
- `RelPath` 未在 adapter 层拒绝 `..` / 绝对路径(依赖 `MaterializeTargets`);P1 负例要覆盖 symlink escape。
|
||||
- `ErrorReason` 拼接 `stderr`,可能带模型/路径;公开日志禁止原样落盘。
|
||||
|
||||
## 取消与竞争
|
||||
|
||||
- HTTP client timeout 与 context cancel 共用;无独立 cancel token 与 result 的 CAS。
|
||||
- P3 真实 PI E2E 必须覆盖:成功、typed error、取消、超时、未知 schema。
|
||||
|
||||
## 开放问题
|
||||
|
||||
- 真实容器内 Runner 镜像版本与是否已能吐 `result_v1` 需 P1 时对一下 pi-agent 镜像,不阻塞立项。
|
||||
|
||||
## 建议动作
|
||||
|
||||
- P1:共享 JSON Schema `configs/schemas/pi-run-result-v1.json`;Runner additive 输出。
|
||||
- P2:Go typed-first parser;handshake 声明旧 Runner 才允许 legacy。
|
||||
- 实施见 [PI typed-result-v1](../../remediation/2026-09-15-pi-typed-result-v1-remediation.md)。
|
||||
@@ -0,0 +1,35 @@
|
||||
---
|
||||
title: "Track E 持久事件交付复盘"
|
||||
created: 2026-09-15
|
||||
status: done
|
||||
confidence: high
|
||||
---
|
||||
|
||||
# 调研:Track E 持久事件交付复盘
|
||||
|
||||
## 结论
|
||||
|
||||
E0A–E1C 已在隔离库证明:领域变化、envelope、delivery 同 UoW;PG dispatcher 原子 lease/fencing;notify / workflow_advance / projection 各自 exactly-one visible outcome。共享集群消费者保持 **off**,HTTP 闭包仍是唯一真实写者。E2 已部署兼容守卫:消费者 `live` 时闭包停写,`off`/`shadow` 时闭包继续写。删除 `OnOutbox` / `AddOnApprovedHook` 必须等 live 发布窗口;当前删除会让 notify/advance 停写。`DOC-RELIABILITY-PILOT` 保持 OPEN。FAV 保持 disabled。
|
||||
|
||||
## 证据
|
||||
|
||||
| 项 | 路径/命令 | 结果 |
|
||||
|----|-----------|------|
|
||||
| E0A | [E0A 报告](../../test-reports/2026-09-15-event-e0a-production-scope-contract-test-report.md) | PASS;dispatcher off;FAV 不写入 |
|
||||
| E0B | [E0B 报告](../../test-reports/2026-09-15-event-e0b-dispatcher-pg-test-report.md) | PASS;1/2/4 worker;旧 token 失败 |
|
||||
| E1A | [E1A 报告](../../test-reports/2026-09-15-event-e1a-notify-cutover-test-report.md) | 隔离库 unique notify PASS;共享 off |
|
||||
| E1B | [E1B 报告](../../test-reports/2026-09-15-event-e1b-workflow-advance-test-report.md) | 隔离库 unique stage-ready PASS;共享 off |
|
||||
| E1C | [E1C 报告](../../test-reports/2026-09-15-event-e1c-projection-test-report.md) | no-replace PASS;共享 off |
|
||||
| E2 | [E2 报告](../../test-reports/2026-09-15-event-e2-hook-guard-test-report.md) | live 停写;off/shadow 仍写;API 保留 |
|
||||
|
||||
## 开放问题
|
||||
|
||||
- 共享环境尚未做 notify/advance/projection 的 live 切换与授权页刷新纵切,因此 Track E DoD 中「生产注册无 OnOutbox=」与「授权 UI 三类重启」未关闭。
|
||||
- 历史 inventory 的 repair/quarantine 真实批量审批未在共享库演练。
|
||||
- FAV 仍只预留 disabled 契约。
|
||||
|
||||
## 建议动作
|
||||
|
||||
- 下一窗口:按消费者独立 shadow coverage → drain → live,闭包因 E2 守卫自动停写;确认 backlog 与 receipt 后再删 hook API。
|
||||
- Track S 从 D6(`internal/doccontent`)开始,不占用 events mutex。
|
||||
- Track P 保持独立 remediation,不阻塞事件交付。
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
title: "文档可靠性 M1 活验签字与条件 M2"
|
||||
status: done
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-14
|
||||
owner: Cursor
|
||||
branch: refactor/document-reliability-pilot
|
||||
worktree: .worktrees/refactor-document-reliability-pilot
|
||||
mutex: workspace
|
||||
---
|
||||
|
||||
# 文档可靠性 M1 活验签字与条件 M2
|
||||
|
||||
## 目标
|
||||
|
||||
占集成槽把试点合入本地 `dev` 并 rebuild,补齐真实 PI / 浏览器 / 跨用户 / 多会话签字。仅当新报告最后一句为「继续 M2」时开工 U5–U7。
|
||||
|
||||
## 范围
|
||||
|
||||
- A1 占槽、合入、rebuild、health/ready
|
||||
- A2 143 只读 + 新建项目页面 + fail-closed
|
||||
- A3 真实 pi-agent 编制后刷新
|
||||
- A4 隔离库双 pool / 4 会话
|
||||
- A5 活验 go/no-go
|
||||
- B 仅 go 后:U5–U7
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不终止项目 143
|
||||
- 未 go 不开 outbox/FAV
|
||||
- 不拆 chat/squad
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 占集成槽并合入本地 dev rebuild
|
||||
2. [x] 浏览器 + 跨用户
|
||||
3. [x] 真实 PI
|
||||
4. [x] 双 pool/4 会话
|
||||
5. [x] 活验报告(最后一句:继续 M2)
|
||||
6. [x] 条件 M2(U5–U7)
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] health + ready 来自本分支镜像
|
||||
- [x] 143/新项目刷新 404/409/projection-missing = 0 或报告停止扩面
|
||||
- [x] 报告最后一句只能是继续 M2 或停止扩面
|
||||
- [x] M2 报告最后一句只能是继续 M3 或停止扩面
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Checklist: [../checklists/2026-09-14-module-decoupling-refactor-acceptance.md](../checklists/2026-09-14-module-decoupling-refactor-acceptance.md)
|
||||
- Prior report: [../../test-reports/2026-09-14-document-reliability-pilot-test-report.md](../../test-reports/2026-09-14-document-reliability-pilot-test-report.md)
|
||||
- Live report: [../../test-reports/2026-09-14-document-reliability-pilot-live-test-report.md](../../test-reports/2026-09-14-document-reliability-pilot-live-test-report.md)
|
||||
- M2 report: [../../test-reports/2026-09-14-document-reliability-m2-test-report.md](../../test-reports/2026-09-14-document-reliability-m2-test-report.md)
|
||||
@@ -0,0 +1,64 @@
|
||||
---
|
||||
title: "文档可靠性纵向试点 M0–M1"
|
||||
status: blocked
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-14
|
||||
owner: Cursor
|
||||
branch: refactor/document-reliability-pilot
|
||||
worktree: .worktrees/refactor-document-reliability-pilot
|
||||
mutex: docgov
|
||||
---
|
||||
|
||||
# 文档可靠性纵向试点 M0–M1
|
||||
|
||||
## 目标
|
||||
|
||||
在不横向搬包的前提下,完成 U1–U4,使受控文档在并发提交、页面刷新、重登、restart、rebuild 和 projection 缺失后仍从数据库账本返回唯一授权正文。
|
||||
|
||||
## 范围
|
||||
|
||||
- U1 架构基线与 production writer/path 门禁。
|
||||
- U2 应用 UnitOfWork 和跨属主事务能力。
|
||||
- U3 人工编辑、agent commit、批准/驳回事务化。
|
||||
- U4 授权后的文档统一读模型。
|
||||
- 项目 143 等价脱敏 hazard 与新项目真实 PI/UI 验收。
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不启用 FAV degraded read。
|
||||
- 不拆 chatlog/contextasm/squadrun 包。
|
||||
- 不统一错误信封,不修改 PI Runner 协议。
|
||||
- 不清理历史 dev 数据。
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 从最新 `dev`(`a8f9451`)创建实现分支,登记 CURRENT 并确认 `docgov` mutex 已释放。
|
||||
2. [x] U1:四类规则 arch-check + archtest + 可重放基线(新违规 block)。
|
||||
3. [x] 实现 U2,验证任意属主写入/commit 故障整体回滚。
|
||||
4. [x] 实现 U3,删除提交后 outbox 正确性回调。
|
||||
5. [x] 实现 U4,保证 GET 零写入和 projection 缺失不再伪装成 404。
|
||||
6. [x] 隔离库 PG + 目标包 race 已跑;真实 PI / 浏览器 / rebuild **未**签字(未占槽)。
|
||||
7. [x] 写 test report:结论 **停止扩面**。更新验收清单、FEATURE-MATRIX、CURRENT 和 gap-matrix。
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 同一 ETag 并发编辑只有一个合法赢家(内存 8 协程 + 隔离库双会话)。
|
||||
- [x] 任一事务故障点不会留下部分提交(U2 隔离库)。
|
||||
- [ ] 项目 143 等价 hazard 和新项目刷新/重启目标 404/409/projection missing 为 0(真实页面未测)。
|
||||
- [x] 服务端匿名/未知文档/跨项目/错误责任人 fail closed;浏览器跨登录未测。
|
||||
- [ ] 1、2、4 个 app 实例的最终状态一致(仅到双会话)。
|
||||
- [x] M1 test report 结论:**停止扩面**。
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Checklist: [../checklists/2026-09-14-module-decoupling-refactor-acceptance.md](../checklists/2026-09-14-module-decoupling-refactor-acceptance.md)
|
||||
- Test report: [../../test-reports/2026-09-14-document-reliability-pilot-test-report.md](../../test-reports/2026-09-14-document-reliability-pilot-test-report.md)
|
||||
- Plan: [../../remediation/2026-09-14-module-decoupling-refactor-plan.md](../../remediation/2026-09-14-module-decoupling-refactor-plan.md)
|
||||
|
||||
## M2+ 门(不开工)
|
||||
|
||||
U5 WorkspaceRef、U6 outbox、U7 按文件摘 FAV 需要独立审批,且仅当 M1 报告最后一句为「继续 M2」。当前是「停止扩面」,禁止实现 U5–U12。
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
隔离库与目标包 race 见 test-report assets。未占槽、未 rebuild。只有真实 PI/浏览器/rebuild 补测并把报告改为「继续 M2」后,才允许启动 durable event/FAV。
|
||||
@@ -0,0 +1,105 @@
|
||||
---
|
||||
title: "多意图持久计划与 HITL(核心 U1–U8,扩面 U9–U12)"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-16
|
||||
owner: Cursor
|
||||
branch: "-"
|
||||
worktree: "-"
|
||||
mutex: "-"
|
||||
---
|
||||
|
||||
# 多意图持久计划与 HITL(核心 U1–U8,扩面 U9–U12)
|
||||
|
||||
## 目标
|
||||
|
||||
不回退现有模块解耦、单意图行为和权限边界,交付可持久、可恢复、可并发裁决的 2–4 步计划;所有批量生成/写入/控制确认前零副作用,执行前逐动作重新授权。
|
||||
|
||||
## 权威文档
|
||||
|
||||
- [详细设计与计划](../../system-design/2026-09-15-multi-intent-hitl-plan.md)
|
||||
- [复核审计](../../audit/2026-09-15-multi-intent-hitl-plan-review.md)
|
||||
- [模块边界 SSOT](../../system-design/module-boundaries.yaml)
|
||||
|
||||
## 强制约束
|
||||
|
||||
- `internal/intent` 继续只依赖 `maturity`;新生命周期归 `internal/app/intentflow`;
|
||||
- 确认不是授权;每步由动作 owner 按当前主体、状态和版本重新鉴权;
|
||||
- PG plan state 权威,卡片/SSE 仅投影;
|
||||
- 每步一个业务事务,不做跨模块长事务;
|
||||
- 中间结果不进 FAV;
|
||||
- 新行为从 legacy/shadow 开始,回滚不丢已有计划。
|
||||
|
||||
## 波次
|
||||
|
||||
| 波次 | 单元 | 交付 | 依赖 | 主 mutex | go/no-go |
|
||||
|------|------|------|------|----------|----------|
|
||||
| W0 | U1 | 模块/API/状态/事件契约 | 无 | `intent`,`events` | arch/event/table owner 全绿 |
|
||||
| W1 | U2 | 纯规则提案 shadow | U1 | `intent` | 不改路由,安全错误为 0 |
|
||||
| W2 | U3 | intentflow + PG/CAS/lease | U1,U2 | `intent-plan` | 两 worker 无双 owner/执行 |
|
||||
| W2 | U4 | outbox + 投影 | U3 | `events` | projection diff=0 |
|
||||
| W3 | U5 | decision API + 授权端口 | U3 | `intent-plan`,`server/authz` | 权限负例全绿 |
|
||||
| W3 | U6 | Web 卡片/刷新/a11y | U4,U5 | `web` | 双标签/reload 无假成功 |
|
||||
| W4 | U7 | 低风险只读执行 | U4-U6 | `intent-plan`,`chat` | legacy 无回归 |
|
||||
| W4 | U8 | task generate adapter | U7 | `taskrun`,`intent-plan` | 首版 real PI 闭环 |
|
||||
| W5 | U9 | 可选 LLM adapter 实验 | U2,U7 | `intent-plan`,`pi-agent` | 不阻塞首版;达阈值才启用 |
|
||||
| W5+ | U10 | low mutate 逐 action 扩面 | U8 | 实际 owner | 单 action 签署 |
|
||||
| W5+ | U11 | docgov 逐 action 扩面 | U8 | `docgov`,`intent-plan` | 单 action 签署 |
|
||||
| W5+ | U12 | workflow/run-control 分项扩面 | U8 | `workflow`/`taskrun` | 分项签署 |
|
||||
|
||||
> 本文件仅是总览,不长期占用一个 mutex。实施时每个 U-ID 新建独立 short-term、分支和认领;U10–U12 还必须按 action 拆分。核心首版为 U1–U8,U9 与后续 owner 扩面不阻塞首版关闭。
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] U1 冻结边界、状态机、批量策略、错误码、事件和默认 legacy tier([独立任务](./2026-09-15-multi-intent-u1-contracts.md);[报告](../../test-reports/2026-09-15-multi-intent-u1-contracts-test-report.md));
|
||||
2. [x] U2 characterization-first 建 golden/hard-negative 与 shadow 基线([独立任务](./2026-09-15-multi-intent-u2-segmenter.md);[报告](../../test-reports/2026-09-15-multi-intent-u2-segmenter-test-report.md));
|
||||
3. [x] U3 建 intentflow owner、PG schema、CAS/lease/fencing/retention([独立任务](./2026-09-15-multi-intent-u3-intentflow-pg.md);[报告](../../test-reports/2026-09-15-multi-intent-u3-intentflow-pg-test-report.md));
|
||||
4. [x] U4 接 Track E outbox/dispatcher,只投影状态事实([独立任务](./2026-09-16-multi-intent-u4-outbox-projection.md);[报告](../../test-reports/2026-09-16-multi-intent-u4-outbox-projection-test-report.md));
|
||||
5. [x] U5 建统一 decision command 与动作 owner 授权端口([独立任务](./2026-09-16-multi-intent-u5-decision-api.md);[报告](../../test-reports/2026-09-16-multi-intent-u5-decision-api-test-report.md));
|
||||
6. [x] U6 取消计划动作的前端本地成功路径,以 PlanView 恢复([独立任务](./2026-09-16-multi-intent-u6-web-cards.md);[报告](../../test-reports/2026-09-16-multi-intent-u6-web-cards-test-report.md));
|
||||
7. [x] U7 只开放独立低风险查询([独立任务](./2026-09-16-multi-intent-u7-auto-read.md);[报告](../../test-reports/2026-09-16-multi-intent-u7-auto-read-test-report.md));
|
||||
8. [x] U8 只接 task generate,完成首版闭环(真实 PI 环境缺失记 stop-gate)([独立任务](./2026-09-16-multi-intent-u8-task-generate.md);[报告](../../test-reports/2026-09-16-multi-intent-u8-task-generate-test-report.md));
|
||||
9. [ ] U9 作为独立可选实验接语义分段;
|
||||
10. [ ] U10–U12 分别按 mutate/docgov/workflow/run-control owner 扩面。
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [ ] 含写/生成/控制时,确认前相关表、任务、文档和工作流零变化;
|
||||
- [ ] 两标签确认/取消只产生一个决策和至多一次动作;
|
||||
- [ ] 服务/worker 重启后 PG 恢复,成功步骤不重跑;
|
||||
- [ ] 确认后权限或资源版本变化时 fail closed;
|
||||
- [ ] 跨用户/项目/会话读取和决策被隐藏;
|
||||
- [ ] 按钮与自然语言确认得到同一服务端 receipt;
|
||||
- [ ] intent 边界、单一写者、UoW、事件静态契约和组合根无回退;
|
||||
- [ ] 无活动计划时单意图生成保持;有活动计划时不创建第二任务;多意图生成需确认;
|
||||
- [ ] 部分确认可稍后处理未选项,只有显式排除才取消;部分完成可重试、继续或关闭;
|
||||
- [ ] 双标签/刷新/重开/SSE 重连真实页面通过;
|
||||
- [ ] 适用的真实 PI E2E 通过,stub 不冒充验收。
|
||||
|
||||
## 非目标
|
||||
|
||||
- >4 步、并行 DAG、多活动写计划自动合并;
|
||||
- 跨步骤 ACID/自动补偿;
|
||||
- coordinator/chat 全量重构;
|
||||
- FAV 启用或中间产物归档;
|
||||
- 改变单意图生成策略。
|
||||
|
||||
## 交付纪律
|
||||
|
||||
- 每单元记录精确边界影响、适用测试、go/no-go、回滚、branch/commit/merge/push 状态;
|
||||
- 每单元独立 test report、CURRENT 认领/集成槽和 FEATURE-MATRIX 回链;
|
||||
- 安全、越权、双执行或刷新差异任一出现,停止当前 tier;dispatcher 故障只停投影;LLM 故障进入澄清。
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Checklist: [U1](../checklists/2026-09-15-multi-intent-u1-contracts.md);[U2](../checklists/2026-09-15-multi-intent-u2-segmenter.md);[U3](../checklists/2026-09-15-multi-intent-u3-intentflow-pg.md);[U8](../checklists/2026-09-16-multi-intent-u8-task-generate.md)
|
||||
- Handoff: 每个 U-ID 独立建立
|
||||
- Test report: [U1](../../test-reports/2026-09-15-multi-intent-u1-contracts-test-report.md);[U2](../../test-reports/2026-09-15-multi-intent-u2-segmenter-test-report.md);[U3](../../test-reports/2026-09-15-multi-intent-u3-intentflow-pg-test-report.md);[U4](../../test-reports/2026-09-16-multi-intent-u4-outbox-projection-test-report.md);[U5](../../test-reports/2026-09-16-multi-intent-u5-decision-api-test-report.md);[U6](../../test-reports/2026-09-16-multi-intent-u6-web-cards-test-report.md);[U7](../../test-reports/2026-09-16-multi-intent-u7-auto-read-test-report.md);[U8](../../test-reports/2026-09-16-multi-intent-u8-task-generate-test-report.md)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
- 当前 `plan_builder.go` 最多两段且写意图返回 nil;`action_planner.go` 的确认仍是文字提示。
|
||||
- 当前 `module-boundaries.yaml` 中 intent 仅依赖 maturity;Track E live,FAV off。
|
||||
- U1 已冻结 intentflow 契约、事件与 BatchActionPolicy,默认 `MULTI_INTENT_PLAN_TIER=legacy`。
|
||||
- U2 已落地规则分段与 shadow `PlanProposal`;生产 TopIntent / IntentPlan 不变;反事实 `false_auto_execute=0`。
|
||||
- U8 已落地 confirm 落盘与 `task.run` adapter;默认 legacy 不落盘。U9–U12 不阻塞核心首版。共享环境 schema 45 待晋升窗口。
|
||||
@@ -0,0 +1,76 @@
|
||||
---
|
||||
title: "多意图 HITL U1:契约冻结"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
owner: Cursor
|
||||
branch: feature/multi-intent-u1-contracts
|
||||
worktree: "-"
|
||||
mutex: architecture-docs
|
||||
---
|
||||
|
||||
# 多意图 HITL U1:契约冻结
|
||||
|
||||
## 目标
|
||||
|
||||
冻结 `app/intentflow` 边界、状态机、BatchActionPolicy、错误码、事件契约与默认 `legacy` tier;不改识别路由、不建表、不接 HTTP。
|
||||
|
||||
## 范围
|
||||
|
||||
- `module-boundaries.yaml`:`app/intentflow` allowlist、三表 owner、`unwrap_owners`、三条 `intent.plan.*` 事件
|
||||
- `events.StaticContracts` 与 YAML 对等;archtest 扫描 `intent.plan.*`
|
||||
- `internal/app/intentflow` 骨架:状态、错误码、Service 端口、政策、tier 开关
|
||||
- CSRF/认证结论:现有 Bearer + CORS 对 U5 足够,不是 blocker
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不修改 `internal/intent` 业务类型或 `MULTI_INTENT_ENABLED`
|
||||
- 不建 Goose 表、不接线 `app.Assemble`、不改 chat/coordinator/Web
|
||||
- 不 Append 事件、不实施 U2–U12
|
||||
|
||||
## REST(U5 再挂路由)
|
||||
|
||||
- `GET /api/v1/intent-plans/active`
|
||||
- `GET /api/v1/intent-plans/{plan_id}`
|
||||
- `POST /api/v1/intent-plans/{plan_id}/decisions`
|
||||
- body:`expected_revision`、`decision_nonce`、`decision_digest`、`kind`、步骤选择
|
||||
|
||||
## CSRF / 认证(U5 前置结论,非 blocker)
|
||||
|
||||
现有认证是 `Authorization: Bearer` 或 `X-Session-Token` 请求头(`internal/server/auth_handlers.go`),无 cookie 会话,无独立 CSRF 中间件;另有 Origin allowlist CORS。
|
||||
|
||||
- 自定义头不会被浏览器跨站表单自动带上,现有模式对 U5 足够
|
||||
- `decision_nonce` / 幂等键只防重放与并发,**不替代** CSRF 或身份认证
|
||||
- U5 必须 `requireAuthenticatedUser` + 四元作用域(environment/project/session/user)
|
||||
- **禁止**为计划 API 改成 cookie 自动提交
|
||||
- 若未来改 cookie 认证,另立 auth 任务,不得在 intent-plan 端点发明弱 CSRF
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 从最新 `dev` 检出 `feature/multi-intent-u1-contracts` 并认领 CURRENT
|
||||
2. [x] 登记边界 YAML、事件契约、archtest regex
|
||||
3. [x] 落地 intentflow 骨架与 BatchActionPolicy
|
||||
4. [x] arch/parity/short 测试与 U1 报告
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] `intent -> maturity` 保持;server/chat 不直写计划表
|
||||
- [x] YAML ↔ StaticContracts parity 绿
|
||||
- [x] 未知 action/policy key fail closed;ActionRegistry 无 batch/tier 字段
|
||||
- [x] 默认 `MULTI_INTENT_PLAN_TIER=legacy`
|
||||
- [x] 单意图生成策略不变(本单元无运行时改动)
|
||||
|
||||
## 相关链接
|
||||
|
||||
- 总览: [2026-09-15-multi-intent-hitl.md](./2026-09-15-multi-intent-hitl.md)
|
||||
- 设计: [../../system-design/2026-09-15-multi-intent-hitl-plan.md](../../system-design/2026-09-15-multi-intent-hitl-plan.md)
|
||||
- Checklist: [../checklists/2026-09-15-multi-intent-u1-contracts.md](../checklists/2026-09-15-multi-intent-u1-contracts.md)
|
||||
- Test report: [../../test-reports/2026-09-15-multi-intent-u1-contracts-test-report.md](../../test-reports/2026-09-15-multi-intent-u1-contracts-test-report.md)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
- 事件登记窗口同时占用 `events` mutex;U1 不改 intent 代码。
|
||||
- 生产者含 `events`:StaticContracts 字面量落在 `internal/events/registry.go`,与现有 document.* 先例一致。
|
||||
- CSRF:Bearer / `X-Session-Token` + CORS allowlist,U5 非 blocker。
|
||||
- 冒烟:`go vet ./...`、`go test -short ./...`、`./scripts/arch-check.sh --mode block` PASS。U1 无 schema/容器变更,集成槽位保持 idle。
|
||||
- 提交:`bdccb4d` docs(ops);`aefb1e4` feat(events);`9364da4` feat(intentflow);随后 docs(status)。
|
||||
@@ -0,0 +1,63 @@
|
||||
---
|
||||
title: "多意图 HITL U2:规则分段与 shadow 提案"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
owner: Cursor
|
||||
branch: feature/multi-intent-u2-segmenter
|
||||
worktree: "-"
|
||||
mutex: intent
|
||||
---
|
||||
|
||||
# 多意图 HITL U2:规则分段与 shadow 提案
|
||||
|
||||
## 目标
|
||||
|
||||
在不改变生产路由(TopIntent / 现有 IntentPlan)的前提下,用纯规则分段器生成 2–4 步 `PlanProposal` 与 shadow 指标;写段不再在提案层被静默丢弃。
|
||||
|
||||
## 范围
|
||||
|
||||
- `internal/intent/segmenter.go`:连接词/句号/分号/换行/序号/先再最后,上限 4
|
||||
- `PlanProposal` L1 值对象:span、证据、缺槽、依赖建议、稳定 digest
|
||||
- Recognize 附加提案与 shadow;**不**改 coordinator 执行路径
|
||||
- golden / hard-negative / 反事实(若处于 auto_read 会如何)
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不建 PG、不接 HTTP、不改 Web
|
||||
- 不把 HITL/tier 回灌 ActionRegistry
|
||||
- 不启用 LLM 分段(U9)
|
||||
- 不把 shadow 提案当作生产 IntentPlan
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 认领 CURRENT,characterization 锁定现有 IntentPlan
|
||||
2. [x] 分段器 + PlanProposal + digest
|
||||
3. [x] 接入 Recognize(leaf 识别防递归)
|
||||
4. [x] golden/hard-negative/反事实与报告
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 「查风险,然后查法规」现有 IntentPlan 仍为 2 步 query
|
||||
- [x] 「查法规然后生成报价单」生产 IntentPlan 仍为 nil(路由不变),提案含写段且 ComboHint=needs_confirm
|
||||
- [x] 「查询并总结」不拆
|
||||
- [x] 指代失败 → needs_clarify
|
||||
- [x] 红线混入 → rejected
|
||||
- [x] 5 段 → rejected_batch_size
|
||||
- [x] 同输入 digest 稳定
|
||||
- [x] 反事实错误自动执行 = 0
|
||||
- [x] `intent -> maturity` 保持
|
||||
|
||||
## 相关链接
|
||||
|
||||
- 总览: [2026-09-15-multi-intent-hitl.md](./2026-09-15-multi-intent-hitl.md)
|
||||
- 设计: [../../system-design/2026-09-15-multi-intent-hitl-plan.md](../../system-design/2026-09-15-multi-intent-hitl-plan.md)
|
||||
- Checklist: [../checklists/2026-09-15-multi-intent-u2-segmenter.md](../checklists/2026-09-15-multi-intent-u2-segmenter.md)
|
||||
- Test report: [../../test-reports/2026-09-15-multi-intent-u2-segmenter-test-report.md](../../test-reports/2026-09-15-multi-intent-u2-segmenter-test-report.md)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
- L1 不 import intentflow;`ComboHint` 只是结构提示,不是授权。
|
||||
- 单段复用 primary frame,避免二次 Recognize。
|
||||
- 冒烟:`go vet ./...`、`go test -short ./...`、`./scripts/arch-check.sh --mode block` PASS。U2 无 schema/容器变更。
|
||||
- 提交:`4751348` docs(ops) 认领;`9005766` test(intent) characterization;`932ba87` feat(intent) 分段器与 shadow 提案。
|
||||
@@ -0,0 +1,68 @@
|
||||
---
|
||||
title: "多意图 HITL U3:intentflow PG/CAS/lease"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
owner: Cursor
|
||||
branch: feature/multi-intent-u3-intentflow-pg
|
||||
worktree: "-"
|
||||
mutex: intent-plan
|
||||
---
|
||||
|
||||
# 多意图 HITL U3:intentflow PG/CAS/lease
|
||||
|
||||
## 目标
|
||||
|
||||
建立持久计划/步骤/决策与并发协议(CAS revision、decision nonce、lease/fencing、创建幂等、retention);不接真实写动作,不改 chat/coordinator 生产路由。
|
||||
|
||||
## 范围
|
||||
|
||||
- Goose `00044`:`intent_plans` / `intent_plan_steps` / `intent_plan_decisions`
|
||||
- `app/intentflow` owner repository + UoW;owner 可 unwrap pgx
|
||||
- 创建幂等 `(environment, session_id, client_turn_id)`;同 turn 异 digest 冲突
|
||||
- 决策 CAS + nonce 同/异 digest;确认/取消/过期竞态
|
||||
- 步骤 lease + 单调 fencing;两 worker 只一个 owner
|
||||
- 业务成功但 receipt 写回失败时按幂等键对账,不盲跑
|
||||
- 环境隔离;关闭计划 retention 由 owner 删除
|
||||
- `app.Assemble` 装配 `*intentflow.Plans`,chat 仍不调用
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不接 HTTP(U5)、不 Append 事件(U4)、不接真实 action adapter(U7/U8)
|
||||
- 不把 HITL/tier 回灌 ActionRegistry
|
||||
- 不改 `internal/intent` 生产 TopIntent / IntentPlan
|
||||
- 不 rebuild 共享 `:8080`(schema 44 仅隔离库/后续晋升窗口应用)
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 认领 CURRENT(mutex `intent-plan`)
|
||||
2. [x] Goose 00044 + migrate gate
|
||||
3. [x] Store/Engine:Create/Decide/Claim/Receipt/Expire/Purge
|
||||
4. [x] 内存并发 + 可选 PG 测试;Assemble 接线
|
||||
5. [x] 报告并合回本地 dev
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 双创建同 digest 返回同一 plan;异 digest 冲突
|
||||
- [x] nonce 同 digest 返回 receipt;异 digest 冲突
|
||||
- [x] 确认/取消/过期只一个 CAS 胜出
|
||||
- [x] 两 worker 抢 eligible 步骤无双 owner
|
||||
- [x] 租约过期可接管;旧 fencing token 被动作属主拒绝
|
||||
- [x] 重启后 succeeded 不重跑;receipt 写回失败按幂等键恢复
|
||||
- [x] 跨 environment 隐藏
|
||||
- [x] 默认 legacy 时 HandleTurn 不落盘
|
||||
- [x] `go test -short ./internal/app/intentflow ./internal/app ./internal/archtest ./internal/db` 绿
|
||||
|
||||
## 相关链接
|
||||
|
||||
- 总览: [2026-09-15-multi-intent-hitl.md](./2026-09-15-multi-intent-hitl.md)
|
||||
- 设计: [../../system-design/2026-09-15-multi-intent-hitl-plan.md](../../system-design/2026-09-15-multi-intent-hitl-plan.md)
|
||||
- Checklist: [../checklists/2026-09-15-multi-intent-u3-intentflow-pg.md](../checklists/2026-09-15-multi-intent-u3-intentflow-pg.md)
|
||||
- Test report: [../../test-reports/2026-09-15-multi-intent-u3-intentflow-pg-test-report.md](../../test-reports/2026-09-15-multi-intent-u3-intentflow-pg-test-report.md)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
- HandleTurn 在默认 legacy 下不落盘;CreatePlan 是 U3 测试与后续 U7 入口。
|
||||
- 动作属主端口仅 FakeActionOwner;真实 adapter 从 U7/U8 按 key 接入。
|
||||
- PG 活验需隔离 `TEST_DATABASE_URL`;本机 short 门禁跳过。共享 `:8080` 仍 schema 43。
|
||||
- 提交:`a75aa45` docs(ops) 认领;`7dfd6d6` feat(db);`da0b3d8` feat(intentflow);`1385002` feat(app)。
|
||||
@@ -0,0 +1,51 @@
|
||||
---
|
||||
title: Demo/测试数据污染全面整改
|
||||
status: done
|
||||
created: 2026-09-16
|
||||
updated: 2026-09-16
|
||||
owner: Cursor-Auto
|
||||
branch: fix/demo-data-pollution-web
|
||||
worktree: "-"
|
||||
mutex: web
|
||||
---
|
||||
|
||||
# Demo / 测试数据污染全面整改
|
||||
|
||||
## 目标
|
||||
|
||||
消除前端 mock/seed 与 DB 演示项目对真实项目清单的污染;生产包无演示文案;main 拒 stub。
|
||||
|
||||
## 范围
|
||||
|
||||
- Wave 0–5 代码 + Wave 6 文档(本分支合并实现)
|
||||
|
||||
## 非目标
|
||||
|
||||
- 删除合法 `*.test.ts` fixture
|
||||
- 改写工作流模板骨架
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] Wave 0 止血
|
||||
2. [x] Wave 1 门控
|
||||
3. [x] Wave 2 localStorage 迁移
|
||||
4. [x] Wave 3 UI 语义
|
||||
5. [x] Wave 4 DB retire
|
||||
6. [x] Wave 5 stub gate
|
||||
7. [x] Wave 6 文档
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] `check-prod-bundle.sh` PASS
|
||||
- [x] deliverableSync / demoSeedIds / ResolveBackend 单测 PASS
|
||||
- [x] `cd web && npm test` 全绿(审核 P0)
|
||||
- [x] 00046/00047 retire + ListChatSessions 过滤(审核 P1)
|
||||
- [x] 合入后共享环境 migrate + 人工空项目/会话抽检(dev schema 47;项目 6357 docs=0;列表无 6001–6010 / sess-wangjing)
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: [.doc/audit/2026-09-16-demo-seed-pollution-systemic.md](../audit/2026-09-16-demo-seed-pollution-systemic.md)
|
||||
- 前序 Audit: [.doc/audit/2026-09-15-mock-deliverables-pollute-real-projects.md](../audit/2026-09-15-mock-deliverables-pollute-real-projects.md)
|
||||
- Remediation: [.doc/remediation/2026-09-16-demo-seed-pollution-remediation.md](../remediation/2026-09-16-demo-seed-pollution-remediation.md)
|
||||
- Test report: [.doc/test-reports/2026-09-16-demo-seed-pollution-test-report.md](../test-reports/2026-09-16-demo-seed-pollution-test-report.md)
|
||||
- 挑拣:`a91a031` `SEED_DEMO_USERS=false`(自 `fix/clean-test-env-baseline`)
|
||||
@@ -0,0 +1,49 @@
|
||||
---
|
||||
title: "FEATURE-MATRIX 深度测试 + 晋升部署 test"
|
||||
status: in_progress
|
||||
created: 2026-09-16
|
||||
updated: 2026-09-16
|
||||
owner: Cursor-Auto
|
||||
branch: feature/matrix-deep-test-promote-test
|
||||
worktree: "-"
|
||||
mutex: infra
|
||||
---
|
||||
|
||||
# FEATURE-MATRIX 深度测试 + 晋升部署 test
|
||||
|
||||
## 目标
|
||||
|
||||
按 FEATURE-MATRIX 对已实现模块做分层深度回归,通过后将本地 `dev` 晋升到 `test`(`rc-v1.0.0-beta.2`)并 rebuild/冒烟 `:8081`。
|
||||
|
||||
## 范围
|
||||
|
||||
- Wave 1:vet/short/arch/npm/bundle + 模块定向 + 隔离治理 PG
|
||||
- Wave 2:dev `:8080` live API 抽检
|
||||
- Wave 3:真实 PI 抽样(失败再升格三链)
|
||||
- Wave 4:`dev` → `test` + rebuild + smoke
|
||||
- Wave 5:测试报告 + SSOT
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不实现纯软件项目自举
|
||||
- 不默认 28min 三工作流 PI;不合 `main`;不改项目 143;不启用 FAV
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [ ] 认领占槽
|
||||
2. [ ] 自动化深度回归
|
||||
3. [ ] live `:8080` 抽检
|
||||
4. [ ] PI 抽样
|
||||
5. [ ] 晋升 test 并冒烟
|
||||
6. [ ] 报告与归档
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [ ] 矩阵已实现行均有 PASS 证据
|
||||
- [ ] `:8081` health/ready schema=47;`test-env-smoke.sh` PASS
|
||||
- [ ] tag `rc-v1.0.0-beta.2`;报告归档
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Plan: matrix_deep_test_promote
|
||||
- FEATURE-MATRIX / CURRENT / gap-matrix
|
||||
@@ -0,0 +1,51 @@
|
||||
---
|
||||
title: "多意图 HITL U4:outbox 与计划投影"
|
||||
status: done
|
||||
created: 2026-09-16
|
||||
updated: 2026-09-16
|
||||
owner: Cursor
|
||||
branch: feature/multi-intent-u4-outbox-projection
|
||||
worktree: "-"
|
||||
mutex: events
|
||||
---
|
||||
|
||||
# 多意图 HITL U4:outbox 与计划投影
|
||||
|
||||
## 目标
|
||||
|
||||
权威计划在同一 UoW 写入 outbox;投影只应用状态事实;消息/SSE 丢失时 GET PlanView 仍能恢复。不改 dispatcher claim/lease/retry 语义。
|
||||
|
||||
## 范围
|
||||
|
||||
- Create/Decide/Receipt 同事务 Append `intent.plan.*`
|
||||
- 最小 payload + golden;伪造 producer 拒绝
|
||||
- projection consumer 幂等、只前进 revision;跨用户不可见
|
||||
- ctxmgr 只经 CardProjector 端口(接口在 intentflow,实现可 no-op)
|
||||
- 复用 Track E LiveConsumers
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不改通用 dispatcher
|
||||
- 不挂 HTTP(U5)、不改 Web(U6)、不执行动作(U7)
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 认领 CURRENT(mutex `events`)
|
||||
2. [x] emit + golden + 投影只前进
|
||||
3. [x] cmd/events 接入 multiplex;goose shadow
|
||||
4. [x] 报告并合回本地 dev
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 创建计划产生 awaiting_input;payload 无 prompt/slots
|
||||
- [x] 重复 event_id 不双写投影
|
||||
- [x] 乱序低 revision 不覆盖高 revision
|
||||
- [x] 伪造 producer 拒绝
|
||||
- [x] GET PlanView 不依赖投影成功
|
||||
- [x] arch-check / short 绿
|
||||
|
||||
## 相关链接
|
||||
|
||||
- 总览: [2026-09-15-multi-intent-hitl.md](./2026-09-15-multi-intent-hitl.md)
|
||||
- Checklist: [../checklists/2026-09-16-multi-intent-u4-outbox-projection.md](../checklists/2026-09-16-multi-intent-u4-outbox-projection.md)
|
||||
- Test report: [../../test-reports/2026-09-16-multi-intent-u4-outbox-projection-test-report.md](../../test-reports/2026-09-16-multi-intent-u4-outbox-projection-test-report.md)
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
title: "多意图 HITL U5:决策 API 与授权端口"
|
||||
status: done
|
||||
created: 2026-09-16
|
||||
updated: 2026-09-16
|
||||
owner: Cursor
|
||||
branch: feature/multi-intent-u5-decision-api
|
||||
worktree: "-"
|
||||
mutex: intent-plan
|
||||
---
|
||||
|
||||
# 多意图 HITL U5:决策 API 与授权端口
|
||||
|
||||
## 目标
|
||||
|
||||
按钮与自然语言走同一 `DecidePlan` 命令;GET 发现活动计划不依赖投影;执行前由动作属主重新授权。确认不是授权。
|
||||
|
||||
## 范围
|
||||
|
||||
- 冻结路径:`GET /api/v1/intent-plans/active`、`GET /api/v1/intent-plans/{plan_id}`、`POST /api/v1/intent-plans/{plan_id}/decisions`
|
||||
- Principal 只从认证会话 + query 的 project/session 组装,忽略 body 中的 user/project/session
|
||||
- 四元作用域;非成员 403;跨 session/user 隐藏为 404
|
||||
- 系统管理员不得绕过项目成员检查
|
||||
- `StepAuthorizer` 端口 + Fake/dry-run;确认与执行前鉴权
|
||||
- expected revision、nonce、依赖闭包、edit 升 revision
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不接真实业务属主 adapter(U7/U8)
|
||||
- 不改 Web(U6)、不改默认 legacy HandleTurn
|
||||
- 不 rebuild 共享 `:8080`
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 认领 CURRENT(mutex `intent-plan`)
|
||||
2. [x] 授权端口与 confirm/execute 即时鉴权
|
||||
3. [x] HTTP handlers + 权限负例
|
||||
4. [x] 报告并合回本地 dev
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [ ] 投影缺失仍能 GET active
|
||||
- [ ] 未登录 401;非成员 403;跨项目/会话/用户隐藏
|
||||
- [ ] stale revision 409;重复 nonce 同 digest 同 receipt
|
||||
- [ ] 非法部分确认拒绝;edit 使旧 revision 失效
|
||||
- [ ] 确认前零副作用;权限撤销/资源版本 fail closed
|
||||
- [ ] 无系统身份绕过
|
||||
- [ ] `go test -short` 绿
|
||||
|
||||
## 相关链接
|
||||
|
||||
- 总览: [2026-09-15-multi-intent-hitl.md](./2026-09-15-multi-intent-hitl.md)
|
||||
- 设计: [../../system-design/2026-09-15-multi-intent-hitl-plan.md](../../system-design/2026-09-15-multi-intent-hitl-plan.md)
|
||||
- Checklist: [../checklists/2026-09-16-multi-intent-u5-decision-api.md](../checklists/2026-09-16-multi-intent-u5-decision-api.md)
|
||||
@@ -0,0 +1,47 @@
|
||||
---
|
||||
title: "多意图 HITL U6:Web 卡片、刷新与可访问性"
|
||||
status: done
|
||||
created: 2026-09-16
|
||||
updated: 2026-09-16
|
||||
owner: Cursor
|
||||
branch: feature/multi-intent-u6-web-cards
|
||||
worktree: "-"
|
||||
mutex: web
|
||||
---
|
||||
|
||||
# 多意图 HITL U6:Web 卡片、刷新与可访问性
|
||||
|
||||
## 目标
|
||||
|
||||
UI 只呈现 PlanView;计划动作不走本地 AST/资源修改;刷新与双标签以 GET reconcile。
|
||||
|
||||
## 范围
|
||||
|
||||
- `PLAN_CONFIRM` 卡片类型
|
||||
- intent-plans API client
|
||||
- submitting/outdated/expired/conflict;409 看最新版
|
||||
- App 计划动作 early-return,禁止本地成功路径
|
||||
- Playwright 门控(无 `RUN_UI_ACCEPTANCE` 则 skip)
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不接 auto_read 执行(U7)
|
||||
- 不 rebuild 共享环境
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 认领 CURRENT
|
||||
2. [x] 卡片/API/reconcile 与无 AST 路径
|
||||
3. [x] 单元测试 + 门控 Playwright
|
||||
4. [x] 报告并合回
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [ ] 计划确认不修改 DocumentAST
|
||||
- [ ] GET 可修复缺失投影
|
||||
- [ ] 409 标 outdated 并带最新 PlanView
|
||||
- [ ] 默认 Playwright skip
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Checklist: [../checklists/2026-09-16-multi-intent-u6-web-cards.md](../checklists/2026-09-16-multi-intent-u6-web-cards.md)
|
||||
@@ -0,0 +1,14 @@
|
||||
---
|
||||
title: "多意图 HITL U7:低风险只读执行"
|
||||
status: done
|
||||
created: 2026-09-16
|
||||
updated: 2026-09-16
|
||||
owner: Cursor
|
||||
branch: feature/multi-intent-u7-auto-read
|
||||
worktree: "-"
|
||||
mutex: intent-plan
|
||||
---
|
||||
|
||||
# 多意图 HITL U7:低风险只读执行
|
||||
|
||||
HandleTurn 在 auto_read 下执行独立查询;默认 legacy 不变。QueryGuard 拒绝 generate。
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
title: "多意图 HITL U8:task generate adapter"
|
||||
status: done
|
||||
created: 2026-09-16
|
||||
updated: 2026-09-16
|
||||
owner: Cursor
|
||||
branch: feature/multi-intent-u8-task-generate
|
||||
worktree: "-"
|
||||
mutex: intent-plan
|
||||
---
|
||||
|
||||
# 多意图 HITL U8:task generate adapter
|
||||
|
||||
## 目标
|
||||
|
||||
`confirm` tier 下查询+生成落盘 awaiting;确认后仅开放 `task.run` / `task.run.adhoc`,稳定幂等键,不改单意图 taskrun HTTP。
|
||||
|
||||
## 范围
|
||||
|
||||
- HandleTurn:`ComboNeedsConfirm` 且 tier≥confirm 时 WritePlan 落盘,不自动执行
|
||||
- `OwnerMux` 把 generate 路由到 Task,其余走 QueryGuard
|
||||
- `TaskRunAdapter` + `LiveTaskStarter`(无 `PI_AGENT_RUNNER_URL` 只占位不启 PI)
|
||||
- Assemble 接线;默认 `MULTI_INTENT_PLAN_TIER=legacy` 不变
|
||||
|
||||
## 非目标
|
||||
|
||||
- U9 LLM 分段、U10–U12 owner 扩面
|
||||
- 不 rebuild 共享环境、不改项目 143
|
||||
- 真实 PI 闭环若环境缺失记 stop-gate,不冒充验收
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 从 `dev` 开 `feature/multi-intent-u8-task-generate`
|
||||
2. [x] confirm 落盘 + mux + adapter
|
||||
3. [x] 单测与 arch-check
|
||||
4. [x] 报告并合回
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 多意图生成确认前零执行
|
||||
- [x] 活动写计划冲突
|
||||
- [x] 确认后 mux 执行 generate,重放 starts=1
|
||||
- [x] QueryGuard 仍拒绝 generate;权限撤销 fail closed
|
||||
- [x] 真实 PI 无 URL 时 skip(stop-gate)
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Checklist: [../checklists/2026-09-16-multi-intent-u8-task-generate.md](../checklists/2026-09-16-multi-intent-u8-task-generate.md)
|
||||
- Test report: [../../test-reports/2026-09-16-multi-intent-u8-task-generate-test-report.md](../../test-reports/2026-09-16-multi-intent-u8-task-generate-test-report.md)
|
||||
- Parent: [./2026-09-15-multi-intent-hitl.md](./2026-09-15-multi-intent-hitl.md)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
默认 legacy HandleTurn 仍不落盘。真实 PI 见报告 stop-gate。
|
||||
@@ -61,5 +61,5 @@ updated: 2026-09-13
|
||||
## 相关链接
|
||||
|
||||
- Audit: [../audit/2026-09-13-chat-history-refresh-disappears.md](../audit/2026-09-13-chat-history-refresh-disappears.md)
|
||||
- Short-term: [../ops/short-term/2026-09-13-chat-history-refresh-remediation.md](../ops/short-term/2026-09-13-chat-history-refresh-remediation.md)
|
||||
- Short-term: [../archive/ops/2026-09-13-chat-history-refresh-remediation.md](../archive/ops/2026-09-13-chat-history-refresh-remediation.md)
|
||||
- gap-matrix 行: `CHAT-HISTORY-REFRESH`
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
---
|
||||
title: "对话意图、可恢复任务状态与文档占用可见性整改"
|
||||
status: in_progress
|
||||
status: done
|
||||
created: 2026-09-13
|
||||
updated: 2026-09-13
|
||||
updated: 2026-09-15
|
||||
---
|
||||
|
||||
# 对话意图、可恢复任务状态与文档占用可见性整改
|
||||
@@ -30,11 +30,10 @@ updated: 2026-09-13
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] “总结一下用户初始需求表”返回已有文档摘要,不创建 `task_runs`。
|
||||
- [ ] “开始编写用户初始需求表”只创建一个 run;运行中再次写请求不创建失败 run。
|
||||
- [ ] 任务失败后刷新,错误码、诊断摘要及允许动作与刷新前一致。
|
||||
- [ ] 运行中刷新,聊天占位、阶段进度、文档 busy 标识和输入保护均恢复。
|
||||
- [ ] 租约释放/任务终态后 UI 自动解除 busy,无需用户手动刷新。
|
||||
- [x] “开始编写用户初始需求表”只创建一个 run;运行中再次写请求不创建失败 run。
|
||||
- [x] 任务失败后刷新,错误码、诊断摘要及允许动作与刷新前一致。
|
||||
- [x] 运行中刷新,聊天占位、阶段进度、文档 busy 标识和输入保护均恢复。
|
||||
- [x] 租约释放/任务终态后 UI 自动解除 busy,无需用户手动刷新。
|
||||
- [x] 测试使用专用项目/会话并在 teardown 清理;禁止 `debug/test` 探针进入非 fixture 会话。
|
||||
|
||||
## 相关链接
|
||||
|
||||
@@ -0,0 +1,677 @@
|
||||
---
|
||||
title: "模块解耦与文档可靠性重构计划"
|
||||
status: planned
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-14
|
||||
type: refactor
|
||||
owner: TBD
|
||||
deepened: 2026-09-14
|
||||
---
|
||||
|
||||
# 模块解耦与文档可靠性重构计划
|
||||
|
||||
## Goal Capsule
|
||||
|
||||
- **Objective:** 项目文档、任务最终产物和最终智能体回复在并发写入、页面刷新、服务重启、工作区清理和受控恢复后仍能按权限定位到唯一、可校验的内容。
|
||||
- **Means:** 采用模块化单体、纵向绞杀、应用 UnitOfWork、数据库互斥、transactional outbox、opaque workspace capability 和 FAV。
|
||||
- **Authority:** 本计划受 [模块化单体解耦 ADR](../adr/2026-09-14-modular-monolith-decoupling.md)、[文档版本边界 ADR](../adr/2026-09-13-document-version-boundary.md) 和 [工作流运行时权威 ADR](../adr/2026-09-12-workflow-runtime-authority.md) 约束。
|
||||
- **Stop condition:** 任一里程碑出现数据不变量无法在单事务维持、授权只能通过放宽实现、旧数据无法安全迁移,或真实页面故障率没有下降时,停止扩面并回到设计评审。
|
||||
- **Execution profile:** 高风险、跨模块、迁移和授权敏感;characterization-first,逐纵向切片发布。
|
||||
- **Delivery:** 每个里程碑独立 short-term、独立分支和独立验收报告;本计划本身不授权合并、部署或删数据。
|
||||
|
||||
---
|
||||
|
||||
## Product Contract
|
||||
|
||||
### Summary
|
||||
|
||||
重构先解决文档事实源、事务与恢复链,再扩展其他模块。
|
||||
架构改造必须用用户可见的刷新、重启、并发和授权结果证明价值,不能只用包数量或代码行数证明完成。
|
||||
|
||||
### Problem Frame
|
||||
|
||||
系统当前同时依赖 PostgreSQL 账本、`document_records` 指针、workspace `output.md` 和若干内存状态。
|
||||
这些状态在提交、刷新和重启时没有统一事务与恢复协议,导致历史上出现正文 404/409、projection missing、缓存竞争和任务完成后文档仍为空。
|
||||
|
||||
原解耦方案提出 contracts、单一写者和事件总线,但没有解释单一写者如何维持现有跨表原子性,也没有为多个 event subscriber、跨实例互斥和 FAV 恢复定义可执行协议。
|
||||
|
||||
### Requirements
|
||||
|
||||
**事实源与持久成果**
|
||||
|
||||
- R1. PostgreSQL immutable ledger 是文档版本与业务关系的权威,workspace 只作为可重建投影。
|
||||
- R2. FAV 只归档服务端确认的终态文档、终态助手回复、类型化 RunManifest 和必要附件,中间结果准入率为零。
|
||||
- R3. 数据库授权图完整但正文不可用时,系统可按 feature flag 从已验证 FAV 只读降级;授权图不完整时必须拒绝。
|
||||
- R4. GET、刷新和重载不得隐式修复数据库、覆盖 head 或创建归档。
|
||||
|
||||
**事务与并发**
|
||||
|
||||
- R5. 一个业务命令只有一个事务 owner;业务状态、账本、当前指针及该里程碑已启用的 staging/outbox 必须原子提交。
|
||||
- R6. 单一写者只约束 SQL 和不变量所有权,不允许各属主各自提交导致跨表半完成。
|
||||
- R7. 多副本正确性必须依赖数据库行锁、事务级 advisory lock、唯一约束、expected version 和 fencing token;进程内 mutex 不能成为唯一正确性条件。
|
||||
- R8. 所有写命令必须具有 idempotency key、expected version 或两者;相同 key 不同 payload 必须返回冲突。
|
||||
- R9. 事务不得包含 LLM、PI Runner、对象存储、HTTP/SSE 或长文件 I/O。
|
||||
|
||||
**事件与恢复**
|
||||
|
||||
- R10. 持久事件采用至少一次投递、逐消费者 delivery、幂等 inbox、租约、fencing token、重试和死信。
|
||||
- R11. 同一聚合事件按 aggregate version 有序,不同聚合允许并发;失败消费者不阻塞其他消费者。
|
||||
- R12. 旧 workspace、旧数据库和 FAV 回填必须可断点续跑、可重复、可审计,异常进入 quarantine。
|
||||
- R13. 恢复只进入 scratch identity,promotion 需要系统管理员和数据责任人确认,并通过属主端口提交。
|
||||
|
||||
**授权与隔离**
|
||||
|
||||
- R14. HTTP、CLI、worker、event subscriber 和恢复工具必须使用服务端构造的 Principal,并按 action/resource/current state 逐动作授权。
|
||||
- R15. 客户端或事件 payload 中的 user、project、role、duty、backend 和路径不能作为授权事实。
|
||||
- R16. WorkspaceRef 只能暴露不可伪造 ID、scope 和 fencing token;物理路径不得跨模块传播。
|
||||
- R17. 路径解析必须拒绝绝对路径、`..`、跨项目 ID、symlink/hardlink 逃逸和 storage identity 不匹配。
|
||||
- R18. 事件、日志、metrics、manifest 和 result 文件不得包含 secret、认证材料、Prompt 或不必要正文。
|
||||
|
||||
**交付与验证**
|
||||
|
||||
- R19. 首个独立交付边界是受控文档可靠性纵向试点,未通过停走门前不启动横向包搬移。
|
||||
- R20. 每个里程碑必须分别提供 unit、PostgreSQL、并发/故障注入、真实 PI、真实浏览器、restart/rebuild 和跨用户负例证据;不适用项必须说明原因。
|
||||
- R21. 迁移采用 expand/migrate/contract,允许新的 Goose migration,禁止修改已发布 migration。
|
||||
- R22. 数据清理必须同时满足完整备份恢复、migration corpus、FAV coverage、精确删除 manifest 和用户批准,不得因“已有最终成果”跳过其他门禁。
|
||||
|
||||
### Success Criteria
|
||||
|
||||
- 项目 143 等价脱敏 hazard 和新建项目两条链路在刷新、重登、restart 与 rebuild 后正文成功率为 100%,目标 404/409/projection missing 为 0。
|
||||
- 同一文档并发写只有一个合法赢家;失败请求不产生孤儿 snapshot、错 head、重复消息、重复通知或重复 artifact。
|
||||
- 每个应发布终态都存在 publish request;已验证 artifact 可在 workspace 删除后按稳定逻辑 ID 定位并校验 SHA。
|
||||
- 匿名、非成员、跨用户、跨项目、错误 duty、错误 stage、篡改事件和授权依赖失败全部 fail closed。
|
||||
- 1、2、4 个应用实例和 dispatcher 下,状态与副作用结果一致;性能阈值由基线报告确认后固化,不能通过降低一致性达标。
|
||||
- 旧 schema corpus、legacy-v0 workspace 和 previous-release corpus 均可升级、重载和回滚到最近兼容点。
|
||||
|
||||
### Scope Boundaries
|
||||
|
||||
**本计划包含**
|
||||
|
||||
- 文档、taskrun、workspace、artifactvault、可靠事件和授权基础设施。
|
||||
- chatlog/contextasm、squadrun、app 组合根和 UserProjectContext 的后续选择性扩展。
|
||||
- 数据生命周期、迁移 corpus、回填、quarantine 和 scratch 恢复的集成门禁。
|
||||
|
||||
**Deferred to Follow-Up Work**
|
||||
|
||||
- HTTP 错误信封统一。
|
||||
- PI Runner stdout/result.json 协议替换。
|
||||
- 全量 SSE transport 重写。
|
||||
- 微服务拆分和跨服务消息基础设施。
|
||||
- main 数据自动清理和未来 tenant 实体。
|
||||
|
||||
---
|
||||
|
||||
## Planning Contract
|
||||
|
||||
### Key Technical Decisions
|
||||
|
||||
- KTD1. **纵向绞杀优先。** 先在原包边界增加窄端口和适配器,迁完消费者并通过行为验收后再物理移动包。
|
||||
- KTD2. **事务 owner 与表属主分离。** 应用用例拥有事务,领域模块拥有 SQL;同一 `pgx.Tx` 通过不透明 TxScope 绑定 repository。
|
||||
- KTD3. **显式锁策略。** 普通状态转换使用 `READ COMMITTED`、行锁和条件更新;项目级不变量使用事务级 advisory lock;Serializable 只用于经过证明的复杂不变量。[PostgreSQL explicit locking](https://www.postgresql.org/docs/17/explicit-locking.html)
|
||||
- KTD4. **固定锁顺序。** project/workflow instance → document root → version/snapshot/turn → task run → staging/outbox/delivery。
|
||||
- KTD5. **事务外副作用。** 网络、LLM、对象存储、通知和投影由提交后的持久事件驱动。
|
||||
- KTD6. **至少一次事件。** outbox 不承诺 exactly-once;event ID、consumer inbox 和业务唯一约束共同提供幂等结果。
|
||||
- KTD7. **opaque workspace capability。** 跨模块不传物理路径,所有读写使用 scope-bound ID、artifact key 和 fencing token。
|
||||
- KTD8. **三层权威。** PostgreSQL 管业务关系与授权,workspace 管临时现场,FAV 管已验证终态 payload/manifest/receipt/tombstone。
|
||||
- KTD9. **授权逐动作重算。** Principal 来自受信适配器;状态改变在取得资源锁后重读当前授权事实,subscriber 的 actor 快照只用于审计。[OWASP Authorization Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Authorization_Cheat_Sheet.html)
|
||||
- KTD10. **依赖感知回滚。** 每个里程碑只保证回到最近兼容点;进入 contract 阶段后须按逆依赖顺序回滚。
|
||||
- KTD11. **按证据收紧门禁。** arch-check 先记录基线,每条规则在对应纵向切片清零后转 block,不按日历统一切换。
|
||||
- KTD12. **FAV 分支先审后用。** `feature/final-artifact-vault` 的现有实现作为候选,不直接视为 dev 已有能力;集成前重放迁移、测试、安全和并发审计。
|
||||
|
||||
### High-Level Technical Design
|
||||
|
||||
#### Component topology
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
Transport[HTTP SSE CLI] --> UseCases[application use cases]
|
||||
Jobs[workers and recovery] --> UseCases
|
||||
UseCases --> Policy[authorization policy]
|
||||
UseCases --> Unit[UnitOfWork]
|
||||
Unit --> DG[docgov owner]
|
||||
Unit --> DR[docrevision owner]
|
||||
Unit --> TR[taskrun owner]
|
||||
Unit --> OB[outbox and staging]
|
||||
UseCases --> WSC[workspace capability]
|
||||
OB --> Dispatch[delivery dispatcher]
|
||||
Dispatch --> Projection[projection subscriber]
|
||||
Dispatch --> AV[artifactvault subscriber]
|
||||
Dispatch --> Notify[notification subscriber]
|
||||
```
|
||||
|
||||
#### Write sequence
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant C as Caller
|
||||
participant A as App use case
|
||||
participant P as Policy
|
||||
participant DB as PostgreSQL
|
||||
participant O as Outbox worker
|
||||
participant V as FAV
|
||||
C->>A: command + idempotency + expected version
|
||||
A->>P: authorize principal/action/resource
|
||||
P-->>A: allow or deny
|
||||
A->>DB: begin and acquire locks in canonical order
|
||||
A->>DB: ledger + root + staging + outbox
|
||||
DB-->>A: commit
|
||||
A-->>C: committed result
|
||||
O->>DB: claim delivery
|
||||
O->>V: publish immutable artifact
|
||||
V-->>O: verified receipt
|
||||
O->>DB: idempotent ack
|
||||
```
|
||||
|
||||
#### Event delivery lifecycle
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> pending
|
||||
pending --> leased
|
||||
leased --> delivered
|
||||
leased --> retryable_failed
|
||||
leased --> dead_letter
|
||||
retryable_failed --> leased
|
||||
leased --> pending: lease expired
|
||||
delivered --> [*]
|
||||
```
|
||||
|
||||
#### Migration lifecycle
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
Expand[Expand schema and compatible readers] --> Shadow[Shadow validation]
|
||||
Shadow --> Backfill[Checkpointed backfill]
|
||||
Backfill --> Switch[Switch writer]
|
||||
Switch --> Observe[Observe and restart test]
|
||||
Observe --> Contract{Go or rollback?}
|
||||
Contract -->|go| Remove[Remove old path]
|
||||
Contract -->|rollback| Previous[Return to prior compatible point]
|
||||
```
|
||||
|
||||
### Concurrency and Lock Matrix
|
||||
|
||||
| Resource/operation | Correctness primitive | Conflict result | Retry policy | Forbidden while held |
|
||||
|---|---|---|---|---|
|
||||
| Project duty/heal/revoke | transaction advisory lock keyed by project | wait then typed timeout | whole idempotent tx for deadlock only | network, LLM, filesystem copy |
|
||||
| Workflow stage advance | instance row lock + expected config revision | stale-state conflict | caller refresh; no blind retry | external execution |
|
||||
| Controlled document edit | document row + open version row + ETag | version conflict with current head metadata | user/client rebases | projection and notification |
|
||||
| Agent candidate commit | candidate/document/version locks + idempotency key | stale candidate or idempotency conflict | exact same request may replay | PI/LLM call |
|
||||
| TaskRun claim/finalize | unique idempotency + conditional status/version update | existing run or state conflict | same digest returns prior result | message/SSE side effect |
|
||||
| Workspace write | DB lease + fencing token + atomic file commit | stale lease/token | reacquire then re-resolve state | arbitrary path access |
|
||||
| Outbox delivery | row lease + `SKIP LOCKED` + fencing token | another worker owns item | retry at next schedule | subscriber work inside claim tx |
|
||||
| FAV publish | artifact idempotency unique key + no-replace object write | existing verified artifact or digest conflict | same digest resumes | reading mutable workspace |
|
||||
|
||||
### Authorization Matrix
|
||||
|
||||
| Surface | Principal source | Resource facts | Required checks | Failure behavior |
|
||||
|---|---|---|---|---|
|
||||
| HTTP/SSE | authenticated session/middleware | DB project/session/document/workflow | membership, owner, duty, stage, action | 401/403/typed conflict; no data |
|
||||
| CLI ops | service identity + operator session | explicit environment/dataset/resource manifest | capability, exact scope, dry-run where destructive | fail closed and audit |
|
||||
| Event subscriber | registered service identity; event actor for audit only | DB current aggregate + event scope/digest | producer allowlist, project/resource match, current policy | dead letter/quarantine |
|
||||
| FAV degraded read | current authenticated Principal | DB relation + vault manifest/tombstone | normal read permission first, then integrity | no fallback if auth graph incomplete |
|
||||
| Recovery promotion | recovery credential + admin + data steward approval | scratch identity + signed plan + conflict map | two-party approval, no unresolved conflicts | refuse promotion |
|
||||
| Agent backend | app-resolved BackendRef | project policy + InputBundle sensitivity | backend allowlist, least data, secret injection boundary | reject before dispatch |
|
||||
|
||||
### Delivery dependency graph
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
M0[M0 baseline and contract correction] --> M1[M1 document reliability pilot]
|
||||
M1 --> M2[M2 durable events and FAV integration]
|
||||
M2 --> M3[M3 taskrun and workspace finalization]
|
||||
M3 --> M4[M4 selective domain decoupling]
|
||||
M4 --> M5[M5 app composition and context ownership]
|
||||
M5 --> M6[M6 transport boundary cleanup]
|
||||
M2 --> D[Data corpus and lifecycle rollout]
|
||||
D --> M3
|
||||
```
|
||||
|
||||
### Assumptions
|
||||
|
||||
- 当前 dev 基线为 schema 33;任何实现分支必须在创建 migration 时重新查询最新序号。
|
||||
- `feature/final-artifact-vault` 尚未合 dev,现有代码与测试只能作为候选实现和证据来源。
|
||||
- 当前无独立 tenant 实体,权限范围沿用 environment + project membership/admin;未来 tenant 模型另立 ADR。
|
||||
- 性能容量目标需要在 M1 压测后固化;本计划先固定正确性和观测项,不伪造吞吐数字。
|
||||
|
||||
---
|
||||
|
||||
## Phased Delivery
|
||||
|
||||
| 里程碑 | 交付边界 | 预计范围 | 进入条件 | 退出/停走门 |
|
||||
|---|---|---|---|---|
|
||||
| M0 | 基线与契约纠偏 | 文档/门禁/characterization | 在途 mutex 不冲突 | 事务/锁/授权/事件/FAV 契约评审通过 |
|
||||
| M1 | 文档可靠性纵向试点 | docflow/docgov/docrevision/docquery | M0 完成,独占 docgov | 刷新、重启、并发、权限和故障注入全 PASS |
|
||||
| M2 | 持久事件与 FAV | outbox/delivery/artifactvault | M1 数据边界稳定 | 多 worker、重放、归档、降级读取和 tombstone PASS |
|
||||
| M3 | taskrun/workspace 终态 | taskrun/squadrun/workspace | M2 verified receipt 可用 | 清 workspace 后最终产物仍可定位,重复 finalize 无副作用 |
|
||||
| M4 | 选择性领域端口化 | chatlog/contextasm/squadrun | M1–M3 复盘证明收益 | 每个子切片独立回归;无纯搬包 |
|
||||
| M5 | 组合根与上下文收权 | app/chatflow/stageflow/UserProjectContext | M4 稳定 | 每个 use case 单 owner;闭包按事件逐个替换 |
|
||||
| M6 | 传输收口 | server/SSE | M5 完成 | server 无 SQL/编排/路径;R1–R7 对应规则全 block |
|
||||
|
||||
M0–M1 是首个批准范围。
|
||||
M2–M6 需要在前一里程碑验收报告后重新 go/no-go,不构成一次性整体授权。
|
||||
|
||||
---
|
||||
|
||||
## Implementation Units
|
||||
|
||||
### Unit Index
|
||||
|
||||
| ID | 标题 | 主要文件 | 依赖 |
|
||||
|---|---|---|---|
|
||||
| U1 | 固化架构基线和门禁 | `scripts/arch-check.sh`, `.doc/system-design/module-boundaries.yaml` | 无 |
|
||||
| U2 | 建立应用 UnitOfWork | `internal/app/uow`, owner repositories | U1 |
|
||||
| U3 | 文档命令原子化 | docgov/docrevision/docflow | U2 |
|
||||
| U4 | 文档授权读模型 | docquery/server/authz | U1, U3 |
|
||||
| U5 | Workspace capability | workspace/squadrun | U1 |
|
||||
| U6 | Durable event delivery | outbox/dispatcher/inbox | U2 |
|
||||
| U7 | FAV 集成与降级读取 | artifactvault/docflow/docquery | U3, U4, U6 |
|
||||
| U8 | TaskRun/RunManifest 终态 | taskrun/squadrun/workspace | U5, U6, U7 |
|
||||
| U9 | 数据回填与迁移 corpus | dataset/FAV tooling | U6–U8 |
|
||||
| U10 | chatlog/contextasm 端口化 | ctxmgr/chat/contextasm | M1–M3 go/no-go |
|
||||
| U11 | 组合根和 use case 收权 | app/server/bizdev/coordinator | U10 |
|
||||
| U12 | 传输边界与最终门禁 | server/stream/CI | U11 |
|
||||
|
||||
### U1. 固化架构基线和可执行门禁
|
||||
|
||||
- **Goal:** 建立不会把现有违规合法化、也不会误报 migration/fixture 的边界基线。
|
||||
- **Requirements:** R19–R21;KTD1、KTD11。
|
||||
- **Dependencies:** 无;必须避开 `intent`、`chat` 等在途 mutex,当前只占 `arch`。
|
||||
- **Files:** `scripts/arch-check.sh`、`.doc/system-design/module-boundaries.yaml`、`internal/archtest/arch_test.go`、`internal/archtest/arch_test_test.go`、`.doc/audit/<date>-arch-check-baseline.md`。
|
||||
- **Approach:**
|
||||
1. 分离 production import、production SQL write、path construction、event producer/consumer 四类规则。
|
||||
2. 表名扫描只识别 production Go 中的写语句;Goose、测试、fixture 和受控运维脚本进入显式类别,不以全仓零出现为目标。
|
||||
3. 为每项既有违规记录 owner、原因、截止里程碑和到期日;新违规立即 block。
|
||||
4. 只为已完成纵向切片的规则切换 block,不能以“两周后统一 block”代替清零。
|
||||
- **Execution note:** 先对当前依赖和 SQL 写者生成可重复 characterization 报告,再改门禁。
|
||||
- **Patterns to follow:** `go list` 依赖图、现有 AGENTS mutex、Goose 不可改写规则。
|
||||
- **Test scenarios:**
|
||||
- 合法的 Goose/fixture 表名不触发生产写者违规。
|
||||
- 非属主 production 包新增 `UPDATE document_records` 时测试失败并定位文件。
|
||||
- 路径通过字符串拼接、`filepath.Join` 和间接常量构造时均被检测。
|
||||
- 无过期日例外、过期例外、新增越权 event producer 均阻断。
|
||||
- **Verification:** 基线报告可重放;新增违规阻断;现有违规数只能下降。
|
||||
|
||||
### U2. 建立应用 UnitOfWork 和事务能力
|
||||
|
||||
- **Goal:** 在单一写者边界内维持跨表业务不变量。
|
||||
- **Requirements:** R5–R9;KTD2–KTD5。
|
||||
- **Dependencies:** U1。
|
||||
- **Files:** `internal/app/uow/uow.go`、`internal/app/uow/pg_uow.go`、`internal/app/uow/pg_uow_test.go`、`internal/docgov/repository.go`、`internal/docrevision/repository.go`、`internal/taskrun/repository.go`、`internal/freedoc/repository.go`。
|
||||
- **Approach:**
|
||||
1. UnitOfWork 开启、提交和回滚唯一 `pgx.Tx`,向每个属主提供绑定该 transaction 的窄 repository capability。
|
||||
2. TxScope 不暴露通用 `Exec` 给应用层;只有属主 repository 能执行自己的 SQL。
|
||||
3. 禁止 repository 在已有 TxScope 内嵌套 transaction 或提前 commit。
|
||||
4. 实现统一的完整事务重试 wrapper,只重试明确的 serialization/deadlock 错误,并保持 idempotency context。
|
||||
5. 为锁超时、事务时长、重试和 rollback reason 加结构化指标,不记录业务正文。
|
||||
- **Test scenarios:**
|
||||
- 第二个属主写入失败时第一个属主写入回滚。
|
||||
- outbox/staging 写入失败时业务状态和账本均回滚。
|
||||
- commit 失败时不会返回成功或执行提交后副作用。
|
||||
- `40001`/`40P01` 重跑完整事务并最终只产生一个业务结果。
|
||||
- version conflict、permission denied、payload digest conflict 不进入自动重试。
|
||||
- 尝试跨属主执行任意 SQL 无法通过类型边界或架构测试。
|
||||
- **Verification:** fault injection 覆盖 begin、每个 owner write、outbox、commit;无部分提交。
|
||||
|
||||
### U3. 文档提交纵向事务化
|
||||
|
||||
- **Goal:** 将人工编辑、agent commit、批准/驳回和根指针投影收敛到文档用例事务。
|
||||
- **Requirements:** R1、R5–R9、R19;KTD2–KTD5。
|
||||
- **Dependencies:** U2;实施时独占 `docgov` mutex。
|
||||
- **Files:** `internal/app/docflow/commands.go`、`internal/app/docflow/commands_pg_test.go`、`internal/docgov/engine.go`、`internal/docgov/lease.go`、`internal/docrevision/pg_mutate.go`、`internal/docrevision/service.go`、`internal/docrevision/document_commit_concurrency_pg_test.go`、`internal/server/document_revision_handlers.go`。
|
||||
- **Approach:**
|
||||
1. 为每个文档命令明确 aggregate、expected head、idempotency key 和授权 action。
|
||||
2. 版本账本与 `document_records` 指针先在同一 UoW 写入;M1 保留现有通知兼容适配,但任何核心正确性不得依赖提交后的 `OnOutbox` 回调。
|
||||
3. 按 KTD4 锁定 document root 与 open version;状态转换采用条件更新。
|
||||
4. 提交返回 ledger/root 已持久化结果;workspace projection 和通知由提交后事件处理。
|
||||
5. 保留现有 ETag 语义,统一 agent、人工与批准路径的冲突分类。
|
||||
- **Execution note:** 先补当前行为的 PG characterization,再移动写入所有权;不得先删除旧事务路径。
|
||||
- **Patterns to follow:** `internal/docrevision/pg_mutate.go` 当前同事务投影、`internal/docgov/lease.go` expected SHA、现有 document revision idempotency tests。
|
||||
- **Test scenarios:**
|
||||
- 同一 ETag 两个用户并发编辑,只有一个成功,另一个得到当前 head。
|
||||
- 人工编辑与 agent commit 并发,账本 event_no 连续且 head 指向赢家。
|
||||
- approve 与 reject 并发,只允许一个合法终态。
|
||||
- candidate commit 在 root/version/outbox 任一故障点整体回滚。
|
||||
- 相同 idempotency key 和相同 digest 返回原结果;不同 digest 返回冲突。
|
||||
- 锁超时返回 typed retryable busy,不泄露 SQL 或路径。
|
||||
- 两个 app 实例执行同一请求,结果与单实例一致。
|
||||
- **Verification:** 文档四类命令的跨表不变量由 PostgreSQL 测试证明;`OnOutbox` 不再承担正确性。
|
||||
|
||||
### U4. 建立授权后的文档统一读模型
|
||||
|
||||
- **Goal:** 正文读取不再依赖 handler 拼路径或把一致性错误伪装成 404。
|
||||
- **Requirements:** R1、R3、R4、R14、R15、R19;KTD1、KTD8、KTD9。
|
||||
- **Dependencies:** U1、U3;实施时按 CURRENT 排队使用 `docgov` 和 `authz` mutex。
|
||||
- **Files:** `internal/app/docflow/query.go`、`internal/app/docflow/query_test.go`、`internal/docquery/service.go`、`internal/docquery/service_pg_test.go`、`internal/server/project_doc_handlers.go`、`internal/server/document_revision_authz_test.go`、`web/src/api/projectDocuments.ts`、`web/src/lib/controlledDocHydrate.ts`、`web/e2e/controlled-document-reload.spec.ts`。
|
||||
- **Approach:**
|
||||
1. Principal 由认证适配器构造,DocRef 不携带可覆盖 Principal 的 user/role/duty。
|
||||
2. 先解析数据库 resource→project、workflow、stage 和 duty,再读取 ledger/current pointer。
|
||||
3. workspace projection 只作为校验缓存;缺失时不阻止读取数据库 immutable content。
|
||||
4. ledger/root、projection 和 FAV 的差异映射为 typed consistency state,不再统一变成 404。
|
||||
5. FAV 降级在 U7 接入前保持关闭;接口先保留明确 extension point。
|
||||
6. 列表和版本查询强制分页,BatchGet 首期上限 100;批量授权按 Principal/project 分组并使用有界并发。
|
||||
- **Test scenarios:**
|
||||
- 正常 projection、projection 缺失、projection hash 漂移、ledger 缺失分别返回正确结果或 typed error。
|
||||
- GET、刷新、重登不产生数据库写入、workspace 文件或归档事件。
|
||||
- 匿名、非成员、跨用户会话、跨项目、错误 stage/duty 均拒绝且不泄露文档存在性。
|
||||
- 授权依赖超时/错误时 fail closed。
|
||||
- BatchGet 的 100/101 边界、重复引用、跨项目混合引用和限流拒绝不泄露资源存在性。
|
||||
- 项目 143 等价 hazard 和新项目在页面刷新、restart、rebuild 后正文一致。
|
||||
- **Verification:** 控制台和服务器目标 404/409/projection missing 为零;所有来源分支有服务端与浏览器证据。
|
||||
|
||||
### U5. Workspace capability、lease 与文件提交
|
||||
|
||||
- **Goal:** 从类型和运行时同时禁止跨模块裸路径与跨租户工作区访问。
|
||||
- **Requirements:** R1、R7、R9、R16–R18;KTD7。
|
||||
- **Dependencies:** U1。
|
||||
- **Files:** `internal/workspace/types.go`、`internal/workspace/resolver.go`、`internal/workspace/capability.go`、`internal/workspace/capability_test.go`、`internal/workspace/lease_pg_test.go`、`internal/squad/workspace_adapter.go`、`internal/bizdev/service.go`、`internal/server/project_doc_handlers.go`。
|
||||
- **Approach:**
|
||||
1. WorkspaceRef 删除 Root/OutputDir/ManifestPath,只保留 scope-bound ID、schema version 和 fencing token。
|
||||
2. workspace service 提供限定 artifact key 的 read、atomic writer、commit projection 和 inspect 能力。
|
||||
3. ID 与 lease 绑定 environment、project、run 和 storage identity;所有写入校验 fencing token。
|
||||
4. 使用 realpath/descriptor-based 检查,拒绝 `..`、绝对路径、symlink/hardlink 和根外 rename。
|
||||
5. legacy-v0 workspace 只读;首次受控 Resume 校验后原子升级 v1,并保留兼容备份一个发布周期。
|
||||
- **Test scenarios:**
|
||||
- `..`、绝对路径、编码后的分隔符、空 key、跨 project Workspace ID 全部拒绝。
|
||||
- symlink 和 hardlink 在校验后替换的 TOCTOU 场景仍不能逃逸。
|
||||
- 旧 lease writer 在新 lease 签发后因 fencing token 过期而失败。
|
||||
- 两个 app 实例并发提交同一 projection,reader 只看到完整 marker。
|
||||
- v0 读取、升级失败回滚、未知 major 版本拒绝。
|
||||
- **Verification:** production 包中 workspace 物理路径只存在于 workspace/squadrun adapter;多实例测试不依赖 `sync.Mutex`。
|
||||
|
||||
### U6. Durable outbox、逐消费者 delivery 与 replay
|
||||
|
||||
- **Goal:** 让后台投影、通知和 FAV 发布在崩溃与水平扩容下可恢复。
|
||||
- **Requirements:** R5、R9–R11、R14、R18、R21;KTD5、KTD6。
|
||||
- **Dependencies:** U2;需要新的 additive Goose migration。
|
||||
- **Files:** `deploy/postgres/goose/000xx_*durable_event_delivery.sql`、`internal/events/envelope.go`、`internal/events/outbox.go`、`internal/events/dispatcher.go`、`internal/events/inbox.go`、`internal/events/dispatcher_pg_test.go`、`internal/events/replay.go`、`cmd/events/main.go`。
|
||||
- **Approach:**
|
||||
1. 保留业务 outbox record,新增 event envelope、每消费者 delivery/inbox、attempt、lease、next_attempt_at 和 dead-letter 数据。
|
||||
2. `FOR UPDATE SKIP LOCKED` 只用于小批次 claim;worker 在 claim transaction 外执行 subscriber。
|
||||
3. ack/fail 使用 delivery version/fencing token,过期 worker 不能覆盖新 lease owner。
|
||||
4. 同 aggregate 依据 aggregate version 串行,不同 aggregate 并行;缺号进入等待或 quarantine。
|
||||
5. retry policy 区分 transient、permanent、authorization/integrity failures;后两者默认 dead letter/quarantine。
|
||||
6. replay CLI 先 dry-run,必须限定 consumer/event/project/time/id 范围并记录 operator、reason 和计划 hash。
|
||||
7. 逐个迁移并删除 `OnOutbox` 与闭包桥;切换前 shadow 对账,切换后旧回调不再注册。
|
||||
- **Test scenarios:**
|
||||
- 两个和四个 worker 并发 claim,没有同一 lease 的双 owner。
|
||||
- worker 在副作用前、后、ack 前崩溃,重启后最终只有一个可见业务结果。
|
||||
- 一个 subscriber 永久失败不阻塞其他 subscriber。
|
||||
- lease 过期后旧 worker ack 被 fencing token 拒绝。
|
||||
- 相同 event 重放被 inbox 去重;相同 aggregate 乱序事件不越过缺失版本。
|
||||
- 伪造 producer、跨项目 scope、payload digest 不符进入 quarantine。
|
||||
- dead-letter replay 未授权、无 dry-run 或范围过宽时拒绝。
|
||||
- **Verification:** 删除旧单一 `published_at` 语义前完成双读对账;pending age、attempt、lease steal、dead letter 可观测。
|
||||
|
||||
### U7. FAV 分支审计、终态发布与授权降级读取
|
||||
|
||||
- **Goal:** 将最终成果与 workspace 清理解耦,同时不形成第三套业务真相源。
|
||||
- **Requirements:** R1–R4、R10–R15、R18、R21、R22;KTD8、KTD9、KTD12。
|
||||
- **Dependencies:** U3、U4、U6;先审计 `feature/final-artifact-vault` 相对当前 dev 的完整差异。
|
||||
- **Files:** `internal/artifactvault/`、`deploy/postgres/goose/000xx_*final_artifact*.sql`、`internal/app/docflow/artifact.go`、`internal/docquery/service.go`、`internal/server/vault.go`、`cmd/artifact-vault/`、`internal/artifactvault/*_test.go`。
|
||||
- **Approach:**
|
||||
1. 重用通过审计的 FAV eligibility、staging、publisher、manifest、tombstone 和 scratch recovery;不直接 cherry-pick 未复核的组合根/handler 改动。
|
||||
2. 重新分配最新 Goose 序号,并验证 migration 与 U6 delivery schema 的组合和 Down 边界。
|
||||
3. 文档终态 transaction 冻结精确 payload/SHA 或 immutable blob ref 并写 publish request;publisher 不重读 workspace 或可变消息行。
|
||||
4. docquery 只在正常数据库授权成功后使用 FAV;manifest 只做 scope/integrity 交叉校验,不能授予权限。
|
||||
5. union-deny:运行删除账本或 vault tombstone 任一侧声明删除即拒绝读取/恢复。
|
||||
- **Execution note:** 现有 FAV 分支包含业务代码和 migration,必须先 rebase/merge audit,再按本计划拆分原子提交。
|
||||
- **Test scenarios:**
|
||||
- committed/sealed/approved 文档按准入表归档;ready/rejected/stale/quality_failed 和 workspace 草稿为零。
|
||||
- publish 重复、对象已存在、每个 fsync/rename/marker 崩溃点都可恢复。
|
||||
- workspace 删除后,授权用户可读 verified payload;未授权用户看不到 artifact 存在性。
|
||||
- DB 授权关系缺失、manifest scope 不符、坏 SHA、tombstone、vault 不可用均 fail closed 或返回明确 degraded error。
|
||||
- GET 零数据库写入、零 workspace 写入、零隐式恢复。
|
||||
- 跨项目相同 SHA 不共享删除或密钥边界。
|
||||
- **Verification:** FAV test report 与当前 dev 重放通过;`FAV_DEGRADED_READ` 默认关闭,直到 M2 全部负例通过。
|
||||
|
||||
### U8. TaskRun、RunManifest 与 workspace 清理门禁
|
||||
|
||||
- **Goal:** 任务终态和最终产物在重复 finalize、SSE 断线和 workspace 清理后保持一致。
|
||||
- **Requirements:** R1、R2、R5–R12、R16–R18、R22;KTD5–KTD8。
|
||||
- **Dependencies:** U5、U6、U7。
|
||||
- **Files:** `internal/taskrun/manager.go`、`internal/taskrun/store.go`、`internal/taskrun/finalize.go`、`internal/taskrun/finalize_pg_test.go`、`internal/squad/manifest.go`、`internal/app/stageflow/execute.go`、`internal/server/task_finalize.go`、`internal/server/task_run_idempotent_sse_test.go`。
|
||||
- **Approach:**
|
||||
1. RunManifest 核心字段类型化并持久化规范字节、SHA、workspace/storage identity 和成员列表。
|
||||
2. taskrun terminal finalize transaction 写状态、assistant terminal turn、manifest、artifact staging 和 outbox。
|
||||
3. SSE done 只投影已提交状态;客户端断线与重试复用 task run idempotency key。
|
||||
4. workspace 清理只依赖已冻结 staging 和 policy;需长期保留的最终成果还必须取得 verified receipt。
|
||||
5. backend 由服务端 BackendRef policy 解析,InputBundle 携带数据分类和最小权限范围。
|
||||
- **Test scenarios:**
|
||||
- 同一 finalize 重复调用返回同结果,不重复消息、事件、manifest 或 artifact。
|
||||
- finalize 与 cancel 并发只有一个合法终态。
|
||||
- SSE 在 commit 前后断线并重试,历史中只有一个 assistant turn。
|
||||
- workspace 在 finalize 后立即清理,publisher 仍从 staging 归档原 SHA。
|
||||
- manifest digest、storage identity、artifact member 不一致阻止 verified/cleanup。
|
||||
- 未授权 backend、敏感 InputBundle、凭证回显和 result 残留全部拒绝或清理。
|
||||
- **Verification:** “完成但没有 durable manifest/publish request”和“已显示完成但正文仍模板”两类状态不可产生。
|
||||
|
||||
### U9. 存量回填、migration corpus 与数据生命周期
|
||||
|
||||
- **Goal:** 只保留可解释的演示/回归数据,并持续验证旧数据迁移、重载和受控恢复。
|
||||
- **Requirements:** R2、R12、R13、R21、R22;KTD8、KTD10。
|
||||
- **Dependencies:** U6–U8。
|
||||
- **Files:** `cmd/dataset/`、`internal/dataset/`、`internal/artifactvault/backfill.go`、`scripts/backup-system-db.sh`、`scripts/restore-system-db-drill.sh`、`.doc/test-fixtures/`、`.doc/test-reports/`。
|
||||
- **Approach:**
|
||||
1. 建立 dataset registry,分类 pinned、demo、regression、migration baseline、ephemeral 和 quarantine。
|
||||
2. backfill 只枚举 immutable document snapshot、approved/commit event 和 completed chat turn,禁止扫描 workspace。
|
||||
3. 大表按稳定主键 checkpoint 分批处理;多个 worker 使用 `SKIP LOCKED` 或互斥 shard,限速避免挤占在线连接池。
|
||||
4. 每个 batch 记录 source schema/commit/storage identity、范围、成功、quarantine 和重试水位。
|
||||
5. dev 先蓝绿建立新数据根,导入 6–10 个批准 dataset;旧库/状态根只读 quarantine 7–14 天后,需用户再次批准才销毁。
|
||||
6. 每个 release 验证 clean、oldest-supported、previous、hazard、import、reload、rollback 和 artifact recovery 八条轨道。
|
||||
- **Test scenarios:**
|
||||
- backfill 中断、重复和并发新终态时分母/分子可复算且不重复 artifact。
|
||||
- legacy-v0 workspace、旧 schema、高 ID、projection missing/fork、缺 snapshot 分别升级或 quarantine。
|
||||
- restore 强制 scratch,拒绝 dev/test/main DSN、错误 storage identity、篡改 manifest 和缺权限凭证。
|
||||
- FAV coverage、完整备份 restore 或 migration corpus 任一失败都阻止 destroy。
|
||||
- dev 选择性导入后项目关系、文件 SHA、sequence、授权和 reload 一致。
|
||||
- **Verification:** 数据清理有精确 manifest、可恢复位置、观察窗口和批准记录;不修改历史 Goose。
|
||||
|
||||
### U10. chatlog/contextasm 原地端口化
|
||||
|
||||
- **Goal:** 在不重复付费搬包的前提下分离对话记录和 prompt 上下文装配。
|
||||
- **Requirements:** R7、R14、R15、R19、R20;KTD1、KTD9。
|
||||
- **Dependencies:** M1–M3 go/no-go;必须等待当前 `chat` mutex 释放。
|
||||
- **Files:** `internal/ctxmgr/`、`internal/chat/`、`internal/app/chatflow/`、`internal/ctxmgr/chat_auth_pg_test.go`、`internal/server/chat_history_auth_test.go`。
|
||||
- **Approach:**
|
||||
1. 先定义 chatflow 所需的消费者侧 ChatLog 和 ContextAssembler ports。
|
||||
2. 在现有 ctxmgr 内提供 adapters,迁移调用者并保持表所有权不变。
|
||||
3. 统计接口 fan-in、DTO 转换和同类改动触达文件数;收益成立后再物理拆为 chatlog/contextasm。
|
||||
4. 所有读取携带 Principal/action,不接受请求体 user/project 作为权限事实。
|
||||
- **Test scenarios:**
|
||||
- 刷新前后同一授权消息集合的正文、分类和计数一致。
|
||||
- 跨用户、跨项目、已退出成员和服务端后台导出负例。
|
||||
- context assembly 只读取允许集合,摘要/缓存不放大不可见消息。
|
||||
- 原地 adapter 与最终拆包实现的 contract tests 等价。
|
||||
- **Verification:** 同类对话变更触达面相对基线下降;拆包前已获得独立行为收益。
|
||||
|
||||
### U11. 组合根迁移、事件替换和共享上下文收权
|
||||
|
||||
- **Goal:** 让每个跨模块业务流程具有唯一应用用例 owner,而不是集中在 server/bizdev 闭包和共享指针。
|
||||
- **Requirements:** R5、R7、R9–R11、R14、R15、R19、R20;KTD1、KTD5、KTD6、KTD9。
|
||||
- **Dependencies:** U10;按四个独立子切片执行,不建立一个巨型 Wave。
|
||||
- **Files:** `internal/app/app.go`、`internal/app/chatflow/`、`internal/app/stageflow/`、`internal/app/docflow/`、`internal/server/server.go`、`internal/bizdev/service.go`、`internal/coordinator/`、对应 contract/integration tests。
|
||||
- **Approach:**
|
||||
1. U11a 只把构造和生命周期迁到唯一 app composition root。
|
||||
2. U11b 一次只替换一种闭包事件;每种事件单独迁移、对账和回滚。
|
||||
3. U11c 逐个迁移 ExecuteTask/executeStageInternal 用例,不同时修改无关领域。
|
||||
4. U11d 将 UserProjectContext 改为只读 snapshot + 类型化 ContextUpdate,单一 use case 应用增量。
|
||||
- **Test scenarios:**
|
||||
- app start/stop/restart 不丢 worker,重复启动不创建重复 subscriber。
|
||||
- 每个闭包新旧路径 shadow 结果一致,切换后旧路径无调用。
|
||||
- ContextUpdate 并发应用使用版本检查,不发生字段级 lost update。
|
||||
- server、CLI 和 worker 调用同一 use case 得到一致授权和事务结果。
|
||||
- **Verification:** 每个子切片独立发布、独立回滚;server 不再保存业务闭包,UserProjectContext 不被多方直接修改。
|
||||
|
||||
### U12. 传输边界收口和最终架构门禁
|
||||
|
||||
- **Goal:** 在领域行为稳定后缩减 server/stream 耦合并全面启用已清零规则。
|
||||
- **Requirements:** R14、R18–R21;KTD1、KTD11。
|
||||
- **Dependencies:** U11。
|
||||
- **Files:** `internal/server/`、`internal/stream/transport/`、`scripts/arch-check.sh`、`.doc/system-design/module-boundaries.yaml`、CI 配置、`web/e2e/`。
|
||||
- **Approach:**
|
||||
1. server handler 只保留参数、Principal、use case 调用和 wire serialization。
|
||||
2. SSE transport 只编码中性 progress/event frame,不拥有业务状态或重试决策。
|
||||
3. 对已清零的 import、SQL writer、path、producer/consumer 规则逐项转 block。
|
||||
4. 错误信封和 PI Runner 协议保持独立 follow-up,不进入本单元。
|
||||
- **Test scenarios:**
|
||||
- HTTP、SSE 断线重连和 CLI 对同一业务状态观察一致。
|
||||
- server 新增领域实现 import、SQL 或路径拼接时 CI 失败。
|
||||
- SSE 慢客户端、断开和重复连接不阻塞业务 transaction 或 dispatcher。
|
||||
- 全套授权、重启和多实例回归保持通过。
|
||||
- **Verification:** R1–R7 的修订版规则全 block;server 行数只作观察指标,不作替代行为验收。
|
||||
|
||||
---
|
||||
|
||||
## Verification Contract
|
||||
|
||||
### Evidence layers
|
||||
|
||||
| 层级 | 必须证明 | 不得替代 |
|
||||
|---|---|---|
|
||||
| Unit | 状态机、错误分类、schema、路径和 policy | PostgreSQL 原子性 |
|
||||
| PostgreSQL integration | 事务回滚、锁、幂等、migration、并发 | 浏览器用户体验 |
|
||||
| Fault injection | 每个 commit/delivery/publish 崩溃窗口 | 真实进程 restart |
|
||||
| Concurrency/load | 多 app/worker、热点与非热点资源、积压和公平性 | 正确性断言 |
|
||||
| Real PI | 真实 agent 生成、manifest、finalize、归档 | stub 或固定假输出 |
|
||||
| Browser | 页面创建/打开/编辑/刷新/重登、错误与 degraded 状态 | API 直接调用 |
|
||||
| Restart/rebuild | app、worker、workspace root、存储 identity 重载 | health 单点检查 |
|
||||
| Authorization negative | 匿名/跨用户/跨项目/阶段/duty/后台/recovery | 前端隐藏按钮 |
|
||||
| Recovery | 完整 DB restore、migration corpus、FAV scratch 恢复 | 仅列出 dump 内容 |
|
||||
|
||||
### Repository gates
|
||||
|
||||
- `go vet ./...`
|
||||
- `go test -short ./...`
|
||||
- 目标模块 PostgreSQL 集成和 race 测试;若全包 race 存在已知 TempDir flake,报告必须分离目标模块结果和基建债。
|
||||
- `scripts/arch-check.sh` 对当前里程碑已收紧规则为 block,对未迁移规则输出基线差异。
|
||||
- `web` 单元测试与 production build。
|
||||
- dev 容器必须 rebuild 后检查 `/health` 与 `/ready`,不能用 restart 证明新代码已部署。
|
||||
- 真实 PI、真实浏览器、post-restart 和多用户负例按独立证据分栏。
|
||||
|
||||
### Concurrency test matrix
|
||||
|
||||
| 维度 | 场景 | 必须断言 |
|
||||
|---|---|---|
|
||||
| App replicas | 1/2/4 | 结果和不变量一致,进程内 mutex 关闭仍正确 |
|
||||
| Dispatcher replicas | 1/2/4 | 无双 owner ack,无重复可见副作用,无永久饥饿 |
|
||||
| Resource shape | 同一文档热点/不同文档并行 | 热点正确冲突,非热点不被全局锁串行化 |
|
||||
| Failure point | before commit/after commit/before ack/after side effect | 无丢事件,重复交付幂等 |
|
||||
| Lock behavior | timeout/deadlock/serialization | 分类和完整事务重试正确,无无限等待 |
|
||||
| Lease behavior | expiry/renew/steal/stale fencing | 旧 owner 无法覆盖新 owner |
|
||||
| Load | steady/burst/backlog recovery | 记录 p50/p95/p99、锁等待、连接池、oldest event age |
|
||||
|
||||
### Authorization test matrix
|
||||
|
||||
每个状态改变和读取接口至少覆盖:匿名、已登录非成员、错误项目成员、会话非 owner、错误 duty、错误 stage、过期 lease、跨环境 ID、服务身份越权、授权依赖失败和系统管理员合法路径。
|
||||
FAV 额外覆盖 manifest project 不符、tombstone、删除账本不一致和授权图缺失。
|
||||
状态改变必须覆盖授权检查后的成员撤销、duty 变化、stage 推进和 lease 失效,证明用例在取得资源锁后重新验证当前事实。
|
||||
|
||||
### Migration and rollback matrix
|
||||
|
||||
| 阶段 | Forward proof | Rollback proof |
|
||||
|---|---|---|
|
||||
| Expand | 新 schema 与旧代码兼容 | migration Down 或旧代码继续运行 |
|
||||
| Shadow | 新旧读取差异为零或有解释的 quarantine | 关闭 flag 回旧路径 |
|
||||
| Backfill | checkpoint、幂等、并发新写一致 | 停止 worker,不撤销已安全扩展列 |
|
||||
| Switch | 新 writer 唯一、旧 writer 只读 | flag 回最近兼容 writer |
|
||||
| Observe | restart/rebuild/浏览器/PI/指标稳定 | 切回旧 reader/writer 与只读 quarantine 数据 |
|
||||
| Contract | 引用扫描和用户批准 | contract 后只能逆序部署兼容版本,不能单 commit revert |
|
||||
|
||||
---
|
||||
|
||||
## Risk Analysis and Mitigation
|
||||
|
||||
| 风险 | 触发信号 | 缓解和停止条件 |
|
||||
|---|---|---|
|
||||
| contracts 成为新万能包 | fan-in、共享 DTO、ADR 数持续上升 | 消费者侧端口;按域拆公共契约;超过阈值回评边界 |
|
||||
| 跨属主事务过大 | 锁等待、事务 p99、deadlock 上升 | 缩小原子集合;事务外副作用;固定锁序;停止扩面 |
|
||||
| advisory lock 形成全局瓶颈 | 非热点资源也排队 | 只对项目级不变量使用;key 分区;检查 `pg_locks` |
|
||||
| outbox backlog 放大 | oldest age/attempt/dead letter 超阈值 | 独立 worker 连接预算、批次和退避;按 aggregate 并行 |
|
||||
| poison event 无限重试 | 同 event 高频失败 | typed permanent failure、dead letter、受控 replay |
|
||||
| FAV 成为授权旁路 | DB 关系缺失仍返回内容 | 正常授权先行、union-deny、默认关闭 degraded read |
|
||||
| 工作区链接逃逸 | realpath/scope mismatch | opaque ID、descriptor 检查、fencing、负例测试 |
|
||||
| 回填压垮在线库 | lock wait/replication lag/连接池饱和 | checkpoint、小批次、限速、独立连接预算、可暂停 |
|
||||
| 双读长期不收口 | exception 数和差异长期不降 | 明确 owner、到期日和 go/no-go;禁止无限兼容 |
|
||||
| 物理搬包造成大冲突 | import churn 大于行为收益 | 原地端口化;行为稳定后再移动;按 mutex 排队 |
|
||||
| FAV 分支漂移 | migration 冲突、dev API 已变化 | rebase audit,不整分支盲合;按单元摘取并重测 |
|
||||
| 数据清理误删 | coverage/backup/corpus 任一未知 | 默认不删;蓝绿迁移;quarantine 观察;用户二次批准 |
|
||||
|
||||
---
|
||||
|
||||
## Operational and Rollout Notes
|
||||
|
||||
### Feature flags
|
||||
|
||||
- 新 docquery reader、单写路径、dispatcher consumer、FAV degraded read 和 legacy workspace reader 分别使用独立 flag。
|
||||
- flag 只选择已兼容路径,不能跳过授权、完整性或终态准入。
|
||||
- 每个 flag 有 owner、默认值、环境范围、启用前置和删除里程碑。
|
||||
|
||||
### Resource budgets
|
||||
|
||||
- app transaction、dispatcher、backfill 和 FAV publisher 使用分离的连接池或明确配额,避免后台积压耗尽在线请求连接。
|
||||
- worker batch、lease、heartbeat、retry 和 concurrency 由配置管理;M1/M2 基线报告确定初值和告警阈值。
|
||||
- 对同 aggregate 设置最大在途数 1;跨 aggregate 并行度按数据库与 vault 指标调节。
|
||||
|
||||
以下是首轮试点的安全起始值,不是产品 SLO;压测报告必须记录调整依据:
|
||||
|
||||
| 参数 | 起始值 | 调整约束 |
|
||||
|---|---|---|
|
||||
| 写事务 lock wait | 最多 2 秒且不超过请求剩余 deadline | 不允许无限等待;热点冲突优先返回 typed busy |
|
||||
| serialization/deadlock retry | 最多 3 次,指数退避并带 jitter | 只重跑完整幂等事务 |
|
||||
| dispatcher claim batch | 50 | claim transaction 只认领,不执行 subscriber |
|
||||
| delivery lease/heartbeat | 30 秒 / 10 秒 | heartbeat 失败后旧 worker 不得 ack |
|
||||
| delivery attempts | 12 次后 dead letter | permanent/auth/integrity failure 不做 12 次盲重试 |
|
||||
| retry backoff ceiling | 15 分钟 | oldest age 仍受告警和人工处置约束 |
|
||||
| backfill batch | 每批 200 个 aggregate | 按 lock wait、replication lag 和在线池占用自动降速 |
|
||||
| backfill workers | dev 初始 1,验证后最多 4 | 每个 shard/checkpoint 不重叠 |
|
||||
|
||||
### Observability
|
||||
|
||||
- Dashboard:transaction/lock、document consistency、outbox delivery、workspace lease、FAV publication、authorization deny、backfill/quarantine。
|
||||
- Alert:oldest event age、dead letter、storage identity mismatch、projection mismatch、FAV coverage gap、恢复/删除拒绝。
|
||||
- Trace 使用 correlation/causation ID 串联 HTTP/use case/transaction/event/subscriber,但不得携带正文或 secret。
|
||||
|
||||
### Documentation lifecycle
|
||||
|
||||
- 每个里程碑开始前新建 short-term 和 CURRENT claim。
|
||||
- 每个里程碑结束生成 test report,回链本计划 U-ID 和验收清单。
|
||||
- 完成项移入 archive;未解决问题进入 audit/remediation,不通过口头说明关闭。
|
||||
|
||||
---
|
||||
|
||||
## Sources and Research
|
||||
|
||||
- [模块解耦方案复核](../audit/2026-09-14-module-decoupling-plan-review.md)记录当前源码中的事务、outbox、workspace 和授权缺口。
|
||||
- `internal/docrevision/pg_mutate.go` 是现有账本与根指针同事务模式,U2–U3 不得降低其原子性。
|
||||
- `internal/docduty/revoke.go` 已使用事务级 project advisory lock,是 KTD3 的本地先例。
|
||||
- `internal/taskrun/manager.go`、`internal/taskrun/store.go` 已有进程内幂等锁与数据库唯一键,U8 需要把正确性完全落到跨实例可用的数据库协议。
|
||||
- `feature/final-artifact-vault` 已实现候选 FAV 能力;U7 必须按当前 dev 重新审计,而不是把分支状态当成当前发布事实。
|
||||
- [PostgreSQL `SKIP LOCKED`](https://www.postgresql.org/docs/current/sql-select.html)只用于队列式 claim,不用于普通一致性读取。
|
||||
- [PostgreSQL serialization failure handling](https://www.postgresql.org/docs/16/mvcc-serialization-failure-handling.html)要求 serialization/deadlock 重试覆盖完整事务逻辑。
|
||||
- [OWASP Business Logic Security](https://cheatsheetseries.owasp.org/cheatsheets/Business_Logic_Security_Cheat_Sheet.html)支持服务端重新推导身份、所有权和安全相关状态。
|
||||
|
||||
---
|
||||
|
||||
## Definition of Done
|
||||
|
||||
- [ ] U1–U9 完成并通过 M0–M3 的逐里程碑 go/no-go;U10–U12 只在收益复盘批准后执行。
|
||||
- [ ] 文档提交不存在跨表半完成,所有提交后副作用来自持久事件。
|
||||
- [ ] 多实例、多 worker、崩溃和 lease 过期场景保持相同业务结果。
|
||||
- [ ] workspace 不再是正文或最终 manifest 的唯一事实源,裸路径不跨模块传播。
|
||||
- [ ] FAV 只含终态成果,中间结果准入率为零,授权缺失时不可降级读取。
|
||||
- [ ] 项目 143 等价 hazard 与新项目完成真实 PI、页面刷新、重登、restart/rebuild 和跨用户负例。
|
||||
- [ ] clean/oldest/previous/hazard/import/reload/rollback/artifact recovery 八条迁移轨通过。
|
||||
- [ ] arch-check 规则按纵向切片清零后全部 block,例外有 owner 和到期日。
|
||||
- [ ] CURRENT、FEATURE-MATRIX、gap-matrix、ADR、系统设计、test report 和 checklist 状态一致。
|
||||
- [ ] 放弃方案、临时代码、双写旁路、过期 flags 和无消费者契约已移除,不留在最终 diff。
|
||||
|
||||
## Related Links
|
||||
|
||||
- Audit: [模块解耦方案复核](../audit/2026-09-14-module-decoupling-plan-review.md)
|
||||
- Architecture: [模块化单体解耦架构](../system-design/2026-09-14-module-decoupling-architecture.md)
|
||||
- ADR: [模块化单体解耦](../adr/2026-09-14-modular-monolith-decoupling.md)
|
||||
- Planning task: [本次计划修订任务](../archive/ops/2026-09-14-module-decoupling-remediation-plan.md)
|
||||
- Acceptance: [重构验收清单](../ops/checklists/2026-09-14-module-decoupling-refactor-acceptance.md)
|
||||
- FAV dependency: `feature/final-artifact-vault` 中的 `.doc/remediation/2026-09-14-final-artifact-vault-remediation.md`
|
||||
- Data lifecycle dependency: `feature/final-artifact-vault` 中的 `.doc/remediation/2026-09-14-runtime-data-lifecycle-and-migration-corpus-remediation.md`
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
---
|
||||
title: "workflow-plan 409 冻结冲突整改 + 文档职责可选治理"
|
||||
status: planned
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-14
|
||||
---
|
||||
|
||||
# workflow-plan 409 冻结冲突整改 + 文档职责可选治理
|
||||
|
||||
## 背景
|
||||
|
||||
- Audit: [2026-09-14-workflow-plan-409-frozen-and-optional-duties.md](../audit/2026-09-14-workflow-plan-409-frozen-and-optional-duties.md)
|
||||
- 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)
|
||||
- gap-matrix: [WORKFLOW-PLAN-FROZEN-OPTIONAL-DUTIES](./gap-matrix.md)
|
||||
|
||||
项目 143 已处于 active,后端按设计返回 409 `PLAN_FROZEN`;前端仍展示可编辑表单,错误又只出现在滚动容器顶部,造成“点击无反应”。新增需求是允许部分非必需文档不设置三权,而不是允许项目配置绕过正式工作流的必需文档。
|
||||
|
||||
## 最终语义
|
||||
|
||||
每个文档任务只有以下三种合法状态:
|
||||
|
||||
| 状态 | 表达 | 生成与账本 | 人工审批 | 阶段门禁 |
|
||||
|---|---|---|---|---|
|
||||
| 关闭 | `enabled=false` | 不生成 | 无 | 不参与 |
|
||||
| 启用、无需人工审批 | `enabled=true` 且三职全空 | 仍生成并进入版本账本 | 不创建三权指派;review/approve 不可用 | 不因批准状态阻塞 |
|
||||
| 启用、纳入人工审批 | `enabled=true` 且三职全满、互异、均为在任项目成员 | 正常生成并进入版本账本 | 完整三权链路 | 按工作流定义的 `BlocksWhenEnabled()` 判定 |
|
||||
|
||||
禁止状态:
|
||||
|
||||
- 仅填写 1–2 个职责:HTTP 400,顶层 `VALIDATION_FAILED`,issue code=`DUTY_PARTIAL_ASSIGNMENT`。
|
||||
- 必需、阻断或不可由创建者裁剪的文档三职全空:issue code=`DUTY_ASSIGNMENT_REQUIRED`。
|
||||
- 激活时没有任何三职完整的受治理文档:issue code=`NO_GOVERNED_DOCUMENT`。
|
||||
- 职责人不是在任项目成员:issue code=`DUTY_ASSIGNEE_NOT_ACTIVE_MEMBER`。
|
||||
|
||||
“三职全空”只能称为“无需人工审批”或“不纳入人工审批”,不得称为“非受控”。正文版本、人工修订、权限审计和来源追踪仍然存在。
|
||||
|
||||
## 关键设计决策
|
||||
|
||||
### D1:工作流定义优先,项目配置不能降低强制治理
|
||||
|
||||
用工作流版本中的任务定义判定是否允许全空。仅当文档任务为非必需、非阻断且允许创建者裁剪时,才允许保持启用但三职全空。至少满足 `Required || Blocking || !IsCreatorConfigurable()` 的任务必须三职完整。
|
||||
|
||||
这样既满足“部分文档不设置”,又避免通过清空职责绕过正式工作流门禁。
|
||||
|
||||
### D2:统一职责分类函数,禁止 validator/gate/access 各自推断
|
||||
|
||||
在 `internal/projectinstance` 建立纯函数,例如:
|
||||
|
||||
```go
|
||||
type DutyMode string
|
||||
const (
|
||||
DutyModeNone DutyMode = "none"
|
||||
DutyModePartial DutyMode = "partial"
|
||||
DutyModeFull DutyMode = "full"
|
||||
)
|
||||
```
|
||||
|
||||
`classifyDocDuty`、`docTaskRequiresDuty` 和规范化函数由保存校验、激活校验、预览、门禁、阶段访问共同复用。禁止只在 `gate.go` 临时判断三个 ID 是否为零。
|
||||
|
||||
保存前服务端规范化:
|
||||
|
||||
- `enabled=false`:清空三职,避免冻结快照和 plan hash 残留旧 ID;
|
||||
- 用户选择“无需人工审批”:三职一次性全部清空;
|
||||
- partial 不自动补齐或自动清空,必须明确拒绝。
|
||||
|
||||
### D3:保存与激活分层校验
|
||||
|
||||
- 保存草稿:允许所有可选文档暂时全空,便于分步配置;仍拒绝 partial、重复人员、非成员及强制文档全空。
|
||||
- 激活预览与最终激活:除重复执行结构校验外,至少要求一份 `DutyModeFull` 文档,并重新核对三名职责人仍为 active project member。
|
||||
- 激活令牌不能替代成员复核。成员可能在预览后退出,最终事务必须 fail closed,要求重新预览。
|
||||
|
||||
成员校验必须在服务端完成,不能只依赖 `ProjectSettingsModal.members`。如现有 `projectinstance.Service` 无成员查询能力,注入最小只读接口,不允许让 validator 直接访问 HTTP 或前端数据。
|
||||
|
||||
### D4:门禁、权限与运行时采用同一模式
|
||||
|
||||
- `DutyModeNone`:`DocTaskReadiness.Enabled=true`,但不要求 approved;建议补充 `approval_managed=false`,避免把 `Required=false` 误读为“不生成”。
|
||||
- `DutyModeFull`:保持当前 `BlocksWhenEnabled()` 逻辑;非阻断文档可以有审批链但不阻塞阶段。
|
||||
- 无人工审批文档对已有项目查看权限的成员只读可见;项目创建者可触发生成和人工编辑;其他成员不能 run/edit/review/approve。
|
||||
- `document_duty_assignments` 对 none 模式不写行;运行时 `TaskResolution` 的三个职责 ID 为 0 必须是显式支持的合法状态,不得触发硬编码人员回退。
|
||||
- 激活预览增加“启用文档、受治理文档、无需人工审批文档、职责数”四类统计,并列出例外文档,用户确认前可见。
|
||||
|
||||
### D5:冻结态是独立只读页面状态
|
||||
|
||||
`ProjectSettingsModal` 加入 `mode=loading|planning|frozen|error`,由服务端 `can_edit_plan`、`lifecycle_status` 和 `live_instance` 决定:
|
||||
|
||||
- frozen 模式展示当前工作流、版本、active stage、冻结职责快照和“为什么不能修改”;
|
||||
- 不渲染工作流选择、职责下拉框和“校验并预览”按钮;
|
||||
- 受控终止作为独立的高风险区域,先展示影响预览,不与普通编辑混在一起;
|
||||
- 所有 mutation handler 在发请求前再次检查 `can_edit_plan`,避免陈旧状态误提交。
|
||||
|
||||
前端 API 引入保留 `status/code/message/issues` 的 `ProjectSettingsApiError`。现有 `parseError` 已能读取后端 message,错误码映射的目的不是重复翻译,而是让 UI 能按 `PLAN_FROZEN`、`PLAN_REVISION_CONFLICT`、`ERR_CONCURRENT_SWITCH` 做定向恢复。
|
||||
|
||||
错误区域使用 `role=alert` / `aria-live`,放在操作按钮邻近的 sticky 区域并自动聚焦。若两标签页中一页先激活、另一页后保存,第二页收到 409 后应保留未提交草稿、重新读取服务端状态并切换 frozen,而不是静默丢弃。
|
||||
|
||||
### D6:项目 143 不作为破坏性测试数据
|
||||
|
||||
项目 143 只做页面只读回归:打开设置应直接看到冻结说明和现有快照,不出现可编辑控件,不调用保存接口。不得在验收中终止它。
|
||||
|
||||
业务上确需修改项目 143 时,必须先查看终止影响。现有终止实现会取消运行中任务、把旧实例标为 terminated,并将项目退回 planning;关闭实例的文档/阶段访问会 fail closed,直到重新规划并激活。不能把“终止再配置”描述成无影响的普通编辑。
|
||||
|
||||
## 分波次计划
|
||||
|
||||
| 波次 | 内容 | 完成判据 |
|
||||
|---|---|---|
|
||||
| Wave 0 | 冻结现状、补齐本文语义;为新错误码和 DutyMode 建立契约测试 | 文档审核通过;不改项目 143 |
|
||||
| Wave 1 | 前端 typed API error、frozen 独立视图、sticky/可访问错误、两标签竞态恢复 | active 项目没有编辑控件;陈旧保存 409 可见且转 frozen,草稿不丢 |
|
||||
| Wave 2 | 后端统一 DutyMode、工作流定义约束、partial/required/zero-governance 校验、服务端 active-member 复核、快照规范化 | focused Go tests、handler tests 与 race tests PASS |
|
||||
| Wave 3 | 门禁、readiness、阶段/文档访问、运行时解析、激活预览统计统一采用 DutyMode | none/full/disabled 在 gate、access、snapshot、assignment rows 上一致 |
|
||||
| Wave 4 | 前端逐文档“纳入人工审批”开关;切换为 none 原子清空三职;仅在存在 full 文档时提示需要至少 3 名成员 | 前端 unit/Vitest/build PASS;错误定位到具体文档和字段 |
|
||||
| Wave 5 | dev 集成与真实浏览器验收;新建专用测试项目,真实页面配置、激活、生成和阶段推进;项目 143 只读回归 | test report 落盘;失败/无效运行如实留档 |
|
||||
|
||||
## 工程测试矩阵
|
||||
|
||||
### 后端
|
||||
|
||||
- `classifyDocDuty`:none/partial/full 边界,0、负数、重复 ID。
|
||||
- 强制任务全空拒绝;允许裁剪的非必需任务全空通过。
|
||||
- partial 返回顶层 `VALIDATION_FAILED`,issue 精确到 `task_key.duties`。
|
||||
- 保存时职责人非 active member 拒绝;预览后成员退出,激活再次拒绝并要求重新预览。
|
||||
- disabled/none 保存后冻结快照、plan hash、`document_duty_assignments` 不含旧职责。
|
||||
- 激活计划零 full 文档拒绝;至少一 full + 一 none 成功。
|
||||
- readiness:none 不要求 approved;full 按定义决定是否阻塞。
|
||||
- access:项目成员可 view none;仅创建者可 run/edit;任何人均不能对 none 执行 review/approve。
|
||||
- termination 后旧实例仍 fail closed;重新激活后访问范围来自新快照。
|
||||
|
||||
### 前端
|
||||
|
||||
- active + `can_edit_plan=false` 直接进入 frozen,不显示 selector/dropdown/save。
|
||||
- 409 `PLAN_FROZEN`、`PLAN_REVISION_CONFLICT`、`ERR_CONCURRENT_SWITCH` 保留 status/code 并呈现不同恢复动作。
|
||||
- 错误在长表单底部视口内可见、可聚焦且有 `role=alert`。
|
||||
- 审批开关由 full→none 时三职原子清空;none→full 时提示完整分配。
|
||||
- 少于 3 名成员但所有可选文档为 none 时可保存草稿;存在 full/强制任务时给出定向提示。
|
||||
- 激活预览展示 full/none 数量和具体例外文档。
|
||||
|
||||
## 真实 UI 验收矩阵
|
||||
|
||||
最终产品验收只通过真实浏览器页面完成;不得用 API/DB 直写项目、成员、计划、助手回复或文档来替代。网络响应只作浏览器操作后的旁证。
|
||||
|
||||
1. 项目 143:页面打开设置即显示冻结说明、当前 main/active stage/职责快照;无可编辑表单、无 workflow-plan PUT。
|
||||
2. 新项目 A:至少一份强制/full 文档 + 一份允许裁剪的 none 文档,页面保存、预览、激活成功。
|
||||
3. 系统真实执行 full 文档生成与审批;none 文档真实生成、正文和版本账本可见,但不出现审核/批准动作,且不阻塞阶段推进。
|
||||
4. 新项目 B:只设置编制,页面在对应文档内联拒绝;不得发出保存请求。
|
||||
5. 新项目 C:尝试所有文档 none,激活预览在页面明确拒绝“至少保留一份受治理文档”。
|
||||
6. 两个浏览器标签页:A 页激活,B 页保存旧草稿;B 页显示 409、保留草稿并转 frozen。
|
||||
7. 非创建者项目成员能只读查看 none 文档,但看不到 run/edit/review/approve;项目外用户不可见。
|
||||
8. 页面刷新、退出重登及 app restart 后,frozen 状态、职责快照、full/none 模式、阶段就绪保持一致。
|
||||
|
||||
项目 143 仅做只读验证。所有会改变状态的验收使用新建测试项目。
|
||||
|
||||
## 发布门槛
|
||||
|
||||
- `go vet ./...`、`go test -short ./...`、相关 `-race`、`cd web && npm test && npm run build` 全绿。
|
||||
- 保存、预览、激活三条服务端路径都执行同一结构/成员策略,不能只修前端。
|
||||
- 真实 UI 验收覆盖 frozen、full+none、partial、零治理、并发、权限、刷新/重启。
|
||||
- 报告归档至 `.doc/test-reports/` 并回链;模块状态只依据有效证据更新。
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: [2026-09-14-workflow-plan-409-frozen-and-optional-duties.md](../audit/2026-09-14-workflow-plan-409-frozen-and-optional-duties.md)
|
||||
- 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)
|
||||
- 关联先例: [duty-etag-overwrite 审计](../audit/2026-09-13-document-revision-duty-etag-overwrite.md)
|
||||
- gap-matrix 行: [WORKFLOW-PLAN-FROZEN-OPTIONAL-DUTIES](./gap-matrix.md)
|
||||
@@ -0,0 +1,58 @@
|
||||
---
|
||||
title: "HTTP 与 SSE 公开错误信封整改"
|
||||
status: planned
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
owner: Cursor
|
||||
---
|
||||
|
||||
# HTTP 与 SSE 公开错误信封整改
|
||||
|
||||
## 背景
|
||||
|
||||
Phase 2 复核确认错误信封涉及全部 HTTP 路由、SSE transport 和前端解析,属于独立 wire-contract 改造,不应阻塞持久事件交付。审阅见 [模块解耦 Phase 2 方案审阅](../audit/2026-09-15-module-decoupling-phase2-plan-review.md)。
|
||||
|
||||
## 目标
|
||||
|
||||
所有公开 HTTP/SSE 错误使用版本化、可脱敏、可测试的信封;客户端按 typed code 分支,不解析任意后端文案。迁移保持 additive,breaking 状态码变化必须另写 ADR。
|
||||
|
||||
## 契约
|
||||
|
||||
- 基础字段:`code`、固定安全 `message`、`request_id`、可选 `details`。
|
||||
- 每个 code 单独维护 `details` 公开字段 allowlist;默认空。
|
||||
- 禁止输出 raw error、SQL、堆栈、绝对路径、凭证、prompt、正文和跨租户资源 ID。
|
||||
- 授权失败保持资源存在性不泄露;404/403 选择由现有授权策略决定。
|
||||
- `VERSION_CONFLICT`、`IDEMPOTENCY_CONFLICT`、`VALIDATION`、`AUTHZ` 先建立领域错误到 wire code 的唯一映射。
|
||||
- SSE error frame 与 HTTP 使用同一 code registry 和脱敏器,保留 transport 所需 event metadata。
|
||||
|
||||
## 分波次计划
|
||||
|
||||
| 波次 | 内容 | 验收 |
|
||||
|---|---|---|
|
||||
| H0 | 盘点路由、现有状态码、前端文本匹配和 SSE error frame | 路由矩阵与兼容风险签字 |
|
||||
| H1 | 新增 envelope/code registry/request ID/details allowlist,旧字段 additive 保留 | schema/golden/negative tests |
|
||||
| H2 | 前端逐 code 迁移,未知 code 显示安全通用错误 | 浏览器覆盖冲突、鉴权、校验、未知 code |
|
||||
| H3 | 删除文本匹配和旧字段;若改变状态码先 ADR | 全路由 contract test;回滚窗口关闭 |
|
||||
|
||||
## 权限与安全验收
|
||||
|
||||
- 未授权用户无法从 code/message/details 区分资源存在性、owner 或项目成员。
|
||||
- 任何 internal error 都只返回 request ID;完整诊断仅在受控服务端日志,且经过字段脱敏。
|
||||
- 结构化 validation details 只包含公开字段名和稳定错误码,不回显原始输入。
|
||||
- 日志按 request ID 关联,不把响应脱敏前对象序列化。
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [ ] HTTP 与 SSE schema/golden 入 CI,所有公开端点有矩阵。
|
||||
- [ ] 前端不再按 message substring 分支。
|
||||
- [ ] XSS、路径/SQL/token/prompt/跨租户 ID 泄露负例通过。
|
||||
- [ ] additive、switch、contract、rollback 各有 test report。
|
||||
- [ ] 未改变的状态码保持兼容;breaking 变更有 ADR 与同步发布计划。
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: [Phase 2 方案审阅](../audit/2026-09-15-module-decoupling-phase2-plan-review.md)
|
||||
- 上位路线: [Phase 2 修订计划](./2026-09-15-module-decoupling-ipc-phase2-remediation-plan.md)
|
||||
- Short-term: 实施前另建;H0 盘点见 [research](../ops/research/2026-09-15-http-error-envelope-h0-inventory.md)
|
||||
- 实施 backlog: [long-term Track P](../ops/long-term/2026-09-15-track-p-protocol-implementation.md)
|
||||
- gap-matrix 行: 当前为工程债,不单独作为 Track E 发布 blocker
|
||||
@@ -0,0 +1,47 @@
|
||||
---
|
||||
title: "mock 交付物污染真实项目整改方案(demo 数据环境门控 + 服务端清单对账回收)"
|
||||
status: planned
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
---
|
||||
|
||||
# mock 交付物污染真实项目整改方案(demo 数据环境门控 + 服务端清单对账回收)
|
||||
|
||||
## 背景
|
||||
|
||||
[Audit 2026-09-15](../audit/2026-09-15-mock-deliverables-pollute-real-projects.md):前端硬编码 mock 交付物(projectId 1/2/3/5201/6001+)与真实项目数字 ID 撞车,空项目展示「终审已生效」幻影受控文档与伪造法定职责人;mock 数据无环境门控且已进入生产构建产物;服务端权威清单为空时前端不回收本地多余项。
|
||||
|
||||
## 目标
|
||||
|
||||
1. 任何真实(服务端注册)项目的工作台**只显示**服务端 `document_records` + 该项目新建模板克隆项,永不出现 mock 幻影文档;
|
||||
2. mock/demo 数据仅在显式开启的 demo 构建中生效(构建期注入,默认关闭);
|
||||
3. 生产构建产物中不含 mock 文档正文与 mock 用户权限;
|
||||
4. localStorage 已持久化的 mock 项在升级后一次性回收;
|
||||
5. 前端对服务端清单做**双向对账**:服务端为权威,本地多余受控项下架(复用 ControlledInvalidationPlan/dropRecordKeys 机制)。
|
||||
|
||||
## 分波次计划
|
||||
|
||||
| 波次 | 内容 | 验收 |
|
||||
|------|------|------|
|
||||
| Wave 0 止血(低风险) | 1) `mergeWorkflowDocumentsFromServer` 增加对账回收:`category=workflow` 且 `isLegacyLocalMockDocId(docId)` 的本地项,在服务端清单返回(含空数组)时一律 drop(走 `dropRecordKeys` + 受控失效计划既有管道);2) 新建项目克隆模板的 docId 命名空间(`doc-p{projectId}-*`)与 mock 命名空间隔离校验测试 | test 环境新建项目后清单只剩 `doc-p1-*` 模板项;单测覆盖空清单回收 |
|
||||
| Wave 1 demo 门控 | 1) 所有 demo 种子(mockDocuments/neuropulse/tenProjects/MOCK_USERS/MOCK 权限)收口到 `web/src/data/seeds/` 单一入口,导出统一 `DEMO_SEEDS`;2) 入口处 `if (!import.meta.env.VITE_ENABLE_DEMO_SEEDS) return EMPTY`(构建期常量,生产默认 false);3) `npm run build` 产物 grep 验证不含「4K超高清荧光」等特征串(`VITE_ENABLE_DEMO_SEEDS= npm run build`);4) demo 构建单独脚本 `build:demo` | 产物 grep 断言进 CI/前端测试;demo 模式显式 opt-in |
|
||||
| Wave 2 存量清理 | 1) `loadDeliverables` 加载时一次性迁移:剔除命中 `isLegacyLocalMockDocId` 的持久化项(版本化 storage key bump);2) `loadUsers`/`loadProjects` 同理剔除 mock 用户/mock 项目(保留真实同步数据);3) 迁移写入 `storage.ts` 版本号,幂等可重放 | 升级后 localStorage 无 mock 残留;重复刷新幂等 |
|
||||
| Wave 3 UI 语义防线 | 1) `DeckDrawer`/`DocGovActionBar` 对非服务端注册文档(无 ledger 事实)禁用生命周期徽章/治理按钮,显示「本地示例(不入账本)」占位标签;2) `visibleDeliverables` 统计口径排除 mock ID(防污染项目文档计数) | 空项目不再出现「终审已生效」徽章;组件测试 |
|
||||
| Wave 4 验收与归档 | 1) test 环境真实新建项目全链路(新建→清单→刷新→重启容器)回归;2) dev 环境 id 1–3 项目抽检;3) `go vet` / `go test -short` / `cd web && npm test && npm run build` 全绿;4) test-report 归档 + gap-matrix 行 | 报告归档 `.doc/test-reports/`;gap-matrix 更新 |
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [ ] test 新建项目:交付物清单 0 幻影文档,仅 `doc-p{id}-*` 模板项(lifecycleState=template)
|
||||
- [ ] dev 项目 id 1/2/3:无 doc-001/doc-cusa-* 等幻影项
|
||||
- [ ] 生产构建产物 grep 无 mock 特征串;demo 构建仅显式开启时含种子
|
||||
- [ ] localStorage 升级迁移后无 mock 残留且幂等
|
||||
- [ ] 服务端清单对账:服务端删除/为空时本地对应受控项下架
|
||||
- [ ] 幻影文档(若 demo 模式保留)不带「终审已生效」徽章与治理操作
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: [../audit/2026-09-15-mock-deliverables-pollute-real-projects.md](../audit/2026-09-15-mock-deliverables-pollute-real-projects.md)
|
||||
- Short-term: [../ops/short-term/2026-09-16-clean-test-env-baseline.md](../ops/short-term/2026-09-16-clean-test-env-baseline.md)
|
||||
- Test Report: [../test-reports/2026-09-16-clean-test-env-baseline-test-report.md](../test-reports/2026-09-16-clean-test-env-baseline-test-report.md)
|
||||
- gap-matrix 行: 待补(发布 blocker:治理记录失实 / 跨环境影响)
|
||||
- 既有同域防线: `web/src/features/documentRevision/revisionToolbarMount.ts`(isLegacyLocalMockDocId)、`web/src/lib/controlledDocHydrate.ts`(shouldLoadControlledContent)、`web/src/lib/deliverableSync.ts`(mergeWorkflowDocumentsFromServer)
|
||||
@@ -0,0 +1,342 @@
|
||||
---
|
||||
title: "模块解耦 Phase 2:持久事件交付与后续解耦路线"
|
||||
status: planned
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
type: refactor
|
||||
owner: TBD
|
||||
---
|
||||
|
||||
# 模块解耦 Phase 2:持久事件交付与后续解耦路线
|
||||
|
||||
## 决策摘要
|
||||
|
||||
Phase 2 的核心交付只包含持久事件链:修正事件生产、补齐 PostgreSQL 投递实现、用无副作用 shadow 对账替换闭包桥,并以授权用户刷新/重启后的正文恢复作为停走门。
|
||||
|
||||
结构解耦(D4–D7)是独立轨道;HTTP 错误信封与 PI Runner typed result 各自单独立项。三条轨道分别验收,不能互相阻塞关闭。
|
||||
|
||||
本计划不拆微服务,不引入外部消息基础设施,不合入 FAV 分支,不删除历史数据,也不授权实施、合并或部署。
|
||||
|
||||
## 背景与纠偏
|
||||
|
||||
- 上位约束:[模块化单体解耦 ADR](../adr/2026-09-14-modular-monolith-decoupling.md)、[架构设计](../system-design/2026-09-14-module-decoupling-architecture.md)、[Phase 1 计划](./2026-09-14-module-decoupling-refactor-plan.md)。
|
||||
- 复核结论:[Phase 2 方案审阅](../audit/2026-09-15-module-decoupling-phase2-plan-review.md)。
|
||||
- 现状调研:[IPC/RPC 现状评估](../ops/research/2026-09-15-module-decoupling-ipc-assessment.md)。
|
||||
- `internal/events/pg.go` 目前只有信封写入与 SELECT 型 `ClaimIDs`,没有原子 lease、ack/fail、重试、dead-letter 的生产闭环。`internal/events/dispatcher_test.go` 只证明 `MemoryBus` 语义,不能作为 PG 运行证据。
|
||||
- `docgov` 仅单向依赖 `docrevision` 的 Markdown canonical/hash 工具,不存在生产双向 import 环。
|
||||
- `module-boundaries.yaml` 已有 `event_producers`/`event_consumers`;缺口是映射不完整、运行时注册未与静态清单校验。
|
||||
- `docflow.Commands` 在部分生产 HTTP 路径临时构造,事件 sink 未稳定注入;其 envelope 仍写入 `Environment:"dev"`、`ProjectID:0`。未先修生产入口就开始 shadow,会得到虚假的零差异。
|
||||
|
||||
## 目标与边界
|
||||
|
||||
### Track E:持久事件交付(本计划核心)
|
||||
|
||||
目标:让 notify 与 projection 副作用在重复投递、进程崩溃、租约过期和重启后达到“至少一次投递、恰好一个可见结果”,并能从数据库追查每次 attempt。
|
||||
|
||||
包含 D1、D2、D3、D10、D11。Track E 完成后即可单独关闭,不等待结构或协议轨道。
|
||||
|
||||
### Track S:结构解耦(后续独立 go/no-go)
|
||||
|
||||
目标:移除 bizdev locator,收敛 stageflow/chat/intent 依赖,并消除 `docgov → docrevision` 的剩余工具依赖。包含 D4、D5、D6、D7a、D7b。
|
||||
|
||||
Track S 只有在 Track E 复盘后重新认领 mutex 才能开始;每个单元独立关闭。
|
||||
|
||||
### Track P:外部协议(另立 remediation)
|
||||
|
||||
- P1:HTTP/SSE 错误信封。
|
||||
- P2:PI Runner typed-result-v1 rollout。
|
||||
|
||||
D8、D9 在本文件保留设计约束和立项入口,不属于 Track E/S 的 Definition of Done。独立方案见 [HTTP/SSE 错误信封](./2026-09-15-http-error-envelope-remediation.md) 与 [PI typed-result-v1](./2026-09-15-pi-typed-result-v1-remediation.md)。
|
||||
|
||||
### 明确排除
|
||||
|
||||
- U4/U5 的 path/sql_write 例外清零及其既有 owner。
|
||||
- `feature/final-artifact-vault` 的审计、合入、subscriber 激活与真实副作用验收。本计划只预留 FAV event schema 和 disabled allowlist 条目。
|
||||
- 全量 IPC/RPC、服务拆分、分布式事务协调器。
|
||||
- 破坏性历史清理。旧事件只允许分类、隔离、修复或明确过期;任何删除另走审批计划。
|
||||
|
||||
## 需求与可追踪性
|
||||
|
||||
| ID | 要求 | 交付单元 | 核心验收 |
|
||||
|---|---|---|---|
|
||||
| E1 | PG delivery 状态机可生产运行 | D1 | 真实 PG 多 worker、崩溃点、fencing 测试 |
|
||||
| E2 | 至少一次投递、一个可见结果 | D1/D2 | 副作用幂等键/事务 receipt;重复投递无重复可见结果 |
|
||||
| E3 | 每次 attempt 可审计 | D1 | 不可变 attempt 表,日志不代替数据库审计 |
|
||||
| E4 | 事件作用域真实且授权闭合 | D3/D11 | env/project/service principal/资源复核全部 fail closed |
|
||||
| E5 | 闭包桥安全下线 | D2 | shadow 覆盖门通过;逐消费者切换;一窗口后删 API |
|
||||
| E6 | 静态契约与运行注册一致 | D10 | allowlist 已有段补全;构建时 registry parity 门禁 |
|
||||
| E7 | 历史脏数据不会误消费 | D11 | dry-run 清单;repair/quarantine/expire 决策可审计 |
|
||||
| E8 | 用户刷新恢复 | D2 | 授权 UI 刷新/重启正文一致,无 projection-missing |
|
||||
| S1 | bizdev 不再充当 locator | D4 | 8 个 getter 最终同批删除;无新调用方 |
|
||||
| S2 | 用例类型归属清楚 | D5 | coordinator 不依赖 bizdev DTO |
|
||||
| S3 | 剩余工具依赖消除 | D6 | docgov/docrevision 互不 import;canonical golden 一致 |
|
||||
| S4 | intent/chat 可独立迁移 | D7a/D7b | 两条独立分支、mutex、验收与回滚 |
|
||||
|
||||
## 关键技术决策
|
||||
|
||||
1. **语义不写“exactly once delivery”。** Dispatcher 提供 at-least-once delivery。消费者用唯一键、事务 inbox/receipt、CAS 或 no-replace 提交保证 exactly-one visible outcome。
|
||||
2. **shadow 不执行业务副作用。** 旧闭包仍是唯一真实写路径;shadow 只计算规范化 intended outcome,并写对账记录。禁止“闭包与消费者双写后比较”。
|
||||
3. **独立 worker 进程。** 事件消费落在 `cmd/events`,与 HTTP 进程分开扩缩容;`internal/app` 不重复启动 dispatcher。该选择沿用 Phase 1 U6,避免两种拓扑并存。
|
||||
4. **先证明事件源,再开始计时。** 三条文档链必须在同一 UoW 写入领域变化、envelope 和目标 delivery。PG 测试证明生产入口确实产生事件后,shadow 窗口才有效。
|
||||
5. **每个消费者独立灰度。** 状态为 `off|shadow|live`,按 environment + consumer 配置。notify、workflow advance、projection 分开切换;FAV 保持 off。
|
||||
6. **静态 allowlist 与运行 registry 同源。** `module-boundaries.yaml` 现有映射补全后生成或校验只读 registry manifest;生产禁止未登记的动态注册。
|
||||
7. **历史事件先盘点。** 作用域为 0、环境错误、未知 consumer、序列不连续或 payload schema 未知的旧记录不得自动 live 消费。
|
||||
8. **结构与协议不绑核心关闭。** Track E、S、P 分别有状态、停走门、测试报告和回滚点。
|
||||
|
||||
## 目标拓扑
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
HTTP[server/use case] -->|domain change + envelope + deliveries / one UoW| PG[(PostgreSQL)]
|
||||
WK[cmd/events] -->|atomic lease| PG
|
||||
WK --> N[notify]
|
||||
WK --> A[workflow advance]
|
||||
WK --> P[projection]
|
||||
N -->|idempotency key| PG
|
||||
A -->|transactional inbox| PG
|
||||
P -->|expected head + digest| WS[workspace projection]
|
||||
F[FAV contract] -. disabled .-> WK
|
||||
```
|
||||
|
||||
## 数据模型与并发协议
|
||||
|
||||
### Delivery 状态机
|
||||
|
||||
```text
|
||||
pending -> leased -> acked
|
||||
|-> pending transient failure / lease expiry
|
||||
|-> dead max attempts or explicit permanent failure
|
||||
|-> quarantine scope, schema, integrity or ordering violation
|
||||
```
|
||||
|
||||
- Claim 必须在一个短事务内 `WITH candidates AS (SELECT ... FOR UPDATE SKIP LOCKED LIMIT ...) UPDATE ... FROM candidates ... RETURNING`,同时写 `lease_owner`、递增 `fencing_token`、`lease_until`、`attempt`。现有 SELECT-only `ClaimIDs` 不满足此条件。
|
||||
- Handler 在 claim 事务外执行。Fencing token 必须随 consumer command 传到最终副作用提交点;数据库副作用在同一事务校验 token,projection marker 使用 expected version + 单调 token。Ack/fail 也必须匹配 `event_id + consumer + lease_owner + fencing_token`。旧 token 的副作用和 ack/fail 都必须失败。
|
||||
- 长任务按受保护的 token 续租;heartbeat 失败立即取消 handler。停机先停止 claim,再等待 inflight 或安全释放租约。
|
||||
- 同一 consumer + aggregate 同时最多一个 inflight;不同 aggregate 可并行。不能把领域版本号直接假设为无缺口事件序号。
|
||||
- D11 必须在以下两种模型中选一并写 ADR/迁移:独立无缺口 event sequence;或 consumer checkpoint + 首事件 bootstrap。未决前禁止启用 gap 阻塞。
|
||||
|
||||
### 副作用原子性
|
||||
|
||||
| 消费者 | 可见结果契约 | 崩溃窗口处理 |
|
||||
|---|---|---|
|
||||
| notify | `event_id + recipient + notification_kind` 唯一键 | 通知写入与 inbox 同一 PG 事务;重放命中唯一键即视为成功 |
|
||||
| workflow advance | `event_id + transition` 唯一 receipt;重新读取当前状态和权限 | 领域转换、outbox、inbox 同一 UoW;状态已前进时按 receipt 判定 |
|
||||
| projection | `document_id + source_snapshot_id + digest` no-replace;expected head | 文件先写临时对象并 fsync,再原子提交 marker;重放核对 digest |
|
||||
| FAV | 本计划不激活 | 由 FAV 审计定义 source-event/digest no-replace 契约 |
|
||||
|
||||
副作用完成后、delivery ack 前必须注入崩溃。恢复后可重复调用 handler,但最终只有一个可见结果。
|
||||
|
||||
### 审计表
|
||||
|
||||
Additive migration 新增不可变 `event_delivery_attempts`,至少记录:event、consumer、attempt、lease owner、fencing token、started/finished、outcome、typed error code、correlation ID。`event_deliveries` 只保存当前游标和状态。
|
||||
|
||||
attempt、dead-letter、shadow reconciliation 只存 ID、digest、typed code 和字段 allowlist 生成的摘要。禁止保存原始 payload、SQL error、绝对路径、token、prompt 或正文。
|
||||
|
||||
## 权限模型
|
||||
|
||||
| 动作 | 主体 | 必须校验 | 禁止 |
|
||||
|---|---|---|---|
|
||||
| 普通消费 | 每个 consumer 独立 service principal | environment、project、consumer、action;副作用前重读资源归属和当前状态 | 继承原用户会话、跨项目查询、共享万能 principal |
|
||||
| shadow | ops service principal | 只写 reconciliation;不持有业务写权限 | 调用真实通知/推进/投影写端口 |
|
||||
| replay dry-run | 具备事件运维 capability 的管理员 | env/project/consumer/event 范围、reason、approval ref | 无范围全库扫描、原始 payload 回显 |
|
||||
| replay apply | 同一操作者能力 + 未过期 plan digest | apply 参数必须与 dry-run digest 完全相同 | 现场改范围;绕过资源当前授权 |
|
||||
| 多项目/批量 replay | 两人批准 | operator 与 approver 分离;不可变审计 | 单人直接执行 |
|
||||
|
||||
worker 数据库角色只授予其拥有表和调用端口所需权限。Replay 是应用用例,不提供裸 SQL 运维入口。授权失败、资源已转移、project 不存在或 env 不匹配一律 quarantine,不重试为 transient。
|
||||
|
||||
## 分波计划
|
||||
|
||||
### E0A:生产者、契约与旧数据门(D3、D10、D11)
|
||||
|
||||
进入条件:认领 `events/app/arch` mutex;dispatcher 保持 off。
|
||||
|
||||
交付:
|
||||
|
||||
1. 组合根构造唯一 `docflow.Commands`,向 server 注入 UoW、PGSink、environment与 project resolver;禁止 HTTP handler 临时漏注入。
|
||||
2. candidate-ready、downstream-impact、approved 三条链在领域提交同一 UoW 内写 envelope 和目标 delivery。
|
||||
3. 修正 `Environment/ProjectID`,缺值 fail closed;先清点历史 `0/dev` 记录。
|
||||
4. 补全现有 event allowlist,校验生产者、消费者、payload schema、运行 registry parity。
|
||||
5. 生成历史事件 dry-run manifest,逐条分类为 safe、repair、quarantine、expire;不删数据。
|
||||
6. 决定连续性模型,审计 `(aggregate_type, aggregate_id, aggregate_version)` 唯一约束是否允许同一版本多个事件;必要时 additive migration。
|
||||
|
||||
退出门:真实 PG 测试证明每条生产链产生正确 envelope/delivery;历史清单有审批结论;未登记事件和动态 consumer 构建失败。
|
||||
|
||||
### E0B:PG dispatcher 基座(D1)
|
||||
|
||||
进入条件:E0A 全部通过;旧数据不会进入 live claim。
|
||||
|
||||
交付:
|
||||
|
||||
1. 完成原子 lease、heartbeat、fenced ack/fail、backoff、dead/quarantine 和 attempt audit。
|
||||
2. 新建 `cmd/events`;每个环境单独容器、配置和 DB 连接预算。HTTP Runtime 不启动 worker。
|
||||
3. 增加 readiness(DB、registry、schema)、liveness、queue age、oldest pending、claim/ack/fail/fenced、attempt latency、dead/quarantine 指标。
|
||||
4. 默认从 Phase 1 基线起步:batch 50、lease 30s、heartbeat 10s、max attempts 12、backoff ceiling 15m;压测报告才能调整。
|
||||
5. 以 1/2/4 worker 验证无双 lease、跨 aggregate 并行、同 aggregate 串行、连接池有界和公平性。
|
||||
|
||||
退出门:PG 集成与 race 测试通过;在副作用后/ack 前、续租前后、停机 drain 等崩溃点均可恢复;资源预算和 p50/p95/p99 基线归档。
|
||||
|
||||
### E1A:notify shadow 与切换(D2-notify)
|
||||
|
||||
1. 旧闭包产生 canonical outcome;shadow handler 产生 intended outcome。两者经同一规范化器比较收件人、类型、去重键、payload digest。
|
||||
2. E0A 根据经作用域校验和审批的前 7 天有效事件基线为每个 event type 预登记最小样本 N,N 不低于 30;低流量分支补确定性 replay fixture。窗口不少于 3 个完整日,并覆盖成功、授权拒绝、重复和 permanent failure。
|
||||
3. 任一未解释 diff、越权、原始 payload 泄露或样本不足均重置窗口。
|
||||
4. `off|shadow|live` 是带 revision 的集群级受控状态,不是单实例环境变量。先部署同时理解新旧模式的兼容代码,drain 并确认旧实例全部退出,再原子切换权威写者。
|
||||
5. 先把 notify 置 live;闭包 notify 路径置 off。保留显式回滚开关一个发布窗口。
|
||||
|
||||
退出门:重复投递只有一个通知;重启不丢;correlation ID 可查 producer→attempt→receipt;回滚演练通过。
|
||||
|
||||
### E1B:workflow advance shadow 与切换(D2-advance)
|
||||
|
||||
批准事务必须发布 typed approved event。Consumer 在副作用前重读 document/project/workflow 状态和 service principal 权限。按 E1A 同样的 coverage gate 切换,随后移除批准 hook 注册。
|
||||
|
||||
退出门:并发批准只推进一次;陈旧或跨项目事件 quarantine;阶段推进产生的下游事件保持 causation/correlation;回滚演练通过。
|
||||
|
||||
### E1C:projection 恢复纵切(D2-projection)
|
||||
|
||||
在副作用前、副作用后/ack 前、lease 过期后三个位置终止 worker并重启。授权用户通过真实页面刷新和重新打开文档,正文必须与数据库 head/snapshot digest 一致,不出现 `projection missing`,不产生重复版本。未授权用户仍得到非泄露式拒绝。
|
||||
|
||||
退出门:真实 PG + browser + worker restart 报告通过;按 correlation ID 能还原完整链路。FAV 仍为 off。
|
||||
|
||||
### E2:核心收口
|
||||
|
||||
- 删除 `OnOutbox =`、`AddOnApprovedHook(` 等生产注册点。
|
||||
- 保留 API 一个发布窗口后,再独立 contract 提交删除字段/方法本体。
|
||||
- Track E 的 release blocker 关闭;Track S/P 保持各自状态,不拖延此关闭。
|
||||
|
||||
## 实施单元明细
|
||||
|
||||
### D1:PG dispatcher 与 attempt audit
|
||||
|
||||
主要文件:`deploy/postgres/goose/<next>_event_dispatcher.sql`、`internal/events/pg.go`、`internal/events/dispatcher.go`、`cmd/events/main.go`、环境 compose/config。
|
||||
|
||||
必须交付 E0B 的状态机、进程拓扑、连接预算、指标和真实 PG 故障注入。MemoryBus 测试只作快速 characterization,不计生产验收。
|
||||
|
||||
### D2:闭包迁移
|
||||
|
||||
主要文件:`internal/docrevision/service.go`、`internal/docgov/engine.go`、`internal/app/app.go`、`internal/app/docnotify`、projection owner。
|
||||
|
||||
拆成 notify、workflow advance、projection 三个 short-term。Shadow 只写 reconciliation;每个消费者都有独立 `off|shadow|live`、停走门和回滚演练。最后一个 live 窗口结束后才能删除 hook API。
|
||||
|
||||
### D3:事件生产与作用域
|
||||
|
||||
主要文件:`internal/app/docflow/commands.go`、server 注入点、`internal/taskrun/finalize.go`。
|
||||
|
||||
修复生产入口漏注入和硬编码。事件构造必须从已授权服务端上下文与持久记录取得 environment/project;客户端字段不可信。FAV staging 调用不属于 Track E;FAV disabled 时,生产链不得写 staging、artifact 或 publication 记录。`Fav.StageAgentCommit(ctx, 0, ...)` 的真实 project scope 修复随独立 FAV 审计实施。
|
||||
|
||||
### D10:事件契约与 registry parity
|
||||
|
||||
主要文件:`.doc/system-design/module-boundaries.yaml`、`internal/archtest`、registry manifest 生成/校验代码。
|
||||
|
||||
不是“新增 allowlist 段”,而是补全已有段并把 payload schema/version、合法 producer、合法 consumer、enabled state 一并校验。运行 registry 必须是静态清单的子集;FAV 条目标记 disabled。
|
||||
|
||||
### D11:历史数据与序列安全
|
||||
|
||||
主要文件:additive migration、只读 inventory/replay use case、审计报告。
|
||||
|
||||
交付历史清单、序列模型、约束审计、repair/quarantine/expire 规则。修复必须保留 old/new digest、operator、reason、approval;禁止原地无审计改值。
|
||||
|
||||
### D4:bizdev locator 最终移除
|
||||
|
||||
先加 no-new-callers 门禁,再分批把调用方迁移到消费者端口。准备工作可分批;8 个 getter 的最终删除必须在一个 contract 提交完成。规则只禁止领域/用例 API 暴露、返回或转发 pool/tx;允许 app/cmd 组合根向表属主构造器注入 pool,也允许登记属主从 opaque TxScope 解出 tx。
|
||||
|
||||
### D5:stageflow 类型归属
|
||||
|
||||
`stageflow` 定义 use-case request/result,并在 app 边界适配 bizdev 领域类型。行为方法不能机械复制成 DTO。用 mapping golden 和 characterization 锁定语义;coordinator 最终不 import bizdev。
|
||||
|
||||
### D6:移除单向 canonical 工具依赖
|
||||
|
||||
当前不是循环。把 Markdown canonicalization 与 SHA 作为一个内聚的共享行为模块(建议 `internal/doccontent`)提取,提供 golden vectors。禁止把带行为的 canonicalizer 塞入 vocabulary。完成后 docgov/docrevision 互不 import。
|
||||
|
||||
D6 不依赖 D4/D5,只受 docgov/docrevision mutex 与 U4/U5 排期约束。
|
||||
|
||||
### D7a:intent 与 bizdev 解绑
|
||||
|
||||
为 intent 注入最小只读消费者端口;单独分支、characterization、mutex 和验收。不得等待 chat 迁移。
|
||||
|
||||
### D7b:chat 编排迁入 chatflow
|
||||
|
||||
逐用例迁移,保留 handler characterization。只有 D4 提供所需端口后才开始;禁止“一次搬空包”。每批收紧一条 import 规则并可独立回滚。
|
||||
|
||||
### D8:HTTP/SSE 错误信封立项约束
|
||||
|
||||
另建 remediation。公开 wire 至少为 `code/message/request_id/details?`;`message` 使用固定安全文案,`details` 按 code 维护公开字段 allowlist。不得回传 raw error、SQL、路径、凭证、prompt、正文或跨租户 ID。授权拒绝保持资源存在性不泄露。全路由、SSE 与前端迁移各有 golden/negative test。
|
||||
|
||||
### D9:PI typed-result-v1 rollout 立项约束
|
||||
|
||||
另建 remediation,不称“协议 v2”。只有 typed 字段完全缺失且握手明确声明旧 Runner 时才允许 legacy;typed 字段存在但 schema/digest/path/run_id/size 校验失败必须 fail closed,禁止降级。真实 PI E2E 覆盖取消、超时、未知 schema、超限输出、secret/prompt 注入与 downgrade attack。
|
||||
|
||||
## 迁移、部署与回滚
|
||||
|
||||
| 阶段 | 部署顺序 | 可回滚动作 | 禁止 |
|
||||
|---|---|---|---|
|
||||
| expand | additive migration → producer 修复 → registry | worker 保持 off;回滚应用不删表 | 旧数据直接 live claim |
|
||||
| shadow | worker shadow → reconciliation | consumer 置 off;保留记录 | 执行业务副作用;清空 diff |
|
||||
| switch | 部署兼容代码 → drain 旧实例 → 记录 backlog 水位 → 原子切换单 consumer live/闭包 off | 暂停 claim,核对已执行 receipt 与 backlog,再 live off + 对应闭包 on;只在兼容窗口内 | 滚动部署时同时开启两条真实写路径 |
|
||||
| contract | 一发布窗口后删 hook API | 通过新提交恢复,不回滚 schema | 删除 delivery/attempt 历史 |
|
||||
|
||||
回滚期间禁止同时 replay。恢复 live 前必须重新做 backlog dry-run,并确认旧 lease 已失效。Migration 只 additive;任何表/列删除另立计划。
|
||||
|
||||
## 分支、mutex 与交付件
|
||||
|
||||
| 单元 | mutex | 分支示例 | 独立报告 |
|
||||
|---|---|---|---|
|
||||
| D3/D10/D11 | events + app + arch | `fix/event-production-scope-contract` | E0A |
|
||||
| D1 | events + deploy | `feature/events-dispatcher-pg` | E0B |
|
||||
| D2-notify | events + docnotify | `fix/event-notify-cutover` | E1A |
|
||||
| D2-advance | events + workflow | `fix/event-workflow-cutover` | E1B |
|
||||
| D2-projection | events + docgov | `fix/event-projection-recovery` | E1C |
|
||||
| D4 | bizdev | `fix/bizdev-locator-removal` | S1 |
|
||||
| D5 | stageflow + coordinator | `fix/stageflow-type-ownership` | S2 |
|
||||
| D6 | docgov + docrevision | `fix/doccontent-canonical-boundary` | S3 |
|
||||
| D7a | intent | `fix/intent-bizdev-boundary` | S4a |
|
||||
| D7b | chat + chatflow | `fix/chatflow-orchestration-boundary` | S4b |
|
||||
|
||||
每行先建 short-term 并登记 CURRENT。合入 dev 与共享容器验证必须占集成槽位。
|
||||
|
||||
## 验收与停走门
|
||||
|
||||
### Track E Definition of Done
|
||||
|
||||
- [ ] E1–E8 均有证据链接;E0A/E0B/E1A/E1B/E1C 各有独立 test report。
|
||||
- [ ] PG 状态机、attempt audit、1/2/4 worker、race、崩溃点、fencing、顺序、背压和连接预算通过。
|
||||
- [ ] notify/workflow/projection 分别完成 shadow coverage、切换和回滚演练;FAV 保持 disabled。
|
||||
- [ ] 生产注册代码无 `OnOutbox =`、无 `AddOnApprovedHook(`;不存在 HTTP 与 worker 双重接线。
|
||||
- [ ] 授权 UI 在三类 worker 重启点刷新/重开正文一致;未授权与跨项目负例通过。
|
||||
- [ ] replay dry-run/apply digest、service principal、字段脱敏、双人批量审批负例通过。
|
||||
- [ ] arch-check block、`go test -race` 目标包、`go test -short ./...`、PG 集成、browser/restart 全绿。
|
||||
- [ ] CURRENT、FEATURE-MATRIX、gap-matrix 只关闭事件可靠性 blocker,不把 Track S/P 写成已完成。
|
||||
|
||||
### Track S 单元 DoD
|
||||
|
||||
D4–D7b 各自满足需求表中的 S1–S4、独立测试报告和 arch rule 收紧即可关闭;无需等待其他结构单元。
|
||||
|
||||
### Track P 立项门
|
||||
|
||||
D8、D9 各有独立 remediation、owner、范围、兼容矩阵、negative tests 和真实验收计划。本 Phase 2 不要求其实现完成。
|
||||
|
||||
## 风险与控制
|
||||
|
||||
| 风险 | 控制 |
|
||||
|---|---|
|
||||
| shadow 因无事件源虚假通过 | E0A 先证明每条生产入口写 envelope/delivery,之后才开始计时 |
|
||||
| 领域版本缺号永久阻塞 | D11 明确 event sequence 或 checkpoint/bootstrap,不把 version 当连续事件号 |
|
||||
| 副作用成功但 ack 丢失 | 每消费者幂等契约;真实崩溃注入;fenced ack |
|
||||
| 重试覆盖历史 | immutable attempts;delivery 只存当前状态 |
|
||||
| 脏旧事件跨环境/项目执行 | inventory + quarantine;资源当前授权复核;service principal 最小权限 |
|
||||
| worker 抢光连接 | 独立 pool 预算、inflight 上限、queue/backpressure 指标、压测后调参 |
|
||||
| poison event 阻塞 aggregate | quarantine 需显式审批;不静默跳号;其他 aggregate 继续 |
|
||||
| shadow/replay 泄密 | schema 字段 allowlist、digest 摘要、无 raw payload/error |
|
||||
| FAV 拖住核心 | 只预留 disabled 契约;激活归独立 FAV 计划 |
|
||||
| 结构改造扩大爆炸半径 | no-new-callers 先行;小批迁移;最终 getter 原子删除 |
|
||||
|
||||
## 相关链接
|
||||
|
||||
- [方案审阅](../audit/2026-09-15-module-decoupling-phase2-plan-review.md)
|
||||
- [现状调研](../ops/research/2026-09-15-module-decoupling-ipc-assessment.md)
|
||||
- [Phase 1 计划](./2026-09-14-module-decoupling-refactor-plan.md)
|
||||
- [模块化单体 ADR](../adr/2026-09-14-modular-monolith-decoupling.md)
|
||||
- [模块边界清单](../system-design/module-boundaries.yaml)
|
||||
- [Track E 任务入口](../ops/short-term/2026-09-15-durable-event-track-e.md)
|
||||
- [HTTP/SSE 错误信封独立方案](./2026-09-15-http-error-envelope-remediation.md)
|
||||
- [PI typed-result-v1 独立方案](./2026-09-15-pi-typed-result-v1-remediation.md)
|
||||
- [发布缺口 SSOT](./gap-matrix.md)
|
||||
@@ -0,0 +1,60 @@
|
||||
---
|
||||
title: "PI Runner typed-result-v1 迁移方案"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
owner: Cursor
|
||||
---
|
||||
|
||||
# PI Runner typed-result-v1 迁移方案
|
||||
|
||||
## 背景
|
||||
|
||||
PI Runner 已有 HTTP/Bearer 传输边界,但结果仍兼容 stdout/result.json。该工作是 Runner、taskrun、agent adapter 和真实 PI E2E 的独立协议迁移,不应称“协议 v2”,也不阻塞持久事件交付。
|
||||
|
||||
## 目标
|
||||
|
||||
`/v1/run` 返回带 schema version、run identity、member 清单、digest 和 typed outcome 的 `result_v1`。服务端严格校验后持久化;legacy 只在明确的旧 Runner 能力握手下保留一个发布窗口。
|
||||
|
||||
## 契约与降级规则
|
||||
|
||||
- JSON Schema:`configs/schemas/pi-run-result-v1.json`,canonical JSON 与 digest 规则固定。
|
||||
- 结果至少包含 `schema_version`、`run_id`、`members[]`、typed success/error、retryable、content digest;member kind 使用 allowlist。
|
||||
- Runner capability/handshake 明确声明是否支持 typed result,并与响应绑定。
|
||||
- typed 字段完全缺失且握手声明旧 Runner 时,才允许 legacy。
|
||||
- typed 字段存在但 schema、digest、run ID、member path、size 或 secret 检查失败时 fail closed,禁止 fallback。
|
||||
- 文件路径必须落在本次 run 的受控输出根;拒绝绝对路径、`..`、symlink escape 和超限成员。
|
||||
- error 分类和 retryable 由 allowlist 决定,不接受模型任意字符串控制重试。
|
||||
|
||||
## 分波次计划
|
||||
|
||||
| 波次 | 内容 | 验收 |
|
||||
|---|---|---|
|
||||
| P0 | 盘点 legacy 输出、最大体积、取消/超时语义和真实 Runner 版本 | compatibility matrix 与 schema review |
|
||||
| P1 | Runner additive 输出 `result_v1`,旧字段保留 | Runner schema/golden、大小/路径/secret 负例 |
|
||||
| P2 | Go parser typed-first 严格校验,按握手决定 legacy | downgrade、未知 major、digest/run mismatch fail closed |
|
||||
| P3 | dev 真实 PI 双轨对账一个发布窗口 | `RUN_PI_E2E=1`;取消、超时、成功、失败均一致 |
|
||||
| P4 | 删除 legacy parser/字段 | contract test 与前滚/回滚说明归档 |
|
||||
|
||||
## 高并发与安全
|
||||
|
||||
- `run_id`、request id、project/environment 和 backend identity 全链关联;禁止一个 run 接受另一个 run 的结果。
|
||||
- Parser 在分配大对象前执行 body/member 数量与尺寸上限;压缩输入限制解压比。
|
||||
- cancel 与 result 竞争使用单调终态:只允许一个 terminal outcome,晚到结果审计后丢弃。
|
||||
- Runner 输出视为不可信输入;字段、路径、MIME、编码和文本均需验证。不得把 prompt、token 或完整模型 stderr 放入结果或公开日志。
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] Schema/golden 在 Runner 与 Go 两侧共享并入 CI。
|
||||
- [x] typed-present-invalid 永不 fallback;handshake downgrade attack 负例通过。
|
||||
- [x] 并发 run/result 串线、cancel/result 竞争、超限与 path escape 负例通过。
|
||||
- [x] 真实 PI E2E 覆盖成功、typed error、取消、超时与未知 schema。
|
||||
- [x] legacy 删除前完成一个发布窗口对账和回滚演练。
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Audit: [Phase 2 方案审阅](../audit/2026-09-15-module-decoupling-phase2-plan-review.md)
|
||||
- 上位路线: [Phase 2 修订计划](./2026-09-15-module-decoupling-ipc-phase2-remediation-plan.md)
|
||||
- Short-term: 实施前另建;P0 矩阵见 [research](../ops/research/2026-09-15-pi-typed-result-p0-matrix.md)
|
||||
- 实施 backlog: [long-term Track P](../ops/long-term/2026-09-15-track-p-protocol-implementation.md)
|
||||
- gap-matrix 行: 当前为工程债,不单独作为 Track E 发布 blocker
|
||||
@@ -0,0 +1,55 @@
|
||||
---
|
||||
title: Demo/测试数据污染整改方案
|
||||
status: done
|
||||
created: 2026-09-16
|
||||
updated: 2026-09-16
|
||||
owner: Cursor-Auto
|
||||
branch: fix/demo-data-pollution-web
|
||||
mutex: web
|
||||
---
|
||||
|
||||
# Demo / 测试数据污染整改方案
|
||||
|
||||
## 目标
|
||||
|
||||
生产构建默认无演示文案;权威服务端空清单回收本地 mock;DB 演示项目不进列表;main 拒绝 stub。
|
||||
|
||||
## 波次与状态
|
||||
|
||||
| Wave | 内容 | 状态 |
|
||||
|------|------|------|
|
||||
| 0 | `isDemoSeedDocId` + `mergeWorkflowDocumentsFromServer` 空清单 drop | done |
|
||||
| 1 | `VITE_ENABLE_DEMO_SEEDS` + `@demo-seeds` alias + `check-prod-bundle.sh` | done |
|
||||
| 2 | `purgeDemoSeedsFromLocalStorage` 幂等迁移 | done |
|
||||
| 3 | DeckDrawer「本地示例」徽章;职责人默认值清空 | done |
|
||||
| 4 | goose `00046` retire projects + `00047` retire sessions + list/`ListChatSessions` 过滤 | done |
|
||||
| 5 | `ResolveBackendInEnv` main/prod 拒 stub | done |
|
||||
| 6 | 审计/整改/报告/gap-matrix | done |
|
||||
|
||||
## 关键实现
|
||||
|
||||
- 判定:[`web/src/data/demoSeedIds.ts`](../../web/src/data/demoSeedIds.ts)
|
||||
- 门控:[`web/vite.config.ts`](../../web/vite.config.ts) alias `@demo-seeds` → enabled/disabled
|
||||
- 同步:[`web/src/lib/deliverableSync.ts`](../../web/src/lib/deliverableSync.ts)
|
||||
- DB:[`deploy/postgres/goose/00046_2026-09-16-retire-demo-ten-projects.sql`](../../deploy/postgres/goose/00046_2026-09-16-retire-demo-ten-projects.sql)
|
||||
- Stub:[`internal/taskrun/backend.go`](../../internal/taskrun/backend.go)
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 默认 `npm run build` 后 `check-prod-bundle.sh` PASS
|
||||
- [x] 空 server 清单 drop demo-seed 单测 PASS
|
||||
- [x] `ResolveBackendInEnv(..., "main")` 拒 stub 单测 PASS
|
||||
- [x] 共享环境 migrate `00046`/`00047` 后列表无 6001–6010(dev schema 47)
|
||||
- [x] 新建空项目 UI/API 交付物无伪造 approved(项目 6357 documents=0)
|
||||
|
||||
## 启用 Demo(仅本地/评审)
|
||||
|
||||
```bash
|
||||
VITE_ENABLE_DEMO_SEEDS=true npm run dev
|
||||
```
|
||||
|
||||
## Follow-up(P2,不挡合入)
|
||||
|
||||
- stub 旁路:`resolveTaskBackend` 双重失败返回 `""` 时 squad 回落 `cfg.AgentBackend`;建议 main/prod 启动 fail-fast 校验 `AGENT_BACKEND≠stub`
|
||||
- `purgeDemoSeedsFromLocalStorage` 对 projectId 1/2/3 无 serverIds 守卫,可能清掉 test 环境真实本地会话缓存;长期改为按 `sess-neuropulse-*` / `sess-wangjing-*` 前缀或注释权衡
|
||||
- 姊妹分支 `fix/clean-test-env-baseline` 重叠前端清理已放弃;已挑拣 `a91a031`(`SEED_DEMO_USERS=false`)与 2026-09-15 审计回链
|
||||
@@ -3,6 +3,11 @@
|
||||
| 文档 | 说明 |
|
||||
|------|------|
|
||||
| [gap-matrix.md](./gap-matrix.md) | 发布缺口 SSOT |
|
||||
| [2026-09-14-module-decoupling-refactor-plan.md](./2026-09-14-module-decoupling-refactor-plan.md) | 纵向绞杀、UnitOfWork、高并发互斥、可靠事件、逐动作授权、FAV、迁移与恢复的详细重构计划 |
|
||||
| [2026-09-15-module-decoupling-ipc-phase2-remediation-plan.md](./2026-09-15-module-decoupling-ipc-phase2-remediation-plan.md) | Phase 2 修订版:Track E 持久事件交付先行;Track S 结构解耦独立 go/no-go;HTTP 与 PI 协议另立 remediation([审阅](../audit/2026-09-15-module-decoupling-phase2-plan-review.md);[调研](../ops/research/2026-09-15-module-decoupling-ipc-assessment.md)) |
|
||||
| [2026-09-15-http-error-envelope-remediation.md](./2026-09-15-http-error-envelope-remediation.md) | HTTP/SSE typed error envelope、公开 details allowlist、前端 additive 迁移与安全负例 |
|
||||
| [2026-09-15-pi-typed-result-v1-remediation.md](./2026-09-15-pi-typed-result-v1-remediation.md) | PI Runner typed-result-v1 schema、严格降级、并发终态与真实 PI 双轨验收 |
|
||||
| [2026-09-14-workflow-plan-409-frozen-and-optional-duties-remediation.md](./2026-09-14-workflow-plan-409-frozen-and-optional-duties-remediation.md) | 项目设置 409 冻结态守卫 + 非必需文档三权全有或全无 + 成员/门禁/权限一致性 |
|
||||
| [2026-09-14-controlled-content-canonical-hash-remediation.md](./2026-09-14-controlled-content-canonical-hash-remediation.md) | 项目 143 正文 canonical/raw 哈希漂移、错误语义与重复 hydration 整改 |
|
||||
| [2026-09-13-document-revision-reviewer-duty-sync.md](./2026-09-13-document-revision-reviewer-duty-sync.md) | UI-01 已分配 B=reviewer,受控文档 reviewer_id 硬编码 2,矩阵降为 viewer |
|
||||
| [2026-09-13-document-revision-duty-cell-assertion.md](./2026-09-13-document-revision-duty-cell-assertion.md) | UI-13a 整行 option 文案误判编制负责人,须读 select value/badge |
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# 整改缺口复核矩阵(SSOT)
|
||||
|
||||
**更新**: 2026-09-14
|
||||
**更新**: 2026-09-16
|
||||
**分支**: dev
|
||||
**production_ready**: no(`CHAT-INTENT-STATE` 等无关 blocker、CI 真实 PI 三工作流 E2E / 前端人工抽检未完成;文档账本运行时 UI Round20 已 PASS,不把 fallback 报告当成完整 PI)
|
||||
**production_ready**: yes(发布门禁 B1–B4 已签;dev/test/main schema=47。U9–U12 / 软件自举 / FAV / 完整 PI change-report 叙事不挡首发)
|
||||
**协作焦点**: [../ops/CURRENT.md](../ops/CURRENT.md)
|
||||
**Agent 手册**: [AGENTS.md](../AGENTS.md) · [PROJECT.md](../PROJECT.md)
|
||||
**Agent 手册**: [AGENTS.md](../../AGENTS.md) · [PROJECT.md](../../PROJECT.md)
|
||||
|
||||
> Codex 2026-09-12 再审计项与本轮回环证据见下表「Codex 再审计」区段。
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
| BUG-05 | 拒绝逻辑分散 | PASS | `document_access.go` + `stage_access_helpers.go` | 已完成 |
|
||||
| BUG-06 | token 明文/重放 | PASS | `activation_token_test.go` | 已完成 |
|
||||
| BUG-07 | 完成后下一流程 | PASS | 同 BUG-01 | 已完成 |
|
||||
| BUG-08 | 测试库隔离 | PARTIAL | `db/testdb.go` Require/Skip | CI 设 `TEST_DATABASE_URL` |
|
||||
| BUG-08 | 测试库隔离 | PASS | `db/testdb.go` Require/Skip;CI `TEST_DATABASE_URL` + governance PG 步骤;[report](../test-reports/2026-09-16-ci-governance-pg-bug08-test-report.md) | 已完成 |
|
||||
| BUG-09 | 版本冲突自动重试 | PASS | `StageAdvanceBanner` reload | 已完成 |
|
||||
| BUG-10 | 无审计视图 | PASS | settings + UI | 已完成 |
|
||||
| BUG-11 | 旧 API 未下线 | PARTIAL | 治理开启时 410 | 保持 + 文档标注 |
|
||||
@@ -41,6 +41,9 @@
|
||||
| DB-USERS-SEQ | 种子 users_id_seq 冷启动冲突 | PASS | `00025_...-sync-seed-sequences.sql`;dev/test setval |
|
||||
| DATA-LIFECYCLE-DEV | completed 实例对应 active 项目 | PASS | dev dry-run 47 → fix SQL → 0 |
|
||||
| DATA-TEST-WF | test 污染 active 工作流定义 | PASS | `retire-nonofficial-workflow-definitions.sql`;test UPDATE 5 |
|
||||
| DEMO-DB-SEED | goose 00011/00012 演示项目污染列表 | **PASS** | `00046` retire projects + `00047` retire chat_sessions;`ListProjects*` / `ListChatSessions` 过滤 `demo_retired`;dev migrate schema **47**;抽检项目列表无 6001–6010、user1/2/3 无 `sess-wangjing*`、新建项目 6357 documents=0 | [audit](../audit/2026-09-16-demo-seed-pollution-systemic.md);前序 [2026-09-15](../audit/2026-09-15-mock-deliverables-pollute-real-projects.md);[report](../test-reports/2026-09-16-demo-seed-pollution-test-report.md) |
|
||||
| DEMO-STUB-API | main/prod 仍可请求 stub Agent | **PASS** | `ResolveBackendInEnv`;`TestResolveBackendInEnv_RejectsStubInMain` |
|
||||
| DEMO-WEB-SEEDS | 前端 mock/seed 进生产包并撞 projectId | **PASS** | `@demo-seeds` 默认关闭;`check-prod-bundle.sh` PASS;[report](../test-reports/2026-09-16-demo-seed-pollution-test-report.md) |
|
||||
| TEST-ADVISOR-BRIEF | 多意图 AdvisorBrief 丢失 | PASS | `action_planner.go` enrich;`action_planner_test.go` |
|
||||
| TEST-V05-ARTIFACTS | V0.5 断言 3 vs 5 | PASS | `types_test.go` / `full_link_e2e_test.go` → 5 |
|
||||
| TEST-CHAT-MEMORY | 语义记忆 sleep 竞态 | PASS | `session_test.go` deadline 轮询 |
|
||||
@@ -57,9 +60,10 @@
|
||||
|
||||
| ID | 描述 | 状态 | 证据 | 计划动作 |
|
||||
|---|---|---|---|---|
|
||||
| WORKFLOW-PLAN-FROZEN-OPTIONAL-DUTIES | active 项目仍展示可编辑职责表单,409 提示在长表单视口外;现有规划又不支持非必需文档“三权全空”,且后端缺少职责人在任成员复核 | **PASS(设置页)** | [audit](../audit/2026-09-14-workflow-plan-409-frozen-and-optional-duties.md);[test-report](../test-reports/2026-09-14-workflow-plan-409-frozen-and-optional-duties-test-report.md)。项目 143 只读 frozen、A full+none 激活、B partial 不发 PUT、C 零治理拒绝、双标签转 frozen、成员无配置入口、刷新后 143 仍 frozen | 真实 PI 生成 full/none 并走审批/阶段不阻塞未纳入本轮页面矩阵,不作为本 gap 关闭的替代证据,另立项 |
|
||||
| DOC-CONTENT-CANONICAL-HASH-DRIFT | 旧受控文档 bootstrap 裁剪 Markdown 双空格硬换行并将 canonical SHA 写入账本/DocGov,但未同步文件;正文读取把完整性冲突误报 404,lease/list sync 又放大并制造刷新后加载死锁 | **PASS(真实 UI)** | [audit](../audit/2026-09-14-project143-controlled-content-404.md);[UI report](../test-reports/2026-09-14-controlled-content-ui-acceptance.md)。代码已合 dev、schema 32、项目 143 定向 `migration_repair`;项目 143 `clean-run3` 与新项目 `full-chain-final` 主链及 restart 全部纯页面 PASS,目标 404=0 | [remediation](./2026-09-14-controlled-content-canonical-hash-remediation.md)。隔离 `TestReconcile_LegacyRepair_PG` 未执行,按用户“本轮只允许页面测试”的边界保留为工程测试债,不作为本轮 UI PASS 的替代证据 |
|
||||
| CHAT-HISTORY-REFRESH | 工作流激活后刷新,对话正文被阶段过滤器清空,但分类数量与锚点仍按全量返回 | **PASS** | [test-report](../test-reports/2026-09-13-chat-history-refresh-test-report.md);代码:`message_scope.go`、`chat_history_auth.go`、goose 00026/00027 | 真实 PI 刷新 E2E 待 dev 容器补录(自动化/PG 已 PASS) |
|
||||
| CHAT-INTENT-STATE | 真实会话被诊断探针污染;只读查询误启动文档写任务;错误动作与编辑状态刷新后丢失 | **FAIL** | [audit](../audit/2026-09-13-conversation-intent-runtime-state.md);dev `sess-p143-u9` / task run / lease 现场 | [remediation](./2026-09-13-conversation-intent-runtime-state-remediation.md) |
|
||||
| CHAT-HISTORY-REFRESH | 工作流激活后刷新,对话正文被阶段过滤器清空,但分类数量与锚点仍按全量返回 | **PASS** | [test-report](../test-reports/2026-09-13-chat-history-refresh-test-report.md);活验 [live.json](../test-reports/assets/2026-09-15-chat-history-refresh-live/live.json)(项目 6252,window=categories=2,guest 403);代码:`message_scope.go`、`chat_history_auth.go`、goose 00026/00027 | 闲聊刷新已补。发布门禁「激活后文档任务 + 重登/重启」仍开放,不回退本 gap |
|
||||
| CHAT-INTENT-STATE | 真实会话被诊断探针污染;只读查询误启动文档写任务;错误动作与编辑状态刷新后丢失 | **PASS** | [audit](../audit/2026-09-13-conversation-intent-runtime-state.md);[test-report](../test-reports/2026-09-13-conversation-intent-runtime-state-test-report.md);双标签活验项目 **6275** / `sess-p6275-u10`(`live.json` + Docker 截图)。**不**删除 `sess-p143-u9` 历史探针 | [remediation](./2026-09-13-conversation-intent-runtime-state-remediation.md)。Wave 3–4 浏览器门已签;诊断污染消息仍不擅自删除 |
|
||||
| ENV-RESTART-SOURCE | `docker compose restart` 只重启旧镜像,健康检查无法证明合入代码已部署 | **PASS** | `env-service.sh rebuild` + 真实摘要重测 | 集成冒烟统一使用 `dev rebuild` |
|
||||
| DOCREV-RUNTIME-404 | revision-state 404;账本内存丢失;块保存/overlay 无效;agent 假报告 | **PASS** | [Round20 报告](../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md);[audit](../audit/2026-09-13-document-revision-runtime-404.md) | 运行时 UI 已闭环。change report 仍为 fallback,不冒充 PI。历史失败目录不删 |
|
||||
| DOCREV-PG-ID-REMAP | 首次生成 PG 已写 snapshot/candidate,commit 因内存误删 baseline 而 not found | **PASS** | [audit](../audit/2026-09-13-document-revision-pg-id-remap.md);Round19 归档 `schema31-round19-ui03-advisor-briefing-docrevision-not-found`(candidate id=175 / output snapshot 250,禁止写成 candidate 250);Round20 UI-03 V2/r0 | 已合入 `dev@b258ab8`;不忽略 ErrNotFound;不删证据 |
|
||||
@@ -68,6 +72,8 @@
|
||||
| DOCREV-QUALITY-SELF-POLLUTE | 自检表引用禁词致 score=40 quality_failed;auto_repair 未启用;UI 映射 completed | **PASS** | [audit](../audit/2026-09-13-document-revision-quality-gate-self-pollution.md);Round20 UI-03 完成 | 不删证据;不删禁词 |
|
||||
| DOCREV-ACTIVE-DOC-ROUTING | UI-05「当前受控文档」被法规关键词改路由到 `feasibility_reg`,intake 无 pending | **PASS** | [audit](../audit/2026-09-13-document-revision-active-doc-routing.md);Round20 UI-05 pending 停在 intake V2 | **不改弱 E2E**;不删证据 |
|
||||
| DOCREV-QUALITY-STATUS-FP | 行动计划表状态列「待续」被门禁当敷衍,两轮 repair 后 quality_failed 80 | **PASS** | [audit](../audit/2026-09-13-document-revision-quality-status-false-positive.md);Round20 UI-03 | **不删禁词、不放宽正文**;不删证据 |
|
||||
| GOVERNANCE-ACTION-AUTHZ | 文档动作按职责鉴权;未激活 202-blocked;关闭创建直通 | **PASS** | [test-report](../test-reports/2026-09-14-governance-action-level-authz-test-report.md);[audit 异态](../audit/2026-09-14-planning-with-workflow-key-anomaly.md) | 不改 83 条 planning+key 夹具;none 长 PI 审批链另开 |
|
||||
| DOC-RELIABILITY-PILOT | 受控文档写路径与 PG 事件交付尚未形成生产闭环;闭包副作用在崩溃/重启后不可重试审计,错误 scope 或 projection 缺失仍可能导致刷新失败 | **PASS** | [初审](../audit/2026-09-14-module-decoupling-plan-review.md);[Phase 1](./2026-09-14-module-decoupling-refactor-plan.md);[Phase 2 复核](../audit/2026-09-15-module-decoupling-phase2-plan-review.md);[Phase 2 修订](./2026-09-15-module-decoupling-ipc-phase2-remediation-plan.md);[U11–U12 报告](../test-reports/2026-09-15-app-composition-u11-u12-test-report.md);[E1A](../test-reports/2026-09-15-event-e1a-notify-cutover-test-report.md);[E1B](../test-reports/2026-09-15-event-e1b-workflow-advance-test-report.md);[E1C](../test-reports/2026-09-15-event-e1c-projection-test-report.md);[E2](../test-reports/2026-09-15-event-e2-hook-guard-test-report.md);[复盘](../ops/research/2026-09-15-track-e-retrospective.md);[notify live](../test-reports/2026-09-15-event-notify-shared-live-test-report.md);[advance live](../test-reports/2026-09-15-event-workflow-advance-shared-live-test-report.md);[projection live](../test-reports/2026-09-15-event-projection-shared-live-test-report.md) | 共享 notify/workflow_advance/projection 已 live;生产不再注册 `OnOutbox=` / `AddOnApprovedHook(`。FAV 仍 off。HTTP/PI 实施不纳入本行。项目 143 只读 |
|
||||
|
||||
---
|
||||
|
||||
@@ -76,13 +82,13 @@
|
||||
```
|
||||
☑ go vet ./... 全绿
|
||||
☑ go test -short ./... 全绿
|
||||
□ TEST_DATABASE_URL 下治理 PG 集成全绿(CI)
|
||||
□ 真实 PI Agent 三工作流治理 E2E 实录(本轮 stub/short 已绿,PI 待 CI token)
|
||||
□ 对话刷新恢复:激活前聊天 + 激活后文档任务 + 刷新/重登/重启可恢复,双用户负例通过
|
||||
☑ TEST_DATABASE_URL 下治理 PG 集成全绿(CI)
|
||||
☑ 真实 PI Agent 三工作流治理 E2E 实录([test-report](../test-reports/2026-09-16-pi-three-workflow-e2e-test-report.md))
|
||||
☑ 对话刷新恢复:激活前聊天 + 激活后文档任务 + 刷新/重登/重启可恢复,双用户负例通过([test-report](../test-reports/2026-09-16-chat-refresh-gate-test-report.md);项目 6359)
|
||||
☑ lifecycle fix SQL 已在 dev 执行
|
||||
☑ test/dev health schema_version=25
|
||||
☑ main 环境部署冒烟(本地 8000 health/ready schema 25)
|
||||
□ 前端:版本冲突刷新、终止 preview 人工抽检
|
||||
☑ test/dev health schema_version=47
|
||||
☑ main 环境部署冒烟(本地 8000;schema 对齐见 CURRENT)
|
||||
☑ 前端:版本冲突刷新、终止 preview 人工抽检([test-report](../test-reports/2026-09-16-frontend-gate-b4-test-report.md);项目 6363)
|
||||
```
|
||||
|
||||
**结论**: 文档账本运行时真实 UI Round20 **PASS**(见 [test-report](../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md))。**发布 blocker 仍包括 `CHAT-INTENT-STATE`、CI 真实 PI 三工作流 E2E 与前端人工抽检**;`-race` 全包并行 TempDir flake 为测试基建残留。不得把 fallback change report 写成完整 PI 叙事。
|
||||
**结论**: 发布门禁四框已签。文档账本运行时 UI Round20 **PASS**;`CHAT-INTENT-STATE` 双标签 busy **PASS**;`DEMO-DB-SEED` **PASS**;BUG-08 **PASS**。`-race` TempDir flake 与 U9–U12 / 软件自举 / FAV / 完整 PI change-report 叙事不挡首发。不得把 fallback change report 写成完整 PI 叙事。
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# 模块与功能完成度(SSOT)
|
||||
|
||||
**更新**: 2026-09-14
|
||||
**production_ready**: no
|
||||
**更新**: 2026-09-16
|
||||
**production_ready**: yes
|
||||
**发布缺口**: [../remediation/gap-matrix.md](../remediation/gap-matrix.md)
|
||||
**协作焦点**: [../ops/CURRENT.md](../ops/CURRENT.md)
|
||||
|
||||
@@ -15,18 +15,20 @@
|
||||
|
||||
| 模块 | 能力 | 状态 | 证据 | 缺口/后续 | mutex |
|
||||
|------|------|------|------|-----------|-------|
|
||||
| 意图识别 L1 | 18 类 Intent + 三分支消解 | partial | [system-design/intent-recognition](../system-design/intent-recognition/);[现场专项审计](../audit/2026-09-13-conversation-intent-runtime-state.md) | 明确写动作与只读总结已分流;完整 hard-negative/eval 集仍待补齐 | `intent` |
|
||||
| 对话 / ctxmgr | 多轮上下文、记忆、摘要 | partial | [system-design/multi-turn-dialogue](../system-design/multi-turn-dialogue/);[刷新恢复专项审计](../audit/2026-09-13-chat-history-refresh-disappears.md) | `CHAT-HISTORY-REFRESH`:作用域写入、同集授权统计、历史回填;语义摘要(D5 backlog) | `chat` |
|
||||
| 意图识别 L1 | 18 类 Intent + 三分支消解 | partial | [system-design/intent-recognition](../system-design/intent-recognition/);[现场专项审计](../audit/2026-09-13-conversation-intent-runtime-state.md);[运行态报告](../test-reports/2026-09-13-conversation-intent-runtime-state-test-report.md);[双标签活验](../test-reports/assets/2026-09-15-conversation-intent-dual-tab/live.json);[多意图复核方案](../system-design/2026-09-15-multi-intent-hitl-plan.md);[U1 契约](../test-reports/2026-09-15-multi-intent-u1-contracts-test-report.md);[U2 分段](../test-reports/2026-09-15-multi-intent-u2-segmenter-test-report.md);[U3 PG](../test-reports/2026-09-15-multi-intent-u3-intentflow-pg-test-report.md) | 明确写动作与只读总结已分流;双标签 `DOC_BUSY` 已签(项目 6275)。多意图核心 U1–U8 已完成;U9–U12 不阻塞首版。intent 纯依赖边界不得回退 | `intent` |
|
||||
| 多意图持久计划 | app/intentflow 生命周期与 HITL 契约 | partial | [设计](../system-design/2026-09-15-multi-intent-hitl-plan.md);[U1](../test-reports/2026-09-15-multi-intent-u1-contracts-test-report.md)–[U8](../test-reports/2026-09-16-multi-intent-u8-task-generate-test-report.md) | U1–U8 核心首版已完成。U9–U12 不阻塞。默认 tier=legacy。真实 PI generate 待 runner URL。共享环境 schema 45 待晋升 | `intent-plan` |
|
||||
| 对话 / ctxmgr | 多轮上下文、记忆、摘要 | partial | [system-design/multi-turn-dialogue](../system-design/multi-turn-dialogue/);[刷新恢复专项审计](../audit/2026-09-13-chat-history-refresh-disappears.md);[U10 端口化](../archive/ops/2026-09-15-chatlog-contextasm-u10.md);[U10 报告](../test-reports/2026-09-15-chatlog-contextasm-u10-test-report.md);[门禁 B3](../test-reports/2026-09-16-chat-refresh-gate-test-report.md) | `CHAT-HISTORY-REFRESH` 与发布门禁「激活后文档任务 + 重登/重启」已签(项目 6359)。U10 原地端口 **停止扩面**。语义摘要(D5 backlog) | `chat` |
|
||||
| 智能体小队 | 角色-任务-工作区-黑板 | done | [system-design/agent-squad](../system-design/agent-squad/);[test 2026-09-07](../test-reports/2026-09-07-dynamic-squad-planning-test-report.md) | 非关键步骤降级(A5/A6 backlog) | `squad` |
|
||||
| 工作流治理 | 三正式工作流 + 阶段门禁 | done | [remediation/three-workflows](../remediation/2026-09-12-three-workflows-strict-governance-remediation.md);[test 2026-09-12](../test-reports/2026-09-12-three-workflows-governance-remediation-test-report.md) | Phase2 设计器 partial | `workflow` |
|
||||
| 工作流治理 | 三正式工作流 + 阶段门禁 | partial | [remediation/three-workflows](../remediation/2026-09-12-three-workflows-strict-governance-remediation.md);[test 2026-09-12](../test-reports/2026-09-12-three-workflows-governance-remediation-test-report.md);[冻结态/职责可选整改](../remediation/2026-09-14-workflow-plan-409-frozen-and-optional-duties-remediation.md);[Wave 5 页面矩阵](../test-reports/2026-09-14-workflow-plan-409-frozen-and-optional-duties-test-report.md);[职责-动作鉴权](../test-reports/2026-09-14-governance-action-level-authz-test-report.md);[真实 PI 三工作流 E2E](../test-reports/2026-09-16-pi-three-workflow-e2e-test-report.md) | 设置页/DutyMode + 动作级鉴权已落地;真实 PI 三工作流 E2E 已签。后续:none 文档真实 PI 审批长链路;模块可仍 partial | `workflow` |
|
||||
| 纯软件项目自举 | 软件项目创建、Bootstrap 基线、Delivery 迭代与受控工程交接 | planned | [详细设计](../system-design/2026-09-14-software-project-bootstrap-workflow.md);[现状调研](../ops/research/2026-09-14-software-project-bootstrap-current-state.md);[验收计划](../ops/checklists/2026-09-14-software-project-bootstrap-acceptance.md) | 当前仅完成方案;目录/模板/执行器/创建向导/真实 PI UI 均未实施。受控代码执行单列后续 Epic | `workflow-design` |
|
||||
| IAM / 鉴权 | 项目级 API 鉴权 + RBAC | partial | [audit/authorization](../audit/authorization-matrix-v2.md);[刷新恢复专项审计](../audit/2026-09-13-chat-history-refresh-disappears.md) | 历史读取端点补统一会话 owner + 阶段授权;旧 API 410 标注(BUG-11 partial) | `authz` |
|
||||
| 文档治理 | 法定文档生命周期 + 租约 + 受控正文读取 | done | [test docgov](../test-reports/2026-09-08-docgov-lifecycle-and-claiming-framework-test-report.md);[项目 143 正文 404 审计](../audit/2026-09-14-project143-controlled-content-404.md);[受控正文真实 UI 验收报告](../test-reports/2026-09-14-controlled-content-ui-acceptance.md);[UI-06 缓存竞争审计](../audit/2026-09-14-document-revision-refresh-cache-race.md);[整改](../remediation/2026-09-14-controlled-content-canonical-hash-remediation.md) | 生命周期/租约保留。W1–W6 + 审查修补 + UI hydrate 资格 + 晚到 list sync 修复均已合入 dev。项目 143 纯 UI 回归(clean-run3)与新项目全链路(main + post-restart)已全量真实页面验证通过(PASS) | `docgov` |
|
||||
| 文档版本与修改认知 | 智能体版本边界、人工修订标记、任意版本比较、变更报告与负责人通知 | partial | [管理测试](../test-reports/2026-09-13-document-revision-management-test-report.md);[运行时 UI Round20](../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md);[运行时审计](../audit/2026-09-13-document-revision-runtime-404.md);[ADR](../adr/2026-09-13-document-version-boundary.md) | **运行时 UI PASS**(6159 / V3/r2)。仍 `partial`:change report=`fallback`(真实 diff+lineage,非完整 PI 叙事)。系统级 `CHAT-INTENT` 见 gap-matrix | `docgov` |
|
||||
| 前端工作台 | 三栏 + 块文档 + SSE | partial | [test workbench](../test-reports/2026-09-08-three-column-workbench-and-block-document-test-report.md);[现场专项审计](../audit/2026-09-13-conversation-intent-runtime-state.md) | 错误卡片/任务进度/文档 busy 状态刷新恢复与人工抽检待完成 | `web` |
|
||||
| PI Runner / 配置链 | pi-agent + MiniMax 真实链路 | done | [test piagent](../test-reports/2026-09-13-codex-audit-p0-remediation-test-report.md);[container-env](../test-reports/2026-09-13-container-env-configuration-test-report.md) | — | `pi-agent` |
|
||||
| 前端工作台 | 三栏 + 块文档 + SSE | partial | [test workbench](../test-reports/2026-09-08-three-column-workbench-and-block-document-test-report.md);[现场专项审计](../audit/2026-09-13-conversation-intent-runtime-state.md);[双标签截图](../test-reports/assets/2026-09-15-conversation-intent-dual-tab/screenshots/tab-b-busy.png);[demo seed 污染整改](../test-reports/2026-09-16-demo-seed-pollution-test-report.md);[门禁 B4](../test-reports/2026-09-16-frontend-gate-b4-test-report.md) | 错误卡片/任务进度/文档 busy 刷新恢复已有项目 6275 证据。Demo seeds 默认关闭。版本冲突信封解包 + 终止 preview 抽检已签(项目 6363) | `web` |
|
||||
| PI Runner / 配置链 | pi-agent + MiniMax 真实链路 + typed-result-v1 | done | [test piagent](../test-reports/2026-09-13-codex-audit-p0-remediation-test-report.md);[container-env](../test-reports/2026-09-13-container-env-configuration-test-report.md);[typed-result-v1](../test-reports/2026-09-15-pi-typed-result-v1-test-report.md) | — | `pi-agent` |
|
||||
| 三环境运维 | dev/test/main + 共享 KB | done | [PROJECT.md](../../PROJECT.md) §4;四环境 healthy | — | `infra` |
|
||||
| CI / E2E | PG 集成 + 真实 PI E2E | partial | [gap-matrix BUG-08](../remediation/gap-matrix.md);[test pg-ci](../test-reports/2026-09-12-pg-ci-soak-e2e-test-report.md);[运行时 UI Round20](../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md) | CI `TEST_DATABASE_URL` 隔离库仍缺;文档运行时真实 UI 已按 UI_PHASE 分文件且 post-restart 断言最终 A1 正文。`-race` 全包并行 TempDir flake 为基建残留 | `ci` |
|
||||
| CI / E2E | PG 集成 + 真实 PI E2E | partial | [gap-matrix BUG-08](../remediation/gap-matrix.md);[test pg-ci](../test-reports/2026-09-12-pg-ci-soak-e2e-test-report.md);[治理 PG BUG-08](../test-reports/2026-09-16-ci-governance-pg-bug08-test-report.md);[真实 PI 三工作流](../test-reports/2026-09-16-pi-three-workflow-e2e-test-report.md);[运行时 UI Round20](../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md) | BUG-08 PASS;真实 PI 三工作流 E2E 与前端/对话门禁已签。`-race` TempDir flake 为基建残留;夜间 CI `RUN_PI_E2E=1` 建议 | `ci` |
|
||||
| 模块解耦与可靠事件 | 文档可靠性纵向试点、PG 持久事件交付与选择性模块化 | partial | [架构](../system-design/2026-09-14-module-decoupling-architecture.md);[ADR](../adr/2026-09-14-modular-monolith-decoupling.md);[Phase 1](../remediation/2026-09-14-module-decoupling-refactor-plan.md);[Phase 2 审阅](../audit/2026-09-15-module-decoupling-phase2-plan-review.md);[Phase 2 修订计划](../remediation/2026-09-15-module-decoupling-ipc-phase2-remediation-plan.md);[E0A](../test-reports/2026-09-15-event-e0a-production-scope-contract-test-report.md);[E0B](../test-reports/2026-09-15-event-e0b-dispatcher-pg-test-report.md);[E1A](../test-reports/2026-09-15-event-e1a-notify-cutover-test-report.md);[E1B](../test-reports/2026-09-15-event-e1b-workflow-advance-test-report.md);[E1C](../test-reports/2026-09-15-event-e1c-projection-test-report.md);[E2](../test-reports/2026-09-15-event-e2-hook-guard-test-report.md);[复盘](../ops/research/2026-09-15-track-e-retrospective.md);[D6](../test-reports/2026-09-15-doccontent-canonical-boundary-test-report.md);[D7a](../test-reports/2026-09-15-intent-bizdev-boundary-test-report.md);[D5](../test-reports/2026-09-15-stageflow-type-ownership-test-report.md);[D4](../test-reports/2026-09-15-bizdev-locator-removal-test-report.md);[D7b](../test-reports/2026-09-15-chatflow-orchestration-boundary-test-report.md);[H0](../ops/research/2026-09-15-http-error-envelope-h0-inventory.md);[P0](../ops/research/2026-09-15-pi-typed-result-p0-matrix.md);[收口](../test-reports/2026-09-15-phase2-closeout-test-report.md);[notify live](../test-reports/2026-09-15-event-notify-shared-live-test-report.md);[advance live](../test-reports/2026-09-15-event-workflow-advance-shared-live-test-report.md);[projection live](../test-reports/2026-09-15-event-projection-shared-live-test-report.md);[HTTP 信封](../test-reports/2026-09-15-http-error-envelope-h1-h3-test-report.md);[PI typed-result](../test-reports/2026-09-15-pi-typed-result-v1-test-report.md) | E0A–E2 与共享 live 已过;生产无 hook 注册。D4–D7b 已合入。FAV off。Track P H1–H3 / P1–P4 已实施 | `architecture-docs` |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -0,0 +1,422 @@
|
||||
# 模块化单体解耦架构
|
||||
|
||||
> 状态:**设计已修订,首个文档可靠性试点待实施**
|
||||
>
|
||||
> 决策:[模块化单体解耦 ADR](../adr/2026-09-14-modular-monolith-decoupling.md)
|
||||
>
|
||||
> 实施:[模块解耦整改与重构计划](../remediation/2026-09-14-module-decoupling-refactor-plan.md)
|
||||
|
||||
## 1. 目标与边界
|
||||
|
||||
本设计把 Agent-System 收敛为模块化单体,使项目文档在刷新、服务重启、并发修改和工作区清理后仍能从稳定逻辑标识定位到正确正文。
|
||||
模块边界必须同时约束依赖、事务、并发、授权、文件和最终成果;只减少 Go import 或移动目录不算解耦完成。
|
||||
|
||||
### 1.1 目标
|
||||
|
||||
1. 每个业务命令有唯一应用用例、事务 owner 和幂等语义。
|
||||
2. 每张运行表和每类文件有唯一写入属主,但跨表不变量仍能在同一事务提交。
|
||||
3. HTTP、SSE、CLI、worker 和恢复工具经过同一授权决策,不信任调用方填写的身份或资源归属。
|
||||
4. workspace 只保存计算现场和可重建投影;最终文档、最终回复和 manifest 进入 FAV。
|
||||
5. 事件在崩溃、重复投递、多订阅者和水平扩容下可追踪、可重试、可隔离。
|
||||
6. 首个纵向试点直接消除受控正文刷新/重启后 404、409 和 projection missing 类故障。
|
||||
|
||||
### 1.2 非目标
|
||||
|
||||
- 不拆微服务,不引入分布式事务协调器。
|
||||
- 不在本轮统一全部 HTTP 错误响应。
|
||||
- 不在本轮替换 PI Runner stdout/result 协议。
|
||||
- 不把所有历史数据永久保留,也不把生产数据复制为测试 fixture。
|
||||
- 不允许 FAV 绕过数据库授权或自动重建活动工作流、lease、pending task。
|
||||
|
||||
## 2. 目标架构
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
Client[Web or CLI] --> Adapter[server adapters]
|
||||
Worker[Background workers] --> App[application use cases]
|
||||
Adapter --> App
|
||||
App --> Authz[authorization policy]
|
||||
App --> UoW[UnitOfWork]
|
||||
App --> ReadModels[read use cases]
|
||||
UoW --> Owners[domain table owners]
|
||||
Owners --> PG[(PostgreSQL)]
|
||||
UoW --> Outbox[(outbox and staging)]
|
||||
Outbox --> Dispatcher[event dispatcher]
|
||||
Dispatcher --> Subscribers[idempotent subscribers]
|
||||
Subscribers --> Vault[artifactvault]
|
||||
App --> Workspace[workspace capability service]
|
||||
Workspace --> Scratch[(scratch workspace)]
|
||||
ReadModels --> PG
|
||||
ReadModels --> Vault
|
||||
```
|
||||
|
||||
### 2.1 分层职责
|
||||
|
||||
| 层 | 职责 | 禁止 |
|
||||
|---|---|---|
|
||||
| `internal/server` | 参数解析、认证信息转 Principal、调用应用用例、序列化 HTTP/SSE | SQL、事务、路径拼接、跨模块编排、后台重试 |
|
||||
| `internal/app/*flow` | 用例编排、授权、UnitOfWork、命令幂等、事件发布 | 领域 SQL、物理路径、传输格式 |
|
||||
| 消费者侧 ports | 表达一个用例需要的最小能力 | 聚合所有模块方法的万能接口 |
|
||||
| 领域模块 | 业务不变量、表/文件写入所有权、事务绑定 repository | import 其他领域实现、开启不受控嵌套事务 |
|
||||
| read model | 授权后的跨模块只读聚合 | 业务状态变更、修复式 GET 写入 |
|
||||
| 基础设施 | PostgreSQL、CAS、FAV、workspace、事件 dispatcher | 推断业务终态或自行授予权限 |
|
||||
|
||||
### 2.2 契约分类
|
||||
|
||||
`internal/contracts` 不再作为所有 DTO 的公共仓库。
|
||||
|
||||
| 契约 | 所有位置 | 版本规则 |
|
||||
|---|---|---|
|
||||
| HTTP/SSE wire DTO | `internal/server/api`、`internal/stream/transport` | 对外兼容,breaking change 走 ADR |
|
||||
| 一对一调用端口 | 消费者 use case 包内 | 随用例演化,不带 JSON tag,不自动走 ADR |
|
||||
| 公共领域事件 | `internal/contracts/events/<domain>` | 有 schema version;生产者和多个消费者共同评审 |
|
||||
| 持久文件/manifest schema | 所属模块,如 `artifactvault`、`workspace` | major/minor 兼容;未知 major fail closed |
|
||||
| 稳定共享词汇 | `internal/contracts/vocabulary` | 仅无行为枚举和值对象;禁止依赖业务实现 |
|
||||
| 错误分类 | 领域错误留领域包;wire 映射留 server | 不把数据库/路径/第三方原始错误暴露给客户端 |
|
||||
|
||||
接口默认由消费者拥有,应用组合根只注入实现。
|
||||
只有三个以上消费者确实共享相同语义时,才提升为公共端口。
|
||||
|
||||
## 3. 模块边界
|
||||
|
||||
| 模块 | 唯一职责与写入所有权 | 可依赖 | 禁止 |
|
||||
|---|---|---|---|
|
||||
| `app/docflow` | 文档读取、提交、批准、投影和归档用例;相关事务 owner | 消费端口、authz、uow | SQL、物理路径 |
|
||||
| `app/stageflow` | 阶段推进和任务执行用例 | 消费端口、authz、uow | bizdev 门面、HTTP DTO |
|
||||
| `app/chatflow` | 一轮对话识别、协调、消息落账和任务触发 | 消费端口、authz、uow | 直接写共享上下文字段 |
|
||||
| `docgov` | 文档治理状态、角色、lease、`document_records` 写者 | 自有 repository、稳定词汇 | 直调 docrevision 实现、读 workspace 文件 |
|
||||
| `docrevision` | immutable snapshot/version/revision/event/report 账本写者 | 自有 repository | 直接写 `document_records`、`freeform_documents` |
|
||||
| `freedoc` | 自由文档根表和发布状态写者 | 自有 repository | 被 docrevision 反向更新 |
|
||||
| `docquery` | 授权后文档列表、正文、版本聚合读取 | 只读端口、artifact read fallback | 任何写入、目录扫描、授权推断 |
|
||||
| `chatlog` | `chat_*` 表族读写和会话/消息/turn 查询 | 自有 repository | prompt 装配、外部导出策略 |
|
||||
| `contextasm` | 记忆、摘要、召回和 prompt 上下文组装 | 消费者侧 ChatLog/KB read ports | HTTP、SQL 越界写入 |
|
||||
| `intent` | 纯规则意图分类 | vocabulary | bizdev、server、IO |
|
||||
| `taskrun` | task run 状态机、claim/finalize、幂等写者 | 自有 repository | server 补协议、workspace 路径 |
|
||||
| `squadrun` | 在受限 workspace capability 内执行角色与步骤 | agent/template/quote 消费端口 | DB、SSE、业务授权、任意路径 |
|
||||
| `workspace` | Workspace ID 签发、物理路径解析、projection 生命周期 | fsutil、storage identity | 业务终态、最终归档 |
|
||||
| `artifactvault` | 终态 payload/manifest/receipt/tombstone 权威 | 独立存储、registry | 活动业务关系、运行授权、workspace 扫描 |
|
||||
| `notification` | 通知偏好、投递和状态 | 事件消费、repository | 业务状态推进 |
|
||||
| `app` | 唯一组合根、worker 生命周期、事件订阅注册 | 所有构造函数 | 被 server 反向装配 |
|
||||
|
||||
模块“可依赖”只表示通过端口调用,不表示允许 import 对方实现包。
|
||||
|
||||
## 4. 事务与单一写者
|
||||
|
||||
### 4.1 两种所有权
|
||||
|
||||
- **表属主**决定 SQL、约束和单表不变量。
|
||||
- **事务 owner**决定一个业务命令需要哪些属主共同提交。
|
||||
|
||||
两者不能合并为“每个模块各开一个事务”。
|
||||
应用用例开启 `UnitOfWork`,取得绑定同一 `pgx.Tx` 的 repository capabilities;领域服务只能使用这些 capabilities,不能 commit、rollback 或启动嵌套事务。
|
||||
|
||||
### 4.2 文档提交原子集合
|
||||
|
||||
一次受控文档提交必须原子包含:
|
||||
|
||||
1. 校验 Principal、项目成员、duty、lease 和 expected head。
|
||||
2. 锁定 `document_records` 与当前 open version。
|
||||
3. 写 immutable content blob/snapshot/revision/change event。
|
||||
4. 更新版本 head 与 `document_records` 当前指针/哈希。
|
||||
5. 冻结应归档 payload 或不可变 blob 引用。
|
||||
6. 写领域事件和 FAV publish request。
|
||||
7. 提交后再进行 workspace 投影、通知和外部存储发布。
|
||||
|
||||
任一步失败,步骤 2–6 全部回滚。
|
||||
投影或发布失败不会回滚业务提交,而是进入可重试队列并在 UI 暴露 degraded 状态。
|
||||
|
||||
### 4.3 事务隔离选择
|
||||
|
||||
| 场景 | 机制 | 原因 |
|
||||
|---|---|---|
|
||||
| 单文档编辑/批准/提交 | `READ COMMITTED` + `SELECT ... FOR UPDATE` + expected head | 竞争范围明确,冲突可向用户解释 |
|
||||
| 同幂等键并发创建 | 唯一约束 + payload digest 校验 | 数据库决定唯一赢家 |
|
||||
| 跨表项目级 duty/heal | `pg_advisory_xact_lock(project_id)` + 固定行锁顺序 | 复用现有项目级互斥,事务结束自动释放 |
|
||||
| 复杂跨聚合唯一不变量 | `SERIALIZABLE`,完整事务有限重试 | 仅在显式证明需要时使用 |
|
||||
| outbox 多 worker claim | `FOR UPDATE SKIP LOCKED` + lease/fencing token | 提高队列吞吐,不作为普通读取语义 |
|
||||
|
||||
### 4.4 锁顺序
|
||||
|
||||
所有跨属主事务按下列顺序获得锁:
|
||||
|
||||
1. project 或 workflow instance 事务级 advisory/row lock;
|
||||
2. document/freeform/chat aggregate root;
|
||||
3. version/snapshot/turn;
|
||||
4. task run;
|
||||
5. staging/outbox/delivery。
|
||||
|
||||
禁止在持锁期间调用 LLM、PI Runner、对象存储、HTTP、SSE 或执行大文件复制。
|
||||
需要外部工作时采用 prepare → 外部执行 → compare-and-commit;commit 阶段重新验证 expected version。
|
||||
|
||||
### 4.5 超时与重试
|
||||
|
||||
- 每个写事务设置独立 context deadline 和数据库 `lock_timeout`;初始预算由配置管理,不在 handler 硬编码。
|
||||
- `40001` 与 `40P01` 只允许重跑完整幂等事务,采用带抖动退避和有限次数。
|
||||
- expected-version 冲突、权限拒绝、唯一键 payload 不同不是瞬时错误,不自动重试。
|
||||
- 事务重试期间不得重复发送消息、SSE、通知或对象存储写入;这些副作用只能由提交后的 outbox 驱动。
|
||||
|
||||
## 5. 并发协议
|
||||
|
||||
### 5.1 文档并发
|
||||
|
||||
客户端读取正文时获得 `ETag = head_snapshot_id:head_revision_no`。
|
||||
PATCH、agent commit、approve 和 projection repair 都必须携带 expected head 或稳定 idempotency key。
|
||||
旧 ETag 返回 typed `VERSION_CONFLICT`,响应包含当前 head 元数据但不泄露无权正文。
|
||||
|
||||
### 5.2 TaskRun 并发
|
||||
|
||||
`Claim(idempotency_key, request_digest)` 通过唯一约束保证只创建一个 run。
|
||||
相同 key、相同 digest 返回既有 run;相同 key、不同 digest 返回 `IDEMPOTENCY_CONFLICT`。
|
||||
状态迁移使用 `WHERE status = expected AND version = expected_version`,影响行数为零即重新读取并分类冲突。
|
||||
幂等键按 environment、project、actor、action 和客户端 key 作用域化,并与规范化 request digest 绑定。
|
||||
幂等记录的保留期不得短于客户端重试窗口、事件重放窗口和对应业务记录的审计期。
|
||||
|
||||
### 5.3 Workspace 并发
|
||||
|
||||
Workspace ID 由服务端签发并绑定 environment、project、run、storage identity 和生命周期。
|
||||
同一 workspace 同时只有一个写 lease;续租返回 fencing token,所有写操作校验 token。
|
||||
本地 `sync.Mutex` 可减少同进程竞争,但跨副本 lease 和 token 才是正确性依据。
|
||||
文件写入采用同目录临时文件、校验、原子 rename 和目录同步;reader 只读取完整 projection marker。
|
||||
|
||||
### 5.4 FAV 并发
|
||||
|
||||
逻辑 artifact 的幂等键由终态事件、资源、payload SHA 和 policy version 决定。
|
||||
对象写入使用 content-addressed key 和 no-replace 语义;blob、manifest 全部校验完成后最后写 commit marker。
|
||||
重复 publisher 可共享已有 blob,但只有一个 registry 状态迁移为 verified。
|
||||
|
||||
### 5.5 查询与背压
|
||||
|
||||
docquery 的列表和版本历史必须分页,BatchGet 首期硬上限 100 个引用;超过上限返回 typed validation error,不自动拆成无界并发查询。
|
||||
批量读取先按 Principal 和 project scope 分组授权,再使用有界并发和数据库 statement deadline。
|
||||
API 对 actor/project/action 维度限流,后台 backfill 和 dispatcher 使用独立连接预算,不能耗尽在线读写连接池。
|
||||
SSE 慢客户端只影响传输缓冲;不能持有业务 transaction、数据库锁或阻止事件持久化。
|
||||
|
||||
## 6. 可靠事件
|
||||
|
||||
### 6.1 事件信封
|
||||
|
||||
每个持久事件至少包含:
|
||||
|
||||
```text
|
||||
event_id
|
||||
event_name
|
||||
schema_version
|
||||
environment
|
||||
project_id
|
||||
aggregate_type / aggregate_id / aggregate_version
|
||||
actor_ref
|
||||
correlation_id / causation_id
|
||||
idempotency_key
|
||||
payload_digest
|
||||
occurred_at
|
||||
```
|
||||
|
||||
事件不携带 secret、认证 token、Prompt、正文或任意文件路径。
|
||||
大 payload 先冻结到不可变 staging,事件只保存引用和 digest。
|
||||
|
||||
### 6.2 投递模型
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant UC as Use case transaction
|
||||
participant DB as PostgreSQL
|
||||
participant W as Dispatcher worker
|
||||
participant S as Subscriber
|
||||
UC->>DB: business state + staging + outbox
|
||||
DB-->>UC: commit
|
||||
W->>DB: claim delivery with SKIP LOCKED
|
||||
W->>S: deliver event and fencing token
|
||||
S->>DB: idempotent side effect and inbox receipt in one transaction
|
||||
S-->>W: success or typed failure
|
||||
W->>DB: ack, retry schedule, or dead letter
|
||||
```
|
||||
|
||||
- 每个订阅者有独立 delivery 状态,不能共享单一 `published_at`。
|
||||
- 投递语义为至少一次;消费者以 event ID/inbox 唯一约束幂等。
|
||||
- 同一 aggregate 按 aggregate version 有序;不同 aggregate 可并行。
|
||||
- claim 按 `next_attempt_at, event_id` 排序并采用 aging,防止热点失败事件令旧事件永久饥饿。
|
||||
- 数据库 subscriber 的业务副作用与 inbox receipt 必须同事务;外部副作用使用业务幂等键并在回执落库前允许安全重放。
|
||||
- transient failure 指数退避;永久失败进入 dead letter,不能阻塞其他订阅者。
|
||||
- worker 认领带 lease、attempt 和 fencing token;过期 worker 无权提交 ack。
|
||||
- replay 必须指定事件范围、目标消费者、操作者和原因,并写审计记录。
|
||||
- delivery/outbox 的清理只能在所有必需消费者完成、重放窗口结束且恢复 checkpoint 已覆盖后执行;审计类事件按独立保留策略处理。
|
||||
|
||||
## 7. Workspace、账本与 FAV
|
||||
|
||||
### 7.1 三层权威
|
||||
|
||||
| 层 | 权威内容 | 清理规则 |
|
||||
|---|---|---|
|
||||
| PostgreSQL | 项目、权限、workflow、task、文档关系、版本账本、当前指针 | 依完整备份/PITR 和环境生命周期处理 |
|
||||
| workspace/state | 执行现场、临时材料、可重建 projection | 终态冻结和归档门禁通过后按 TTL 清理 |
|
||||
| FAV | 已归档 payload、manifest、receipt、tombstone | 按 retention/legal hold/delete ledger 处理 |
|
||||
|
||||
### 7.2 Workspace capability
|
||||
|
||||
跨模块 DTO 只包含:
|
||||
|
||||
```text
|
||||
workspace_id
|
||||
project_scope
|
||||
run_id
|
||||
lease_fencing_token
|
||||
schema_version
|
||||
```
|
||||
|
||||
调用方使用 `ReadArtifact(key)`、`OpenAtomicWriter(key)`、`CommitProjection(key, digest)` 等受限端口。
|
||||
artifact key 必须是受控相对标识,禁止绝对路径、`..`、空段、跨作用域 ID、symlink 和 hardlink 逃逸。
|
||||
|
||||
### 7.3 RunManifest
|
||||
|
||||
RunManifest 的规范字节、SHA、workspace ID、storage identity 和输出成员在 taskrun finalize 时持久化。
|
||||
`Evidence map[string]string` 和 `Gaps []string` 不作为核心协议;核心字段类型化,扩展只能进入带 namespace 和 schema 的 extensions。
|
||||
workspace 内 manifest 是可重建副本,不是唯一事实源。
|
||||
|
||||
### 7.4 FAV 接入
|
||||
|
||||
artifactvault 只接收服务端确认的终态文档、终态助手回复和必要附件。
|
||||
流式 chunk、候选、Prompt、工具轨迹、修复过程、临时报告和 workspace 草稿准入率必须为零。
|
||||
发布从终态事务的 staging/outbox 驱动,禁止目录扫描。
|
||||
|
||||
docquery 的读取优先级为:
|
||||
|
||||
1. 校验 Principal 和数据库 resource→project 授权图;
|
||||
2. 读取数据库 immutable ledger/current pointer;
|
||||
3. 检查并校验 workspace projection,仅作为缓存;
|
||||
4. 正文缺失但授权图完整时,可按 feature flag 从 FAV 只读降级;
|
||||
5. 权限图缺失、vault tombstone、SHA 冲突或来源不一致时 fail closed。
|
||||
|
||||
GET 不得修复数据库或覆盖 head。
|
||||
修复和恢复是独立命令,并产生审计记录。
|
||||
|
||||
## 8. 授权架构
|
||||
|
||||
### 8.1 Principal
|
||||
|
||||
Principal 由 HTTP session、服务身份或恢复凭证适配器构造,至少包含 actor ID、actor type、environment、认证来源、request/correlation ID 和明确 capabilities。
|
||||
`UserID`、`ProjectID`、role 和 duty 不能直接从业务请求体覆盖 Principal。
|
||||
|
||||
### 8.2 决策模型
|
||||
|
||||
授权决策输入为 `Principal + Action + Resource + CurrentState`。
|
||||
|
||||
| 动作类别 | 强制条件 |
|
||||
|---|---|
|
||||
| 文档读取 | 项目成员/管理员 + 分类可见性 + stage/duty 范围 |
|
||||
| 文档编辑/提交 | 写权限 + 当前 duty + 合法状态 + 有效 lease + expected head |
|
||||
| 批准/驳回 | 对应 action-level duty + 冻结实例配置 + 当前状态 |
|
||||
| TaskRun 执行/恢复 | 项目权限 + 合法 workflow/stage + 服务端解析的 backend capability |
|
||||
| FAV 降级读取 | 正常读取授权已成功 + artifact scope/hash/删除状态一致 |
|
||||
| replay/backfill | 运维 capability + 精确范围 + dry-run + 审计 |
|
||||
| scratch recovery promotion | 系统管理员 + 数据责任人确认 + scratch identity + 冲突计划无未决项 |
|
||||
|
||||
应用用例可以在事务前做快速拒绝,但状态改变必须在取得资源锁后重新读取授权相关事实并再次判定,防止成员、duty、stage 或 lease 在检查后变化。
|
||||
授权服务不可用或关系不完整时默认拒绝。
|
||||
事件携带的 actor 只用于审计;订阅者产生持久或外部副作用前重新读取当前权威状态。
|
||||
|
||||
### 8.3 后端与数据最小化
|
||||
|
||||
调用方不能提交任意 `Backend string`。
|
||||
应用层按环境、项目策略和输入敏感级别解析 `BackendRef`,agent 适配器再注入受管凭证。
|
||||
凭证不得进入 DTO、日志、事件、manifest、result 文件或 FAV。
|
||||
InputBundle 只包含完成任务必需的材料,并标记来源、分类、允许用途和生命周期。
|
||||
|
||||
## 9. 架构门禁
|
||||
|
||||
### 9.1 静态规则
|
||||
|
||||
| 规则 | 检查对象 | 例外 |
|
||||
|---|---|---|
|
||||
| 领域实现互不 import | Go production packages | 消费端口和稳定 vocabulary |
|
||||
| server 不 import repository/领域实现 | server production packages | app facade、wire DTO |
|
||||
| 表写入唯一属主 | production SQL 的 INSERT/UPDATE/DELETE/MERGE | Goose、测试 fixture、批准的修复工具 |
|
||||
| 工作区物理路径唯一属主 | production path construction/open/write | workspace/squadrun adapter |
|
||||
| 事件发布者 allowlist | event name → producer package | 无运行时动态注册旁路 |
|
||||
| 订阅者 allowlist | event name → consumer use case | replay 工具需显式 capability |
|
||||
|
||||
例外必须记录 owner、原因、范围、到期日和移除里程碑。
|
||||
warn/block 不按固定“两周”切换;每条规则在对应纵向切片清零后单独转 block。
|
||||
|
||||
### 9.2 行为门禁
|
||||
|
||||
架构检查不能替代以下测试:
|
||||
|
||||
- 同文档并发编辑、批准和 agent commit;
|
||||
- 任意事务步骤失败时全量回滚;
|
||||
- worker 崩溃、lease 过期、重复投递和多订阅者部分失败;
|
||||
- workspace 删除、换根、重启和 projection 重建;
|
||||
- FAV 降级读取与 scratch 恢复;
|
||||
- 匿名、非成员、跨用户、跨项目、错误 duty、错误 stage、授权依赖失败;
|
||||
- 真实浏览器刷新/重登/rebuild 与真实 PI 主链。
|
||||
|
||||
## 10. 可观测性与容量
|
||||
|
||||
### 10.1 必须指标
|
||||
|
||||
- 数据库事务时长、锁等待、deadlock、serialization retry、版本冲突率。
|
||||
- outbox pending/oldest age、delivery attempts、lease steal、dead letter 数。
|
||||
- projection missing/mismatch/repair、FAV degraded read、vault verification lag。
|
||||
- 授权 deny 按 action/reason 计数,不记录正文或敏感资源名。
|
||||
- workspace active lease、过期清理、fencing rejection、storage identity mismatch。
|
||||
|
||||
### 10.2 高并发基线
|
||||
|
||||
首个试点必须建立并保存基线,而不是直接承诺未经测量的容量数字:
|
||||
|
||||
- 同一文档热点写入与不同文档并行写入分开压测。
|
||||
- 1、2、4 个 app 实例下验证进程内锁不影响正确性。
|
||||
- 1、2、4 个 dispatcher 下验证无重复可见副作用、无饥饿和有界积压。
|
||||
- p50/p95/p99 延迟、锁等待、事务重试、CPU/连接池和队列年龄进入 test report。
|
||||
- 正确性门禁固定;吞吐阈值在基线评审后写入环境配置与发布 SLO,不能靠降低一致性通过。
|
||||
|
||||
## 11. 迁移与兼容
|
||||
|
||||
采用 expand → migrate → contract:
|
||||
|
||||
1. 新增兼容 schema、端口和读路径,不改变旧写入。
|
||||
2. 新写路径 shadow/dual-read 验证,禁止无审计双写。
|
||||
3. 按 checkpoint 幂等回填,异常进入 quarantine。
|
||||
4. 切主写者,保留旧 reader 一个明确发布窗口。
|
||||
5. 验证真实刷新/restart/rebuild、FAV coverage 和回滚。
|
||||
6. 删除旧路径前再次审计引用和数据差异。
|
||||
|
||||
旧 workspace 文件缺少 `schema_ver` 时按只读 legacy-v0 解析。
|
||||
首次受控 Resume 先校验并原子升级到 v1,保留可回滚备份;未知 major 版本 fail closed。
|
||||
|
||||
回滚只保证回到最近兼容点。
|
||||
已被下游里程碑消费的 schema 或契约必须按逆依赖顺序回滚,不能单独 revert 早期提交。
|
||||
|
||||
## 12. 首个交付边界
|
||||
|
||||
首个里程碑只覆盖受控文档可靠性:
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
Read[Authorized content read] --> Ledger[Immutable ledger]
|
||||
Ledger --> Projection{Projection aligned?}
|
||||
Projection -->|yes| Return[Return canonical content]
|
||||
Projection -->|no| Vault{Authorized FAV fallback enabled?}
|
||||
Vault -->|yes| Degraded[Return verified degraded content]
|
||||
Vault -->|no| Conflict[Typed consistency error]
|
||||
Commit[Edit or agent commit] --> Tx[Single UnitOfWork]
|
||||
Tx --> Ledger
|
||||
Tx --> Root[Document root pointer]
|
||||
Tx --> Stage[Artifact staging]
|
||||
Tx --> Event[Outbox]
|
||||
```
|
||||
|
||||
只有这个切片完成刷新、重启、并发、权限和恢复验收后,才启动其他包的物理拆分。
|
||||
|
||||
## 13. 后续扩展顺序
|
||||
|
||||
1. 文档可靠性试点。
|
||||
2. taskrun finalize、RunManifest 持久化和 FAV 集成。
|
||||
3. 逐个事件替换闭包桥。
|
||||
4. chatlog/contextasm 原地端口化,再按证据移动包。
|
||||
5. squadrun capability 化和 backend policy。
|
||||
6. app 组合根迁移。
|
||||
7. UserProjectContext 增量收权。
|
||||
8. server/SSE 收口。
|
||||
9. 错误信封与 PI Runner 协议作为独立项目实施。
|
||||
|
||||
详细依赖、文件和测试场景见整改计划。
|
||||
@@ -0,0 +1,475 @@
|
||||
# 多意图多任务识别、持久计划与 HITL 统一确认方案
|
||||
|
||||
> 状态: planned(方案已复核,未实施)
|
||||
> 日期: 2026-09-15
|
||||
> 作者: Cline(初稿)/ Codex(架构、安全与实施计划复核)
|
||||
> 关联: [方案审计](../audit/2026-09-15-multi-intent-hitl-plan-review.md);[意图识别深读](./intent-recognition/01-意图识别框架-设计-架构-实现-难点-解决方案-亮点与优势.md);[模块化单体架构](./2026-09-14-module-decoupling-architecture.md);[任务总览](../ops/short-term/2026-09-15-multi-intent-hitl.md)
|
||||
|
||||
---
|
||||
|
||||
## 一、结论与目标
|
||||
|
||||
方向可行,但原稿不能直接实施。需要先闭合计划生命周期、确认回路、授权、并发和模块归属。修订目标是:
|
||||
|
||||
1. 一次输入可安全识别 2–4 个候选子任务,并让用户核对系统理解;
|
||||
2. 只有确定的低风险只读组合可自动执行;批量生成、写入、控制、缺槽、冲突或不确定组合必须进入服务端持久化 HITL;
|
||||
3. 刷新、双标签页、服务/worker 重启和 SSE 晚到时,计划与卡片从 PostgreSQL 权威状态恢复;
|
||||
4. 确认只表达用户意愿,不授予权限。每一步执行前按当前主体、成员关系、资源状态和版本重新授权;
|
||||
5. 不回退已完成的解耦:`internal/intent` 保持纯规则领域模块;跨属主写入继续使用端口、单一写者、`app/uow` 和静态事件契约。
|
||||
|
||||
第一版按显式依赖顺序执行,每步独立提交,不承诺跨步骤原子回滚或并行 DAG 调度。
|
||||
|
||||
这项能力的直接价值不是替代逐条对话,而是消除当前“用户已经明确给出多个任务,系统却只执行 TopIntent 且不告知”的不可信行为,并让有依赖的“先查再生成”在一次可审计确认中完成。逐条提交仍是低复杂度场景的有效入口;如果 shadow 期显示多意图采用率低、确认放弃率高或用户普遍主动拆单,U7 之后的写动作扩面应停止,而不是为了完成路线图继续建设。
|
||||
|
||||
---
|
||||
|
||||
## 二、当前事实与缺口
|
||||
|
||||
| 能力 | 当前事实 | 证据 |
|
||||
|------|----------|------|
|
||||
| 单意图识别 | 18+ Intent、四级漏斗、三分支已实现;FEATURE-MATRIX 仍为 `partial`,不能称“已成熟” | `internal/intent/recognizer.go`、`.doc/status/FEATURE-MATRIX.md` |
|
||||
| V2 帧/动作表 | `IntentFrameV2`、ActionRegistry、风险、必填槽位、灰度开关已存在 | `internal/intent/types_v2.go`、`registry.go`、`flags.go` |
|
||||
| 有限多意图 | 默认开启;只按首个连接词拆两段;写意图返回 `nil` | `internal/intent/plan_builder.go` |
|
||||
| 有限执行 | 只读步骤顺序执行;需确认步骤只有文字提示 | `internal/coordinator/action_planner.go` |
|
||||
| HITL 基础 | PendingExpectation、四类卡片和 ExpiresAt 已存在;前端仍有本地业务状态修改路径 | `internal/intent/types.go`、`web/src/App.tsx` |
|
||||
| 可靠事件 | PG dispatcher、delivery、静态契约已 live;FAV 关闭 | `internal/events`、`.doc/ops/CURRENT.md` |
|
||||
| 模块边界 | `intent` 只允许依赖 `maturity`;chatflow/stageflow/doccontent 等解耦已完成 | `.doc/system-design/module-boundaries.yaml` |
|
||||
|
||||
关键缺口:分段不确定时可能退回 TopIntent 并静默丢任务;计划没有 revision、决策凭据、执行账本或可恢复状态机;确认没有统一服务端命令;ActionRegistry 风险容易被误当授权;未处理重复提交、双标签决策、过期竞态和 worker 抢占;卡片/SSE 不是权威状态;原稿把 agent backend 引入 L1 会破坏 intent 边界;T1–T5 全用 `intent` mutex 与实际跨模块范围不符;自由文本结果传递存在提示注入和数据泄露风险;固定样例数不能代替质量门槛。
|
||||
|
||||
---
|
||||
|
||||
## 三、硬约束与非目标
|
||||
|
||||
### 3.1 不可回退的解耦约束
|
||||
|
||||
| 约束 | 强制规则 | 验证 |
|
||||
|------|----------|------|
|
||||
| L1 纯度 | `internal/intent` 只做确定性分段、识别、帧和计划提案;不得访问网络、PG、文件或 agent backend | arch-check 保持 `intent -> maturity` |
|
||||
| 应用编排 | 新增 `internal/app/intentflow` 作为计划生命周期唯一编排入口 | chat/server 只依赖深接口,不获得 store/engine |
|
||||
| 单一写者 | `intent_plans*` 仅由 intentflow repository owner 写;业务动作仍写自己的表 | table owner + SQL write archtest |
|
||||
| 跨属主一致性 | 计划、决策、投影请求和 outbox 需要一致时使用不透明 `app/uow.TxScope` | 不暴露 pool/pgx.Tx |
|
||||
| 事件契约 | 新事件先登记 YAML 与 `events.StaticContracts`,再接 dispatcher | registry parity + 未注册 fail closed |
|
||||
| 授权归属 | intentflow 不复制 docgov/taskrun/workflow 权限,调用动作属主用例端口 | 每个 adapter 有即时授权负例 |
|
||||
| 组合根 | store、adapter、clock、ID generator、event sink 仅在 `internal/app/app.go` 装配 | server 不重新接线 |
|
||||
|
||||
### 3.2 非目标
|
||||
|
||||
- 不拆微服务或新增 RPC;不支持 >4 步、并行 DAG、多个活动写计划自动合并;
|
||||
- 不承诺跨步骤 ACID 或自动补偿;
|
||||
- 当前作用域没有活动写/生成计划时,不改变单意图生成任务行为;已有活动计划时统一进入冲突/替换流程,禁止启动第二个写计划;
|
||||
- 不让 LLM 决定风险、权限、槽位真值或执行顺序;
|
||||
- 不启用 FAV,也不把中间结果归档到 FAV;
|
||||
- 不借机全量重构 coordinator/chat action executor。
|
||||
|
||||
---
|
||||
|
||||
## 四、总体架构与权威性
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
UI[Web 计划卡] --> API[server HTTP/SSE]
|
||||
API --> FLOW[app/intentflow\n计划生命周期]
|
||||
CHAT[chat/chatflow] --> FLOW
|
||||
FLOW --> L1[intent\n纯规则提案]
|
||||
FLOW --> STORE[(plan owner store)]
|
||||
FLOW --> UOW[app/uow]
|
||||
FLOW --> PORTS[动作属主端口]
|
||||
FLOW --> EVENTS[events outbox]
|
||||
EVENTS --> PROJ[projection/notify]
|
||||
FLOW -.只建议分段.-> SEM[语义 adapter\nagent backend]
|
||||
```
|
||||
|
||||
`app/intentflow` 对外只提供:处理一轮输入、提交计划决策、读取授权后的 PlanView、恢复/推进已有计划。不得向调用者暴露 PlanStore、事务、`docgov.Engine`、`taskrun.Manager` 或 pool。
|
||||
|
||||
权威性从高到低:当前认证主体与资源状态 → 动作属主的授权/业务不变量 → PG 计划/步骤/决策 → 消息卡片投影 → SSE/前端内存。下层不得覆盖上层。
|
||||
|
||||
### 4.1 端到端流
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant U as 用户
|
||||
participant W as Web/server
|
||||
participant F as app/intentflow
|
||||
participant I as intent
|
||||
participant D as PG plan store
|
||||
participant A as 动作属主
|
||||
U->>W: input + client_turn_id
|
||||
W->>F: HandleTurn(principal, context, input)
|
||||
F->>I: 安全扫描、分段、逐段识别
|
||||
I-->>F: PlanProposal + evidence + digest
|
||||
alt 独立低风险只读
|
||||
F->>A: 每步即时授权并执行
|
||||
F-->>W: 聚合结果
|
||||
else 需澄清/确认
|
||||
F->>D: 同事务写 plan/steps/outbox
|
||||
F-->>W: 权威卡片
|
||||
U->>W: decision + nonce + expected_revision
|
||||
W->>F: DecidePlan
|
||||
F->>D: CAS 状态
|
||||
F->>A: 每步重新授权、执行
|
||||
F->>D: CAS step + receipt/ref
|
||||
F-->>W: PlanView
|
||||
end
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、领域模型与状态机
|
||||
|
||||
- `intent.PlanProposal`:L1 值对象,含规范化分段、候选帧、证据、缺槽和依赖建议;不含授权结论或 DB 状态;
|
||||
- `intentflow.Plan`:应用实体,含主体/会话/项目作用域、请求摘要、revision、过期、决策与执行账本;
|
||||
- `PlanView`:脱敏 UI 投影,不回传内部 payload、权限快照或完整中间结果;
|
||||
- UserProjectContext/消息只保留 `plan_id + revision` 引用,不持久化第二份 PendingPlan。
|
||||
|
||||
### 5.1 计划状态
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> proposed
|
||||
proposed --> awaiting_clarification
|
||||
proposed --> awaiting_confirmation
|
||||
proposed --> executing: 仅低风险只读
|
||||
awaiting_clarification --> awaiting_confirmation
|
||||
awaiting_clarification --> executing
|
||||
awaiting_clarification --> awaiting_clarification: 增量补槽形成新 revision
|
||||
awaiting_clarification --> superseded
|
||||
awaiting_confirmation --> executing
|
||||
awaiting_confirmation --> cancelled
|
||||
awaiting_confirmation --> expired
|
||||
awaiting_confirmation --> superseded
|
||||
executing --> partially_completed
|
||||
executing --> completed
|
||||
executing --> failed
|
||||
executing --> cancelled: 仅未开始步骤
|
||||
partially_completed --> completed
|
||||
partially_completed --> failed
|
||||
partially_completed --> executing: 用户选择重试/继续
|
||||
partially_completed --> cancelled: 取消全部未开始步骤
|
||||
```
|
||||
|
||||
编辑产生新 revision/digest,旧卡片 `outdated`;取消不能回滚已完成业务副作用;`skip` 只允许独立低风险只读步骤;依赖失败阻塞所有后代;`confirm_retry` 暂停计划并对指定失败步骤重新确认。
|
||||
|
||||
### 5.2 步骤、部分确认与幂等
|
||||
|
||||
步骤状态:`pending -> eligible -> running -> succeeded | failed | denied | conflicted | blocked_dependency | skipped | cancelled`。
|
||||
|
||||
- `eligible -> running` 用条件更新和 fencing token;
|
||||
- 动作幂等键:`plan_id:plan_revision:step_id:action_digest`;同键同摘要返回既有 receipt,同键异摘要冲突;
|
||||
- 动作属主端口必须接收 idempotency key、action digest、expected resource version 和 fencing token,并能按同一身份查询 receipt。只有属主事务能原子提交幂等占位与业务副作用,或已证明原生机制等价时,该 action 才能放量;旧 fence 必须被属主拒绝;
|
||||
- 部分确认必须是依赖闭包;选中步骤进入 eligible,未选独立步骤继续等待确认。只有用户显式“排除未选项”才写 `cancelled_by_user`,其后代取消或阻塞;
|
||||
- 高风险步骤逐项可见;确认父步骤不自动确认新出现的高风险后代;
|
||||
- “确认第 1 项并修改第 2 项”拆成决策和新 revision,不混为一个转移。
|
||||
|
||||
---
|
||||
|
||||
## 六、分段、识别与组合策略
|
||||
|
||||
### 6.1 确定性分段
|
||||
|
||||
`internal/intent` 内扩展纯规则分段器,支持连接词、句号、分号、换行、序号和“先/再/最后”,上限 4 段。输出包含规范化文本、原文 span、连接证据、结构置信类别和未解析指代。
|
||||
|
||||
1. 整句先做 Stage 0 安全扫描;分段规范化、槽位补丁、LLM 建议后再次逐段扫描;原文命中优先,整体拒绝;
|
||||
2. “查询并总结”“阅读后概括”等单动作内部链不拆;
|
||||
3. 只有确定为完整单意图时才合并回单意图;低置信、指代补全失败或无法证明完整时进入澄清,禁止退回 TopIntent 执行;
|
||||
4. 逐段识别后检查同资源冲突、重复动作和依赖;
|
||||
5. 超过 4 段不创建残缺计划,明确要求分批。
|
||||
|
||||
### 6.2 可选语义分段
|
||||
|
||||
LLM adapter 位于 intentflow 外围,不放进 `internal/intent`。它只能提出 `text span + connector + reason`,不能输出权限、风险、ActionKey、执行顺序或权威槽位。
|
||||
|
||||
- 只发送当前文本和必要的脱敏实体标签;不发送 secrets、完整历史、文档正文或权限表;
|
||||
- 严格版本化 schema;超时、格式错、span 重叠、越界或安全冲突均 fail closed;
|
||||
- 每段重新进入确定性 recognizer、ActionRegistry 和安全扫描;护栏优先,无法裁定就澄清;
|
||||
- 以 `request_digest + segmenter_version + model_contract_version` 固化已展示分段;重试不得因模型漂移改变计划;
|
||||
- shadow 日志只保留 digest、类别、差异和计数。
|
||||
|
||||
### 6.3 组合风险矩阵
|
||||
|
||||
ActionRegistry 提供动作身份、目标类别和静态风险提示,但不是授权或批量编排 SSOT。`app/intentflow` 拥有版本化 `BatchActionPolicy`,只记录 action key 的批量确认要求、可开放 tier、adapter 能力和 execution mode,并在启动时校验 key 存在于 ActionRegistry。它不得复制 Risk、RequiredSlots、CapabilityKey 或 AllowedStates。`task.run`/`task.run.adhoc` 的批量策略要求确认,同时保持其单意图 `RequiresConfirm` 不变。
|
||||
|
||||
| 条件 | 模式 | 行为 |
|
||||
|------|------|------|
|
||||
| 全部独立 RiskLow 查询、槽位齐、无冲突 | `auto_read` | 即时授权后执行 |
|
||||
| 任一批量生成、mutate/control、中高风险或 BatchActionPolicy 要求确认 | `awaiting_confirmation` | 先持久化并出卡,确认前零副作用 |
|
||||
| 缺槽、指代/分段/依赖不明 | `awaiting_clarification` | 聚合澄清;有槽位依赖时分组问 |
|
||||
| 原文或变换结果命中红线 | `rejected` | 整体拒绝,不执行其他段 |
|
||||
| >4 段 | `rejected_batch_size` | 要求分批 |
|
||||
|
||||
V2 灰度不可绕过:只有 ActionRegistry 映射稳定、V2 shadow 达门槛且当前 multi-intent tier 允许的动作可进入 decision;其余走 legacy 或显式澄清。
|
||||
|
||||
---
|
||||
|
||||
## 七、HITL、授权与并发协议
|
||||
|
||||
### 7.1 服务端权威卡片
|
||||
|
||||
`PLAN_CONFIRM` 折叠态也必须显示任务数、受影响目标、生成/写入/控制类型、最高风险、不可撤销副作用和“逐步提交、后续失败不回滚”提示;高风险步骤始终逐项可见。只有 action key、revision、digest 等技术元数据和低风险细节可折叠。支持全部确认、依赖闭包内部分确认、编辑、取消。
|
||||
|
||||
`CLARIFY_AGGREGATE` 展示逐步缺槽、约束、已知值和冲突。回复形成 slot patch 后必须重新识别、重新计算 digest、风险和授权预检。
|
||||
|
||||
用户只回答部分问题时保存可唯一映射的增量 patch,产生新 revision 并继续停留在 awaiting_clarification;新卡同时显示已解决值和剩余问题,旧卡 stale。不会要求重填已经验证的值,也不会在缺槽未闭合时提前执行。
|
||||
|
||||
澄清字段按步骤和依赖分组,标记“已验证/待填写/冲突/无效”,显示剩余数量;提交文案为“保存已填写并继续”,提交后保留合法值并聚焦首个未解决字段。
|
||||
|
||||
卡片 metadata 是 PG 状态投影。按钮和自然语言“确认/取消/只做第 1 项”统一进入服务端 `DecidePlan`;前端不得本地修改业务资源或先标成功。
|
||||
|
||||
部分确认 UI 使用依赖层级列表:选择子步骤时立即勾选并解释必需前置;存在已选后代时不能取消前置;提交按钮显示本次确认的步骤数和目标。未选项标为“继续等待”,显式排除是独立次级动作,并在提交前列出会被取消或阻塞的后代。
|
||||
|
||||
自然语言决策采用确定性语法优先:明确 plan/步骤编号或当前会话只有一个活动可见计划时才可绑定;“确认”在多个活动计划、步骤引用不合法或同时包含新任务时不执行,改为定向澄清。聚合槽位优先使用结构化卡片字段;自由文本只把可唯一映射的 `label:value`/已有 PatchSlots 结果写入 patch,冲突值、依赖值无效或多义值保持未解析并再次提问,绝不猜测。
|
||||
|
||||
### 7.2 确认不等于授权
|
||||
|
||||
执行每一步前,动作属主重新校验当前认证用户与 plan session/project/user、当前成员/duty/capability、资源归属/lifecycle/stage、expected version/ETag、动作允许状态。计划中的角色/权限快照只用于审计。失败进入 `denied/conflicted`,不得换系统身份代执行。
|
||||
|
||||
### 7.3 并发规则
|
||||
|
||||
- 创建:`(session_id, client_turn_id, request_digest)` 唯一;同 turn 异 digest 冲突;
|
||||
- 决策:必须带 `expected_revision`、`decision_nonce`、`decision_digest`;同 nonce 同摘要返回 receipt,异摘要冲突;
|
||||
- 标识:plan_id、step_id、decision_nonce 使用不可预测的随机标识;安全性不依赖其保密,所有访问仍做四元作用域授权;
|
||||
- 状态:当前 revision 且未过期的等待态才能 CAS;陈旧卡片返回 409 和当前安全视图;
|
||||
- 过期:服务端 `expires_at` 权威,TTLTurns 只显示;
|
||||
- 执行:短 lease + owner + lease_until + 单调 fencing;续租失败不再领步骤;
|
||||
- 竞态:确认/取消/过期、编辑/确认只允许一个 CAS 胜出;
|
||||
- SSE:允许重复/乱序/丢失,前端按 revision/step version 去重,发现缺口 GET 对账。
|
||||
|
||||
同一 user/session/project 同时只允许一个活动写/生成计划。新的低风险查询可独立处理;新的写计划必须让用户完成、取消或显式替换旧计划,不自动合并。计划锁不替代业务资源自己的 lease/version lock。
|
||||
|
||||
因此“单意图生成保持现状”仅适用于没有活动写/生成计划的作用域。有活动计划时,无论新输入是单意图还是多意图,都返回同一服务端冲突视图,禁止创建第二个 task/run;真实页面验收分别覆盖无活动计划兼容和有活动计划冲突。
|
||||
|
||||
`partially_completed` 必须提供前向收口卡:重试指定失败步骤、继续仍 eligible 的独立步骤、取消所有未开始步骤并关闭计划。已成功 receipt 永不回滚;running 步骤先由 lease/fencing 收口,卡片列明已发生且不可撤销的副作用。
|
||||
|
||||
---
|
||||
|
||||
## 八、持久化、事务、事件与数据治理
|
||||
|
||||
### 8.1 表与所有权
|
||||
|
||||
`intent_plans`:plan_id、environment/project/session/user/client_turn、request_digest、segmenter/policy version、status、revision、expires_at、timestamps、last_fencing_token。原始输入沿用 chat message 保留;计划表保存引用、digest 和脱敏展示快照。
|
||||
|
||||
`intent_plan_steps`:plan/step、action_key、规范化 slots、依赖、status、expected_resource_version、action_digest、idempotency_key、attempt、result_ref/digest、safe_summary、timestamps、version。
|
||||
|
||||
`intent_plan_decisions`:append-only decision id/nonce、plan revision、actor、kind、step selection、patch/request digest、outcome、created_at。关键 CAS、审计和查询字段必须类型化;JSONB 只用于版本化 slots/display snapshot。三表 owner 登记为 `app/intentflow`,其他包只能走端口。
|
||||
|
||||
### 8.2 事务与恢复
|
||||
|
||||
- 创建:plan + steps + card projection request + outbox 同一 UoW;
|
||||
- 决策:decision append + plan CAS + eligible steps 同一 UoW;
|
||||
- 业务副作用由动作属主事务提交,再以 idempotent receipt 更新步骤,不制造跨模块长事务;
|
||||
- 业务成功但 receipt 写回失败时,通过动作幂等键查既有结果并对账,不盲跑;
|
||||
- 消息投影失败不回滚权威计划,dispatcher 重试,刷新 GET 修复。
|
||||
|
||||
### 8.3 事件与作用域
|
||||
|
||||
只发布事实,不发布执行命令。候选事件 `intent.plan.awaiting_input`、`intent.plan.step_changed`、`intent.plan.completed` 必须同时登记 YAML、StaticContracts、schema/golden 和 parity test。
|
||||
|
||||
payload 仅含 plan/revision/step/status、environment/project/user/session scope 和安全摘要引用;不含原 prompt、完整 slots、权限快照或完整结果。消费者和 SSE 投递前按当前主体重新读取授权后的 PlanView;同项目不同用户不能互见。
|
||||
|
||||
### 8.4 留存与结果传递
|
||||
|
||||
- plan/decision 随会话和项目数据政策清理,不早于关联 chat/taskrun 审计窗口;删除由 owner 执行;
|
||||
- 中间结果仅保存 `ResultReference`:producer、result/artifact ID、digest、类型、敏感级别、允许用途和长度受限 safe summary;
|
||||
- 不把前序自由文本直接拼入权威槽位或后续指令区。后续生成只能把带来源的数据放入隔离材料区,不能扩大 action/target/tool/capability;
|
||||
- 若结果导致动作、目标或范围变化,产生新 revision 并重新确认;
|
||||
- 最终生成物仍归 taskrun/受控文档/FAV(启用后),计划库不充当成果仓。
|
||||
|
||||
---
|
||||
|
||||
## 九、API、刷新与前端
|
||||
|
||||
资源接口必须包括 `GET /api/v1/intent-plans/active`(按当前 principal/environment/project/session/user 发现活动计划)、`GET /api/v1/intent-plans/{plan_id}` 与 `POST /api/v1/intent-plans/{plan_id}/decisions`。页面 bootstrap、刷新和 SSE 缺口恢复先查询 active,再拉 PlanView;消息投影失败时仍能找回计划。
|
||||
|
||||
decision API 继承当前服务端认证方式、Origin/CSRF 策略和统一限流;nonce/幂等键只防重放与并发,不替代 CSRF 或身份认证。若当前认证方式不具备适用的 CSRF 防护,U1 必须把它列为 U5 的前置 blocker,而不是在计划端点单独发明一套弱机制。
|
||||
|
||||
统一错误码至少包括:`PLAN_NOT_FOUND_OR_HIDDEN`、`PLAN_STALE_REVISION`、`PLAN_EXPIRED`、`PLAN_DECISION_CONFLICT`、`PLAN_DEPENDENCY_INVALID`、`PLAN_ACTION_FORBIDDEN`、`PLAN_ACTION_VERSION_CONFLICT`。无权主体沿用资源隐藏策略,避免枚举 plan_id。
|
||||
|
||||
刷新时由 plan 表生成卡片/进度,不从旧按钮或 SSE 推断。页面刷新、重开、SSE 重连均以 GET 覆盖本地缓存。卡片需支持键盘/读屏、依赖说明、错误焦点、过期/陈旧状态;按钮提交后可显示 submitting,但只有服务端 receipt 能变为 executing/resolved。完整结果从 owning API 读取,SSE 只携安全摘要和版本。
|
||||
|
||||
状态恢复矩阵:submitting 锁定重复提交并保留选择;outdated/conflict 自动读取最新 PlanView、聚焦状态通知并提供“查看最新版”;expired 禁用原决策,保留只读摘要并提供“按当前上下文重建计划”;服务端字段错误保留未提交输入并聚焦对应字段。会话顶部提供可关闭但可重新发现的活动计划入口,无活动计划返回明确空态。
|
||||
|
||||
可访问性契约:步骤用有序列表和带 legend 的选择组;折叠控件暴露 `aria-expanded/aria-controls`;进度用 polite live region,阻断错误用 alert 并聚焦;状态不只靠颜色;键盘顺序为摘要、步骤、主/次动作;窄屏单列、无横向滚动、触控目标至少 44px,并支持 reduced-motion。
|
||||
|
||||
---
|
||||
|
||||
## 十、灰度、指标与回滚
|
||||
|
||||
保留 `MULTI_INTENT_ENABLED` 作为 legacy 开关;在任何行为变更前新增 `MULTI_INTENT_PLAN_TIER=legacy|shadow|auto_read|confirm|full`,默认 `legacy`。
|
||||
|
||||
- legacy:保持现有路径,但一旦可靠检测到未处理写/生成段,不得静默只执行 TopIntent,应澄清;
|
||||
- shadow:只生成提案/指标,不建计划、不改路由;
|
||||
- auto_read:先保持现状上限,仅开放 2 个低风险只读步骤;3–4 个只读步骤先进入确认/观察,达到单独门槛后再扩大;
|
||||
- confirm:开放持久卡片;真实 adapter 未启用时只能产生 `validated_only` 预检。Plan、step、receipt 和 PlanView 显式携带 execution mode;`validated_only` 不能写 `succeeded/completed`,UI 必须显示“仅验证,未执行”;
|
||||
- full:按 action key 逐项开放已验收 adapter。
|
||||
|
||||
LLM 分段独立开关且从 shadow 起步。关闭新计划创建后,已有计划仍能读取、取消和收口;不能回滚到无法处理已持久计划的版本。
|
||||
|
||||
| 指标 | 停走条件 |
|
||||
|------|----------|
|
||||
| 未确认/越权副作用 | 0 |
|
||||
| 安全红线绕过 | 0 |
|
||||
| hard-negative 反事实错误自动执行 | 0;shadow 必须计算“若处于 auto_read/confirm 会如何路由”,不能用实际未执行冒充零错误 |
|
||||
| 重复确认导致重复动作 | 0 |
|
||||
| refresh/restart 权威状态差异 | 0 |
|
||||
| split precision/recall、澄清率、放弃率 | U2 先固定数据集与基线,再预注册阈值;未达不切档 |
|
||||
| 用户采用与确认负担 | 记录多意图采用率、确认放弃率、拆单回退率;若价值不足,停止 U8/U9 而保留“识别后不静默丢弃”的安全改进 |
|
||||
| projection backlog/dead letter | 不突破 Track E 既有预算 |
|
||||
|
||||
观察窗口由样本量和流量决定,不能用固定“一周”代替证据。
|
||||
|
||||
---
|
||||
|
||||
## 十一、实施计划(核心 U1–U8、按属主扩面 U10–U12、可选实验 U9)
|
||||
|
||||
### U1. 契约冻结与架构门禁
|
||||
|
||||
**目标:** 冻结 intentflow 边界、状态机、数据字典、错误码、事件和兼容策略。
|
||||
**依赖:** 无。
|
||||
**文件:** `.doc/system-design/module-boundaries.yaml`、`internal/events/registry.go`、API/schema 文档、arch/event tests。
|
||||
**做法:** 注册 app/intentflow allowlist 与 table owner;保持 intent->maturity;冻结 BatchActionPolicy,但不向 intent 回灌 HITL/tier/adapter 字段;先落默认 legacy tier;禁止 server/chat 直写计划表。
|
||||
**测试:** 新 import/SQL/event 违规 block;YAML/registry parity;未知 action/policy key fail closed;ActionRegistry 不出现批量执行策略;单意图生成策略不变。
|
||||
**停走门:** 架构测试全绿,授权/状态契约无待实现者猜测。
|
||||
**mutex:** 纯契约文档用 `architecture-docs`;事件注册变更串行占 `events`。U1 不修改 intent 业务类型,intent 代码变更从 U2 开始。
|
||||
|
||||
### U2. 确定性分段、PlanProposal 与 shadow 基线
|
||||
|
||||
**目标:** 不改变生产路由地生成 2–4 步提案和差异指标。
|
||||
**依赖:** U1。
|
||||
**文件:** `internal/intent/segmenter.go`、`plan_builder.go`、`types_v2.go`、`registry.go`、`internal/intent/testdata/*` 及 tests。
|
||||
**做法:** characterization-first;规则分段、span、指代/连动护栏、安全复扫、显式依赖、稳定 digest。
|
||||
**测试:** 连接词/句号/序号;查询并总结不拆;指代失败澄清;红线整体拒绝;5 段拒绝;同输入 digest 稳定;写段不静默丢弃。
|
||||
**停走门:** shadow 不改响应;对 golden、hard-negative 和真实抽样人工标签做 counterfactual evaluation,报告分母、误拆/漏段/错误自动执行率及置信区间;预注册阈值未达不得切档。
|
||||
**mutex:** `intent`。
|
||||
|
||||
### U3. intentflow、PG 状态机与 repository
|
||||
|
||||
**目标:** 建立持久计划/步骤/决策与并发协议,不接真实写动作。
|
||||
**依赖:** U1、U2。
|
||||
**文件:** `internal/app/intentflow/*`、`deploy/postgres/goose/*intent_plan*`、`internal/app/app.go`、PG tests。
|
||||
**做法:** owner repository、UoW、CAS revision、decision nonce、绝对过期、lease/fencing、创建幂等、retention、组合根装配。
|
||||
**测试:** 双创建;nonce 同/异 digest;确认/取消/过期竞态;两 worker 抢占;租约接管;旧 fencing token 在动作属主处被拒绝;重启恢复;业务成功但 receipt 写回失败;环境隔离。
|
||||
**停走门:** 无双 owner/双执行,arch-check 无新例外。
|
||||
**mutex:** 新增 `intent-plan`,迁移窗口协调 `db/app`。
|
||||
|
||||
### U4. 事件、卡片与步骤投影
|
||||
|
||||
**目标:** 权威计划可靠投影;消息/SSE 丢失不影响恢复。
|
||||
**依赖:** U3。
|
||||
**文件:** 新增 intent-plan event registry/schema、intentflow projection subscriber、ctxmgr owner port、对应 parity/dispatcher integration tests。
|
||||
**做法:** 同 UoW outbox、事实事件、消费者幂等与最小 payload;复用 Track E 已有重试/dead letter/replay。禁止修改通用 claim、lease、delivery、retry 或 replay 语义;若确需修改,另立缺陷任务。
|
||||
**测试:** 重复/乱序;projection 暂停 replay;消息失败后 GET 修复;worker restart;伪造 producer/字段拒绝;同项目跨用户不可见。
|
||||
**停走门:** shadow projection 与 DB diff=0,delivery 可查。
|
||||
**mutex:** `events`;ctxmgr 写入只走 owner 端口。
|
||||
|
||||
### U5. 决策 API 与即时授权端口
|
||||
|
||||
**目标:** 按钮/自然语言走同一服务端命令,执行前重新授权。
|
||||
**依赖:** U3。
|
||||
**文件:** `internal/server/*intent_plan*`、`internal/app/intentflow/*`、授权端口契约、fake/dry-run adapter、auth integration tests。
|
||||
**做法:** active discovery/GET/decision、错误信封、四元作用域、expected revision、依赖闭包、资源版本;不在本单元接真实业务属主 adapter。
|
||||
**测试:** 投影缺失仍能发现活动计划;非成员/跨项目/跨 session;角色撤销;资源变更;stale revision;重复点击;非法部分确认;edit 使旧卡失效;按钮/自然语言同 receipt。
|
||||
**停走门:** 权限负例全绿;确认前零副作用;无系统身份绕过。
|
||||
**mutex:** `intent-plan` + `server/authz`;动作接入另占 owner mutex。
|
||||
|
||||
### U6. Web 卡片、刷新与可访问性
|
||||
|
||||
**目标:** UI 只呈现 PlanView,刷新和多标签一致。
|
||||
**依赖:** U4、U5。
|
||||
**文件:** `web/src/types/workbench.ts`、`web/src/components/chat/InteractiveCard.tsx`、API client、`web/src/App.tsx`、web/browser tests。
|
||||
**做法:** 两卡、步骤进度、依赖选择、submitting/outdated/expired/conflict、GET reconcile;计划动作不进入本地 AST/资源修改路径。
|
||||
**测试:** reload/reopen 与无投影 active discovery;双标签确认/取消;409 查看最新版;过期重建;字段输入保留;键盘/读屏/live-region;窄屏 44px/reduced-motion;SSE 重复乱序;慢请求;validated_only 明示未执行。
|
||||
**停走门:** 真实浏览器双标签/reload 无本地假成功。
|
||||
**mutex:** `web`。
|
||||
|
||||
### U7. 低风险只读执行与聚合
|
||||
|
||||
**目标:** 独立低风险查询从 proposal 安全推进到完成。
|
||||
**依赖:** U4、U5;可与 U6 并行,开放 auto_read tier 前两者都必须通过。
|
||||
**文件:** `internal/app/intentflow/*`、query adapters、coordinator/chatflow 兼容入口、integration tests。
|
||||
**做法:** 每步即时授权、显式依赖、ResultReference、失败/阻塞汇报;旧 executeIntentPlan 仅兼容,不扩成跨模块 switch。
|
||||
**测试:** 2–4 查询;独立失败继续;依赖失败阻塞;敏感字段脱敏;同 turn 重放;重启续跑。
|
||||
**停走门:** legacy 单意图无回归,重复执行为 0。
|
||||
**mutex:** `intent-plan`;触及入口时协调 `chat`。
|
||||
|
||||
### U8. 生成任务 adapter
|
||||
|
||||
**目标:** 经确认后只开放 `task.run` 与 `task.run.adhoc`,形成第一版生成闭环。
|
||||
**依赖:** U7。
|
||||
**文件:** intentflow taskrun adapter、taskrun owner port/tests、real PI/browser tests。
|
||||
**做法:** shadow/dry-run 后开启;传稳定幂等键,保存 result reference/receipt;不改变无活动计划时的单意图行为。
|
||||
**测试:** 多意图生成需确认;活动计划冲突;权限撤销;重放;部分完成;receipt 丢失恢复;真实 PI 结果引用。
|
||||
**停走门:** taskrun owner/PG/auth/browser/real PI 分层证据全绿。
|
||||
**mutex:** `taskrun` + `intent-plan`。
|
||||
|
||||
### U9. LLM 分段 adapter 与全面灰度
|
||||
|
||||
**目标:** 仅为规则无法可靠判断的输入提供受控建议。
|
||||
**依赖:** U2、U7。
|
||||
**文件:** intentflow segment proposal port/adapter、版本化 schema、eval/real PI tests。
|
||||
**做法:** 最小输入、严格 schema、固定版本/digest、护栏优先、shadow、超时 fail closed。
|
||||
**测试:** malformed/timeout;重试稳定;模型改风险/权限无效;红线拆分逃逸失败;敏感内容不出站;冲突澄清。
|
||||
**停走门:** real PI eval 达预注册阈值且安全错误为 0。
|
||||
**mutex:** `intent-plan` + `pi-agent`,不得改变 intent imports。
|
||||
|
||||
U9 是核心首版之外的独立实验,不参与 U1–U8 的完成判定。未实施或未达阈值时,规则无法裁定的输入继续进入澄清。
|
||||
|
||||
### U10. 低风险 mutate adapters
|
||||
|
||||
**目标:** 只接入经专项批准的 medium/low mutate action。
|
||||
**依赖:** U8。
|
||||
**文件:** 每个动作的 intentflow adapter 与 owner tests。
|
||||
**做法:** 每个 action 独立 short-term、flag、dry-run、权限负例和回滚;不打包发布。
|
||||
**停走门:** 单 action 证据齐全后才加入 full tier。
|
||||
**mutex:** 对应动作 owner + `intent-plan`。
|
||||
|
||||
### U11. 文档治理 adapters
|
||||
|
||||
**目标:** 按 claim/submit/review/final 等 action 分项接入 docgov,不复制其 duty/lifecycle 规则。
|
||||
**依赖:** U8。
|
||||
**文件:** intentflow docgov adapters、docgov owner ports/tests、browser auth negatives。
|
||||
**做法:** 高风险动作逐个任务、逐个 go/no-go;必须带 expected document version。
|
||||
**停走门:** 各 action 的跨角色、生命周期和并发负例独立签署。
|
||||
**mutex:** `docgov` + `intent-plan`。
|
||||
|
||||
### U12. Workflow 与 run-control adapters
|
||||
|
||||
**目标:** 分别接入 workflow switch/run 与 task run resume/restart/cancel。
|
||||
**依赖:** U8。
|
||||
**文件:** intentflow workflow/run adapters、owner ports/tests。
|
||||
**做法:** workflow 与 run-control 必须拆成独立 short-term,不共用发布开关或回滚点。
|
||||
**停走门:** 当前 stage/state、权限、幂等和冲突负例分别通过。
|
||||
**mutex:** `workflow` 或 `taskrun` + `intent-plan`。
|
||||
|
||||
---
|
||||
|
||||
## 十二、验收矩阵与 DoD
|
||||
|
||||
必须覆盖:两个只读查询;查询+生成确认前零副作用;部分确认后未选项仍可稍后确认、显式排除才取消;增量补槽保留已验证值;部分完成可重试/继续/关闭;确认后权限撤销;双标签确认/取消只一方成功;确认/过期竞态;服务/worker 重启不重跑成功步骤;投影停机而 GET 正确;“查法规并总结”不误拆;红线混入整体拒绝;前序结果含提示注入仍只作材料;无活动计划时单意图生成不变、有活动计划时不创建第二任务、批量生成需确认;跨用户/项目/会话隐藏;同 turn/nonce 异摘要冲突;编辑后旧卡 stale。
|
||||
|
||||
Definition of Done:
|
||||
|
||||
- [ ] 核心首版 U1–U8 按各自停走门独立验收;U9、U10–U12 未实施不阻塞首版,但任何已启用 adapter 必须满足自己的停走门;
|
||||
- [ ] `intent -> maturity` 保持,intentflow 无 service locator、pool 或跨 owner SQL;
|
||||
- [ ] 所有写/生成/控制在未确认和越权时副作用为 0;
|
||||
- [ ] 双标签、刷新、服务/worker 重启、重复/乱序事件下无双执行且可恢复;
|
||||
- [ ] 按钮与自然语言走同一命令,每步即时授权并校验资源版本;
|
||||
- [ ] 中间结果不进 FAV,事件不携带敏感正文;
|
||||
- [ ] arch-check、Go short、PG、web build/test、真实 browser 和适用 real PI 分别有报告;
|
||||
- [ ] FEATURE-MATRIX、CURRENT、任务与必要时 gap-matrix 一致;
|
||||
- [ ] 清除废弃实验、旧本地成功路径和临时开关;回滚版本仍能读取/取消已有计划。
|
||||
|
||||
---
|
||||
|
||||
## 十三、关键决策
|
||||
|
||||
1. 采用 `app/intentflow` 深模块,不继续膨胀 coordinator;
|
||||
2. 单意图生成行为保持;多意图策略由 intentflow 的 BatchActionPolicy 管理并引用 ActionRegistry action key,不把应用编排政策回灌 L1;
|
||||
3. 同步权威状态 + outbox 投影,不用纯事件驱动 plan state;
|
||||
4. 服务端绝对过期,不用 TTLTurns 作权威;
|
||||
5. 逐步骤事务,不制造跨 owner 长事务;
|
||||
6. LLM 只建议分段且最后实施;
|
||||
7. 新行为默认 legacy/shadow,现有 `MULTI_INTENT_ENABLED=true` 不是自动放量许可。
|
||||
|
||||
不采用:把完整 PendingPlan 塞进 UserProjectContext、扩展前端本地 cardActionEngine 执行业务、用 coordinator switch 持有所有具体 engine、LLM 直接生成可执行计划、跨模块大事务。它们会造成双真相、越权/假成功、service locator 回潮、不可信执行或解耦倒退。
|
||||
|
||||
长期维护归属按模块分开:intent owner 维护规则与评测;intentflow owner 维护状态机、schema 和 rollout;web owner 维护卡片交互;events owner 维护投影契约;各 action owner 维护自己的授权 adapter。上线后每次新增 ActionSpec 必须同时给出批量策略、计划适配能力和负例,不能让矩阵靠人工记忆同步。
|
||||
@@ -99,6 +99,45 @@
|
||||
|
||||
---
|
||||
|
||||
### 6. 模块化单体解耦架构
|
||||
|
||||
| 项 | 链接 |
|
||||
|-----|------|
|
||||
| 主报告 | [2026-09-14-module-decoupling-architecture.md](2026-09-14-module-decoupling-architecture.md) |
|
||||
| ADR | [../adr/2026-09-14-modular-monolith-decoupling.md](../adr/2026-09-14-modular-monolith-decoupling.md) |
|
||||
| 整改计划 | [../remediation/2026-09-14-module-decoupling-refactor-plan.md](../remediation/2026-09-14-module-decoupling-refactor-plan.md) |
|
||||
| 一句话总结 | 先以文档可靠性纵向试点验证事务、锁、授权、事件与 FAV,再按证据扩展模块边界 |
|
||||
|
||||
**核心要点**:
|
||||
|
||||
- 单一写者负责 SQL 和不变量,应用 UnitOfWork 负责跨属主原子提交;
|
||||
- 数据库行锁、事务级 advisory lock、唯一约束和 fencing token 支撑多副本并发;
|
||||
- workspace 是可清理投影,FAV 只保存已确认终态成果;
|
||||
- 事件采用逐消费者 delivery、幂等 inbox、租约、重试和 dead letter;
|
||||
- HTTP、CLI、worker、subscriber 和恢复工具使用同一逐动作授权模型;
|
||||
- 先原地端口化,行为稳定后才物理搬包。
|
||||
|
||||
---
|
||||
|
||||
### 7. 多意图持久计划与 HITL
|
||||
|
||||
| 项 | 链接 |
|
||||
|-----|------|
|
||||
| 主方案 | [2026-09-15-multi-intent-hitl-plan.md](2026-09-15-multi-intent-hitl-plan.md) |
|
||||
| 复核 | [../audit/2026-09-15-multi-intent-hitl-plan-review.md](../audit/2026-09-15-multi-intent-hitl-plan-review.md) |
|
||||
| 任务总览 | [../ops/short-term/2026-09-15-multi-intent-hitl.md](../ops/short-term/2026-09-15-multi-intent-hitl.md) |
|
||||
| U1 契约 | [../ops/short-term/2026-09-15-multi-intent-u1-contracts.md](../ops/short-term/2026-09-15-multi-intent-u1-contracts.md) |
|
||||
| U2 分段 | [../ops/short-term/2026-09-15-multi-intent-u2-segmenter.md](../ops/short-term/2026-09-15-multi-intent-u2-segmenter.md);[报告](../test-reports/2026-09-15-multi-intent-u2-segmenter-test-report.md) |
|
||||
| U3 PG | [../ops/short-term/2026-09-15-multi-intent-u3-intentflow-pg.md](../ops/short-term/2026-09-15-multi-intent-u3-intentflow-pg.md);[报告](../test-reports/2026-09-15-multi-intent-u3-intentflow-pg-test-report.md) |
|
||||
| U4 投影 | [../ops/short-term/2026-09-16-multi-intent-u4-outbox-projection.md](../ops/short-term/2026-09-16-multi-intent-u4-outbox-projection.md);[报告](../test-reports/2026-09-16-multi-intent-u4-outbox-projection-test-report.md) |
|
||||
| U5 API | [../ops/short-term/2026-09-16-multi-intent-u5-decision-api.md](../ops/short-term/2026-09-16-multi-intent-u5-decision-api.md);[报告](../test-reports/2026-09-16-multi-intent-u5-decision-api-test-report.md) |
|
||||
| U6 Web | [../ops/short-term/2026-09-16-multi-intent-u6-web-cards.md](../ops/short-term/2026-09-16-multi-intent-u6-web-cards.md);[报告](../test-reports/2026-09-16-multi-intent-u6-web-cards-test-report.md) |
|
||||
| 一句话总结 | intent 保持纯规则,intentflow 持久化计划并统一确认、授权、幂等、恢复和逐动作执行 |
|
||||
|
||||
**硬边界**:确认不等于授权;PG 是计划真相,卡片/SSE 是投影;写动作按 owner 端口逐项接入;LLM 只能提出不可信分段建议。
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ 在整体架构中的位置
|
||||
|
||||
```
|
||||
@@ -161,6 +200,7 @@
|
||||
├── 04-项目多工作流与智能产品经理-测试经理工作流-实施计划.md
|
||||
├── 05-Phase0-基线确认与契约冻结.md
|
||||
└── 06-Phase7-全链路验收与发布基线.md
|
||||
├── 2026-09-14-module-decoupling-architecture.md ← 模块化单体解耦
|
||||
|
||||
.tmp/ ← 中间分析文件
|
||||
├── intent-recognition/
|
||||
|
||||
@@ -0,0 +1,600 @@
|
||||
# U1 architecture baseline. Import allowlist is a 2026-09-14 production go list snapshot.
|
||||
# SQL write / path / event rules apply only to production Go (not Goose, *_test.go, or fixtures).
|
||||
# Existing debt lives in exceptions with owner + milestone + expiry. New findings block immediately.
|
||||
|
||||
imports:
|
||||
agent:
|
||||
- config
|
||||
auth:
|
||||
- config
|
||||
authz:
|
||||
- docduty
|
||||
bizdev:
|
||||
- authz
|
||||
- config
|
||||
- ctxmgr
|
||||
- db
|
||||
- docduty
|
||||
- docgov
|
||||
- docrevision
|
||||
- freedoc
|
||||
- kb
|
||||
- maturity
|
||||
- projectcontext
|
||||
- projectworkflow
|
||||
- quote
|
||||
- squad
|
||||
- storage
|
||||
- stream
|
||||
- workflowdef
|
||||
chat:
|
||||
- app/chatflow
|
||||
- app/intentflow
|
||||
- app/stageflow
|
||||
- coordinator
|
||||
- ctxmgr
|
||||
- docgov
|
||||
- intent
|
||||
- projectinstance
|
||||
- replyexport
|
||||
- squad
|
||||
- stream
|
||||
- taskrun
|
||||
config: []
|
||||
coordinator:
|
||||
- agent
|
||||
- app/stageflow
|
||||
- ctxmgr
|
||||
- docgov
|
||||
- intent
|
||||
- kb
|
||||
- maturity
|
||||
- projectinstance
|
||||
- squad
|
||||
- stream
|
||||
ctxmgr:
|
||||
- app/uow
|
||||
- docgov
|
||||
- replyexport
|
||||
- storage
|
||||
db: []
|
||||
docduty: []
|
||||
app:
|
||||
- agent
|
||||
- app/chatflow
|
||||
- app/docadvance
|
||||
- app/docflow
|
||||
- app/docnotify
|
||||
- app/docproject
|
||||
- app/intentflow
|
||||
- app/stageflow
|
||||
- app/uow
|
||||
- artifactvault
|
||||
- auth
|
||||
- authz
|
||||
- bizdev
|
||||
- config
|
||||
- coordinator
|
||||
- ctxmgr
|
||||
- docgov
|
||||
- docrevision
|
||||
- events
|
||||
- freedoc
|
||||
- intent
|
||||
- kb
|
||||
- notification
|
||||
- observability
|
||||
- projectinstance
|
||||
- projectworkflow
|
||||
- storage
|
||||
- taskrun
|
||||
- workflowdef
|
||||
- workspace
|
||||
app/chatflow:
|
||||
- coordinator
|
||||
- ctxmgr
|
||||
- maturity
|
||||
- projectinstance
|
||||
app/docnotify:
|
||||
- docgov
|
||||
- docrevision
|
||||
- notification
|
||||
- events
|
||||
app/docadvance:
|
||||
- docgov
|
||||
- events
|
||||
- notification
|
||||
- projectinstance
|
||||
- projectworkflow
|
||||
app/docproject:
|
||||
- docgov
|
||||
- events
|
||||
app/docflow:
|
||||
- app/uow
|
||||
- docgov
|
||||
- docquery
|
||||
- docrevision
|
||||
- events
|
||||
app/intentflow:
|
||||
- app/uow
|
||||
- events
|
||||
- intent
|
||||
app/uow: []
|
||||
app/stageflow:
|
||||
- bizdev
|
||||
docquery:
|
||||
- docgov
|
||||
- docrevision
|
||||
docgov:
|
||||
- app/uow
|
||||
- doccontent
|
||||
- docduty
|
||||
- fsutil
|
||||
docrevision:
|
||||
- app/uow
|
||||
- doccontent
|
||||
- fsutil
|
||||
doccontent: []
|
||||
freedoc:
|
||||
- app/uow
|
||||
- ctxmgr
|
||||
- docrevision
|
||||
- replyexport
|
||||
fsutil: []
|
||||
httpx: []
|
||||
intent:
|
||||
- maturity
|
||||
kb:
|
||||
- config
|
||||
maturity: []
|
||||
notification: []
|
||||
observability: []
|
||||
projectcontext:
|
||||
- squad
|
||||
projectinstance:
|
||||
- docduty
|
||||
- docgov
|
||||
- projectworkflow
|
||||
- workflowdef
|
||||
projectworkflow:
|
||||
- auth
|
||||
quote: []
|
||||
replyexport: []
|
||||
server:
|
||||
- agent
|
||||
- app
|
||||
- app/chatflow
|
||||
- app/docflow
|
||||
- app/intentflow
|
||||
- app/stageflow
|
||||
- app/uow
|
||||
- auth
|
||||
- authz
|
||||
- bizdev
|
||||
- chat
|
||||
- config
|
||||
- coordinator
|
||||
- ctxmgr
|
||||
- docduty
|
||||
- docgov
|
||||
- docquery
|
||||
- docrevision
|
||||
- events
|
||||
- freedoc
|
||||
- httpx
|
||||
- intent
|
||||
- kb
|
||||
- notification
|
||||
- observability
|
||||
- projectinstance
|
||||
- projectworkflow
|
||||
- replyexport
|
||||
- storage
|
||||
- squad
|
||||
- stream
|
||||
- stream/transport
|
||||
- taskrun
|
||||
- upload
|
||||
- workflowdef
|
||||
- workspace
|
||||
- artifactvault
|
||||
squad:
|
||||
- agent
|
||||
- config
|
||||
- quote
|
||||
- stream
|
||||
- template
|
||||
- workspace
|
||||
storage: []
|
||||
stream: []
|
||||
stream/transport:
|
||||
- stream
|
||||
taskrun:
|
||||
- app/uow
|
||||
- artifactvault
|
||||
- bizdev
|
||||
- ctxmgr
|
||||
- events
|
||||
- projectworkflow
|
||||
- stream
|
||||
- workspace
|
||||
template: []
|
||||
upload: []
|
||||
workflow: []
|
||||
workflow/runtime:
|
||||
- projectinstance
|
||||
- workflowdef
|
||||
workflowdef:
|
||||
- projectworkflow
|
||||
- storage
|
||||
- upload
|
||||
- workflow
|
||||
workspace:
|
||||
- app/uow
|
||||
events:
|
||||
- app/uow
|
||||
artifactvault:
|
||||
- app/uow
|
||||
- fsutil
|
||||
dataset:
|
||||
- artifactvault
|
||||
- app/uow
|
||||
|
||||
table_owners:
|
||||
document_records:
|
||||
- docgov
|
||||
chat_messages:
|
||||
- ctxmgr
|
||||
chat_turns:
|
||||
- ctxmgr
|
||||
freeform_documents:
|
||||
- freedoc
|
||||
task_runs:
|
||||
- taskrun
|
||||
task_run_manifests:
|
||||
- taskrun
|
||||
document_versions:
|
||||
- docrevision
|
||||
document_snapshots:
|
||||
- docrevision
|
||||
document_change_events:
|
||||
- docrevision
|
||||
event_envelopes:
|
||||
- events
|
||||
event_deliveries:
|
||||
- events
|
||||
event_dead_letters:
|
||||
- events
|
||||
event_inventory_decisions:
|
||||
- events
|
||||
event_repair_audit:
|
||||
- events
|
||||
event_replay_plans:
|
||||
- events
|
||||
event_service_principals:
|
||||
- events
|
||||
event_delivery_attempts:
|
||||
- events
|
||||
event_consumer_modes:
|
||||
- events
|
||||
event_consumer_checkpoints:
|
||||
- events
|
||||
event_reconciliations:
|
||||
- events
|
||||
event_projection_outcomes:
|
||||
- app/docproject
|
||||
notifications:
|
||||
- notification
|
||||
stage_advance_requests:
|
||||
- notification
|
||||
final_artifacts:
|
||||
- artifactvault
|
||||
artifact_payload_staging:
|
||||
- artifactvault
|
||||
artifact_blob_references:
|
||||
- artifactvault
|
||||
artifact_publication_attempts:
|
||||
- artifactvault
|
||||
artifact_deletion_ledger:
|
||||
- artifactvault
|
||||
artifact_quarantine:
|
||||
- artifactvault
|
||||
artifact_backfill_exclusions:
|
||||
- artifactvault
|
||||
dataset_registry:
|
||||
- dataset
|
||||
dataset_backfill_jobs:
|
||||
- dataset
|
||||
dataset_backfill_checkpoints:
|
||||
- dataset
|
||||
dataset_backfill_queue:
|
||||
- dataset
|
||||
dataset_destroy_requests:
|
||||
- dataset
|
||||
intent_plans:
|
||||
- app/intentflow
|
||||
intent_plan_steps:
|
||||
- app/intentflow
|
||||
intent_plan_decisions:
|
||||
- app/intentflow
|
||||
intent_plan_projections:
|
||||
- app/intentflow
|
||||
intent_plan_shadow:
|
||||
- app/intentflow
|
||||
|
||||
path_owners:
|
||||
output.md:
|
||||
- squad
|
||||
- workspace
|
||||
data/dev:
|
||||
- config
|
||||
- workspace
|
||||
- artifactvault
|
||||
workspaces/:
|
||||
- squad
|
||||
- workspace
|
||||
|
||||
event_producers:
|
||||
outbox.notify:
|
||||
- docrevision
|
||||
- app/docflow
|
||||
document.agent_candidate_ready:
|
||||
- docrevision
|
||||
- app/docflow
|
||||
- events
|
||||
document.agent_version_committed:
|
||||
- docrevision
|
||||
- app/docflow
|
||||
- events
|
||||
- app/docproject
|
||||
document.downstream_impact_detected:
|
||||
- docrevision
|
||||
- app/docflow
|
||||
- events
|
||||
document.change_report_degraded:
|
||||
- docrevision
|
||||
- app/docflow
|
||||
- events
|
||||
document.approved:
|
||||
- app/docflow
|
||||
- events
|
||||
- app/docadvance
|
||||
taskrun.completed:
|
||||
- taskrun
|
||||
taskrun.cancelled:
|
||||
- taskrun
|
||||
fav.artifact_staged:
|
||||
- app/docflow
|
||||
intent.plan.awaiting_input:
|
||||
- app/intentflow
|
||||
- events
|
||||
intent.plan.step_changed:
|
||||
- app/intentflow
|
||||
- events
|
||||
intent.plan.completed:
|
||||
- app/intentflow
|
||||
- events
|
||||
|
||||
event_consumers:
|
||||
outbox.notify:
|
||||
- app/docnotify
|
||||
- notification
|
||||
document.agent_candidate_ready:
|
||||
- notify
|
||||
document.agent_version_committed:
|
||||
- projection
|
||||
- notify
|
||||
document.downstream_impact_detected:
|
||||
- notify
|
||||
document.change_report_degraded:
|
||||
- notify
|
||||
document.approved:
|
||||
- workflow_advance
|
||||
- notify
|
||||
taskrun.completed:
|
||||
- notify
|
||||
taskrun.cancelled:
|
||||
- notify
|
||||
fav.artifact_staged:
|
||||
- fav
|
||||
intent.plan.awaiting_input:
|
||||
- projection
|
||||
- notify
|
||||
intent.plan.step_changed:
|
||||
- projection
|
||||
- notify
|
||||
intent.plan.completed:
|
||||
- projection
|
||||
- notify
|
||||
|
||||
unwrap_owners:
|
||||
- docgov
|
||||
- docrevision
|
||||
- taskrun
|
||||
- freedoc
|
||||
- events
|
||||
- artifactvault
|
||||
- ctxmgr
|
||||
- app/intentflow
|
||||
|
||||
exceptions:
|
||||
- kind: sql_write
|
||||
package: docduty
|
||||
file: internal/docduty/revoke.go
|
||||
symbol: document_records
|
||||
owner: docduty
|
||||
reason: duty slot revoke still writes reviewer/approver columns directly; fold into docgov repository during U3
|
||||
milestone: U3
|
||||
expires: "2026-09-28"
|
||||
- kind: sql_write
|
||||
package: docduty
|
||||
file: internal/docduty/store.go
|
||||
symbol: document_records
|
||||
owner: docduty
|
||||
reason: heal/store updates duty columns on document_records; move behind docgov repository in U3
|
||||
milestone: U3
|
||||
expires: "2026-09-28"
|
||||
- kind: sql_write
|
||||
package: docrevision
|
||||
file: internal/docrevision/pg_store.go
|
||||
symbol: document_records
|
||||
owner: docrevision
|
||||
reason: projectRootPointersTX updates controlled root pointers; U3 must keep this inside the shared UnitOfWork
|
||||
milestone: U3
|
||||
expires: "2026-09-28"
|
||||
- kind: sql_write
|
||||
package: docrevision
|
||||
file: internal/docrevision/pg_store.go
|
||||
symbol: freeform_documents
|
||||
owner: docrevision
|
||||
reason: projectRootPointersTX also projects freeform heads; keep atomic in U3 then hand write ownership back
|
||||
milestone: U3
|
||||
expires: "2026-09-28"
|
||||
- kind: sql_write
|
||||
package: projectinstance
|
||||
file: internal/projectinstance/store.go
|
||||
symbol: task_runs
|
||||
owner: projectinstance
|
||||
reason: workflow terminate cancels task_runs; U8 owns run finalization in the same UoW
|
||||
milestone: U8
|
||||
expires: "2026-10-26"
|
||||
- kind: path
|
||||
package: agent
|
||||
file: internal/agent/cursor.go
|
||||
symbol: output.md
|
||||
owner: agent
|
||||
reason: runner still names the deliverable file; U5 replaces this with WorkspaceRef
|
||||
milestone: U5
|
||||
expires: "2026-10-12"
|
||||
- kind: path
|
||||
package: agent
|
||||
file: internal/agent/piagent.go
|
||||
symbol: output.md
|
||||
owner: agent
|
||||
reason: PI runner contract still uses output.md; U5 capability must hide the literal
|
||||
milestone: U5
|
||||
expires: "2026-10-12"
|
||||
- kind: path
|
||||
package: bizdev
|
||||
file: internal/bizdev/service.go
|
||||
symbol: data/dev
|
||||
owner: bizdev
|
||||
reason: default data-root example string; U5 resolver owns environment roots
|
||||
milestone: U5
|
||||
expires: "2026-10-12"
|
||||
- kind: path
|
||||
package: bizdev
|
||||
file: internal/bizdev/service.go
|
||||
symbol: output.md
|
||||
owner: bizdev
|
||||
reason: orchestration still joins workspace output.md; U5 removes Root/OutputDir
|
||||
milestone: U5
|
||||
expires: "2026-10-12"
|
||||
- kind: path
|
||||
package: coordinator
|
||||
file: internal/coordinator/context.go
|
||||
symbol: output.md
|
||||
owner: coordinator
|
||||
reason: coordinator reads projection path; U4/U5 must go through workspace capability
|
||||
milestone: U5
|
||||
expires: "2026-10-12"
|
||||
- kind: path
|
||||
package: coordinator
|
||||
file: internal/coordinator/dialogue_llm.go
|
||||
symbol: data/dev
|
||||
owner: coordinator
|
||||
reason: prompt example embeds data/dev; U5 must not leak runtime roots
|
||||
milestone: U5
|
||||
expires: "2026-10-12"
|
||||
- kind: path
|
||||
package: coordinator
|
||||
file: internal/coordinator/document_summary.go
|
||||
symbol: data/dev
|
||||
owner: coordinator
|
||||
reason: summary prompt embeds data/dev; U5 must not leak runtime roots
|
||||
milestone: U5
|
||||
expires: "2026-10-12"
|
||||
- kind: path
|
||||
package: coordinator
|
||||
file: internal/coordinator/engine.go
|
||||
symbol: output.md
|
||||
owner: coordinator
|
||||
reason: engine joins deliverable path; U5 WorkspaceRef
|
||||
milestone: U5
|
||||
expires: "2026-10-12"
|
||||
- kind: path
|
||||
package: docgov
|
||||
file: internal/docgov/lease.go
|
||||
symbol: output.md
|
||||
owner: docgov
|
||||
reason: SaveDocumentContent still writes projection files; U5 capability + U4 ledger-first read
|
||||
milestone: U5
|
||||
expires: "2026-10-12"
|
||||
- kind: path
|
||||
package: docgov
|
||||
file: internal/docgov/project_docs.go
|
||||
symbol: output.md
|
||||
owner: docgov
|
||||
reason: project doc helpers still construct output.md; U5
|
||||
milestone: U5
|
||||
expires: "2026-10-12"
|
||||
- kind: path
|
||||
package: docrevision
|
||||
file: internal/docrevision/projection.go
|
||||
symbol: output.md
|
||||
owner: docrevision
|
||||
reason: InspectProjection reads workspace file; U4 treats this as optional cache only
|
||||
milestone: U4
|
||||
expires: "2026-09-28"
|
||||
- kind: path
|
||||
package: docrevision
|
||||
file: internal/docrevision/reconcile.go
|
||||
symbol: output.md
|
||||
owner: docrevision
|
||||
reason: reconcile still repairs projection files; U5
|
||||
milestone: U5
|
||||
expires: "2026-10-12"
|
||||
- kind: path
|
||||
package: server
|
||||
file: internal/server/document_revision_access.go
|
||||
symbol: output.md
|
||||
owner: server
|
||||
reason: handler still reads workspace files; U4 must use docquery ledger
|
||||
milestone: U4
|
||||
expires: "2026-09-28"
|
||||
- kind: path
|
||||
package: server
|
||||
file: internal/server/document_revision_handlers.go
|
||||
symbol: output.md
|
||||
owner: server
|
||||
reason: handler error text mentions output.md; U4/U5 remove path leakage
|
||||
milestone: U4
|
||||
expires: "2026-09-28"
|
||||
- kind: path
|
||||
package: server
|
||||
file: internal/server/server.go
|
||||
symbol: workspaces/
|
||||
owner: server
|
||||
reason: server still concatenates workspaces/ roots; U5
|
||||
milestone: U5
|
||||
expires: "2026-10-12"
|
||||
- kind: path
|
||||
package: storage
|
||||
file: internal/storage/cas.go
|
||||
symbol: data/dev
|
||||
owner: storage
|
||||
reason: CAS default example path; U5 resolver
|
||||
milestone: U5
|
||||
expires: "2026-10-12"
|
||||
|
||||
baseline_counts:
|
||||
import: 0
|
||||
sql_write: 5
|
||||
path: 16
|
||||
event: 0
|
||||
|
||||
# U12: kinds already at zero production findings fail --mode block.
|
||||
# sql_write/path keep dated exceptions until their owner milestones clear them.
|
||||
block_kinds:
|
||||
- import
|
||||
- event
|
||||
@@ -0,0 +1,21 @@
|
||||
# U9 migration corpus 与八条轨道
|
||||
|
||||
八条 release 轨道(clean / oldest-supported / previous / hazard / import / reload / rollback / artifact recovery)的可执行夹具在:
|
||||
|
||||
- `internal/dataset/testdata/registry.json`(6–10 个批准 dataset:pinned / demo / regression / migration_baseline / ephemeral;quarantine 类不计入导入分母)
|
||||
- `go test ./internal/dataset -run TestEightTracksPass`
|
||||
|
||||
## 轨道含义
|
||||
|
||||
| 轨道 | 验证 |
|
||||
|------|------|
|
||||
| clean | 空源 backfill 分母为 0 |
|
||||
| oldest-supported | schema 28 可升级回填 |
|
||||
| previous | schema 37(U8 节点)可回填 |
|
||||
| hazard | 缺 snapshot、fork、高 ID、legacy-v0 → quarantine |
|
||||
| import | 批准 registry 6–10 条 |
|
||||
| reload | 重放不重复 artifact |
|
||||
| rollback | 共享 DSN / 缺备份阻止 destroy;scratch 可过门禁 |
|
||||
| artifact recovery | FAV recover-as-collection 只写 scratch |
|
||||
|
||||
回填枚举 SQL 只读 `document_snapshots` / `document_change_events` / `document_records` / `chat_turns`,禁止 `work_dir` 与 `workspaces/`。
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
- OS: Linux;Go 模块测试 + `cd web && npm test`
|
||||
- PG 集成:`TEST_DATABASE_URL` 可用时执行 `chat_history_refresh_pg_test.go`
|
||||
- 真实 PI E2E:待 dev `:8080` + pi-agent 人工补录
|
||||
- 真实 PI E2E:dev `:8080` + 运行中 `pi-agent`(U9 镜像);脚本 `assets/2026-09-15-chat-history-refresh-live/chat-refresh-live.py`
|
||||
|
||||
## 四、 预期结果 (Expected Results)
|
||||
|
||||
@@ -59,11 +59,12 @@
|
||||
- **Actual Output**: 192 tests PASS
|
||||
- **Evaluation**: PASS
|
||||
|
||||
### 用例 F:真实 PI 刷新 E2E
|
||||
### 用例 F:真实 PI 闲聊刷新 E2E
|
||||
|
||||
- **Input**: dev 环境文档生成 → 浏览器刷新
|
||||
- **Actual Output**: 本轮未执行(需运行中 pi-agent 容器)
|
||||
- **Evaluation**: DEFERRED — 合入 dev 后占集成槽位补录
|
||||
- **Input**: 运行中 dev `:8080` + `pi-agent`;新建项目 6252 / `sess-p6252-u10`;`POST /api/v1/chat` 后 `GET /api/v1/chat/messages/window` 与 `GET /api/v1/chat/categories`;guest 读同一 session。产物:`.doc/test-reports/assets/2026-09-15-chat-history-refresh-live/live.json`
|
||||
- **Actual Output**: `agent_backend=pi-agent`,schema 38;闲聊 200(3481ms);window_msgs=2 且 category_total=2;guest 403 `SESSION_FORBIDDEN`。`core_overall=PASS`。文档任务 `PUT workflow-plan` 400,未跑 intake。
|
||||
- **Evaluation**: 闲聊刷新同集与跨用户负例 **PASS**;激活后文档任务刷新仍开放
|
||||
- **Duration**: 3704ms(core)
|
||||
|
||||
## 六、 自动化测试套件汇总 (Test Suite Execution)
|
||||
|
||||
@@ -74,5 +75,5 @@ cd web && npm test → PASS (192)
|
||||
|
||||
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
|
||||
|
||||
- 代码与 PG 集成测试达到合并标准;真实 PI 刷新 E2E 需在 dev 容器冒烟后补证据。
|
||||
- 合入后执行 `./scripts/env-service.sh dev restart` 并对 project 143 样本验证 backfill 效果。
|
||||
- 自动化、PG 与真实 PI 闲聊刷新同集已补证据;guest 403 成立。
|
||||
- 发布门禁中的「激活后文档任务 + 重登/重启」仍未勾选。项目 143 只读,未用作活验样本。
|
||||
|
||||
@@ -59,9 +59,18 @@
|
||||
|
||||
### 用例 E:真实 PI + 浏览器刷新/双标签页
|
||||
|
||||
- **Input**: 真实 PI 只读总结已执行;浏览器刷新/双标签页待执行
|
||||
- **Actual Output**: 只读总结见用例 H;刷新和 busy 可见性尚无浏览器证据
|
||||
- **Evaluation**: PARTIAL
|
||||
- **Input**: 新建项目 `INTENT双标签-061002`(id **6275**,**禁止 143**)/ `sess-p6275-u10`;Tab A `POST /api/v1/tasks/runs`「请开始编写用户初始需求表」真实 `pi-agent`;租约出现后 Tab B 再 POST;浏览器双标签打开同一项目
|
||||
- **Actual Output**:
|
||||
- health/ready schema **38**、`agent_backend=pi-agent`
|
||||
- Tab A `202` `run_1789452602295343365` status=running;2ms 内 `lease_holder_type=squad`
|
||||
- Tab B HTTP **409** `DOC_BUSY`,响应无 `run_id`;PG `task_runs` 仅 1 行
|
||||
- 聊天窗 assistant `error_info.code=DOC_BUSY` 且 `actions=[]`,另有 `task_status=running` 占位;再次 GET window 同集
|
||||
- 真实 PI **completed**(约 280s,质量 100);租约在终态探测后 **1ms** 已空(无需客户端刷新)
|
||||
- 终态后再 GET window:DOC_BUSY 卡仍 `actions=[]`,无重试动作
|
||||
- 浏览器(Docker Playwright,宿主机缺 libatk):双标签可见「本文档正由【项目助手】编辑/生成中」、聊天 `DOC_BUSY`、发送按钮 disabled、刷新后仍无重试。截图 `assets/2026-09-15-conversation-intent-dual-tab/screenshots/`
|
||||
- **Evaluation**: **PASS**
|
||||
- **性能与耗时**: API 活验 281s;Docker UI 4.4s。产物:`assets/2026-09-15-conversation-intent-dual-tab/live.json`、`playwright-docker.json`
|
||||
- 诊断污染:`sess-p143-u9` **未**写入、未删除历史探针
|
||||
|
||||
### 用例 F:dev 集成冒烟
|
||||
|
||||
@@ -106,4 +115,4 @@ git diff --check PASS
|
||||
|
||||
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
|
||||
|
||||
代码级、构建门禁及真实 PI 只读总结已通过;原句不会创建任务或租约。最终 dev 镜像重建后 `/ready` 为 HTTP 200;只读复核确认用户原会话最大消息 ID 仍为 567、隔离 fixture 会话/消息/run 均为 0、project 143 无有效文档租约。尚不能标记发布完成:浏览器刷新恢复、双标签页租约可见性与并发写“不新增第二 run”仍需补录。真实会话中的诊断消息与误启动产物只记录证据,不在未获确认时删除或回滚。
|
||||
代码级、构建门禁、真实 PI 只读总结与 **新建项目双标签 busy** 已通过。项目 **6275** / `run_1789452602295343365`:并发写 409 `DOC_BUSY` 不新增第二 run;刷新后 `actions=[]`;PI 终态后租约自动解除。浏览器双标签截图见 `assets/2026-09-15-conversation-intent-dual-tab/screenshots/`。真实会话 `sess-p143-u9` 中的诊断消息与误启动产物只记录证据,不在未获确认时删除或回滚。`production_ready` 仍为 no(CI 三工作流 E2E / 前端抽检等其它 blocker)。
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
# 文档可靠性 M2(U5–U7)测试报告
|
||||
|
||||
## 一、 测试背景 (Background)
|
||||
|
||||
M1 活验报告最后一句为 **继续 M2**([2026-09-14-document-reliability-pilot-live-test-report.md](./2026-09-14-document-reliability-pilot-live-test-report.md))。上一份「停止扩面」试点报告保持原句,不改写。本轮只实施并验证 U5 WorkspaceRef、U6 耐久投递、U7 按文件摘取 FAV,并给出能否开工 M3 的停走句。
|
||||
|
||||
## 二、 测试目标 (Test Objectives)
|
||||
|
||||
- 2/4 dispatcher 无双 owner;crash-before/after-side-effect/ack 可恢复。
|
||||
- 乱序 aggregate version 不越过缺号。
|
||||
- 跨项目事件 / 坏 digest / 伪造 producer → quarantine;auth/integrity 立即死信;attempt 12 后死信。
|
||||
- `SKIP LOCKED` 只用于 claim。
|
||||
- 业务终态、staging、outbox 同事务;失败回滚无泄漏。
|
||||
- union-deny;中间态(prompt/tool_trace/scratch)准入率 0。
|
||||
- `FAV_DEGRADED_READ` 默认 false;授权成功之后才允许 degraded read。
|
||||
- Goose 00034–00036 重取号;组合 Up+Down;禁止把 FAV 树的 00034 原样合入。
|
||||
- 占槽后主仓 rebuild;health/ready 为 schema 36,无路径泄漏。
|
||||
|
||||
## 三、 测试方案与环境 (Test Plan & Environment)
|
||||
|
||||
| 项 | 值 |
|
||||
|----|-----|
|
||||
| OS | Linux 7.0.0-31-generic |
|
||||
| Go | 本机 `go test`;容器 `agent-dev-app` |
|
||||
| 合入 | 主仓 `dev` `--no-ff` `refactor/document-reliability-pilot` → `0872d8f` |
|
||||
| 部署 | 主仓 `./scripts/env-service.sh dev rebuild`(禁止 worktree 内 env-service;禁止 `compose restart` 当证据) |
|
||||
| Compose | 项目 `agent-dev`,HTTP `:8080` |
|
||||
| Agent | `agent_backend=pi-agent` |
|
||||
| Schema | **36**(00034 fencing + 00035 envelopes + 00036 FAV) |
|
||||
| `FAV_DEGRADED_READ` | 宿主与容器均 unset / 默认 false |
|
||||
| PostgreSQL | 隔离库 `agent_rel_m2`(`shuimu-system-pg-test:5434`),另建 `agent_rel_m2_goose` 做 Down;测完 `DROP`;禁止 `agent_system_dev/test/main` |
|
||||
| 项目 143 | **只读**;本轮未 terminate,未改 workflow-plan |
|
||||
| 证据 | `.doc/test-reports/assets/2026-09-14-document-reliability-m2/` |
|
||||
|
||||
镜像身份:`app_image=sha256:8ab9f63a05274e08d55322e162f8fec3f5822bd3e14375376df856308329b511`。见 `rebuild-health-ready.txt`。
|
||||
|
||||
## 四、 预期结果 (Expected Results)
|
||||
|
||||
| 栏 | 期望 |
|
||||
|----|------|
|
||||
| Unit | WorkspaceRef 无物理路径;旧 fencing 被拒;事务内禁止文件 I/O;2/4 dispatcher 单 owner;gap 不跳号;中间态准入 0 |
|
||||
| PostgreSQL | 00034–00036 Down 到 33 后再 Up;outbox+staging 同 TX,失败零泄漏 |
|
||||
| 故障注入 | crash-before/after ack 无双副作用;attempt 12 死信 |
|
||||
| 真实 PI | 本轮不重跑编制;rebuild 后 ready 仍为真实 `pi-agent` |
|
||||
| 真实浏览器 | 本轮不重跑 Playwright;web 单测 + production build 必须绿 |
|
||||
| restart/rebuild | health/ready `status=ok`,`schema_version=36`,无路径泄漏,vault 未配置不假绿 |
|
||||
| 跨用户 / 授权 | 授权失败不碰 vault;tombstone union-deny |
|
||||
|
||||
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
|
||||
|
||||
### 5.1 Unit / stub
|
||||
|
||||
- **测试输入**: `unset TEST_DATABASE_URL; go test -short ./...`;目标包 `go test -race -short`;`./scripts/arch-check.sh --mode warn`
|
||||
- **实际输出**: 全仓 short 包 `ok`。目标包 race:`TestTwoAndFourWorkersNoDoubleOwner`、`TestCrashBeforeAfterAck`、`TestGapDoesNotSkipVersion`、`TestQuarantineBadDigestForgedProducerCrossProject`、`TestAttempt12GoesDeadLetter`、`TestStaleFencingRejected`、`TestEvaluateEligibility_IntermediateAdmissionZero`、`TestTombstoneUnionDeny`、`TestFavDegradedReadDefaultOff` 均为 PASS。`arch-check warn: production gate passed`。`--mode block` 仍会因既有 path/sql_write 例外基线失败(U1 设计;本里程碑新增 import 已清零)。
|
||||
- **评价判定**: **PASS**
|
||||
- **性能与耗时**: 全仓 short 约 13s;目标包 race 约 3–4s。日志:`go-test-short.txt`、`go-test-m2-packages-race.txt`、`arch-check-warn.txt`
|
||||
|
||||
### 5.2 PostgreSQL 事务与并发
|
||||
|
||||
- **测试输入**: 隔离库 `TEST_DATABASE_URL` → `TestGooseM2_00034to00036_DownThenUp`、`TestOutboxAndStagingSameTxRollback`
|
||||
- **实际输出**:
|
||||
|
||||
```
|
||||
--- PASS: TestGooseM2_00034to00036_DownThenUp (0.36s)
|
||||
--- PASS: TestOutboxAndStagingSameTxRollback (0.01s)
|
||||
```
|
||||
|
||||
00034–00036 Up 到 36,Down 到 33 后 `event_envelopes`/`final_artifacts`/`lease_fencing_token` 消失,再 Up 回 36。同 UoW 写入 envelope + FAV staging 后故意 `boom`,回滚后两表计数为 0。测完 `DROP DATABASE agent_rel_m2`(goose 子库随测试 Cleanup DROP)。
|
||||
- **评价判定**: **PASS**
|
||||
- **性能与耗时**: goose 组合约 0.36s。日志:`goose-00034-36-down-up.txt`
|
||||
|
||||
### 5.3 故障注入
|
||||
|
||||
- **测试输入**: 内存 dispatcher crash/lease 过期/重放;attempt 12;目标包 `-race`
|
||||
- **实际输出**: 过期 worker ack 为 `ErrStaleFencing`;后到 worker 副作用恰好 1;inbox 去重。12 次瞬时失败后 status=`dead`。
|
||||
- **评价判定**: **PASS**
|
||||
- **性能与耗时**: 亚秒。日志:`go-test-m2-packages-race.txt`
|
||||
|
||||
### 5.4 真实 PI
|
||||
|
||||
- **测试输入**: 本轮不新编制文档。检查 rebuild 后 `/api/v1/ready` 的 `agent_backend`
|
||||
- **实际输出**: `agent_backend=pi-agent`,不是 stub。编制活验仍以 M1 报告为准。
|
||||
- **评价判定**: **PASS**(继承 M1 活验;本轮验证后端身份与 schema 36 ready)
|
||||
- **性能与耗时**: health/ready 亚秒
|
||||
|
||||
### 5.5 真实浏览器
|
||||
|
||||
- **测试输入**: 本轮未重跑 Playwright(项目 143 只读约束仍在)。`web`:`npm test` + `npm run build`
|
||||
- **实际输出**: tsx **365 passed / 0 fail**;vitest **30 passed**;production build `✓ built in 8.07s`(容器 rebuild 内 web build 同样成功)。
|
||||
- **评价判定**: **PASS**(页面回归以 M1 活验为准;本轮前端门禁绿)
|
||||
- **性能与耗时**: 单测约 1.4s + vitest 0.5s;本地 build 约 8s。日志:`web-unit.txt`、`web-build.txt`
|
||||
|
||||
### 5.6 restart / rebuild
|
||||
|
||||
- **测试输入**: 占集成槽后主仓 `./scripts/env-service.sh dev rebuild`;`curl -sf http://127.0.0.1:8080/api/v1/health` 与 `/api/v1/ready`
|
||||
- **实际输出**: 两者 HTTP 200,body 均为
|
||||
|
||||
```
|
||||
{"status":"ok","env":"dev","agent_backend":"pi-agent","version":"v1.0","shared_kb_port":5432,"database_ready":true,"schema_version":36,"schema_ready":true,"task_store_ready":true}
|
||||
```
|
||||
|
||||
无文件系统路径字段。vault 未配置时 ready 仍按 DB/schema/task_store 判定。
|
||||
- **评价判定**: **PASS**
|
||||
- **性能与耗时**: rebuild 约 27s。日志:`rebuild-health-ready.txt`、`health.json`、`ready.json`
|
||||
|
||||
### 5.7 跨用户 / 授权负例
|
||||
|
||||
- **测试输入**: `TestFavDegradedReadOnlyAfterAuthorize`;`TestTombstoneUnionDeny`;跨项目 envelope Apply
|
||||
- **实际输出**: 授权失败时 vault `calls=0`;tombstone 读为 `ErrUnionDeny`;跨项目 delivery 为 `quarantine`
|
||||
- **评价判定**: **PASS**
|
||||
- **性能与耗时**: 亚秒
|
||||
|
||||
## 六、 自动化测试套件汇总 (Test Suite Execution)
|
||||
|
||||
| 命令 | 结果 |
|
||||
|------|------|
|
||||
| `go vet ./...` | PASS |
|
||||
| `go test -short ./...` | PASS |
|
||||
| 隔离库 goose Down/Up + 同事务回滚 | PASS,随后 `DROP DATABASE` |
|
||||
| 目标包 `-race` | PASS |
|
||||
| `arch-check --mode warn` | PASS |
|
||||
| `arch-check --mode block` | 仍因既有例外基线失败(预期;非本里程碑新增违规) |
|
||||
| web `npm test` | 365 + 30 PASS |
|
||||
| web production build | PASS |
|
||||
| 占槽 rebuild + health/ready | PASS,`schema_version=36` |
|
||||
|
||||
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
|
||||
|
||||
U5–U7 的停走项在本轮全部观测为 PASS:dispatcher 无双 owner,崩溃与过期 fencing 可恢复,缺号不跳过,坏 digest/伪造 producer/跨项目进入 quarantine,FAV 中间态准入为 0,union-deny 生效,outbox 与 staging 同事务回滚,Goose 00034–00036 可 Down。`document.agent_version_committed` 已从 `OnOutbox` 正确性路径摘除,改由 `events.EventSink` 在 UoW 内追加。剩余 agent/coordinator 的 `output.md` 字面量仍是 U1 例外基线,属 M3 Workspace 清理范围,不构成本轮扩面失败。未把 `feature/final-artifact-vault` 整支 merge,未启用 `FAV_DEGRADED_READ`。
|
||||
|
||||
继续 M3
|
||||
@@ -0,0 +1,137 @@
|
||||
# 文档可靠性试点 M1 活验签字测试报告
|
||||
|
||||
## 一、 测试背景 (Background)
|
||||
|
||||
上一份 [M1 试点报告](./2026-09-14-document-reliability-pilot-test-report.md) 在 Unit/隔离库通过后,因未占槽 rebuild、无真实 PI/浏览器/4 会话而把最后一句写成 **停止扩面**。本轮不改写那份结论句;只补活验签字,决定能否开工 U5–U7。
|
||||
|
||||
## 二、 测试目标 (Test Objectives)
|
||||
|
||||
- A1:占集成槽,本地 `dev` `--no-ff` 合入试点分支,`env-service.sh dev rebuild`,health+ready 来自本分支镜像。
|
||||
- A2:项目 143 只读打开/刷新/重登;新建项目打开/刷新/重登;`GET .../content` 为 200 且带 `consistency`;禁止把 missing 当 404。
|
||||
- A3:真实 `pi-agent` + MiniMax 编制一条受控文档,刷新不丢正文。禁止 stub 当终态。
|
||||
- A4:隔离库两个 pgx pool + 4 会话同 ETag 一赢,同 key+digest 跨 pool 重放。测完 `DROP DATABASE`。
|
||||
- A5:分栏签字;最后一句只能是「继续 M2」或「停止扩面」。
|
||||
|
||||
## 三、 测试方案与环境 (Test Plan & Environment)
|
||||
|
||||
| 项 | 值 |
|
||||
|----|-----|
|
||||
| OS | Linux 7.0.0-31-generic |
|
||||
| Go | 本机 `go test`;容器 `agent-dev-app` |
|
||||
| 合入 | 主仓 `dev` `--no-ff` `refactor/document-reliability-pilot` → `cb8eaca` |
|
||||
| 部署 | 主仓 `./scripts/env-service.sh dev rebuild`(禁止 `compose restart` 当证据) |
|
||||
| Compose | 项目 `agent-dev`,HTTP `:8080` |
|
||||
| Agent | 真实 `pi-agent`(`AGENT_BACKEND=pi-agent`),模型 `MiniMax-M2.7-highspeed`(云端 API,非 stub) |
|
||||
| Schema | **33** |
|
||||
| `FAV_DEGRADED_READ` | unset / 默认 false |
|
||||
| 浏览器 | `mcr.microsoft.com/playwright:v1.63.0-noble`,`--network host --ipc host` |
|
||||
| PostgreSQL | 隔离库 `agent_rel_itest`(`shuimu-system-pg-test:5434`),测完 `DROP`;禁止 `agent_system_dev/test/main` |
|
||||
| 项目 143 | **只读**;未 terminate,未 `PUT /143/workflow-plan` |
|
||||
| 证据 | `.doc/test-reports/assets/2026-09-14-document-reliability-pilot-live/` |
|
||||
|
||||
镜像身份(rebuild 后):`app_image=sha256:251fa99d5de47d452b7f099304aa34b1e2aacf1b4e9d2d23d1cb4b850084910e`;随后把 `pi-agent` force-recreate 到 rebuild 所打的 `sha256:21fc9b64066c33e94d8db83695b4ff64ea5e49f6d65661f8ccab11ead083042d`。见 `rebuild-health-ready.txt`。
|
||||
|
||||
## 四、 预期结果 (Expected Results)
|
||||
|
||||
| 栏 | 期望 |
|
||||
|----|------|
|
||||
| Unit / stub | `go test -short` 全绿;hydrate 把 `missing` 当正文 |
|
||||
| PostgreSQL | 双 pool 同 ETag 一赢;同 key+digest 跨 pool 重放;4 会话同 ETag 一赢 |
|
||||
| 故障注入 | 与上一份隔离库 U2 一致,本轮 `-race` 再跑目标包 |
|
||||
| 真实 PI | 新建项目激活后编制,账本 head 可读 |
|
||||
| 真实浏览器 | 143 与新项目刷新/重登 200 + markdown;页面无「加载失败」;无 PROJECTION 409 |
|
||||
| restart/rebuild | health/ready `status=ok`,`agent_backend=pi-agent`,`schema_version=33`;ready 不因 vault 未配置假绿,响应无路径泄漏 |
|
||||
| 跨用户 | 匿名 401;非成员/跨项目/错误 stage-duty 同一 404 `DOCUMENT_NOT_FOUND` |
|
||||
|
||||
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
|
||||
|
||||
### 5.1 Unit / stub
|
||||
|
||||
- **测试输入**: `unset TEST_DATABASE_URL; go test -short ./...`;`npx tsx --test src/lib/controlledDocHydrate.test.ts`;`./scripts/arch-check.sh --mode warn`
|
||||
- **实际输出**: 全仓 short 包 `ok`;hydrate **17 passed**;`arch-check warn: production gate passed`
|
||||
- **评价判定**: **PASS**
|
||||
- **性能与耗时**: `internal/server` 约 9.6s。日志:`go-test-short.txt`、`hydrate-unit.txt`、`arch-check-warn.txt`
|
||||
|
||||
### 5.2 PostgreSQL 事务与并发
|
||||
|
||||
- **测试输入**: 隔离库 `TEST_DATABASE_URL` → `./internal/docrevision -run 'TestDocumentCommitConcurrencyPG|TestDocumentCommitTwoPoolsAndFourSessionsPG'`
|
||||
- **实际输出**:
|
||||
|
||||
```
|
||||
--- PASS: TestDocumentCommitConcurrencyPG (0.03s)
|
||||
--- PASS: TestDocumentCommitTwoPoolsAndFourSessionsPG (0.03s)
|
||||
```
|
||||
|
||||
两个独立 `pgxpool` 打同一 ETag 仅一赢;赢家 key+digest 跨 pool 重放 head 一致;随后 4 个会话同 ETag 仅一赢。测完 `DROP DATABASE agent_rel_itest`。
|
||||
- **评价判定**: **PASS**(不是 4 个 OS 进程,是计划要求的双 pool 模拟两进程 + 4 会话;未使用进程内全局 mutex)
|
||||
- **性能与耗时**: 62ms。日志:`go-test-pg-two-pool.txt`
|
||||
|
||||
### 5.3 故障注入
|
||||
|
||||
- **测试输入**: `go test -race ./internal/app/uow ./internal/app/docflow ./internal/docquery`(同一隔离库,DROP 前)
|
||||
- **实际输出**: 三包 `ok`(含 cached)
|
||||
- **评价判定**: **PASS**
|
||||
- **性能与耗时**: 亚秒到约 1.8s
|
||||
|
||||
### 5.4 真实 PI
|
||||
|
||||
- **测试输入**: Playwright 新建项目 → 未激活编制被 202 `blocked_pending_governance` → 配置并激活 → 发送「请基于本项目编制首轮《用户需求》摸底文档…」→ 等待小队终态 → 打开 `doc_proj*` intake
|
||||
- **实际输出**: 编制用例 **4.2min PASS**。`GET /api/v1/docgov/documents/{id}/content` **200** 且 `markdown` 非空;刷新与重登正文相同。截图 `07-new-doc.png` / `08-new-doc-reload.png` / `09-new-doc-relogin.png`
|
||||
- **评价判定**: **PASS**(真实 `pi-agent`,非 stub)
|
||||
- **性能与耗时**: 编制+打开约 4.2min
|
||||
|
||||
### 5.5 真实浏览器
|
||||
|
||||
- **测试输入**: `RUN_UI_ACCEPTANCE=1 BASE_URL=http://127.0.0.1:8080`;`web/e2e/controlled-document-reload.spec.ts`(官方 Playwright 镜像)
|
||||
- **实际输出**:
|
||||
|
||||
```
|
||||
✓ project 143 content is 200 with consistency; anonymous is 401; unknown is 404 (4.6s)
|
||||
✓ non-member GET of project 143 is the same 404 as unknown (7.4s)
|
||||
✓ new project PI compile then reload keeps ledger markdown (4.2m)
|
||||
✓ cross-project and wrong-stage GET stay DOCUMENT_NOT_FOUND (3.8s)
|
||||
4 passed (4.5m)
|
||||
```
|
||||
|
||||
143 打开/刷新/重登均为 200 + markdown + typed `consistency`,无 `PROJECTION` 409,页面无「加载失败」。未对 `/143/` 发 `PUT workflow-plan`,未 terminate。
|
||||
- **评价判定**: **PASS**
|
||||
- **性能与耗时**: 整套 4.5min。日志:`playwright-controlled-reload.txt`;截图 `screenshots/01`–`10`
|
||||
|
||||
### 5.6 restart / rebuild
|
||||
|
||||
- **测试输入**: 占槽后 `./scripts/env-service.sh dev rebuild`;`curl -sf http://127.0.0.1:8080/api/v1/health` 与 `/api/v1/ready`
|
||||
- **实际输出**: 两者 HTTP 200,body 均为
|
||||
|
||||
```
|
||||
{"status":"ok","env":"dev","agent_backend":"pi-agent","version":"v1.0","shared_kb_port":5432,"database_ready":true,"schema_version":33,"schema_ready":true,"task_store_ready":true}
|
||||
```
|
||||
|
||||
无文件系统路径字段。vault 未配置时 ready 仍按 DB/schema/task_store 判定,不是假绿。
|
||||
- **评价判定**: **PASS**
|
||||
- **性能与耗时**: rebuild 约 79s。日志:`rebuild-health-ready.txt`、`health.json`、`ready.json`
|
||||
|
||||
### 5.7 跨用户负例
|
||||
|
||||
- **测试输入**: 匿名 GET 143;局外人 D GET 143 与新项目文档;审核人 B GET 143 与伪造 `_design_control` stage
|
||||
- **实际输出**: 匿名 **401**;其余均为 **404** `DOCUMENT_NOT_FOUND`,不泄露存在性
|
||||
- **评价判定**: **PASS**
|
||||
- **性能与耗时**: 3.8s。截图 `10-fail-closed.png`
|
||||
|
||||
## 六、 自动化测试套件汇总 (Test Suite Execution)
|
||||
|
||||
| 命令 | 结果 |
|
||||
|------|------|
|
||||
| `go vet ./...` | PASS(合入后、rebuild 前) |
|
||||
| `go test -short ./...` | PASS |
|
||||
| 隔离库双 pool / 4 会话 | PASS,随后 `DROP DATABASE` |
|
||||
| 目标包 `-race` | PASS |
|
||||
| `arch-check --mode warn` | PASS |
|
||||
| hydrate 单测 | 17/17 PASS |
|
||||
| Playwright 活验(官方镜像) | **4 passed** |
|
||||
| 宿主 `npx playwright` | 因缺 `libatk-1.0.so.0` 无法启动;改走已验证的 `mcr.microsoft.com/playwright:v1.63.0-noble` |
|
||||
|
||||
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
|
||||
|
||||
活验补齐了上一份报告缺的 rebuild、真实 PI、真实浏览器、双 pool/4 会话与 HTTP 跨用户负例。hazard 真页面 404/409/projection-missing 本轮观测为 0;授权未靠放宽;4 会话赢家来自数据库锁而非进程内 mutex。M1 签字通过,允许按计划实施 U5–U7。上一份「停止扩面」报告保持原句,不改写。
|
||||
|
||||
继续 M2
|
||||
@@ -0,0 +1,132 @@
|
||||
# 文档可靠性纵向试点(M0–M1 / U1–U4)测试报告
|
||||
|
||||
## 一、 测试背景 (Background)
|
||||
|
||||
受控文档写路径曾把账本、root pointer 与通知拆到提交后回调;读路径在 ledger 已存在时仍被 `InspectProjection` 绑架成 409。刷新、重登或 projection 缺失会被前端当成 404 再 hydrate。本轮只批准 M0–M1(U1–U4):门禁纠偏、UnitOfWork、文档命令同事务、授权后账本读。明确不授权 FAV 降级读、拆 chat/squad、占槽 rebuild。
|
||||
|
||||
## 二、 测试目标 (Test Objectives)
|
||||
|
||||
- U1:四类生产规则可重放;新违规 block;Goose/`*_test.go` 不记生产写者债。
|
||||
- U2:跨属主同事务;第二属主/staging/commit 失败零残留;仅 `40001`/`40P01` 整事务重试。
|
||||
- U3:人工编辑 / agent commit / approve / reject 锁后重鉴权;同 ETag 一赢一输。
|
||||
- U4:projection missing/drift/empty 仍返回账本正文 + typed `consistency`;GET 零写入。
|
||||
- 分栏必须各自签字。未占集成槽不得把 `:8080` 旧镜像或 `docker compose restart` 写成 rebuild 证据。
|
||||
|
||||
## 三、 测试方案与环境 (Test Plan & Environment)
|
||||
|
||||
| 项 | 值 |
|
||||
|----|-----|
|
||||
| OS | Linux 7.0.0-31-generic |
|
||||
| Go | 1.27.1 |
|
||||
| 分支 / worktree | `refactor/document-reliability-pilot` / `.worktrees/refactor-document-reliability-pilot` |
|
||||
| 实现基线 | `dev@a8f9451` → `c754f77`(另含本报告前的 `fix(docflow)` 竞态修复) |
|
||||
| Unit / stub | `go test -short ./...`(**未**设置 `TEST_DATABASE_URL`) |
|
||||
| PostgreSQL | 隔离库 `agent_rel_itest`(`shuimu-system-pg-test:5434`),测完 `DROP DATABASE`;禁止 `agent_system_dev/test/main` |
|
||||
| 目标包 race | `./internal/app/uow ./internal/app/docflow ./internal/docquery ./internal/archtest` |
|
||||
| 前端 | `npx tsx --test src/lib/controlledDocHydrate.test.ts`(17 passed) |
|
||||
| 真实 PI / 浏览器 / rebuild | **未执行**。集成槽 idle;CURRENT 禁止 M1 未签字 rebuild;`:8080` 仍是治理鉴权旧镜像,不能当本分支证据 |
|
||||
| 证据 | `.doc/test-reports/assets/2026-09-14-document-reliability-pilot/` |
|
||||
|
||||
## 四、 预期结果 (Expected Results)
|
||||
|
||||
| 栏 | 期望 |
|
||||
|----|------|
|
||||
| Unit / stub | 全绿;arch-check `--mode warn` 过门;characterization 同 ETag 一赢、approve/reject 唯一终态 |
|
||||
| PG 事务与并发 | U2 故障注入绿;同 ETag 双会话 HumanEdit 仅一赢;head revision=1 |
|
||||
| 故障注入 | 第二属主失败 / staging 失败 / commit 失败零行;`40001` 整事务重跑一条结果 |
|
||||
| 真实 PI | 本分支容器内真实 `pi-agent` 全链路。**本轮不做** |
|
||||
| 真实浏览器 | 项目 143 等价 hazard + 新建项目打开/刷新/重登正文 100%,404/409/projection-missing=0。**本轮不做** |
|
||||
| restart/rebuild | 占槽后 `env-service.sh dev rebuild`。**本轮不做** |
|
||||
| 跨用户负例 | 匿名/未知文档/授权拒绝 → `docquery.ErrClosed`,不泄露存在性 |
|
||||
|
||||
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
|
||||
|
||||
### 5.1 Unit / stub
|
||||
|
||||
- **测试输入**: `go test -short ./...`
|
||||
- **实际输出**: 38 个有测试包 `ok`,无 `FAIL`。摘录:
|
||||
|
||||
```
|
||||
ok chat-agent-system/internal/app/docflow
|
||||
ok chat-agent-system/internal/app/uow
|
||||
ok chat-agent-system/internal/archtest
|
||||
ok chat-agent-system/internal/docquery
|
||||
ok chat-agent-system/internal/docrevision
|
||||
ok chat-agent-system/internal/server 9.796s
|
||||
```
|
||||
|
||||
- **评价判定**: **PASS**
|
||||
- **性能与耗时**: `internal/server` 约 9.8s,其余亚秒到数秒。日志:`assets/2026-09-14-document-reliability-pilot/go-test-short.txt`
|
||||
|
||||
`./scripts/arch-check.sh --mode warn` → `arch-check warn: production gate passed`。`--mode block` 仍会因既有例外基线失败(U1 设计如此)。
|
||||
|
||||
### 5.2 PostgreSQL 事务与并发
|
||||
|
||||
- **测试输入**: 隔离库 `TEST_DATABASE_URL` → `./internal/app/uow`、`./internal/app/docflow`、`./internal/docquery`;`./internal/docrevision -run TestDocumentCommitConcurrencyPG`
|
||||
- **实际输出**:
|
||||
|
||||
```
|
||||
ok chat-agent-system/internal/app/uow 0.065s
|
||||
ok chat-agent-system/internal/app/docflow 0.003s
|
||||
ok chat-agent-system/internal/docquery 0.003s
|
||||
ok chat-agent-system/internal/docrevision 0.024s
|
||||
```
|
||||
|
||||
- **评价判定**: **PASS**(1–2 会话级)。**未**跑 4 个独立 app 进程。
|
||||
- **性能与耗时**: UoW 包 65ms;并发编辑 24ms。日志:`go-test-pg-race.txt`
|
||||
|
||||
### 5.3 故障注入
|
||||
|
||||
- **测试输入**: `internal/app/uow` PG 用例(第二属主失败、staging/outbox 失败、commit 失败、`40001` 重试、version/permission/digest 不重试)
|
||||
- **实际输出**: `ok chat-agent-system/internal/app/uow 0.065s`
|
||||
- **评价判定**: **PASS**
|
||||
- **性能与耗时**: 与 5.2 同一次隔离库运行
|
||||
|
||||
### 5.4 真实 PI
|
||||
|
||||
- **测试输入**: 未切本分支容器,未跑真实 `MiniMax-M2.7-highspeed` 编制链路
|
||||
- **实际输出**: 无
|
||||
- **评价判定**: **FAIL(未测)** — 禁止用 stub 冒充终态
|
||||
- **性能与耗时**: n/a
|
||||
|
||||
### 5.5 真实浏览器
|
||||
|
||||
- **测试输入**: 未对项目 143 / 新建项目做本分支页面打开、刷新、重登
|
||||
- **实际输出**: 仅前端单测 17/17(`hydrate treats projection missing as ledger content, not 404`)
|
||||
- **评价判定**: 单测 **PASS**;真实页面 **FAIL(未测)**
|
||||
- **性能与耗时**: hydrate 套件 149ms
|
||||
|
||||
### 5.6 restart / rebuild
|
||||
|
||||
- **测试输入**: 未占集成槽,未执行 `./scripts/env-service.sh dev rebuild`
|
||||
- **实际输出**: 无。`:8080` 仍为既有 dev 镜像(治理鉴权 G5),不得当作本分支部署证据
|
||||
- **评价判定**: **FAIL(未测)**
|
||||
- **性能与耗时**: n/a
|
||||
|
||||
### 5.7 跨用户负例
|
||||
|
||||
- **测试输入**: `TestGetFailClosed`(匿名、Authorize 拒绝、未知 doc_id);`TestReauthDeniesWrongAuthor`;`TestBatchGetLimitsAndCrossProject`(101 条 / 跨项目)
|
||||
- **实际输出**: 均失败关闭;未知文档与拒绝同一 `ErrClosed`
|
||||
- **评价判定**: 服务端单测 **PASS**。HTTP 跨登录浏览器负例 **未测**
|
||||
- **性能与耗时**: 亚秒
|
||||
|
||||
## 六、 自动化测试套件汇总 (Test Suite Execution)
|
||||
|
||||
| 命令 | 结果 |
|
||||
|------|------|
|
||||
| `go vet ./...` | PASS(U4 提交前) |
|
||||
| `go test -short ./...` | PASS,38 ok |
|
||||
| 隔离库 `go test ./internal/app/uow ./internal/app/docflow ./internal/docquery` | PASS |
|
||||
| `go test ./internal/docrevision -run TestDocumentCommitConcurrencyPG` | PASS |
|
||||
| `go test -race` 目标包 | PASS(修复 `Commands.Auth` 并发写入后) |
|
||||
| `arch-check --mode warn` | PASS |
|
||||
| `tsx --test controlledDocHydrate.test.ts` | 17 passed |
|
||||
| 全仓 `go test`(带 `TEST_DATABASE_URL` 且无 `-short`) | 未作为本报告门禁;会把无关 workflow PG 和「5434=共享 test 口」拒绝用例搅在一起 |
|
||||
|
||||
`-race` 初跑曾在 `run()` 里给共享 `Commands.Auth` 赋值,判定为数据竞争;已改为只读 `authorizer()`。
|
||||
|
||||
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
|
||||
|
||||
U1–U4 代码已在实现分支落地,Unit/stub、隔离库事务/故障注入、目标包 race 与前端 hydrate 单测通过。用户可感知的主修复(ledger-first GET)**没有**真实 PI、真实浏览器、restart/rebuild 签字;1/2/4 进程一致性只验证到双会话。按计划停走门,不得用「部分通过」打开 U5–U12。
|
||||
|
||||
停止扩面
|
||||
@@ -0,0 +1,172 @@
|
||||
# 治理鉴权升级(职责-动作 + 未激活 202-blocked)测试报告
|
||||
|
||||
## 一、 测试背景 (Background)
|
||||
|
||||
Wave 5 已收口冻结态与 DutyMode,但 full 文档仍因创建者隐式全通行、未激活 run 仍可能拉起小队、`initial_workflow_key` 仍可能直通 active。本轮按已锁定矩阵落地动作-职责鉴权、未激活 202-blocked、关闭创建直通,并在真实 `pi-agent` 开发栈做页面 + API 负例验收。项目 143 **只打开设置/文档做只读回归,未终止、未改规划**。
|
||||
|
||||
## 二、 测试目标 (Test Objectives)
|
||||
|
||||
- 零治理新项目可普通对话;编制类文档任务 202 + `blocked_pending_governance`,chat 出现固定治理提示,无 workspace / 小队。
|
||||
- 一份 full + 其余 none 可激活;激活确认页提示「不纳入人工审批的文档激活后不可补配三职」。
|
||||
- 负例:author/creator 不可审核或批准 full;reviewer 不可 run/submit full;none 无送审/审核/批准;创建者可对处于当前阶段的 none 触发生成。
|
||||
- `POST /projects` 带 `initial_workflow_key` 仍 `planning`、空 `active_workflow_key`,目录仍挂上;旧切换 API 不能直切 active。
|
||||
- 项目 143 设置页仍 frozen,不点终止。
|
||||
|
||||
## 三、 测试方案与环境 (Test Plan & Environment)
|
||||
|
||||
| 项 | 值 |
|
||||
|----|-----|
|
||||
| OS | Linux 7.0.0-31-generic |
|
||||
| 浏览器 | `mcr.microsoft.com/playwright:v1.63.0-noble`,`--network host --ipc host`,`BASE_URL=http://127.0.0.1:8080` |
|
||||
| 服务 | 开发环境 `:8080`;rebuild 后 `GET /api/v1/health` → `status=ok`,`env=dev`,`agent_backend=pi-agent`,`schema_version=33` |
|
||||
| Agent | 真实 `pi-agent`(闲聊走对话后端;未激活编制走 202-blocked,不启小队) |
|
||||
| 分支 / worktree | `fix/governance-action-level-authz` / `.worktrees/fix-governance-action-level-authz` |
|
||||
| 合入 | 独立 merge worktree `/tmp/as-dev-wf409-merge` 对本地 `dev` `--no-ff`;编码 worktree **未**执行 `env-service.sh` |
|
||||
| 脚本 | `web/e2e/governance-action-level-authz.spec.ts`(`RUN_UI_ACCEPTANCE=1`);API 旁证 `assets/.../g5_api_matrix.py` |
|
||||
| 末次页面矩阵 | **1 passed / 12.9s**(用例墙钟 12.3s) |
|
||||
| 本轮页面项目 | `GOVAUTH-mu0z*`(管理员新建立项 + 两名协作者;口令不入库) |
|
||||
| API 旁证项目 | `6209` planning keyed create;`6210` full+none 激活;`6211` 首阶段 none 生成 |
|
||||
| 对照项目 | 143「对话协同会话」(只读) |
|
||||
| 证据 | `.doc/test-reports/assets/2026-09-14-governance-action-level-authz/screenshots/` 与 `api-matrix.json` |
|
||||
|
||||
未在编码 worktree 内执行 `env-service.sh`。
|
||||
|
||||
### 用例矩阵
|
||||
|
||||
| ID | 输入 | 期望 |
|
||||
|----|------|------|
|
||||
| UI-01 | 零治理创建 | 顶栏可见新项目,可配置工作流 |
|
||||
| UI-02 | 「今天天气如何,先闲聊一句。」 | 用户消息 + 助手回复,不走任务 run |
|
||||
| UI-03 | 「请编制用户初始需求收集表」 | 202 blocked、固定治理提示、「待激活工作流」 |
|
||||
| UI-04 | 首份 full + 其余关审批 → 预览 | 冻结提示「不可补配三职」后激活成功 |
|
||||
| UI-05 | 打开非编制文档 | 无送审/审核/批准(none 隐藏审批条) |
|
||||
| UI-06 | 打开 143 设置 | frozen + 「确认终止当前实例」可见但**未点击** |
|
||||
| API-01 | `POST /projects` + `initial_workflow_key=main` | 201 `planning`,空 key;`PUT /active-workflow` 410 |
|
||||
| API-02 | 未激活 `POST /tasks/runs` intake | 202 `blocked_pending_governance`,空 workspace |
|
||||
| API-03 | 未激活 submit/review/approve | 403 `WORKFLOW_NOT_ACTIVATED` |
|
||||
| API-04 | 激活一份 full + 其余 none | `lifecycle=active` |
|
||||
| API-05 | 职责负例 + 创建者 run none | 403 `DOC_DUTY_FORBIDDEN`;none 生成 202 running(随即 cancel) |
|
||||
| API-06 | `GET /projects/143/settings` | live instance,`can_edit_plan=false` |
|
||||
|
||||
页面编制话术使用「请编制用户初始需求收集表」:产品里「帮我生成立项文档」会走私密草稿捷径,不会 `POST /tasks/runs`。
|
||||
|
||||
## 四、 预期结果 (Expected Results)
|
||||
|
||||
未激活:view/闲聊放行;run 建 blocked run 并写固定文案;审批流动作 4xx。激活后 full 只认对应职责,创建者不再越权;none 无审批按钮;当前阶段 none 允许创建者 run。创建带 key 不升 active。项目 143 保持运行中冻结。
|
||||
|
||||
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
|
||||
|
||||
### UI-01 零治理创建
|
||||
|
||||
- **测试输入 (Input)**:管理员开通两名协作者后立项 `GOVAUTH-mu0z*`。
|
||||
- **实际输出 (Actual Output)**:顶栏「当前项目」为新项目;侧栏出现该会话。
|
||||
- **评价判定 (Evaluation / Verdict)**:**PASS**
|
||||
- **性能与耗时 (Duration & Latency)**:截图 `01-zero-gov-created.png`。
|
||||
|
||||
### UI-02 普通对话
|
||||
|
||||
- **测试输入 (Input)**:`今天天气如何,先闲聊一句。`
|
||||
- **实际输出 (Actual Output)**:用户气泡与助手闲聊回复可见;未出现治理拦截条。
|
||||
- **评价判定 (Evaluation / Verdict)**:**PASS**
|
||||
- **性能与耗时 (Duration & Latency)**:截图 `02-casual-chat.png`。
|
||||
|
||||
### UI-03 未激活编制 → 202 blocked
|
||||
|
||||
- **测试输入 (Input)**:`请编制用户初始需求收集表`
|
||||
- **实际输出 (Actual Output)**:助手气泡为「当前项目尚未激活工作流,文档任务不会启动。请先在设置中配置并激活至少一份纳入人工审批的文档。」;状态「待激活工作流」。`POST /api/v1/tasks/runs` 捕获 202 + `blocked_pending_governance`。
|
||||
- **评价判定 (Evaluation / Verdict)**:**PASS**
|
||||
- **性能与耗时 (Duration & Latency)**:截图 `03-blocked-generate.png`。
|
||||
|
||||
首轮页面跑曾因 `chk_task_run_status` 拒收新状态而 500 / `NETWORK_ERROR`。补 `00033` 后复测通过。
|
||||
|
||||
### UI-04 激活一份 full + 其余 none
|
||||
|
||||
- **测试输入 (Input)**:配置工作流:首份纳入审批并填三职,其余关闭;校验并预览 → 确认激活。
|
||||
- **实际输出 (Actual Output)**:预览含「不纳入人工审批的文档激活后不可补配三职」;激活后顶栏「运行中」。
|
||||
- **评价判定 (Evaluation / Verdict)**:**PASS**
|
||||
- **性能与耗时 (Duration & Latency)**:截图 `04-activation-confirm.png`、`05-activated-full-none.png`。
|
||||
|
||||
### UI-05 按钮级职责门禁
|
||||
|
||||
- **测试输入 (Input)**:打开调研/法规等非编制文档。
|
||||
- **实际输出 (Actual Output)**:无「提交送审」;截图见文档栏与动作条。
|
||||
- **评价判定 (Evaluation / Verdict)**:**PASS**
|
||||
- **性能与耗时 (Duration & Latency)**:截图 `06-duty-gated-actions.png`。
|
||||
|
||||
### UI-06 项目 143 只读
|
||||
|
||||
- **测试输入 (Input)**:侧栏打开「对话协同会话」→「查看工作流设置」。
|
||||
- **实际输出 (Actual Output)**:「当前工作流已冻结,只读查看」;「确认终止当前实例」可见,**未点击**。
|
||||
- **评价判定 (Evaluation / Verdict)**:**PASS**
|
||||
- **性能与耗时 (Duration & Latency)**:截图 `07-project-143-readonly.png`。
|
||||
|
||||
### API-01 创建不再直通 active
|
||||
|
||||
- **测试输入 (Input)**:`POST /api/v1/projects` `{"name":"GOVAUTH-API-KEYED-*","initial_workflow_key":"main"}`;再 `PUT /active-workflow`。
|
||||
- **实际输出 (Actual Output)**:201,`id=6209`,`lifecycle=planning`,`active_workflow_key=""`,workflows HTTP 200;切换 410 `WORKFLOW_SWITCH_API_RETIRED`。
|
||||
- **评价判定 (Evaluation / Verdict)**:**PASS**
|
||||
- **性能与耗时 (Duration & Latency)**:26ms。
|
||||
|
||||
### API-02 / API-03 未激活 run / 审批
|
||||
|
||||
- **测试输入 (Input)**:对 6209 发 intake run;对 `doc_proj6209_intake` 发 submit/review/approve。
|
||||
- **实际输出 (Actual Output)**:run 202 `run_1789375353946456022` / `blocked_pending_governance`;GET 无 workspace。库:`status=blocked_pending_governance`,`workspace_id` 空。审批三接口 403 `WORKFLOW_NOT_ACTIVATED`。
|
||||
- **评价判定 (Evaluation / Verdict)**:**PASS**
|
||||
- **性能与耗时 (Duration & Latency)**:run 13ms。
|
||||
|
||||
### API-04 / API-05 激活与职责负例
|
||||
|
||||
- **测试输入 (Input)**:6210 激活 intake=full、其余 none;审核人 run/submit;创建者 review/approve;再对 6211(intake=none + 后续 full)由创建者 run intake。
|
||||
- **实际输出 (Actual Output)**:6210 `lifecycle=active`。审核人/创建者审批 403 `DOC_DUTY_FORBIDDEN`。后期 none 的 submit 403 `DOC_TASK_NOT_IN_ACTIVE_STAGE`(当前 `V0.1_triage`)。6211 创建者 run none → 202 `running`(随即 cancel,避免长 PI)。
|
||||
- **评价判定 (Evaluation / Verdict)**:**PASS**
|
||||
- **性能与耗时 (Duration & Latency)**:激活 461ms;负例合计 43ms。
|
||||
|
||||
### API-06 项目 143
|
||||
|
||||
- **测试输入 (Input)**:`GET /api/v1/projects/143/settings`
|
||||
- **实际输出 (Actual Output)**:`lifecycle=active`,`has_live_instance=true`,`can_edit_plan=false`。未调用终止。
|
||||
- **评价判定 (Evaluation / Verdict)**:**PASS**
|
||||
- **性能与耗时 (Duration & Latency)**:7ms。
|
||||
|
||||
## 六、 自动化测试套件汇总 (Test Suite Execution)
|
||||
|
||||
在 feature worktree(合入前):
|
||||
|
||||
```text
|
||||
go vet ./...
|
||||
go test -short ./...
|
||||
go test -short -race ./internal/projectinstance ./internal/projectworkflow ./internal/server
|
||||
cd web && npm test && npm run build
|
||||
```
|
||||
|
||||
G5 复测(rebuild 后,2026-09-14):
|
||||
|
||||
```text
|
||||
$ curl -sf http://127.0.0.1:8080/api/v1/health
|
||||
{"status":"ok","env":"dev","agent_backend":"pi-agent","version":"v1.0","shared_kb_port":5432,"database_ready":true,"schema_version":33,"schema_ready":true,"task_store_ready":true}
|
||||
|
||||
$ go test -short -count=1 -timeout 180s ./internal/projectinstance ./internal/projectworkflow ./internal/server
|
||||
ok chat-agent-system/internal/projectinstance 0.003s
|
||||
ok chat-agent-system/internal/projectworkflow 0.002s
|
||||
ok chat-agent-system/internal/server 9.957s
|
||||
|
||||
$ npx playwright test e2e/governance-action-level-authz.spec.ts --project=chromium
|
||||
✓ 1 [chromium] › e2e/governance-action-level-authz.spec.ts:57:3 › governance action-level authz › real page matrix G5 (12.3s)
|
||||
1 passed (12.9s)
|
||||
|
||||
$ python3 g5_api_matrix.py
|
||||
wrote .../api-matrix.json verdict=PASS cases=6
|
||||
```
|
||||
|
||||
通过率:页面 1/1;API 6/6;上述 Go 包 short 全绿。未用 stub 输出充当验收。
|
||||
|
||||
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
|
||||
|
||||
**结论**:G1–G5 达到合入标准。动作级职责已落地;未激活编制保持 202 且不启小队;创建带 key 不再直通 active;项目 143 只读回归通过。
|
||||
|
||||
**后续(不阻塞本任务)**:
|
||||
|
||||
- 不把 Wave 5 未跑的「none 文档真实 PI 审批长链路」算进本报告。
|
||||
- 规划话术「帮我生成立项文档」仍走私密草稿捷径;若产品要它走 intake,需另开 templateMatch 任务。
|
||||
- `GET /tasks/runs/{id}` 响应仍是 Go 导出字段 PascalCase,前端创建接口用 snake_case;建议后续统一 JSON tag。
|
||||
- 83 条 planning+残留 key 夹具只审计、未改库。
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
# workflow-plan 409 冻结态 + 可选职责 测试报告
|
||||
|
||||
## 一、 测试背景 (Background)
|
||||
|
||||
已激活项目(现场样本:项目 143 / 侧栏「对话协同会话」)对 `PUT /workflow-plan` 正确返回 409 `PLAN_FROZEN`,但设置页仍渲染职责下拉与「校验并预览」,错误落在长表单视口外,表现为「点击无反应」。同时规划校验把「三职全空」一律当成非法,无法表达「启用文档但不纳入人工审批」。
|
||||
|
||||
本轮按整改方案 Wave 1–4 落地 typed error、frozen 只读页、`DutyMode`、门禁/权限/快照/预览统计与逐文档开关;Wave 5 在真实 `pi-agent` 开发栈上做页面矩阵验收。项目 143 **只打开设置页做只读回归,未终止、未改规划**。
|
||||
|
||||
## 二、 测试目标 (Test Objectives)
|
||||
|
||||
- 项目 143 打开即 frozen:无编辑控件、无 workflow-plan PUT、不点终止。
|
||||
- 新项目 A:一份纳入人工审批 + 其余不纳入 → 保存、预览、激活成功;激活后再打开为 frozen。
|
||||
- 新项目 B:只填编制 → 内联/sticky 拒绝「不能只指派部分职责」,**不发出** PUT。
|
||||
- 新项目 C:全部不纳入 → 预览拒绝「至少一份文档必须纳入人工审批」。
|
||||
- 双标签:C 在另一页激活后,原标签陈旧草稿保存见冻结文案,草稿策略按 Wave 1 保留本地 plan。
|
||||
- 非创建者成员打开 A:无「配置工作流」。
|
||||
- 刷新后项目 143 仍 frozen。
|
||||
- 质量门禁:相关 Go 短测与 `web` 单测全过。
|
||||
|
||||
明确未宣称:本轮 **未** 用真实小队把 full 文档走完审批、也 **未** 对 none 文档做生成 + 版本账本 + 阶段不阻塞的长链路 PI 实测;该项留作后续,不以 stub 或 API 旁证冒充。
|
||||
|
||||
## 三、 测试方案与环境 (Test Plan & Environment)
|
||||
|
||||
| 项 | 值 |
|
||||
|----|-----|
|
||||
| OS | Linux 7.0.0-31-generic |
|
||||
| 浏览器 | `mcr.microsoft.com/playwright:v1.63.0-noble`,`--network host`,`BASE_URL=http://127.0.0.1:8080` |
|
||||
| 服务 | 开发环境 `:8080`;`GET /api/v1/health` → `status=ok`,`env=dev`,`agent_backend=pi-agent`,`schema_version=32` |
|
||||
| Agent | 真实 `pi-agent`(本轮页面矩阵未再触发长文档生成) |
|
||||
| 分支 / worktree | `fix/workflow-plan-409-frozen-and-optional-duties` / `.worktrees/fix-workflow-plan-409-frozen-and-optional-duties` |
|
||||
| 脚本 | `web/e2e/workflow-plan-409-frozen-duties.spec.ts`,`RUN_UI_ACCEPTANCE=1` |
|
||||
| 末次页面矩阵 | **1 passed / 11.4s**(用例墙钟 10.7s) |
|
||||
| 本轮项目(仅用户名/标题,无口令) | `WP409-A-mu0x38jh` / `WP409-B-mu0x38jh` / `WP409-C-mu0x38jh`;成员 `wpb_*` / `wpc_*` |
|
||||
| 对照项目 | 143「对话协同会话」(只读) |
|
||||
| 证据 | `.doc/test-reports/assets/2026-09-14-workflow-plan-409-frozen-and-optional-duties/screenshots/` |
|
||||
|
||||
未在 worktree 内执行 `env-service.sh`。合入与 rebuild 在独立 `dev` worktree / 主仓 compose 完成,编码 worktree 只跑单测与 Playwright。
|
||||
|
||||
### 用例矩阵
|
||||
|
||||
| ID | 输入 | 期望 |
|
||||
|----|------|------|
|
||||
| UI-01 | 打开 143 设置 | frozen 说明 + 无下拉/预览/激活;无 PUT `/143/` |
|
||||
| UI-02 | A:首份开审批并填三职,其余关审批 | 预览可见不纳入统计,确认激活后「运行中」 |
|
||||
| UI-03 | 再开 A 设置 | frozen,无「纳入人工审批」/「校验并预览」 |
|
||||
| UI-04 | B:开审批后只选编制 | sticky「不能只指派部分职责」,PUT 计数不增加 |
|
||||
| UI-05 | C:全部关审批后预览 | sticky「至少一份文档必须纳入人工审批才能激活工作流」 |
|
||||
| UI-06 | 另一标签激活 C,原标签再预览 | 见「工作流已激活,规划已冻结」并转 frozen 只读 |
|
||||
| UI-07 | 成员 B 进 A | 无「配置工作流」 |
|
||||
| UI-08 | 刷新后开 143 | 仍 frozen |
|
||||
|
||||
## 四、 预期结果 (Expected Results)
|
||||
|
||||
- 三个合法配置态:关闭文档 / 启用但不纳入人工审批 / 启用并纳入人工审批。
|
||||
- partial、强制空职责、零治理激活、非在任成员由客户端和/或服务端拒绝。
|
||||
- 已激活项目 `can_edit_plan=false` 或存在 live instance → 只读快照 + 独立受控终止区。
|
||||
- 409 `PLAN_FROZEN`:保留本地草稿并 `fetchProjectSettings` 后切 frozen。
|
||||
|
||||
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
|
||||
|
||||
### UI-01 项目 143 只读冻结
|
||||
|
||||
- **测试输入 (Input)**:管理员登录,侧栏点「对话协同会话」,点「查看工作流设置」。
|
||||
- **实际输出 (Actual Output)**:标题「当前工作流已冻结,只读查看」;工作流 `main` / 版本 v2 / 阶段 `V0.1-triage`;无「纳入人工审批」、无「校验并预览」、无「确认激活」;有受控终止区(文案含 pending documents / 将取消任务)。快照区显示「当前没有启用的文档任务。」(历史冻结 JSON 在本页未展开出文档行;**未改 143**)。监听未出现 `PUT` 含 `/143/`。
|
||||
- **评价判定 (Evaluation / Verdict)**:**PASS**。未点击「确认终止当前实例」。
|
||||
- **性能与耗时 (Duration & Latency)**:含在 10.7s 总矩阵内;截图 `01-project-143-frozen.png`。
|
||||
|
||||
### UI-02 / UI-03 新项目 A 一份 full + 其余 none
|
||||
|
||||
- **测试输入 (Input)**:立项 `WP409-A-mu0x38jh`,加入两名协作者;首份「用户初始需求收集表」勾选纳入人工审批,三职分别为系统管理员 / 王总监 / 测试工程师;其余文档开关关闭。
|
||||
- **实际输出 (Actual Output)**:预览步出现「激活预览」且可见「不纳入」统计;确认后顶栏「商务对接流程 / 运行中」。再次打开设置为 frozen,无开关与预览按钮。
|
||||
- **评价判定 (Evaluation / Verdict)**:**PASS**
|
||||
- **性能与耗时 (Duration & Latency)**:截图 `02-project-a-full-none.png`、`03-project-a-activated.png`、`03b-project-a-frozen.png`。
|
||||
|
||||
### UI-04 新项目 B 部分职责
|
||||
|
||||
- **测试输入 (Input)**:立项 `WP409-B-mu0x38jh`;勾选首份纳入人工审批,只选编制「系统管理员」,点「校验并预览」。
|
||||
- **实际输出 (Actual Output)**:文档下内联「文档「用户初始需求收集表」不能只指派部分职责」;底部 sticky 同文案;该步 `PUT /workflow-plan` 计数为 0。
|
||||
- **评价判定 (Evaluation / Verdict)**:**PASS**
|
||||
- **性能与耗时 (Duration & Latency)**:截图 `04-project-b-partial.png`。
|
||||
|
||||
### UI-05 新项目 C 零治理激活
|
||||
|
||||
- **测试输入 (Input)**:立项 `WP409-C-mu0x38jh`(含协作者);全部「纳入人工审批」关闭后点「校验并预览」。
|
||||
- **实际输出 (Actual Output)**:sticky「至少一份文档必须纳入人工审批才能激活工作流」。
|
||||
- **评价判定 (Evaluation / Verdict)**:**PASS**
|
||||
- **性能与耗时 (Duration & Latency)**:截图 `05-project-c-no-governed.png`。
|
||||
|
||||
### UI-06 双标签 409 → frozen
|
||||
|
||||
- **测试输入 (Input)**:标签 2 登录后打开 C,将首份纳入审批并填满三职,预览并激活;标签 1 仍停在 C 的全空草稿上再点「校验并预览」。
|
||||
- **实际输出 (Actual Output)**:标签 1 转为「当前工作流已冻结,只读查看」;sticky「工作流已激活,规划已冻结」;无编辑下拉。本地快照仍显示激活前全空三职(Wave 1:保留 draftPlan)。
|
||||
- **评价判定 (Evaluation / Verdict)**:**PASS**
|
||||
- **性能与耗时 (Duration & Latency)**:截图 `06-dual-tab-frozen.png`。
|
||||
|
||||
### UI-07 非创建者成员
|
||||
|
||||
- **测试输入 (Input)**:`协作者B-mu0x38jh` 首次改密后进入工作台,点开 `WP409-A-mu0x38jh`。
|
||||
- **实际输出 (Actual Output)**:顶栏为「商务对接流程 / 运行中」,**没有**「配置工作流」按钮。成员侧栏仅见自己加入的项目。
|
||||
- **评价判定 (Evaluation / Verdict)**:**PASS**(本步只断言配置入口;未再点审核/批准动作)。
|
||||
- **性能与耗时 (Duration & Latency)**:截图 `07-member-no-settings.png`。
|
||||
|
||||
### UI-08 刷新后 143
|
||||
|
||||
- **测试输入 (Input)**:管理员页 `reload`,再开「对话协同会话」设置。
|
||||
- **实际输出 (Actual Output)**:仍为「当前工作流已冻结,只读查看」。
|
||||
- **评价判定 (Evaluation / Verdict)**:**PASS**(页面刷新;**未**再做 app 容器 restart)。
|
||||
- **性能与耗时 (Duration & Latency)**:截图 `08-reload-frozen.png`。
|
||||
|
||||
### 未执行:真实生成 / 审批 / 阶段不阻塞
|
||||
|
||||
- **测试输入 (Input)**:无(本轮 Playwright 未发送编制任务、未走审核/批准、未推进阶段)。
|
||||
- **实际输出 (Actual Output)**:无页面证据。
|
||||
- **评价判定 (Evaluation / Verdict)**:**未测**。门禁/权限/none 不阻塞的契约由 Wave 3 单测覆盖,不能代替真实 PI 页面。
|
||||
- **性能与耗时 (Duration & Latency)**:—
|
||||
|
||||
## 六、 自动化测试套件汇总 (Test Suite Execution)
|
||||
|
||||
在 feature worktree:
|
||||
|
||||
```text
|
||||
go vet ./internal/projectinstance/... ./internal/server/... ./internal/workflow/runtime/...
|
||||
go test -short ./...
|
||||
# 全部包 ok / no test files,无 FAIL
|
||||
cd web && npm test -- --run
|
||||
# 361 passed + vitest 30 passed,fail 0
|
||||
```
|
||||
|
||||
真实页面:
|
||||
|
||||
```text
|
||||
npx playwright test e2e/workflow-plan-409-frozen-duties.spec.ts --project=chromium
|
||||
# 1 passed (11.4s)
|
||||
```
|
||||
|
||||
Playwright 原始 output/report 按 `.gitignore` 不入库(`playwright-output-*` / `playwright-report-*`);可复核截图已入库。
|
||||
|
||||
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
|
||||
|
||||
**设置页与激活治理:达到合入标准(页面矩阵 PASS)。** 项目 143 只读回归通过且未被改写/终止。新项目证明了 full+none 激活、partial 不发 PUT、零治理拒绝、双标签转 frozen、成员无配置入口、刷新后 frozen。
|
||||
|
||||
**未达到计划中的「真实执行」全链路。** 后续应单独立项:在已激活的 A 上用真实小队生成首份 full 文档并走审批,生成一份 none 文档确认入账本且无审核/批准、不阻塞阶段;必要时再做一次 `dev` app restart 后的 frozen/快照一致性。
|
||||
|
||||
**观察(不修 143)**:143 frozen 快照区写「当前没有启用的文档任务」,与现场仍有受控文档并行存在。若要展示历史职责,需另开任务读冻结 JSON,禁止在本任务回写 143。
|
||||
|
||||
回链:
|
||||
|
||||
- short-term:[2026-09-14-workflow-plan-409-frozen-and-optional-duties.md](../archive/ops/2026-09-14-workflow-plan-409-frozen-and-optional-duties.md)
|
||||
- FEATURE-MATRIX:工作流治理行
|
||||
- gap-matrix:`WORKFLOW-PLAN-FROZEN-OPTIONAL-DUTIES`
|
||||
@@ -0,0 +1,103 @@
|
||||
# M5/M6 U11–U12 组合根与传输门禁 测试报告
|
||||
|
||||
## 一、 测试背景 (Background)
|
||||
|
||||
权威停走门是 U10 报告最后一句 **停止扩面**([2026-09-15-chatlog-contextasm-u10-test-report.md](./2026-09-15-chatlog-contextasm-u10-test-report.md))。用户于 2026-09-15 明确授权「继续解耦到 U11、U12」,推翻该停止扩面。本轮按整改计划四个子切片落地组合根、文档通知闭包迁出、stageflow 用例、UserProjectContext CAS,以及 SSE 中性编码与已清零规则的 arch-check block。
|
||||
|
||||
## 二、 测试目标 (Test Objectives)
|
||||
|
||||
- U11a:`internal/app.Runtime` 是唯一 composition root;重复 Start 不重复注册 subscriber;Stop 后再 Start worker 仍在。
|
||||
- U11b:文档 `OnOutbox` 从 `internal/server` 迁到 `internal/app/docnotify`;Bind 幂等。
|
||||
- U11c:HTTP / CLI / coordinator 走同一 `stageflow.UseCase`。
|
||||
- U11d:`ApplyContextUpdate` 版本 CAS,并发同版本恰好一个赢家。
|
||||
- U12:SSE 只编码中性 frame;`import`/`event` 进入 `--mode block`;不改错误信封与 PI Runner 协议。
|
||||
- 不碰 `intent`;不终止项目 143;不启用 `FAV_DEGRADED_READ`。
|
||||
|
||||
## 三、 测试方案与环境 (Test Plan & Environment)
|
||||
|
||||
| 项 | 值 |
|
||||
|----|-----|
|
||||
| OS | Linux 7.0.0-31-generic |
|
||||
| 分支 | `feature/app-composition-u11-u12` → `--no-ff` 合入 `dev@bf59cce` |
|
||||
| 本机合同测试 | `unset TEST_DATABASE_URL; go test -short ./internal/app ./internal/app/docnotify ./internal/app/stageflow ./internal/coordinator ./internal/stream/transport ./internal/archtest` |
|
||||
| 架构门 | `./scripts/arch-check.sh --mode warn` 与 `--mode block` |
|
||||
| 目标包 race | `go test -race -short` 上述包(不含全仓 race) |
|
||||
| 全仓 short | `unset TEST_DATABASE_URL; go test -short -count=1 ./...` |
|
||||
| 真实 PI / 浏览器 / rebuild | 主仓占槽后 `./scripts/env-service.sh dev rebuild`;`:8080` health/ready schema 38 |
|
||||
| 证据 | `.doc/test-reports/assets/2026-09-15-app-composition-u11-u12/` |
|
||||
|
||||
## 四、 预期结果 (Expected Results)
|
||||
|
||||
| 栏 | 期望 |
|
||||
|----|------|
|
||||
| Start 幂等 | 连续两次 Start,`StartCount==1` 且 `SubscriberCount==1` |
|
||||
| Restart | Stop 后再 Start,`StartCount==2` 且 subscriber 不加倍 |
|
||||
| OnOutbox | 生产 `internal/server` 无 `OnOutbox =`;`docnotify.Bind` 第二次为 no-op |
|
||||
| stageflow | HTTP 与 CLI 均调用 `stageflow.UseCase`,同一 stub 计数共享 |
|
||||
| CAS | 两 goroutine 同 `ExpectedVersion` → 1 成功 / 1 `ErrStaleContext` |
|
||||
| SSE | frame 含 `event:`/`data:`,不含 `retry:` |
|
||||
| arch-check block | `import`/`event` 计数为 0;sql_write/path 既有例外仍允许 |
|
||||
|
||||
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
|
||||
|
||||
### 5.1 U11a composition root
|
||||
|
||||
- **测试输入**: `go test -short -count=1 ./internal/app -run TestStartStopRestartIdempotent -v`
|
||||
- **实际输出**: `TestStartStopRestartIdempotent` PASS;`cmd/server` 改为 `app.New` + `Runtime.Start` + `server.NewFromRuntime`
|
||||
- **评价判定**: **PASS**
|
||||
- **性能与耗时**: 0.014s。日志:`assets/2026-09-15-app-composition-u11-u12/go-test-u11-packages.txt`
|
||||
|
||||
### 5.2 U11b 文档通知闭包
|
||||
|
||||
- **测试输入**: `go test -short -count=1 ./internal/app/docnotify -v`;`rg OnOutbox internal/server`
|
||||
- **实际输出**: `TestBindOnce` / `TestHandleCandidateReady` / `TestHandleSkipsUnknownAndNoRecipient` PASS。生产 server 包无 `OnOutbox`。`event_consumers.outbox.notify` 属主改为 `app/docnotify`
|
||||
- **评价判定**: **PASS**
|
||||
- **性能与耗时**: 0.002s
|
||||
|
||||
### 5.3 U11c stageflow
|
||||
|
||||
- **测试输入**: `go test -short -count=1 ./internal/app/stageflow -v`
|
||||
- **实际输出**: `TestUseCaseDelegates` PASS(HTTP/CLI 两个 UseCase 共享同一 stub,task=1 stage=1);`handlers` / `task_run_handlers` / `cmd/bizdev-cli` / coordinator `SetStageTaskRunner` 均走该用例
|
||||
- **评价判定**: **PASS**
|
||||
- **性能与耗时**: 0.004s
|
||||
|
||||
### 5.4 U11d ContextUpdate CAS
|
||||
|
||||
- **测试输入**: `go test -race -short -count=1 ./internal/coordinator -run TestContextUpdateConcurrentNoLostUpdate -v`
|
||||
- **实际输出**: 两 goroutine 同版本写 blackboard:1 赢家、1 `ErrStaleContext`,`Version==2`。`-race` PASS(零值 `sync.Mutex`,无懒初始化竞态)
|
||||
- **评价判定**: **PASS**
|
||||
- **性能与耗时**: 约 1.0s(race)。日志:`assets/2026-09-15-app-composition-u11-u12/go-test-u11-packages-race.txt`
|
||||
|
||||
说明:`UserProjectContext` 字段仍导出供读取。跨模块写路径(server 会话组装、chatflow assembler、chat session、coordinator pending/card/blackboard)已改 `ApplyContextUpdate`。coordinator 内部仍有 `Project.CurrentStage` 等字段赋值(该包为上下文 owner)。
|
||||
|
||||
### 5.5 U12 SSE 与 arch-check
|
||||
|
||||
- **测试输入**: `go test -short ./internal/stream/transport`;`./scripts/arch-check.sh --mode warn`;`./scripts/arch-check.sh --mode block`
|
||||
- **实际输出**: `TestWriteNeutralFrame` / `TestHeartbeat` PASS。warn 与 block 均为 `production gate passed`。CI 增加 `arch-check --mode block`。`block_kinds: [import, event]`。未到期 sql_write(5)/path(16) 例外保留
|
||||
- **评价判定**: **PASS**(已清零规则 block;路径/SQL writer 基线例外未假装清零)
|
||||
- **性能与耗时**: arch-check block 约 0.2s。日志:`arch-check-warn.txt`、`arch-check-block.txt`
|
||||
|
||||
### 5.6 真实 PI / 浏览器 / rebuild
|
||||
|
||||
- **测试输入**: 占 CURRENT 集成槽后 `git merge --no-ff feature/app-composition-u11-u12`;`go vet ./...`;`unset TEST_DATABASE_URL; go test -short -count=1 ./...`;`./scripts/arch-check.sh --mode block`;主仓 `./scripts/env-service.sh dev rebuild`;`curl -sf http://127.0.0.1:8080/health` 与 `/ready`
|
||||
- **实际输出**: merge `bf59cce`。vet / short / arch-check block 均 PASS。rebuild 后容器 Recreate。health 与 ready 均为 `status=ok`、`env=dev`、`agent_backend=pi-agent`、`schema_version=38`、`schema_ready=true`、`task_store_ready=true`。镜像 `sha256:a8e3e940f01111c4298c67947ae9f4cd6105f13cf58134672f4a87daa19e27ab`(`agent-dev-app:latest`,created=2026-09-15T05:52:24Z)
|
||||
- **评价判定**: **PASS**
|
||||
- **性能与耗时**: rebuild 约 22s(Go 层未命中 cache;web 层 cache)。证据:`assets/2026-09-15-app-composition-u11-u12/rebuild-health-ready.txt`
|
||||
- 真实 PI 编制任务:本切片不改生成链路,未重跑。浏览器:未改 web 交互。
|
||||
|
||||
## 六、 自动化测试套件汇总 (Test Suite Execution)
|
||||
|
||||
| 命令 | 结果 |
|
||||
|------|------|
|
||||
| `go vet ./...` | PASS |
|
||||
| `unset TEST_DATABASE_URL; go test -short -count=1 ./internal/app ./internal/app/docnotify ./internal/app/stageflow ./internal/coordinator ./internal/stream/transport ./internal/archtest` | PASS |
|
||||
| `go test -race -short -count=1` 同上目标包(不含 archtest) | PASS |
|
||||
| `./scripts/arch-check.sh --mode warn` | PASS |
|
||||
| `./scripts/arch-check.sh --mode block` | PASS(import/event 已清零) |
|
||||
| `unset TEST_DATABASE_URL; go test -short -count=1 ./...` | PASS(EXIT:0,`internal/server` 9.992s) |
|
||||
|
||||
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
|
||||
|
||||
U11a–U11d 与 U12 已合入 `dev@bf59cce` 并完成主仓 rebuild。未清零的 server `workspaces/` / `output.md` 路径例外与 sql_write 基线仍按到期日保留,不把 `--mode block` 写成全规则清零。
|
||||
|
||||
**停止扩面**(整改计划 U1–U12 已落地;未到期 path/sql_write 例外不属于本单元删除范围)。
|
||||
@@ -0,0 +1,68 @@
|
||||
# D4 bizdev locator 移除测试报告
|
||||
|
||||
## 一、 测试背景 (Background)
|
||||
|
||||
`bizdev.Service` 对外暴露 8 个 locator getter(`Pool` / `DocGov` / `DocRevision` / `ContextManager` / `CAS` / `ProjectWorkflow` / `FreeformDoc` / `KB`),HTTP handler 与 CLI 在每次请求上穿过编排根取协作对象。D4 要求组合根一次性 `Snapshot`,由 Runtime/Server 持有端口,并原子删除 getter。
|
||||
|
||||
## 二、 测试目标 (Test Objectives)
|
||||
|
||||
- 生产代码不再调用上述 8 个 getter。
|
||||
- `*bizdev.Service` 上不再存在这 8 个方法;`BizdevService` 接口同步去掉 locator。
|
||||
- archtest 禁止把 getter 加回去。
|
||||
- `go test -short ./...` 与 `arch-check --mode block` 全绿。
|
||||
- 不切事件 live;不删 hook API。
|
||||
|
||||
## 三、 测试方案与环境 (Test Plan & Environment)
|
||||
|
||||
| 项 | 值 |
|
||||
|----|-----|
|
||||
| OS | Linux 7.0.0-31-generic |
|
||||
| Go | go1.27.1 linux/amd64 |
|
||||
| 分支 | `fix/bizdev-locator-removal` |
|
||||
| 层级 | 表征/短测 + arch-check |
|
||||
| 项目 143 | 只读 |
|
||||
|
||||
## 四、 预期结果 (Expected Results)
|
||||
|
||||
| 用例 | 期望 |
|
||||
|------|------|
|
||||
| Snapshot + Assemble | Runtime 字段来自 `bizdev.Snapshot(svc)`,不再走 getter |
|
||||
| Server 端口 | handlers 使用 `s.gov` / `s.ctxMgr` / `s.rev` 等 |
|
||||
| 删除 getter | `func (s *Service) DocGov()` 等 8 个方法不存在 |
|
||||
| archtest | `TestBizdevNoLocatorGetters` PASS |
|
||||
| 短测 | `go test -short ./...` PASS |
|
||||
|
||||
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
|
||||
|
||||
### 5.1 getter 门禁
|
||||
|
||||
- **测试输入 (Input)**:`go test -count=1 ./internal/archtest -run TestBizdevNoLocatorGetters`
|
||||
- **实际输出 (Actual Output)**:`ok chat-agent-system/internal/archtest 0.120s`(含于 arch-check)
|
||||
- **评价判定 (Evaluation / Verdict)**:**PASS**
|
||||
- **性能与耗时 (Duration & Latency)**:~0.12s
|
||||
|
||||
### 5.2 arch-check
|
||||
|
||||
- **测试输入 (Input)**:`./scripts/arch-check.sh --mode block`
|
||||
- **实际输出 (Actual Output)**:`arch-check block: production gate passed`
|
||||
- **评价判定 (Evaluation / Verdict)**:**PASS**
|
||||
- **性能与耗时 (Duration & Latency)**:~0.79s
|
||||
|
||||
### 5.3 短测全量
|
||||
|
||||
- **测试输入 (Input)**:`unset TEST_DATABASE_URL DATABASE_URL CONTEXT_DB_HOST CONTEXT_DSN ALLOW_IN_MEMORY; go vet ./... && go test -short -count=1 ./...`
|
||||
- **实际输出 (Actual Output)**:`go vet` 无输出;各包 `ok`(server 9.926s,cli 2.007s,其余 <2s)
|
||||
- **评价判定 (Evaluation / Verdict)**:**PASS**
|
||||
- **性能与耗时 (Duration & Latency)**:约 12.2s
|
||||
|
||||
## 六、 自动化测试套件汇总 (Test Suite Execution)
|
||||
|
||||
| 命令 | 结果 |
|
||||
|------|------|
|
||||
| `go vet ./...` | PASS |
|
||||
| `go test -short -count=1 ./...` | PASS |
|
||||
| `./scripts/arch-check.sh --mode block` | PASS |
|
||||
|
||||
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
|
||||
|
||||
D4 **PASS**。8 个 locator getter 已删除;组合根持有端口。`internal/chat` 生产包仍 import bizdev 跑 `CreateAndStart`(D7b 剩余批次)。Track P 仍只立项。不切 shared consumer live。
|
||||
@@ -0,0 +1,67 @@
|
||||
# D7b chat 编排剩余批次测试报告
|
||||
|
||||
## 一、 测试背景 (Background)
|
||||
|
||||
D7b 首批只把 `app/chatflow` assembler 的阶段常量迁到 `maturity`。`internal/chat` 生产包仍通过 `ActionServices.Bizdev` 和 `bizdev.TaskRunRequest` 绑在编排根上。D4 已提供 Server 端口后,本批去掉 chat 生产对 bizdev 的 import。
|
||||
|
||||
## 二、 测试目标 (Test Objectives)
|
||||
|
||||
- `internal/chat` 生产代码不再 import `bizdev`。
|
||||
- 任务续跑/重启走 `stageflow.TaskRunRequest` 别名;`CreateAndStart` 类型身份不变。
|
||||
- 去掉 `ActionServices.Bizdev`;仅要求 `TaskRuns`。
|
||||
- arch-check 收紧 chat allowlist(去掉 bizdev,加入 app/stageflow)。
|
||||
- 既有 `TestExecuteAction_DocGovReviewApprove` 与 chat 表征仍过。
|
||||
|
||||
## 三、 测试方案与环境 (Test Plan & Environment)
|
||||
|
||||
| 项 | 值 |
|
||||
|----|-----|
|
||||
| OS | Linux 7.0.0-31-generic |
|
||||
| Go | go1.27.1 linux/amd64 |
|
||||
| 分支 | `fix/chatflow-orchestration-boundary` |
|
||||
| 层级 | 表征/短测 + arch-check |
|
||||
| 项目 143 | 只读 |
|
||||
|
||||
## 四、 预期结果 (Expected Results)
|
||||
|
||||
| 用例 | 期望 |
|
||||
|------|------|
|
||||
| 生产 import | chat 无 bizdev |
|
||||
| 审核动作 | `TestExecuteAction_DocGovReviewApprove` PASS |
|
||||
| 短测 | `go test -short ./...` PASS |
|
||||
| arch-check | block 通过 |
|
||||
|
||||
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
|
||||
|
||||
### 5.1 表征
|
||||
|
||||
- **测试输入 (Input)**:`go test -short -count=1 ./internal/chat ./internal/server ./internal/archtest ./internal/app/stageflow`
|
||||
- **实际输出 (Actual Output)**:上述包全部 `ok`(server 9.950s)
|
||||
- **评价判定 (Evaluation / Verdict)**:**PASS**
|
||||
- **性能与耗时 (Duration & Latency)**:约 11.6s
|
||||
|
||||
### 5.2 arch-check
|
||||
|
||||
- **测试输入 (Input)**:`./scripts/arch-check.sh --mode block`
|
||||
- **实际输出 (Actual Output)**:`arch-check block: production gate passed`
|
||||
- **评价判定 (Evaluation / Verdict)**:**PASS**
|
||||
- **性能与耗时 (Duration & Latency)**:~0.22s
|
||||
|
||||
### 5.3 短测全量
|
||||
|
||||
- **测试输入 (Input)**:`go test -short -count=1 ./...`
|
||||
- **实际输出 (Actual Output)**:各包 `ok`(server 10.007s,cli 2.327s)
|
||||
- **评价判定 (Evaluation / Verdict)**:**PASS**
|
||||
- **性能与耗时 (Duration & Latency)**:约 12.6s
|
||||
|
||||
## 六、 自动化测试套件汇总 (Test Suite Execution)
|
||||
|
||||
| 命令 | 结果 |
|
||||
|------|------|
|
||||
| chat/server/archtest/stageflow | PASS |
|
||||
| `./scripts/arch-check.sh --mode block` | PASS |
|
||||
| `go test -short -count=1 ./...` | PASS |
|
||||
|
||||
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
|
||||
|
||||
D7b 剩余批次 **PASS**。chat 生产不再 import bizdev。测试仍可用 bizdev 构造夹具。taskrun 签名仍是 bizdev 类型别名,未机械复制字段。Track P 仍只立项;不切 shared consumer live。
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user