mcpField
P
pr-recap

pr-recap

github.com/mdsmithaustin其他844 次安装今天更新
代码仓库

关于 pr-recap

pr-recap 是为代码审查者撰写拉取请求摘要的技能,以 GitHub 评论形式发布并核验事实。它涵盖差异分析、可选示意图绘制和评论维护流程。

主要功能

  1. 01基于差异核验说法
  2. 02面向审查者的叙述模板
  3. 03可选 PNG 机制示意图
  4. 04GitHub 评论更新流程
  5. 05核对提交 SHA 与链接

适用场景

  1. 01概述涉及行为变化的拉取请求
  2. 02新提交后更新摘要
  3. 03发布前核验摘要内容

安装

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

$npx skills add https://github.com/mdsmithaustin/pstack --skill pr-recap

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

包含的文件

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

CREDITS.md
references/
block.md
reader.md
sketch.md
references/examples/
bars.json
check.json
flow.json
rewire.json
to-scale.json
scripts/
attachment.mjs
scripts/sketch/
bun.lock
draw.mjs
package.json
sketch.mjs
scripts/sketch/vendor/
OFL-Excalifont.txt

详细介绍

PR 摘要

为审查 PR 的人员写一份摘要。审查者应能从首屏了解这项变更为何存在、改了什么,以及如何实现。摘要应指向差异内容,不能代替阅读差异。

在本地运行此工作流。摘要是一条 PR 评论:GitHub Markdown 加一张上传到 PR 自有主机的 PNG 图片。需要 gh,绘图需要 Bun 和随附的绘图工具。不会向任何其他主机发布内容。

判断 PR 是否需要摘要

如果差异中没有审查者必须追踪的行为变化,就跳过摘要。例如,版本固定及其哈希值、拼写或措辞修正、仅格式变更、仅锁文件变更,以及单个提交的回滚。即使跨越主版本,版本固定也无需摘要,因为版本固定没有可绘制的机制。

对于跳过摘要的 PR,不要在 GitHub 上发布任何内容。在回复中写一行:

Recap skipped for PR <n>: <what the diff is>, <why it needs no recap>.

否则,写摘要。每次推送导致差异发生变化后,都要重新撰写摘要;须等新提交已发布,且在其上运行的任何门禁都已得出结果。

收集事实

  1. 从 origin 的 fetch URL 解析出 <host>/<owner>/<repo>。每次调用 gh pr 时都传入 -R <host>/<owner>/<repo>。每次调用 gh api 时都传入 --hostname <host>。
  2. 使用 gh pr view <n> -R <host>/<owner>/<repo> --json number,title,body,baseRefName,baseRefOid,headRefOid,files,commits,reviews,comments,closingIssuesReferences 读取 PR 记录。记录 baseRefOid 和 headRefOid。摘要中的每项事实都必须描述这两个 SHA 之间的差异。
  3. 使用 gh pr diff <n> -R <host>/<owner>/<repo> 阅读完整差异。阅读你要描述的每个代码块周围的代码、其调用方,以及所有已关联的问题。不要对未读过的文件作出任何断言。
  4. 阅读已发布的审查意见、已发布的评审结论评论,以及 head 上的 CI 运行记录。未在 PR 上发布的评审结论不能作为证据。
  5. 根据这些记录构建每项断言。会话记忆可以帮助你找到记录,但不能证明断言成立。

撰写前先梳理核心内容

在笔记中回答以下三个问题,每个答案都要依据一条记录:

  • 原因。 在此 PR 之前出了什么问题,或缺少什么?指出人们实际看到的具体症状,例如路由丢失、结论错误,或合并时没有监视器。“改进 X”不是原因。
  • 内容。 PR 更改的一个机制。如果更改了多个机制,就选出原因所依赖的那个。
  • 方式。 修复问题的具体改动,例如调整顺序、新增角色、新增检查,或重新连接调用。

不要编造理由。只有在差异、PR 正文、已关联的问题、提交消息或已发布的审查意见中有依据时,才能说明原因。其他原因一律标注为 (a guess)。

撰写评论

复制此区块中的模板。首屏必须恰好包含三个部分:

  1. 核心内容。 最多两句话,不超过 60 个单词。第一句说明原因,并指出具体症状。第二句说明改了什么以及如何实现,措辞应与审查者在差异中看到的内容一致。不要使用分号、文件列表,也不要列出绘图已展示的数量。
  2. 示意图。 展示一张描绘已更改机制的图片。参见示意图。
  3. 未涵盖内容。 用一行指出 PR 无法证明的内容,例如未测量的运行时表现、未经测试的路径,或已发布评审结论中的注意事项。

其他所有内容都放在它们之后的一个折叠式 <details> 区块中:风险说明、SHA、阅读顺序、简短的变更区域列表,以及证明材料链接。不要使用表格。

