Files
AirCoding/AirPlan/docs/round4-AUDIT-FINAL.md
AirCoding ae44be31d5 chore: push all design docs, V2 plan specs, and current working state
Includes AirPlan design documents, AircOding-alpha1-plan, AirPlanV2,
AirPlan-ParaV2, AirPlan-Para V1 reference docs, and all working code
changes across packages.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-12 17:12:29 +08:00

18 KiB
Executable File

全代码 code-to-design 审计 — 最终报告

14 子系统 code-to-design 比对汇总 (round4 Stage 3) 源: 14 份 agent 子系统审计报告 (A-N) → 合并去重 + 严重度再评估 + 影响链标注

0. 元信息

  • 14 子系统全部完成 (A: Contracts, B: Storage, C: Event, D: Lifecycle, E: Scheduler, F: Worker/IPC, G: Tool/Perm, H: Context, I: Artifact, J: Provider, K: Projection+TUI, L: Agents, M: Toolchain, N: Doctor)
  • 合并后共 97 条发现 (CRITICAL 18 / DEVIATION 32 / GAP 27 / EXCESS 20)
  • 报告期: round4 plan §3 格式逐项对齐, INV-1/INV-2/INV-3/INV-5 多子系统重复违反

1. CRITICAL (必须修) — 共 18 条

id 子系统 标题 违反约束 触发场景 影响链
round4-C-1 A,B,D,J,K,L 架构旁路: 多子系统自研 SessionManager/ProjectStore/ProviderManager 而旁路设计契约类 DD §6.1-§6.2, §12, INV-2 single-writer 启动任意 session, RuntimeApp / init / ProviderManager 全部跳过契约类, 直接 fs.write/SQLite/JSON.parse 触发 C-2,C-4,C-5,C-8,C-11
round4-C-2 C EventStore 单例 + 事后注入, SessionManager 创建的 EventStore 实例从未被消费 DD §5.1 §22.2 构造注入 任何 session 打开后 session.created 写入空 db 或被抛弃, domain projection 变 no-op C-3, C-6, C-15, G-C1
round4-C-3 C EventIngestor.ingest() 走 fallback 无 tx 路径, 违反 BEGIN/insert/project/COMMIT 单事务 runtime-semantics §3 同上事件路径, project() 与 event insert 不在同一事务 C-2, I-C1
round4-C-4 C project() switch 跳过 context.compaction.*/permission.*/doctor.*/memory.*/debug.* 20+ 事件类型 DD §5.4 Table A+B 上述事件全部不更新 domain table, 但 events 表行仍写 → 审计日志与 domain 永久不一致 C-2, C-3, G-C2, N-D1
round4-C-5 E 失败/阻塞任务被路由到设计无的 TERMINATED 终态 scheduler-state-machine §10 (仅 COMPLETED/BLOCKED/CANCELLED) 任何 task 失败 → run_until_idle 退出但 API 不暴露 TERMINATED, 调度死锁 E-2, E-7
round4-C-6 E PLANNING_WAVE → MONITORING 跳过 DISPATCHING, 旁路 spawn scheduler-state-machine §4 任何非空 running task, 调度直接进入监控态, worker 永不被 spawn E-3, E-5, F-C1
round4-C-7 E Scheduler 公开 API add_dependency / load_graph / cancel_task 完全缺失 DD §7.1, contracts task.ts:194-200 DAG 编辑与取消无法调用, CLI/TUI 失去图编辑能力 E-5, E-8
round4-C-8 E,F agent.start IPC 控制消息未按设计携带 context_pack/runtime/AgentRuntimeContext, WorkerRole.run 单参 DD §8.2 handshake, contracts §10 worker 启动后拿不到 permission_template / ContextPack, 权限与上下文全空 F-C2, F-D3, G-C3
round4-C-9 F WorkerRuntime 自加 call_llm, 凭据路径走 process.env.AIRCODING_MODEL fallback 'glm-5.1', 绕过 TaskSpec.constraints.model_id DD §18 INV-3, interface-contracts §10 worker 直连 LLM 风险 + 模型 ID 决定顺序错乱 (env > spec) F-C1, J-C1, C-2
round4-C-10 G ToolRegistry.call / PermissionEngine.record 完全不发射 tool.* / permission.decision.recorded 事件 DD §9.1 §9.2, INV-1 任意 tool 调用与权限决策不入 tool_runs / 决策审计, 投影与追责链断 C-4, G-C2, K-D1
round4-C-11 G execute_branch 在 allow/announce_then_run 跳过 grant_scope 持久化与 backup_before_write DD §9.3, 安全模型 §11 同一 scope 每次 call 重复 prompt, 写操作无备份 G-C1, G-D1
round4-C-12 I CppToolRegistrar write_artifacts 完全旁路 ArtifactStore, 用 file:// URI, 不算 sha256 DD §994-1002, naming §8 cpp.build/test 失败时写出的产物既不在 artifacts 表, 也无法回链 evidence I-C3, I-G2, M-E1
round4-C-13 I EvidenceStore.create 在 ingest event 后又重复插 evidence_refs, 打破 single-writer DD §18.4, runtime-semantics §6.3 每次 evidence 创建产 2 行 DB, 触发 FK-off 检测假阳 C-3, B-C3
round4-C-14 J **ProviderManager 硬编码 `provider_id 'anthropic'`, 多 provider 路由坍缩为单 provider fallback** DD §12.1 §12.2 adapter_for(provider_id)
round4-C-15 L CONFIRMING → confirm 路由到 DELEGATING 而非 EXECUTING (Opus 报告"已修"未验证) DD §20.1 state machine 用户确认后任务被 re-delegated 而非直接执行, 卡死 L-2, L-3, E-7
round4-C-16 L ArchitectureDesigner 放在 simple/plan 分支前, 强制所有 task-path 走 Architect 评估 DD §20.1 §14.1 每个 task 请求都做 impact_assess, 性能与设计意图双重偏离 L-3, L-4
round4-C-17 N DoctorService --fix 裸跑 sudo apt install, 绕过 PermissionEngine DD §16.1, INV-3 --fix 自动修复触发高危命令, 任何用户/任务权限配置被跳过 N-D1, G-C3
round4-C-18 B,C,I,N Recovery.scanOrphanReferences FK-off 8 不变量只覆盖 session_id 一类, 实际只查 5/8, 标修复但无 UPDATE/DELETE DD §18.3 §16.3, runtime-semantics §14 孤儿 task/agent/tool_run/command_run 不被检测/修复, 累积 → 重启后状态漂移 C-6, I-C1, I-G2

