# MIMO2.5 三角度架构审查报告

Date: 2026-05-28
Status: Second-round architecture review after major corrections
Model: MIMO v2.5 (1M context)
Reviewer scope: All architecture documents under `AirPlan/docs/architecture/`

## 审查背景

本轮审查基于第一轮审查后的修正结果，包括：

- 接口契约统一为 `snake_case` 并重写为可实现版本
- Permission 统一为 `action + grant_scope` 模型
- Error 统一为 `AirError` 嵌入式结构
- Task 依赖统一为边列表模型（含 `hard/soft/conflict/serialization`）
- IPC 补齐 `tool.call/tool.result/tool.stream/worker.result/worker.checkpoint/protocol.error`
- C4/UML 修正 TUI、ProviderManager、EventIngestor、Scheduler/WorkerManager、Capability/Doctor 依赖方向
- 新增 `runtime-semantics-v1.md` 明确跨 DB 事务、heartbeat、执行原语等
- 目标从半成品 MVP 升级为 V1.0.0 Alpha（含完整 C++ 工作流和插件基础）
- 明确 source-of-truth precedence
- 消除 VibeBox 双 baseline 歧义

---

## 1. 架构师视角

### 1.1 总体评价

架构方向正确，修正后的 IPC 协议、依赖方向、EventIngestor、权限模型、任务依赖边列表均已收敛。剩余问题主要是**跨文档一致性**，不是设计方向问题。

V1.0.0 Alpha 范围合理：完整 C++ 开发闭环、插件/能力基础、TUI/HUD、验证与打包都在范围内。推迟容器沙箱、第三方插件签名、Windows 原生支持等是正确的取舍。

### 1.2 可接受的取舍

| 取舍 | 理由 |
|---|---|
| 项目本地 `.air` 作为状态源 | 本地 coding agent 的合理选择，避免云端耦合 |
| Anthropic canonical 内部消息格式 | 简化多 Provider 支持，转换在 adapter 边界 |
| EventBus 用于实时、SQLite 用于恢复 | 正确的职责分离，已通过 EventIngestor 澄清 |
| 独立 Bun 子进程 + NDJSON IPC | 良好的隔离边界，协议已补齐 |
| C++ 作为第一个深度工具链 | 对架构有高验证价值，同时保持 `toolchain-*` 可扩展性 |
| Architecture Designer 作为显式升级路径 | 多 agent 编码运行时的合理治理模型 |
| `foreign_keys = OFF` | 降低迁移/恢复复杂度，但需要应用层一致性契约（见 S8） |

### 1.3 已修正的关键问题

1. **IPC 协议**：已补齐 tool.call/result/stream、worker.result/checkpoint、protocol.error
2. **依赖方向**：已消除 Scheduler↔WorkerManager、EventStore↔EventBus、CapabilityRegistry↔DoctorService 循环
3. **TUI 边界**：已明确 TUI 只依赖 `ProjectionClient`，不导入 runtime 内部
4. **ProviderManager 归属**：已明确在 `packages/llm`，runtime 通过 facade 调用
5. **EventIngestor**：已引入作为事件摄入边界，EventStore 不再隐式触发业务动作
6. **Permission 模型**：已统一为 `action + grant_scope`
7. **Task 依赖**：已改为边列表模型，Scheduler 可动态追加持久化冲突边
8. **执行原语**：已通过 `runtime-semantics-v1.md` 定义 read-before-edit token、exact edit、completion gate

### 1.4 剩余架构关注点

1. **跨 DB/文件事务**：`runtime-semantics-v1.md` 已定义 outbox/compensation 模型，但 `DebugKnowledgeStore` 和 `learned-memory` 服务接口尚未定义
2. **学习/技能生命周期**：`candidate → approval → promotion → rollback` 流程已有文档描述，但缺少形式化状态机
3. **项目扫描**：已确认无限递归无排除原则，安全边界（symlink 环、挂载异常）已补充

---

## 2. 工程师视角

### 2.1 阻塞级问题（B1-B6）

这些问题会阻止 `packages/contracts` 编译为可用 TypeScript 包，或导致运行时失败。

#### B1. `AirError.cause_ref` 类型冲突

**位置**：`interface-contracts-v1.md` §3 vs `error-taxonomy-v1.md` §2

