Community编程与开发github.com

appshapes/pr

打开当前分支的拉取请求并作为作者完成整个审查循环:一条指令一个门控,审查记录作为正文,合并主分支,自动合并标签,等待每个阶段所需的时间,以及每个停滞点所需的唯一手动步骤,并在合并后整理干净。

pr 是什么?

该技能为AI助手(特别是Claude Code会话)提供了一种结构化方法,用于通过拉取请求将功能分支合并到主分支。它涵盖了完整的作者端流程:从打开拉取请求、运行门控检查、提交审查记录、合并主分支,到监督审查过程直至合并。该技能优先使用合并而非变基,处理冲突(特别是在追加文件中),并监控CI状态。它支持通过CLI命令在GitHub上进行自动审查循环,并处理常见场景,如审查被请求、修复运行、冲突和自动合并。该技能与CLAUDE.md中定义的工作规则保持一致,旨在防止不必要的人为干预,同时指导在停滞点所需的唯一手动步骤。

兼容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/appshapes/cavalry/tree/HEAD/.claude/skills/pr

Installed? Explore more 编程与开发 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

通过拉取请求将分支合并到 master 上。/commit 是个人直接通往 master 的路径;而这条路径适用于 Claude Code 会话处理分支上的任务卡片,CLAUDE.md 将其分配给机器人和代理(代理工作规则;ADR 0004)。拉取请求由 docs/how-to/ask-the-agent.md 中的循环进行审查,该页面从问题的角度描述了这个循环。此技能是作者端的内容:要运行什么、等待什么,以及在每个停滞点需要做的一件事。循环自动完成的所有事情都留给它自己处理;在错误时机的人为干预正是此技能要防止的。

参数是:$ARGUMENTS。卡片编号会打开拉取请求(第 1 节)并监控它(第 2 节)。watch <number> 监控一个已打开的拉取请求。空参数:在分支上有提交领先于 origin/master 且没有拉取请求时,打开一个;有打开的拉取请求时,监控它;在 master 上时,停止并说明 /commit 是从 master 出发的路径。

仅合并。绝不使用 rebase,绝不使用 --force。如果冲突出现在下面命名的追加文件之外,则停止并将问题交回。

