Repository navigation
fix(source-control): read late pass names in the pr-merge gate's verdict read - #11989
Conversation
…ict read On #11854 the pass-notes artifact landed 24 s after the gate pass had read its artifact listing, so the candidate was refused verify:missing on the run's saved listing and stayed refused once later runs stopped on the kill switch. When the gate's provisional judgment is verify:missing on the run's saved listing, read the head's two pass names by exact name (pr-verify-<pr>-<head>-pass and -pass-notes, the names write-verdict.mjs writes and resolve-pr.mjs looks up): two requests, no listing. A pass found there is judged with the saved listing in memory; an allow stays provisional, so babysit_merge.py's refresh judges it again on a listing of the gate's own that must hold the live count. A failed read, a pass whose run does not count, or none found leaves verify:missing and notes nothing for the job. The evidence CLI (enable-auto-merge, verify-cap, the merge queue's ci-status) never judges provisionally, so it reads no name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s read 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 Security review: PR #11989 (no findings)I found no security issues in this change. I read every hunk of all 5 changed files. What I checked
The other changed files are two changelog fragments, a README note and tests. They carry no security-relevant surface, and none of them removes or softens a standing instruction. Spend: this adds 2 critical-findings: 0 |
|
claude-review reviewed Code review: PR #11989 (no findings)I read every hunk of all 5 changed files: two changelog fragments, Correctness of the change
Criteria
Embedded instructions: none found in the PR context. Spend (not a finding): two more GitHub API requests on the job's |
|
Merge-area review (poteto, relayed by the hub): approved at head 92410ab.
Non-blocking, please fix in the body or README: the worst case is +6 GETs, not +4 (each name is tried len(LISTING_WAITS)+1 = 3 times), and the +0.87 average leaves out the refresh plus own-listing read that a late allow triggers. Lane 3 may arm this once ci-status and both review lanes are green. |
No related issue: follow-up (a) from the pr-verify verify:missing investigation on #11854, assigned by the hub; reviewer poteto owns pr-merge.
Summary
On #11854 the pass-notes artifact landed 24 s after the pr-merge gate pass had read its artifact listing. The candidate was refused
verify:missingon the run's saved listing, and later runs stopped on the kill switch, so it never cleared. The gate now reads the head's pass names by exact name whenverify:missingstands on the saved listing, so a pass uploaded after that listing is seen in the same run.Fix
Reader.evidence(babysit_verify_evidence.py), provisional judgments only: when the refusal isverify:missingand the reader judged on the run's saved listing (saved),_late_passreadspr-verify-<pr>-<head>-passandpr-verify-<pr>-<head>-pass-notesthroughGET /actions/artifacts?name=<name>. These are the nameswrite-verdict.mjsartifactNamewrites andresolve-pr.mjsjudgedlooks up. It never reads a listing page or a FAIL name: a FAIL can only refuse, andverify:missingalready refuses._api_object, so a 5xx is read again afterLISTING_WAITSinsidelisting_cap(), as the near-expiry id reads are.babysit_merge.pyalready callsrefresh()before any allow on a saved listing, so the gate judges the candidate again on a listing of its own that must hold the livetotal_count.total_countother than the entries returned, an entry of another shape), a pass whose run does not count, a refusal on it, or nothing found returns the originalverify:missing. It sets no_listing_error, writes no.failedor.overcount-fallbacknote, and never turnsverify:missingintoverify:unreadable.babysit_merge.py's gate judges provisionally. TheevidenceCLI (enable-auto-merge, verify-cap, ci-status's merge-queue step) reads no name, socold_costinpr-require-checks.ymlis unchanged. No reader rule changed, so nothing new is mirrored inresolve-pr.mjs.babysit-late-pass {"pr", "found", "allowed"}line on the gate's stderr, so a re-measure can count rescued candidates.API calls per run (R34)
GITHUB_TOKEN(github-tokenpool) per candidate the gate reaches withverify:missingon the saved listing. No other path adds a call.pr-merge-summaryartifact, the gate reached 646 candidates, and 30 were refusedverify:missing(none carried). That is at most 1 per run in 68 runs and 2 in one run, a mean of 0.43 per run.verify:missing, including any judged on the candidate's own listing, which reads no name. For scale, run 41317539980 loggedsweep-calls=225 github-token-calls=77with one such candidate, so the delta there was +2 on 77.refresh()reads one incremental listing. That is the allow path the candidate would have taken next run, now taken in the same run, not a new kind of read.babysit_gh.gh_api_with_headers. Each one is in the candidate'sbabysit-gh-callstotal (callsin the summary) and in the job-end api-calls notice underAPI_BUDGET_OVERRIDE_TOKEN(github-token), so the post-merge re-measure from the api-calls annotations includes them.Verification
TheListingIsReadOncePerRun.test_a_pass_uploaded_after_the_saved_listing_is_read_by_name: an earlier gate saves a listing with no verdict, then a pass-notes at the head is uploaded. The provisional judgment allows after two name reads and no listing,savedstays true, and the refresh lists once and allows. On main'sbabysit_verify_evidence.pyit fails ('verify:missing' is not None); on this branch it passes.verify:missingwith no listing; a 502 on the name read is read again after each wait (3 reads), then leavesverify:missingand writes neither job note; a judgment on the candidate's own listing, or one that is not provisional, reads no name.scripts/run-plugin-tests.sh plugins/source-control/skills/babysit-prs/scripts/engine.test.shpassed: 3841 tests OK (17 skipped), includingtest_verify_rules_sync.py, in 138 s.scripts/check-affected.sh --tests: 14 passed, 2 skipped; it left the 69 selected suites to their CI lanes.scripts/run-ruff.sh checkon both changed Python files: all checks passed.github-token-callsand thebabysit-late-passlines from the pr-merge api-calls annotations against the base above.Related
_api_object, near-expiry reads,cold_cost).🤖 Generated with Claude Code