绝不要从差异中复制秘密、令牌或看起来像凭据的值。应以 <redacted> 替代。

对摘要中的句子使用 technical-writing 技能,然后使用 unslop 技能。

绘制草图

在技能目录之外,选择一个可写的工作文件夹,用于存放 scene.json、sketch.png、story.txt 和 recap.md。从该文件夹运行渲染、读取和发布命令。将 <skill> 替换为此技能目录的绝对路径。

按照草图操作。简而言之:从其目录中选一幅图,在工作文件夹中编写 scene.json,使用 bun "<skill>/scripts/sketch/sketch.mjs" scene.json sketch.png 渲染,修复它报告的所有问题,然后在使用前亲自查看 PNG。

如果运行时没有 Bun,或只有较旧版本,请按照草图中的 npx --allow-scripts=bun [email protected] 方式渲染。如果该方式也失败,或运行时无法显示图片,则跳过草图。发布故事、“Not covered”行和详情块,并在回复中说明已跳过草图及原因。不要用 Mermaid 图或表格替代。

发布前检查每项声明

  1. 列出回顾中的每个事实句子和草图中的每个标签。
  2. 根据 diff 的代码块或 SHA 固定的行逐一核查。标记为已验证、已更正、不受支持或无法验证。
  3. 修正每项已更正的声明。删除每项不受支持或无法验证的声明,或将其改写为猜测。若标签有变化,重新渲染草图。
  4. 检查每个链接。将源代码链接固定到记录的 head SHA。Review 和 CI 链接必须指向 PR 上的记录,CI 运行必须对应于该 head。评论中绝不可包含机器人 review 的 URL,包括代码跨度中的 URL。回顾不会对 review 的发现进行分类,watch-pr 和 merge-gate 也绝不会将回顾视为已确认 review。
  5. 再次读取 headRefOid。如果它发生变化,请根据新的 diff 重新整理回顾。

将标记保留在笔记中,不要放进评论。在回复中报告计数。

发布或更新评论

将回顾写入同一工作文件夹中的 recap.md,即使跳过草图也要写入。包含草图时,图片行格式为 ![<alt text>](./sketch.png)。所有命令都从该文件夹运行。attachment.mjs 的路径为 <skill>/scripts/attachment.mjs。使用 bun 或 node 运行它。使用 --host 传入 PR 所属的主机。

评论会在起始标记后的下一行记录草图:``。下次刷新时会读取该记录;如果草图没有变化,则重用已上传的图片。不会记录评论 ID,因为评论无法保存自己的 ID。通过起始标记和作者查找你的回顾评论。

没有草图时,执行步骤 1,跳过步骤 2 和 3,并运行 gh api --hostname <host> -X PATCH "repos/<owner>/<repo>/issues/comments/<current>" -f body="$(cat recap.md)",将 recap.md 写入 current。如果没有现有评论,则运行 gh pr comment <n> -R <host>/<owner>/<repo> --body-file recap.md。从评论中取得 <keep>,然后转到步骤 4。

  1. 按时间从早到晚列出你的回顾评论。最后一条为 current。如果没有,则转到步骤 3。
me=$(gh api --hostname <host> user --jq .login)
gh api --hostname <host> --paginate "repos/<owner>/<repo>/issues/<n>/comments" \
	--jq ".[] | select(.user.login == \"$me\" and (.body | startswith(\"\"))) | .id"
gh api --hostname <host> "repos/<owner>/<repo>/issues/comments/<current>" --jq .body > old.md
  1. 重用已上传的图片。只有当 old.md 记录了此 sketch.png 的哈希时,reuse 才会输出记录的 URL。然后,stamp 会将该 URL 和新的记录写入新正文,再由 API 将其写入 current。不运行 attach。
url=$(bun "<skill>/scripts/attachment.mjs" reuse --host <host> sketch.png old.md) &&
bun "<skill>/scripts/attachment.mjs" stamp --host <host> sketch.png recap.md "$url" > body.md &&
gh api --hostname <host> -X PATCH "repos/<owner>/<repo>/issues/comments/<current>" -f body="$(cat body.md)"

将 <current> 作为 <keep>,然后转到步骤 4。如果 reuse 以状态码 1 退出,说明草图已更改或评论中没有记录,因此需要上传。

  1. 上传草图。先尝试一次 CLI:
gh pr comment <n> -R <host>/<owner>/<repo> --body-file recap.md --attach sketch.png

它会输出新评论的 URL。其中的 #issuecomment-<id> 即为 <keep>。使用 gh api --hostname <host> "repos/<owner>/<repo>/issues/comments/<keep>" --jq .body > new.md 将该评论正文读取到 new.md,运行 stamp --host <host> sketch.png new.md > body.md,再使用 body.md 对 <keep> 执行 PATCH。转到步骤 4。

