关于 qa-team
协调专业 Agent 独立审查分支变更,并将发现汇总为带风险评估的报告的仓库技能。
主要功能
- 01收集 Diff 并分类文件
- 02专业 Agent 独立审查
- 03核对审查覆盖情况
- 04汇总分析与风险评分
- 05生成 Markdown 报告
适用场景
- 01合并前审查分支变更
- 02评估涉及后端与前端文件的修改
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ posthog/ posthog --skill qa-team安装后在 Claude Code 中输入/qa-team确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/incident-patterns.mdpersonas.mdscripts/build_launch_scripts.jsclaim_persona.sh详细介绍
QA 团队:多 Agent 代码审查
一组专业 Agent 会各自独立地根据真实事故模式审查当前分支的变更。它们的发现会被综合成一份单一报告,并附带收敛分析。
Agent 的独立性至关重要。 每个 Agent 只会收到自己的角色定义、与其关注领域相关的事故模式以及 diff。绝不能告知 Agent 其他 Agent 的存在、它们的代号、正在运行的 Agent 数量,或将会执行收敛分析。这确保了发现结果完全独立。
工作流
第 1 步:收集 diff
确定基础分支。如果用户提供了 $ARGUMENTS,则将其用作基础分支。
否则,默认为 master。
在仓库之外创建运行目录(会话暂存区或 mktemp -d —— 绝不要放在仓库内),然后将上下文收集到其中:
RUN_DIR="$(mktemp -d "${TMPDIR:-/tmp}/qa-team-XXXXXX")"
mkdir -p "$RUN_DIR/personas" "$RUN_DIR/claimed"
git diff <base>...HEAD --name-only > "$RUN_DIR/files.txt"
git log <base>...HEAD --oneline > "$RUN_DIR/commits.txt"
git diff <base>...HEAD > "$RUN_DIR/diff.patch"
运行目录存放角色队列、claim 脚本以及生成的启动脚本(第 3 步);diff 由构建脚本写入共享的 Agent 提示词中,不会经过模型(原因见第 3 步)。将 diff.patch 保留在磁盘上 —— 构建脚本会读取它,而过大的 diff 会在审查时回退到它。
如果没有变更,请告知用户并停止。
第 2 步:对变更文件进行分类
对变更文件进行分类,以确定哪些 Agent 相关:
| 文件模式 | 相关 Agent |
|---|---|
*.py(迁移) | database、reliability、compatibility |
*.py(Django 视图/API) | security、reliability、performance、data-integrity |
*.py(Celery 任务) | reliability、performance、data-integrity |
*.rs(Rust 服务) | security、performance、compatibility、reliability |
*.tsx、*.ts(前端) | frontend、security、performance、copy |
*.sql、ClickHouse 查询 | database、performance、data-integrity |
| Helm charts、ArgoCD、k8s | compatibility、reliability |
requirements*.txt、pyproject.toml、package.json | security、compatibility |
| SDK/扩展代码 | compatibility、frontend、security、copy |
| 任何包含用户可见字符串的文件 | copy |
| GitHub Actions 工作流 | security |
始终至少运行 4 个专业 Agent。如果根据文件分类相关的 Agent 少于 4 个,则添加适用范围最广的那些(reliability、security、performance、compatibility),直到至少有 4 个专业 Agent 处于活动状态。
始终启动两个通才 Agent(generalist-a 和 generalist-b),无论文件分类如何。它们会审查所有变更。
第 3 步:启动评审 Agent(缓存感知协议)
为什么需要这个协议: 每个 Agent 请求都携带一个很大的固定前缀(系统提示词、工具、项目上下文和用户提示词),只有当提示词在所有 Agent 之间逐字节完全一致时,这个前缀才会被提示词缓存。提示词缓存基于严格前缀:提示词中任何一个字符不同,都会迫使每个 Agent 以全价重新读取整个前缀——数万个 token。由此得出四条规则:
- 每个 Agent 拿到完全相同的提示词,逐字节一致——包括完整 diff。 相同提示词中的 diff 是共享缓存前缀的一部分,因此后续 Agent 以缓存读取价格读取它,而不是各自为文件读取工具结果重新支付写入价格。
- 启动脚本由随附的构建工具生成,绝不由编排器手写。
scripts/build_launch_scripts.js将提示词(包含 diff)进行 JSON 编码,写入两个 Workflow 脚本文件,因此 diff 永远不会作为输出 token 经过模型,两个脚本的提示词也不会因为一个多余的字节而产生偏差。 - 每个 Agent 的差异(persona)通过工具结果到达,而不是通过提示词。 每个 Agent 的第一个动作是运行 claim 脚本,以原子方式为它分配一个 persona。工具结果位于共享前缀之后,因此不会破坏缓存。绝不要把 persona 作为后续消息发送给已完成的 Agent——恢复一个已经完成的 Agent 会从头重建其请求,从而完全错过缓存。
- 错开启动。 第一个评审者单独启动;它的 persona claim 出现在
claimed/中,就是它的第一个请求已完成、共享前缀已缓存的信号。只有到这时,其余评审者才并行启动并读取它。同时冷启动会让每个 Agent 写入前缀而不是读取它(实测:同时启动的两个 Agent 各自写入了完整的约 42k token)。
关键——Agent 独立性: 每个 Agent 都必须完全隔离运行。不要在共享提示词或任何 persona 文件中包含以下任何内容:
- 其他 Agent 的名称、代号或描述
- 正在启动的 Agent 数量
- 将执行收敛分析
- 其他评审者正在查看同一份代码
- 任何对评审者“团队”的提及
每个 Agent 都相信自己唯一的评审者。这确保了发现完全独立。(磁盘上的 persona 队列必然包含其他 persona;共享提示词禁止 Agent 检查运行目录,这在实践中保持了独立性。)
3a. 编写 persona 文件
为每个选中的 Agent 向 $RUN_DIR/personas/ 写入一个文件,文件名带数字前缀,使 claim 顺序具有确定性(01-generalist-a.md、02-generalist-b.md、03-security.md、04-database.md、……)。通才排在前面,因为它们在每次评审中都会运行,所以评审者 1——即预热共享缓存的 Agent——始终是同一个 persona,无论 diff 选中了哪些专家。persona 文件的数量必须等于你将启动的评审者数量——构建脚本会从该目录推导启动数量。
对于每个专家(security、database、reliability、performance、frontend、compatibility、data-integrity、copy),文件包含:
Your assigned review focus: {FOCUS_AREA}
## Your expertise
{PERSONA_DESCRIPTION_AND_CHECKLIST from references/personas.md — this agent's section only}
## Known failure patterns
{RELEVANT_PATTERNS from references/incident-patterns.md — only patterns matching
this agent's focus area. Omit this entire section for the copy persona.}
始终包含两个通才 persona。通才 A(fresh-eyes 资深工程师):
Your assigned review focus: general correctness and safety
You are a senior software engineer reviewing this code change for the first time.
You have no prior context about the codebase — approach it with fresh eyes.
Focus on things that would concern you if you saw this code in a pull request:
- Does the code do what the commit messages claim?
- Are there obvious bugs, logic errors, or edge cases?
- Is error handling adequate? What happens when things fail?
- Are there race conditions or concurrency issues?
- Is the code readable and maintainable?
- Are there any "that looks wrong" moments?
Do NOT focus on style, formatting, or minor nits. Focus on correctness and safety.
This focus has no formal checklist — omit the Checklist Coverage section from your review.
通才 B(对抗性测试者):
Your assigned review focus: breakability
You are a QA engineer who tries to break things. Your job is to think about how
this code could fail in production, be misused, or cause unexpected behavior.
Think like an attacker, an impatient user, a misconfigured deployment, or an
edge-case dataset. For each change, ask:
- What if the input is malformed, huge, empty, or malicious?
- What if the external service is slow, down, or returns garbage?
- What if two requests hit this code at the same time?
- What if this runs against a database with millions of rows?
- What happens during deployment — is there a window where old and new code coexist?
- What if a developer misunderstands this code and extends it incorrectly?
Do NOT focus on style or readability. Focus on breakability.
This focus has no formal checklist — omit the Checklist Coverage section from your review.
3b. 安装 claim 脚本并构建启动脚本
两者都位于本技能的 scripts/ 目录中 —— 将 claim 脚本复制到运行目录,然后根据运行目录的内容构建两个 Workflow 启动脚本:
SKILL_DIR="<this skill's base directory>"
cp "$SKILL_DIR/scripts/claim_persona.sh" "$RUN_DIR/"
node "$SKILL_DIR/scripts/build_launch_scripts.js" "$RUN_DIR"
claim_persona.sh 以原子方式将下一个未认领的 persona 交给每个调用者(mv 是原子的,因此并发的 Agent 各自赢得一个不同的 persona)。build_launch_scripts.js 将共享的审查提示词 —— 认领指令、变更的文件、提交信息以及完整 diff(当 diff 超过约 200 KB 时,改为从磁盘读取的指令)—— JSON 编码到 $RUN_DIR/launch_first.js 和 $RUN_DIR/launch_rest.js 中,并根据 persona 数量确定并行扇出规模。提示词文本本身位于构建脚本中;不要重新输入或编辑生成的文件。
3c. 分两个阶段启动
-
使用
{scriptPath: "$RUN_DIR/launch_first.js"}调用 Workflow 工具。它会在后台单独启动 reviewer 1。 -
轮询 reviewer 1 的 persona 认领 —— 这是其首次请求完成的信号(约 15 秒后),且共享前缀(包含 diff)已被缓存:
timeout 120 bash -c 'until [ -n "$(ls -A '"$RUN_DIR"'/claimed)" ]; do sleep 1; done'不要等待第一个 workflow 运行完成 —— reviewer 1 会在其余 reviewer 启动期间继续审查,因此除了这个短暂的预热窗口外,所有 reviewer 都并发运行。如果轮询超时,先检查
launch_first运行是否出错,然后继续执行,并在最终报告中注明本次运行未使用缓存 —— 缓存未命中损失的是金钱,而非正确性,但应当可归因。 -
使用
{scriptPath: "$RUN_DIR/launch_rest.js"}调用 Workflow 工具。它会并行启动其余 reviewer;每个 reviewer 都会读取 reviewer 1 写入的缓存前缀。 -
两个 workflow 运行在完成时都会返回
{ reviews: [...] }—— 收集两者以供步骤 4 使用。失败的 reviewer 会以显式的REVIEWER FAILED: ...哨兵条目出现,绝不会静默缺失。 -
在综合前先核对:
personas/必须为空,且收集到的 review 数量(包括哨兵条目)必须等于 persona 数量。若不匹配,请在报告中指明未认领或未审查的 persona —— 或为剩余的 persona 重新启动单个 Agent —— 而不是将部分覆盖当作完整审查呈现。(已知限制:认领不是幂等的 —— 重新运行认领的 Agent 会消耗第二个 persona,从而使后面的 reviewer 得不到 persona;核对步骤正是用来捕获这一问题的。)
报告写完后,尽力清理运行目录(rm -rf "$RUN_DIR")—— 它包含磁盘上的完整 diff,已无其他用途。
回退方案: 如果 Workflow 工具不可用,请直接使用 Agent 工具启动 Agent,使用一个共享提示词,引用运行目录中的文件而不是嵌入 diff(Read $RUN_DIR/diff.patch 等 —— 手动输入 diff N 次的成本高于缓存节省的成本)。启动第一个 Agent,执行与上面相同的 claimed/ 轮询,然后在一条消息中并行启动其余的 Agent。
步骤 4:综合报告
所有 Agent 完成后,将其发现汇编成一份统一报告。
4a. 收敛分析
检查是否有多个 Agent 标记了同一文件或问题。收敛性发现(由 2 个及以上 Agent 独立识别)置信度更高,应在摘要中突出显示。
4b. 风险评分
计算总体风险评分:
- CRITICAL:任何 Agent 返回 Risk Level CRITICAL -> 总体 CRITICAL
- HIGH:2 个及以上 Agent 返回 Risk Level HIGH,或 1 个 HIGH + 2 个 MEDIUM Agent -> 总体 HIGH
- MEDIUM:1 个 Agent 返回 Risk Level HIGH,或 3 个及以上 Agent 返回 Risk Level MEDIUM -> 总体 MEDIUM
- LOW:仅 LOW/NONE 的 Agent 风险等级 -> 总体 LOW
4c. 判定
将总体风险映射为判定结果:
- ✅ APPROVE — 总体风险为 LOW,无可执行的发现项
- 💬 APPROVE WITH NITS — 风险为 MEDIUM,存在不会阻碍合并的小建议
- ⚠️ REQUEST CHANGES — 风险为 HIGH,合并前需要具体修复
- 🚫 BLOCKED — 风险为 CRITICAL,发现阻塞性的安全/数据问题
4d. 最终报告格式
使用 Write 工具将报告写入仓库根目录下的 QAREPORT.md,
然后向用户呈现简要摘要,包含判定结果和主要发现项。
报告必须使用 emoji 来构建视觉结构,并避免冗长的散文式段落。 保持一切易于扫读——使用表格、检查清单和简短的要点。
# 🔍 QA Team Review Report
| Key | Value |
| ------------------- | ----------------------- |
| **Branch** | `{branch_name}` |
| **Base** | `{base_branch}` |
| **Files changed** | {count} |
| **Agents deployed** | {emoji + codename list} |
| **Date** | {YYYY-MM-DD} |
---
## 📋 Summary
{2-4 bullet points: what was changed and why. No long paragraphs.}
### Key findings
- {1-line per convergent or critical/high finding, with emoji severity prefix}
---
## 🏁 Verdict
> {emoji} **{APPROVE / APPROVE WITH NITS / REQUEST CHANGES / BLOCKED}**
{1-2 sentences explaining the verdict. Reference the top blocking items if not approving.}
---
## 👥 Agent summaries
| Agent | Risk | Summary |
| ----------------- | -------------------- | --------------------------------- |
| 🔒 security | {risk emoji + level} | {1-2 sentence summary from agent} |
| 🗄️ database | {risk emoji + level} | {1-2 sentence summary from agent} |
| 🔄 reliability | {risk emoji + level} | {1-2 sentence summary from agent} |
| ⚡ performance | {risk emoji + level} | {1-2 sentence summary from agent} |
| 🎨 frontend | {risk emoji + level} | {1-2 sentence summary from agent} |
| 🔗 compatibility | {risk emoji + level} | {1-2 sentence summary from agent} |
| 📊 data-integrity | {risk emoji + level} | {1-2 sentence summary from agent} |
| ✏️ copy | {risk emoji + level} | {1-2 sentence summary from agent} |
| 🧑💻 generalist-a | {risk emoji + level} | {1-2 sentence summary from agent} |
| 🕵️ generalist-b | {risk emoji + level} | {1-2 sentence summary from agent} |
(Only include rows for agents that were deployed.)
**Note:** ✏️ copy findings are always non-blocking nits. 🧑💻 generalist-a and 🕵️ generalist-b
are independent generalist reviewers used for convergence validation — their findings
carry extra weight when they independently match a specialist's finding.
Risk emojis: 🔴 CRITICAL, 🟠 HIGH, 🟡 MEDIUM, 🟢 LOW, ⚪ NONE
---
## 📝 Findings
Actionable findings as a checklist table, sorted by priority (highest first).
Each row is a checklist item. The `Status` column starts as `⬜ Open`.
Use convergence markers when 2+ agents flagged the same issue.
| # | Status | Priority | Finding | Location | Agents | Reasoning | Suggested fix |
| --- | ------- | ----------- | ------------- | ----------- | ----------- | ------------------------------------------------------------ | -------------- |
| 1 | ⬜ Open | 🔴 Critical | {short title} | `file:line` | {codenames} | {why it matters — reference incident patterns if applicable} | {specific fix} |
| 2 | ⬜ Open | 🟠 High | {short title} | `file:line` | {codenames} | {reasoning} | {fix} |
| 3 | ⬜ Open | 🟡 Medium | {short title} | `file:line` | {codenames} | {reasoning} | {fix} |
| ... | ... | ... | ... | ... | ... | ... | ... |
| N | ⬜ Open | 🟢 Low | {short title} | `file:line` | {codenames} | {reasoning} | {fix} |
Priority mapping:
- 🔴 Critical — Security vulnerability, data loss, or production outage risk
- 🟠 High — Significant bug or security concern, must fix before merge
- 🟡 Medium — Should fix, but not a merge blocker
- 🟢 Low — Nit or minor improvement, nice to have
Convergent findings (flagged by 2+ agents independently) should be noted
in the `Agents` column and carry higher confidence.
参考文件
人设定义
references/personas.md-- 专家 Agent 的完整人设描述、上下文和审查清单(不用于通才 Agent——其人设文件在步骤 3a 中内联定义)
事故模式
references/incident-patterns.md-- 从生产事故中综合提炼的故障模式,用于将专家 Agent 的审查建立在真实世界的故障模式之上(不用于通才 Agent)