pr

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese
Turn committed work into a draft PR a reviewer trusts in under a minute: what changed, proof it works, and how risky it is to merge. The draft is the gate: the human marks it ready, so you open it and stop.
The skill starts once the code is committed and ends at a published draft. Scratch lives outside the repo:
SCRATCH="${TMPDIR:-/tmp}/pr-<branch>"
. Screenshots and logs stay there, off the branch, and are kept after upload so revisions can reuse them.
将已提交的代码工作在一分钟内转化为值得审核者信赖的草稿PR:包含变更内容、生效证明以及合并风险。草稿PR是一道关卡:由人类标记为就绪状态,因此你只需创建草稿PR后即可停止。
该Skill在代码提交后启动,在草稿PR发布后结束。临时工作区(Scratch)位于仓库外部:
SCRATCH="${TMPDIR:-/tmp}/pr-<branch>"
。截图和日志存储在此处,不纳入分支,上传后仍会保留,以便后续修订时复用。

Steps

步骤

  1. Shape. Decide how many PRs this work becomes and each one's base, per Shape. Done when every change belongs to exactly one PR and each PR has a base.
  2. Claims. Read the diff GitHub will show (
    git diff origin/<base>...HEAD
    ) and write each change as a claim: one sentence a reviewer could check by looking or running. Done when every changed file sits under a claim or is named in the Scope line.
  3. Proof. Prove each claim with the lowest rung of the proof ladder that carries it. Done when every claim has its proof or a "Not verified: <why>" line.
  4. Body. Write
    $SCRATCH/body.md
    and a title, per Body. Done when every claim appears in Evidence and every referenced file exists.
  5. Publish. Push and open or update the draft, per Publish. Done when the read-back passes.
  6. Report. Post the PR URL, one line on what was proved and one on what wasn't, then stop. A helper under an orchestrator reports per delegate.
  1. 拆分(Shape)。 参照拆分章节,确定本次工作应拆分为多少个PR,以及每个PR的基分支。当所有变更都恰好归属一个PR、且每个PR都有明确的基分支时,该步骤完成。
  2. 变更声明(Claims)。 读取GitHub将展示的diff(
    git diff origin/<base>...HEAD
    ),将每一项变更整理为一条声明:用一句话描述,审核者可通过查看或运行验证其正确性。当所有变更文件都对应某条声明,或在范围行中被提及时,该步骤完成。
  3. 证明(Proof)。 参照证明阶梯,使用能支撑声明的最低层级证明方式来验证每一条声明。当所有声明都有对应证明,或标注了“未验证:<原因>”时,该步骤完成。
  4. 正文(Body)。 参照正文章节,编写
    $SCRATCH/body.md
    和PR标题。当所有声明都出现在证据部分、且所有引用的文件都存在时,该步骤完成。
  5. 发布(Publish)。 参照发布章节,推送代码并创建或更新草稿PR。当回读验证通过时,该步骤完成。
  6. 报告(Report)。 输出PR链接,用一行说明已验证的内容,一行说明未验证的内容,然后停止。若为编排器下的辅助Agent,需参照委派章节进行报告。

Shape

拆分(Shape)

Ask of each change: would this build, pass CI and make sense if it were the only thing merged into main?
  • Yes, and it's one change: one PR on the default branch.
  • Yes, and there are several unrelated changes: one PR each, every one on the default branch, each in its own worktree, even when built in parallel.
  • No, it needs another open PR's code: a stack, one concern per layer, foundation at the bottom, built with the
    gh-stack
    skill.
  • Unrelated fixes that touch the same lines: one combined PR, or a stack whose body says the dependency is textual.
Why chaining unrelated fixes hurts, and stack layers in worktrees: stacks. Handing PRs to parallel helpers: delegate. Branch names follow the repo's and the user's conventions.
Base is the PR's real base:
gh pr view --json baseRefName
; with no PR yet, the nearest unmerged branch below in the stack, else the default branch. An orchestrator's handoff names it. Before is
git merge-base HEAD origin/<base>
after fetching the base, the same three-dot diff GitHub shows reviewers.
针对每一项变更,询问以下问题:如果这是唯一合并到main分支的变更,它能否正常构建、通过CI,且逻辑合理?
  • 是,且为单一变更:在默认分支上创建一个PR。
  • 是,但包含多个不相关变更:每个变更对应一个PR,所有PR都以默认分支为基分支,每个PR在独立的worktree中开发,即使是并行构建也如此。
  • 否,依赖另一个未合并PR的代码:使用PR栈,每层对应一个关注点,基础变更在最底层,通过
    gh-stack
    Skill构建。
  • 触及相同代码行的不相关修复:合并为一个PR,或创建一个PR栈,并在正文中说明依赖仅为文本层面的。
