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