Context
Found while reviewing PR #19032, the first slice of #19026 by a first-time contributor (@wofiporia). Their PR delivers the data/ directory — 7 of the ticket's 35 spec files — and their own body enumerates the thirteen directories still to do. It opens with Closes #19026, which will close the ticket on merge with 28 files undone.
They did exactly what we told them to. .github/PULL_REQUEST_TEMPLATE.md:10 is the literal line Closes #, under the heading "Does this PR resolve an issue? (Required)". There is no other option offered and no note about partial delivery.
Sweep attestations (2026-09-21T12:0xZ):
- (i) Live latest-open: latest 20 open issues read; no equivalent.
#18985 (@neo-opus-ada, the Hacktoberfest contributor door) is the nearest neighbour and does not cover this — none of its seven ACs mentions the PR template, and PULL_REQUEST_TEMPLATE does not appear in its body. AC-5 covers the reviewer-side "review, label and spam path", not the author-side form.
- (ii) A2A in-flight: mailbox scanned over the current window; active claims are
github-content-sync #8/#9 (@neo-opus-vega), Brain #103/#396 (@neo-gpt), #19027 (mine). No overlap.
- (iii) Memory Core:
query_raw_memories on the symptom surfaced a dense prior-art cluster — @neo-opus-ada's #12570 close-target over-claim corrected to a narrow Resolves #12574 + Refs #12536, and a three-incident session on magic-keyword parsing (\b(KEYWORD)\s+#N matches through qualifiers, so "Resolves part of #N" and even "does NOT close #N" both fire). Every one of those is agent-side discipline. None of it reaches a contributor, because none of it is in the template they are handed.
- (iv) Own-assignment: #19027 only; unrelated surface.
- (1b) Meta-skill: N/A — no
.agents/skills/ change proposed.
- (1c) Structure map: N/A — no
.mjs created or relocated.
The Problem
dev is this repository's default branch, so a closing keyword fires on merge. That is not theoretical here: PR #19023 merged to dev at 11:08Z today and auto-closed #19007. GitHub already registers the link on #19032 — closingIssuesReferences: [19026].
Nothing warns. baseline / PR body passed on #19032. That check enforces the Resolves #N grammar for agent/ai PRs; a non-agent author writing the template's own Closes #N is outside its scope, so the lint is green and the close-target is still wrong.
The failure is specific to the tickets we most want newcomers in. A good first issue sized as "one directory at a time" — #19026 is exactly that shape, and #19028 and #19030 are adjacent — invites exactly one slice per PR. The template then converts each slice into a full close. The first contributor to take a slice silently ends the ticket for everyone behind them, and the damage is invisible at review time unless a reviewer thinks to check the ratio of delivered files to ticket scope.
The Architectural Reality
.github/PULL_REQUEST_TEMPLATE.md:10 — Closes #, under a heading marked (Required), with two HTML comments below it that address only the case of no issue, never the case of a partial one.
CONTRIBUTING.md — documents setup and the review path; says nothing about close-target scope.
- The agent-side rule lives in
.agents/skills/pull-request/references/pull-request-workflow.md §9.1 (Resolves only for the fully-delivered leaf; Closes/Fixes forbidden; broad parents get Refs) and is enforced by baseline / PR body — for ai-labelled PRs. The two audiences have opposite instructions and only one of them is enforced.
The Fix
Give the template a second, equally prominent option, and one sentence explaining when to pick it. Keep it shorter than the rule it replaces — a contributor reads this form once, under friction.
Shape (wording to settle in the PR, not prescribed here):
**Does this PR resolve an issue?** (Required)
Closes # <!-- this PR finishes the issue -->
Refs # <!-- this PR is one slice; the issue stays open for the rest -->
Two follow-on questions the implementation must answer rather than assume:
- Does
CONTRIBUTING.md need the same sentence, or does the template carry it alone? Prefer one site.
- Should
baseline / PR body grow a warning — not a failure — when a non-agent PR's Closes target has visibly more scope than the diff? Probably out of scope for this leaf, and worth a follow-up only if the template change proves insufficient.
Prescription checked: .github/PULL_REQUEST_TEMPLATE.md owns the concern. No better owner — CONTRIBUTING.md is read before the work, the template at the moment the decision is made.
Contract Ledger Matrix
| Target surface |
Source of authority |
Proposed behaviour |
Fallback |
Docs |
Evidence |
.github/PULL_REQUEST_TEMPLATE.md issue-reference block |
this ticket |
offers both a closing and a non-closing form, with one line on when each applies |
contributor writes neither; the existing "PRs without issue references may be closed" note already covers that |
the template itself |
a partial-slice PR opened after the change carries Refs and closingIssuesReferences is empty |
Decision Record impact: none — no ADR governs contributor-facing templates.
Acceptance Criteria
Out of Scope
- The agent-side
Resolves-only rule and its lint; those are correct and enforced.
- A lint that fails a non-agent
Closes overclaim. Named as a possible follow-up above; a form that reads correctly is the cheaper fix to try first.
- Re-scoping #19026 or any other multi-slice ticket.
#18985's contributor-door work. This is one form field; that epic is the door.
Avoided Traps
- Treating this as the contributor's mistake. It is not; they followed the only instruction given. A ticket framed as "reviewers should catch bad close targets" would put the cost on every future review instead of removing it once.
- Adding a lint before fixing the form. The form says
Closes # and nothing else. Enforcing against a rule we never wrote down is how the agent-side discipline stayed invisible to contributors in the first place.
- Folding it into
#18985. That epic's ACs are the door, the issues, CONTRIBUTING, and the merge window; a template field is a leaf, and it can land now rather than at that epic's pace. Related, not absorbed.
Related
- #19032 — the PR that surfaced it; review 5266388586 carries the measurement.
- #19026 — the multi-slice ticket at risk, plus #19028 / #19030 of the same shape.
- #18985 — the contributor door (@neo-opus-ada). Related; this leaf is narrower and independently landable.
- #19023 / #19007 — the live control proving a
dev merge auto-closes.
Handoff Retrieval Hints
query_raw_memories: "PULL_REQUEST_TEMPLATE Closes partial slice auto-close contributor"
- Reproduce the hazard:
gh pr view 19032 --json closingIssuesReferences against the file count in its own body table.
- Prior art that shaped the framing: @neo-opus-ada's #12570 → #12574 narrow-close correction, and her three-incident magic-keyword session (qualifiers do not neutralise the parser).
Origin Session ID: 24396022-ee78-42d8-8935-0c860eb992bc
Context
Found while reviewing PR #19032, the first slice of #19026 by a first-time contributor (@wofiporia). Their PR delivers the
data/directory — 7 of the ticket's 35 spec files — and their own body enumerates the thirteen directories still to do. It opens withCloses #19026, which will close the ticket on merge with 28 files undone.They did exactly what we told them to.
.github/PULL_REQUEST_TEMPLATE.md:10is the literal lineCloses #, under the heading "Does this PR resolve an issue? (Required)". There is no other option offered and no note about partial delivery.Sweep attestations (2026-09-21T12:0xZ):
#18985(@neo-opus-ada, the Hacktoberfest contributor door) is the nearest neighbour and does not cover this — none of its seven ACs mentions the PR template, andPULL_REQUEST_TEMPLATEdoes not appear in its body. AC-5 covers the reviewer-side "review, label and spam path", not the author-side form.github-content-sync#8/#9 (@neo-opus-vega), Brain #103/#396 (@neo-gpt), #19027 (mine). No overlap.query_raw_memorieson the symptom surfaced a dense prior-art cluster — @neo-opus-ada's #12570 close-target over-claim corrected to a narrowResolves #12574+Refs #12536, and a three-incident session on magic-keyword parsing (\b(KEYWORD)\s+#Nmatches through qualifiers, so "Resolves part of #N" and even "does NOT close #N" both fire). Every one of those is agent-side discipline. None of it reaches a contributor, because none of it is in the template they are handed..agents/skills/change proposed..mjscreated or relocated.The Problem
devis this repository's default branch, so a closing keyword fires on merge. That is not theoretical here: PR #19023 merged todevat 11:08Z today and auto-closed #19007. GitHub already registers the link on #19032 —closingIssuesReferences: [19026].Nothing warns.
baseline / PR bodypassed on #19032. That check enforces theResolves #Ngrammar for agent/aiPRs; a non-agent author writing the template's ownCloses #Nis outside its scope, so the lint is green and the close-target is still wrong.The failure is specific to the tickets we most want newcomers in. A
good first issuesized as "one directory at a time" — #19026 is exactly that shape, and #19028 and #19030 are adjacent — invites exactly one slice per PR. The template then converts each slice into a full close. The first contributor to take a slice silently ends the ticket for everyone behind them, and the damage is invisible at review time unless a reviewer thinks to check the ratio of delivered files to ticket scope.The Architectural Reality
.github/PULL_REQUEST_TEMPLATE.md:10—Closes #, under a heading marked (Required), with two HTML comments below it that address only the case of no issue, never the case of a partial one.CONTRIBUTING.md— documents setup and the review path; says nothing about close-target scope..agents/skills/pull-request/references/pull-request-workflow.md§9.1 (Resolvesonly for the fully-delivered leaf;Closes/Fixesforbidden; broad parents getRefs) and is enforced bybaseline / PR body— forai-labelled PRs. The two audiences have opposite instructions and only one of them is enforced.The Fix
Give the template a second, equally prominent option, and one sentence explaining when to pick it. Keep it shorter than the rule it replaces — a contributor reads this form once, under friction.
Shape (wording to settle in the PR, not prescribed here):
Two follow-on questions the implementation must answer rather than assume:
CONTRIBUTING.mdneed the same sentence, or does the template carry it alone? Prefer one site.baseline / PR bodygrow a warning — not a failure — when a non-agent PR'sClosestarget has visibly more scope than the diff? Probably out of scope for this leaf, and worth a follow-up only if the template change proves insufficient.Prescription checked:
.github/PULL_REQUEST_TEMPLATE.mdowns the concern. No better owner —CONTRIBUTING.mdis read before the work, the template at the moment the decision is made.Contract Ledger Matrix
.github/PULL_REQUEST_TEMPLATE.mdissue-reference blockRefsandclosingIssuesReferencesis emptyDecision Record impact:
none— no ADR governs contributor-facing templates.Acceptance Criteria
.github/PULL_REQUEST_TEMPLATE.mdoffers a non-closing reference alongsideCloses #, with one sentence distinguishing them, and the block is no longer than the current one plus two lines.CONTRIBUTING.mdgains a sentence, the template links to it rather than repeating it.baseline / PR body's pass/fail behaviour in this ticket.Out of Scope
Resolves-only rule and its lint; those are correct and enforced.Closesoverclaim. Named as a possible follow-up above; a form that reads correctly is the cheaper fix to try first.#18985's contributor-door work. This is one form field; that epic is the door.Avoided Traps
Closes #and nothing else. Enforcing against a rule we never wrote down is how the agent-side discipline stayed invisible to contributors in the first place.#18985. That epic's ACs are the door, the issues,CONTRIBUTING, and the merge window; a template field is a leaf, and it can land now rather than at that epic's pace. Related, not absorbed.Related
devmerge auto-closes.Handoff Retrieval Hints
query_raw_memories:"PULL_REQUEST_TEMPLATE Closes partial slice auto-close contributor"gh pr view 19032 --json closingIssuesReferencesagainst the file count in its own body table.Origin Session ID: 24396022-ee78-42d8-8935-0c860eb992bc