mcpField
Q
qc-code

qc-code

github.com/rheinmir测试与质量10171 次安装2 周前更新
代码仓库

关于 qc-code

qc-code 是面向代码变更审查的技能,按安全、性能、命名和逻辑四项评分,并为逻辑缺陷生成复现测试。它输出带证据的建议性结论,不会阻止提交。

主要功能

  1. 01按四项审查代码并评分
  2. 02为逻辑缺陷生成红色测试
  3. 03输出 PASS 或 CẦN SỬA 结论
  4. 04生成带证据的 verdict JSON
  5. 05通过现有测试运行器执行测试

适用场景

  1. 01提交前审查当前代码差异
  2. 02为发现的逻辑错误添加回归测试
  3. 03梳理安全、性能与命名问题

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/rheinmir/setup --skill qc-code

安装后在 Claude Code 中输入/qc-code确认已加载。

详细介绍

技能:qc-code

WHAT

目的与背景
  • **目的:**以资深工程师的视角,从安全性 · 性能 · 命名 · 逻辑四个方面审查代码——每项打分/10 + 最严重的问题 + 修复方法;为每个逻辑 Bug 生成可复现的红色测试,然后给出 advisory PASS/CẦN SỬA verdict,并附带有证据的 JSON。
  • 触发条件(何时使用):
    • 用户想让资深工程师在定稿前检查代码:“review code”“检查代码”“给代码打分”。
    • 提交重大更改前——在 /orca-workflow 中将其作为可选步骤,放在 verify-before-commit 之前。
  • **非目标:**不用于静态安全扫描(使用 /orca-sec-scans — Trivy)或处理已发生的事件(使用 /orca-issue — 先复现)。不用于 /code-review 内置工具所提供的通用审查;默认不审查整个代码库;verdict 不阻止提交。
心智模型

范围(与 base 的 diff | 用户指定的文件)→ 4 项评分 → finding [类别][严重性] → 逻辑 Bug → qc-* 红色测试 → 文本 verdict + qc-verdict.json(grounding-check)→ 将测试写入项目 → qc-regression.py --run 自动运行(0-token)。成本高 = 手动调用 LLM 审查;成本低 = 通过 hook 运行确定性测试。

审查范围(默认 = 当前 diff)

默认检查自 base 以来的更改(从原始 commit/branch 开始的 git diff)——适合提交前检查,速度快,也能精准覆盖刚写的内容。用户指定文件/目录时,则检查指定内容。默认不检查整个代码库(速度慢、消耗 token,而且大部分内容都没有更改)。

输入和输出约定
FieldRequired?含义
In范围否(默认 = 与 base 的 diff)用户指定的文件/目录
In项目测试 runner存在逻辑 Bug 时必需已有的 pytest/vitest/jest
Out4 项报告是每项打分/10 · 最严重的问题 · 修复方法;性能项另加最慢的 3 个点;命名项另附改名表
Out测试 qc-<slug-bug>每个逻辑 Bug放在项目标准测试目录中,在当前版本上应为红色
Outverdict PASS / CẦN SỬA是advisory,附带必须修复的问题清单
Outharness/out/qc-verdict.json是包含 decision/claim/reason/required_evidence,通过 grounding-check,退出码为 0
规则与能力
  • RULE-01 (MUST):**区分高成本和低成本:**LLM 审查(本技能)= 手动调用/可选工作流步骤。自动生成的测试 = 通过确定性 hook 自动运行。绝不在 hook 中调用 LLM(overstack 的 hook-0-token 原则)。
  • RULE-02 (MUST):Verdict 仅供参考,确定性测试负责硬性把关——不得让 LLM verdict 阻止提交。
  • RULE-03 (MUST):避免重复:/orca-sec-scans = Trivy 静态扫描 · /code-review 内置工具 = 通用审查 · /orca-issue = 先复现事件。/qc-code = 资深工程师进行四项评分并生成测试。
  • RULE-04 (MUST):**审查结论存在未知项?**如果某项判断取决于尚未确认的内容(生产环境配置、尚未观察到的运行时行为),则记录到 [[150726-unknown-ledger]],不要妄下结论。
  • RULE-05 (MUST):安全性关乎信任边界——不可在此偷懒(CLAUDE.md carve-out)。
  • RULE-06 (MUST):每个 finding 只能归属一个类别和一个严重性;严重性应基于实际影响。
  • 能力:读取 diff/code;在项目中写入测试文件及 harness/out/qc-verdict.json;运行已有的测试 runner。不联网。