为什么串联不相关的修复是有害的,以及如何在worktree中分层构建PR栈:PR栈。如何将PR分派给并行辅助Agent:委派。分支命名遵循仓库和用户的约定。
基分支(Base) 指PR的实际目标分支:可通过
gh pr view --json baseRefName
获取;若尚未创建PR,则为PR栈中下方最近的未合并分支,否则为默认分支。编排器交接时会指定基分支。基准版本(Before) 是拉取基分支后执行
git merge-base HEAD origin/<base>
得到的提交,也就是GitHub向审核者展示的三点diff的基准。

Proof ladder

证明阶梯(Proof ladder)

Each row adds to the rows above only when the change really is that kind.
ChangeMinimum proof
No runtime change (docs, comments, rename)One line saying why. CI green.
Refactor that keeps behaviorThe covering tests by name, plus "no test files changed" or the list of test edits.
Visual tweakOne before/after screenshot pair, with route and action. After-only for brand-new UI. A second viewport only if responsive rules changed.
Bug fix or logic changeA test that goes red with the fix reverted and green with it. Revert only the source files and keep the new test. No test harness: real command output before and after.
Feature without UI interactionNew tests plus one real run (curl, CLI) with its output.
Interaction, motion, multi-step flowStills of the key states plus one short video, made with the
record-ui-walkthrough
skill, only because a still can't show it.
Sensitive area (auth, secrets, CI, weakened tests)The above, plus a note on what could go wrong and what was checked.
One-way door (migration, data, public contract)Migrate and rollback output, affected rows, a recovery plan, and the Hard to undo line in Body.
At every rung: proof comes from the head being merged, so rerun it after a rebase. Name what you didn't verify ("Not verified: Safari"). List every deleted, skipped or weakened test.
Running the app is the repo's business. Use what it documents (a verify skill,
AGENTS.md
, README, its scripts); with nothing documented, work it out and say in Evidence how you ran it. Ready means you can observe the change: the changed element on the page, the new behavior from the service or CLI. A startup log line or an HTTP 200 is not ready. Keep long-running processes alive with your harness's background mode or tmux, and stop only what you started.
Capturing before. Keep the app running. Revert the changed source files in place, let the app reload, capture, then restore and check
git status
matches where you started:
bash
git restore --source="$(git merge-base HEAD origin/<base>)" --worktree -- <source files>
git restore --source=HEAD --worktree -- <source files>
Use a separate worktree of the base only when the in-place revert can't work (no reload, generated code, schema changes).
Screenshots. Use
agent-browser
if it's installed, otherwise whatever browser automation is available, at the viewport the claim needs.
  • Always a full-viewport before/after pair, scrolled so the change and its surroundings are in view. Add a zoomed pair of the changed area when the change is small relative to the page; capture the full page only when its shape changed.
  • Leave subtle changes (gap, alignment, color) unpainted. For a discrete element, draw a thin outline set slightly off it, on the shot where the element exists. Skip arrows and text callouts.
  • Use demo or test data. Open every image before upload and retake any that shows secrets or personal data.