2. DEVIATION (高优) — 共 32 条 (节选要点, 完整 32 条见附录)

id 子系统 偏离 影响
D-A-1..6 A ProviderCapabilityMatrix / ProviderCompletionInput / ProviderManager.load_config / PromptLayerLoader / FollowUpTask.type 等 6 处与 contracts §15 §16 字段类型不一致 type 漂移累积 → runtime/contracts 边界失真
D-B-1..6 B list_active(project_id) 必传参, insert 硬写 status='active', update 接受 patch.status 无守卫, DatabaseHandle 返回 {path} 不含 db, 类型在 MigrationRunner INV-1 守卫仅靠注释, 模块边界混乱
D-C-1..7 C EventSchemaRegistry.validate 只查 type, EventBus.publish 内存泄漏, append_many 共享 tx, project() 跳过 20+ 事件, ingest_batch 不在 contract, assistant.message.created 投影顺序, agent.started 丢失 starting 分支 事件管道不严, 大量 corner case 未覆盖
D-D-1..4 D ProjectionStore.rebuild 一致 ✓, 但 RuntimeApp 启动序列命名/编号与 §22.2 不一致, migrate 走 ad-hoc dbHandle 启动行为可观察但语义不清
D-E-1..8 E SchedulerState 多 TERMINATED, WavePlanner 字段名错, record_heartbeat 签名错且不写 domain, WorkspaceManager 不发事件, RetryPlanner.decide 永不被调, TaskGraph.get_runnable_tasks 忽略 soft/serialization, MONITORING 收 WorkerResult, create_tasks 跳过 LOADING_GRAPH 调度可用但状态机闭包破坏
D-F-1..4 F IpcKind 双重协议 (IpcKind + WorkerMessageType), ExitCode 5 永未触发, NDJSON 编码只校验 4 字段, 父进程全量继承 process.env 协议冗余, 凭据泄漏风险面
D-G-1..4 G PermissionAction 6 个但 block 不抛 task.blocked, PermissionEngine.evaluate 3 参, BuiltInToolRegistrar 18 vs 28 缺 cpp.*6/fs.stat 等, call_streaming 不处理 ask_user/block/refuse 决策 schema 漂移, V1 工具面残缺 1/3
D-H-1..5 H L8 用 message_repo 替代 tool_runs/command_runs, AssembledContextcanonical_format:"anthropic", L6 Evidence 第一参错 (传 'task_id' 而非 'task'), messages_artifact_id 溢出路径未触发, CompactorRole 行为一致 ✓ ArchitectureDesigner L4 失效, L6/L8 数据源错
D-I-1..4 I artifact_id 用 UUID 截 24 hex 不用 ULID, DebugKnowledgeStore/LearnedMemoryStore 自定 schema 不同步 contracts, ArtifactStore 不 gzip, get 暴力 readdir 不用 DB 命名不匹配触发 Recovery 假阳, 性能浪费
D-J-1..5 J Adapter 缺 count_tokens, complete 非流式 (等待整响应再 yield), ProviderConversionReport.status 缺, ModelConfigLoader 不解析嵌套 YAML, select_model 忽略 ModelRequirement capability-based selection 与流式语义失效
D-K-1..2 K ProjectionStore.apply 在生产路径是死代码 (RuntimeApp 用 snapshot push), TuiApp.start 返回 Promise 路径与设计意图分裂
D-L-1..3 L MainAgent 状态多 ERROR+TERMINATED, AWAITING 状态无转换, handle_user_message 不返回 y/n 循环 状态爆炸但未连通
D-M-1..4 M DiagnosticParser.semantic_signature 名字/签名错, ClangdClient 拆 query_symbol/query_diagnostics, CppProjectDetector 实例化用构造参数, CppTestRunner.parse_ctest_output 不在设计 工具链接口小幅漂移, 可互通
D-N-1..6 N Doctor 8 类 (含 project/runtime 多), run_diagnostics(scope) 签名不符, 7-day retention 缺失, MigrationRunner 17 表 OK, Recovery 8 步只 3 步, FK 检查 5/8, SecretRedactor 未共享 运维数据积累无清理, 恢复路径不完整