**问题**：
- `interface-contracts-v1.md` 中 `cause_ref` 类型为 `EntityRef`（`{ type: EntityType, id: string }` 结构）
- `error-taxonomy-v1.md` 中 `cause_ref` 为内联扁平字段对象：`{ event_id?, task_id?, agent_id?, tool_run_id?, command_run_id?, artifact_id?, diagnostic_id? }`
- 两个结构体不兼容，消费者期望其中一种格式会与另一种冲突

**修复方向**：以 `interface-contracts-v1.md` 的 `EntityRef` 为准，更新 `error-taxonomy-v1.md`

---

#### B2. `DebugKnowledgeStore` 和 learned-memory 服务接口缺失

**位置**：`runtime-semantics-v1.md` §6.3, §6.4

**问题**：
- `runtime-semantics-v1.md` 引用 `DebugKnowledgeStore` 作为写入 `debug-records.db` 的服务
- 引用未命名的 "ExperienceMiner/Curator service" 写入 `learned-memory.db`
- 两个服务在 `interface-contracts-v1.md` 中均无接口契约
- `c4/code-view.md` 中也未列出这些运行时类
- 开发者实现 §6 的跨 DB 事务语义时没有可实现的契约

**修复方向**：在 `interface-contracts-v1.md` 中添加 `DebugKnowledgeStore` 和 `LearnedMemoryStore` 接口

---

#### B3. `debug-records.db` 和 `learned-memory.db` 无 schema 定义

**位置**：`db-schema-v1.md`

**问题**：
- `db-schema-v1.md` 只覆盖 `session.db`
- 这两个项目级数据库在至少 4 个文档中被引用，但无 DDL、无表定义、无列规范
- `debug.record.created` 事件载荷暗示了 `debug_record_id`、`failure_signature`、`summary` 等列，但目标表结构未定义

**修复方向**：在 `db-schema-v1.md` 中补充 `debug-records.db` 和 `learned-memory.db` 的 schema

---

#### B4. `PermissionProfile` 命名冲突

**位置**：`security-model-v1.md` §3 vs `interface-contracts-v1.md` §10

**问题**：
- `security-model-v1.md` 定义 `PermissionProfile` 为 `"low" | "normal" | "high" | "developer"`（安全态势）
- `interface-contracts-v1.md` 定义 `AgentRuntimeContext.permission_profile` 为 `"main_direct" | "executor" | "reviewer" | "debugger" | "system"`（角色权限模板）
- 两个不同概念使用相同名称 `permission_profile`，实现者可能混淆

**修复方向**：将 `AgentRuntimeContext.permission_profile` 重命名为 `permission_template` 或 `role_permission`

---

#### B5. `EntityType` 集合不一致

**位置**：`interface-contracts-v1.md` §4 vs `event-registry-v1.md` §1

**问题**：
- `interface-contracts-v1.md` 定义 `EntityType` 含 12 个值，包括 `"capability"` 和 `"provider"`
- `event-registry-v1.md` 内联定义自己的 `EntityRef` 只有 10 个值，缺失 `"capability"` 和 `"provider"`
- 如果两者编译到同一包，会有两个冲突的 `EntityRef` 定义

**修复方向**：以 `interface-contracts-v1.md` 为准，event-registry 引用该定义而非内联

---

#### B6. `CompactionPolicy`、`PromptLayer`、`PromptLayerLoader` 无契约

**位置**：`c4/code-view.md` §4 vs `interface-contracts-v1.md` §16

**问题**：
- `c4/code-view.md` 列出 `CompactionPolicy.ts`、`PromptLayerLoader.ts` 并引用 `PromptLayer` 类型
- `interface-contracts-v1.md` §16 只定义了最小 `ContextAssembler` 接口
- `ContextAssembleInput.refs` 是 `string[]` 无结构，而 code-view 的 `ContextPack.refs` 有结构化形状
- 没有 `PromptLayer` 定义，`ContextAssembler` 无法实现

**修复方向**：在 `interface-contracts-v1.md` 中补充 `PromptLayer`、`CompactionPolicy`、`PromptLayerLoader` 接口

---

### 2.2 应修复问题（S1-S10）

这些问题不会阻止编译，但会造成混淆、重复或测试困难。

#### S1. `ToolCategory` 和 `ToolResultEnvelope` 重复定义

**位置**：`interface-contracts-v1.md` §12 和 `tool-registry-v1.md` §2

**问题**：两者定义了相同的 `ToolCategory` 和 `ToolResultEnvelope`。编译到同一包时 TypeScript 会报重复标识符。

**修复方向**：`tool-registry-v1.md` 引用 `interface-contracts-v1.md`，不重复定义。

---

#### S2. `TaskInsert = TaskRecord` 强制调用方传服务器生成字段

**位置**：`interface-contracts-v1.md` §6

**问题**：`TaskInsert` 等于 `TaskRecord`，意味着调用方必须提供 `created_at`、`retry_count`、`status`。通常 insert 应使用子集类型，服务器默认值由存储层填充。`PersistedEventRecord` 有同样问题。

**修复方向**：定义 `TaskInsert` 和 `EventInsert` 为省略服务器生成字段的子集类型。

---

#### S3. `ToolExecutor.execute` 返回未区分联合类型

**位置**：`interface-contracts-v1.md` §12

**问题**：返回 `AsyncIterable<ToolEvent> | Promise<ToolResultEnvelope<O>>`，调用方需 duck-type 或 `Symbol.asyncIterator` 检查来区分流式与非流式。`streaming: boolean` 字段存在但未在类型层面强制。

**修复方向**：使用判别联合或品牌化返回类型。

---

#### S4. `EventBus.subscribe` handler 抛错行为未定义

**位置**：`interface-contracts-v1.md` §7

**问题**：如果订阅 handler 抛出异常，契约未说明：(a) 错误被吞掉，(b) 传播给发布者，(c) 订阅被终止。

**修复方向**：明确 handler 错误不影响发布者，错误被记录但不传播。

---

#### S5. `JsonSchema<T>` 泛型参数 `T` 未使用

**位置**：`interface-contracts-v1.md` §2

**问题**：`type JsonSchema<T = unknown> = JsonObject` 中 `T` 从未在类型体中引用，是幽灵类型，不提供编译时安全。

**修复方向**：移除泛型参数或定义品牌化类型。

---

#### S6. `SchedulerWavePlan.wave_id` 是 `string` 而非品牌化 ID

**位置**：`interface-contracts-v1.md` §9

**问题**：系统中其他标识符都用品牌化类型别名（`TaskID`、`AgentID` 等），`wave_id` 是普通 `string`，不一致且无法防止 ID 类型混淆。

**修复方向**：添加 `WaveID` 品牌化类型。

---

#### S7. `FollowUpTask.type` 允许 `"docs"` 但 `TaskType` 不含 `"docs"`

**位置**：`interface-contracts-v1.md` §11

**问题**：`FollowUpTask.type` 为 `TaskType | "docs"`，但 `TaskType` 不含 `"docs"`。Scheduler 收到 `type: "docs"` 的 follow-up 时无法调度。

**修复方向**：将 `"docs"` 加入 `TaskType`，或从 `FollowUpTask.type` 中移除。

---

#### S8. `foreign_keys = OFF` 无应用层一致性契约

**位置**：`db-schema-v1.md` §1

**问题**：禁用外键并声明"应用层一致性检查处理引用"，但无文档定义这些检查是什么、何时运行、孤立行如何处理。

**修复方向**：在 Repository 接口中明确 insert 是否验证外键存在，或在 `runtime-semantics-v1.md` 中补充孤儿清理规则。

---

#### S9. `PermissionEngine.record` 返回 `Promise<void>` 无错误指示

**位置**：`interface-contracts-v1.md` §10

**问题**：如果记录权限决策失败（磁盘满、DB 锁），调用方无法得知。

**修复方向**：返回结果类型或指定抛出的类型化错误。

---

#### S10. `ProjectionStore.apply` 接受任意事件无过滤规范

**位置**：`interface-contracts-v1.md` §14

**问题**：`apply(event: RuntimeEvent): void` 未指定哪些事件类型会触发投影更新，实现者需猜测。

**修复方向**：添加文档说明预期的事件集，或使用类型窄化联合。

---

### 2.3 可接受的缺口

| 缺口 | 理由 |
|---|---|
| 无 monorepo 工具配置 | 实现选择 |
| 无具体 SQLite 迁移策略 | 单版本 V1.0.0 Alpha 可接受 |
| 无 Provider 重试/退避细节 | adapter 实现细节 |
| 无 TUI 组件细节 | TUI 仅消费投影，实现自由度高 |
| 无具体 token 计数实现 | Provider adapter 处理 |
| `ProviderCapabilityMatrix.supports/.conversion` 为 `JsonObject` | 故意保留 provider 特定形状灵活性 |
| 无具体 `semantic_signature` 算法 | 格式已定义，哈希函数为实现选择 |
| 无 IPC 传输层契约 | 信封格式已定义，传输为实现细节 |
| 无 EventStore schema 验证失败的具体错误形状 | 次要缺口 |

