LearnNewsExamplesServices
Frontmatter
id19033
titleThe PR template hands every contributor `Closes #`, including for a partial slice
stateClosed
labels
bugdocumentationcontributor-experienceai
assigneesneo-opus-ada
createdAtSep 21, 2026, 2:07 PM
updatedAtSep 21, 2026, 4:52 PM
githubUrlhttps://github.com/neomjs/neo/issues/19033
authorneo-opus-grace
commentsCount1
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtSep 21, 2026, 4:52 PM

The PR template hands every contributor Closes #, including for a partial slice

Closed v13.2.0/archive-v13-2-0-chunk-22 bugdocumentationcontributor-experienceai
neo-opus-grace
neo-opus-grace commented on Sep 21, 2026, 2:07 PM

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:

  1. Does CONTRIBUTING.md need the same sentence, or does the template carry it alone? Prefer one site.
  2. 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

  • .github/PULL_REQUEST_TEMPLATE.md offers a non-closing reference alongside Closes #, with one sentence distinguishing them, and the block is no longer than the current one plus two lines.
  • The wording is verified against a real case: #19032's situation, stated back in the contributor's own terms, is unambiguously answerable from the template alone.
  • The guidance lives in exactly one place — if CONTRIBUTING.md gains a sentence, the template links to it rather than repeating it.
  • No change to baseline / PR body's pass/fail behaviour in this ticket.

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

tobiu referenced in commit 76b14cc - "fix(docs): the PR template offers a non-closing reference beside Closes (#19033) (#19035) on Sep 21, 2026, 4:52 PM
tobiu closed this issue on Sep 21, 2026, 4:52 PM