pr 精读:用最小的那个视图说清改动,再交出一个门和一片爆炸半径
pr 的正文是一条模板:Summary 要选「最小的那个能说清变化的视图」(伪代码、调用树、组件树、文件树、Mermaid、diff,用一到几个),Evidence 必须是 before/after 而不是一句「测试通过」,Merge Danger 要给出 one-way / two-way door 与 blast radius 这两种判断。本文讲清它为什么把一份 PR 描述做成「字段 + 判据」而不是填空题,为什么视图菜单旁边写着「你可以用一个,几乎不会用全部」,以及它如何在 CREDITS.md 里如实标出 Summary 部分的出处(Dex Horthy 的 show-me),并解释为什么不加一个硬依赖。
本篇属于系列 读懂最优秀的开发技能是怎么写的(Matt Pocock skills 逐技能精读) · 第 20 篇
(本文读的是 mattpocock/skills 快照 5beb35b,2026-10-19。引用原文都能按文中路径回仓库核对。这是「逐个技能精读」系列的第二十篇,聚焦 pr 一个技能。)
它怎么工作:一条模板、三个小节、每个小节给判据
skills/engineering/pr/SKILL.md 的 frontmatter 里,description 只有一行:Use when writing a PR body. 正文第一句是 Use this template for writing the PR body:,后面跟一段围起来的 markdown 模板,只有三个小节:
## Summary
<diagram, diff-sketch, or tree>
## Evidence
- **Before:** <screenshot/output/failing test run>
**After:** <screenshot/output/passing test run>
## Merge Danger
**Door:** <one-way or two-way>
**Blast Radius:** <one-word description>
触发有两种:敲 /pr,或者任何一次 agent 要写 PR body 的时候自动用上。但边界写在文档里——它不推分支、不开 PR、不决定 PR 里放什么,它只规定描述该长什么样。用之前还有一句总纲:Skip all preambles and keep prose brief. Use the user's domain language from GLOSSARY.md.
Summary 的核心判据是一句话:
Pick the smallest view that makes the key point clear.
后面跟一份视图菜单:逻辑或算法写成伪代码;运行时控制流写成调用树;UI 结构写成组件树(带上有意义的 state 和模块边界);文件职责或大重构写成浅文件树;组件交互、控制流、数据流用 Mermaid;当重点是「变了什么」而周边形状已经存在时用 diff。
菜单之外还有两处细节值得抄。一是 diff 本身也要挑形状:组件变更、文件布局变更、调用树变更、状态或控制流变更各配一个示例,因为同一种改动配错视图等于没画。二是什么时候该贴整块:大部分是新代码时、省略上下文会藏住归属或顺序时、用户需要一个可直接复制的目标形状时——那时给一整个抓得住的函数,而不是一段 diff。
然后是一段摆放指导。每个视图要挨着它支撑的那句短文本;只保留回答当前问题所需要的调用、文件、props、状态和边界;末尾一句几乎是这个技能的语气代言:
You may use one of these, you may use several, it is unlikely you will use all of them. Use your judgement and don’t overwhelm the user.
Evidence 要求具体证据,并且必须是 before / after。截图是 S 级——前提是环境搭好了、改动是视觉的。执行类证据是 A 级,而且要求很具体:Show the exact test that now fails and passes, using pseudocode. 注意是「写出那个先红后绿的确切测试」,不是「说测试通过了」。
Merge Danger 要求两件事:它是哪一种门,和它的爆炸半径。文档给的是定义而不是清单:两步门你可以走回来,一步门走不回来,所以便宜回滚的 PR 风险更低;涉及破坏性操作或难以逆转的决定就是一步门。半径则是这次改动可能影响的范围——布局位移、下游消费者被破坏、移动端响应式这些都是它点名的例子。
产物很朴素:一段可以直接粘进 PR 描述框的 markdown。
它在这条链上的位置也写明了(docs/engineering/pr.md):to-spec → to-tickets → implement → code-review → pr → retro,排在评审之后、复盘之前——因为一份 PR 描述应该描述已经评审过的 diff。又因为它是 model-invoked,任何一次「帮我把这个开成 PR」都会自动套上这个形状。
它和「一般技能」的差别:给菜单不给格式,给判据不给结论
一般的 PR 技能会说「用清晰的小标题总结你的改动」。这里给的是判据加菜单:六种视图、每种配一个「什么时候用」、再加上一句「你几乎不会全用」。它把「选哪个」这个决定交回给作者,而不是塞一个固定格式给所有人。
第二个差别是它把「风险」从一个形容词变成一个可以被反对的断言。常见模板写「risk: low / medium / high」,读者只能选择信不信。这里要求你说出是哪种门、半径用一个词,于是「这能不能合」从一种感觉变成一句可以被反驳的话,也顺手告诉评审者注意力该花在哪:两步门小半径扫一眼,一步门慢慢读。
第三个差别是证据必须是 before / after。「测试都绿了」这种句子在模板里根本没有位置可放。
第四个差别是它诚实标出处。frontmatter 里有机器可读的 metadata.credits(技能名、作者、组织、URL),skills/engineering/pr/CREDITS.md 里则说明:Summary 那一节的视图菜单和摆放指导,几乎逐字来自 Dex Horthy 的 show-me,只是从「实时对话」改瞄准了「diff」。
第五个差别是它把目标反过来写:一般模板想把信息写全,它想别让评审者淹死。文档记录了要防的那种 body——“a long summary but all I need to know is what changed, how it was verified, what could break, and whether it’s safe to merge”。后半句正是它的三个小节。这不是审美偏好,而是把评审者真正要回答的问题按顺序摆好;如果最后还是收到一堆图,文档也承认可能发生,那时问题通常在 PR 本身太大——pr 不会替你拆。
它有意识摒弃了什么
一、摒弃了开场白。 Skip all preambles:body 直接从 ## Summary 开始,不介绍背景、不客套。
二、摒弃了散文式描述。 Summary 的位置留给一个视图,措辞只作为视图的注解。
三、摒弃了「证据 = 断言」。 没有 before 和 after 就不是证据。
四、摒弃了风险清单。 它给门的定义,不给一张打分表——打分表会让你填,定义会让你想。
五、摒弃了注意力均摊。 视图挨着它支撑的那句话,只保留当下问题需要的元素,默认读者已经打开 diff 了。
六、摒弃了越界,也摒弃了兼容。 不开 PR、不推分支、不替你把大 PR 拆小、不处理回来的评审意见、不负责让正文随 PR 更新;它也不看你仓库里既有的 .github/pull_request_template.md,文档直说这两个模板默认谁都不让,要你自己在仓库的 agent 文档里裁决。
原文证据
三句判据原文:
Pick the smallest view that makes the key point clear. Place each visual next to the short text it supports. Keep only the calls, files, props, states, and boundaries needed to answer the user’s current question or the options to resolve the current discussion point. Screenshots are S-tier - when the environment is set up for it and the change is visual.
门的定义(第 168 行):
Describe whether it’s a one-way or two-way door. You can walk back through two-way doors, but not one-way doors. A PR that is cheap to roll back is lower risk. Changes that involve destructive actions or hard-to-reverse decisions are one-way doors.
出处声明(skills/engineering/pr/CREDITS.md)写得不含糊:
The Summary section’s menu of visuals (pseudocode, call trees, component trees, file trees, Mermaid, diffs) and its placement guidance come from Dex Horthy’s
show-meskill, reproduced almost word for word and aimed at a diff instead of a live conversation.prdoes not depend onshow-meas a skill (it isn’t part of this repo, and a hard dependency would break standalone installs), so the content is copied in rather than pointed at; this file is the attribution a dependency would otherwise have carried.
可迁移结论
- 产出物给「字段 + 判据」,不给填空题。 模板只圈出三个字段,每个字段旁边写着它要满足的条件——填空容易糊弄,判据才逼你想。
- 用菜单代替格式。 给选项、给每个选项的适用条件、再明确说「你几乎不会全用」,比规定一种格式更能适配不同改动。
- 把主观判断变成可反对的断言。 「一步门 / 两步门 + 半径」比「风险低」有用,因为前者可以被评审者当场反驳。
- 证据必须可证伪。 before / after 是最低门槛;「已验证」不是证据。
- 抄别人的东西就抄得明白。 机器可读的
metadata.credits加人读的CREDITS.md,并把「为什么不加硬依赖」也写进去——声明不只是礼貌,它解释了一个技术取舍。 - 明确写下技能不做的事。 「不推分支、不开 PR、不拆大 PR、不同步正文」这几句,省掉了使用者所有的猜测。
pr 总共 170 行,其中一半是示例代码块。它真正说出口的只有三件事:一张最小的视图、一组 before/after、一句门和半径。 它不替你做判断,只要求你把已经做过的判断写下来。
讨论
用 GitHub 账号留言;评论保存在公开仓库chengshu-blog-discussions的 Discussions 里。也可通过 RSS 订阅后续文章。