失败边界
  • 无法确定 base/范围 → clarify(询问文件/branch),不要默认检查整个代码库。
  • 项目没有标准测试目录 → partial:明确说明,并将测试放在源文件旁边,不要猜测目录结构。
  • grounding-check 退出码为 2 → verdict 尚未生效,必须重写;不要提交含糊的 verdict。
  • 判断依赖未知项 → 记录到 unknown-ledger,不要妄下结论。
  • 尚无 qc-* 测试 → qc-regression.py fail-open。

HOW

Main workflow
StepTypeInputsActionOutputs/exitFailure/next
W01deterministic基准 / 用户指出的文件使用 git diff <base>..HEAD --stat 确定范围,阅读代码范围有歧义 → 澄清
W02judgment代码对四个项目评分 + 标注类别/严重程度(13 类映射)四个项目均包含三部分—
W03effect逻辑 bug为每个 bug 生成复现测试 qc-*可运行的红色测试未变红 → bug 尚未得到证明,降级为疑似问题
W04judgmentW02–W03 的结果判定 PASS / 需要修复 + 写入 harness/out/qc-verdict.jsonverdict + JSONhook exit 2 → 重写 W04
W05effect测试将测试写入项目 + 提醒 qc-regression.py --run 会自动运行仓库中的测试没有测试目录 → 在源代码旁创建,并明确说明

各步骤详情(W01–W05 的事实依据):

Steps
  1. 确定范围 — git diff <base>..HEAD --stat(或用户指出的文件)。阅读该范围内的代码。
  2. 对四个项目评分(见下文)。每项包含:分数/10 · 最严重的问题 · 修复方法。→ 四项都包含这三部分后即完成。
  3. 逻辑项目:为每个 bug 生成复现测试(见下文“逻辑与 bug”)。→ 每个 bug 都有一个可运行的红色测试后即完成。
  4. 给出结论 — PASS(进入下一步)或 需要修复(列出通过前必须修复的内容)。→ verdict 明确,且在需要修复时列出待修复项后即完成。
  5. 将测试写入项目(见下文“编写测试”)+ 提醒 qc-regression.py --run 会自动运行这些测试。
四个项目
1. 安全 — 分数/10 · 最严重的问题 · 修复方法

检查:SQL 注入(将字符串拼接到查询中,未使用参数化查询)· XSS(输出未转义,使用 innerHTML/dangerouslySetInnerHTML)· API key / secrets 泄露(硬编码 key、secret 出现在日志/仓库中)· 输入验证(接收外部数据时未检查)· 权限控制(未检查谁可以执行什么操作,IDOR)。这是信任边界——不能在这里偷懒(CLAUDE.md 中的例外条款)。

2. 性能 — 分数/10 · 最严重的问题 · 修复方法 · 最慢的 3 个点

检查:N+1 查询(在循环中逐个元素调用数据库,而不是一次查询)· 无谓的嵌套循环(可用 O(n) 时却用了 O(n²))· 隐性内存泄漏(未移除 listener/timer、ref 一直保留、缓存没有限制)。指出最慢的 3 个点,并说明每项的优化方法(估算量级:O(?)、往返次数)。

3. 命名与可读性 — 分数/10 · 最严重的问题 · 改名表

检查:名称是否准确描述其用途(函数 getUser 却写入数据库,变量 data 毫无意义)· 命名规范是否一致(camelCase/snake_case 混用,单复数混乱)。返回以下表格:

旧名称新名称原因
ddueDate单字母名称无法说明含义
4. 逻辑与 bug — 分数/10 · 最严重的问题 · 为每个 bug 编写复现测试

检查:边界情况(null · 空值 · 负数 · 溢出)· 差一错误(< vs <=,最后一个 index)· 竞态条件(共享 state、交错的 await、读取后写入不是原子操作)。每发现一个 bug → 编写一个复现该错误的红色测试用例(证明 bug 确实存在,而非只是怀疑)。红色测试是事实依据;verdict 是意见。

13 类问题图谱(gstack)+ 严重程度

每条发现严格对应一个类别 + 一个严重程度,格式:[<类别>][<严重程度>] <描述> — <修复方法>。先检查 5 个 CRITICAL 类别:

