# 集成测试阶段 MiniMax-M3 审查结果 **审计日期**: 2026-06-05 **项目**: AirCoding V1.0.0 Alpha **审计员**: MiniMax-M3 (整合阶段) **审计模式**: 四视角交叉审计(系统架构师 / 开发工程师 / 真实用户 / 测试工程师) --- ## 0. 核心矛盾 (E2E Gates 失真) 13/13 E2E gates 全部通过,但用户视角测试**真实任务成功率近乎为零**。 | 维度 | 表现 | |---|---| | tsc typecheck | 0 errors | | 单元测试 | 169/169 passed | | E2E gates | 13/13 passed | | 真实用户场景 | **多数失败** | E2E gates 仅验证"测试能跑通"和"组件存在",**从未验证"用户场景成功"**。所有 gate 仅检查语法、类型、stub 数量、单元测试通过率;没有一项 gate 验证"LLM 调通 + 文件真的写出 + 多步骤任务真完成"。 --- ## 1. 系统架构师审查 ### FR-005 (Main Agent 对话) — 部分实现 `MainAgent.chat_with_llm()` 每次调用仅构造 system+user 两条消息,**无 conversation history**,无 context reference,无 Anthropic canonical content blocks——严重违反 FR-014 上下文分层。 追问"现在什么情况"时,LLM **没有上下文**,是 stateless 单轮调用,必然幻觉。 ### FR-016 (TUI) — 不支持交互输入 `TuiApp.setup_input` 只处理 `q/1/2/3/4/h` 键盘事件,**无文本输入路径**。`run.ts` 用 `readline` 在 TUI 之外独立处理 stdin,TUI 和 CLI 互相竞争字符。TUI 实际是**只读 viewer,不能输入任务**。 ### FR-007/008 (Scheduler/Worker) — 链路通但判定错误 Worker 真实 spawn,IPC 真实 NDJSON,tool.call / llm.request 通过 IPC 回父进程由 ProviderManager 真实调用 LLM——**链路是通的**。 但 `Scheduler.step` 的 `MONITORING` 状态存在严重 bug:worker 还在跑就 mark `completed`,任务可能"假完成"。 ### FR-009 (执行原语) — 不强制 read-before-edit `ExecutorRole` 直接接受代码块写入,**不强制 read-before-edit**——违反 FR-009。run.ts 的"扫描最近 60 秒修改的文件"是 post-hoc 发现,不验证文件来源、不执行 verification-before-completion。 ### FR-017 (C++ 完整闭环) — 工具链与主链路不联动 `toolchain-cpp` 实现了 cpp.detect / cpp.build / cpp.test 工具,但**无 fixture 项目、无自动 configure→build→test→fix→review e2e 集成**。Executor 用 fs.write 写 C++ 源文件,**不调用任何 cpp.* 工具**。C++ 工具链对用户不可见地存活,但与主链路不联动。 ### 未对齐设计的关键差异 | 设计 | 实际 | |---|---| | ProjectionStore 消费 DB+EventBus | `run.ts` 直接 `receive_snapshot` 构造假数据绕开 EventStore | | 严格状态机 12 态 | 真实遍历,但 MONITORING 完成判定错误 | | 5 角色独立 worker | Debugger/Compactor/ExperienceMiner 未被 run.ts 触发 | | Anthropic canonical messages | MainAgent 用 string content,非 content block[] | --- ## 2. 开发工程师 Bug 报告 ### P0 阻塞 (2) **Bug #2 — Scheduler 早判完成** (Scheduler.ts:252-260) 当 `worker_manager.has_running() === false` 时,将**所有** `running` 状态任务直接标记为 `completed`,**不管 worker 是否实际成功**。失败任务可能显示为成功。 **Bug #6 — MainAgent 确认门形同虚设** (run.ts:108-112) `MainAgent.classify()` 对"delete/remove"类消息返回 `{action: 'delegate', response: 'Are you sure? (y/n)'}`,但 `run.ts:115` 直接 `console.log` `classification.response` 并 `rl.prompt()`——**用户的 y/n 永远到不了 `MainAgent.handle_confirmation()`**。破坏性操作无防护。 ### P1 重要 (3) **Bug #3 — ExecutorRole 转义顺序错误** (ExecutorRole.ts:222) 代码块内容转义还原顺序:`\\n → \n`, `\\t → \t`, `\\" → "`, `\\\\ → \\`。若 LLM 输出 `\n`(单反斜杠 n),会被错误地换成真换行,破坏 JSON/Python 字面量。 **Bug #4 — MainAgent 不带上下文** (MainAgent.ts:73) `chat_with_llm(message)` 只发送单轮 system + user。追问"现在什么情况"时,**LLM 不知道项目里有啥**。 **Bug #5 — DONE 竞态** (ask.ts:182-186) 若 LLM 单次输出既有 `fs.write` 又有 `DONE`,执行完 tool_call 后立即返回 `completed`。**剩余未完成的 acceptance_criteria 被静默忽略**。 **Bug #7 — 多文件任务漏写** 第一次写到 `src/main.cpp`(正确),第二次写到根 `main.cpp`(简化版 stub)。两个 task 缺乏协调。 ### P2 nice-to-have (2) - **Bug #1 — 退出码误判** (WorkerProcess.ts:127): `code || 1` 误判为错误 - **Bug #8 — `has_running` 误判** (WorkerManager.ts:303-305): `ready` 状态也算 running --- ## 3. 真实用户测试报告 (UAT) | 用例 | 状态 | 关键现象 | |---|---|---| | `air init` | ✅ PASS | 创建 .air/ 目录和 project.json | | `air ask "..."` 写文件 | ✅ PASS | fs.write 工作 | | TUI 启动 | ✅ PASS | OpenTUI 渲染正确 | | `air doctor` | ✅ PASS | 检测 bun/sqlite/git/shell | | **shell.run 任意命令** | ❌ **FAIL** | 10/10 次返回 `Error: undefined` | | **追问项目内容** | ❌ **FAIL** | LLM 答"我没有文件系统访问" | | **危险操作 (删除)** | ❌ **FAIL** | 静默通过,文件仍在 | | **false-positive 成功** | ❌ **FAIL** | tool 报错但 CLI 仍打印 `✅` | | **多文件 C++ 任务** | ❌ **FAIL** | main.cpp 内容退化为 stub | | `air doctor --fix` | ❌ FAIL | 标 [fixable] 不修 | ### 用户最痛 3 个问题 1. **shell 工具整体坏死**,让 AI 跑任何命令都失败 10/10 次。 2. **报错说"成功",实际没干**——用户以为工作流跑通了,回头看磁盘空的。false-positive 比直接报错危险十倍。 3. **TUI 和 CLI 是两套东西**,`air ask` 能用工具,`air run` TUI 输入路径不可见(实际仅 readline 跑,渲染层 OK 但端到端未跑通)。 --- ## 4. QA 测试矩阵 | Test | 状态 | 关键观察 | |---|---|---| | 1: 简单文件创建 | PASS | hello.txt 创建成功,内容正确。Worker stderr 异常但不影响产出。 | | 2: 多文件 (C++ + CMake) | **PARTIAL** | main.cpp 内容退化为 stub,CMakeLists.txt 正确。两文件被写到不同位置 | | 3: 追问项目内容 | **FAIL** | agent.handle_user_message("我的项目有哪几个文件?") 走 answer 分支,LLM 幻觉 | | 4: TUI 启动 | PASS | OpenTUI 渲染正确,状态栏正常 | | 5: E2E gates | PASS | 13/13 (但 gates 与用户场景脱节) | --- ## 5. 用户核心痛点 (按严重度排序) | 排名 | 问题 | 严重度 | 触发场景 | |---|---|---|---| | 1 | **shell.run 工具完全坏死** | P0 阻塞 | 任何命令执行 (编译、运行、git) | | 2 | **追问上下文失效** (LLM 答"我没文件系统") | P0 阻塞 | 完成任务后问"现在什么情况" | | 3 | **危险操作无 confirmation 路由** | P0 安全 | 删除、覆盖文件 | | 4 | **Scheduler 早判完成** (假完成) | P0 阻塞 | 多步任务 | | 5 | **TUI 无文本输入路径** | P0 用户体验 | TUI 实际只读 | | 6 | **多文件任务漏写 / 覆盖** | P1 | 复杂任务 | | 7 | **false-positive 成功 banner** | P1 | 任何报错场景 | | 8 | **DONE 竞态导致提前退出** | P1 | LLM 同 turn 输出 tool+DONE | | 9 | **ExecutorRole 转义顺序错误** | P1 | LLM 输出含 `\n` 字符 | | 10 | **退出码误判** (stderr 噪音) | P2 | 排查时迷惑 | --- ## 6. 根因分析 E2E gates 框架本身存在结构性缺陷: - 仅做静态检查:tsc/depcruise/单元测试 - 不做端到端真实任务验证 - 缺"用户成功完成一个 C++ 任务"等综合场景 gate 需要新增的 gates: - 真实 LLM 端到端任务完成 - 多文件任务产出验证 - shell.run 工具真实执行 - 上下文追问验证 - 危险操作 confirmation 验证 --- ## 7. 修复建议 (按优先级) ### 立即修复 (P0, 阻塞发布) 1. 修复 `shell.run` AsyncGenerator 序列化问题 2. 修复 Scheduler MONITORING 早判完成 bug 3. MainAgent 注入工具/项目上下文到 LLM 调用 4. 修复 confirmation 路由 (run.ts → MainAgent.handle_confirmation) 5. TUI 增加文本输入路径 (或移除 TUI 包装直接 CLI) ### 必须修复 (P1, 关键) 6. ExecutorRole 转义顺序 7. DONE 竞态检测 8. 多文件任务协调 (检查文件已存在) 9. Tool 失败时正确报失败 (false-positive 修复) 10. 真实集成测试加入 E2E gates ### 长期改进 (P2) 11. 退出码误判 12. has_running 误判 13. Worker stderr 去噪 14. Anthropic canonical content blocks 完整支持 --- ## 8. 综合判断 **V1.0.0 Alpha 不应发布**。 - 13/13 E2E gates passed 但**用户场景真实成功率极低**——这是 E2E gate 设计缺陷 - 5 个 P0 问题中,3 个是用户每次使用都会触发的(shell 坏死、追问失效、确认门失效) - C++ 工作流工具链与主链路未联动,FR-017 名存实亡 - TUI 渲染层 OK 但无输入路径,FR-016 名存实亡 修复 P0 后必须**用真实任务重新端到端测试**,而不是用 E2E gates 替代。需要在 E2E gates 框架中**加入"真实 LLM 任务闭环"维度**,否则同样的审计盲点会再次出现。 **核心教训**: 代码质量指标 (tsc/stub 数/单元测试) 与用户可用性指标是正交的。质量分高 ≠ 产品可用。后续每个审计必须包含**真实任务端到端测试**作为硬性 gate。