mcpField
D
double-check

double-check

github.com/fellowship-dev测试与质量3232 次安装2 周前更新
代码仓库

关于 double-check

分阶段执行 GitHub Pull Request 二次审查的技能,涵盖准备、独立审查、修复和发布结论。它核验先前意见并检查当前差异,且仅在提交与审查版本匹配时发布评论和标签。

主要功能

  1. 01四阶段顺序审查
  2. 02隔离式关键审查
  3. 03基于 patch-id 延续结论
  4. 04针对新提交审查差异
  5. 05精确提交版本发布门槛

适用场景

  1. 01复核先前的 PR 审查
  2. 02审查修复后的变更
  3. 03差异未变时沿用审查结论

安装

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

$npx skills add https://github.com/fellowship-dev/dogfooded-skills --skill double-check

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

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

CONTEXT.md
references/
follow-up-issue-template.md
shared/
exact-head-receipt.sh
report-template.md
review-comment-template.md
stages/01-setup/
CONTEXT.md
stages/02-review/
CONTEXT.md
stages/03-fix/
CONTEXT.md
stages/04-post/
CONTEXT.md
tests/
base-merge-no-push.test.sh
exact-head-receipt.test.sh
patch-id-carry.test.sh
speed-contract.test.sh
test_installed_resources.py
tests/fixtures/
pr-3179-stage03-to-stage04.json

详细介绍

double-check

目的

独立的第二轮 PR 审查,按阶段拆分为 ICM 流程。获取 PR、第一轮审查和差异,并检出代码(setup),随后在干净的上下文中进行一次连贯的审慎评审(核实第一轮审查的结论、查找遗漏的边缘情况,并结合检查测试和文档 → 得出单一的综合结论),然后在需要时应用修复并重新运行测试(fix),最后发布整理后的评论、应用 double-checked 标签并撰写报告(post)。行为上等同于原始的 double-check 技能,只是将其隔离,避免评审判断受到编排器历史记录的影响。

参数

参数必填默认值说明
pr是—PR 编号,例如 742
repo是—org/repo,例如 fellowship-dev/booster-pack

