代码生成QA平台

一个可重用的QA平台,用于评估代码生成MCP服务器,通过可执行证明验证生成的代码。

  • by Whyme-Labs
  • TypeScript
  • 本地部署
  • 更新于
在 GitHub 查看 Whyme-Labs/whyme-qa

使用说明

为什么我QA

用于代码生成MCP服务器的可重用QA平台。使用以下命令评估生成的代码 可执行证明:如果它编译并通过测试,那么它在客观上是可用的。

快速开始

# Install
pnpm install
pnpm build

# Configure environment (copy and edit with your values)
cp .env.example .env

# List available scenarios
npx whyme-qa list -d scenarios/

# Run a scenario against an MCP server
npx whyme-qa run -s scenarios/counter.yaml

# Run with workspace preserved for debugging
npx whyme-qa run -s scenarios/counter.yaml --keep-workspace

运作原理

  1. 场景YAML 定义MCP服务器、工具调用、预期输出和验证门
  2. 跑者 连接到MCP服务器,执行工具调用,实现生成的代码
  3. 关卡脚本 验证代码:编译、lint、测试、WASM构建、激活检查
  4. 代理循环 (可选)--如果门失败,LLM会检查错误并修复代码,重新运行门最多N次迭代
  5. 记者 生成带有迭代历史的分数、JUnitXML和Markdown报告

建筑

whyme-qa/
├── packages/
│   ├── runner/      # CLI + scenario orchestrator + agent loop
│   ├── adapters/    # MCP client + gate execution + LLM client
│   ├── reporter/    # Scoring, JUnit, Markdown reports
│   └── schemas/     # TypeScript type definitions
├── gates/
│   └── stylus/      # Shell scripts for Stylus verification
├── scenarios/       # YAML scenario definitions
├── .gitlab/
│   └── duo/flows/   # GitLab Duo flow definitions
└── .gitlab-ci.yml   # CI pipeline configuration

数据流

MCP Server → File Extraction → Workspace → Gates → [Agent Loop] → Score → Report
                                                        │
                                              LLM (via OpenRouter)
                                              Read files + gate errors
                                              Return fixed files
                                              Re-run all gates
                                              Repeat until pass or max iterations

验证门(触控笔)

门 命令 点
格式 cargo fmt --check 5
Clippy cargo clippy -- -D warnings 10
编译 cargo build --release 10
单元测试 cargo test --all 30
WASM构建 cargo build --target wasm32-unknown-unknown 10
触控笔检查 cargo stylus check 20
安全 cargo audit 15

MCP响应格式

跑步者的 extractFilesFromResponse 支持三种响应格式:

  1. 通用的 {files: {path: content}} --一个JSON对象 files 将文件路径映射到内容字符串的键
  2. ARBuilder风格 --带顶级键的JSON code, cargo_toml, main_rs, stylus_toml, rust_toolchain_toml 映射到Stylus项目文件。还处理a tests 附加到的密钥 src/lib.rs (或放置在 tests/mod.rs 如果不 code 密钥存在)
  3. --- FILE: path --- 分隔块 --带有文件边界标记的纯文本 --- FILE: <path> --- 标头
ARBuilder密钥 映射文件
code src/lib.rs
cargo_toml Cargo.toml
main_rs src/main.rs
stylus_toml Stylus.toml
rust_toolchain_toml rust-toolchain.toml

写作场景

看 scenarios/counter.yaml 举个例子。关键字段:

  • sut.mcp_server --如何启动被测MCP服务器
  • plan.steps --要执行的有序工具调用(使用ARBuilder的 prompt 参数,不是 description)
  • workspace.required_files --生成后必须存在的文件
  • gates --运行哪些验证门
  • agent --(可选)代理循环配置:模型、max_iteractions、api_key_env

环境变量替换

场景YAML文件支持 ${VAR} 和 ${VAR:-default} 从以下位置解析的占位符 process.env 在加载时。这使得机密和特定于机器的路径不会出现在已提交的文件中:

sut:
  mcp_server:
    command: "${ARBBUILDER_PYTHON:-python3}"
    cwd: "${ARBBUILDER_DIR}"
    env:
      OPENROUTER_API_KEY: "${OPENROUTER_API_KEY}"

代理循环

配置后,代理循环使用LLM迭代修复验证门失败的代码。在测试了初始MCP生成的代码后,如果任何门失败,则代理:

  1. 读取所有工作区文件和门错误输出
  2. 将它们发送到LLM(通过OpenRouter),要求其解决问题
  3. 将LLM返回的文件更改应用于工作区
  4. 重新运行所有启用的门
  5. 重复直到所有门都通过或 max_iterations 已达到

在YAML中按场景配置:

agent:
  enabled: true
  model: "anthropic/claude-sonnet-4"
  max_iterations: 5
  api_key_env: OPENROUTER_API_KEY
  temperature: 0.2

CLI参考

# Run a scenario
whyme-qa run -s <scenario.yaml> [-o <output-dir>] [-g <gates-dir>] [--keep-workspace]

# Run without agent loop (even if configured in scenario)
whyme-qa run -s <scenario.yaml> --no-agent

# Override agent model and iterations
whyme-qa run -s <scenario.yaml> --agent-model "anthropic/claude-sonnet-4" --max-iterations 10

# List scenarios
whyme-qa list [-d <scenarios-dir>]

CI/CD管道

这 .gitlab-ci.yml 定义了四个阶段:

阶段 职位 描述
lint lint 构建所有包并运行类型检查
test unit_tests 运行单元测试,将报告作为工件上传
verify e2e_counter 端到端运行计数器场景(手动触发)
report (保留) 未来的报告工作

这 e2e_counter 工作是手动的(when: manual)以及 allow_failure: true,因此不会堵塞管道。JUnitXML报告作为GitLab测试报告工件收集。

GitLab Duo流定义也提供在 .gitlab/duo/flows/whyme_qa.yaml 与GitLab Duo工作流自动化一起使用。

许可证

阿帕奇-2.0