仅当变更确实属于对应类型时,才需要提供该行及以上层级的证明。
变更类型最低证明要求
无运行时变更(文档、注释、重命名)一行说明变更原因,CI通过。
保持行为不变的重构列出覆盖该变更的测试名称,并注明“无测试文件变更”或列出测试文件的修改内容。
视觉调整一组修改前/后的截图,包含对应的路由和操作。全新UI可仅提供修改后截图。仅当响应式规则变更时,才需要额外提供另一视口的截图。
Bug修复或逻辑变更有测试用例在回退修复时显示红(失败),应用修复后显示绿(通过)。仅回退源文件,保留新增的测试。若无测试框架:提供修改前后真实命令的输出结果。
无UI交互的功能新增测试,加上一次真实运行(curl、CLI)的输出结果。
交互、动效、多步骤流程关键状态的静态截图,加上一段短视频,视频需通过
record-ui-walkthrough
Skill制作,且仅在静态截图无法展示时才需要。
敏感区域(认证、密钥、CI、被削弱的测试)上述所有证明,外加一份说明,列出可能出现的问题以及已检查的内容。
单向门变更(迁移、数据、公开契约)迁移和回滚的输出、受影响的行数、恢复计划,以及正文章节中提到的“难以撤销”说明行。
在所有层级:证明都来自待合并的HEAD提交,因此在rebase后需要重新运行验证。明确列出未验证的内容(例如“未验证:Safari”)。列出所有被删除、跳过或削弱的测试。
运行应用 是仓库自身的职责。使用仓库文档中记录的方式(验证Skill、
AGENTS.md
、README、自带脚本);若无相关文档,自行摸索运行方式,并在证据部分说明你是如何运行的。就绪 指你可以观察到变更:页面上的修改元素、服务或CLI的新行为。仅一条启动日志或HTTP 200响应不算就绪。使用你所用运行环境的后台模式或tmux保持长时运行进程的存活,且仅停止你自己启动的进程。
捕获修改前状态。 保持应用运行。就地回退已修改的源文件,让应用重新加载,捕获截图,然后恢复文件,并检查
git status
与初始状态一致:
bash
git restore --source="$(git merge-base HEAD origin/<base>)" --worktree -- <source files>
git restore --source=HEAD --worktree -- <source files>
仅当就地回退不可行时(例如无热重载、生成代码、schema变更),才使用基分支的独立worktree。
截图。 若已安装
agent-browser
则使用该工具,否则使用任何可用的浏览器自动化工具,在声明所需的视口下截图。
  • 始终提供完整视口的修改前/后截图,滚动页面使变更及其周边区域处于可视范围内。当变更相对于页面较小时,额外提供一组变更区域的放大截图;仅当页面整体结构变化时才截取全页截图。
  • 对于细微变更(间距、对齐、颜色),不要在截图上涂画。对于独立元素,在元素存在的截图上,沿元素外侧绘制一圈细轮廓线。不要使用箭头和文字标注。
  • 使用演示或测试数据。上传前检查所有图片,若有泄露密钥或个人数据的情况,重新截取。

Body

正文(Body)

Template first. If the repo has a PR template (
.github/pull_request_template.md
,
.github/PULL_REQUEST_TEMPLATE/
,
docs/
or the root), fill it. Its required fields (ticket, change type, checklists) stay at the top word for word. Add a section below only where the template has nothing similar. With no template:
markdown
undefined
优先使用模板。 若仓库有PR模板(位于
.github/pull_request_template.md
、
.github/PULL_REQUEST_TEMPLATE/
、
docs/
目录或根目录),请填写模板。模板中的必填字段(工单、变更类型、检查清单)需逐字保留在顶部。仅当模板中没有类似内容时,才在下方添加新的章节。若无模板,使用以下格式:
markdown
undefined

Summary

Summary

<What changed and why, 1–3 sentences. Ticket link.> Scope: <what this covers; what it deliberately leaves out>
<What changed and why, 1–3 sentences. Ticket link.> Scope: <what this covers; what it deliberately leaves out>

Evidence

Evidence

  • <claim>: <live UI | test red→green | command output | not verified: why>
  • <claim>: <live UI | test red→green | command output | not verified: why>

Blast Radius

Blast Radius

Door: <two-way: a revert undoes it | one-way: why> Reaches: <what could break, and who consumes it> Look at: <one or two places to read first> Tests/CI changed: <none | list> Not verified: <none | list>

Write a briefing, about 40 lines at most. A rejected alternative a reviewer would ask about gets one sentence in Summary. An optional visual (diff sketch, call tree, diagram) goes in Summary, per [summary](references/summary.md). In Evidence, lead each screenshot pair with its claim, route and action, then a two-column Before | After table. A video sits in its own paragraph (`![](/abs/scratch/walkthrough.mp4)`) so GitHub renders a player. A red/green test shows the command, then what failed before and passes now.

