docs(ops): land Phase 2 Track E/S/P plans onto a legal feature branch
Move the reviewed durable-event, HTTP envelope, and PI typed-result designs off the docs/ prefix so Track E can start from latest dev. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+4
-3
@@ -1,8 +1,8 @@
|
||||
---
|
||||
title: "可靠事件与 FAV 集成 M2–M3"
|
||||
status: planned
|
||||
status: cancelled
|
||||
created: 2026-09-14
|
||||
updated: 2026-09-14
|
||||
updated: 2026-09-15
|
||||
owner: TBD
|
||||
branch: refactor/durable-event-fav-integration
|
||||
worktree: "-"
|
||||
@@ -10,6 +10,7 @@ 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 验收。
|
||||
|
||||
## 目标
|
||||
|
||||
@@ -50,7 +51,7 @@ mutex: event-delivery
|
||||
|
||||
## 相关链接
|
||||
|
||||
- Checklist: [../checklists/2026-09-14-module-decoupling-refactor-acceptance.md](../checklists/2026-09-14-module-decoupling-refactor-acceptance.md)
|
||||
- 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)
|
||||
@@ -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,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 分类。
|
||||
@@ -13,6 +13,15 @@
|
||||
|
||||
## 核心文档(按阅读顺序推荐)
|
||||
|
||||
### 模块解耦 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)
|
||||
|
||||
+6
-2
@@ -5,8 +5,8 @@
|
||||
|
||||
## 焦点
|
||||
|
||||
1. **CHAT-INTENT**: [对话意图运行时状态](../test-reports/2026-09-13-conversation-intent-runtime-state-test-report.md)(双标签 busy 已签:项目 **6275** / `DOC_BUSY` 单 run;不删 `sess-p143-u9` 探针)
|
||||
2. **DOC-RELIABILITY**: [U11–U12 组合根与传输门禁](../archive/ops/2026-09-15-app-composition-u11-u12.md)(已合入 `dev@bf59cce`;rebuild digest `a8e3e940…`;schema 38)
|
||||
1. **TRACK-E**: [持久事件交付](./short-term/2026-09-15-durable-event-track-e.md)(方案已审阅;下一开工为 E0A 生产者/契约/历史数据门;dispatcher 保持 off)
|
||||
2. **CHAT-INTENT**: [对话意图运行时状态](../test-reports/2026-09-13-conversation-intent-runtime-state-test-report.md)(双标签 busy 已签:项目 **6275** / `DOC_BUSY` 单 run;不删 `sess-p143-u9` 探针)
|
||||
3. **CHAT**: [对话历史刷新活验已补](../test-reports/2026-09-13-chat-history-refresh-test-report.md)(项目 6252 闲聊刷新同集 + guest 403;编制任务链仍开放)
|
||||
|
||||
## 并行认领
|
||||
@@ -20,6 +20,8 @@
|
||||
| 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 | in_progress |
|
||||
| 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 |
|
||||
@@ -98,6 +100,8 @@
|
||||
| 纯软件项目自举设计 | [../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) |
|
||||
| 文档可靠性 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) |
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: "模块解耦与 IPC/RPC 交互现状评估(耦合点清点与进一步解耦方案)"
|
||||
title: "模块解耦与 IPC/RPC 交互现状评估(复核修订版)"
|
||||
status: done
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
@@ -11,133 +11,139 @@ confidence: high
|
||||
|
||||
## 结论
|
||||
|
||||
1. **系统走的是"模块化单体"路线,而不是全量 IPC/RPC 微服务**——这是 [ADR 2026-09-14](../../adr/2026-09-14-modular-monolith-decoupling.md) 的明确决策(非目标:不拆微服务、不引入分布式事务协调器)。模块间解耦靠三件套:**消费者拥有的 Go 端口接口 + 唯一组合根(`internal/app`)装配 + PostgreSQL outbox 事件**。真正的跨进程边界只有三条:前端↔server(HTTP/SSE)、Go↔PI Agent Runner 容器(HTTP + Bearer)、规划中的独立事件 dispatcher 进程。
|
||||
2. **调用契约已大部分"机器可执行地"约定**:`.doc/system-design/module-boundaries.yaml` + `internal/archtest` 四类静态规则(import / event 两类已在生产门禁 `--mode block` 下清零;path 16 条、sql_write 5 条为带 owner/到期日的例外账本),外加 `events.Envelope` schema 1、`taskrun.RunManifest` schema 1、SSE transport、幂等协议(idempotency key + request digest;ETag = `head_snapshot_id:head_revision_no`)。
|
||||
3. **残留的强耦合集中在五处**:bizdev 门面兼 service locator、docgov↔docrevision 双向 import、chat/coordinator 各依赖 ~10 个包、进程内闭包 hook 桥(崩溃即丢、无幂等)、durable dispatcher 未接线(事件写进了 outbox 但没有消费者 worker 在跑)。另有 PI Runner stdout/result.json 旧协议与 HTTP 错误信封未统一两项已声明的 deferred 债。
|
||||
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 交付的前置条件。
|
||||
|
||||
对用户目标的直接回答:**"彻底解耦、一处修改不扩散"已大体达成**(import 违规为 0、单一写者、契约带版本与 SHA),**但"所有交互都走 IPC/RPC"并非本仓库的方向也不建议照搬**;错误排查能力的短板不在进程边界,而在事件链路只写不消费、闭包桥无审计痕迹。
|
||||
## 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 | 独立审计轨道 | 分支未整支合入;不得作为本轮验收前置 |
|
||||
|
||||
## 1. 通信边界清点(谁和谁怎么交互)
|
||||
不建议把单体内端口改成 RPC。那会增加序列化、延迟、部分失败与运维成本,却不消除当前 locator、授权、幂等和事件消费缺口。
|
||||
|
||||
| 边界 | 机制 | 契约位置 | 状态 |
|
||||
|---|---|---|---|
|
||||
| Web 前端 ↔ server | HTTP `/api/v1/*`(~110 路由)+ SSE | `internal/server`(wire DTO)、`internal/stream/transport/sse.go` | ✅ 已约定;错误信封统一 deferred |
|
||||
| Go ↔ PI Agent Runner 容器 | HTTP + `Bearer RUNNER_AUTH_TOKEN`;`/health`、`/v1/run`、`/v1/cancel`、`/v1/search`(`deploy/pi-agent/runner.mjs:319-405`) | backend allowlist(`internal/taskrun/backend.go`:stub/pi-agent/cursor);结果经 stdout/result.json | ⚠️ 传输已约定;**结果协议仍是 stdout/result.json**(整改计划明确 deferred 不本轮替换) |
|
||||
| 模块 ↔ 模块(进程内) | Go 端口接口(消费者所有)+ `internal/app` 组合根注入 | `module-boundaries.yaml` imports allowlist + archtest | ✅ 机器可执行;bizdev/coordinator/chat 例外见 §3 |
|
||||
| 领域事件 | PG outbox + envelope + 逐消费者 delivery + fencing token | `internal/events/envelope.go`(schema 1、digest、secret 扫描)、`pg.go`、`replay.go` | ⚠️ **写侧已落地、消费侧未接线**(见 §3.4) |
|
||||
| 终态产物 | RunManifest(canonical JSON + SHA-256)+ FAV | `internal/taskrun/manifest.go`(schema 1) | ✅ U8 已合入 dev;FAV 分支未整支 merge(KTD12) |
|
||||
## 2. 已有契约与真实边界
|
||||
|
||||
## 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,不是新建段落。
|
||||
|
||||
- 静态边界:`scripts/arch-check.sh --mode block` 通过(`block_kinds: [import, event]`,baseline import=0、event=0);例外必须有 owner/milestone/expires。
|
||||
- 事件信封:`EnvelopeSchema=1`,字段齐全(event_id/aggregate_type/version/correlation/causation/idempotency_key/payload_digest/producer),`ValidateEnvelope` 拒绝伪造 producer、digest 不符、payload 携带 secret。
|
||||
- 投递协议:`Delivery`(pending/leased/acked/dead/quarantine)+ lease + fencing token + `MaxAttempts=12` + aggregate version gap 等待(`events/bus.go`,PG 版 `SKIP LOCKED` 同语义)。
|
||||
- 幂等协议:TaskRun `Claim(idempotency_key, request_digest)` 同 key 异 digest 返回 `IDEMPOTENCY_CONFLICT`;文档 ETag/expected head。
|
||||
- 持久 schema:RunManifest v1(member kinds 枚举 + canonical 排序 + SHA);`configs/schemas/change-report-v1.json`。
|
||||
- 后端选择:`ResolveBackend` 服务端 allowlist,调用方不可注入任意字符串;`StripSecrets` 出站脱敏。
|
||||
### 尚未闭合
|
||||
|
||||
**未约定 / 弱约定:**
|
||||
- `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 记录。
|
||||
|
||||
- PI Runner 结果解析(stdout/result.json)——deferred。
|
||||
- HTTP 错误信封统一——deferred。
|
||||
- 闭包 hook(`OnOutbox`、`AddOnApprovedHook`)无 schema、无版本、无审计记录。
|
||||
- docflow 发事件的 `Environment: "dev"` 与 `ProjectID: 0` 硬编码(`internal/app/docflow/commands.go:167`),未从 Principal/命令注入——协议字段存在但值来源失真(test/main 环境下事件环境标注错误)。
|
||||
## 3. 耦合点
|
||||
|
||||
## 3. 强/弱耦合点清点(附证据)
|
||||
### 3.1 bizdev service locator
|
||||
|
||||
### 3.1 强耦合:bizdev 门面 + service locator(最大枢纽)
|
||||
`bizdev.Service` 暴露 `Pool()/CAS()/DocGov()/DocRevision()/ProjectWorkflow()/FreeformDoc()/KB()/ContextManager()`。调用方可以绕过端口取得数据库池和其他模块实现,令签名或构造变化向多包扩散。
|
||||
|
||||
- ~4.8k LOC,被 **12 个生产包 import(78 处引用)**;自身 import 18 个内部包。
|
||||
- `bizdev.Service` 暴露 `Pool()/CAS()/DocGov()/DocRevision()/ProjectWorkflow()/FreeformDoc()/KB()/ContextManager()`(`service.go:229-260`)——**service locator 反模式**:任何拿到 `*bizdev.Service` 的包都能直取 `*pgxpool.Pool` 和其他模块的具体实现,绕过所有端口抽象。
|
||||
- `app/stageflow` 已开始绞杀(只依赖 bizdev),但 `coordinator.StageTaskRunner` 仍以 `bizdev.TaskRunRequest/Result` 为词汇(`engine.go:85-88`),即传输类型与门面绑死。
|
||||
- 影响:改 bizdev 任何签名会波及 chat/coordinator/taskrun/projectinstance/intent 等全部下游——正是"一处修改多处出问题"的活样本。
|
||||
整改应先加 no-new-callers 门禁,再逐调用方迁移,最后在一个 contract 提交删除 8 个 getter。门禁应禁止领域/用例 API 暴露或转发 pool/tx,同时允许 app/cmd 组合根向表属主构造器注入 pool,并允许登记属主从 opaque TxScope 解出 tx。
|
||||
|
||||
### 3.2 强耦合:docgov ↔ docrevision 双向 import
|
||||
### 3.2 docgov 到 docrevision 的单向工具依赖
|
||||
|
||||
- `docgov` imports `docrevision`,`docrevision` imports `docgov`(boundaries.yaml 双向 allowlist)。两个"单一写者"模块互相拿到对方类型,表所有权边界在类型层面没有闭合。
|
||||
生产依赖方向是 `docgov → docrevision`。直接用途集中在 Markdown canonicalization 与 SHA helper;`docrevision` 不生产 import `docgov`。
|
||||
|
||||
### 3.3 强耦合:chat / coordinator 扇出过大
|
||||
目标不是“破双向环”,而是把 canonical Markdown + digest 提取为有行为、内聚、带 golden vectors 的共享模块,例如 `internal/doccontent`。它不应进入只放无行为值对象的 vocabulary。
|
||||
|
||||
- `chat` 依赖 11 个包(bizdev、coordinator、ctxmgr、docgov、intent、projectinstance、replyexport、squad、stream、taskrun…);`coordinator` 依赖 10 个包。U10 已完成 chatlog/contextasm 端口化,但 `internal/chat` 本体尚未收编进 `app/chatflow`。
|
||||
- `ctxmgr` 被 5 个包共享(56 处引用),是共享可变上下文状态的汇聚点。
|
||||
- `intent`(纯规则模块)依赖 `bizdev`——与架构文档 §3 的模块表(intent 只准依赖 vocabulary)直接矛盾,属于基线豁免债。
|
||||
### 3.3 chat、coordinator 与 intent
|
||||
|
||||
### 3.4 强耦合:进程内闭包桥替代事件消费(可靠性缺口)
|
||||
- coordinator 仍以 `bizdev.TaskRunRequest/Result` 为词汇。
|
||||
- chat 编排跨多个模块,需按用例逐批迁入 chatflow。
|
||||
- intent 与 bizdev 的解绑是较小且独立的迁移,不应和 chat 大迁移绑成一个分支。
|
||||
|
||||
- 生产发布者只有两处:`app/docflow`(AgentCommit)与 `taskrun/finalize.go`(`events.PGSink{}.Append`,consumers 声明为 projection/fav/notify)。
|
||||
- **没有任何生产代码构造/运行 PG dispatcher**(全仓 grep `events.New|Dispatcher` 无命中;`MemoryBus` 仅 characterization 用;U6 规划的 `cmd/events/main.go` 不存在)。`Runtime.Start` 只跑 reminder loop 并绑定闭包。
|
||||
- 消费侧仍是闭包:`docnotify.Bind` 直接改写 `docrevision.Service.OnOutbox` 字段;`docgov.AddOnApprovedHook → app.go:180 onWorkflowDocumentApproved` 在组合根内联编排 projectinstance + projectworkflow + notification。
|
||||
- 后果:进程崩溃/重启时 hook 注册丢失、无 delivery 记录、无重试/死信/replay——设计目标 5(事件在崩溃、重复投递下可追踪可重试)**未达成**;这也正是错误排查最痛的盲区(事件有表可查,hook 无迹可寻)。
|
||||
### 3.4 闭包桥与未接线事件
|
||||
|
||||
### 3.5 弱耦合(已在例外账本内、有到期日)
|
||||
当前批准后的推进与通知仍可通过 `docrevision.OnOutbox`、`docgov.AddOnApprovedHook` 及组合根闭包执行。闭包在提交后的进程内调用不能提供 durable delivery、重试、dead-letter、replay 或 attempt audit。
|
||||
|
||||
- **path 16 条**:bizdev(4)/coordinator(4)/docgov(2)/docrevision(2)/server(3)/storage(1) 直接拼 `output.md`、`data/dev`、`workspaces/` 物理路径;U4 到期 2026-09-28,U5 到期 2026-10-12。
|
||||
- **sql_write 5 条**:生产写越界,按属主里程碑清零。
|
||||
- **server 适配层**:102 文件 / 17,211 LOC,allowlist 28 个包——架构上允许(server 是唯一传输适配层),但 `chatflow_http` 等编排仍在 server 内,U12 传输收口未完全做完。
|
||||
- **uow.AsPG unwrap owner**:已有 archtest 规则约束谁能解出 `pgx.Tx`,方向正确。
|
||||
不能直接删除闭包。正确顺序是:
|
||||
|
||||
## 4. 进一步解耦方案(按优先级)
|
||||
1. 证明生产入口在同一 UoW 写入领域变化、envelope 和目标 delivery。
|
||||
2. 对历史事件做 dry-run inventory,隔离 scope/schema/sequence 异常。
|
||||
3. 完成真实 PG dispatcher。
|
||||
4. shadow 只计算 intended outcome,不执行业务副作用。
|
||||
5. 以时间、样本和状态分支覆盖作为切换门。
|
||||
6. 按 notify、workflow advance、projection 独立切换和回滚。
|
||||
|
||||
### P0 正确性/可排查性(先做,收益最大)
|
||||
## 4. 并发、数据与权限风险
|
||||
|
||||
1. **接线 durable dispatcher,替换闭包桥(U6 收尾)**:
|
||||
- 新增 `cmd/events` worker(claim → deliver → ack/dead-letter,`SKIP LOCKED` + fencing token 已有实现 `internal/events/pg.go`);
|
||||
- 在组合根把 `projection`/`notify`/`fav` 注册为真实消费者,逐个删除 `docrevision.OnOutbox` 与 `docgov.AddOnApprovedHook` 闭包桥(U6 Approach 第 7 步原文);
|
||||
- 验收即架构文档 §9.2 行为门禁:worker 崩溃/lease 过期/重复投递后副作用恰好一次。
|
||||
- 这一步同时解决"崩溃丢通知"和"排查无审计痕迹"两个问题。
|
||||
2. **修 docflow 事件字段注入**:`Environment/ProjectID` 从 Principal 与命令上下文取值,禁止硬编码 `"dev"`/`0`;可加 archtest 规则(production 禁止 `Environment: "dev"` 字面量出现在 envelope 构造)。
|
||||
### 并发
|
||||
|
||||
- `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。
|
||||
|
||||
### P1 结构解耦(消除"一处改、多处坏")
|
||||
### 历史数据
|
||||
|
||||
3. **绞杀 bizdev**:删除 `Service` 上的 `Pool()/CAS()/ContextManager()` 等 locator 访问器,组合根直接装配具体服务;`ExecuteTask/ExecuteStage/InspectWorkspace` 全面移交 `app/stageflow`;`coordinator.StageTaskRunner` 改用 stageflow 自有请求/结果类型,切断对 `bizdev.*` 传输类型的依赖。目标:bizdev 退化为纯领域包(docduty/stage_access 等)或拆散归零。
|
||||
4. **打破 docgov↔docrevision 循环**:共享类型提升到 `contracts/vocabulary`(仅无行为值对象)或改为消费者端口;随后在 boundaries.yaml 中互相移出 allowlist 并转 block。
|
||||
5. **收编 `internal/chat`**:把剩余编排并入 `app/chatflow`,chat 包依赖从 11 收敛到端口集合。
|
||||
6. **解除 `intent → bizdev`**:与架构表对齐,intent 只依赖 vocabulary(现为豁免债)。
|
||||
旧记录可能含 project 0、错误 environment、未知 consumer、未知 payload schema 或稀疏 aggregate version。启用 live claim 前必须生成 manifest,并分类 safe/repair/quarantine/expire。任何修复保留 old/new digest、operator、reason、approval;本计划不删历史数据。
|
||||
|
||||
### P2 契约完善(对外接口收口)
|
||||
### 权限
|
||||
|
||||
7. **path/sql_write 例外按期清零转 block**(2026-09-28 / 2026-10-12 到期,owner 已登记);到期未清零的按 archtest 语义直接红。
|
||||
8. **HTTP 错误信封统一**(deferred 项单独立项):typed `VERSION_CONFLICT`/`IDEMPOTENCY_CONFLICT` 已有领域错误,补 wire 映射规范。
|
||||
9. **PI Runner 协议 v2**(deferred 项单独立项):以 RunManifest schema 为基础定义 typed result 契约 + JSON Schema 入 `configs/schemas/`,替换 stdout/result.json 解析;保留 `/v1/run|cancel|search|health` + Bearer 传输不变。
|
||||
10. **事件 producer/consumer allowlist 落地为 yaml**(架构文档 §9.1 已规划):event name → producer/consumer 映射进 `module-boundaries.yaml`,archtest 校验,防运行时动态注册旁路。
|
||||
后台 consumer 使用按 env/consumer/action 约束的 service principal。处理事件时按 ProjectID/DocID 重读资源归属、成员/duty、workflow config revision、活动 stage 和当前状态。事件 actor 只用于审计,不能把历史用户权限带到延迟执行时。
|
||||
|
||||
### 关于"要不要全面 IPC/RPC 化"的总体建议
|
||||
Replay 必须是应用用例:管理员 capability、精确范围、reason/approval、dry-run plan digest、apply exact digest 和不可变审计。多项目或批量 apply 需要操作者与批准人分离。
|
||||
|
||||
- **不建议**把单体内的端口调用改成 RPC:ADR 与 KTD1–KTD12 的判断在当前规模下成立——进程内端口 + archtest 门禁 + 带版本契约已实现"改一处不扩散"(import 违规 0、单一写者、schema 版本 + SHA 校验),RPC 只会引入序列化、部分失败、延迟与运维成本。
|
||||
- **值得保持/推进的进程边界**恰好是三条已有/已规划的:PI Runner(已独立容器 + HTTP 契约)、durable dispatcher 独立进程(`cmd/events`,本次 P0-1)、FAV 发布 worker(U7 后续)。
|
||||
- 若未来确需拆服务,先决条件清单即 P2 三项:错误信封、PI 协议 schema 化、事件 allowlist——完成后每条进程边界都有显式契约。
|
||||
日志、dead-letter 和 reconciliation 只能保存 ID、digest、typed error code 与字段 allowlist 生成的摘要,不能保存原始 payload、正文、SQL error、绝对路径、token 或 prompt。
|
||||
|
||||
## 证据
|
||||
## 5. 优先级建议
|
||||
|
||||
| 项 | 路径/命令 | 结果 |
|
||||
|----|-----------|------|
|
||||
| 架构决策 | `.doc/adr/2026-09-14-modular-monolith-decoupling.md`、`.doc/system-design/2026-09-14-module-decoupling-architecture.md` | 模块化单体;非目标含"不拆微服务" |
|
||||
| 静态门禁 | `scripts/arch-check.sh` + `internal/archtest` | `--mode block` 通过;import/event=0;path=16、sql_write=5 例外 |
|
||||
| 里程碑状态 | `.doc/status/FEATURE-MATRIX.md:30`、CURRENT | U5–U12 已合入 `dev@bf59cce`(schema 38);path/sql_write 例外保留 |
|
||||
| PI Runner 协议 | `deploy/pi-agent/runner.mjs:81-89,319-405` | Bearer 鉴权 + 4 端点 |
|
||||
| 事件信封/投递 | `internal/events/envelope.go`、`bus.go`、`pg.go` | schema 1 + fencing + inbox;无生产 dispatcher 装配点 |
|
||||
| 闭包桥 | `internal/app/docnotify/subscriber.go:30-36`、`internal/docgov/engine.go:39-53`、`internal/app/app.go:170-208` | OnOutbox / AddOnApprovedHook 进程内直绑 |
|
||||
| bizdev locator | `internal/bizdev/service.go:229-260` | Pool/CAS/DocGov 等 8 个访问器 |
|
||||
| 扇出统计 | `grep` import 扫描(生产包) | bizdev 被 12 包 78 处引用;chat 11 包;coordinator 10 包;ctxmgr 5 包 56 处 |
|
||||
| 双向依赖 | `module-boundaries.yaml` | docgov↔docrevision 互在 allowlist |
|
||||
| 事件字段硬编码 | `internal/app/docflow/commands.go:160-177` | `Environment:"dev"`、`ProjectID:0` |
|
||||
| RunManifest | `internal/taskrun/manifest.go` | schema 1 + canonical + SHA-256 |
|
||||
### 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。
|
||||
|
||||
- `projection`/`fav` 两个已声明的 outbox 消费者当前没有任何注册实现——dispatcher 接线时需先确认 projection subscriber(workspace 投影重建)归属哪个用例包。
|
||||
- FAV 分支 `feature/final-artifact-vault` 未整支合入(KTD12 要求先审后用);U7 降级读取依赖它,需单独排期审计。
|
||||
- `*pgxpool.Pool` 跨包传递(bizdev.Pool() 暴露)是否已被 archtest 覆盖未见显式规则;绞杀 bizdev 时应同步补规则,防止 locator 以新形式回潮。
|
||||
### 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` |
|
||||
|
||||
## 建议动作
|
||||
|
||||
1. 立项 P0-1(durable dispatcher 接线 + 闭包桥下线)为下一个 short-term 任务,占 `events`/`app` mutex。
|
||||
2. P0-2 可作为小修复随 P0-1 同批提交。
|
||||
3. P1-3(bizdev 绞杀)建议拆为多支 short-term,先从删除 locator 访问器开始(编译器会列出全部受影响点,天然的工作清单)。
|
||||
4. P2 三项各走独立 remediation 计划(与既有 deferred 清单一致,避免与在途任务抢 mutex)。
|
||||
|
||||
下一项只立 Track E 的 E0A:事件生产、契约与历史数据门。Dispatcher 必须保持 off,直到 PG 测试证明事件源和旧数据分类正确。完整执行计划见 [Phase 2 持久事件交付与后续解耦路线](../../remediation/2026-09-15-module-decoupling-ipc-phase2-remediation-plan.md)。
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
---
|
||||
title: "Track E 持久事件交付"
|
||||
status: planned
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
owner: TBD
|
||||
branch: fix/event-production-scope-contract
|
||||
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. [ ] E0A 单独建 short-term/分支,dispatcher 保持 off。
|
||||
2. [ ] E0A 报告通过后再认领 E0B。
|
||||
3. [ ] 依次交付 E1A notify、E1B workflow advance、E1C projection;每步独立 go/no-go。
|
||||
4. [ ] 一个兼容发布窗口后 contract 删除闭包 API。
|
||||
5. [ ] 同步 test report、CURRENT、FEATURE-MATRIX、gap-matrix。
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [ ] 满足 [Phase 2 Track E Definition of Done](../../remediation/2026-09-15-module-decoupling-ipc-phase2-remediation-plan.md#track-e-definition-of-done)。
|
||||
- [ ] 每个波次拥有独立 owner、mutex、分支、报告和回滚证据。
|
||||
- [ ] 未把计划、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: 待实施
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
本条只建立执行入口,不代表已批准 E0A 或已认领 mutex。实施前必须按 CURRENT 检查冲突并从当时最新 dev 建分支。
|
||||
@@ -0,0 +1,56 @@
|
||||
---
|
||||
title: "HTTP 与 SSE 公开错误信封整改"
|
||||
status: planned
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
---
|
||||
|
||||
# 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: 实施前另建
|
||||
- gap-matrix 行: 当前为工程债,不单独作为 Track E 发布 blocker
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: "模块解耦 Phase 2 整改方案(事件消费接线、bizdev 绞杀、双向依赖破环与契约收口)"
|
||||
title: "模块解耦 Phase 2:持久事件交付与后续解耦路线"
|
||||
status: planned
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
@@ -7,255 +7,336 @@ type: refactor
|
||||
owner: TBD
|
||||
---
|
||||
|
||||
# 模块解耦 Phase 2 整改方案
|
||||
# 模块解耦 Phase 2:持久事件交付与后续解耦路线
|
||||
|
||||
## 背景
|
||||
## 决策摘要
|
||||
|
||||
- 调研与耦合清点:[2026-09-15 模块解耦与 IPC/RPC 交互现状评估](../ops/research/2026-09-15-module-decoupling-ipc-assessment.md)(下称"调研报告")。
|
||||
- 上位约束:[模块化单体解耦 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)(U1–U12 已合入 `dev@bf59cce`,path/sql_write 例外保留)。
|
||||
- 调研结论:静态边界(import/event)已 block 清零,但事件链路**只写不消费**、bizdev 仍是 service locator 枢纽、docgov↔docrevision 双向 import、chat/coordinator 扇出过大、两项 deferred 契约债(HTTP 错误信封、PI Runner 结果协议)未立项。本方案即 Phase 1 "Deferred to Follow-Up Work" 的正式接续。
|
||||
Phase 2 的核心交付只包含持久事件链:修正事件生产、补齐 PostgreSQL 投递实现、用无副作用 shadow 对账替换闭包桥,并以授权用户刷新/重启后的正文恢复作为停走门。
|
||||
|
||||
## Goal Capsule
|
||||
结构解耦(D4–D7)是独立轨道;HTTP 错误信封与 PI Runner typed result 各自单独立项。三条轨道分别验收,不能互相阻塞关闭。
|
||||
|
||||
- **Objective:** 让模块间副作用全部经持久事件可恢复、可重放、可审计;消除 bizdev locator 与双向依赖两类结构性耦合;把剩余对外契约(HTTP 错误、PI 结果协议、事件 allowlist)显式化。
|
||||
- **Means:** durable dispatcher 接线并 shadow 对账后下线闭包桥;编译器驱动的 bizdev 访问器移除;vocabulary 提升破环;allowlist 落地为 archtest 规则。
|
||||
- **Authority:** 上列 ADR / 架构文档 / Phase 1 计划;本方案不推翻其任何 KTD,只接续未完成项。
|
||||
- **Stop condition:** 任一波次出现"事件至少一次语义无法与现有闭包副作用等价"、"bizdev 移除导致行为回归无法用 characterization 锁定"、或"错误信封变更破坏既有前端契约"时,停止扩面回设计评审。
|
||||
- **Execution profile:** 高风险、跨模块、事件与授权敏感;characterization-first,逐波次独立 short-term / 分支 / 验收。
|
||||
- **Delivery:** 每个单元独立验收报告;本方案本身不授权合并、部署或删数据。
|
||||
本计划不拆微服务,不引入外部消息基础设施,不合入 FAV 分支,不删除历史数据,也不授权实施、合并或部署。
|
||||
|
||||
## Scope
|
||||
## 背景与纠偏
|
||||
|
||||
**包含**:调研报告 P0(D1–D3)、P1(D4–D7)、P2(D8–D10)。
|
||||
- 上位约束:[模块化单体解耦 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,会得到虚假的零差异。
|
||||
|
||||
**不包含**(已有 owner,不重复立项):
|
||||
- path 16 条 / sql_write 5 条例外清零——归 U4(2026-09-28)/ U5(2026-10-12)里程碑 owner。
|
||||
- FAV 分支 `feature/final-artifact-vault` 审计与整支合入——归 KTD12 独立流程。
|
||||
- 微服务拆分与跨服务消息基础设施——维持 ADR 非目标。
|
||||
## 目标与边界
|
||||
|
||||
## Requirements
|
||||
### Track E:持久事件交付(本计划核心)
|
||||
|
||||
- **R1(事件可恢复)** projection/notify/fav 三类消费者的副作用在进程崩溃、重启、重复投递后恰好一次;delivery 表可查每次 attempt/lease/fencing。
|
||||
- **R2(闭包桥下线)** `docrevision.Service.OnOutbox` 与 `docgov` `OnApprovedHook(s)` 不再被生产代码注册;等价行为由事件消费者提供,shadow 对账零差异后才切换。
|
||||
- **R3(事件字段真实)** envelope 的 `Environment/ProjectID` 来源于服务端上下文,production 禁止硬编码字面量。
|
||||
- **R4(无 locator)** 生产包之间不传递 `*pgxpool.Pool`;`bizdev.Service` 不再暴露 `Pool()/CAS()/ContextManager()/DocGov()/DocRevision()/ProjectWorkflow()/FreeformDoc()/KB()`。
|
||||
- **R5(单向依赖)** `docgov` 与 `docrevision` 互不 import 对方实现;共享类型只经 vocabulary/端口。
|
||||
- **R6(扇出收敛)** `internal/chat` 并入 `app/chatflow` 或其依赖降到端口集合;`intent` 不再依赖 `bizdev`。
|
||||
- **R7(错误信封)** HTTP 错误响应有统一 typed 信封(含 `VERSION_CONFLICT`/`IDEMPOTENCY_CONFLICT` 映射),前端按信封分支,breaking change 走 ADR。
|
||||
- **R8(PI 结果协议)** Runner 结果以带 schema 版本的 typed JSON 契约交付(JSON Schema 入 `configs/schemas/`),stdout/result.json 解析仅作 legacy 兼容一个发布窗口。
|
||||
- **R9(事件 allowlist)** event name → producer/consumer 映射进 `module-boundaries.yaml`,archtest 校验;无运行时动态注册旁路。
|
||||
- **R10(门禁收紧)** 每个单元完成后把对应规则加入 `block_kinds` 或新增规则;新违规立即 block,不带无主例外。
|
||||
- **R11(兼容迁移)** 闭包→事件、错误信封、PI 协议均 expand → shadow → switch → contract,保留一个发布窗口的旧路径。
|
||||
- **R12(行为等价证据)** 每波次交付前提供 characterization 基线(旧路径行为快照)+ 切换后 diff 为零或差异逐条解释。
|
||||
目标:让 notify 与 projection 副作用在重复投递、进程崩溃、租约过期和重启后达到“至少一次投递、恰好一个可见结果”,并能从数据库追查每次 attempt。
|
||||
|
||||
## Planning Contract
|
||||
包含 D1、D2、D3、D10、D11。Track E 完成后即可单独关闭,不等待结构或协议轨道。
|
||||
|
||||
### Key Technical Decisions
|
||||
### Track S:结构解耦(后续独立 go/no-go)
|
||||
|
||||
- **KTD1(dispatcher 先行,桥后下线)。** 先接线 dispatcher 与消费者并 shadow 运行(闭包与事件双写、只以闭包为准),对账连续 N 天零差异后才删除闭包注册;不允许直接切换。
|
||||
- **KTD2(编译器驱动绞杀)。** 删除 bizdev 访问器是原子提交,编译错误清单即受影响点工作清单;禁止"保留访问器但少用"的半吊子状态。
|
||||
- **KTD3(vocabulary 只放无行为类型)。** 破环时共享类型提升到 vocabulary 包仅限枚举/值对象;带方法的类型改消费者端口,不得把 vocabulary 变成新垃圾桶。
|
||||
- **KTD4(传输类型与用例同包)。** `stageflow` 定义自己的请求/结果类型,coordinator 依赖该端口而非 `bizdev.*` DTO;一对一端口留在消费者包(沿用 Phase 1 §2.2 契约分类)。
|
||||
- **KTD5(错误信封 additive 优先)。** 新信封字段 additive;旧客户端忽略未知字段不破坏;状态码语义变化走 ADR + 前端同步发布。
|
||||
- **KTD6(PI 协议双轨一个窗口)。** `/v1/run` 响应同时携带 legacy 字段与 typed result(RunManifest 风格 schema v1);服务端优先解析 typed,解析失败按 legacy;一个发布窗口后删除 legacy。
|
||||
- **KTD7(allowlist 即代码)。** producer/consumer 映射与 import allowlist 同文件同规则同门禁,不另建运行时注册机制。
|
||||
- **KTD8(逐消费者灰度)。** 事件消费者按 notify → projection → fav 顺序逐个上线(风险与可观测性递增),每个消费者独立验收,不整批切换。
|
||||
目标:移除 bizdev locator,收敛 stageflow/chat/intent 依赖,并消除 `docgov → docrevision` 的剩余工具依赖。包含 D4、D5、D6、D7a、D7b。
|
||||
|
||||
### High-Level Topology(目标态)
|
||||
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 TB
|
||||
UC[app use cases] -->|Append envelope| OB[(PG outbox + delivery)]
|
||||
WK[cmd/events dispatcher] -->|claim SKIP LOCKED| OB
|
||||
WK --> N1[notify consumer]
|
||||
WK --> N2[projection consumer]
|
||||
WK --> N3[fav consumer]
|
||||
N1 --> Notif[notification]
|
||||
N2 --> WS[workspace projection]
|
||||
N3 --> FAV[artifactvault]
|
||||
SF[app/stageflow] -->|ports| DOM[domain modules]
|
||||
CO[coordinator] -->|StageTaskRunner port| SF
|
||||
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
|
||||
```
|
||||
|
||||
## Phased Delivery
|
||||
## 数据模型与并发协议
|
||||
|
||||
| 波次 | 交付边界 | 单元 | 进入条件 | 退出/停走门 |
|
||||
|---|---|---|---|---|
|
||||
| W0 | 事件消费接线 + 字段修正 | D1, D3 | 在途 mutex 不冲突;占 `events`/`app` | dispatcher 双 worker 并发 claim 无双 owner;shadow 对账启动 |
|
||||
| W1 | 闭包桥下线 | D2, D10 | W0 shadow 连续零差异(建议 ≥3 天 dev 流量) | R1/R2/R9 全 PASS;hook 注册代码删除 |
|
||||
| W2 | bizdev 绞杀 | D4, D5 | W1 完成;占 `bizdev`/`stageflow`/`coordinator` | R4 PASS;`go list` 证明 bizdev 出口只剩领域类型 |
|
||||
| W3 | 双向破环 + 扇出收敛 | D6, D7 | W2 完成;逐个占 `docgov`/`docrevision`/`chat`/`intent` | R5/R6 PASS;boundaries.yaml 互相移出并 block |
|
||||
| W4 | 契约收口(独立 go/no-go) | D8, D9 | W0–W3 复盘批准;各占 `server`/`taskrun`+`deploy/pi-agent` | R7/R8 PASS;前端与 Runner 双轨窗口开闭明确 |
|
||||
### Delivery 状态机
|
||||
|
||||
W0–W1 是首个批准范围;W2–W4 需前一波次验收报告后重新 go/no-go,不构成一次性整体授权。
|
||||
```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 阻塞。
|
||||
|
||||
## Implementation Units
|
||||
### 副作用原子性
|
||||
|
||||
### Unit Index
|
||||
|
||||
| ID | 标题 | 主要文件 | 依赖 | 对应调研项 |
|
||||
|---|---|---|---|---|
|
||||
| D1 | dispatcher worker 与消费者注册 | `cmd/events/main.go`、`internal/events/pg.go`、`internal/app` | 无 | P0-1 |
|
||||
| D2 | 闭包桥 shadow 对账与下线 | `internal/docrevision/service.go`、`internal/docgov/engine.go`、`internal/app/app.go`、`internal/app/docnotify` | D1 | P0-1 |
|
||||
| D3 | docflow 事件字段注入 + archtest 规则 | `internal/app/docflow/commands.go`、`internal/archtest` | 无 | P0-2 |
|
||||
| D4 | bizdev locator 访问器移除 | `internal/bizdev/service.go`、全部调用方 | D2(避免同批改 app) | P1-3 |
|
||||
| D5 | stageflow 接管与 coordinator 解绑 | `internal/app/stageflow`、`internal/coordinator/engine.go` | D4 | P1-3 |
|
||||
| D6 | docgov↔docrevision 破环 | `internal/contracts/vocabulary`(新)、docgov/docrevision | 无硬依赖,建议 W2 后 | P1-4 |
|
||||
| D7 | chat 收编与 intent 解绑 | `internal/chat`、`internal/app/chatflow`、`internal/intent` | D4 | P1-5/6 |
|
||||
| D8 | HTTP 错误信封统一 | `internal/server`、`internal/stream/transport`、`web/src` | 独立 | P2-8 |
|
||||
| D9 | PI Runner 协议 v2 | `deploy/pi-agent/runner.mjs`、`internal/taskrun`、`configs/schemas` | 独立 | P2-9 |
|
||||
| D10 | 事件 producer/consumer allowlist | `module-boundaries.yaml`、`internal/archtest` | D1 | P2-10 |
|
||||
|
||||
### D1. dispatcher worker 与消费者注册
|
||||
|
||||
- **Goal:** 让 outbox 事件有真实消费者在跑,副作用可恢复、可审计。
|
||||
- **Requirements:** R1、R10;KTD1、KTD8。
|
||||
- **Files:** `cmd/events/main.go`(新)、`internal/events/pg.go`(补 pool 版 Claim/Apply 封装与 dead-letter 落库)、`internal/events/dispatcher.go`(新,worker 循环)、`internal/app/app.go`(Runtime.Start 注册 worker 生命周期)。
|
||||
- **Approach:**
|
||||
1. worker:`ClaimIDs(consumer, limit)`(已有 `FOR UPDATE SKIP LOCKED`)→ 逐条调用注册的 consumer handler → `Apply` ack/fail;fail 走退避与 `MaxAttempts` 死信。
|
||||
2. 消费者按 KTD8 顺序上线:先 `notify`(等价 docnotify.Subscriber.Handle 行为),再 `projection`,最后 `fav`。
|
||||
3. W0 阶段消费者只写 side-effect 审计日志 + inbox receipt,不产生业务可见变化(shadow 态)。
|
||||
4. 生产先内嵌 Runtime goroutine 托管;独立进程 `cmd/events` 在 W4 后评估。
|
||||
- **Test scenarios:** 双 worker 并发 claim 无双 lease;worker 在副作用后 ack 前崩溃重启恰好一次;一个消费者 permanent failure 不阻塞其他消费者;lease 过期后旧 worker ack 被 fencing token 拒绝;aggregate version gap 等待不跳号。
|
||||
- **Verification:** PG 集成测试(`TEST_DATABASE_URL`)全绿;dev shadow 运行日志含 delivery attempt 记录。
|
||||
|
||||
### D2. 闭包桥 shadow 对账与下线
|
||||
|
||||
- **Goal:** 删除 `docrevision.OnOutbox` 与 `docgov OnApprovedHook(s)` 的生产注册,行为由事件消费者等价提供。
|
||||
- **Requirements:** R2、R11、R12;KTD1。
|
||||
- **Files:** `internal/docrevision/service.go:38,535,682`、`internal/docgov/engine.go:39-69`、`internal/app/app.go:170-208`(bindWorkflowApprovalHook/onWorkflowDocumentApproved)、`internal/app/docnotify/subscriber.go`。
|
||||
- **Approach:**
|
||||
1. characterization:对 `document.agent_candidate_ready`、`document.downstream_impact_detected`、批准→阶段推进→`EmitStageReadyToAdvance` 三条链录制旧路径行为快照(收件人、去重键、payload)。
|
||||
2. shadow:事件消费者与闭包同时执行,闭包结果为准,消费者结果入对账表;dev 连续 ≥3 天 diff=0。
|
||||
3. 切换:删除闭包注册;批准→阶段推进改为消费 `document.approved` 类事件。
|
||||
4. contract:一个发布窗口后删除 `OnOutbox` 字段与 hook 方法本体。
|
||||
- **Test scenarios:** 崩溃重启后批准通知不丢;同一事件重复投递不重复通知(inbox 幂等);对账 diff≠0 时切换被停走门拦截;删除注册后 grep 生产代码无 `AddOnApprovedHook(` 调用。
|
||||
- **Verification:** R2 PASS;架构文档 §9.2 行为门禁(worker 崩溃/lease 过期/重复投递)PASS;test report 归档。
|
||||
|
||||
### D3. docflow 事件字段注入 + archtest 规则
|
||||
|
||||
- **Goal:** envelope 的 `Environment/ProjectID` 反映真实上下文。
|
||||
- **Requirements:** R3、R10。
|
||||
- **Files:** `internal/app/docflow/commands.go:160-183`、`internal/taskrun/finalize.go`(核对同问题)、`internal/archtest/scan.go`(新增规则:production 禁止 `Environment: "dev"` 字面量出现在 envelope 构造)。
|
||||
- **Approach:** Principal/命令结构携带 environment 与 projectID(从 docgov record 取),构造 envelope 时注入;缺 projectID 时 fail closed 拒绝发布而非填 0;archtest 规则随 PR 转 block。
|
||||
- **Test scenarios:** test/main 环境发布事件 environment 正确;缺 projectID 拒绝发布;archtest 迷你仓违规样例报错。
|
||||
- **Verification:** 新规则入 `block_kinds`;单测 + archtest 双绿。
|
||||
|
||||
|
||||
### D4. bizdev locator 访问器移除
|
||||
|
||||
- **Goal:** 消灭 service locator,模块只能经端口拿能力。
|
||||
- **Requirements:** R4、R10;KTD2。
|
||||
- **Files:** `internal/bizdev/service.go:229-260`(8 个访问器)、全部调用方(编译器列出)、`internal/app/app.go`(组合根直接构造各服务)、`module-boundaries.yaml`(新增规则:生产包间禁传 `*pgxpool.Pool`/`pgx.Tx`)。
|
||||
- **Approach:**
|
||||
1. characterization 锁定 `ExecuteTask/ExecuteStage` 关键行为。
|
||||
2. 组合根直接持有 `docgov`、`docrevision`、`projectworkflow`、`kb`、`storage.CAS` 等构造结果(部分已具备,如 `authStores`、`wfDefSvc`)。
|
||||
3. 原子删除 8 个访问器;逐调用方改为构造注入或端口;必要时按访问器分两批(先 `Pool()/CAS()`,后服务 getter)。
|
||||
4. archtest 新规则转 block。
|
||||
- **Test scenarios:** 编译零错误即范围闭合;`go vet`/`-short` 全绿;跨包无 `Pool()` 调用残留;archtest 迷你仓样例(跨包传 pool)被 block。
|
||||
- **Verification:** R4 PASS;受影响文件清单进 test report。
|
||||
|
||||
### D5. stageflow 接管与 coordinator 解绑
|
||||
|
||||
- **Goal:** 任务/阶段执行用例 owner 是 `app/stageflow`;coordinator 只依赖其端口与自有类型。
|
||||
- **Requirements:** R4(延伸);KTD4。
|
||||
- **Files:** `internal/app/stageflow/usecase.go`(扩展)、`internal/coordinator/engine.go:83-88`(StageTaskRunner 词汇替换)、`internal/bizdev/service.go:1071+`(编排迁移源)。
|
||||
- **Approach:** stageflow 定义本包 `TaskRunRequest/StageRunRequest` 类型;bizdev 同名类型 deprecated 一个窗口;coordinator 端口签名改用 stageflow 类型;迁移后 bizdev 保留纯领域逻辑(docduty 解析、stage_access、质量门禁)。
|
||||
- **Test scenarios:** coordinator/stageflow/bizdev 现有测试全绿无行为 diff;`go list -deps` 证明 coordinator 不再 import bizdev 实现。
|
||||
- **Verification:** coordinator import 列表收敛进 boundaries.yaml 并 block。
|
||||
|
||||
### D6. docgov↔docrevision 破环
|
||||
|
||||
- **Goal:** 两个写者模块类型层单向化。
|
||||
- **Requirements:** R5;KTD3。
|
||||
- **Files:** `internal/contracts/vocabulary`(新包,仅无行为枚举/值对象)、`internal/docgov`、`internal/docrevision`、`module-boundaries.yaml`。
|
||||
- **Approach:** 实施前先出符号级双向 import 清单(调研仅确认包级事实);值对象提升 vocabulary,带方法类型改消费者端口;随后互相移出 allowlist 转 block。
|
||||
- **Test scenarios:** archtest 对新增互相 import 立即报错;两包测试全绿。
|
||||
- **Verification:** boundaries.yaml 中两者互不出现;规则 block。
|
||||
|
||||
### D7. chat 收编与 intent 解绑
|
||||
|
||||
- **Goal:** `internal/chat` 编排并入 `app/chatflow`;`intent` 只依赖 vocabulary。
|
||||
- **Requirements:** R6。
|
||||
- **Files:** `internal/chat/*.go`、`internal/app/chatflow/`、`internal/intent/`、`module-boundaries.yaml`。
|
||||
- **Approach:** chat 剩余编排逐个挂到 chatflow 用例(U10 已完成 chatlog/contextasm 端口,本轮只搬编排);`intent→bizdev` 引用点改为注入只读端口;boundaries 收紧。
|
||||
- **Test scenarios:** chat handler 测试全绿;intent 测试不再构造 bizdev;`chat` 包消失或只剩端口。
|
||||
- **Verification:** 扇出复测:chat ≤ 端口集合,intent = vocabulary。
|
||||
|
||||
### D8. HTTP 错误信封统一
|
||||
|
||||
- **Goal:** 对外错误响应统一 typed 信封。
|
||||
- **Requirements:** R7、R11;KTD5。
|
||||
- **Files:** `internal/server`(信封类型与 handler 收敛)、`internal/stream/transport`(SSE error frame)、`web/src/api`(解析层)、ADR(状态码语义变更时)。
|
||||
- **Approach:** 信封含 `code`(typed:`VERSION_CONFLICT`/`IDEMPOTENCY_CONFLICT`/`VALIDATION`/`AUTHZ` 等)、`message`、`details?`;先 additive(新旧并存),前端按 code 分支迁移;contract 阶段删旧文本匹配;SSE error frame 同步定义。
|
||||
- **Test scenarios:** 全量路由错误响应符合信封 schema(golden 文件);前端 e2e 版本冲突/幂等冲突分支;未识别 code 的客户端 fail closed。
|
||||
- **Verification:** wire 契约测试入 CI;ADR 归档。
|
||||
|
||||
|
||||
### D9. PI Runner 协议 v2
|
||||
|
||||
- **Goal:** Runner 结果从 stdout/result.json 升级为带版本的 typed JSON。
|
||||
- **Requirements:** R8、R11;KTD6。
|
||||
- **Files:** `deploy/pi-agent/runner.mjs`(响应扩展)、`configs/schemas/pi-run-result-v1.json`(新)、`internal/taskrun`(结果解析器)、`internal/agent`(backend 适配)、`deploy/pi-agent/tests/`。
|
||||
- **Approach:** `/v1/run` 响应新增 `result_v1`(对齐 RunManifest 风格:schema_version、run_id、members[]、digest、error 分类、retryable);服务端优先 typed、失败回退 legacy;JSON Schema 校验入 CI;一个发布窗口后删 legacy 解析。
|
||||
- **Test scenarios:** stub/真实 Runner 双轨输出一致;未知 schema major fail closed;敏感字段扫描(不含 token/prompt);legacy 窗口到期后解析删除。
|
||||
- **Verification:** 真实 PI E2E(`RUN_PI_E2E=1`)在 dev 验证 v2 路径;schema 文件入仓。
|
||||
|
||||
### D10. 事件 producer/consumer allowlist
|
||||
|
||||
- **Goal:** 事件名与生产者/消费者的映射成为机器可执行契约。
|
||||
- **Requirements:** R9、R10;KTD7。
|
||||
- **Files:** `.doc/system-design/module-boundaries.yaml`(新增 `event_producers:`/`event_consumers:` 段)、`internal/archtest`(扫描 envelope 构造点与消费者注册点)。
|
||||
- **Approach:** 以 D1/D2 落地后的事件集合生成初始映射(`document.agent_version_committed`→docflow、`document.agent_candidate_ready`→docrevision、批准类→docgov、finalize 类→taskrun,实施时以代码为准);archtest 校验 producer 构造点包名一致、消费者注册无映射外条目。
|
||||
- **Test scenarios:** 迷你仓新增未登记 producer/consumer 被 block;映射变更需同时改 yaml 与代码。
|
||||
- **Verification:** 规则入 block;event findings 持续为 0。
|
||||
|
||||
---
|
||||
|
||||
## Mutex 与分支安排
|
||||
|
||||
| 单元 | mutex | 建议分支 |
|
||||
| 消费者 | 可见结果契约 | 崩溃窗口处理 |
|
||||
|---|---|---|
|
||||
| D1/D3 | events + app | `feature/events-dispatcher-wiring` |
|
||||
| D2 | app + docnotify | `fix/closure-bridge-offline` |
|
||||
| D4 | bizdev | `refactor/bizdev-locator-removal` |
|
||||
| D5 | stageflow + coordinator | `refactor/stageflow-takeover` |
|
||||
| D6 | docgov + docrevision | `refactor/docgov-docrevision-uncycle` |
|
||||
| D7 | chat + intent | `refactor/chat-chatflow-merge` |
|
||||
| D8 | server | `feature/http-error-envelope` |
|
||||
| D9 | taskrun + deploy/pi-agent | `feature/pi-runner-protocol-v2` |
|
||||
| D10 | arch | `feature/event-allowlist`(可与 D2 同批) |
|
||||
| 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 契约 |
|
||||
|
||||
每单元独立 short-term 条目 + 独立验收报告;合回 dev 占集成槽位并跑默认冒烟(`go vet`、`go test -short`、`env-service.sh dev rebuild`、health)。
|
||||
副作用完成后、delivery ack 前必须注入崩溃。恢复后可重复调用 handler,但最终只有一个可见结果。
|
||||
|
||||
## 验收标准(Definition of Done)
|
||||
### 审计表
|
||||
|
||||
- [ ] R1–R12 逐条有证据链接;W0–W4 各有独立 test report 归档 `.doc/test-reports/`。
|
||||
- [ ] 生产代码 grep 无 `OnOutbox =`、无 `AddOnApprovedHook(` 注册点;delivery 表可查全部事件副作用。
|
||||
- [ ] bizdev 出口仅领域类型;跨包无 `*pgxpool.Pool` 传递;coordinator 不 import bizdev 实现。
|
||||
- [ ] docgov/docrevision 互不 import;`intent` 依赖只剩 vocabulary;chat 编排全部在 chatflow。
|
||||
- [ ] HTTP 错误信封与 PI result v2 各有 schema/golden 测试与 ADR(如涉 breaking)。
|
||||
- [ ] `module-boundaries.yaml` 新规则全部 block;新 findings=0;例外均有 owner/到期日。
|
||||
- [ ] arch-check `--mode block`、`go test -short ./...`、PG 集成在 CI 全绿。
|
||||
- [ ] CURRENT / FEATURE-MATRIX / gap-matrix 与本计划状态一致。
|
||||
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 不要求其实现完成。
|
||||
|
||||
## 风险与控制
|
||||
|
||||
| 风险 | 控制 |
|
||||
|---|---|
|
||||
| 事件切换重复/丢通知 | KTD1 shadow 对账 + 停走门;inbox 幂等测试先行 |
|
||||
| bizdev 原子删除波及面失控 | KTD2 编译器清单即范围;先 characterization;可按访问器分两批 |
|
||||
| vocabulary 变垃圾桶 | KTD3 只允许无行为类型;评审含"新增类型无方法"检查 |
|
||||
| 错误信封破坏旧前端 | KTD5 additive + golden + 前端同步窗口 |
|
||||
| PI v2 与真实 Runner 漂移 | KTD6 双轨 + `RUN_PI_E2E=1` 真实验收,禁止 stub 冒充 |
|
||||
| 与 U4/U5 到期(09-28/10-12)撞车 | D6 与 path 例外清理批次属主协调排期,避免同占 docgov/docrevision |
|
||||
| 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/调研: [模块解耦与 IPC/RPC 交互现状评估](../ops/research/2026-09-15-module-decoupling-ipc-assessment.md)
|
||||
- 上位设计: [模块化单体解耦架构](../system-design/2026-09-14-module-decoupling-architecture.md) · [ADR](../adr/2026-09-14-modular-monolith-decoupling.md)
|
||||
- Phase 1: [模块解耦与文档可靠性重构计划](./2026-09-14-module-decoupling-refactor-plan.md)
|
||||
- gap-matrix 行: ARCH-DECOUPLE-PHASE2
|
||||
|
||||
- [方案审阅](../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,58 @@
|
||||
---
|
||||
title: "PI Runner typed-result-v1 迁移方案"
|
||||
status: planned
|
||||
created: 2026-09-15
|
||||
updated: 2026-09-15
|
||||
---
|
||||
|
||||
# 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 放入结果或公开日志。
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [ ] Schema/golden 在 Runner 与 Go 两侧共享并入 CI。
|
||||
- [ ] typed-present-invalid 永不 fallback;handshake downgrade attack 负例通过。
|
||||
- [ ] 并发 run/result 串线、cancel/result 竞争、超限与 path escape 负例通过。
|
||||
- [ ] 真实 PI E2E 覆盖成功、typed error、取消、超时与未知 schema。
|
||||
- [ ] 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: 实施前另建
|
||||
- gap-matrix 行: 当前为工程债,不单独作为 Track E 发布 blocker
|
||||
@@ -4,7 +4,9 @@
|
||||
|------|------|
|
||||
| [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:dispatcher 接线与闭包桥下线、bizdev locator 绞杀、docgov↔docrevision 破环、HTTP 错误信封与 PI Runner 协议 v2(调研见 [../ops/research/2026-09-15-module-decoupling-ipc-assessment.md](../ops/research/2026-09-15-module-decoupling-ipc-assessment.md)) |
|
||||
| [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 |
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
**分支**: dev
|
||||
**production_ready**: no(CI 真实 PI 三工作流 E2E / 前端人工抽检未完成。`CHAT-INTENT-STATE` 双标签 busy 已 PASS。文档账本运行时 UI Round20 已 PASS,不把 fallback 报告当成完整 PI)
|
||||
**协作焦点**: [../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 再审计」区段。
|
||||
|
||||
@@ -70,8 +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);[M1 停止扩面](../test-reports/2026-09-14-document-reliability-pilot-test-report.md);[M1 活验](../test-reports/2026-09-14-document-reliability-pilot-live-test-report.md);[M2](../test-reports/2026-09-14-document-reliability-m2-test-report.md);[M3 U8](../test-reports/2026-09-15-taskrun-runmanifest-u8-test-report.md);[M3 U9](../test-reports/2026-09-15-dataset-lifecycle-u9-test-report.md);[U10 报告](../test-reports/2026-09-15-chatlog-contextasm-u10-test-report.md);[U11–U12 报告](../test-reports/2026-09-15-app-composition-u11-u12-test-report.md) | U11–U12 已合入 `dev@bf59cce` 并 rebuild(digest `a8e3e940…`,schema 38)。path/sql_write 未到期例外保留。不整支 merge FAV。项目 143 只读 |
|
||||
| ARCH-DECOUPLE-PHASE2 | 事件 outbox 只写不消费(无 dispatcher worker,消费侧仍闭包桥,崩溃丢通知且无审计);bizdev service locator(8 访问器);docgov↔docrevision 双向 import;chat/coordinator 扇出过大;docflow 事件 Environment/ProjectID 硬编码;HTTP 错误信封与 PI Runner 结果协议未约定 | OPEN | [调研报告](../ops/research/2026-09-15-module-decoupling-ipc-assessment.md);[Phase 2 方案](./2026-09-15-module-decoupling-ipc-phase2-remediation-plan.md) | W0(D1 dispatcher 接线 + D3 字段注入)为首个批准范围;W1–W4 逐波次 go/no-go。path/sql_write 例外仍归 U4/U5 owner,不在本行范围 |
|
||||
| DOC-RELIABILITY-PILOT | 受控文档写路径与 PG 事件交付尚未形成生产闭环;闭包副作用在崩溃/重启后不可重试审计,错误 scope 或 projection 缺失仍可能导致刷新失败 | OPEN | [初审](../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) | 下一 go/no-go 仅为 Track E E0A:生产者、event contract、历史数据与 sequence 门;dispatcher 保持 off。FAV、结构整理、HTTP/PI 协议不纳入本 blocker 关闭条件。项目 143 只读 |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -27,7 +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 与选择性模块化 | partial | [架构](../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);[M1 停止扩面](../test-reports/2026-09-14-document-reliability-pilot-test-report.md);[M1 活验](../test-reports/2026-09-14-document-reliability-pilot-live-test-report.md);[M2](../test-reports/2026-09-14-document-reliability-m2-test-report.md);[M3 U8](../test-reports/2026-09-15-taskrun-runmanifest-u8-test-report.md);[M3 U9](../test-reports/2026-09-15-dataset-lifecycle-u9-test-report.md);[U10 报告](../test-reports/2026-09-15-chatlog-contextasm-u10-test-report.md);[U11–U12 报告](../test-reports/2026-09-15-app-composition-u11-u12-test-report.md) | U5–U12 合同已签并合入 `dev@bf59cce`(U11–U12 rebuild digest `a8e3e940…`,schema 38)。path/sql_write 未到期例外保留。未整支 merge FAV | `architecture-docs` |
|
||||
| 模块解耦与可靠事件 | 文档可靠性纵向试点、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);[U11–U12 报告](../test-reports/2026-09-15-app-composition-u11-u12-test-report.md) | U5–U12 已合入 `dev@bf59cce`。PG dispatcher/闭包迁移仍未实施;Track E 是当前可靠性缺口。Track S 与 HTTP/PI 协议分别规划,不阻塞 Track E;FAV 保持独立审计 | `architecture-docs` |
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user