Files
AirCoding/集成测试阶段MiniMax-M3审查结果.md
AirCoding ddefcbb2b1 fix: integrate audit findings round 1 - tools, worker, scheduler, main agent
- Unify ToolResultEnvelope (output vs content) for built-in tools
- Fix shell.run AsyncGenerator consumption in ToolRegistry.call/streaming
- Scheduler: consume WorkerResult.status instead of marking all running tasks completed
- WorkerProcess/WorkerManager: surface exit events and generate failed/cancelled result
- MainAgent: integrate ContextAssembler, Chinese destructive regex, ArchitectureDesigner impact gate
- run.ts: pendingConfirmation flow, dispatch extracted, .air files filtered from /results
- CapabilityRegistry wired into RuntimeApp and ServiceRegistry; DoctorService uses it
- release.ts: findRepoRoot/findBun, run air e2e + depcruise + runtime regression
- New gates: release-critical-gates, CLI run command regression
- 14/14 e2e gates pass; 3/3 release dry-run pass

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-05 18:39:10 +08:00

197 lines
9.2 KiB
Markdown
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 集成测试阶段 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 之外独立处理 stdinTUI 和 CLI 互相竞争字符。TUI 实际是**只读 viewer不能输入任务**。
### FR-007/008 (Scheduler/Worker) — 链路通但判定错误
Worker 真实 spawnIPC 真实 NDJSONtool.call / llm.request 通过 IPC 回父进程由 ProviderManager 真实调用 LLM——**链路是通的**。
`Scheduler.step``MONITORING` 状态存在严重 bugworker 还在跑就 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 内容退化为 stubCMakeLists.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。