@ganziliang/zhizh-pi-qa-agent
v0.2.1
Published
pi 原生端到端 QA 验收扩展:上下文收集 → 风险分析 → 用例确认(唯一人工门禁)→ 脚本生成 → 执行与报告 → 独立代码审查。
Maintainers
Readme
@ganziliang/zhizh-pi-qa-agent
pi 原生的端到端 QA 验收扩展。把一个「验收 / 回归 / 质量检查」请求拆成有门禁、可追溯的阶段:
初始化 → 环境体检 → 上下文收集 → 风险分析 → 用例设计
↓
★ 人工门禁:用户确认用例(唯一需要人介入的一步)
↓
脚本生成 → 执行与报告 → G5 独立代码审查 → 最终报告只支持 pi。不依赖 Claude Code / Codex,也不写它们的配置文件。
为什么是扩展而不是一堆 skill
| 上游 skill 做法 | 本扩展做法 |
|---|---|
| 用提示词说「确认前不写测试代码」 | tool_call 真的拦截写 tests/**(可用 /qa:unlock 临时放行) |
| 靠模型记住 7 个 skill 的阶段顺序 | 阶段由文件事实推导,qa_status 直接告诉你下一步 |
| 手抄 30+ 条 PowerShell 命令 | 引擎命令目录内建在工具描述里,参数走 schema |
| 「等待用户确认」靠对话猜 | qa_confirm_cases / /qa:confirm 弹出真的确认框,用例内容一变确认自动失效 |
| 6 个 stage skill 各自维护职责散文 | 6 个 .pi/agents/qa-*.md 子代理,按阶段按需加载 |
安装
pi install npm:@ganziliang/zhizh-pi-qa-agent装好后新开一个 pi 会话,输入 /qa 看帮助。
前置要求:
| 依赖 | 必需性 | 说明 |
|---|---|---|
| Python 3 | 必需 | 确定性引擎(校验 / 门禁 / 报告渲染 / 用例索引)。没有 Python 时扩展仍会加载,但会提示。可用环境变量 QA_AGENT_PYTHON 指定解释器(例如 py -3)。 |
| git | 建议 | 没有 git 时 diff 类上下文、ensure-branch、atomic-commit 不可用 |
| node / npm / npx | 按需 | 前端与 Playwright E2E 需要 |
| Maven / JDK | 按需 | Java 项目需要 |
第一次使用:/qa:init
/qa:init 是一个 4 步向导,只会问你「只有人知道」的问题:
- 确认探测结果 —— 语言/框架/模块、测试套件与命令、被测服务与端口、MySQL MCP。
- 模块名 —— 用例固化文件名与报告归档前缀(默认从分支名推导)。
- 运行模式 —— 验收 / 回归 / 增量。
- MySQL MCP —— 有多个候选时才问你选哪个(见下)。
会生成 / 补齐什么
| 文件 | 是否入库 | 内容 |
|---|---|---|
| .qa-agent/config/qa-agent.config.yaml | 入库 | gate 命令、模型与网关、覆盖率阈值、修复路径约束、MCP server 名 |
| .qa-agent/config/pi-extension.json | 入库 | 模块名、运行模式、门禁开关与受保护路径、MCP server 名、界面噪音开关(ui) |
| .qa-agent/config/env.shared | 入库 | 团队共享的非敏感环境值(服务地址、账号名、MySQL 连接信息) |
| .qa-agent/config/accounts.json | 入库 | 测试账号清单(只存环境变量名) |
| .qa-agent/config/services.json | 入库 | 被测服务清单 + dir / startCmd / readySignal / healthUrl |
| .qa-agent/profiles/project-test-profile.json | 入库 | 测试画像(套件、测试文件、每个 gate 的命令) |
| .qa-agent/fixtures/*.example.* | 入库 | 脱敏模板 |
| .qa-agent/references/*.md | 入库 | 用例 schema、spec-task 规范、门禁语义、报告规范、Playwright 取证协议(每次 init 随包同步) |
| .qa-agent/risk-rules/README.md | 入库 | 项目专用风险规则说明(自己往里写业务不变量) |
| .qa-agent/local/.env | 不入库 | 本地密钥与覆盖值 |
| .pi/agents/qa-*.md | 入库 | 6 个阶段子代理 |
| 目标项目的规则载体(探测命中:.claude/rules/e2e-and-delegation.md、.cursor/rules/*.mdc、AGENTS.md …) | 入库 | 「E2E 提速与子代理委派纪律」:证据档(关重试)、快失败、派子代理前的预检与任务模板;并在 agent 入口文件里挂一行引用 |
| .qa-agent/.gitignore + 根 .gitignore 片段 | 入库 | 运行时产物忽略规则 |
幂等性:已存在的文件默认不覆盖;环境变量模板按 key 增量补齐,你填好的值不会被改掉。要强制同步用 /qa:init --force。
协作规则写到哪:探测目标项目的约定,不发明新约定
模型不跨会话记忆,所以纪律必须落到目标项目自己读得到的位置。初始化时按下面的优先级探测,命中哪个写哪个:
| 优先级 | 命中条件 | 写入位置 |
|---|---|---|
| 1 | .claude/rules/ 目录存在 | .claude/rules/e2e-and-delegation.md |
| 2 | .cursor/rules/ 目录存在 | .cursor/rules/e2e-and-delegation.mdc |
| 3 | .github/instructions/ 目录存在 | .github/instructions/e2e-and-delegation.instructions.md |
| 4 | .windsurf/rules/ 目录存在 | .windsurf/rules/e2e-and-delegation.md |
| 5 | AGENTS.md / CLAUDE.md / claude.md 存在(无规则目录) | 直接追加一个受标记管理的段落 |
| 6 | 都没有 | 建 .claude/rules/e2e-and-delegation.md |
- 内容是按本项目探测结果生成的(文末带真实的 e2e 运行/列举命令与测试目录);
- 规则是独立文件时,会在
AGENTS.md(或CLAUDE.md)里挂一行引用;入口文件都没有才新建一个只含引用段的AGENTS.md; - 幂等:本包写入的段落用
<!-- zhizh-pi-qa-agent:rule begin (e2e-and-delegation) -->包裹,重跑只替换标内内容; - 同名文件已存在但不是本包写的 → 不覆盖,只在结果里提醒(要用
force=true显式覆盖); - 不想写规则:
qa_setup//qa:init传installDelegationRule=false(对应SetupOptions.installDelegationRule)。
必须填的东西(只有 1 项是必需的)
/qa:init 结束时会明确列出来。唯一必填项是:
# .qa-agent/local/.env
QA_AGENT_LLM_API_KEY=<公司 LLM 网关的 key>它只影响 /qa:review(三模型交叉审查用例)。没填也不会阻断其它阶段,只是用例少了一道交叉验证。
按需填写的条目(缺失时对应能力退化,不报错):
| 条目 | 作用 |
|---|---|
| QA_USER_USERNAME / QA_USER_PASSWORD | 被测系统的测试账号(密码只进 local/.env) |
| QA_ADMIN_USERNAME / QA_ADMIN_PASSWORD | 后台测试账号(探测到 admin 类目录时才会生成) |
| QA_MYSQL_HOST / QA_MYSQL_PORT / QA_MYSQL_DATABASE / QA_MYSQL_USER | 数据核对用的连接信息(QA_MYSQL_PASS 只进 local/.env) |
| QA_API_BASE_URL / QA_WEB_BASE_URL 等 | 探测出的服务地址,团队成员可在 local/.env 覆盖 |
模板永远不会遗漏条目:
envCatalog()是条目清单的唯一来源,向导、.env模板、env.example、/qa:doctor都从它生成。
MySQL MCP:复用,不新建
需求很明确:成员本机/本项目已经有在用的 MySQL MCP server 配置时,用回它的配置。
本扩展的行为:
- 只读 扫描
.mcp.json、.pi/mcp.json、~/.pi/agent/mcp.json,以及 pi 运行时已连接的 MCP(工具名前缀mcp__*)。 - 把看起来是 MySQL 的 server 脱敏后列出来(
password/token/key之类的值一律替换成***)。 - 你选中的 server 只写进
.qa-agent/config/pi-extension.json的mysqlMcpServerName。 - 绝不写
.mcp.json、.pi/mcp.json、settings.json,也绝不新建 server。扩展源码里init/init-config/init-project/install-mysql-mcp这些上游命令被显式禁用(调用会直接报错)。
没有找到任何 MySQL server 时:向导会提示你「本扩展不会替你创建(避免覆盖团队配置)」,其余阶段照常可用,只是涉及数据库核对/测试数据准备的用例会缺少证据来源。配好之后重跑 /qa:init 会自动识别。
命令
| 命令 | 作用 |
|---|---|
| /qa | 帮助 + 当前状态 |
| /qa:init | 交互式初始化/修复(--module --run-type --mysql-mcp --force --yes) |
| /qa:doctor | 环境体检(--services 额外探测服务可达性) |
| /qa:status | 阶段、缺失项、下一步 |
| /qa:context | 阶段 0:收集上下文 + 索引存量用例 |
| /qa:risk | 阶段 1:风险骨架(--paths 限定扫描范围) |
| /qa:cases | 阶段 2:生成用例 + 确认页(--incremental) |
| /qa:confirm | ★ 确认用例(唯一人工门禁) |
| /qa:tasks | 阶段 3:spec-task + 脚本(--dev-mode 用金字塔比例) |
| /qa:run | 阶段 4:执行 + 分类失败 + 门禁(--regression) |
| /qa:review | 阶段 5:G5 独立代码审查 |
| /qa:report | 阶段 6:三连门禁 + 最终报告 + 时间戳归档 |
| /qa:unlock <原因> / /qa:lock | 临时放行/恢复写测试代码的门禁 |
| /qa:agents | 安装/更新 .pi/agents/qa-*(--force) |
工具(供模型调用)
| 工具 | 作用 |
|---|---|
| qa_status | 只读:阶段、就绪、缺失项、产物清单 |
| qa_agent | 调用确定性引擎(35 个命令,含参数说明;初始化和安装类命令被禁用) |
| qa_setup | 非交互初始化/修复(幂等,dry_run 可预览) |
| qa_confirm_cases | 弹确认框请用户确认用例;只有用户点了确认才会固化并解锁门禁 |
用例确认门禁(本扩展最实用的部分)
默认情况下,在用例被用户确认之前,以下写入会被直接拦截:
tests/** test/** e2e/** src/test/**
**/*.spec.ts **/*.spec.js **/*.spec.mjs
**/*.test.ts **/*.test.js **/*.test.mjs **/*.test.tsx包括用 bash 重定向绕道的写法(echo x > tests/a.spec.ts)。
- 写
.qa-agent/**永远放行。 - 跑测试(
npx playwright test ...)永远放行——门禁管的是「写」,不是「跑」。 - 用例内容一变,已确认状态自动失效(按内容指纹判断),门禁重新生效。
- 你在调试时可以用
/qa:unlock 临时调试登录流程放行(原因会记录),完事/qa:lock恢复。
受保护路径可以在 .qa-agent/config/pi-extension.json 里改:
{
"caseGate": {
"enabled": true,
"protectedPaths": ["tests/**", "**/*.spec.ts"]
}
}界面噪音同样在这个文件里控制(默认都开,只有显式关闭才生效):
{
"ui": {
"widget": false,
"status": false
}
}ui.widget:true(默认)输入框上方三行进度;"compact"压成一行;false完全不显示。ui.status:false时不再占用底部状态栏的QA <阶段>。- 关掉之后仍然可以随时用
/qa:status(或qa_status工具)看阶段与缺失项。
三种运行模式
| 模式 | 触发 | 行为 |
|---|---|---|
| 验收 | 默认 | 全流程:上下文 → 风险 → 用例(需确认)→ 脚本 → 执行 → 审查 → 报告 |
| 回归 | /qa:run --regression | 不重新收集上下文、不重新设计用例、不重新生成脚本;每个 task 都必须重新执行并产生新证据 |
| 增量 | /qa:cases --incremental | 已有用例不动,只针对新场景走完整流程 |
报告
.qa-agent/reports/latest-report.html—— 始终指向最后一次运行.qa-agent/reports/<module>-<runType>-<YYYYMMDD-HHMMSS>.html—— 时间戳归档副本
最终判定严格引用 readiness-check.json:就绪 / 有条件就绪 / 未就绪 / 未完成。
completion-check 通过但 G5 审查有 blocking 发现时,报告必须是未就绪——不允许「用例都过了就说 Ready」。
目录结构(本包)
src/ 扩展本体(TypeScript,jiti 直接加载)
index.ts 注册工具/命令/事件
engine.ts 引擎封装 + 命令目录(CLI 参考的唯一真相)
detect.ts 通用项目探测(Maven/npm/Playwright/pytest/Go)
scaffold.ts 初始化落地(幂等)
mcp-mysql.ts MCP 只读发现与复用选择
gates.ts 用例确认门禁
status.ts 阶段/就绪/缺失项推导
doctor.ts 环境体检
templates.ts 所有模板(条目清单的唯一来源)
wizard.ts /qa:init 向导
ui.ts 面向用户的中文排版
agents/ 6 个阶段子代理(安装到项目 .pi/agents/)
engine/scripts/ vendored 确定性引擎(见 PATCHES.md)
engine/assets/ 报告模板、E2E fixture 模板
engine/references/ schema/门禁/报告规范(安装到 .qa-agent/references/)
scripts/self-test.mjs 自检开发与自检
npm install --no-save typescript @types/node # 仅类型检查需要
npm run verify # = typecheck + self-test
npm run typecheck # 用 pi 安装目录里的 peer 类型做一次完整类型检查
npm run self-test # 假仓库里跑通「加载 → 初始化 → 状态 → 门禁 → 引擎调用」
python engine/scripts/qa_agent.py self-test # 引擎自身自检.qa-agent/references/*.md 由包内文件在每次 /qa:init 时同步(会覆盖本地修改)——
需要改规范请改 engine/references/ 并重新发版,避免各项目规范漂移。
常见问题:
| 现象 | 原因 / 处理 |
|---|---|
| 提示「未找到 Python 3」 | 装 Python 3,或 set QA_AGENT_PYTHON=py -3 |
| /qa:review 失败 | QA_AGENT_LLM_API_KEY 没填;只影响用例交叉审查 |
| 门禁一直拦你 | 用例没确认(/qa:confirm),或用例改过导致确认失效;调试用 /qa:unlock <原因> |
| 测试画像为空 | 探测不到测试目录时,手工补 .qa-agent/profiles/project-test-profile.json |
| 服务不可达 | 按 .qa-agent/config/services.json 的 dir/startCmd 启动,再 /qa:doctor --services |
| MCP 没识别到 | 扩展不读你 pi 配置以外的来源;确认 server 名里含 mysql/db,或 /qa:init --mysql-mcp <名字> 显式指定 |
升级引擎(上游 skill 更新后):
cp ~/.claude/skills/quality-assurance-agent/scripts/qa_agent.py engine/scripts/qa_agent.py
# 重新应用 PATCHES.md 里标记的改动,然后跑 self-test安全说明
- 扩展不会启动任何后台进程;只在命令/工具被调用时执行 Python 与外部命令。
- 不打印密钥、token、数据库口令;MCP 配置展示前一律脱敏。
- 不改动 MCP 配置、不动 Claude/Codex 配置、不自动 git commit(
atomic-commit需要显式调用且受repair.allowedPaths约束)。
