Add system-detailed-design.md (2033 lines, 23 sections) derived from frozen baselines and overview. Complete four-model cross-review: - DeepSeek: baseline coverage audit (PASS, 9.6/10) - MIMO 2.5 Pro: internal consistency (PASS, 9.4/10) - GPT-5.5 Pro: baseline conflict detection (Requires repair) - Opus 4.8: validation + root cause analysis (CONDITIONAL PASS, 9.1/10) Key findings requiring resolution before freeze: - P1-01: Worker exit code semantic conflict (baselineV1 vs overview) - P1-02: PromptLayerLevel enum vs L0-L9 layer name mismatch - P1-03: EventStore.project() error handling undefined - P1-04: PromptLayerLoader interface incomplete for 10 layers Coverage verified: 100% contracts, events, DB schema, state machines. Architecture validated: no circular dependencies, proper separation. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
18 KiB
Opus 4.8 系统详细设计全量交叉审查
Date: 2026-05-29
Reviewer: Claude Opus 4.8 (independent multi-model cross-review)
Status: Full cross-verification with independent findings and prior-review validation
Scope: system-detailed-design.md against all frozen baselines, frozen overview, internal consistency, and architecture soundness
1. 审查方法
1.1 审查对象
AirPlan/docs/architecture/system-detailed-design.md(2033 行,23 节)
1.2 审查输入
| 文档 | 角色 |
|---|---|
interface-contracts-v1.md (23 节) |
接口契约 |
event-registry-v1.md (55 durable + 7 ephemeral) |
事件注册表 |
db-schema-v1.md (19 表, 18 个关闭枚举) |
数据库 Schema |
runtime-semantics-v1.md (19 节) |
运行时语义 |
scheduler-state-machine-v1.md (11 节) |
调度器状态机 |
main-agent-state-machine.md |
主代理状态机 |
prompt-layering-v1.md (L0-L9) |
提示分层 |
scope-escalation-v1.md (13 节) |
作用域升级 |
security-model-v1.md (8 PathRisk + 10 CommandRisk) |
安全模型 |
capability-trust-v1.md |
能力信任 |
baselineV1.md |
架构基线 |
c4/code-view.md |
C4 代码视图 |
system-overview-design.md (FROZEN) |
概要设计 |
1.3 前轮审查报告
| 审查者 | 结论 | P0 | P1 | P2 |
|---|---|---|---|---|
| DeepSeek | PASS | 0 | 0 | 3 |
| MIMO 2.5 Pro | PASS (附修复建议) | 0 | 2 | 5 |
| GPT-5.5 Pro | Requires repair | 0 | 2 (High) | 4 (Medium/Low) |
1.4 审查方法
- 独立全量覆盖核对(不依赖前轮结论)
- 前轮发现的独立验证
- 寻找前轮可能遗漏的新问题
- 基线间冲突的根因分析
- 架构合理性和内在一致性评估
2. 总体评估
2.1 评分
| 维度 | 得分 | 说明 |
|---|---|---|
| 契约覆盖 | 9.5/10 | 接口字段全覆盖,PromptLayerLevel/AgentType 类型边界有缺口 |
| 事件覆盖 | 10/10 | 55 durable + 7 ephemeral 全覆盖 |
| DB Schema 覆盖 | 10/10 | 19 表全仓储 |
| 状态机覆盖 | 10/10 | 6 个状态机全覆盖 |
| 基线一致性 | 7.5/10 | 2 处基线间冲突未收束,1 处详细设计放大了冲突 |
| 架构合理性 | 9.0/10 | 依赖方向正确,职责分离良好,但 EventStore 职责边界模糊 |
| 可实现性 | 8.5/10 | 方法签名可编码,但 3 处需要设计决策才能实现 |
综合评分:9.1/10
2.2 结论
详细设计在覆盖性上是完整的,但存在 3 处需要在实现前解决的基线级冲突。这些冲突不是详细设计本身的错误,而是上游冻结文档之间的语义不一致,详细设计未能收束它们。
建议:在冻结详细设计前,先修复基线间冲突,或在详细设计中明确记录设计决策来收束这些冲突。
3. 前轮发现验证
3.1 GPT-5.5 Pro 发现验证
| Finding | GPT-5.5 判定 | Opus 4.8 验证 | 结论 |
|---|---|---|---|
| Worker exit code 语义冲突 | High | 确认 | 真实基线冲突,需要修复 |
| EventStore.project 职责越界 | High | 部分确认 | 措辞问题,非职责越界(见 §4.1) |
memory.promoted outbox 语义 |
Medium | 确认 | 事件阶段语义不清 |
docs task 类型未闭合 |
Medium | 确认 | 需要设计决策 |
| Prompt role/profile 类型不完整 | Medium | 确认 | AgentType 不覆盖 main/architecture/scheduler |
| contracts 包文件集两套命名 | Low | 确认 | 需要统一 |
3.2 MIMO 2.5 Pro 发现验证
| Finding | MIMO 判定 | Opus 4.8 验证 | 结论 |
|---|---|---|---|
| PromptLayerLevel 枚举与 L0-L9 不对齐 | P1 | 确认 | 真实结构性不匹配 |
| EventStore.project() 错误处理未定义 | P1 | 确认 | 需要补充错误语义 |
| agent.started 投影措辞 | P2 | 确认 | 含糊但可接受 |
| WorkspaceManager/Scheduler 职责边界 | P2 | 确认 | 隐含分工但未显式标注 |
3.3 DeepSeek 发现验证
| Finding | DeepSeek 判定 | Opus 4.8 验证 | 结论 |
|---|---|---|---|
| PromptLayerLevel 枚举映射 | P2 | 升级为 P1 | 同意 MIMO 的升级判定 |
| Architecture gate 无独立序列图 | P2 | 确认 | 可从文本推导,非阻塞 |
| CLI catalog 类归属 | P2 | 确认 | IMPL 范围,非阻塞 |
4. Opus 4.8 独立发现
4.1 Finding O1 — High — Worker exit code 基线冲突(验证 + 根因分析)
问题
baselineV1.md §8 定义的 worker exit code 语义与 system-overview-design.md §11 和 system-detailed-design.md §8.1 不一致。
baselineV1.md:351-360(冻结基线):
0 protocol-level completion, including task failed/blocked
1 uncaught exception
2 startup/protocol error
3 permission error
4 parent cancelled
5 hard timeout killed
system-overview-design.md:856-866 和 system-detailed-design.md:566-569:
0 success
1 task failed
2 crashed
3 protocol error
4 cancelled
5 permission/policy blocked
根因分析
这不是详细设计的错误,而是 概要设计在冻结时已经与基线冲突。概要设计声称"frozen source documents are authoritative",但它自己定义了一套不同的 exit code 语义。详细设计沿用了概要设计的定义,从而继承了这个冲突。
关键语义差异:
| Exit code | baselineV1 | overview/DD | 冲突点 |
|---|---|---|---|
| 0 | protocol-level completion (包括 task failed/blocked) | success | task failed 是 0 还是 1? |
| 1 | uncaught exception | task failed | task failed 是业务失败还是进程异常? |
| 2 | startup/protocol error | crashed | crashed 是否包含 startup error? |
| 3 | permission error | protocol error | permission 和 protocol 互换了 |
| 5 | hard timeout killed | permission/policy blocked | timeout 和 permission 互换了 |
影响
WorkerManager 实现时无法确定:
- task failed/blocked 应该返回 exit code 0(baselineV1)还是 1(overview/DD)
- permission blocked 应该返回 exit code 3(baselineV1)还是 5(overview/DD)
- Scheduler 的 retry/blocked/failed/lost 判定逻辑会因此不确定
建议处理
- 确定哪份文档是权威:baselineV1 还是 overview
- 如果 baselineV1 是权威,修复 overview 和 DD
- 如果 overview 是权威,记录 ADR 说明 baselineV1 §8 被 overview §11 取代
- 无论哪种,DD 应明确:task failed/blocked 通过 WorkerResult 返回,exit code 0 表示协议正常完成
4.2 Finding O2 — High — EventStore.project 职责边界澄清
问题
GPT-5.5 Pro 报告 EventStore.project 职责越界,但 Opus 4.8 认为这是 措辞问题而非真正的职责越界。
DD §5.4 投影映射表:
context.compaction.requested | insert compaction task if accepted
memory.promoted | append + write rules/skill/learned-memory.db via owner (outbox §18.4)
debug.record.created | insert/update debug-records.db (outbox §18.4) + append session event
runtime-semantics-v1.md:43:
EventStore must not create scheduler tasks, permission decisions, memory promotions, or doctor fixes by policy.
Opus 4.8 分析
DD §5.4 的措辞确实容易误解,但仔细阅读后:
-
context.compaction.requested | insert compaction task if accepted— 这里的 "if accepted" 暗示 Scheduler 做决策,EventStore 只是记录事件。但措辞不清。 -
memory.promoted | append + write ... via owner (outbox §18.4)— "via owner" 明确说明写入由 owning service 执行,EventStore 只 append 事件。 -
debug.record.created | insert/update debug-records.db (outbox §18.4)— 同样引用 outbox 模型,说明外部写入不在 EventStore 事务内。
真正的问题
DD §5.4 的投影映射表混合了两种不同的内容:
- session DB domain projection(应该在 EventStore.project 内)
- cross-DB/file side effects(应该由 owning service 处理,EventStore 只 append 事件)
这种混合导致读者误解 EventStore 的职责边界。
建议处理
将 DD §5.4 拆分为两个表:
- Session DB projection map:只包含 session DB domain table updates
- Cross-store side effect triggers:说明哪些事件触发 owning service 的外部操作
4.3 Finding O3 — Medium — PromptLayerLoader 接口与 prompt-layering 层定义不匹配
问题
prompt-layering-v1.md §2 定义了 L0-L9 共 10 层,但 interface-contracts-v1.md §16 的 PromptLayerLoader 接口只有 4 个方法:
export interface PromptLayerLoader {
load_runtime_invariant(): PromptLayer // L0
load_role(role: AgentType): PromptLayer // L1
load_project_rules(project: ProjectContext): PromptLayer[] // L3
load_task_context(spec: TaskSpec, refs: TaskContextRefs): PromptLayer[] // L5
}
缺失的层:
| Layer | Name | Loader method |
|---|---|---|
| L2 | Safety and permission policy | 缺失 |
| L4 | Architecture baseline and current plan | 缺失 |
| L6 | Relevant code/artifacts/evidence | 缺失 |
| L7 | Recent conversation and decision context | 缺失 |
| L8 | Tool result history / diagnostics | 缺失 |
| L9 | Immediate instruction | 缺失 |
DD §10.2 的处理
DD §10.2 承认了这个差异,并用 IMPL 注释说明:
IMPL note: contracts §16 enumerates 10 PromptLayerLevel symbols; prompt-layering L2 (safety) is
carried by the runtime_invariant/role immutable layers and a dedicated safety layer is loaded with
immutable=true.
但这只解释了 L2,没有解释 L4-L9 如何加载。
影响
实现 ContextAssembler 时,需要加载 10 层,但 PromptLayerLoader 接口只提供 4 个方法。实现者必须:
- 扩展接口(违反冻结契约)
- 在
load_task_context中塞入所有剩余层(违反单一职责) - 在
ContextAssembler中硬编码剩余层的加载逻辑(绕过 Loader 抽象)
建议处理
在 DD 中明确记录设计决策:
PromptLayerLoader 接口只覆盖需要外部配置/数据的层(L0, L1, L3, L5)。
其他层由 ContextAssembler 内部组装:
- L2 Safety: 从 PermissionEngine 获取当前 permission profile
- L4 Architecture: 从 TaskSpec.context_refs.arc_ref 加载
- L6 Evidence: 从 TaskSpec.context_refs.artifacts 加载
- L7 Conversation: 从 SessionStore.messages 加载
- L8 Tool output: 从 SessionStore.tool_runs/command_runs 加载
- L9 Immediate: 从 TaskSpec.description/acceptance_criteria 构建
4.4 Finding O4 — Medium — AgentType 不覆盖 runtime roles
问题
interface-contracts-v1.md §5 定义:
export type AgentType = "executor" | "reviewer" | "debugger" | "compactor" | "experience_miner"
但 prompt-layering-v1.md §3.1 要求 L1 role 覆盖:
built-in role prompt for main/architecture/scheduler/executor/reviewer/debugger/compactor/experience_miner
main, architecture, scheduler 不在 AgentType 中。
影响
PromptLayerLoader.load_role(role: AgentType) 无法类型安全地加载 Main Agent、Architecture Designer、Scheduler 的 role prompt。
DD §10.2 的处理
DD 沿用了 contracts 的 AgentType,没有补充 runtime role 类型。
建议处理
在 DD 中明确:
AgentType 只覆盖 worker roles(child process agents)。
Runtime roles(main, architecture, scheduler)不通过 PromptLayerLoader.load_role 加载,
而是由 MainAgent/ArchitectureDesigner/Scheduler 内部硬编码其 role prompt。
或者建议在 contracts 中添加:
export type RuntimeRole = "main" | "architecture" | "scheduler"
export type PromptRole = RuntimeRole | AgentType
4.5 Finding O5 — Low — DD §18.4 outbox 示例与 runtime-semantics 不一致
问题
DD §18.4 的 outbox 示例:
Example: memory.promoted → session event (step 1) → LearnedMemoryStore.insert (step 3) →
memory.promoted completion evidence (step 4).
这暗示 memory.promoted 同时是 step 1 的 intent event 和 step 4 的 completion event。
但 runtime-semantics-v1.md §6.4 说:
memory.promoted means:
candidate was approved/promoted by owning service
rule/skill/learned-memory write is performed by ExperienceMiner/Curator service
session event records completed promotion and target ref
这里 memory.promoted 只表示 completed promotion,不是 intent。
影响
如果 memory.promoted 是 completion event,那 step 1 的 intent event 是什么?DD 没有说明。
建议处理
明确 outbox 流程:
1. memory.candidate.created (intent/request)
2. ExperienceMiner/Curator 审批
3. LearnedMemoryStore.insert
4. memory.promoted (completion)
或者如果 memory.promoted 确实是 intent+completion 合一,需要在 DD 中明确说明这是一个简化设计,并解释 recovery 如何区分 pending 和 completed。
5. 覆盖性检查
5.1 契约覆盖
| 契约章节 | DD 覆盖 | 状态 |
|---|---|---|
| §2 Core primitives | §3 ids.ts | ✓ |
| §3 Error | §3 error.ts, §18.1 | ✓ |
| §4 EntityRef | §3 event.ts | ✓ |
| §5 RuntimeEvent | §3 event.ts, §5 | ✓ |
| §6 Transaction/Repository | §4.1-§4.3, §18.2 | ✓ |
| §7 EventBus/Store/Ingestor | §5.1-§5.5 | ✓ |
| §8 Project/Session | §6 | ✓ |
| §9 Task/Scheduler | §7 | ✓ |
| §10 IPC | §8.1-§8.3 | ✓ |
| §11 WorkerResult | §8.3 | ✓ |
| §12 Tool | §9.1 | ✓ |
| §13 Permission | §9.2-§9.3 | ✓ |
| §14 Artifact/Evidence | §11.1-§11.2 | ✓ |
| §15 Provider | §12 | ✓ |
| §16 Context/Prompt | §10 | ✓ |
| §17 Projection | §13 | ✓ |
| §18 Capability | §9.5 | ✓ |
| §19 Doctor | §16 | ✓ |
| §20 Knowledge | §11.3 | ✓ |
| §21 Diagnostic | §15 | ✓ |
| §22 Versioning | §3 | ✓ |
| §23 Forbidden paths | §2, §18.5 | ✓ |
结果:23/23 契约章节全覆盖
5.2 事件覆盖
55 个 durable 事件全部在 DD §5.4 投影映射表中覆盖。 7 个 ephemeral 事件全部在 DD §5.5 中列出。
结果:62/62 事件全覆盖
5.3 DB Schema 覆盖
19 张表全部有对应的 Repository 或 Store。
结果:19/19 表全覆盖
5.4 状态机覆盖
| 状态机 | DD 覆盖 | 状态 |
|---|---|---|
| Main Agent (9 states) | §14.1, §20.1 | ✓ |
| Scheduler (11 states) | §7, §20.2 | ✓ |
| Task status (7 values) | §20.3 | ✓ |
| Agent status (6 values) | §20.4 | ✓ |
| Workspace status (5 values) | §20.5 | ✓ |
| Capability lifecycle (8 phases) | §9.5, §20.6 | ✓ |
结果:6/6 状态机全覆盖
5.5 禁止路径覆盖
10 条 contracts §23 禁止路径全部在 DD §2 和 §18.5 中强制执行。
结果:10/10 禁止路径全覆盖
6. 架构合理性分析
6.1 依赖方向
contracts → (none)
llm → contracts
toolchain-cpp → contracts
tui → contracts
runtime → contracts, llm (facade only)
cli → contracts, runtime, tui, llm, toolchain-cpp
workers → contracts + WorkerRuntime IPC (no direct runtime import)
评估:完全正确。无循环依赖。
6.2 职责分离
| 组件 | 职责边界 | 评估 |
|---|---|---|
| EventIngestor | 不创建 scheduler/permission/memory 决策 | ✓ |
| EventStore | 持久化 + session DB projection | ✓ (但措辞需澄清) |
| EventBus | 不是恢复源 | ✓ |
| SessionStore | 不含调度/权限/投影策略 | ✓ |
| Scheduler | 不是编码代理 | ✓ |
| ToolRegistry | 所有 side effect 经过 PermissionEngine | ✓ |
| PermissionEngine | 不绕过 credential/system-sensitive override | ✓ |
| TUI | 只依赖 ProjectionClient/contracts | ✓ |
| ContextAssembler | 不自行压缩 | ✓ |
评估:职责分离良好,无泄漏。
6.3 事务语义
所有 durable event + domain update 在同一 SQLite transaction 内。 EventBus publish 在 commit 后。 Cross-DB writes 使用 outbox 模型。
评估:事务语义正确。
7. 门禁判定
| 条件 | 状态 |
|---|---|
| P0 = 0 | PASS |
| 契约覆盖 100% | PASS |
| 事件覆盖 100% | PASS |
| DB Schema 覆盖 100% | PASS |
| 状态机覆盖 100% | PASS |
| 禁止路径全执行 | PASS |
| 架构无循环依赖 | PASS |
| 职责分离无泄漏 | PASS |
| 基线间冲突已收束 | FAIL (3 处未收束) |
门禁结果:CONDITIONAL PASS
详细设计在覆盖性和架构合理性上通过,但存在 3 处基线间冲突需要在冻结前解决:
- Worker exit code 语义冲突(baselineV1 vs overview/DD)
- PromptLayerLoader 接口与 prompt-layering 层定义不匹配
memory.promotedoutbox 阶段语义不清
8. 修复建议优先级
| 优先级 | Finding | 建议处理 |
|---|---|---|
| P0 | Worker exit code 冲突 | 发布 ADR 明确 baselineV1 §8 被 overview §11 取代,或修复 overview/DD |
| P1 | EventStore.project 措辞 | 拆分 DD §5.4 为 session DB projection 和 cross-store triggers 两个表 |
| P1 | PromptLayerLoader 接口 | 在 DD §10.2 明确记录 L2/L4-L9 的加载方式 |
| P2 | AgentType 不覆盖 runtime roles | 在 DD 中明确 runtime roles 的 prompt 加载方式 |
| P2 | memory.promoted outbox 语义 |
明确 intent event 和 completion event 的区分 |
| P3 | contracts 包文件集命名 | 在 DD 中冻结唯一文件树 |
| P3 | docs task 类型 |
决定是正式 task type 还是移除 |
9. 与前轮审查的一致性总结
| 审查者 | P0 | P1 | P2 | 综合评分 | Opus 4.8 验证 |
|---|---|---|---|---|---|
| DeepSeek | 0 | 0 | 3 | 9.6/10 | 过于乐观,遗漏了基线冲突 |
| MIMO 2.5 Pro | 0 | 2 | 5 | 9.4/10 | 准确,但未深入基线冲突根因 |
| GPT-5.5 Pro | 0 | 2 | 4 | — | 准确,发现了基线冲突 |
| Opus 4.8 | 0 | 2 | 5 | 9.1/10 | 验证前轮 + 根因分析 + 修复建议 |
多模型审查结论:
四轮审查在覆盖性上一致(100%),在基线冲突上逐步深入。Opus 4.8 确认 GPT-5.5 Pro 发现的 Worker exit code 冲突是真实的基线级问题,需要在冻结前解决。