# MIMO 2.5 Pro 系统详细设计全量交叉审查 Date: 2026-05-29 Reviewer: MIMO 2.5 Pro (single-model, independent pass) Status: Full cross-verification of `system-detailed-design.md` against all frozen baselines, frozen overview, and internal architectural consistency Scope: Coverage + consistency + architecture soundness audit --- ## 1. 审查方法 审查对象:`AirPlan/docs/architecture/system-detailed-design.md`(2033 行,23 节) 审查三维度: 1. **覆盖性**:基线/概要设计的每个 item 是否在详细设计中有对应项 2. **一致性**:详细设计内部是否存在矛盾、基线引用是否准确 3. **架构合理性**:类职责划分、依赖方向、边界执行是否合理,是否存在内在冲突 审查输入: | 文档 | 角色 | |---|---| | `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` | 能力信任 | | `system-overview-design.md` (FROZEN, 1222 行) | 概要设计 | | `DeepSeek系统详细设计审查.md` | 前一轮审查报告 | 方法: - 逐契约接口字段比对 - 逐事件投影映射核对 - 逐表仓储核对 - 逐状态机转换核对 - PromptLayer 三方比对(contracts / prompt-layering / overview) - 依赖方向一致性验证 - 内在冲突检测 --- ## 2. 总体评估 ### 2.1 评分 | 维度 | 得分 | 说明 | |---|---|---| | 契约覆盖 | 9.5/10 | 接口字段全覆盖,1 处 PromptLayerLevel 枚举与层名不完全对齐 | | 事件覆盖 | 10/10 | 55 durable + 7 ephemeral 全覆盖 | | DB Schema 覆盖 | 10/10 | 19 表全仓储 | | 状态机覆盖 | 10/10 | 6 个状态机全覆盖 | | 内在一致性 | 8.5/10 | 1 处真实内部矛盾(PromptLayer),1 处架构弱点(EventStore 错误隔离) | | 架构合理性 | 9.5/10 | 边界清晰、职责分离良好、依赖方向正确 | | 序列图覆盖 | 8.0/10 | 4 个关键序列覆盖,2 个可补充 | | 可实现性 | 9.5/10 | 方法签名可直接编码,无歧义 | **综合评分:9.4/10** ### 2.2 结论 详细设计是一个高质量的实现导向文档。架构边界清晰,依赖方向正确,类职责分离良好。发现了 **1 处真实内部矛盾** 和 **1 处架构弱点** 需要解决,但均不阻塞实现阶段——可以通过明确的设计决策澄清来修复。 --- ## 3. P0 发现(0 项) 未发现 P0 项。 --- ## 4. P1 发现(2 项) ### P1-01: PromptLayerLevel 枚举与 L0-L9 层名结构性不对齐 **严重度**:P1(真实内部矛盾,影响实现一致性) **问题**:`interface-contracts-v1.md` §16 定义了 10 个 `PromptLayerLevel` 枚举值,`prompt-layering-v1.md` §2 定义了 L0-L9 共 10 个层名。概要设计 §13 已将 L0-L9 逐层与基线对齐。但三方存在结构性不匹配: | L# | prompt-layering-v1 §2 | contracts §16 枚举值 | 对齐状态 | |---|---|---|---| | L0 | Runtime invariant | `runtime_invariant` | ✓ | | L1 | Role / agent mode | `role` | ✓ | | L2 | Safety and permission policy | **(无对应枚举值)** | ✗ | | L3 | Project rules and user preferences | `project_rules` | ✓ | | L4 | Architecture baseline and current plan | `architecture` | ✓ | | L5 | Task specification and acceptance criteria | `task_spec` | ✓ | | L6 | Relevant code / artifacts / evidence | `evidence` | ✓ | | L7 | Recent conversation and decision context | `conversation` | ✓ | | L8 | Tool result history / diagnostics | `tool_output` | ✓ | | L9 | Immediate instruction | `user_override`(名字不同) | △ | | — | (无对应层) | `system_debug` | ✗ | **矛盾点**: 1. L2 "Safety and permission policy" 没有对应的 `PromptLayerLevel` 枚举值——但它是 prompt-layering-v1 定义的独立层 2. `user_override` 映射到 L9,但概要设计 §13 说 L9 = "Immediate instruction",名字不一致 3. `system_debug` 枚举值没有对应的 L 层——DD §10.2 说"applied within L9 when present",但这是一个缩写而非结构映射 **影响**:实现时 `ContextAssembler.load_layers()` 需要 10 个加载点,但 `PromptLayerLoader` 接口只有 4 个方法(`load_runtime_invariant`, `load_role`, `load_project_rules`, `load_task_context`)。L2 safety、L4 architecture、L6 evidence、L7 conversation、L8 tool_output、L9 immediate instruction 都没有明确的 loader 方法。 **修复建议**(需要设计决策): - 选项 A:在 contracts §16 添加 `safety_permission` 枚举值,将 `user_override` 改名为 `immediate_instruction`,删除 `system_debug` 或并入 L9 - 选项 B:保持枚举不变,在实现层将 L2 映射到 `runtime_invariant`(immutable=true),L9 由 `user_override` + `system_debug` 合并 - 选项 C:扩展 `PromptLayerLoader` 接口添加 L2/L4-L9 的显式加载方法 无论选哪个,需要一个明确的设计决策记录。 --- ### P1-02: EventStore.project() 错误处理未定义 **严重度**:P1(架构弱点,影响运行时鲁棒性) **问题**:DD §5.3 `EventStore.append()` 在事务内执行 `EventRepository.insert()` 和 `project(event, tx)`。但 `project()` 执行的是多行 domain update(如 `task.started` 需要更新 `tasks` 表 + 插入 `task_attempts` 行)。如果 `project()` 中间步骤失败,事务会回滚——但此时 `EventBus.publish()` 不会执行(正确行为),然而 **没有描述 `project()` 内部的错误语义**: - 如果 `project()` 抛出异常,是整个 `append()` 回滚?(应该) - 如果 domain update 因 FK-off 不一致失败(如引用了不存在的 `tasks.id`),错误如何传播? - `project()` 是否有部分失败的恢复逻辑? **影响**:在高并发或重启恢复场景下,如果 `project()` 的某一步 domain update 失败(如引用的 task 已被删除),整个事件追加会回滚——这是正确的原子行为,但 DD 没有显式描述这个错误路径。 **修复建议**:在 DD §5.3 或 §18.2 添加:`project()` 异常 → 事务回滚 → `EventBus.publish()` 不执行 → 返回 `AirError{kind: "system_error"}`。如果是因为 FK-off 不一致导致,记录到 developer log 并触发 `referential_check()`。 --- ## 5. P2 发现(5 项) ### P2-01: DeepSeek 审查报告中的 3 项 P2 已验证 DeepSeek 审查报告的 3 项 P2 均确认属实: | ID | DeepSeek 发现 | MIMO 验证 | |---|---|---| | DeepSeek P2-01 | PromptLayerLevel 枚举与 L0-L9 不完全 1:1 | 确认(已升级为 MIMO P1-01) | | DeepSeek P2-02 | Architecture Designer gate 无独立序列图 | 确认,P2 | | DeepSeek P2-03 | CLI catalog 命令类归属未指定 | 确认,P2 | ### P2-04: `agent.started` 投影映射措辞 DD §5.4 投影映射表中 `agent.started` 的域更新描述为 "insert `agents` (starting/running)"。这暗示 `project()` 可能选择 `starting` 或 `running`,但 event-registry §3.3 固定为 "insert `agents` row with `status = running` or `starting`"——具体选择哪个取决于调度器上下文(spawn 前 vs 握手后)。 建议:DD 应明确 `starting` 是初始状态,`running` 是握手完成后的状态(与 db-schema §10 agent status 一致)。当前描述可接受但含糊。 ### P2-05: `WorkspaceManager` 与 `Scheduler` 状态机 MERGING 阶段的职责边界 DD §7.5 `WorkspaceManager.merge_workspace()` 和 DD §20.2 Scheduler 的 MERGING 状态都描述了合并逻辑。但 Scheduler 状态机的 MERGING 包含了冲突处理路由(trivial → repair/debugger, semantic → Reviewer/Architecture Designer, architecture → block, user → Main Agent)——这些是 Scheduler 级别的决策,而 `WorkspaceManager` 只负责 git 操作。 建议:明确 `WorkspaceManager` 返回 `MergeResult{status: success|conflict, conflict_files?, conflict_type?}`,Scheduler 根据 `conflict_type` 做路由决策。当前描述隐含了这个分工但没有显式标注。 --- ## 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) ``` **评估**:完全正确。`contracts` 是叶节点,`cli` 是根节点,`runtime` 依赖 `llm` 但仅通过 facade(`ProviderManager` 接口),`workers` 通过 IPC 间接依赖 `runtime`(不直接 import)。这个依赖方向避免了循环依赖,允许各包独立编译。 ### 6.2 职责分离 | 组件 | 职责 | 边界 | 评估 | |---|---|---|---| | EventIngestor | 事件入口 | 不创建 scheduler/permission/memory 决策 | ✓ 正确隔离 | | EventStore | 持久化事件 + 投影 | 不直接暴露 EventBus | ✓ 正确(投影在事务内,发布在事务后) | | EventBus | 实时发布/订阅 | 不是恢复源 | ✓ 正确 | | SessionStore | 聚合所有仓储 | 不含调度/权限/投影策略 | ✓ 正确(code-view §9) | | Scheduler | 编排服务 | 不是编码代理 | ✓ 正确(scheduler-state-machine §intro) | | ToolRegistry | 工具调用 | 所有 side effect 必须经过 PermissionEngine | ✓ 正确(contracts §23) | | PermissionEngine | 权限决策 | 不绕过 credential/system-sensitive override | ✓ 正确 | | TUI | UI 渲染 | 只依赖 ProjectionClient/contracts | ✓ 正确(contracts §23) | | ContextAssembler | 上下文组装 | 不自行压缩 | ✓ 正确(概要设计 §13) | **评估**:所有组件的职责边界与基线一致。没有发现职责泄漏或边界违反。 ### 6.3 状态机一致性 6 个状态机之间的交互路径: | 源状态机 | 目标状态机 | 事件/数据流 | 一致性 | |---|---|---|---| | Main Agent → Scheduler | DELEGATING → SCHEDULING | `task.created` | ✓ | | Scheduler → Worker | DISPATCHING → worker spawn | `agent.start` IPC | ✓ | | Worker → Scheduler | worker.return → COLLECTING_RESULTS | `worker.result` IPC | ✓ | | Scheduler → Architecture Designer | architecture-sensitive review | `architecture.impact.completed` | ✓ | | Architecture Designer → Scheduler | impact assessment done | Scheduler consumes impact | ✓ | | Main Agent ← Scheduler | progress/blocked/complete | `task.progress/blocked/completed` events | ✓ | | EventBus → ProjectionStore | all events | subscribe/apply | ✓ | | ContextAssembler → Scheduler | `compaction_requested` | Scheduler creates compact task | ✓ | **评估**:所有状态机交互路径的事件名称、方向和触发条件一致。没有发现状态机之间的死锁或悬空事件路径。 ### 6.4 事务语义一致性 关键事务边界: | 操作 | 事务范围 | 后置操作 | 一致性 | |---|---|---|---| | EventStore.append | event insert + domain projection | EventBus.publish (after commit) | ✓ | | ArtifactStore.create | temp→rename→DB record | event ingest | ✓ | | Task.start | task.started event + tasks update + task_attempts insert | agent.started event | ✓ | | Compaction | summary.created event + summaries insert | context.compaction.completed | ✓ | | Cross-DB write (outbox) | session event → external DB → completion event | recovery on restart | ✓ | **评估**:所有事务边界遵循 runtime-semantics §3 规则(durable event + domain update 同事务,EventBus 发布在事务后)。 --- ## 7. 与 DeepSeek 审查的交叉验证 | 发现 | DeepSeek 判定 | MIMO 判定 | 差异 | |---|---|---|---| | PromptLayerLevel 结构性不对齐 | P2 | **P1** | MIMO 升级:这不是"措辞差异"而是真实内部矛盾,影响实现一致性 | | Architecture gate 无独立序列图 | P2 | P2 | 一致 | | CLI catalog 类归属 | P2 | P2 | 一致 | | EventStore.project() 错误处理 | **未报告** | **P1** | MIMO 独立发现 | | agent.started 投影措辞 | **未报告** | P2 | MIMO 独立发现 | | WorkspaceManager/Scheduler 职责边界 | **未报告** | P2 | MIMO 独立发现 | **差异分析**:DeepSeek 将 PromptLayer 问题标记为 P2,理由是"DD §10.2 正确记录了此映射"。MIMO 认为这是 P1,因为虽然 DD 记录了差异,但没有给出明确的解决决策——实现时仍然面临"枚举值和层名不完全对应"的问题,而这个差异发生在两个已冻结的基线之间(contracts 和 prompt-layering),属于需要明确澄清的架构级问题。 --- ## 8. 覆盖性检查 ### 8.1 契约接口字段抽样 | 接口 | 基线字段数 | DD 覆盖数 | 缺失 | |---|---|---|---| | TaskSpec | 9 fields | 9 | 0 | | WorkerResult | 12 fields | 12 | 0 | | IpcEnvelope | 9 fields | 9 | 0 | | PermissionDecision | 7 fields | 7 | 0 | | AirError | 11 fields | 11 | 0 | | ProviderCapabilityMatrix | 10 fields | 10 | 0 | | CapabilityManifestV1 | 13 fields | 13 | 0 | | DebugRecord | 10 fields | 10 | 0 | | LearnedMemory | 9 fields | 9 | 0 | | Diagnostic | 14 fields | 14 | 0 | **10/10 接口字段完整性抽样全部通过。** ### 8.2 事件投影映射核对 55 个持久化事件逐一对比 event-registry §3 的 Domain update 描述。全部 55/55 覆盖且域更新描述准确。 ### 8.3 DB Schema 表核对 19 张表(db-schema §2-§18 + §20.1-§20.2)逐一对比 DD §4.3 仓储清单 + §11.3 项目级 DB Store。19/19 全覆盖。 ### 8.4 禁止路径核对 10 条 contracts §23 禁止路径逐一对比 DD §2 + §18.5。10/10 全覆盖。DD 额外添加 1 条 C4 规则(runtime → TUI import)。 --- ## 9. 与前轮审查的一致性 | 维度 | DeepSeek | MIMO 2.5 Pro | |---|---|---| | P0 | 0 | 0 | | P1 | 0 | 2 | | P2 | 3 | 5 | | 综合评分 | 9.6/10 | 9.4/10 | | 新发现 | — | P1-02, P2-04, P2-05 | **一致性结论**:两轮审查在 P0 层面一致(0 项)。MIMO 发现了 DeepSeek 未报告的 P1 级 EventStore 错误处理问题,并将 PromptLayer 结构性矛盾从 P2 升级为 P1。 --- ## 10. 门禁判定 | 条件 | 状态 | |---|---| | P0 = 0 | PASS | | P1 ≤ 2(均有明确修复路径)| PASS | | 契约覆盖 100% | PASS | | 事件覆盖 100% | PASS | | DB Schema 覆盖 100% | PASS | | 状态机覆盖 100% | PASS | | 禁止路径全执行 | PASS | | 架构无循环依赖 | PASS | | 职责分离无泄漏 | PASS | | 状态机交互无死锁 | PASS | | 事务语义一致 | PASS | **门禁结果:PASS(附 2 项 P1 修复建议)** 详细设计可以进入实现阶段,但建议在实现开始前明确 P1-01(PromptLayer 设计决策)和 P1-02(EventStore 错误路径文档化)。 --- ## 11. P1 修复建议 ### P1-01 修复路径 需要一个设计决策(ADR 或详细设计补充): **推荐方案 B**:保持枚举不变,在实现层建立映射: ```text L0 → runtime_invariant (immutable=true) L1 → role (immutable=true) L2 → (safety layer loaded by ContextAssembler as a runtime_invariant variant with immutable=true, source from ~/.air/permissions.yaml + project permissions) L3 → project_rules L4 → architecture (loaded from plan/todo/ADR context) L5 → task_spec L6 → evidence (loaded from artifacts/diagnostics/evidence_refs) L7 → conversation (loaded from messages/summaries) L8 → tool_output (loaded from recent tool_runs/command_runs/diagnostics) L9 → user_override + system_debug (merged, highest priority non-immutable layer) ``` PromptLayerLoader 接口扩展为: ```text load_safety_policy(): PromptLayer // L2 load_architecture_context(refs): PromptLayer[] // L4 load_evidence_context(refs): PromptLayer[] // L6 load_conversation(session_id): PromptLayer[] // L7 load_tool_output(recent_runs): PromptLayer[] // L8 load_immediate_instruction(): PromptLayer // L9 ``` ### P1-02 修复路径 在 DD §5.3 或 §18.2 补充: ```text EventStore.append error semantics: - project() 内部异常 → 整个事务回滚 - EventBus.publish() 不执行(正确:post-commit only) - 返回 AirError{kind: "system_error", message: "event projection failed"} - 如果是因为 FK-off 不一致(如引用不存在的 task_id): - 记录到 developer log - 触发 SessionStore.referential_check() - Scheduler 将受影响的 task 标记为 interrupted/blocked - 不会部分投影:SQLite 事务保证原子性 ```