3. GAP (设计有、实现无) — 共 27 条

事件/存储契约层 (影响 4 子系统)

  • G-1 缺失 §7 全部契约 EventBus/EventStore/EventIngestor/EventSchemaRegistry/Subscription/EventAppendOptions (A)
  • G-2 缺失 §6 持久化记录 PersistedEventRecord/PersistedEventInsert/SessionRecord/MessageRecord/EventRepository (A)
  • G-3 缺失 §16 Context 核心接口 ContextAssembler/ContextAssembleInput/AssembledContext/CompactionPolicy/CompactionResult (A)
  • G-4 SessionStore 聚合类缺失, 15 repos 散落 (B) — 触发 C-18
  • G-5 Outbox 模型未实现 (B) — 触发 C-2, C-13, I-C1
  • G-6 EventIngestorFactory.createForSession 无实现 (C)

工具/能力层 (影响 3 子系统)

  • G-7 BuiltIn 28 工具仅 18 注册, cpp.*6/fs.stat/git.worktree/process.kill 全部缺 (G) — 触发 C-12, M-E1
  • G-8 artifact.create/read 工具是 stub 不调 ArtifactStore (I) — 触发 C-12
  • G-9 Recovery.open() 无 bootstrap 调用点 (N) — 触发 C-18
  • G-10 check_capability() private helper 缺失 (N)
  • G-11 doctor --bundle 命令模式缺失 (N)
  • G-12 context.compaction.requested 事件从未由 Scheduler 发出 (H) — 触发 C-4
  • G-13 copy-on-write compaction 缺失 (H)
  • G-14 L4 Architecture 层未实现 plan/ADR/C4 文档加载 (H)
  • G-15 L2 Safety 层是硬编码 placeholder (H)
  • G-16 L7 omission/conflict 路由未实现 (H)
  • G-17 EventSchemaRegistry 无 version 升级路径 (C)
  • G-18 assistant.message.failed 失败 artifact 创建缺失 (C)
  • G-19 FK-off 一致性 enforcement 缺失 (C) — 触发 C-18

UI/Agent 层

  • G-20 TUI theme/keymap/ 目录缺失 (K)
  • G-21 ProjectionStore 未与 SessionStore 仓库连接, rebuild() 生产未调 (K) — 触发 C-18
  • G-22 HUD 未挂载主界面 (K)
  • G-23 缺失 ephemeral 事件处理 (assistant.message.delta 等) (K)
  • G-24 Regex 分类器替代 CLASSIFYING LLM 步骤 (L)
  • G-25 requirement.changed 发射路径缺失 (L)
  • G-26 INTERRUPTING/ARCHITECTURE_REVISING 分支不可达 (L)
  • G-27 main-agent-state-machine 7-day retention / Bundle 模式 (N)