---

## 3. 用户视角（原始需求对齐）

### 3.1 需求对齐检查

| 原始需求 | 当前状态 | 评价 |
|---|---|---|
| 自有 AI coding agent/runtime，非 Claude Code 插件包装 | 独立架构，自有运行时、调度器、工具系统 | 已满足 |
| Claude Code 级执行层质量 | D-059 + runtime-semantics 定义了 read-before-edit、exact edit、completion gate | 已满足 |
| OpenCode TUI 风格复用 | `@opentui/solid`，投影消费模式，不复用业务状态 | 已满足 |
| 项目本地 `.air` 状态 | `.air/shared` + `.air/local`，session DB 项目本地 | 已满足 |
| 事件驱动 + SQLite 恢复 | EventBus 实时 + EventStore 持久化 + ProjectionStore 投影 | 已满足 |
| 独立子进程 worker + NDJSON IPC | 已定义完整 IPC 协议含 tool 调用 | 已满足 |
| C++ 作为第一个深度工具链 | `toolchain-cpp` 包含完整工作流 | 已满足 |
| 多 agent 调度 | Scheduler + TaskGraph + 边列表依赖 + 波次规划 | 已满足 |
| 权限模型 | `action + grant_scope`，路径/命令/网络/凭据分类 | 已满足 |
| VibeBox 下游分支 | `branchvibebox/` 独立 baseline + feasibility plan | 已满足 |
| 非半成品 MVP，目标 V1.0.0 Alpha | 范围已升级，含完整 C++ 工作流和插件基础 | 已满足 |

### 3.2 无方向性冲突

用户视角下无设计方向性冲突。所有 B/S 级问题都是工程实现一致性问题，不影响产品定位和架构决策。

---

## 4. 优先级建议

### 必须在系统概要设计前修复（B1-B6）

| 优先级 | ID | 修复内容 |
|---|---|---|
| 1 | B1 | 统一 `AirError.cause_ref` 为 `EntityRef`，更新 error-taxonomy |
| 2 | B4 | 重命名 `AgentRuntimeContext.permission_profile` 为 `permission_template` |
| 3 | B5 | event-registry 引用 interface-contracts 的 `EntityRef`，不内联 |
| 4 | B2 | 在 interface-contracts 补充 `DebugKnowledgeStore` 和 `LearnedMemoryStore` 接口 |
| 5 | B3 | 在 db-schema-v1 补充 `debug-records.db` 和 `learned-memory.db` DDL |
| 6 | B6 | 在 interface-contracts 补充 `PromptLayer`、`CompactionPolicy`、`PromptLayerLoader` |

### 可在概要设计中同步修复（S1-S10）

| 优先级 | ID | 修复内容 |
|---|---|---|
| 1 | S7 | 将 `"docs"` 加入 `TaskType` 或从 `FollowUpTask.type` 移除 |
| 2 | S2 | 定义 `TaskInsert`/`EventInsert` 子集类型 |
| 3 | S1 | tool-registry 引用 interface-contracts，不重复定义 |
| 4 | S6 | 添加 `WaveID` 品牌化类型 |
| 5 | S4 | 定义 EventBus handler 错误行为 |
| 6 | S8 | 补充 FK 一致性契约或孤儿清理规则 |
| 7 | S9 | `PermissionEngine.record` 返回结果类型 |
| 8 | S10 | `ProjectionStore.apply` 添加事件过滤文档 |
| 9 | S3 | `ToolExecutor` 返回判别联合 |
| 10 | S5 | 移除 `JsonSchema<T>` 泛型参数 |

---

## 5. 审查结论

**可以进入系统概要设计阶段**，前提是 B1-B6 先修复。S1-S10 可在概要设计过程中同步处理。

架构文档集整体质量高，V1.0.0 Alpha 范围明确，接口契约基本可编译，运行时语义已澄清。本轮修正解决了第一轮审查发现的所有关键问题，剩余问题都是工程一致性层面的细节。
