Repository navigation
fix(pr-merge): pin the head before a native arm so an immediate enqueue reads back - #9576
Conversation
…e lane merge Arming a lanes App pull request that is already mergeable enqueues it at once, and GitHub records only an AddedToMergeQueueEvent by the identity, no AutoMergeEnabledEvent (#9554). native_auto_merge read that as a gate merge, so the post-merge check waited on a pin the gate never posts and would file a read-back demotion after six hours. It is now native when there is no auto-merge event, every enqueue in the history is the identity's, and merge.lane-prs was native at the merge commit's first parent. The merged read gains the parent and up to ten enqueue events in place; the config is read only for that shape, once per parent, and an unreadable config keeps the pin read-back. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
claude-security-review reviewed No security issues found in the incremental change since e52f3fd. It touches What changed: Why it holds:
manifest fields: not hit. This incremental diff has no plugin manifest or instruction-surface change. The Actions and workflow surfaces are untouched in this range. critical-findings: 0 |
|
claude-review reviewed Incremental review of What changed. Tests. The new I only read the code and the diff. I did not run the tests. The closing-issue and manifest checks don't apply to this change. No hold class applies. |
…ue reads back enable-auto-merge posts the gate's babysit-merge-pin comment for the head before it arms, unless the lanes App's newest pin already names that head unedited; a pin that fails to post leaves the pull request unarmed and fails the run. Arming an already-mergeable pull request enqueues it at once with no auto-merge event, so the post-merge check now reads that head back against a pin, and a later push fails the read-back. The immediate-enqueue native tests are split one condition per test, and the safety reference states both rules and the residual. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… native merge An immediate-enqueue native merge now reads the identity's unedited pin when one stands: a match verifies and a mismatch is a read-back failure, as on the pin-required path. Only a merge with no unedited pin skips the read-back, which pin-before-arm leaves to merges armed before it, such as #9554. The enable-event native path is unchanged. The no-merge-parent guard is removed: a missing parent reads as "", which read_config_at refuses, so it is not native either way. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eue native merge _immediate_enqueue now refuses a timeline with no AddedToMergeQueueEvent before its actor loop, so a lagging or unrecorded enqueue never reads as native by an empty loop. The guard replaces the indirect `merge.queued` check, which derive_auto_merge sets from the same nodes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs: #9508
Summary
Arming a lanes App pull request that is already mergeable enqueues it at once. GitHub then records only an
AddedToMergeQueueEventbymelodic-automation-lanes, with no auto-merge event (#9554, armed at 03:29:53Z). The post-merge check read that as a gate merge and waited on a pin nobody posted. Aftermerged_at + DISPATCH_DEADLINEit would file a false read-back demotion and stop the pr-merge lane. This PR does two things:enable-auto-mergepins the head before it arms, so such a merge reads back against a pin.Fix
Pin before arm (
.github/scripts/pr-merge/enable-auto-merge.mjs): just beforeARM_MUTATION, the script posts<!-- babysit-merge-pin sha=<headRefOid> -->, the format ofbabysit_postmerge.PIN_RE, as the lanes App.DETAIL_QUERYnow readslastEditedAtfor this.Immediate-enqueue native (
native_auto_merge): with no auto-merge event, a merge is native only when all of these hold:AddedToMergeQueueEventhas the identity asactor, and anenqueuerthat is null or the identity;hasPreviousPagefalse);merge.lane-prsisnativeat the merge commit's first parent.An unreadable config at that parent keeps the pin required (fail closed) and leaves the verdict readable. A missing parent is read as
"", whichread_config_atrefuses, so the separate guard for it was removed. Even when the merge is native, an unedited identity pin that stands is read back: a match verifies, and a mismatch is a read-back failure. The enable-event native path is unchanged.MERGED_QUERYis extended in place:mergeCommit.parents(first:1), pluslast:10andpageInfoon the enqueue connection. The config is read only for this shape, once per parent.Residual, stated in the docstring and in
reference/safety.md: only a merge of this shape with no unedited pin skips the read-back. With pin-before-arm in place, that is a merge armed before this PR (feat(performance): add an optional holdout harness to performance:climb, off by default #9554), or one whose pin was edited or deleted after the enqueue. Such a merge still needs a green dispatch run and a green canary run.Verification
node --test .github/scripts/pr-merge/*.test.mjs: 301 tests pass. The new tests cover:pinned()to false fails the no-duplicate test.test_babysit_postmerge.py, OK. There is one test per condition: author, cross-repo, auto-merge event, enqueue actor, enqueuer, fix(planning): brief TLDR reads "1 question" for a single question #9540-style earlier human enqueue,hasPreviousPage, no parent,lane-prsgate at the parent, a value other than native or gate, native only at the merge commit (gate at the parent), a gate enqueue under gate reading its pin back, an unreadable config, and an arm pinned before an immediate enqueue verifying with nothing pending.scripts/check-affected.sh --uncommitted: 11 passed.scripts/run-ruff.sh checkpasses.d90fa9dbreadslane-prs: native), while fix: feat(discovery,implementation,plugin-quality): add a next: field to the subagent return contract #9489 and docs(harness-ops): add harness-ops:prerequisites row to README skills table #9475 (parent config gate) stay pin-required.Related
merge.lane-prs.🤖 Generated with Claude Code