1. 打开拉取请求

  1. 读取状态。 git fetch --quiet origin,然后 git status(绝不使用 -uall)、git log --oneline origin/master..HEAD、git diff 和 git diff --cached。分支名称为 <card>-<slug>;如果更改位于 master 上,则首先使用 git switch -c <card>-<slug> 将其移动到新分支。像 /commit 一样检查差异是否符合 CLAUDE.md(每个提交一个 crate,文档在同一个提交中,数据平面更改的直方图,依赖项的理由,spec/ 的 ADR),并扫描每一行新增代码以查找密钥。如果差异大约超过一千行变更(排除生成和记录的文件),则不是一个拉取请求能处理的:按照 docs/how-to/implement-a-feature.md 步骤 3.8 中的说明,按 crate 和平面拆分,以便第一次审查的阻塞点能在一次修复运行中解决,并在当前拉取请求合并后从各自的分支打开其余部分。

  2. 运行门控,每条命令单独运行。 在下一个命令之前读取每个退出码:

    just lint;      echo "lint exit $?"
    just test;      echo "test exit $?"
    just docs;      echo "docs exit $?"
    just lint-docs; echo "lint-docs exit $?"
    

    绝不要通过管道或管道后面的 && 链接门控:just lint 2>&1 | tail -1 && git commit 会报告 tail 的退出码,导致失败的门控被忽略。2026 年 10 月 26 日,有两个提交因此进入了拉取请求 57 的分支,一个未通过 just lint,另一个未构建成功,每个都浪费了一个审查周期。非零退出码会停止执行序列;修复后,重新开始此步骤。

    笔记本的门控仅编译笔记本的平台。如果更改添加或修改了 cfg(target_os = "linux") 块或它的 not 对等块,则在推送前需要针对 Linux 进行类型检查,因为 Linux 门控和两个基准测试主机都会构建它:

    cargo check --workspace --all-targets --target x86_64-unknown-linux-gnu; echo "check exit $?"
    

    一次性 rustup target add x86_64-unknown-linux-gnu 即可安装目标;检查不需要链接器。2026 年 11 月 1 日,拉取请求 94 的第一次审查中,CI 在一个文件上报告了三个 Linux 错误,而所有 macOS 门控都已通过。 如果 cfg(target_os) 阶梯有两个以上的分支,则需要在第三个目标上进行检查,即 --target x86_64-unknown-freebsd(一次性 rustup target add 后):在 CI 运行的两个目标上,只有一个分支是活跃的,因此第三个分支在那里是死代码,或者与其他分支重叠的分支,只会在其他平台上暴露。2026 年 11 月 1 日,拉取请求 95 的第二次审查中,有两个常量在每个目标上都定义了两次,除了 Linux 和 macOS。

  3. 提交。 消息是审查记录,如同 /commit 所写的那样:主题 <card>: <祈使句主语>(不超过 72 个字符);正文包含更改内容、涉及的不可变规则编号以及证据(门控结果、ADR 编号、数据平面 crate 下更改的两个直方图、just conformance 和 just replay-check 的结果,当更改声称正确时)。分支上有多个提交是可以的;压缩合并会将拉取请求的标题和正文作为 master 上的提交(auto-merge.yml),因此分支上的消息只是该提交的草稿。

  4. 合并 master。 git merge --no-edit origin/master。如果冲突出现在每个人都会追加的文件(CHANGELOG.md、docs/SUMMARY.md、docs/glossary.md、spec/README.md、counters.toml、crate 的 lib.rs)中,则通过保留双方内容并让 master 的行排在前面来解决(CLAUDE.md,代理工作规则);任何其他冲突则交回处理。合并提交后,再次运行步骤 2。

  5. 检查 CI 将要检查的内容。 CI 的 lint-docs 针对 origin/master...HEAD(整个分支)运行,而笔记本只检查工作树或最后一个提交(scripts/lint-docs.py,头部)。在推送前运行 CI 的范围:

    LINT_DOCS_RANGE=origin/master...HEAD just lint-docs; echo "lint-docs exit $?"
    

    这也是为什么在一个分支的一个提交中接受、在后续提交中编辑的 ADR,会通过 CI 但笔记本的 HEAD~1..HEAD 检查却会失败,提示“在 HEAD 处接受并已更改”:在分支的范围内,ADR 是新的。请信任 CI 运行的范围。

  6. 推送并打开。 git push -u origin <branch>。将正文写入文件,绝不要内联写入:它是 master 上的提交消息,因此是完整的审查记录,根据分支的提交消息构建,就像循环的 open-pr 作业根据代理的提交消息构建一样:更改内容、涉及的不可变规则编号、证据以及 CI 未检查的内容(数据平面更改的主机基准测试数据、解析器更改后的 just fuzz 结果)。当存在相关问题时,以 Closes #<issue> 结尾。然后:

    gh pr create --title "<card>: <祈使句主语>" --body-file <file> --label auto-merge
    

    在创建时添加 auto-merge:审查者对当前 head 的批准随后会启动一个压缩合并,在所需检查通过时自动完成,无需任何人介入(auto-merge.yml)。仅当用户要求先阅读拉取请求时才不添加该标签。

  7. 确认审查已开始。 在一分钟内,gh run list --workflow "dispatch review" --limit 3 会显示一个以拉取请求命名的 pull_request_target 运行,一分钟后 gh run list --workflow "review pr" --limit 3 会显示 review pr <number>, attempt 1。审查者在 master 上运行(ADR 0005),因此它位于 Actions 选项卡中,而不是拉取请求的检查列表中。两分钟后仍未出现:gh pr edit <number> --add-label review 并再次检查。

2. 监控拉取请求

一次性读取状态,然后等待。一次推送后,审查大约需要十分钟;修复运行最多需要三十分钟;bench (linux) 和 bench (grip) 作业各自拥有自己的主机 bench 和 grip。轮询频率不超过每五分钟一次,并且不要触及以下规则未提及的任何内容。每次等待都是循环自身正在进行的工作;停滞点由规则说明。

