# 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 审查方法

1. 独立全量覆盖核对（不依赖前轮结论）
2. 前轮发现的独立验证
3. 寻找前轮可能遗漏的新问题
4. 基线间冲突的根因分析
5. 架构合理性和内在一致性评估

---

## 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**（冻结基线）：

```text
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**：

```text
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 判定逻辑会因此不确定

**建议处理**

1. 确定哪份文档是权威：baselineV1 还是 overview
2. 如果 baselineV1 是权威，修复 overview 和 DD
3. 如果 overview 是权威，记录 ADR 说明 baselineV1 §8 被 overview §11 取代
4. 无论哪种，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 投影映射表**：

```text
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**：

```text
EventStore must not create scheduler tasks, permission decisions, memory promotions, or doctor fixes by policy.
```

**Opus 4.8 分析**

DD §5.4 的措辞确实容易误解，但仔细阅读后：

1. `context.compaction.requested | insert compaction task if accepted` — 这里的 "if accepted" 暗示 Scheduler 做决策，EventStore 只是记录事件。但措辞不清。

2. `memory.promoted | append + write ... via owner (outbox §18.4)` — "via owner" 明确说明写入由 owning service 执行，EventStore 只 append 事件。

3. `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 拆分为两个表：
1. **Session DB projection map**：只包含 session DB domain table updates
2. **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 个方法：

```ts
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 注释说明：

```text
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 中明确记录设计决策：

```text
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 定义：

```ts
export type AgentType = "executor" | "reviewer" | "debugger" | "compactor" | "experience_miner"
```

但 `prompt-layering-v1.md` §3.1 要求 L1 role 覆盖：

```text
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 中明确：

```text
AgentType 只覆盖 worker roles（child process agents）。
Runtime roles（main, architecture, scheduler）不通过 PromptLayerLoader.load_role 加载，
而是由 MainAgent/ArchitectureDesigner/Scheduler 内部硬编码其 role prompt。
```

或者建议在 contracts 中添加：

```ts
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 示例：

```text
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 说：

```text
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 流程：

```text
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 依赖方向

```text
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 处基线间冲突需要在冻结前解决：

1. Worker exit code 语义冲突（baselineV1 vs overview/DD）
2. PromptLayerLoader 接口与 prompt-layering 层定义不匹配
3. `memory.promoted` outbox 阶段语义不清

---

## 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 冲突是真实的基线级问题，需要在冻结前解决。
