- 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>
277 lines
16 KiB
Markdown
Executable File
277 lines
16 KiB
Markdown
Executable File
# 集成测试阶段 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
|