4. EXCESS (实现有、设计无) — 共 20 条

  • E-1 ProviderIdentity/ProviderConversionReport/ToolCall/DoctorIssue/CapabilityTrustLevel 等类型别名抽取, 扩大 contracts 导出表面 (A) — 触发 C-14
  • E-2 Repository 基类重复样板 ~800 行 (B)
  • E-3 EventIngestor.ingest_batch/EventIngestorFactory/NullEventIngestor (C) — 触发 C-2
  • E-4 EventStore.setTransactionManager/setRepositories 事后注入 setter (C) — 触发 C-2
  • E-5 EventBus.getSubscriptionCount (C)
  • E-6 EventStore 手写 UUID 生成器 (C) — 触发 G-17
  • E-7 EventStore repository 字段类型 any (C) — 触发 C-4
  • E-8 createRuntime.ts / loadConfig.ts 自实现 project_id 加载 (D) — 触发 C-1
  • E-9 WorkerRuntime 多 4 个方法 (call_llm/report_result/heartbeat/send_*) (F) — 触发 C-9
  • E-10 WorkerProtocol 多 5 种消息类型 (F) — 触发 C-8
  • E-11 WorkerHandle.state 元数据多余 (F)
  • E-12 find_bun() / worker.error 私有通道 (F)
  • E-13 ToolRegistry.execute_branchdowngrade_to_readonly/apply_sandbox_restrictions dead code (G)
  • E-14 ToolRegistry.global_tool_registry 单例 (G)
  • E-15 CapabilityManifestValidator trust_level enum 校验未决策 (G) — 触发 G-7
  • E-16 PermissionEngine LAYER_ORDER + decision_log (G)
  • E-17 SkillLoader trust_root bypass 旁路 (G)
  • E-18 ContextAssembler L3 project_files 非设计层 (H)
  • E-19 TUI 端重复定义 ProjectionClient 与投影类型 (K) — 触发 K-D1
  • E-20 CppToolRegistrar write_artifacts 写文件, 重复 runtime EventSink (M) — 触发 C-12

5. 影响链分析

核心根因 (修这个能解多个症状):

  1. 根因-A: 设计契约类被实现旁路 (C-1, C-2, D-C1, D-C2, F-C1, J-C1, N-C1) → SessionManager / ProjectStore / ProviderManager / PermissionEngine 在 7 个子系统中实现完整但被 RuntimeApp / WorkerRuntime / ProviderManager / DoctorService 旁路 → 修一个 RuntimeApp 启动路径让其走 SessionManager.open_session, 7 个 CRITICAL 同步关闭

  2. 根因-B: INV-1 事件链整体失效 (C-2, C-3, C-4, G-C1, G-C2, H-G1, I-C1) → event → projection → domain table 这条链上 5+ 子系统不发射或不投影关键事件 → 修 EventStore.project() switch 覆盖 55 个事件 + 移除单例, 8 个症状同时解

  3. 根因-C: 状态机闭包破坏 (E-1, E-2, E-6, L-1, L-2) → Scheduler 5 个 CRITICAL + MainAgent 2 个 CRITICAL 都是状态转换路由错 → 统一从 state machine 重写主控循环

  4. 根因-D: outbox/INV-2 缺失 (B-G2, C-2, I-C1, I-C3, I-G2) → external write → ingest event 同事务模式未实施, 导致 4 个子系统重复插入/孤儿文件 → 修 G-5 outbox 模型一处, 4 个症状同步解

  5. 根因-E: 设计类 vs 实现类双轨 (A-G1, A-G2, A-G3) → contracts 设计了 §6 §7 §16 全部接口但实现未映射到任何 .ts 文件 → 修 contracts package index 重新映射, 3 个 GAP 关闭

症状层 (依赖根因):

  • K-D1, H-D1, H-D2 全部因 C-2/C-3 投影失效
  • M-D1-D4 因 G-7 工具面残缺间接暴露
  • L-D2, L-D3 因 E-5/E-6 调度状态错

CRITICAL 互相触发关系图 (简化):

C-1 (架构旁路) ─┬─→ C-2 (EventStore 单例) ─→ C-3 (no-tx) ─→ C-4 (project switch 缺) ─→ C-13
                ├─→ C-5/C-6 (Scheduler 状态) ─→ C-7 (API 缺)
                ├─→ C-9 (call_llm) ─→ C-14 (Provider 硬编码)
                ├─→ C-10 (Tool 不发事件) ─→ C-11 (execute_branch)
                ├─→ C-12 (Artifact 旁路) ─→ C-13
                ├─→ C-15/L-1 (CONFIRMING 错) ─→ C-5
                └─→ C-17 (Doctor 裸 sudo)
C-18 (Recovery FK 5/8) ←─ C-3, C-4, I-C1

6. 建议修复顺序