#类别(CRITICAL)检查内容
1SQL 与数据安全在查询中拼接字符串(包括已使用 .to_i 的情况),而不是使用参数化查询;先检查再设置但不具备原子性(TOCTOU);绕过模型验证写入数据库;N+1 查询缺少预加载。
2竞态条件与并发读取-检查-写入时没有唯一约束;find-or-create 缺少索引 → 并行调用产生重复记录;更改状态时没有使用 WHERE old_status=? 原子操作;在用户数据上渲染原始 HTML(XSS)。
3LLM 输出信任边界LLM 生成的值(电子邮件/URL/名称)未经格式验证就写入数据库;结构化输出未检查类型/形状;未使用允许列表就抓取 LLM 生成的 URL(SSRF);LLM 输出未经净化就进入知识库(存储型提示词注入)。
4Shell 注入使用 subprocess/os.system 时设置 shell=True 并插入字符串 — 应改用参数数组;在没有沙箱的情况下对 LLM 生成的代码使用 eval/exec。
5枚举与值完整性新增枚举/状态/层级值时 → 必须阅读 diff 之外的代码:所有 switch/filter/显示相关值的消费者、所有允许列表 %w[]、所有 case/if-elif 链 — 漏掉一个消费者就会造成隐蔽错误。

8 个 INFORMATIONAL 类别(之后检查,倾向于自动修复):async/sync 混用(在 async def 中调用同步阻塞函数、用 time.sleep 代替 asyncio.sleep) · 列/字段名称安全(ORM 查询中的列名与 schema 不一致 → 静默返回空结果) · LLM 提示词(提示词中的列表从 0 开始索引、提示词声明的工具与代码不一致、多个地方声明限制导致容易漂移) · 类型强制转换(值经过 Ruby→JSON→JS 边界后类型发生变化;输入 hash/digest 未规范化类型) · 视图/前端(每次渲染都重新解析内联样式、视图中的 O(n·m) 查找、用应用端过滤代替 WHERE) · 时间窗口安全(“今天”未覆盖完整 24 小时;两个功能对同一数据使用两种时间分桶方式) · 完整性缺口(只完成 80-90%,而做到 100% 只需多写少量代码;测试缺少容易补充的负向分支) · 分发与 CI/CD(工作流中的工具版本与项目不一致、硬编码 secret、标签 v1.2.3 与 1.2.3 不一致、发布不具幂等性)。

严重程度(提炼自 awesome-skills/code-review-skill):[blocking] = 合并前必须修复 · [important] = 建议修复,如有异议可讨论 · [nit] = 小问题,由作者自行决定 · [suggestion] = 值得考虑的替代方案,不强制。CRITICAL 类别倾向于 blocking/important;INFORMATIONAL 类别倾向于 nit/suggestion — 但严重程度应依据发现的实际影响,而不能机械地按类别划分。

结论(verdict)

二选一,并附上理由:

  • PASS — 没有任何项目存在严重问题,可以进入下一步。
  • 需要修改 — 具体列出通过前必须修改的内容(优先处理安全问题 + 有失败测试的逻辑问题,再处理命名)。

Verdict 仅供参考 — 由人决定,不阻止提交。 真正严格把关的是复现测试(红→绿)。不要让用户误以为“qc-code PASS = 绝对安全”;它只是资深人员的一双眼睛,并非证据。

Verdict JSON + grounding-check

除上面的文字 verdict 外,还要额外输出一个结构化 JSON block——“看起来不错”不是反馈,它会因 schema 无效而被确定性拦截:

{
  "decision": "revise",
  "claim": "paginate() bỏ sót phần tử cuối khi total % size == 0",
  "reason": "off-by-one ở điều kiện `<` tại api/paginate.py:42",
  "required_evidence": [
    "test qc-off-by-one-pagination chạy ĐỎ trên bản hiện tại",
    "api/paginate.py:42 sau khi sửa dùng `<=`"
  ]
}
  • PASS → decision: "approve"。CẦN SỬA → decision: "revise" + required_evidence,其中列出需要补充的具体证据,每项指向 file:line 或测试用例名称。
  • claim 和 reason 不能为空;未知字段只会发出警告,不会导致失败(向前兼容)。
  • 将 JSON 写入 harness/out/qc-verdict.json(在仓库内——不是 /tmp)。PostToolUse Hook 发现文件名以 qc-verdict.json 结尾时,会在写入时自动运行 grounding-check;verdict 无效则会拦截工具调用(exit 2),并通过 stderr 返回信息,以便就地修正。

无需记得输入命令——门槛设在结构上,而不是靠提醒。需要手动检查时(文件位于仓库外,或检查他人的 verdict):

python3 harness/scripts/grounding-check.py --check <file.json>

exit 0 = 有效;exit 2 = verdict 尚未有效,必须重写——Agent 不得提交含糊或缺少证据的 verdict。

将复现测试写入项目

