Complete architecture document set with multi-model review remediation: - Frozen interface contracts, runtime semantics, DB schemas - Event/tool/error/provider registries - Scheduler and main agent state machines - C4 module/code views, solution architecture, baseline V1 - Multi-model review reports and joint assessment - Phase-gate remediation complete (P0/P1/P2/UX resolved) - Implementation plan with T-000A through T-045 - Reference folders kept as placeholders only
330 lines
15 KiB
Markdown
330 lines
15 KiB
Markdown
# 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 范围明确,接口契约基本可编译,运行时语义已澄清。本轮修正解决了第一轮审查发现的所有关键问题,剩余问题都是工程一致性层面的细节。
|