从 $ARGUMENTS 解析:第一个 token 是 pr,第二个是 repo。 GitHub 身份验证由环境提供 — 无需 token 环境变量。pod 的 git-credential-pylot 辅助程序和 gh shim 会为每项操作生成短期 App 安装令牌,因此 git URL 必须保持为普通形式 (https://github.com/<org>/<repo>.git);内联凭据会绕过辅助程序,并在运行过程中途失效。

功能说明

4 阶段顺序执行的 ICM 流程(无并行阶段):

阶段模式说明
01-setup子 Agent获取 PR 元数据,包括当前 HEAD;将收到的第一轮审查回执(其 Head reviewed 行)归类为 current/stale/absent;收集评论和完整差异;检出 PR 分支和合并基准
02-review子 Agent在干净的上下文中进行一次连贯的审慎评审:核实第一轮审查的结论、查找遗漏的边缘情况、检查测试和文档 → 得出综合结论(仅当没有未解决的 MUST-FIX 代码问题时才为 ready)和整理后的发现
03-fix子 Agent应用 MUST-FIX(以及值得做的 NICE-TO-HAVE)修复,重新运行测试并推送 — 仅在需要修复时执行
04-post内联重新获取当前 head;如果它与阶段 02 审查的确切 40 位十六进制 head 相同,或携带相同的 patch-id,则晋级;否则执行一次重启。随后发布整理后的审查评论,并且仅针对匹配的 head 应用标签
Patch-id 延续与差异审查(pylot#3738)

每份结论回执都会记录 head 和 PR 的 patch-id (git diff base...head | git patch-id --verbatim)。仅 head 发生变化不会导致审查失效:

  • Patch-id 相同(变基、从基准分支合并):结论和 double-checked 会延续到新 head,并附上一行“结论已延续:patch-id 未变化”的说明。Setup 会报告 review_scope: carry,跳过阶段 02 和 03,阶段 04 执行延续分支。
  • 新增提交(返工、阶段 03 修复):阶段 02 只审查自上次结论以来 hunks 发生变化的文件, 以及这些改动旨在修复的发现(review_scope: delta)。如果 PR 中超过 30% 的文件发生变化,或无法找到可达的先前结论,则进行完整审查。
  • 冲突解决导致差异变化会产生新的 patch-id,因此始终需要重新审查。

交接位置

所有交接文件都位于仓库工作目录中:

.procedure-output/double-check/{stage}/handoff.md

Setup 阶段会在交接文件中记录本地检出目录(REPO_DIR),以便 fix 阶段在同一工作树中操作。每个子 Agent 阶段只会收到所需的交接文件 — 而非完整的编排器上下文。

执行

在更改工作目录之前,使用已加载的 SKILL.md 所提供的资源路径,将 DC_SKILL_DIR 解析为其所在目录的绝对路径。对阶段说明、模板和辅助程序使用同一根目录;不要根据已审查仓库的 cwd 推断该目录,也不要优先选择其他已安装版本。明确将其传递给每个阶段,并在该阶段的 shell 中导出。如果无法获取已加载资源路径,请先停止并解析该路径,再运行各阶段。

精确头部周期(顺序子代理)

每个阶段运行一个 Task,依次执行。不要并行启动任何阶段。当前阶段完成前,不要启动下一阶段。以 restart_count=0 开始。如果阶段 04 发现完整远程 SHA 不同且 patch-id 不同,则停止,不发布判定,也不触碰标签;协调器在观测到的 SHA 上运行一个完整的条件式 01 → 02 → 03 → 04 周期,并设置 restart_count=1,将 delta_base_head(上一周期审查的头部)传给阶段 01,并先将上一阶段 02 的交接文件移至 .procedure-output/double-check/prior-review.md,这样新周期只审查增量及其修复的发现。阶段 02 仍只接收新的设置交接文件和工件:绝不接收编排历史。若再次发生转换,或实时头部无法读取,则停止并阻塞。头部移动但 patch-id 相同不算转换:阶段 04 保留判定。

每个 Task 提示词都必须自包含:

  • 仅包含该阶段的输入交接文件路径
  • 包含该阶段 CONTEXT.md 的路径
  • 传入 pr 和 repo 值
  • 不要传入编排历史或先前推理

Task 提示词模板:

You are running stage {NN}-{name} of the double-check procedure.

PR: {pr}    REPO: {repo}
DC_SKILL_DIR: {absolute skill directory}
Export DC_SKILL_DIR to this absolute path before executing shell snippets.

Read your stage instructions:
  {DC_SKILL_DIR}/stages/{NN}-{name}/CONTEXT.md

Your inputs:
  {list only the input handoff paths from that stage's CONTEXT.md}

Write your output to:
  .procedure-output/double-check/{NN}-{name}/handoff.md

Execute all steps in CONTEXT.md. Write handoff.md before exiting.

阶段门控:

  • 阶段 02 是独立的关键判断步骤。其提示词必须仅包含设置交接文件(PR + 首次审查 + 差异)——不得包含其他内容。这是整个流程存在的目的:提供干净的上下文窗口。
  • 阶段 01 完成后,读取其交接文件。如果 review_scope: carry,则跳过阶段 02 和 03,运行阶段 04 的 carry 分支(自 ready 判定后,PR 自身的差异未发生变化)。
  • 阶段 02 完成后,读取其交接文件。如果 fixes_needed: false,则跳过阶段 03(无需应用修复),直接进入阶段 04。否则运行阶段 03。
阶段 04(内联)

在协调器上下文中自行运行阶段 04——不要派生 Task。读取 CONTEXT.md:

{DC_SKILL_DIR}/stages/04-post/CONTEXT.md

运行实时精确头部门控(gh pr view),然后仅当头部匹配时才发表评论并应用标签。验证标签和评论确实已生效,写入报告文件,并由协调器发出 [pylot] outcome=... 标记(绝不能由子代理发出)。 如果阶段 04 以 3 退出,则设置 RESTART_COUNT=1,并在当前实时头部上运行新的完整条件式阶段 01 → 02 → 03 → 04 周期;不要传入旧的阶段 02 或阶段 03 交接文件。如果以 2 退出,则表示终止阻塞:不要运行晋级路径。

阶段交接链

01-setup ─► 02-review ─► 03-fix ─► 04-post (inline, reads 01+02+03)
                  │                    ▲
                  └── fixes_needed:false ┘  (skip 03)

退出路径

  • 首次检查失败并默认关闭(至少有一个未解决的 MUST-FIX 代码项):stage 04 会发布一条 `` 评论,移除/不添加 double-checked,添加或 保留 needs-work,且不会创建任何正向后续操作。它会发出: [pylot:$PYLOT_OUTCOME_NONCE] outcome="double-check {repo}#{pr} — verdict {verdict}, double-checked withheld, needs-work retained" status=success
  • 重新检查通过(PR 带有 needs-work,verdict=ready):stage 04 会移除 needs-work,重新切换 double-checked(移除后重新添加),并发出: [pylot:$PYLOT_OUTCOME_NONCE] outcome="double-checked re-check PASS {repo}#{pr} — loop closed, cto-review re-fired" status=success
  • 重新检查失败(PR 带有 needs-work,且至少有一个未解决的 MUST-FIX 代码项):stage 04 会保留 needs-work, 不会重新切换 double-checked,会发布一条带有 `` 标记的结构化 verdict 评论(幂等——若标记已存在则跳过),并发出: [pylot:$PYLOT_OUTCOME_NONCE] outcome="double-checked re-check FAIL {repo}#{pr} — needs-work retained" status=success
  • 首次检查成功:只有在精确匹配当前 40 位十六进制 head 时,明确给出 ready verdict 才能 应用 double-checked;它会发出: [pylot:$PYLOT_OUTCOME_NONCE] outcome="double-checked {repo}#{pr} — verdict ready, {N} findings curated, {N} fixes pushed" status=success
  • 沿用 verdict(review_scope: carry):stage 04 会发布一行沿用说明,保留 标签,并发出: [pylot:$PYLOT_OUTCOME_NONCE] outcome="double-check {repo}#{pr} — verdict carried: patch-id unchanged, no re-review" status=success
  • 失败:失败的 stage 会发出 [pylot:$PYLOT_OUTCOME_NONCE] outcome="double-check failed at stage NN: {reason}" status=failed
  • 受阻:设置过程无法获取/检出 PR(例如合并冲突、PR 缺失)、无法读取当前 head,或发生第二次 head 转换 → [pylot:$PYLOT_OUTCOME_NONCE] outcome="double-check blocked: {reason}" status=blocked(这是有意停止——blocked 是独立的终止状态,并非失败)

返工跟进模式

是否存在“产出修复”跟进派发,以及如何派发,属于仓库策略,而非协议:有些组织会在此技能之上配置 CTO 返工自动化,有些则不会。阅读仓库操作手册(GET /admin/playbooks/<org>/<repo>),查找返工派发部分;如果其中定义了约定,内容会类似这样:

当先前的审查结果为 needs-work 时,门禁规则会将任务派回此技能,并通过任务字符串标明这是 PRODUCE 跟进(而非重新评判)。操作手册会指定要匹配的确切触发字符串/标签,以及自动化的身份——请将它们视为下文已确定的值,而不要在此处硬编码字面文本。

在此约定下收到派发时,请在运行上述阶段之前执行以下操作(操作手册是触发条件和规则名称的准确信息来源——请使本协议与其保持同步,避免两者不一致):

  1. 先扫描 PR 的评论。如果先前的尝试已经发布了 ⚠️ NEEDS HUMAN 标记,或者先前的返工已经在同一个门禁上尝试但失败,就不要循环处理——留给人工处理并停止。切勿在未产出任何内容的情况下重新检查并再次应用 needs-work。
  2. 阅读最新的 CTO 审查评论,了解其中的具体待办事项。
  3. 实际解决这些事项。代码/测试/文档修复:进行更改并推送。要求编辑 PR 正文或提供暂存环境证据不属于返工事项:暂存是发布列车步骤(pylot#3389),而正文不会决定审查结论。如果没有剩余代码事项,就运行下述阶段;MUST-FIX 项为零即为通过。如果请求确实超出此技能的范围(需要专用运行器、人工决策,或你不具备的凭据),请勿悄悄地重新应用 needs-work——发布一条以 ⚠️ NEEDS HUMAN 开头的评论,明确说明阻碍因素及解除阻碍所需的条件,然后停止。
  4. 只有在实际解决这些事项后,才运行 gh pr edit <number> --repo <repo> --remove-label "double-checked,needs-work",然后运行上述阶段,以重新触发标签链。设置流程会将返工后的差异与上次审查结论的 patch-id 进行比较,因此审查只涵盖返工增量及其解决的发现项(如果增量涉及的文件超过 30%,则进行完整审查)。

操作手册中没有返工派发部分? 此模式不适用——按正常的审查/修复/发布流程运行上述阶段。

硬性规则

  1. 只能顺序执行 —— 每个阶段只启动一个 Task,依次运行。绝不并行启动 Task。
  2. 评审是一个连贯的阶段 —— 不要将阶段 02 拆分为按文件或按维度进行的子代理。正确性、边界情况、测试、文档、依赖项和安全性必须一并评判,给出单一结论。
  3. 阶段 02 使用干净的上下文 —— 只传入设置阶段的交接内容及其产物文件(PR 正文、首次评审、变更文件、diff)。绝不要将编排器历史传入其中。
  4. 阶段 04 内联运行 —— [pylot] outcome=... 标记必须由编排器发出。
  5. 绝不将完整的编排器上下文传入子代理 Task 提示词 —— 仅传入输入内容。
  6. 每个阶段都必须在下一阶段读取前写入 handoff.md。
  7. 不得跳过阶段,除非 fixes_needed: false 时跳过阶段 03(这是明确允许的例外)。
  8. 禁止使用 Quest。 仅通过本地报告文件进行报告——不得 POST 到 Quest,不得使用 127.0.0.1:4242、quest.fellowship.dev 或 QUEST_TOKEN。
  9. 仅在评论成功发布后才应用标签(阶段 04)。重新检查通过时,先移除 needs-work,再添加 double-checked——这是打破结构性循环的关键。重新检查未通过时,不得触碰标签或重新切换 double-checked。
  10. 由代码决定结论;没有 MUST-FIX 即通过。 仅当没有尚未解决的 MUST-FIX 代码问题时,结论才是 ready,首次检查和重新检查均如此;阶段 04 会将 must_fix_open: 0 的 needs-work 规范化为 ready。PR 正文仅表达意图:不进行声明核对,过时的正文至多只需加一行说明。(这取代了 pylot#2649 的声明门槛:在一轮 30 天的检查中,其大多数 needs-work 标记都是由正文过时造成,而 diff 本身没有问题;每次都因此产生返工。)
  11. 阶段 04 必须验证自身副作用 ——应用标签后,使用 gh pr view 查看 PR,并确认预期的标签和评论确实存在。未验证副作用就报告成功,正是这项技能旨在防止的问题。
  12. 整理首次评审,绝不盲目重新推导 ——设置阶段逐字捕获首次评审评论及其 Head reviewed 回执行;阶段 02 按层级调整评审深度,且只增不减。未找到首次评审时,执行全深度的新评审。
  13. 过时的首次评审是历史证据,不是阻碍,也不代表当前覆盖范围 ——将其 head_sha 与变基后的 PR HEAD 进行比较。针对完整的当前 diff 继续进行连贯评审,重新检查此前的问题,并发布新的当前 HEAD 回执。绝不要仅因收到的回执已过时,就重启整个流程。
  14. 晋级必须绑定最终完整 SHA ——每次发布结论评论或修改标签前,立即获取 headRefOid。40 个字符的实时 SHA 必须与阶段 02 的 reviewed_head_sha 相同,或与已评审 diff 具有相同的完整 patch-id(此时实时 HEAD 成为晋级后的 HEAD);否则必须安全失败。首次 patch-id 变化时,重新开始增量评审;第二次变化或获取失败时,停止并阻止晋级。文件列表、diff 统计、短 SHA 或本地 HEAD 均不能替代 SHA 或 patch-id 的相等性。运行结果过时或被阻止时,绝不能修改 double-checked,也不能触发下游自动化。
  15. 首次检查的晋级必须明确为正向 ——只有评审结论恰为 ready 且绑定到完全一致的实时 HEAD 时,才应用 double-checked。任何负面、缺失、格式错误、过时或相互矛盾的信号都必须安全失败:移除或不添加 double-checked,添加或保留 needs-work,并且不得创建 CTO、FlowChad、staging 或合并后续流程。
  16. 成功标记只能来自阶段 04 的模板(pylot#3392)。 阶段 04“发出 outcome 标记”部分中记录的五个 status=success 标记(四个结论分支和一个延续分支)是完整集合。绝不能由编排器自行编造自由格式的成功标记;除非阶段 04 已完整运行——回执评论已发布且后续验证已通过——否则绝不能发出任何 status=success。2026-09-05,编排器未运行阶段 04 就发出了“queued-worker result ok”:任务被终结为 done,却没有回执,已完成的工作也因此约 6 小时不可见。如果无法运行阶段 04,结果必须是 status=failed 或 status=blocked,并说明原因——伪造成功是最糟糕的退出方式。
  17. 逐字产物必须由 shell 写入,绝不能重新键入。 阶段 01 将 PR 正文、首次评审、清单和 diff 重定向到与其 handoff 同目录的文件中。通过 Write 工具复制这些内容是设置阶段最大的耗时来源,而且可能在不知不觉中偏离源内容。
  18. 等待进程,不要等待时间。 长命令(测试、带钩子的 git push)应以前台方式运行并使用工具允许的最长超时;或在后台运行、记录其 PID,并进行阻塞式等待,在命令退出时立即返回(参见阶段 03“等待长命令”)。绝不要使用 30 秒或更长的固定 sleep N 轮询:实测中最长曾在进程完成后仍多等待 10 分钟。
  19. 验证遵循所属仓库的约定。 阶段 03 根据修复增量及受影响的使用方,选择有意义的检查,并保留必要的广泛/全量、依赖项、转换、集成和发布门槛。只有当前仓库策略和已配置的工作流明确规定某项门槛由 CI 负责时,才可由 CI 承担。只有在策略允许复用且范围/环境一致时,才避免在同一修订版本上重复运行;如有变更、失败或未解决的问题,必须重新运行。绕过钩子必须获得仓库的明确许可,并证明所有被绕过的检查均已通过。阶段 02 的独立评审和阶段 04 的精确 HEAD 验收仍是必需步骤;聚焦测试不能免除任何一项。

参考文件

  • CONTEXT.md — 架构概述
  • stages/NN-name/CONTEXT.md — 各阶段的输入、任务和输出约定
  • shared/review-comment-template.md — 精选的 PR 评论模板(阶段 04)
  • shared/report-template.md — 本地报告文件模板(阶段 04)

评论

支持 Markdown