docs(arch): archive document reliability pilot plan and claim docgov
Land the revised modular-monolith scheme on the implementation branch so U1–U4 can proceed against a frozen design, and register the docgov mutex without occupying the integration slot. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -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,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,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、整改方案与测试报告
|
||||
@@ -13,6 +13,14 @@
|
||||
|
||||
## 核心文档(按阅读顺序推荐)
|
||||
|
||||
### 模块解耦方案复核(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)
|
||||
|
||||
+8
-2
@@ -5,13 +5,16 @@
|
||||
|
||||
## 焦点
|
||||
|
||||
1. **CHAT-INTENT**: [对话意图运行时状态](../audit/2026-09-13-conversation-intent-runtime-state.md)(`fix/conversation-intent-state`;与文档账本运行时无关)
|
||||
2. **CHAT**: [对话历史刷新](../audit/2026-09-13-chat-history-refresh-disappears.md)(认领仍 `in_progress`;gap 行已 PASS,以代码/handoff 为准收敛)
|
||||
1. **DOC-RELIABILITY**: [文档可靠性纵向试点 M0–M1](../ops/short-term/2026-09-14-document-reliability-pilot.md)(`refactor/document-reliability-pilot`;`mutex=docgov`;不占集成槽、不 rebuild)
|
||||
2. **CHAT-INTENT**: [对话意图运行时状态](../audit/2026-09-13-conversation-intent-runtime-state.md)(`fix/conversation-intent-state`;与文档账本运行时无关)
|
||||
3. **CHAT**: [对话历史刷新](../audit/2026-09-13-chat-history-refresh-disappears.md)(认领仍 `in_progress`;gap 行已 PASS,以代码/handoff 为准收敛)
|
||||
|
||||
## 并行认领
|
||||
|
||||
| owner | task | branch | worktree | mutex | status |
|
||||
|-------|------|--------|----------|-------|--------|
|
||||
| Cursor | document-reliability-pilot | refactor/document-reliability-pilot | .worktrees/refactor-document-reliability-pilot | docgov | in_progress |
|
||||
| Codex | module-decoupling-remediation-plan | feature/module-decoupling-remediation | .worktrees/feature/module-decoupling-remediation | architecture-docs | done |
|
||||
| verifier_antigravity | controlled-content-ui-acceptance | fix/controlled-content-ui-acceptance | .worktrees/fix-controlled-content-ui-acceptance | document-content-ui-acceptance | done |
|
||||
| implementer_cursor | controlled-content-canonical-hash | fix/controlled-content-canonical-hash | .worktrees/fix-controlled-content-canonical-hash | docgov | done |
|
||||
| Codex | project143-controlled-content-404-diagnosis | fix/project143-controlled-content-404-diagnosis | - | docgov-content-diagnosis | done |
|
||||
@@ -51,6 +54,7 @@
|
||||
> 新任务开始前登记。`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` 仅占 `docgov` 编码;合 `dev` + `env-service rebuild` 必须另占集成槽位。M1 报告未签字前不得 rebuild。
|
||||
|
||||
## 集成槽位
|
||||
|
||||
@@ -84,6 +88,8 @@
|
||||
| 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) |
|
||||
| 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: planned
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-14
|
||||
owner: TBD
|
||||
---
|
||||
|
||||
# 模块解耦重构验收清单
|
||||
|
||||
## M0 架构与基线
|
||||
|
||||
- [ ] contracts 分类、事务 owner、表属主、锁顺序、事件信封、Principal 和 FAV 边界均有唯一规范来源。
|
||||
- [ ] arch-check 分离 production import、SQL write、path 和 event registration;例外有 owner 与到期日。
|
||||
- [ ] 当前违规基线可重复生成,新违规立即阻断。
|
||||
|
||||
## M1 文档可靠性
|
||||
|
||||
- [ ] 人工编辑、agent commit、approve/reject 的跨表写入同事务。
|
||||
- [ ] fault injection 任一点失败均无部分提交。
|
||||
- [ ] 同 ETag 并发写只有一个赢家;不同文档不被全局锁串行。
|
||||
- [ ] 1、2、4 app replicas 结果一致。
|
||||
- [ ] GET/refresh/reload 零写入,projection 缺失不伪装成 404。
|
||||
- [ ] 项目 143 等价 hazard 与新项目真实页面刷新、重登、restart、rebuild PASS。
|
||||
- [ ] 匿名、非成员、跨用户、跨项目、错误 stage/duty、授权失败负例 PASS。
|
||||
|
||||
## M2 事件与 FAV
|
||||
|
||||
- [ ] 业务终态、staging 和 outbox 同事务。
|
||||
- [ ] 每个 consumer 有独立 delivery/inbox/attempt/lease/dead-letter。
|
||||
- [ ] 1、2、4 dispatcher 无重复可见副作用和永久饥饿。
|
||||
- [ ] crash-before/after-side-effect/ack 全部可恢复。
|
||||
- [ ] stale fencing、跨项目事件、错误 producer、坏 digest 均拒绝。
|
||||
- [ ] FAV 中间结果、Prompt、工具轨迹和 secret 准入率为零。
|
||||
- [ ] DB 授权成功后才允许 degraded read;授权图缺失 fail closed。
|
||||
- [ ] tombstone/删除账本 union-deny PASS。
|
||||
|
||||
## M3 TaskRun、workspace 与数据生命周期
|
||||
|
||||
- [ ] RunManifest 规范字节、SHA、成员和 storage identity 持久化。
|
||||
- [ ] 重复 finalize、SSE 断线和 cancel race 不重复消息或 artifact。
|
||||
- [ ] WorkspaceRef 无物理路径,路径遍历和链接逃逸负例 PASS。
|
||||
- [ ] 旧 lease writer 被 fencing token 拒绝。
|
||||
- [ ] workspace 清空后最终成果仍可定位和校验。
|
||||
- [ ] backfill 可暂停、续跑和重放;异常进入 quarantine。
|
||||
- [ ] 八条 migration/reload/recovery 轨道 PASS。
|
||||
- [ ] 数据销毁前完整备份、corpus、FAV coverage 和人工批准全部满足。
|
||||
|
||||
## M4–M6 选择性扩展
|
||||
|
||||
- [ ] 每个子切片在原包边界先获得行为收益,再决定物理搬包。
|
||||
- [ ] chatlog/contextasm 保持授权可见集合和计数一致。
|
||||
- [ ] app 是唯一组合根,subscriber 重复启动不重复注册。
|
||||
- [ ] UserProjectContext 不再被多个模块字段级直改。
|
||||
- [ ] server 无 SQL、路径拼接和业务闭包。
|
||||
- [ ] 对应架构规则全部 block,过期例外和 flags 已删除。
|
||||
|
||||
## 证据分层
|
||||
|
||||
- [ ] Unit/stub 证据。
|
||||
- [ ] PostgreSQL integration 证据。
|
||||
- [ ] race/concurrency/load 证据。
|
||||
- [ ] fault injection/crash 证据。
|
||||
- [ ] 真实 PI 证据。
|
||||
- [ ] 真实浏览器证据。
|
||||
- [ ] restart/rebuild 证据。
|
||||
- [ ] cross-user/project authorization negative 证据。
|
||||
- [ ] scratch recovery 与完整 DB restore 证据。
|
||||
|
||||
## 关闭条件
|
||||
|
||||
- [ ] test report 回链具体 U-ID、commit、环境 identity 和 fixture/dataset。
|
||||
- [ ] CURRENT、FEATURE-MATRIX、gap-matrix 与任务状态一致。
|
||||
- [ ] 未实施后续仍为 planned/deferred,不用局部测试冒充全计划完成。
|
||||
@@ -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,61 @@
|
||||
---
|
||||
title: "文档可靠性纵向试点 M0–M1"
|
||||
status: in_progress
|
||||
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. [ ] 为当前跨表提交、刷新读取、ETag/idempotency 和权限负例补 characterization。
|
||||
3. [ ] 实现 U1–U2,验证任意属主写入/commit 故障整体回滚。
|
||||
4. [ ] 实现 U3,删除提交后 outbox 正确性回调。
|
||||
5. [ ] 实现 U4,保证 GET 零写入和 projection 缺失不再伪装成 404。
|
||||
6. [ ] 执行多实例并发、PG、真实 PI、真实浏览器和 restart/rebuild 验收。
|
||||
7. [ ] 写 test report,更新验收清单、FEATURE-MATRIX、CURRENT 和 gap-matrix。
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [ ] 同一 ETag 并发编辑只有一个合法赢家,账本/head/outbox 无孤儿。
|
||||
- [ ] 任一事务故障点不会留下部分提交。
|
||||
- [ ] 项目 143 等价 hazard 和新项目刷新/重启目标 404/409/projection missing 为 0。
|
||||
- [ ] 匿名、非成员、跨用户、跨项目、错误 stage/duty 和授权依赖失败均 fail closed。
|
||||
- [ ] 1、2、4 个 app 实例的最终状态一致。
|
||||
- [ ] M1 test report 给出继续 M2 或停止扩面的明确结论。
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Checklist: [../checklists/2026-09-14-module-decoupling-refactor-acceptance.md](../checklists/2026-09-14-module-decoupling-refactor-acceptance.md)
|
||||
- Handoff: 实施时创建
|
||||
- Test report: 实施后创建 `.doc/test-reports/<date>-document-reliability-pilot.md`
|
||||
- Plan: [../../remediation/2026-09-14-module-decoupling-refactor-plan.md](../../remediation/2026-09-14-module-decoupling-refactor-plan.md)
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
只有本任务真实验收通过后,才允许启动 durable event/FAV 与横向模块扩展。
|
||||
@@ -0,0 +1,60 @@
|
||||
---
|
||||
title: "可靠事件与 FAV 集成 M2–M3"
|
||||
status: planned
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-14
|
||||
owner: TBD
|
||||
branch: refactor/durable-event-fav-integration
|
||||
worktree: "-"
|
||||
mutex: event-delivery
|
||||
---
|
||||
|
||||
# 可靠事件与 FAV 集成 M2–M3
|
||||
|
||||
## 目标
|
||||
|
||||
完成 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. [ ] 读取 M1 test report,确认继续 M2 的 go/no-go 已通过。
|
||||
2. [ ] 重新分配 Goose 序号并审计 U6/FAV schema 组合。
|
||||
3. [ ] 实现 U5–U6,多 app/worker 和 crash matrix 先通过。
|
||||
4. [ ] 逐文件审计 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](../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,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`
|
||||
@@ -3,6 +3,7 @@
|
||||
| 文档 | 说明 |
|
||||
|------|------|
|
||||
| [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-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 |
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
| 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 | 受控文档写路径跨表非同事务、读路径被 projection 绑架、授权 TOCTOU;刷新/重启后可能 404/409/projection-missing | OPEN | [复核](../audit/2026-09-14-module-decoupling-plan-review.md);[重构计划](./2026-09-14-module-decoupling-refactor-plan.md);[试点任务](../ops/short-term/2026-09-14-document-reliability-pilot.md) | M0–M1=U1–U4;未占槽不得 rebuild;M2+ 需独立 go/no-go |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
| 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` |
|
||||
| 三环境运维 | 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` |
|
||||
| 模块解耦与可靠事件 | 文档可靠性纵向试点、跨属主事务、多副本互斥、FAV 与选择性模块化 | planned | [架构](../system-design/2026-09-14-module-decoupling-architecture.md);[ADR](../adr/2026-09-14-modular-monolith-decoupling.md);[重构计划](../remediation/2026-09-14-module-decoupling-refactor-plan.md);[试点任务](../ops/short-term/2026-09-14-document-reliability-pilot.md) | 方案已入库。M0–M1=U1–U4 为首个批准范围;M2+ 需 M1 go/no-go | `docgov` |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -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 协议作为独立项目实施。
|
||||
|
||||
详细依赖、文件和测试场景见整改计划。
|
||||
@@ -99,6 +99,26 @@
|
||||
|
||||
---
|
||||
|
||||
### 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 和恢复工具使用同一逐动作授权模型;
|
||||
- 先原地端口化,行为稳定后才物理搬包。
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ 在整体架构中的位置
|
||||
|
||||
```
|
||||
@@ -161,6 +181,7 @@
|
||||
├── 04-项目多工作流与智能产品经理-测试经理工作流-实施计划.md
|
||||
├── 05-Phase0-基线确认与契约冻结.md
|
||||
└── 06-Phase7-全链路验收与发布基线.md
|
||||
├── 2026-09-14-module-decoupling-architecture.md ← 模块化单体解耦
|
||||
|
||||
.tmp/ ← 中间分析文件
|
||||
├── intent-recognition/
|
||||
|
||||
Reference in New Issue
Block a user