AirCoding V1.0.0 Alpha — Opus 开发阶段审计报告
审计员: Claude Opus 4.8 (1M context)
审计日期: 2026-06-02
审计方法: 4 个独立子代理对照规范文档逐文件交叉审查
审计依据: interface-contracts-v1, db-schema-v1, event-registry-v1, security-model-v1, tool-registry-v1, capability-trust-v1, prompt-layering-v1, provider-capability-matrix-v1, scheduler-state-machine-v1, runtime-semantics-v1, scope-escalation-v1, main-agent-state-machine, error-taxonomy-v1, c4/code-view, system-detailed-design (§7/8/13/14/15/16/17/22)
审计范围: 全部 146 个源文件 vs 全部规范文档
执行摘要
总体评级:C+ — 骨架完整,规范符合度低,存在阻断级缺陷
与 DeepSeek 审计(侧重发现问题数量)不同,本次 Opus 审计逐字段对照规范文档,得出更严峻的结论:
核心发现:packages/contracts/src/ 中的规范契约忠实地编码了全部规范文档,但下游实现(runtime/llm/workers/tui/toolchain-cpp)系统性地重新定义了本地的、与契约冲突的类型,几乎不 import 契约。这导致大量"实现存在但与规范不符"的偏差。
关键指标对比
| 维度 |
DeepSeek 审计 |
Opus 审计(本报告) |
| 发现总数 |
97 |
140+ |
| 审计深度 |
阶段级 |
字段级/逐行 |
| 契约对照 |
部分 |
全部 16 合约文件 |
| 状态机验证 |
否 |
是(Scheduler/MainAgent 逐状态) |
| 阻断级缺陷 |
10 |
18 |
阻断级缺陷速览(18 项)
| # |
缺陷 |
文件 |
后果 |
| 1 |
workspace 投影写入非法枚举 'created'/'merging' |
EventStore.ts:900,909 |
workspace.created 持久化必抛错 |
| 2 |
项目级 DB 表名/路径/列全面偏离 db-schema §20 |
DebugKnowledgeStore.ts, LearnedMemoryStore.ts |
与契约无法对接 |
| 3 |
route_prefix 查询用 . 拼接但存储用 / |
EventRepository.ts:185 |
多段路由前缀过滤永久失效 |
| 4 |
TaskAttemptRepository 复制粘贴 bug |
TaskAttemptRepository.ts:114 |
failure_signature 列永不更新 |
| 5 |
ToolRegistry 权限上下文硬编码 undefined |
ToolRegistry.ts:262-263 |
权限模型被完全旁路 |
| 6 |
ACTION_BRANCHES 内 this.* 调用崩溃 |
ToolRegistry.ts:62,72 |
read_only/sandbox 分支运行时崩溃 |
| 7 |
ModelConfig.api_key 明文内嵌 |
ModelConfigLoader.ts:17 |
违反 auth_ref 规范,密钥泄露 |
| 8 |
Scheduler 状态机缺 BLOCKED/CANCELLED |
Scheduler.ts:18-29 |
无法表达 5 处规范转换 |
| 9 |
WorkerProcess 退出码 4 错配为 blocked |
WorkerProcess.ts:17,30 |
parent-cancelled 语义丢失 |
| 10 |
命令注入 — CMakeConfigurator |
CMakeConfigurator.ts:40 |
execSync 字符串拼接 |
| 11 |
命令注入 — CppBuilder |
CppBuilder.ts:27 |
LLM 可控 target 注入 |
| 12 |
命令注入 — CppcheckRunner |
CppcheckRunner.ts:36 |
project_root 注入 |
| 13 |
C++ 工具绕过 PermissionEngine |
CppToolRegistrar.ts:23 |
违反 INV-3 |
| 14 |
INV-2 outbox 完全未发事件 |
wiring.ts:35-73 |
跨 DB 一致性断裂 |
| 15 |
DeveloperLogEncryptor 硬编码弱密钥 'dev-key' |
DeveloperLogEncryptor.ts:22 |
日志加密等同明文 |
| 16 |
CapabilityTrustLevel 用错误枚举值 |
CapabilityManifestValidator.ts:19 |
信任模型失效 |
| 17 |
PermissionEngine 缺 block/refuse/announce_then_run |
PermissionEngine.ts:19-26 |
无法执行高风险拒绝/备份 |
| 18 |
ProjectionClient↔ProjectionStore 从未连接 |
(全仓) |
投影数据无法到达 TUI |
第一部分:契约层审计(packages/contracts)
评级:✅ 忠实编码规范(少量缺失)
合约层是整个项目最符合规范的部分。16 个文件忠实编码了 interface-contracts-v1 的 §2-§21。
| 合约区块 |
状态 |
说明 |
| §2 ID 别名 (17) + Clock/IdGenerator |
✅ |
完全一致 (ids.ts) |
| §3 ErrorKind(22)/Severity/Retryability/AirError |
✅ |
字段完全匹配 (error.ts) |
| §4 EntityType(12)/EntityRef |
✅ |
一致 (event.ts) |
| §5 RuntimeEvent/EventSource/EventFilter |
✅ |
一致 |
| §6 SessionRecord/MessageRecord |
⚠️ |
定义在 runtime 而非 contracts(违反 §22.1) |
| §6 PersistedEventRecord/PersistedEventInsert |
❌ |
contracts 包完全缺失 |
| §7 EventBus/EventStore/EventIngestor/SchemaRegistry 接口 |
❌ |
6 个核心接口在 contracts 中全部缺失(仅作 runtime class 存在) |
| §8-§21 其余契约 |
✅ |
大部分一致 |
| §16 ContextAssembler/CompactionPolicy 接口 |
❌ |
contracts 中未找到 |
关键发现: 契约层缺失存储/事件层接口定义,导致下游实现"无契约可依",进而各自定义本地类型。
第二部分:P1 存储与事件审计
评级:⚠️ 表结构正确,投影与项目级 DB 有阻断缺陷
| 检查项 |
状态 |
详情 |
| 17 张会话表全列匹配 |
✅ |
MigrationRunner.ts 逐列核对 db-schema §2-§18 |
| 55 持久 + 7 短暂事件注册 |
✅ |
程序化 diff 验证零差异 |
| EventStore.project() 域投影 |
⚠️ |
session/task/agent/tool/command 等已覆盖 |
| workspace 投影非法枚举 |
❌ |
status:'created'/'merging' 不在闭合枚举 → assertEnum 抛错 |
| context.compaction. 缺投影* |
❌ |
4 个事件落入 default,规范要求标记压缩任务 |
| debug-records.db schema |
❌ |
路径 .air/shared (应 .air/local),列集合全面偏离 |
| learned-memory.db schema |
❌ |
表名 learned_memory (应 learned_memories),列偏离 |
| route_prefix 查询 bug |
❌ |
EventRepository.ts:185 用 . 拼接但存储用 / |
| TaskAttempt update bug |
❌ |
failure_signature 分支错误 push failure_summary |
| EventBus.subscribe 返回 Subscription |
⚠️ |
缺 unsubscribe() 方法 |
| EventStore.append 缺 EventAppendOptions |
⚠️ |
无乐观并发校验、无外部事务复用 |
| INV-1 status 写入 |
✅ |
5 仓库已修复为硬编码默认值 |
第三部分:P2 工具/权限/能力审计
评级:❌ 系统性偏离规范,存在权限旁路
这是问题最严重的阶段。实现几乎全部重新定义本地类型,忽略契约。
3.1 PathClassifier vs security-model §4(8 路径类别)
| 规范类别 |
实现 |
状态 |
| project_air_shared / project_air_local |
笼统归入 project_internal |
❌ 缺失 |
| project_git |
混入 project_internal |
❌ 缺失(.git 需独立保护) |
| credential_store |
无(~/.ssh 归为 user_home) |
❌ 缺失(安全关键) |
| unknown |
默认归类为 project_config |
❌ 方向错误(应保守) |
8 个规范类别仅对应 3 个,且全部命名不一致。
3.2 PermissionEngine vs security-model §13
| 项 |
状态 |
详情 |
| 6 层评估顺序 |
✅ |
capability→profile→task_scope→risk→credential→prompt |
| PermissionAction 枚举 |
❌ |
缺 block/refuse/announce_then_run;多 read_only/sandbox/audit_log |
| PermissionDecision 结构 |
❌ |
缺 grant_scope/risk_level/backup_required/evidence_refs |
| profile 概念 |
❌ |
被替换为 AgentType,缺 low/normal/high/developer 四档 |
| capability/prompt 层 |
⚠️ |
桩实现,恒 allow |
| record 发事件 |
❌ |
仅 push 内存数组 |
| decision.redacted 字段 |
❌ |
ToolRegistry 引用不存在的字段 |
3.3 ToolRegistry vs tool-registry-v1
| 项 |
状态 |
详情 |
| 权限上下文硬编码 undefined |
❌ |
build_permission_context 把 task_scope/profile 设为 undefined → Layer 2/3 恒放行,权限旁路 |
| ACTION_BRANCHES this 崩溃 |
❌ |
模块级常量内 this.downgrade_to_readonly → 运行时 TypeError |
| 6 分支 |
❌ |
仅 allow/deny 正确,缺 block/refuse/announce_then_run |
| 生命周期事件 |
❌ |
无 tool.started/completed/failed 发射 |
| schema 校验 |
❌ |
validate_input 自承"simplified" |
| 28 个 MVP 工具 |
❌ |
仅 ~7 个命中,cpp/debug/gui/network/process/fs.stat 全缺 |
3.4 CapabilityTrustLevel vs capability-trust-v1
| 规范值 |
实现 |
状态 |
| built_in |
core |
❌ 错误值 |
| project_local |
无 |
❌ 缺失 |
| user_installed |
无 |
❌ 缺失 |
| verified_publisher |
无 |
❌ 缺失 |
| untrusted |
untrusted |
✅ |
| — |
trusted |
❌ 规范外 |
实现 core/trusted/untrusted 中仅 1 个命中。
第四部分:P3 提供者/上下文审计
评级:❌ 能力矩阵严重不全,上下文 L5-L9 未实现
4.1 ProviderCapabilityMatrix vs provider-capability-matrix-v1
| 规范 supports 字段 |
实现 |
状态 |
| 16 个能力字段 |
仅 ~7 个(命名偏差) |
❌ 一半缺失 |
| quality_tier |
无 |
❌ 缺失(模型选择核心) |
| cost_tier |
无 |
❌ 缺失 |
| default_use(按角色) |
无 |
❌ 缺失(Scheduler 分配依赖) |
| max_tokens_output: 200000 |
数据错误 |
⚠️ 把上下文窗口误填为 output |
4.2 ContextAssembler vs prompt-layering-v1 (L0-L9)
| 层 |
状态 |
详情 |
| L0 runtime_invariant |
✅ |
加载正确 |
| L1 role |
⚠️ |
仅支持 worker 角色,main/architecture/scheduler 无法加载 |
| L2 safety |
⚠️ |
硬编码字符串,非来自 permissions.yaml |
| L3 project_rules |
⚠️ |
路径/来源不符,缺全局与 toolchain rules |
| L4 architecture |
⚠️ |
无 AGENTS.md/plan.md/ADR 加载 |
| L5 task_spec |
❌ |
硬编码假任务"Current Task" |
| L6 evidence |
❌ |
TODO 未实现 |
| L7 conversation |
❌ |
TODO 未实现 |
| L8 tool_output |
❌ |
TODO 未实现 |
| L9 user_override |
❌ |
TODO 未实现 |
| Anthropic canonical 输出 |
❌ |
用 {role,content:string} 非 content blocks |
第五部分:P4 Worker IPC / 调度器审计
评级:❌ 状态机终态模型错误,核心状态为存根
5.1 Scheduler 状态机(11 状态)
| 规范状态 |
实现 |
评级 |
| IDLE/LOADING_GRAPH/PLANNING_WAVE |
存在 |
⚠️ 转换简化 |
| DISPATCHING |
🔧 存根 |
未创建 workspace/context/事件 |
| MONITORING |
⚠️ |
缺 cancel/blocker 转换 |
| COLLECTING_RESULTS/MERGING/REVIEWING_WAVE/REPAIRING |
🔧 存根 |
无条件跳转 |
| COMPLETED |
✅ |
终态 |
| BLOCKED |
❌ |
SchedulerState 联合类型根本没有 |
| CANCELLED |
❌ |
同上 |
| TERMINATED |
⚠️ |
规范中不存在的多余状态 |
5.2 其他 P4 发现
| 项 |
状态 |
详情 |
| RetryDecision 6 枚举 |
✅ |
齐全 |
| RetryPlanner.skip 分支 |
❌ |
decide() 从不返回 skip |
| RetryPlanner 未接线 |
❌ |
Scheduler 仅注释,不调用 decide() |
| 退出码 4=parent cancelled |
❌ |
错配为 blocked |
| 工作空间三策略枚举 |
✅ |
main/worktree/isolated_copy |
| worktree git merge |
🔧 存根 |
仅改内存 state |
| Recovery 8 步 |
🔧 |
仅第 5 步实现,其余存根/缺失 |
| ScopeImpactLevel |
❌ |
未定义(scope-escalation §13 必须) |
| BlockerReport |
❌ |
角色仅返回裸 {error} |
| WorkerProtocol 方向验证 |
✅ |
逻辑正确,但未知类型放行 |
第六部分:P5 C++ 工具链审计
评级:❌ 命令注入 + 绕过权限 + signature 格式错误
| 项 |
状态 |
详情 |
| 命令注入 ×3 |
❌ |
CMakeConfigurator/CppBuilder/CppcheckRunner execSync 拼接 |
| 绕过 PermissionEngine |
❌ |
CppToolRegistrar executor 直接 execSync(违反 INV-3) |
| semantic_signature 格式 |
❌ |
输出 diag_<hex>,应为 <kind>:<surface>:<class>:<loc>:<hash> |
| signature 丢弃 line/column |
⚠️ |
同消息不同位置会冲突 |
| 无 LLM |
✅ |
纯正则+哈希 |
| ClangdClient |
🔧 |
两方法纯存根 |
| find_cpp_sources |
🔧 |
永远返回 [] |
| 错误映射 AirError |
❌ |
仅返回 {ok:false},无 kind/retryability |
| capability.ts 类型 |
✅ |
已修复对齐 CapabilityManifestV1 |
第七部分:P6 投影 / TUI 审计
评级:❌ 投影不符契约,数据链路断裂
| 项 |
状态 |
详情 |
| ProjectionStore 实现契约 §17 |
❌ |
方法签名全错 |
| 8 类投影 |
❌ |
仅有 tasks/agents,缺 tool_runs/command_runs/artifacts/permission_prompts/blockers/updated_at |
| apply 处理事件名 |
❌ |
处理 task.status.changed 等不存在的事件名 |
| 订阅 EventBus |
❌ |
无注入/订阅 |
| ProjectionClient↔Store 桥接 |
❌ |
receive_snapshot 无调用者,投影到不了 TUI |
| TUI 仅渲染(INV-4) |
✅ |
组件纯函数,仅 import contracts |
| TUI 实际渲染 |
🔧 |
render() 仅 console.log,无 OpenTUI 依赖 |
| PermissionPrompt UiCommandChannel |
❌ |
用回调,UiCommandChannel 全仓零引用 |
| HUD 三预设 |
✅ |
Full/Essential/Minimal |
第八部分:P7 Agent 集成审计
评级:❌ MainAgent 状态机缺 7 态,INV-2 未发事件
8.1 MainAgent 状态机(13 状态)
| 项 |
状态 |
详情 |
| 实现状态数 |
❌ |
仅 6 态,缺 CLASSIFYING/SCHEDULING/ARCHITECTURE_DESIGNING/EXECUTING/INTERRUPTING 等 7 态 |
| CLASSIFYING 经 LLM |
❌ |
用正则匹配首词,规范要求 LLM |
| DELEGATING 分支 |
❌ |
硬编码 tasks:['task-1'],无 Scheduler 调用 |
| /direct /done 触发 |
⚠️ |
用正则非命令 |
| permission_template 映射 |
❌ |
无 main_direct 设置 |
| requirement.changed |
❌ |
缺失 |
8.2 INV-2 Outbox
| 项 |
状态 |
详情 |
| debug.record.created 发射 |
❌ |
wiring.ts 写库后仅注释,无 ingest |
| memory.promoted 发射 |
❌ |
同上,且 status='draft' 与 promote 语义矛盾 |
| 单写者结构 |
✅ |
每 store 独立 db |
| 外部失败补偿 |
❌ |
无 task.failed 路径 |
| ArchitectureDesigner 经 LLM |
❌ |
关键字匹配,无 ProviderManager |
| 四类结果枚举 |
✅ |
齐全 |
第九部分:P8 CLI / Doctor / RuntimeApp 审计
评级:❌ DI 容器虚设,Doctor 多为存根
| 项 |
状态 |
详情 |
| DoctorService 契约签名 |
❌ |
run_diagnostics vs 契约 run(input) |
| self_bootstrap 顺序 |
✅ |
先于 capability |
| self_bootstrap 真实性 |
⚠️ |
sqlite/shell 硬编码 passed:true |
| capability 检查 |
❌ |
全硬编码 passed:true |
| read_only/fix/bundle 三模式 |
❌ |
fix/bundle 存根 |
| doctor.* 事件 |
❌ |
无发射 |
| ServiceRegistry 使用 |
❌ |
RuntimeApp/createRuntime 均绕过,自行 new |
| RuntimeApp 服务完整 |
❌ |
缺 ProjectStore/SessionManager/Event* |
| shutdown 清理 |
🔧 |
仅 log |
| CLI 命令表(11) |
✅ |
全覆盖 |
| CLI 副作用经 RuntimeApp |
❌ |
doctor 直接 new DoctorService |
| run 启动 TUI |
🔧 |
console.log 占位 |
| Logger 双日志 |
⚠️ |
只写 air.log,不写 developer.log |
| DeveloperLogEncryptor 连接 |
❌ |
无调用者,且硬编码弱密钥 |
第十部分:不变量合规总评
| 不变量 |
DeepSeek 评级 |
Opus 评级 |
关键差异 |
| INV-1 Status 投影 |
✅ |
⚠️ |
Opus 发现 workspace 投影写非法枚举 + Scheduler/WorkspaceManager 仅改内存 |
| INV-2 Outbox |
⚠️ |
❌ |
完全未发事件,跨 DB 一致性断裂 |
| INV-3 副作用门控 |
⚠️ |
❌ |
ToolRegistry 权限旁路 + C++ 工具绕过 PermissionEngine |
| INV-4 导入方向 |
✅ |
✅ |
一致通过 |
| INV-5 EventBus 传输 |
✅ |
✅ |
一致通过(但 rebuild 是存根) |
第十一部分:与 DeepSeek 审计的对比结论
| 方面 |
DeepSeek |
Opus |
| 总体评级 |
B+ |
C+ |
| 侧重 |
问题计数 + 高层分类 |
逐字段对照规范 |
| 独特发现 |
— |
权限旁路、状态机终态缺失、能力矩阵不全、ProjectionClient 断裂、退出码错配、signature 格式错误 |
| 共识 |
命令注入、INV-2 未实现、合约漂移、存根率高 |
同 |
Opus 的更严峻判断:DeepSeek 评 B+ 反映"文件齐全、骨架正确";Opus 评 C+ 反映"逐字段对照规范后,实现与规范的偏差是系统性的,且包含权限旁路这一安全致命缺陷"。
第十二部分:整改优先级
P0 — 安全致命(发布前必修)
- ToolRegistry 权限旁路(ToolRegistry.ts:262-263)— 真实加载 task_scope/profile
- ACTION_BRANCHES this 崩溃(ToolRegistry.ts:62,72)— 改为实例方法或独立函数
- 3 处命令注入(CMake/CppBuilder/Cppcheck)— execSync → execFileSync + args 数组
- C++ 工具绕过 PermissionEngine — 经 CapabilityRegistry.register_tools
- 明文 API key(ModelConfigLoader.ts:17)— 改用 auth_ref
- 硬编码弱密钥 'dev-key' — 强制 env 变量
P1 — 阻断运行时
- workspace 投影非法枚举 — 修正为合法 workspaces.status 值
- route_prefix 查询
. vs / — 统一分隔符
- TaskAttempt update bug — 修正 failure_signature 分支
- Scheduler 缺 BLOCKED/CANCELLED — 补回状态
- 退出码 4 错配 — 4=parent cancelled, 5=hard timeout
P2 — 规范符合
- INV-2 outbox 发事件 — wiring/stores 注入 EventIngestor
- ProjectionClient↔Store 桥接 — 接通投影数据链路
- 下游 import 契约类型 — 删除本地重定义(PermissionAction/TrustLevel/Diagnostic/投影)
- 项目级 DB schema — 对齐 db-schema §20
- semantic_signature 格式 — 对齐 error-taxonomy §6
P3 — 完整性
- ContextAssembler L5-L9、Recovery 8 步、ClangdClient、MainAgent 状态机、Doctor 检查、TUI OpenTUI 集成
附录:审计方法论
本次审计派发 4 个独立 general-purpose 子代理,每个负责 2-3 个阶段:
- 代理 1: contracts + P1(存储/事件)— 266K tokens, 44 工具调用
- 代理 2: P2(工具/权限/能力)+ P3(提供者/上下文)— 160K tokens, 24 工具调用
- 代理 3: P4(Worker/调度器状态机)— 134K tokens, 29 工具调用
- 代理 4: P5-P8(C++/TUI/Agent/CLI)— 154K tokens, 44 工具调用
每个代理先完整阅读对应规范文档,再逐文件对照实现,输出 ✅符合/⚠️偏差/❌缺失/🔧存根 四级评定,附精确 文件:行。
合约文件被全部 4 个代理交叉引用,确保契约层评估的一致性。
报告结束 — 共发现 140+ 项,其中 18 项阻断级。建议按整改优先级 P0→P3 顺序处理。