关于 file-pr
file-pr 是用于准备和发布拉取请求的开发技能,会检查分支、就绪证据、已验证变更和发布信息。它还指导标题与正文撰写、冷读审查,以及创建或复用 PR。
主要功能
- 01校验分支与就绪卡
- 02复核基础版本和已验证差异
- 03撰写以结果为中心的标题与正文
- 04按七项标准冷读审查
- 05提交并发布或复用 PR
适用场景
- 01将已验证变更发布为 PR
- 02根据就绪卡更新现有 PR
- 03为 UI 或 API 变更准备 PR 证据
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ bhagyamudgal/ skills --skill file-pr安装后在 Claude Code 中输入/file-pr确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/existing-pr-reuse.mdfork-creation-lanes.mdupstream-binding.md详细介绍
提交拉取请求
PR 的读者可能没有看过会话、差异或工单。以下每一项要求都是为了让读者一次就能理解这项更改。
1. 检查前置条件
阅读分支和当前的 done 就绪卡片。
- 分支。
git rev-parse --abbrev-ref HEAD必须与卡片中的 Branch 完全一致,并符合CLAUDE.md中的分支命名规则。重命名或切换分支会使卡片过期,并返回done。 - 就绪卡片。 必须有
done定义的当前 Git 卡片,其中包含 request、currency、coverage、lane、evidence、verdict 和 next-action 字段。其 verdict 必须为ready-to-publish,且 next action 必须准确指定此技能。缺少字段或 verdict 不同,都要返回done。不要在此处重建卡片。 - 发布模式。 根据用户的发布请求确定预期 PR 状态和草稿模式。若请求未指定以草稿形式发布,则使用
OPEN和isDraft: false。
只有分支、卡片是否存在、预期状态和草稿模式都记录了结果,才满足此门槛;任何一项失败都必须停止 PR。
2. 验证基准并确定问题链接
使用 done 已确定的 PR 基准 ref 和确切基准远程。使用卡片中的确切命令刷新已记录的 <base-remote> ref,然后要求其远程名称、ref 名称、远程基准 tip SHA 和 merge-base SHA 均匹配。硬编码或替换远程会使卡片过期。其他基准状态或选择都必须返回 done,因为这会改变已验证的差异。
只选择一个问题链接:
- 差异完全解决了该问题:
Closes #N - 解决了部分问题、总工单下的子任务,或 Epic 中的一个部分:
Refs #N,并用一行说明覆盖了哪一部分,以及哪些内容仍未解决 - 调查某个问题时发现了此项更改,但并未修复该问题:
Refs #N,并在正文中说明
如果此差异没有彻底解决某个问题,绝不要使用 Closes。
只有基准 ref、远程基准 tip 和 merge base 与刷新后的远程状态一致,且问题链接来自问题输出而非假设,才满足此门槛。
重新验证卡片时效性和交接资格
重新计算卡片,不要只相信其标签:
- 当前请求范围与 Originating request 匹配;
- 当前分支与 Branch 完全一致;
- 刷新后的基准 ref、tip 和 merge base 与 PR base ref、Remote base-tip commit 和 Merge-base commit 匹配;
- 对每个混合外部目标进行新的权威回读,其目标、版本和字段都与记录的内容匹配;并且
- 卡片符合
done的ready-to-publish规则。
在验证范围之前,执行 done 的备用索引构建,并运行 git write-tree。清理之前,运行候选差异:
GIT_INDEX_FILE="$snapshot_index" git diff --cached --no-ext-diff <merge-base> --
要求快照与 Verified content snapshot 匹配。将每个已更改的代码块或逻辑变更归入一个已验证的请求行。任何不属于这些行的内容,都属于 CLAUDE.md 中要求停止并询问的情况。然后执行 done 的索引清理。
对于 Existing PR URL 为 not-applicable 的首次发布卡片,要求 HEAD 与 Pre-verification head 相同,且 Expected append-only commits 为 none。对于替代现有 PR 的卡片,要求 done 中记录的仅追加变更和提交后的内容密封与当前 HEAD 及 Verified content snapshot 匹配。禁止其他提交。请求、基准、意外的 head 或内容快照发生变化,都会使卡片过期。任何不匹配都必须返回 done。
只有重新计算的请求、分支、基准 ref 和 SHA、head、快照、外部时效性、候选差异以及 ready-to-publish verdict 全部与卡片匹配,才满足此门槛。
3. 编写标题
格式:<type>(<module>): <description>。模块名称应采用其在看板上的写法,而不是目录中的拼写。
描述应说明用户能观察到什么:出了什么问题,或者现在可以做什么,而不是你修改了什么。
以下词语不能单独作为完整描述:improve、update、handle、refactor、fix logic、clean up、various fixes。
| 机制:重写 | 结果:交付 |
|---|---|
fix(portions): correct filter logic | fix(portions): portion totals skipped orders placed after cutoff |
feat(auth): update session handling | feat(auth): stay signed in across browser restarts |
在标题中指出是谁观察到这个现象。如果唯一诚实的答案是“阅读差异的人”,那标题写的就是一种机制,应当重写。
验收标准是:标题中明确指出观察者,且没有禁用词单独作为描述。
4. 撰写正文
先用两到四句话的普通文字说明问题所在,然后说明做了哪些改动。文字要让从未查看过差异的人也能看懂。上方不得有标题,绝不能使用项目符号列表,也不能省略。
然后只包含有实际内容的章节:
- 改动内容。 根据每一条已核实的请求记录,提炼一条以结果为重点的项目符号。不得根据差异推断新增内容。
- 改动前后及 QA 测试结果。 如果改动会改变 UI 或 API 行为,卡片的 Browser 维度会从
browser-qa中指定.qa/pr-evidence.md。在此逐字粘贴该文件,但如果缺少推送权限且用户首次选择不发布嵌入行,则不粘贴这些行。其 SHA-256 必须与记录的摘要一致;如果缺少片段或摘要不一致,则返回done;如果冷读检查未通过片段中所述的门槛,也要返回done,并在返回原因中说明,因为done会通过browser-qa重新生成该文件。 - 验证方法。 只能根据证据索引中的准确观察结果推导。包含适用的
not-applicable原因,不得编造证据。如果 PR 没有该片段,则在此用一行说明为何不适用浏览器 QA,例如No UI or API behavior changed, so there is no browser QA. - 风险或范围说明。 仅当确实存在不确定事项、迁移事项或有意延期事项时添加。
- 第 2 节中的问题链接。
附件列表是片段中代码块之外每个  嵌入文件的目标,按其在片段中出现的顺序排列,每个文件只列一次;且每个文件的 SHA-256 必须与 Browser 维度记录的摘要一致。没有片段的 PR 不附加任何文件。数据审批涵盖整个片段,包括文本和文件:只有当其中包含合成或脱敏数据,或用户明确批准发布时,才能粘贴和附加。未获批准时,停止所有推送、创建或编辑正文等副作用,并请用户批准列出的文件和文本,或返回 done,以便基于合成数据重新生成。附加文件要求 gh v2.99.0 或更高版本;在进行任何推送或创建操作前,使用 gh --version 确认版本要求。如果安装版本较旧,则返回 done 并升级 gh,不要在缺少证据的情况下发布 UI 或 API PR。只有用户明确决定后,才能不附加文件直接发布;随后升级 gh,并通过第 6 节的 gh pr edit --attach 步骤上传片段中的文件;在这些文件上传前,done 会将 Browser 状态设为 deferred。
上传还需要对基础仓库具有推送权限。如果附件列表非空,则像第 6 节一样,通过卡片的基础远程仓库使用 gh repo view --json nameWithOwner 解析基础仓库,然后在进行任何推送、创建或编辑正文等副作用前,读取 gh api repos/<nameWithOwner> --jq .permissions.push。如果结果不是 true,则此账户无法通过上传替换正文中的本地路径,因此应在产生任何副作用前停止,并请用户选择:
- 不附加文件发布。 从正文中移除片段里的嵌入行;所有通道的冻结附件列表均为空;将被省略的路径及其摘要写入发布证据。
done会将 Browser 状态设为deferred。 - 交由有推送权限的人处理。 返回
done,将 Browser 状态设为blocked,并列出发布所需的.qa/文件及其摘要。
如果 gh 版本过旧且同时缺少推送权限,则以此处的选择为准。
没有内容的标题应删除。小型 PR 的正文包括开篇段落、验证方法和链接。不要将内部就绪情况表粘贴到 PR 正文中。
CLAUDE.md 中由人工编写的规则决定正文的语气,并禁止提及 Agent、流水线和会话。
验收标准是:开篇段落无需查看差异也能独立表达完整意思,且每个保留的标题下都有内容。
5. 冷读结果
以不了解会话上下文的读者身份,通读组合后的标题和正文。为每项标准写出结论:
- 标题。 谁会看到它。
- 导语。 说明出了什么问题、发生了什么变化,不提差异内容。
- 术语。 每个文件、标志或术语都在首次出现时作出介绍。
- 交叉引用。 不使用“如前所述”“以上内容”“之前的问题”之类的表述。
- 验证。 描述实际运行了什么,而不是描述应该能正常工作的内容。
- 语气。 不使用套话、不使用 em dash 或 en dash,也不提 Agent 或会话。
- 依据。 UI 或 API 变更附上相关片段;其他 PR 附上一句话说明原因。
没有写明结论的标准,就是没有检查的标准。改写未通过的标准,并重新通读。绝不要把未通过的标准作为已知例外提交。
通过条件是七项标准都有明确结论,且没有任何一项未通过。
6. 提交并创建 PR
通过经过身份验证的 gh repo view ... --json id,nameWithOwner 解析 $repository,并将其记录为基础仓库。有效的远程仓库必须在 git remote get-url --all <remote> 和 git remote get-url --push --all <remote> 中具有完整且顺序一致的拉取和推送端点集合;这些端点经过去除凭据的规范化后,都必须能通过经过身份验证的 gh repo view ... --json id,nameWithOwner 解析到同一个仓库 ID 和 nameWithOwner。即使端点可以解析,只要其协议不是 HTTPS 或 SSH,就无效,因为凭据会以明文方式通过网络传输。如果解析时发生重定向,最终主机、所有者和仓库必须与预期目标一致,否则远程仓库无效。如果推送输出提到重定向,则以同样方式解析该最终 URL,并要求其使用 HTTPS,且主机、所有者和仓库均与预期目标一致,然后才能记录推送已完成。只保留有序的规范化集合或其摘要以及解析出的 ID,绝不保留凭据。
如果存在 Existing PR URL,则跳过提交、推送和创建操作,并在枚举远程仓库之前加载 ${CLAUDE_SKILL_DIR}/references/existing-pr-reuse.md。其中包含对该分支现有 URL 执行的 gh pr view 读取、通过头部身份匹配远程仓库时针对多个匹配和零个匹配的处理方式、冻结、重新验证和协调要求、无需再次推送即可提供远程头部证据的内容,以及下文中的分页候选搜索在出现后续替代卡片时对标题或正文编辑的处理方式。
如果没有 Existing PR URL,则在选择远程仓库之前检查当前分支配置的上游。只有当上游配置完整、可解析,且其分支引用与发布分支匹配时,才选择其指定的远程仓库,并且该远程仓库必须有效。如果配置的上游格式错误、不完整或无法解析,则状态为 reconcile-required。如果明确不存在上游,则枚举有效的远程仓库:只有一个时自动选择;有多个时,使用 AskUserQuestion 提供具体的 <remote>: <nameWithOwner> (<id>) 选项,并进行分页;如有需要,将选项分页为互不重叠的集合;如果没有,则停止并提示:Configure one valid publication remote or bind the branch upstream, then rerun file-pr.。选定的有效远程仓库会确定头部仓库身份和 <head-owner>。它可以与基础仓库相同,也可以不同。
将选定远程仓库完整且有序的端点集合,以及基础仓库和头部仓库的独立身份记录为保护条件和失效条件。在每次推送和权威回读之前立即重新枚举。如果集合中有任何新增、移除、顺序变化、解析失败或头部仓库不匹配,则状态为 reconcile-required。仅当指定远程仓库的完整推送集合仍与冻结记录一致时,才能向其推送。
对于首次发布,请在执行 git-commit 之前立即,或在无需提交时于推送之前,重复第 1–2 节中的分支、HEAD、刷新后的基础引用及 SHA、混合外部回读和备用索引快照检查。仅当快照未变时,才可复用已完成的区块核算。快照发生变化时,返回 done。当已验证快照与 HEAD^{tree} 不同时,以密封索引模式对已验证的请求行调用 git-commit:传入 Verified content snapshot,要求暂存树与其一致,并禁止在提交前再次暂存。记录它创建的每个 SHA。运行 done 定义的只追加转换命令。其祖先关系、合并和精确有序列表标准都必须通过。发生变基、合并或未记录的提交时,返回 done。将精确有序列表添加到随卡片返回的发布证据中的 Expected append-only commits。
对于首次发布,在推送前,要求活动分支仍与 Branch 一致,重新获取每个混合外部目标,并要求其时效性仍然匹配。然后运行 done 的提交后内容封存。记录 git status --porcelain=v1 --untracked-files=all 和 git rev-parse HEAD^{tree} 的精确输出。状态输出必须为空,且树 SHA 必须与 Verified content snapshot 完全一致。否则返回 done。
对于首次发布,仅当 git symbolic-ref --quiet HEAD 等于 refs/heads/<card-branch>,且该分支引用与 HEAD 解析到同一 SHA 后,才冻结 push-attempt SHA。查询精确的远程引用,并要求返回一个 SHA 或权威确认不存在。若存在,要求该 SHA 是 push-attempt SHA 的祖先。推送前立即使用一张内联的单项卡片调用 preflight-mutations。其操作是将 push-attempt SHA 推送到精确引用。其防护条件和失效条件包括活动符号引用、分支引用 SHA、HEAD SHA、所选远程名称、完整且有序的获取与推送端点集合及仓库 ID、分别记录的基础仓库和头部仓库 ID、精确的远程 SHA 或不存在状态,以及混合外部时效性。其回读是下方精确的 git ls-remote 查询。全局规则下获准的 file-pr 调用是授权来源。独立应用结果:仅当结果为 ready 且每项失效条件都匹配时才继续;若为 confirmation-required,则呈现确认要求;若为 blocked,则停止。紧邻命令执行前,重新读取活动符号引用、分支引用、HEAD 和所选远程身份。任何变动都会使此次尝试失效。
git push --force-with-lease="refs/heads/<card-branch>:<expected-remote-sha-or-empty>" "<push-remote>" "<push-attempt-sha>:refs/heads/<card-branch>"
git ls-remote --heads "<push-remote>" "refs/heads/<card-branch>"
每次推送尝试后(包括命令结果非零或含糊不清的情况),重新检查所选远程身份,并运行一次精确的 git ls-remote 回读。仅当该权威 SHA 与 push-attempt SHA 相等时,才记录 landed-push SHA。若 SHA 过时或意外、无法回读,或远程身份发生变化,则状态为 reconcile-required:停止发布,绝不可仅凭推送命令结果重试。
首次发布时,根据冻结的尝试重新检查活动符号引用、分支引用 SHA 和 HEAD。即使远程回读成功,本地变动也会使后续发布失效。然后加载 ${CLAUDE_SKILL_DIR}/references/upstream-binding.md。仅在首次发布分支中到达此步骤;该文件包含用于解析分支上游状态的两个 git config 探测、ABSENT、reconcile-required 和权威无操作分类、带回读的受保护绑定命令,以及推送成功后绑定失败时的 remote landed / upstream not bound 处置方式。
将最终正文写入文件,并记录其 SHA-256 摘要。在判断是否存在早先的尝试之前,通过权威分页 REST 查询获取基础仓库中的所有 PR:
gh api --paginate --slurp "repos/$repository/pulls?state=all&per_page=100"
要求每个页面都成功返回并完成解析。任何页面出错、无法继续获取或分页不完整,都属于 reconcile-required。在本地按精确条件 head.repo.id == <selected-head-repository-id> 和 head.ref == <head-branch> 筛选完整结果,然后将保留的记录映射到现有候选字段:根据 merged_at 是否为非空值推导 MERGED,否则保留 OPEN 或 CLOSED。
若没有 Existing PR URL,重新检查活动符号引用、分支引用 SHA 和 HEAD 是否与 landed-push SHA 一致,然后针对所有保留候选(包括所有状态)进行协调。任何 OPEN 候选的 head SHA 错误,或存在多个开放候选,都属于 reconcile-required,并且必须停止创建。一个有效的开放候选要么符合所请求的 base、状态和草稿模式,要么进入明确的 base-rebind 或发布决策流程。记录其 URL,并返回 done,以便在进行任何编辑前将其绑定。head SHA 不同的 CLOSED 或 MERGED 候选属于历史记录,不会阻止分支复用。位于 landed-push SHA 的已关闭或已合并候选需要明确决定重新打开、创建新分支或不发布。只有当完整的所有状态结果中既没有开放候选,也没有当前尝试对应的已关闭或已合并候选时,才可创建。如果创建尝试未返回可用 URL,则使用相同的完整分页查询和精确的本地筛选。
必须通过权威仓库元数据确认所选 head 是 base 仓库,或属于其 fork 网络。无关的 head 会阻止创建。在预检前冻结一条创建路径:同仓库 head 使用 gh pr create --head <branch>。当所选 head 仓库不是 base 仓库时,冻结路径前先加载 ${CLAUDE_SKILL_DIR}/references/fork-creation-lanes.md。其中包含由已认证用户拥有和由组织拥有的 fork 路径、基于稳定 ID 的所有者类型和所有权判定(其他任何关系都会因此受阻),以及 REST head_repo 创建表单。创建 PR 前立即调用 preflight-mutations,并传入一个新的内联单项卡片。其目标是精确的 base 仓库和所选 head 仓库。操作记录冻结的创建路径、base、head 仓库和分支、landed-push SHA、标题、正文路径和摘要、附件列表及其数据审批,以及冻结时每个路径的 SHA-256 摘要和字节大小,并记录预期的 OPEN 状态和预期草稿模式。其守卫条件包括两端完整的端点集合及其仓库 ID、分别记录的 base 和 head 仓库 ID、活动符号引用、仍指向 landed-push SHA 的分支引用 SHA 和 HEAD、已验证的远程分支、记录的 base tip、完整的分页候选结果及精确筛选条件,以及已确认不存在开放候选或 head SHA 相同的当前尝试。其回读内容是下方的精确 gh pr view 查询。按相同的结果契约独立应用此结果。若本地引用、HEAD、端点集合、base 或 head 身份、创建路径、标题、正文路径、摘要、附件列表、审批、任何附件文件的摘要或大小、状态或草稿模式发生变化,卡片即失效。PR 卡片未就绪不会抹除已落地推送的证据。
当绑定的草稿模式为 isDraft: true 时,才在创建命令中追加 --draft。
同一仓库:
gh pr create --repo "$repository" --base "$base" --head "$head_branch" --title "$title" --body-file "$body_path" [--attach "<attach-list path>" ...] [--draft]
--attach 会将每个文件(包括 WebM)上传到 GitHub,每条命令最多 50 个。它会将正文中所有解析到与参数所指相同绝对路径的引用替换为该文件的 URL,因此应在仓库根目录运行,此时片段中的路径是相对路径。Free 计划的视频上限为 10 MB,付费计划为 100 MB;通常无法读取计划类型,因此除非用户确认使用付费计划,否则按 10 MB 上限处理。使用 --attach 创建前,立即重新计算附件列表中每个文件的 SHA-256 摘要和字节大小,要求与冻结卡片中的值一致,并确认每个视频都未超过上限。视频超限时返回 done。
使用下面的十字段查询,逐一原样读回每个通道。此列表是唯一权威来源;references/existing-pr-reuse.md 和 references/fork-creation-lanes.md 引用此列表,不得重复陈述:
gh pr view <pr-url> --repo "$repository" --json url,title,body,baseRefName,baseRefOid,headRefName,headRefOid,headRepository,state,isDraft
只能执行已冻结的通道。结果含糊时,不得将其他示例作为备用方案。
要求 PR 的 title 与冻结值完全一致。未附加任何文件时,要求 body 与冻结正文完全一致。附加了文件时,要求冻结正文中的每个附加列表引用都改写为 https://github.com/user-attachments/assets/ URL,除此之外不得有任何改动:图片保留 ,只替换路径;单独位于段落中的视频嵌入则改为纯 URL。任何协调过程中都要保留这些 URL,不得将正文改回冻结时的字节内容。上传失败时,gh 仍会创建 PR 并以非零状态退出。待上传的路径恰好是那些在读回正文中仍保留本地嵌入的附加列表路径。对每个路径,通过预检后的 gh pr edit <pr-url> --attach <path> 上传一次,以相同方式读回正文,且绝不再次创建。仍然失败的路径标记为 reconcile-required。要求 headRepository.id 等于选定的 head 仓库 ID,headRefName 等于 Branch,headRefOid 等于 landed-push SHA,baseRefOid 等于 Remote base-tip commit。要求其 URL、base 名称、state 和 isDraft 与发布请求一致。在确认发布前,重新核对当前符号引用、分支引用 SHA 和 HEAD 是否都与 landed-push SHA 一致。一旦权威确认了某个 PR,立即将其 URL 记录为 landed。若只有标题或正文不同,而仓库、base、head、状态和草稿模式仍然匹配,则对该现有 PR 预检并执行精确编辑,然后读回确认。base 不匹配时,携带该 URL 及其观测值,进入 done 现有 PR 重新绑定流程。绝不再次创建。状态或草稿模式不匹配时,停止并请求明确的发布决定。绝不静默地重新打开、关闭、转换或创建另一个 PR。将两个单步卡片、已落地的推送、PR 观测结果、按顺序排列的提交列表以及确切命令记录为发布证据,供下一次 done 运行使用。如果无法通过权威搜索确认是否已创建 PR,则将创建操作标记为 reconcile-required,且不得重试。
打印 URL 并返回 done,以进行 CI、审查、发布通道和最终行评估。绝不合并。打开 PR 是一次发布转换,不代表整个任务已完成。
只有在前置条件均满足、base 最新状态和 issue 链接均来自真实输出、标题和正文通过冷读、远程分支与 PR 均符合本地发布状态,且证据已交回 done 并未声称整体完成时,交接才算完成。