stack-on-pr
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseStack the frontier a PR unlocks
堆叠某个 PR 解除的 frontier
Turn the tickets an open PR unblocks into draft PRs stacked on that PR's branch, then hand each to Copilot — so work a still-open PR blocks can start now, against the contract that PR already defines (its API, its schema, its types).
This is with two deltas: the frontier is computed as if the PR were already merged, and each new PR is based on the PR's head branch instead of the default branch. The PR body shape and the Copilot handoff are unchanged — follow them live from .
delegate-frontier../delegate-frontier/SKILL.md将开放 PR 解除的工单转化为堆叠在该 PR 分支上的草稿 PR,然后交给 Copilot——这样,被仍开放 PR 阻塞的工作现在就能基于该 PR 已定义的契约(其 API、schema 和 types)启动。
这是 的变体,有两项调整:frontier 按该 PR 仿佛已经合并的情形计算,每个新 PR 都基于该 PR 的 head 分支,而不是默认分支。PR 正文结构和 Copilot 交接方式保持不变——实时遵循 。
delegate-frontier../delegate-frontier/SKILL.mdSteps
步骤
1. Resolve the tracker, the PR, and its spec
1. 解析 tracker、PR 及其 spec
The tracker is the upstream org repo from (not a personal fork). The PR is the user's argument (number or URL). Read the PR's to get the base ticket(s) it will close, that ticket's to get the spec, and the PR's head branch — the branch the new PRs stack on.
git remote -vCloses #<ticket>## ParentDone when: you have the tracker , the PR number and its head branch, the base ticket(s) the PR closes, and the spec issue number.
owner/repo工单系统(tracker)是从 获取的上游组织仓库(而不是个人 fork)。PR 是用户参数(编号或 URL)。读取 PR 的 ,获取它将关闭的基础工单;读取该工单的 以获取 spec;并读取 PR 的 head 分支——新 PR 将堆叠其上的分支。
git remote -vCloses #<ticket>## Parent完成条件: 已获取 tracker 的 、PR 编号及其 head 分支、PR 将关闭的基础工单,以及 spec issue 编号。
owner/repo2. Compute the frontier the PR unlocks
2. 计算 PR 解除的 frontier
Over the spec's open tickets, compute the frontier exactly as step 2 does — but count the PR's base ticket(s) as already closed. The result is the tickets that only this PR still blocks. Drop any ticket that already has an open PR that it — whether that PR is stacked on this PR's head branch or targets the default branch — so a re-run never re-opens one.
delegate-frontierClosesDone when: you have the tickets unblocked solely by this PR and with no existing open PR that them, and can name why every excluded ticket was held — another open blocker, or an existing PR.
Closes按照 步骤 2 完全相同的方式,对 spec 中的开放工单计算 frontier——但将 PR 的基础工单视为已经关闭。结果应是仅由此 PR 解除阻塞的工单。丢弃任何已有开放 PR 通过 关闭的工单——无论该 PR 是堆叠在此 PR 的 head 分支上,还是以默认分支为目标——从而确保重新运行时不会重复创建。
delegate-frontierCloses完成条件: 已获取仅由此 PR 解除阻塞且不存在已有开放 PR 通过 关闭的工单,并能说明每个被排除工单被暂缓处理的原因——另一个仍开放的 blocker,或已有 PR。
Closes3. Open a draft PR per ticket, stacked on the PR
3. 为每个工单打开堆叠草稿 PR
For each unlocked ticket, first re-check that no open PR already it (guarding against a re-run or a PR opened since step 2); if one exists, skip the ticket. Otherwise open a draft PR exactly as step 3 — same repo-convention title, template body, and labels — with one change: branch off the PR's head branch and set the new PR's base to that head branch. The PR then stacks and shows only its incremental diff on top of the base PR.
Closesdelegate-frontierDone when: every unlocked ticket has exactly one labelled draft PR based on the PR's head branch, its title passing the repo's convention, body linking with acceptance criteria and every required template section — and no ticket that already had a PR got a second one.
Closes #<ticket>对于每个已解除阻塞的工单,先重新检查是否已有开放 PR 通过 关闭它(防止重新运行,或防止步骤 2 之后新打开了 PR);如果存在,则跳过该工单。否则,完全按照 步骤 3 打开草稿 PR——使用相同的仓库约定标题、模板正文和 labels——仅做一处调整:从 PR 的 head 分支切出分支,并将新 PR 的 base 设置为该 head 分支。这样,PR 就形成堆叠,并且相对于基础 PR 仅显示其增量 diff。
Closesdelegate-frontier完成条件: 每个已解除阻塞的工单都恰好对应一个带 labels 的草稿 PR,基于该 PR 的 head 分支;其标题符合仓库约定,正文链接 并包含验收标准和所有必需的模板章节;任何已有 PR 的工单都不会获得第二个 PR。
Closes #<ticket>4. Hand each PR to Copilot
4. 将每个 PR 交给 Copilot
Exactly as step 4.
delegate-frontierDone when: every stacked PR carries one comment per step 4.
@copilotdelegate-frontier完全按照 步骤 4 执行。
delegate-frontier完成条件: 每个堆叠 PR 都按照 步骤 4 包含一条 评论。
delegate-frontier@copilotReference
参考
Frontier-on-merge. The pick is 's frontier rule with the PR's base ticket(s) forced closed: a downstream ticket qualifies when every issue is closed once the PR's ticket is counted as closed. Any ticket with another still-open blocker waits for a later run.
delegate-frontier## Blocked byStacking base. The new PR's base is the PR's head branch, not the default branch. When the base PR merges and its branch is deleted, GitHub auto-retargets the stacked PR to the base PR's base (the default branch) and its diff settles to the ticket's own changes; rebase the stacked branch afterward if the retarget leaves conflicts.
Idempotent re-runs. The dedup key is an open PR that , checked both when computing the frontier (step 2) and again immediately before opening (step 3). Re-running the skill on the same PR therefore only fills gaps — tickets that still have no PR — and never opens a second PR for a ticket already delegated.
Closes #<ticket>合并时的 frontier。 采用 的 frontier 规则,并强制将 PR 的基础工单视为已关闭:当 PR 的工单被计为已关闭后,下游工单的每个 issue 都已关闭时,该下游工单才符合条件。任何仍有另一个开放 blocker 的工单都要等待后续运行。
delegate-frontier## Blocked by堆叠基分支。 新 PR 的 base 是 PR 的 head 分支,而不是默认分支。当基础 PR 合并且其分支被删除时,GitHub 会自动将堆叠 PR 的目标重新指向基础 PR 的 base(默认分支),其 diff 最终只剩该工单自身的变更;如果重新定向后出现冲突,请 rebase 堆叠分支。
幂等重新运行。 去重键是开放 PR 是否通过 关闭工单;计算 frontier(步骤 2)时检查一次,打开 PR 前(步骤 3)再立即检查一次。因此,对同一个 PR 重新运行此 skill 时,只会填补空缺——仅为尚无 PR 的工单创建 PR——绝不会为已经委派的工单打开第二个 PR。
Closes #<ticket>