gh pr view <number> --json state,mergeable,headRefOid,labels,reviewDecision
gh api repos/{owner}/{repo}/pulls/<number>/reviews --jq '.[] | "\(.submitted_at) \(.state) \(.commit_id[0:7]) \(.user.login)"'
gh run list --workflow claude --limit 5
gh run list --workflow "dispatch review" --limit 5
gh run list --workflow "review pr" --limit 5
gh pr checks <number>
  • claude[bot] 请求更改。 claude 运行(事件 pull_request_review)在一分钟内启动并应用分支上的阻塞点。在其运行或等待期间,不要推送任何内容:每个周期只能有一个写入者。它的运行在每个拉取请求的队列中一次处理一个,并且 GitHub 每个队列保留一个待处理运行,因此你现在的推送会获得自己的审查,并且该审查启动的修复运行会取消已在等待的那个;在拉取请求 57 中,两次审查因此丢失了它们的修复运行,而实际执行工作的运行响应的是两个 head 之前的审查。修复者会在每个阻塞点通过测试后提交,并在过程中推送,因此在一个运行期间 head 可能会移动多次;审查是针对它离开时的 head。当运行完成时,它的最后一个作业会取消 GitHub 在修复者最后一次推送之前的 head 上保留的 ci 运行(claude.yml,“取消修复者遗留的 head 上保留的运行”:如果分支在合并时被删除,保留的运行如果单独留下会以失败告终并发送邮件;auto merge 运行会在合并前清理这些保留的运行),批准最后一次推送上的 ci 运行,如果 head 还没有 dispatch review 运行,或者修复仅是对拉取请求正文的编辑(claude.yml,“请求审查代理的推送”),则添加 review 标签,以便在运行结束一分钟后出现 dispatch review 运行。仅当一分钟过去且仍未出现时,才自行添加 review。

  • “自主修复上限已达到”。 第四次请求更改的审查会结束修复者的部分(claude.yml,MAX_ATTEMPTS: 3)。现在轮到作者处理拉取请求:修复、步骤 2、步骤 4、推送。人的推送会触发其自己的 dispatch review 运行。

  • 修复者无法应用的阻塞点。 修复者的运行拒绝写入 .github/workflows/**、.claude/**、spec/** 和 bench/baseline.json(claude.yml,settings.deny),因此如果审查的所有阻塞点都在这些文件中,其运行会以“修复会话在没有推送的情况下结束……并且未对拉取请求正文进行更改”而结束。这些从第一次审查开始就需要作者处理:应用更改,推送。仅涉及拉取请求正文的阻塞点,修复者会自行使用 gh pr edit 应用,并且其运行会请求审查未更改的 head(问题 11);当你自己编辑正文时,使用 gh pr edit <number> --body-file <file>,然后使用 gh pr edit <number> --add-label review,因为对正文的编辑不会触发新的审查。

  • 一个 head 十五分钟后仍无审查。 gh run list --workflow "review pr":一个审查者会话未得出裁决的运行会由循环本身重试为 attempt 2;失败的 attempt 2 是第二次错过,gh pr edit <number> --add-label review 会启动第三次。在你推送后,如果 head 根本没有 dispatch review 运行,则使用相同的标签。

  • CONFLICTING。 分支下的 master 发生了移动;GitHub 不会对有冲突的拉取请求启动任何运行。执行步骤 4、步骤 2、推送。

  • 红色检查。 gh run view <run id> --log-failed。bench (linux) 在主机 bench 上运行,bench (grip) 在 grip 上运行:绝不要在作业可能正在运行时(gh run list 显示为 in_progress 或 queued;主机上的 pgrep -a cavalry-bench)在任一主机上运行基准测试,并且那里的门控失败应在更改任何内容之前从 bench-compare 自身的日志行中读取。

  • 已批准。 auto-merge.yml 在批准时启动合并,但要求批准的 commit_id 是当前 head;对旧 head 的批准不会启动任何操作,较新的 head 会获得自己的审查。合并会在所需检查通过时完成:gh pr checks <number> --required。批准后发生移动的分支会被 GitHub 拒绝,auto merge 运行会说明原因:如果 GitHub 为新 tip 启动了运行,则发送通知且运行显示绿色(循环会自行审查);如果一分钟后未启动任何运行,且拉取请求对象仍指向已批准的提交,则标记为失败,此时只有推送才能继续:步骤 4、步骤 2、推送(auto-merge.yml 的头部;2026 年 11 月 4 日的拉取请求 106)。

  • 已合并。 git fetch --quiet origin 和 git log --oneline -1 origin/master 显示包含拉取请求标题的压缩提交;gh run list --branch master --workflow ci --limit 1 是其 CI 运行,并且拉取请求的完成需要等待该运行变为绿色。然后在卡片上评论提交哈希并归档它,然后运行 just tidy:它会在本地清理分支及其工作树,而 GitHub 已在远程删除该分支。

3. 报告

提供拉取请求编号和 URL;每次审查的裁决,谁响应的以及使用了哪个推送;master 上的压缩提交及其 CI 运行;以及 just tidy 已执行。如果应用了上述规则,请说明是哪条以及原因。如果拉取请求正在等待修复运行或审查,请说明并告知下一个要检查的内容;不要添加标签来催促进程。

相关技能