These lines go at the very top of the body when they apply:

- A hard-to-undo change: "Hard to undo: <why>. Needs an owner's review before ready."
- The app couldn't run: "Not verified: live UI, <reason>." Open the draft anyway with the strongest proof you have.
- A judgment call you couldn't settle: one short question for the reviewer.

**Updating a PR.** Keep text a human wrote and work it in; replace only placeholders and what an agent wrote. After new commits, rewrite the body to describe the current head and rerun proof only for the claims those commits touch.

**Title** follows the repo's convention, read from recent merged titles (`gh pr list --state merged --limit 15 --json title`). Include a ticket key only when the branch or commits name one and the convention uses keys.
Door: <two-way: a revert undoes it | one-way: why> Reaches: <what could break, and who consumes it> Look at: <one or two places to read first> Tests/CI changed: <none | list> Not verified: <none | list>

正文需为摘要形式,最多约40行。如果存在审核者可能会问到的、已被否决的替代方案,在摘要中用一句话说明。可选的可视化内容(diff草图、调用树、图表)可放在摘要中,参照[摘要](references/summary.md)章节。在证据部分,每组截图前需先说明对应的声明、路由和操作,然后放置一个两列的“修改前 | 修改后”表格。视频需单独放在一个段落中(`![](/abs/scratch/walkthrough.mp4)`),以便GitHub渲染播放器。红/绿测试结果需先展示命令,再说明修改前失败的内容和修改后通过的内容。

以下内容在适用时需放在正文的最顶部:

- 难以撤销的变更:“难以撤销:<原因>。标记就绪前需负责人审核。”
- 应用无法运行:“未验证:线上UI,<原因>。” 即便如此,仍需使用你能提供的最强证明创建草稿PR。
- 你无法决断的判断性问题:向审核者提出一个简短的问题。

**更新PR时。** 保留人类编写的文本并整合进去;仅替换占位符和Agent编写的内容。新增提交后,重写正文以描述当前HEAD的状态,且仅重新验证这些提交涉及的声明。

**标题** 遵循仓库的命名规范,可参考近期合并的PR标题(使用`gh pr list --state merged --limit 15 --json title`命令查看)。仅当分支或提交中包含工单编号、且规范要求使用编号时,才在标题中加入工单编号。

Publish

发布(Publish)

bash
git push -u origin HEAD
gh pr create --draft --base <base> --title "<title>" --body-file "$SCRATCH/body.md" \
  --attach "$SCRATCH/<slug>-before.png" --attach "$SCRATCH/<slug>-after.png"
gh pr edit <number> --title "<title>" --body-file "$SCRATCH/body.md" --attach ...   # existing PR
gh pr view <number> --json isDraft,body
--attach
uploads each file and rewrites the matching local path in the body; pass one per file, with the same absolute path the body uses. A partial upload failure still creates or updates the PR and exits nonzero, so repair it with
gh pr edit
. The read-back passes when a new PR is a draft and the body has no local paths left (
/tmp/
,
/var/folders/
,
/Users/
,
/home/
).
An existing PR keeps whatever draft or ready state it has. Marking ready, CI and review comments belong to the human or a separate step, so the run ends here.
bash
git push -u origin HEAD
gh pr create --draft --base <base> --title "<title>" --body-file "$SCRATCH/body.md" \
  --attach "$SCRATCH/<slug>-before.png" --attach "$SCRATCH/<slug>-after.png"
gh pr edit <number> --title "<title>" --body-file "$SCRATCH/body.md" --attach ...   # existing PR
gh pr view <number> --json isDraft,body
--attach
参数会上传每个文件,并替换正文中对应的本地路径;每个文件单独传入一个
--attach
参数,路径需与正文中使用的绝对路径一致。部分文件上传失败时仍会创建或更新PR,但命令会返回非零退出码,因此需使用
gh pr edit
修复。当新建的PR为草稿状态、且正文中不再包含任何本地路径(
/tmp/
、
/var/folders/
、
/Users/
、
/home/
)时,回读验证通过。
已有PR将保留其原有的草稿或就绪状态。标记就绪、CI运行和审核评论属于人类或其他独立步骤的职责,因此本Skill的运行到此结束。