P0 - 必须先修 (5 条根因)

  1. C-1 + D-C1 + D-C2: RuntimeApp 启动路径改走 SessionManager / ProjectStore — 解 7 个子系统症状 (估 1-2 天)
  2. C-2 + C-3: 撤销 EventStore/eventIngestor 模块单例, 改回 SessionManager 构造注入, 恢复 txManager/repos 在构造时绑定 — 解 C-13/C-15/I-C1 等 (估 1 天)
  3. C-4: EventStore.project() switch 覆盖 55 个事件类型 + Table B cross-DB 占位 — 解 C-13/C-10/G-C2 (估 1-2 天)
  4. C-5 + C-6 + C-7 + E-D1: 重写 Scheduler 状态机主循环 (terminal_state 去掉 TERMINATED, PLANNING_WAVE→DISPATCHING→MONITORING, 补齐 add_dependency/load_graph/cancel_task) — 解 E-2/L-1 (估 2-3 天)
  5. C-18 + B-G1 + B-G3: Recovery 8 步全部实现 + FK-off 8 invariant 全覆盖 + 实际 archive/reparent 动作 — (估 1 天)

P1 - 高优 (症状层, 根因修后自动解或独立修) 6. C-9 + C-14 + J-C1: WorkerRuntime 移除 call_llm, ProviderManager 走 adapter_for 路由 — (估 1 天) 7. C-10 + C-11 + G-D1: Tool/Permission 事件链修复 + PermissionDecision schema 对齐 contracts — (估 1-2 天) 8. C-12 + I-G1 + I-G2: CppToolRegistrar 走 ArtifactStore + tool 包装 — (估 1 天) 9. L-1 + L-2 + L-3: MainAgent CONFIRMING→EXECUTING + ArchitectureDesigner 仅 plan 分支 + architecture.plan.updated 发射 — (估 1 天) 10. N-C1 + N-C2: Doctor --fix 走 PermissionEngine, 双份日志连通 DeveloperLogEncryptor — (估 0.5 天) 11. K-D1 + K-G2: ProjectionStore.apply 走真实事件流 + 注入 SessionStore 仓库 — (估 0.5 天)

P2 - 可后修 (设计 polish) 12. A-G1/G2/G3: contracts §6/§7/§16 接口映射 .ts 文件 (估 0.5 天) 13. D-D4 + D-G1: RuntimeApp 启动序列命名/编号与 §22.2 对齐 (估 0.5 天) 14. F-D1/D2/D4: IpcKind 单一协议 + ExitCode 5 触发路径 + 父进程 env 白名单 (估 1 天) 15. J-D1-D5 + J-G1-G4: Provider 5 DEVIATION + 4 GAP (估 2 天) 16. H-D1/D2/D3/D4 + H-G2/G3/G4: Context 6 处偏离 (估 1 天) 17. M-D1-D4: Toolchain 4 处 API 漂移 (估 0.5 天) 18. N-D2 + N-G1-G3: Doctor 7-day retention + Recovery bootstrap + bundle (估 1 天) 19. K-G1/G3/G4 + K-E1/E2/E3: TUI 主题/键位/HUD/ephemeral/类型镜像 (估 1-2 天) 20. EXCESS 全部 (20 条): 死代码清理 (估 0.5-1 天)

总工作量估算:

  • P0: 6-9 天 (1 个工程师)
  • P1: 5-7 天
  • P2: 8-12 天
  • 合计: 19-28 工作日 (4-6 周)

7. 附录: 子系统审计发现数

子系统 CRITICAL DEVIATION GAP EXCESS 合计
A Contracts 4 6 3 4 17
B Storage 3 6 5 4 18
C Event 3 7 6 5 21
D Lifecycle 3 4 2 1 10
E Scheduler 5 8 4 0 17
F Worker/IPC 2 4 3 4 13
G Tool/Perm 3 4 5 5 17
H Context 1 5 4 2 12
I Artifact 3 4 3 1 11
J Provider 1 5 4 3 13
K Projection+TUI 1 2 5 3 11
L Agents 4 3 3 2 12
M Toolchain 0 4 0 2 6
N Doctor 2 6 3 2 13
合计 (去重前) 35 68 50 38 191
合并去重后 18 32 27 20 97

去重说明:

  • 多 agent 报告同一条 (如 C-2/C-3/C-4/C-10 都是 INV-1 事件链断裂的不同切面) 合并为 1 条
  • 工具缺注册 (G-D3) 与 contracts 缺接口 (A-G1) 因根因不同保留
  • 影响范围扩到 3+ 子系统的偏离被升级评估, 18 条 CRITICAL 包含 5 条根因型 (影响 7+ 子系统)

审计范围: 14 个子系统 + 0 个遗漏 报告字数: ~1500 字 (含表格) 未修代码: 严格遵守 Stage 3 汇总完成