逻辑项中的每个测试:

  • 放入项目的标准测试目录——自动检测:tests/ · test/ · __tests__/ · *_test.py 文件 · 与源文件同级的 *.spec.ts · *.test.js。若不存在 → 明确报告,并将测试放在源文件旁边;不要臆测目录结构。
  • 命名为 qc-<slug-bug>(例如 qc-off-by-one-pagination)——以便与 qc-code 生成的测试区分开,方便 qc-regression.py 收集。
  • 使用项目现有的运行器(pytest/vitest/jest)运行——不要新建测试框架。
  • 测试修复前必须失败(复现问题),修复后通过(作为证据)。如果 bug 再次出现 → 测试再次失败(防止回归)。
自动运行测试(确定性,0-token)

python3 harness/scripts/qc-regression.py --run 会运行指定的 qc-* 测试并报告通过/失败——不会调用 LLM。它会在 verify-before-commit 阶段自动运行(提交前);如需即时反馈,也可额外启用 PostToolUse。若尚无任何 qc-* 测试,则默认放行。这就是“修改代码时自动运行 Hook”的部分——只对廉价且确定性的部分设置 Hook,LLM 审查(本技能)仍由手动调用。

分支
ID类型条件行为跳过/失败重新汇合
B01user_optional用户指定文件/目录检查指定范围,而不是 diff—W02
B02conditional_required逻辑项发现 bugW03 为每个 bug 生成失败的测试没有 bug → 跳过 W03、W05W04
B03user_optional我是 finding 的接收者(来自用户、LLM reviewer,包括 /qc-code)执行“接收审查——修复前先验证”流程(Reference 部分)finding 有误 → 提供附带证据的技术回复逐项修复,逐项测试
B04capability_optional需要即时反馈额外启用 PostToolUse 运行 qc-regression.py --run默认只在 verify-before-commit 阶段运行—
验证与停止条件

确定性检查:qc-* 测试从失败变为通过;qc-verdict.json 必须通过 python3 harness/scripts/grounding-check.py --check <file.json>(写入时 Hook 会自动运行)。判断:评分和 verdict(仅供参考)。四个部分各自包含三个组成项、每个 bug 都有失败测试且 verdict 有效时停止。

示例
  • **正例:**对新增 paginate() 的 diff 执行“qc code” → 四个部分均有评分;逻辑项发现 api/paginate.py:42 处的 off-by-one < → 测试 qc-off-by-one-pagination 失败;verdict 为 CẦN SỬA + JSON decision: "revise",其中 required_evidence 指向测试和 file:line;grounding-check exit 0。
  • **边界/失败:**verdict JSON {"decision":"approve","claim":"","reason":"nhìn ổn"} → claim 为空 → Hook 拦截并返回 exit 2,stderr 返回信息,必须重写;项目没有 tests/ → 将测试放在源文件旁边并明确报告。
参考 — 接收评审 — 修改前先验证

这项技能的反向用法:当我收到问题反馈时(来自他人、LLM 评审者,甚至来自我自己的 /qc-code)。问题反馈是 CLAIM,而非事实(提炼自 obra/superpowers receiving-code-review):

  1. 先读完所有反馈,再做出反应 — 用自己的话复述要求;有不理解的地方,就先提问,再修改任何一项(各项可能相互关联——只理解一半就会改错)。
  2. 用实际代码验证问题反馈 — 运行或阅读所指的具体代码:问题反馈是否适用于这个代码库,按建议修改会不会造成问题,现有代码是否有其存在的理由。
  3. 只有在自己确认确实有问题后才修改 — 如果问题反馈有误,就用技术理由和证据回应,不要默默忽略,也不要默默照做。如果无法验证,就直说:“由于缺少 X,目前无法检查”。
  4. 一次修改一项,并逐项测试 — 不要一口气全改完,然后寄希望于一切正常。
  5. 禁止表演式认同 — “You're absolutely right!” / 用夸奖反馈代替实际行动,是正在盲目照做的信号。要么进行技术确认,要么开始处理,不要作秀。

盲目照做错误的评审会引入新 bug,并披着“已评审”的外衣——这是最难让人起疑的一类 bug。

来源

  • 根据 2026-07-15 的用户要求提炼(qc-code 的 4 项要求 + 生成测试 + 自动 hook)。已向用户询问“接到哪里”→ 选项 3(手动 LLM,确定性自动 hook 测试),范围为当前 diff。
  • 通过 /propose 吸收 → 150726-qc-code-skill,任务 T-260715-04。
  • 2026-07-17 吸收(adapt_mode: dissolve,T-260717-02): 从 garrytan/gstack(review/checklist.md)提炼出的 13 类错误图谱;严重程度来自 awesome-skills/code-review-skill;“接收评审”部分来自 obra/superpowers(receiving-code-review)。在 scratchpad/ 中进行 depth-1 克隆,不 vendoring 字节内容。
  • 提交: (verify-before-commit 填写)

评论

支持 Markdown