diff --git a/skills/opening-a-pull-request/SKILL.md b/skills/opening-a-pull-request/SKILL.md index 07dc04d..95058f9 100644 --- a/skills/opening-a-pull-request/SKILL.md +++ b/skills/opening-a-pull-request/SKILL.md @@ -47,6 +47,7 @@ Which keyword belongs depends on **which branch the PR targets**: - **PR targets `main` (the default branch)** — use `Fixes` / `Closes` if the merge should close the issue; use `Towards` if the issue should stay open. This includes sub-PRs in the `sub_pr_target: main` model (see `feature-dev-workflow:fanning-out-with-worktrees`): each sub-PR targets main directly with the type-appropriate closing keyword (`Fixes #` for a bug sub-issue, `Closes #` otherwise); the epic is closed manually by the orchestrator after all sub-PRs merge. - **PR targets a feature branch** (`feature/` in the multi-PR feature-branch model — see `feature-dev-workflow:developing-a-feature`) — use `Towards #`. `Fixes` / `Closes` keywords only auto-trigger on merges to the default branch, so writing them on a feature-branch-bound PR creates a misleading promise that nothing will fulfill. The sub-issue is closed manually by the orchestrator after the self-merge. The integration PR (feature → main) gets `Closes #` because that PR does merge to main. +- **PR temporarily targets a sibling branch and will be retargeted to `main`** (stacked sub-PRs in the `sub_pr_target: main` model: each draft opens against its parent branch so its diff shows only its own commits, then retargets to `main` when the parent merges) — use the type-appropriate closing keyword (`Fixes #` for a bug sub-issue, `Closes #` otherwise) from the start. It describes the merge that will eventually happen on `main`, and it survives the retarget with no body edit; a `Towards` placed "because the base isn't main yet" has to be remembered and upgraded at every retarget, and a forgotten upgrade means the sub-issue never auto-closes. Know what the keyword does NOT do while the base is a sibling branch: GitHub only creates the issue's linked-PR association (and only auto-closes) for closing keywords on default-branch-base PRs, so until the retarget the sub-issue shows a plain timeline mention and **no linked PR** — deferred, not broken. At each retarget, verify the linkage materialized (`gh pr view --json closingIssuesReferences` lists the sub-issue); if it stays empty, re-save the body so GitHub re-evaluates the keyword against the new base. If there is no tracking issue, drop the line entirely and open the section with prose. @@ -104,5 +105,6 @@ These thoughts mean the PR isn't actually ready to publish or flip: | "The user said yes a turn ago, this is the same thing" | Bodies change between turns. Confirm the exact body about to land. | | "I'll just append a note and they can edit later if needed" | They shouldn't have to clean up after the agent. Confirm first. | | "The PR's already open/ready, the stale body isn't worth re-editing" | The body is what the reviewer reads first; once the diff moves past it, it misleads. Reconcile the body to match the diff — body only, no comment (§Reconciling an open PR's body with reality). | +| "The sub-issue shows no linked PR, the keyword must be wrong" | Closing-keyword linkage only materializes while the PR's base is the default branch. On a stacked draft it's deferred until retarget — verify with `gh pr view --json closingIssuesReferences` then, not before. | All of these mean: rewrite the body from the right template, paste it inline in chat, and wait for an explicit yes.