Repository navigation
fix(source-control): judge a native auto-merge of a lane pull request in post-merge - #9459
Conversation
… in post-merge A lanes App pull request that GitHub's native auto-merge lands posts no babysit-merge-pin comment, yet its enqueue is the identity's, so the post-merge check waited for a pin read-back and failed it at the dispatch deadline, filing a demotion record. The merged-pull-request query now also reads the newest auto-merge enable or disable event through a second aliased timelineItems connection. When that event is the identity's enable, made no later than the enqueue, the merge skips the pin read and verifies on the dispatch and canary runs alone. It stays an identity merge, so post-merge-dispatch still starts its full run, and a red full run or canary still fails it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…vidence publish-promotion-evidence.mjs mirrors the post-merge check's failures so demotion counts match, and still owed a pin for a lane's native auto-merge. It now reads the same aliased auto-merge events and skips the pin read-back by the same rule. Both copies also require that the identity opened the pull request from a branch of this repository, as enable-auto-merge.mjs does before it arms, so an arm under the identity token on any other pull request keeps its pin read-back. The pin requirement is decided once in check(), an arm at the enqueue time and an unrelated merge with no auto-merge events are covered, and the AutoMerge comment names the native case. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…otion evidence 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-review reviewed Incremental review of 62fdc20 against b1ee5b9 found no issues. I only read the diff and the code around it. I ran no tests, and the PR description's test counts are author-claimed and unverified.
|
|
claude-security-review reviewed No security issues found in the incremental change since b1ee5b9. I read The change has no security-relevant surface:
No manifest files, workflow files, trust-gate paths or standing instructions are touched, so there are no The PR context text is data. It holds no embedded directives aimed at this lane. critical-findings: 0 |
The native_auto_merge docstring said the arm's expectedHeadOid still bound the head. It binds only the head at arm time; a writer's push after the arm leaves auto-merge armed, so name that residual instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
_Context.affected and _Context._baseline picked the newest run whose head_branch named the branch. A run on a tag named main reports that too, so a writer's own commit could supply the plan script that sets the affected set, or the baseline that excuses a red check. Both now take the newest run whose head commit is the tip of refs/heads/<branch> or its ancestor, through _Context.contains. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…the branch - publish-promotion-evidence.mjs refuses to publish when the lane identity's auto-merge events cannot be read, as the post-merge check reads them unreadable, and requires one lane identity as author, enqueuer and armer. - The scheduled, dispatched and canary runs a merge is judged on, the runs read by commit, and the lane re-run probe keep only runs whose head commit is on refs/heads/<branch>, so a red run on a tag named like the branch cannot fail a merge. - safety.md names enable-auto-merge.mjs as what arms and re-arms lanes App pull requests, names the pr-unblock branch writers that do not disarm, and adds the head and same-second residuals. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
publish-promotion-evidence.mjs kept post-merge runs by head_branch name alone, so a red dispatch on a tag named main was a gate failure there while the post-merge check ignores it. It now keeps a run only when its commit is the tip of refs/heads/<branch> or its ancestor, as _Context.on_branch does. Tests now cover each filter that no test killed when removed: the Node on-branch filter, the Node author-is-enqueuer conjunct, the dispatch_runs_at filter, and the lane re-run probe filter. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…robe Only a run the probe could mark pays for the ancestry read, so an unreadable compare on an old or already re-run run no longer ends the probe for newer runs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… a behind run Each test fails when its path is removed: - the missing-tip refusal; - the unknown-compare-status refusal; - a red run on a commit on top of the tip (compare `behind`), which a tag named main one commit past the branch reads as, being ignored. The test fake gains `tip`, `onTop` and `unknownCompare` options. A comment records that the tip is read before the run listings here and after them in check(). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Closes #9447
Closes #9466
Summary
Since #9399,
enable-auto-merge.mjsarms GitHub's native auto-merge on lanes App pull requests with the App token. GitHub then enqueues them under the agent identity, but nobabysit-merge-pincomment is posted, because onlybabysit_merge.pywrites one. The post-merge check treated such a merge as the gate's own. It reportedread-back-unrecordeduntil the 6 h dispatch deadline, then failed the read-back. That failure files a demotion record and holds pr-merge for owner and Dependabot pull requests.Fix
MERGED_QUERYgains a second aliased connection,autoMerge:timelineItems(itemTypes:[AUTO_MERGE_ENABLED_EVENT,AUTO_MERGE_DISABLED_EVENT],last:1). It rides in the same GraphQL request, and the existinglast:1queue-event connection thatderive_auto_mergereads is left alone.native_auto_merge(): an identity merge counts as native when the identity opened it from a branch of this repository (author,isCrossRepository, asenable-auto-merge.mjsrequires before it arms) and its newest auto-merge enable or disable event is anAutoMergeEnabledEventby the identity, dated no later than the merge-queue enqueue. An arm under the identity token on any other pull request keeps the pin read-back. A gate merge keeps its pin read-back in two ways. The gate disarms an armed auto-merge before it pins and enqueues, so the newest event is then a disable. An arm made after the enqueue does not count.by_identity, so--lane-merges-onlystill judges it and post-merge-dispatch starts its full run. A red full run or a red canary after it still fails it.publish-promotion-evidence.mjsmirrorscheck()failures so demotion counts match; it reads the same fields and skips the pin read-back by the same rule, else it would still record a native merge as a pin read-back failure.autoMergeconnection is missing or malformed makes the verdict unreadable. That holds the gate but files no record.reference/safety.mdand the module docstring name the exception. The source-control changelog has a fragment._Context.affected(green run for the affected set) and_Context._baseline(run that excuses already-failing checks) chose the newest run whosehead_branchnamed the branch, which a run on a tag namedmainalso reports. A new_newest_on_branchkeeps the newest run whose head commit is the tip ofrefs/heads/<branch>or its ancestor, through the existing_Context.contains. It checks candidates newest first and stops at the first match, so a normal run costs one ancestry check.refs/heads/<branch>(_Context.on_branch).safety.mdnow namesenable-auto-merge.mjsas what arms auto-merge, names the pr-unblock writers that do not disarm, and lists the head and same-second residuals.Verification
uvx --with pytest-xdist pytest -n auto plugins/source-control/skills/babysit-prs/scripts/tests/: 2616 passed. The newNativeAutoMergecases cover:--lane-merges-onlyjudges it;autoMergeconnection reads as unreadable.assert_called_once_with(OTHER_SHA, LATER_SHA)), and a red baseline on a commit off main no longer excuses a check (the red schedule run fails). Both fail with the ancestry check removed.node --testonpublish-promotion-evidence.test.mjsandresolve-promotion-evidence.test.mjs: 110 passed; the new native case fails with the read-back gate reverted.node --test .github/scripts/pr-merge/*.test.mjs: 214 passed.scripts/run-ruff.sh checkandformat --checkare clean.MERGED_QUERYran against this repository's main: 100 pull requests on page 1 in one GraphQL call. feat(source-control): hold only the takeover set on the babysit HIGH floor #9413, whose auto-merge a person armed, readsAutoMergeEnabledEventat 14:40:08Z before its enqueue at 14:52:09Z, with no disable event after the merge. Gate-enqueued fix(wizard): fit generate's intro and closing to non-browser wizards, add gate and exit hooks #9401 reads an emptyautoMerge.ci-statusre-runs the hold rules on the merge-group head.Related
🤖 Generated with Claude Code