feat(GATE-PR-BODY-TRAILERS): refuse a body whose closing keyword contradicts the canonical record - #3144
Merged
Conversation
…radicts the canonical record `squash_merge_commit_message = PR_BODY` makes a pull request body the landed commit message, so `Closes #N` in a body closes the GitHub mirror the moment the squash lands. Local files under `.agents/issues` are the issue authority, and nothing checked that the branch also carries `ISSUE-GH-N.md` reading `State: CLOSED`. The two authorities therefore diverge at the merge, and the authoritative half is the one left reading OPEN. Four pull requests in a single review pass carried it: #3101 closed #3098 whose record read OPEN; #3095 closes #3092 while that row's own gate table reads FAILING; #3096 carries five closing keywords against four OPEN records and one issue with no local record at all; #3097 closed #3093 against a spec saying the row is not ready to land. `check-agent-record.py` cannot catch this. It is offline and never sees a body, and `check_canonical_issue_references` silently continues on an unresolvable bare `#N`. Making THAT strict was the obvious repair and is the wrong one: open pull requests carry six to ten bare citations each, mostly without a local record (measured: 6 of 7, 4 of 4, 8 of 8, 10 of 11), so it would fire on ordinary work rather than on the defect. The rule therefore keys on the closing keyword alone and lives in `agent-pr-body.py`, which already reads the live body and already runs before a merge. Red before: a body closing an issue with no record exits 1 naming the missing path. Green after: a bare `Refs #N` still exits 0, which is what keeps the gate narrow. The spec's `Kind` line is amended in the same change, because it claimed this row edits no checker rule and now it does. Refs ISSUE-LOCAL-01M298Q7PPM145DQA5C30GRYJA. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5-1m [claude-code]
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
GATE-PR-BODY-TRAILERS. Refs ISSUE-LOCAL-01M298Q7PPM145DQA5C30GRYJA.What changed
squash_merge_commit_message = PR_BODYmakes a pull request body the landedcommit message, so
Closes #Nin a body closes the GitHub mirror the moment thesquash lands. Local files under
.agents/issuesare the issue authority, andnothing checked that the branch also carries
ISSUE-GH-N.mdreadingState: CLOSED. The two authorities diverge at the merge, and the authoritativehalf is the one left reading OPEN.
scripts/agent-pr-body.pynow refuses such a body. It already fetches the livebody and already runs before a merge, which is exactly when this matters.
Why here, and why only closing keywords
check-agent-record.pycannot catch it: it is offline and never sees a body,and
check_canonical_issue_referencessilentlycontinues on an unresolvablebare
#N. Making that strict was the obvious repair and is the wrong one.Measured over four open pull requests, bare citations lacking a local record run
6 of 7, 4 of 4, 8 of 8 and 10 of 11 — so failing them would fire the gate on
ordinary work, which AGENTS.md names as the defect rather than the discipline.
The rule therefore keys on the closing keyword alone.
Evidence
Red before: a body closing an issue with no record exits 1 naming the missing
path. Green after: a bare
Refs #Nstill exits 0. Both are committed as casesin
tests/scripts/test_agent_pr_body.py(suite: 21 passed, 16 subtests), andthe spec's
## Teststable is updated because that table is compared with theloaded suite rather than sampled.
Found live on four pull requests in one review pass: #3101 carried a closing keyword for #3098, whose
record read OPEN; #3095 did the same for #3092 while that row's own gate table reads
FAILING; #3096 carries five closing keywords against four OPEN records and one
issue with no local record at all; #3097 likewise for #3093, against a spec saying the
row is not ready to land. On its first live run against #3095 it also caught a closing keyword for #3106, which the human review pass and I had both missed — that record
reads OPEN and its Resolution says it stays open until the reviewed production
repair lands.
The spec's
Kindline is amended in the same change, because it claimed thisrow edits no checker rule and now it does.
FOLLOWING_AGENTS_PROTOCOL
Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:claude-opus-5-1m [claude-code]