Skip to content

Release PR fails to inherit Closes #N keywords from constituent PRs (Submitted from external project) #186

Description

@sebastientaggart

Summary

When /deploy creates the release PR (dev → main), it does not reliably propagate the Closes #N keywords from the constituent PRs into the release PR's own body. Issues
that were Closes-marked in a dev-target PR stay open after the release ships, because GitHub's closing-keyword parser scans only the merging PR's body — not the bodies
of intermediate dev-target PRs. This is compounded by another problem: PR-authoring agents sometimes write Issue #N (a plain link) when they mean Closes #N, and /deploy
has no way to recover the intent at release time.

Repro

  1. Branch off dev → write a fix → open PR with body containing Closes Add shields.io badges and MIT LICENSE file #123 → merge to dev. GitHub does not auto-close Add shields.io badges and MIT LICENSE file #123 (it auto-closes only on default-branch
    merges). This is expected GitHub behavior, not the bug — context for the next step.
  2. Repeat for several issues over weeks.
  3. Run /deploy. The release PR is created targeting main with a Closes #N block.
  4. After the release PR merges, observe that some issues whose constituent PRs did say Closes #N are still open.

Root cause (two compounding)

  1. /deploy Step 2 extracts both Closes #N and Issue #N from constituent PR bodies but appears to merge them into a single linked-issues set used for display, then writes
    the release PR body without distinguishing which were close-intent vs. reference-intent. The release PR's auto-close set is incomplete as a result.
  2. PR-authoring (/start and /submit-for-review) doesn't enforce which closing form to use. Issue #N is just a link — it does not trigger auto-close at any merge target.
    So even if /deploy fixed the propagation, the constituent PRs with Issue #N bodies still wouldn't auto-close. There's no semantic distinction in the data being read.

What good looks like

  • /start and /submit-for-review should require Closes #N (not Issue #N, not Fixes #N-style alternates) when a PR fully resolves a ticket, and instruct the author to
    write Related to #N (not auto-closing) for context-only references. The distinction is editorial but the skill can enforce it.
  • /deploy Step 2 should parse Closes #N separately from Issue #N / Related to #N, and the release PR body should reproduce the exact Closes #N lines from every
    constituent PR — verbatim. Anything that's Closes-tagged in a constituent must appear Closes-tagged in the release PR. Step 5's HUMAN GATE should display this
    explicitly: "Issues that will close on merge: #A, #B, #C" vs "Issues referenced but not closing: #X, #Y" so the operator can spot a missing close at gate time.

Concrete evidence from this deploy (v0.12.0)

Four issues had their fixing PR shipped in v0.12.0 but were not auto-closed by the release PR (#326) because the release PR body did not include Closes #N for them:

┌───────┬────────────────┬───────────────────────────────────────────────────────────────────────────────────────────────┐
│ Issue │ Constituent PR │ What its body said │
├───────┼────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────┤
│ #319 │ #321 │ Issue #319 (link only — no close intent recoverable) │
├───────┼────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────┤
│ #317 │ #320 │ Issue #317 (same) │
├───────┼────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────┤
│ #269 │ #272 │ Issue #269 (same) │
├───────┼────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────┤
│ #271 │ #286 │ Closes #271 (close intent was present in constituent body but dropped at release-PR assembly) │
└───────┴────────────────┴───────────────────────────────────────────────────────────────────────────────────────────────┘

Three more (#223, #232, #253) shipped in earlier releases without ever being closed — the same bug, accumulated over time. After v0.12.0 merged, the operator audited and
closed all seven manually.

Severity

Medium. No data loss, but the backlog drifts further from reality every release. Operators discovering it after the fact (as here) is expensive: each missed issue
requires verifying which PR closed it, which release shipped it, then writing a close comment.

Workaround until fixed

In the /deploy Step 5 HUMAN GATE, the operator should ask: "Show me every PR's Closes #N lines as a single list, and confirm they all appear in the release PR body's
Closes block." This is what the skill should be doing automatically.

Metadata

Metadata

Assignees

No one assigned

    Labels

    ready-for-qaIssue is ready to be QA tested

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions