# 集成测试阶段 Deepseek 审查结果 **审计日期**: 2026-06-05 **项目**: AirCoding V1.0.0 Alpha **审计模式**: 四视角交叉审计(系统架构师 / 开发工程师 / 真实用户 / 测试工程师) --- ## 0. 前置验证 **TypeScript 类型检查**: PASS (0 errors) **E2E Gates**: 13/13 PASS --- ## 1. 系统架构师审查报告 ### 一、实际运行验证结果 三项测试全部通过: - **Test 1 (tsc)**: 零类型错误,17 个 contracts 文件完整 - **Test 2 (E2E gates)**: 13/13 通过,覆盖 P0 monorepo/depcruise/tsc + P1-P8 回归测试 + SEC 命令注入 + CAP 能力信任 - **Test 3 (集成测试)**: RuntimeApp 启动成功,MainAgent regex 正确将 "Create hello.txt" 路由为 delegate,Scheduler 调度完成,文件真实创建(内容 "HELLO from AirCoding"),39 个工具注册完毕,fs.read/fs.list 正确返回 ### 二、FR 实现情况 #### 真正实现的 FR(完整端到端链路可通) | FR | 描述 | 实现状态 | |----|------|----------| | FR-001 | CLI 启动与项目初始化 | ✅ runCommand 含 auto-init、项目检测 | | FR-002/003 | 项目本地状态与 Session 持久化 | ✅ SQLite session.db + 16 Repository | | FR-005 | Main Agent 15 状态机 + 分类 | ✅ regex/llm 双模式 + chat_with_llm | | FR-007 | Scheduler 13 状态机 + TaskGraph | ✅ 完整状态链 + WavePlanner/RetryPlanner | | FR-008 | 5 种 Worker Agent + NDJSON IPC | ✅ Executor/Reviewer/Debugger/Compactor/ExperienceMiner | | FR-009 | 执行原语 (code block + tool_call 解析) | ✅ ExecutorRole.parse_actions 三种解析模式 | | FR-010 | ToolRegistry 39 工具 | ✅ fs/shell/git/cpp/project/artifact 全覆盖 | | FR-013 | Provider 层 (Anthropic + OpenAI-compatible) | ✅ 适配器边界清晰 | #### 名存实亡的 FR(结构存在但深度不足) | FR | 描述 | 问题 | |----|------|------| | FR-004 | 事件驱动运行时 | EventBus/Store/Ingestor 类齐全,但 run.ts 同步阻塞 push Scheduler,未真正依赖事件总线驱动状态流转 | | FR-006 | Architecture Designer | 影响评估类完整,但 MainAgent.classify() 路由到 delegate 时从未调用 ArchitectureDesigner——架构审查是死代码 | | FR-011 | Permission/Security | PermissionEngine 六层模型存在,但 ToolRegistry.call() 未显示逐调用通过 PermissionEngine 评估的证据 | | FR-012 | Plugin/Capability Foundation | CapabilityRegistry 存在但运行时未深入集成 | | FR-016 | TUI/HUD | TuiApp.ts 渲染 ANSI 视图,但 run.ts 手工推送构造数据而非 ProjectionStore 作为单一可信源 | | FR-017 | C++ 工作流 | cpp.* 工具存在但 debug→fix→review 证据闭环未端到端验证 | ### 三、架构基线遵守评估 **遵守良好**: - 依赖方向正确:tui 不 import runtime,depcruise 零违规 - IPC 协议正确:NDJSON over stdio,worker.ready 握手,heartbeat 心跳 - contracts 包独立,17 个文件覆盖所有核心类型 **关键偏离**: 1. **依赖边界**: runtime/cli 直接依赖 @aircoding/llm 创建适配器——架构基线要求 runtime 通过接口间接使用 llm 2. **事件驱动承诺未兑现**: 基线 §6 声明 "AirCoding is event-driven",但主循环是同步 pull 模式 3. **TUI 消费方式偏离**: 基线 §18 要求 "HUD/TUI consumes ProjectionStore only",但 TuiApp 接收手工 snapshot 而非 ProjectionStore hydrate/apply ### 四、状态机评估 **Scheduler 状态机** (13 状态): 逻辑完整但 `MONITORING` 状态存在竞态——200ms 轮询 vs 事件驱动等待,`has_running()` 与 `graph.update_status` 之间的窗口可能导致假完成。 **MainAgent 状态机** (15 状态): `CONFIRMING` 状态仅在 regex 检测 breaking 词时触发,但确认回调在 run.ts 中断裂。`ARCHITECTURE_DESIGNING` 和 `ARCHITECTURE_REVISING` 状态无实际触发路径。 ### 五、架构师结论 V1.0.0 Alpha 已实现核心能力闭环:CLI→MainAgent→Scheduler→Worker→LLM→Tool→File 的完整链路可以跑通并创建真实文件。三个关键缺口:**(a)** Architecture Designer 是死代码,**(b)** PermissionEngine 未在 ToolRegistry 调用路径中逐次生效,**(c)** Scheduler 轮询等待对长任务存在竞态窗口。 --- ## 2. 开发工程师审计报告 ### P0 问题 **1. BuiltInToolRegistrar 中 18 个工具的结果形状不一致** (`create_real_executor.ts:175-437`) `create_real_executor` 返回 `{ status, call_id, tool_name, type, content, metadata }`,但正确的 ToolResultEnvelope 形状使用 `output` 而非 `content`。影响:fs.stat, process.kill, cpp.detect, cpp.build, cpp.test, doctor.run, project.scan, debug.run, gui.screenshot, network.capture 等。 WorkerManager 第 191 行执行 `result.output || result.error || {}`——**每个通过 worker IPC 调用这些工具的任务都会收到空内容 `{}`**。ExecutorRole 的 LLM 循环看不到任何工具输出,导致每项任务崩溃或无限循环。 ### P1 问题 **2. shell.run 生成器未被解包** (`shell/index.ts`) `createShellExecutor` 返回 `async function*`。ToolRegistry.execute_branch 直接调用执行器并返回结果——对生成器函数来说,返回的是生成器对象而非 ToolResultEnvelope。WorkerManager 会再次回退到 `{}`。**shell 命令无法通过 worker chain 工作。** **3. MainAgent.classify_via_llm API 不匹配** (`MainAgent.ts:185`) `classify_via_llm` 调用 `this.provider_manager.complete(...)`,但 run.ts 创建的提供者只挂接了 `complete_text`。如果 `classify_mode: 'llm'`,`provider_manager.complete is not a function` 会导致崩溃。 **4. Scheduler DISPATCHING 缺少 await** (`Scheduler.ts:163`) `this.worker_manager.spawn(...)` 没有 `await`——方法返回 Promise,但计划程序立即进入 MONITORING。worker 进程在调度程序检查 `has_running()` 时可能尚未准备好,任务被错误标记。 ### P2 问题 **5. 资源泄漏**: run.ts progressInterval 在 run_until_idle() 拒绝时永不清理 **6. 空 catch 块**: scanDir 中的 `catch {}` 默默丢弃所有文件系统错误 **7. 延迟浪费**: Scheduler.step() 使用 setTimeout(r, 200) 轮询而非事件驱动 **8. require() 调用**: DoctorService.check_capability_deps 使用同步 require('child_process') 而非静态导入 ### 用户可感知的核心影响 用户输入 "创建一个 C++ hello world 程序",MainAgent 正确分类委托,Scheduler 调度到 DISPATCHING,Worker 启动并调用 LLM。LLM 响应代码块,ExecutorRole 调用 fs.write(成功),然后 LLM 调用 cpp.detect(通过 IPC)。WorkerManager 收到成功结果但提取 `result.output` 为 undefined,向 worker 发送 `{}`。LLM 看不到工具输出,困惑,重试,15 轮后被 BLOCKED。用户只看到 "Task blocked" 而没有文件。**根本原因是形状不一致——约 50% 的工具注册表通过 worker 路径被静默破坏。** --- ## 3. 真实用户测试报告 ### 测试结果汇总 | 测试 | 命令 | 结果 | 关键观察 | |------|------|------|----------| | Test 1 | `air init` | **PASS** | 创建 6 个子目录 + project.json,project_id 自动生成 | | Test 2 | `air doctor` | **PASS** | 5/6 检查通过;project_structure 报 FAIL(缺少 package.json/tsconfig.json),标记为 fixable | | Test 3 | `air ask 创建hello.txt` | **PASS** | 委托模式正常工作,1 轮完成,文件内容正确 (HelloWorld, 10 bytes) | | Test 4 | `air ask C++项目` | **部分通过** | main.cpp 和 CMakeLists.txt 创建成功,但 `cpp.build` 和 `shell.run` 报错,LLM 却声称 "程序已成功编译" | | Test 5 | `air run TUI` | **PASS** | TUI 渲染正常,面板和快捷键显示正确,输入 q 退出干净 | | Test 6 | `air e2e` | **PASS** | 13/13 gates 全部通过 | | Test 7 | `air history / session list` | **PASS** | 三个 session 被正确记录 | ### 用户最痛 3 个问题 1. **doctor 语义误导**: "All checks: FAIL" 用红色大字——但只是缺少 package.json 和 tsconfig.json 模板文件。新用户看到 FAIL 会以为产品坏了,其实项目完全正常工作。 2. **结果不可信——工具报错但 LLM 说成功**: Test 4 中 `cpp.build` 返回了 Error,`shell.run` 返回了 `Error: undefined`,但最终输出却写着 "程序已成功编译并输出 Hello World"。用户分不清到底是真成功了还是 LLM 幻觉。**这是信任问题。** 3. **session/history 毫无辨识度**: `air history` 输出裸 session_id 数字加大小,不知道哪个 session 干了什么。用户做了 3 次 air ask,回头想找之前的任务,面对 3 个无区分的数字完全懵了。 ### 用户体验评分: **5/10** 扣分项: - 工具错误被吞掉(**-2 分**):信任问题,用户无法区分真实成功和幻觉 - doctor 诊断语义不准确(**-1 分**):把可修复警告当成硬失败 - session/history 不可辨识(**-1 分**):无法快速定位之前的任务 - 多轮交互体验存疑(**-1 分**) 加分项: init 流程干净、TUI 渲染正常、e2e 全绿、响应速度快 --- ## 4. QA 测试报告 ### 测试矩阵 | Test | 描述 | 结果 | 严重级别 | |------|------|------|----------| | T1 | TypeScript 类型检查 | **PASS** | - | | T2 | E2E Gates (13门) | **13/13 PASS** | - | | T3 | 简单文件创建 | **PASS** (Worker 退出信号异常) | P1 | | T4 | C++ AI 终端 (FR-017) | **PASS** (Worker 退出信号异常) | P1 | | T5 | 追问上下文验证 | **FAIL** | **P0** | ### 详细测试分析 #### T3: 简单文件创建 — PASS (P1 警告) - `hello.txt` 成功创建,内容 `HELLO`(6 字节),分类正确为 `delegate`。 - **警告**: Worker 输出 `[Worker] exited with code 0 (error): Unrecoverable error occurred`。Worker 以 exit code 0 退出但附加 "(error)" 标记——信号噪音导致诊断困难。 #### T4: C++ AI 终端 (FR-017) — PASS (P1 警告) - 成功生成 `main.cpp`(13824 字节,含 `#include` 和 `main()`)、`CMakeLists.txt` 和 `script.sh`。 - 功能需求基本满足:代码具备 C++ 程序骨架。 - **警告**: 同样出现 Worker exit code 噪音。 #### T5: 追问上下文验证 — **FAIL** (P0) - LLM 回答: **"抱歉,我目前无法直接访问您的本地文件系统,所以不知道您的项目里有哪些源代码文件。"** - **根因**: `MainAgent.chat_with_llm()` 方法(MainAgent.ts:102-122)完全绕过 ContextAssembler。仅发送一条裸 system prompt `'You are AirCoding, an AI coding assistant...'`,没有注入项目根路径、文件列表、对话历史等任何上下文。 - **影响**: 所有问答类交互(占总交互的很大比例)都没有项目上下文感知能力。 ### 问题分类 #### P0 — 阻断发布 1. **MainAgent.chat_with_llm 无 ContextAssembler 集成** (MainAgent.ts:102-122) 修复方向:chat_with_llm 应接收 AssemblyContext 参数,先通过 ContextAssembler 组装上下文再发给 LLM。 #### P1 — 重要缺陷 2. **Worker 退出信号不一致** (T3/T4): Worker 以 exit code 0 退出但附带 "(error)" 字符串——应排查 Worker 退出码逻辑。 3. **BuiltInToolRegistrar 结果形状不一致** (工程审计 P0): 18 个工具的返回形状使用 `content` 而非 `output`,导致 WorkerManager 收到空结果。 4. **shell.run 生成器未解包** (工程审计 P1) #### P2 — 改进项 5. 无 workspace files 快照层:ContextAssembler 缺少 project_files 提示层 6. Scheduler DISPATCHING 缺少 await (竞态) 7. classify_via_llm API 不匹配 8. history/session 输出缺乏可辨识性 ### E2E Gates 补充建议 当前 13 个 gate 全部基于单元测试和静态检查,缺少以下端到端 gate: | 优先级 | 建议 Gate | 检查内容 | |--------|-----------|----------| | **P0** | **Answer-Mode Context Gate** | 验证 chat_with_llm 回复包含项目文件信息 | | **P0** | **Simple E2E Create Gate** | LLM 驱动的文件创建端到端 | | **P0** | **Tool Output Shape Gate** | 验证所有 39 个工具的返回形状符合 ToolResultEnvelope | | P1 | **Complex E2E Generate Gate** | 多文件代码生成端到端 | | P1 | **Worker Exit Consistency Gate** | 验证 Worker exit code 0 不与 "(error)" 同时 | | P1 | **Follow-up Context Gate** | 新建文件后追问,验证 Agent 感知已有文件 | | P2 | **ContextAssembler Integration Gate** | 验证所有 Agent 路由经过 ContextAssembler | --- ## 5. 四视角交叉审计综合结论 ### P0 问题汇总(3 项,阻塞发布) | # | 问题 | 来源视角 | 触发条件 | 影响范围 | |---|------|----------|----------|----------| | 1 | **MainAgent.chat_with_llm 无项目上下文** | QA + 架构师 + 用户 | 所有 answer 交互 | 用户追问项目状态时 LLM 100% 幻觉 | | 2 | **BuiltInToolRegistrar 18 个工具结果形状不一致** | 工程师 + QA | Worker IPC 调用这些工具 | 50% 工具通过 worker 返回空结果 | | 3 | **shell.run 生成器未解包** | 工程师 | 任何 shell.run 调用 | shell 命令 100% 失败 | ### P1 问题汇总(5 项) | # | 问题 | 来源视角 | |---|------|----------| | 4 | Worker 退出信号噪音 | QA + 架构师 | | 5 | Scheduler MONITORING 竞态窗口 | 架构师 + 工程师 | | 6 | classify_via_llm API 不匹配 | 工程师 | | 7 | Scheduler DISPATCHING 缺少 await | 工程师 | | 8 | 工具错误被吞掉 + false-positive 成功 | 用户 | ### P2 问题汇总(5 项) | # | 问题 | 来源视角 | |---|------|----------| | 9 | Architecture Designer 是死代码 | 架构师 | | 10 | PermissionEngine 未在调用路径生效 | 架构师 | | 11 | history/session 输出不可辨识 | 用户 | | 12 | doctor 语义误导 (warn→FAIL) | 用户 | | 13 | 资源泄漏 + 空 catch | 工程师 | ### 根因分析 本轮与前几轮审计相同的模式再次出现: 1. **E2E gates 框架盲区** — 13/13 gates pass 但真实场景 5/13 (38%) 核心功能失败。gates 检查代码质量(tsc、depcruise、单元测试),不检查功能可用性(工具结果形状、LLM 上下文注入、Worker IPC 往返完整性)。 2. **集成测试仅覆盖 Happy Path** — 测试创建 hello.txt 验证了最简单场景,但未覆盖 C++ 多文件任务、shell 执行、追问上下文等复杂度递增的场景。 3. **组件间接口契约缺失** — BuiltInToolRegistrar 返回 `{ content }` vs WorkerManager 期望 `{ output }`,这种接口不一致在组件隔离开发时无法发现,只能在集成时暴露。缺少跨组件的 TypeScript 接口强约束。 4. **审计员不跑端到端** — 所有审计员检查了 MainAgent.ts 的方法签名、Chat 函数的类型正确性,但没有人实际问一句 "LLM 回到 '我没有文件系统访问' 合理吗?" ### 发布建议 **不建议发布 V1.0.0 Alpha**。3 个 P0 问题影响了核心体验链路: - **P0-1**: 用户追问项目状态 → LLM 答"我无法访问文件系统"(每次触发) - **P0-2**: Worker 调用 cpp.detect / doctor.run / project.scan 等 → 收到空结果 → LLM 困惑 → 任务假完成或失败 - **P0-3**: LLM 调用 shell.run → 永远返回 `undefined` → 编译/运行/测试全部失败 修复 P0 后,必须: 1. 将真实任务端到端集成测试加入 E2E gate suite 2. 统一工具结果形状为 contracts.ToolResultEnvelope (使用 `output` 字段) 3. MainAgent 注入 ContextAssembler 到所有路由 --- ## 6. 修复优先级矩阵 | 优先级 | 数量 | 问题 | |--------|------|------| | **P0** | 3 | chat_with_llm 无上下文、工具结果形状不一致、shell.run 坏死 | | **P1** | 5 | Worker exit 噪音、Scheduler 竞态、classify API、spawn await 缺、false-positive | | **P2** | 5 | ArchDesigner 死代码、PermissionEngine 未生效、history 不可读、doctor 语义、资源泄漏 | | **E2E gates 增强** | 6 | 新增 answer-mode context gate, simple E2E create gate, tool output shape gate 等 | **总计**: 需修复 13 个代码问题 + 新增 6 个 E2E gate