如果 gh 拒绝上传,或没有 --attach,则 CLI 无法上传到此主机。将其归类为 CLI 限制即可,不要重复尝试。GHES 可能会拒绝上传,但这并不表示该仓库禁止附件。

  • 用户已授权手动上传。 向用户提供 sketch.png 的绝对路径。请他们将它拖入网页界面中 PR 的评论框,但不要提交,然后把出现的 URL、![...](...) 或 <img> 标记粘贴回来。将粘贴内容写入 paste.txt,然后运行此代码块:

    url=$(bun "<skill>/scripts/attachment.mjs" url --host <host> paste.txt) &&
    bun "<skill>/scripts/attachment.mjs" stamp --host <host> sketch.png recap.md "$url" > body.md
    

    url 接受这些标记形式,并输出纯 URL;对于其他主机或路径,则以状态码 1 退出。代码块的状态码 1 可能来自任一命令,因此请查看错误信息。no https://<host>/user-attachments/assets/<uuid> URL found 来自 url,表示粘贴的内容不是此主机上的附件。将其视为无法上传,不要猜测 URL,并采用未获授权的路径。no <host> attachment image in the body; pass the attachment URL to replace ./sketch.png 或 the body must start with 来自 stamp,表示 recap.md 存在编写错误。修正 recap.md,然后重新运行代码块。代码块以状态码 0 退出时,用 body.md 执行 PATCH,更新 current(<keep> 为 current);如果没有 current,则用 gh api --hostname <host> -X POST "repos/<owner>/<repo>/issues/<n>/comments" -f body="$(cat body.md)" 执行 POST,并将返回的 id 作为 <keep>。

  • 未获授权。 从 recap.md 中移除图片行。用该正文覆盖 current;如果没有 current,则发布该正文,并将其设为 <keep>。报告 upload unavailable: <the gh error>。

  1. 删除你发布的其他所有 recap,让 PR 只保留一个。
me=$(gh api --hostname <host> user --jq .login)
gh api --hostname <host> --paginate "repos/<owner>/<repo>/issues/<n>/comments" \
	--jq ".[] | select(.user.login == \"$me\" and (.body | startswith(\"\")) and .id != <keep>) | .id" |
	while read -r id; do gh api --hostname <host> -X DELETE "repos/<owner>/<repo>/issues/comments/$id"; done
  1. 检查已保存的评论,统计你的 recap 数量,然后确认图片是否正常显示。分别报告上传、已保存的评论和图片显示这三项结果。
me=$(gh api --hostname <host> user --jq .login)
gh api --hostname <host> --paginate "repos/<owner>/<repo>/issues/<n>/comments" \
	--jq ".[] | select(.user.login == \"$me\" and (.body | startswith(\"\"))) | .id" | grep -c .
gh api --hostname <host> "repos/<owner>/<repo>/issues/comments/<keep>" --jq .body > saved.md
bun "<skill>/scripts/attachment.mjs" check --host <host> --head <head SHA, 8 characters> saved.md
curl -s -o /dev/null -w '%{http_code} %{content_type}' -L -H "Authorization: Bearer $(gh auth token --hostname <host>)" "<url that check printed>"

check 会确认起始标记、结束标记、head SHA,以及此主机上的图片(两种形式均可)。如果存在记录,它会检查正文中的记录 URL 是否为图片 URL。它不要求必须有记录,也不验证记录的哈希值。阅读错误信息,确定哪项检查未通过。计数必须输出 1。如果输出其他数字,表示步骤 4 失败,请重新运行该步骤。获取操作必须输出 200 image/png。404 表示此请求无法获取该资源。重复使用的 URL 获取失败时,视为记录已失效,并从步骤 3 重新上传。未登录状态下的获取操作可能会在上传有效时失败,因此不能据此得出任何结论。没有草图时,使用 --no-image 运行 check;此时只检查标记和 head SHA,并跳过获取操作。

编辑器生成的 <img width=... alt=... src="..."> 标记可通过 url 和 check 的检查。编写 recap 时,使用 Markdown 图片形式,并采用代码块中的替代文本。stamp 会在其读取的正文中保留图片形式。将图片托管在仓库中或作为发行资源,不属于此技能的范围。

将其发布为 PR 评论,切勿放入 PR 正文。在由 no-mistakes 管控的仓库中,PR 正文由该门禁负责。

回复

  • 评论 URL 和 recap 所描述的 head SHA,或跳过说明。
  • 使用了哪幅目录绘图,或跳过草图的原因。
  • 声明核查的数量:已验证、已更正,以及作为猜测已删除或重写的数量。

CREDITS.md 列出了此技能改编自的来源。

评论

支持 Markdown