Repository navigation
fix(source-control): check near-expiry entries on an exact-count verdict listing - #12020
Conversation
…ict listing The pr-verify verdict reader accepted a listing whose entry count equals the first page's total_count, and re-read entries near expiry only on an over-count. An entry GitHub deleted early could stand in for a FAIL a whole listing skipped at a page boundary, or that a stale carry lacked, so the count matched and the FAIL was left out. _incremental now runs _near_expiry whenever a kept entry expires within EARLY_DELETION_LEAD, on an exact count too, under the existing per-listing caps. _near_expiry reports whether it settled every such entry; an exact count it cannot settle (a cap, an unbracketed group, an odd id answer) fails the listing instead of being accepted, and a 5xx that outlasts its waits stays transient. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…near-expiry drop Read the pages near expiry only on an exact count or an over-count: a short count is never kept, so on main it waited and read again with no extra reads, while 80f20f4 re-read those pages on every attempt and, once the shared cap ran out, refused a count main would retry. An exact count those pages leave short now goes straight to a whole listing (COUNT_OVER) from the incremental stage: the base still holds what they dropped, so each wait re-read the same pages and spent the cap the whole listing's top-up needs. A top-up's short count still goes to another whole listing. Rename the test helper that shadowed TestCase.fail, which made assertIn, assertIsNone and list assertEqual pass on failure in that class, and align the docstrings with the returns. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…unt slot The ready-gate code review found two branches no test held: a top-up's exact count left short must read another whole listing, and an exact count must not take the job's over-count slot. Each test fails under the mutant that breaks its branch. Reword the COUNT_OVER docstrings to match the returns. 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. |
… the job An exact count the near-expiry reads leave unsettled only because NEAR_EXPIRY_PAGE_CAP or NEAR_EXPIRY_ID_READ_CAP ran out still refuses the read, but as transient: no .failed note, so a later Reader with fresh caps can list and settle it. _near_expiry now returns why an entry stayed undecided (near-expiry-cap, unbracketed, id-answer), and every unsettled exact count prints a babysit-listing-miss line naming that cause. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
claude-security-review reviewed Security review: PR #12020, incremental (
|
|
claude-review reviewed Code review: PR #12020, incremental (round 3, from 4c82d34 to 5fcddd3)I read every hunk of both in-scope files in Last round's finding (discussion_r4437104835): fixed. That finding said a top-up's own first pages could run out of time after an earlier top-up's near-expiry reads, and the failure was still noted for the job. The new head extends the classification at What I checked:
Minor, not counted: Docstring: Verification: I ran nothing; this lane has no shell. The test results in the PR description are the author's claims and I have not checked them. Settled threads: the thread on the listings' time budget (owner reply, Spend: no change from the last round. The near-expiry reads still draw on the GitHub REST rate limit, not on billing. |
listing_timeout sizes the whole listings' deadline for LISTING_READS listings and their top-ups only. Exact-count top-ups now spend it on near-expiry page and id reads, so a short top-up's next whole listing, or a later region page, can run out of time; that failure was non-transient and noted for the job, so every later Reader refused. When the deadline runs out after this listing's near-expiry reads began (in _read_listing, a region page or an id read), the read is refused as transient, never allowed, writes no .failed note, and prints a babysit-listing-miss line with cause near-expiry-deadline. listing_timeout and cold_cost are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A top-up's own page that ran out of the shared deadline after an earlier top-up's near-expiry reads returned a bare None with no transient flag, so the whole listings raised _Unreadable and noted the failure for the job. Classify it with _near_expiry_out_of_time like the whole-listing case: it stays a refusal, refused as transient, with no job-wide .failed note. The near-expiry deadline subtest gains a 12 s step that lands the timeout on the second top-up's page 1; it fails on the previous head. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
No related issue: follow-up to #11921's review (exact-count FAIL hole)
Summary
The pr-verify verdict reader (
babysit_verify_evidence.py) accepted an artifact listing whose entry count equals the first page'stotal_count, and re-read the entries near expiry only on an over-count. Two exact-count cases could hide a FAIL:EARLY_DELETION_LEADbefore itsexpires_at), so the count still matches;Fix
Reader._incrementalnow runs_near_expiryon an exact count whenever a kept entry expires withinEARLY_DELETION_LEAD, as well as on an over-count. Each such id is decided by the pages that hold it now, or by its own read, under the existingNEAR_EXPIRY_PAGE_CAP/NEAR_EXPIRY_ID_READ_CAP._near_expiryreports why it left an entry undecided, or that it settled every one. An exact count it cannot settle (near-expiry-cap: a cap ran out;unbracketed: a group it cannot bracket;id-answer: an id answer it cannot read) is refused instead of accepted, and prints ababysit-listing-missline with thatcause. A 5xx that outlastsLISTING_WAITS, or a refusal caused only by the caps running out, is transient: no.failednote for the job, so a later Reader with fresh caps can list again. Every other unsettled refusal is noted as before.listing_timeoutsizes the whole listings' deadline forLISTING_READSlistings and their top-ups only, and exact-count top-ups now spend it on near-expiry reads. When that deadline runs out after this listing's near-expiry reads began (in_read_listing, a top-up's own page, a region page or an id read), the read is refused as transient, never allowed, writes no.failednote, and prints ababysit-listing-missline withcausenear-expiry-deadline.listing_timeoutandcold_costare unchanged.COUNT_MISSEDretries cost what they did on main.COUNT_OVER, noINCREMENTAL_WAITS): the base still holds what they dropped, so a wait would re-read the same pages and spend the cap the top-up needs. A top-up's short count still goes to another whole listing.TestCase.failis renamed (it madeassertIn,assertIsNoneand listassertEqualpass on failure in that class).Per-run call delta: +0 when no kept entry is near expiry; otherwise at most the existing
NEAR_EXPIRY_PAGE_CAP(24 pages) andNEAR_EXPIRY_ID_READ_CAP(34 id reads) per listing, incremental read and top-up together. On a saved 3011-artifact listing, the entries near expiry formed one group spanning about 5 to 7 pages at every hour sampled.Verification
New and changed tests in
test_babysit_verify_evidence.py, run against three versions of the reader:cause: near-expiry-cap; a fresh Reader allows.failed)cause: near-expiry-deadline(whole-listing and region-page subtests).failednoted)test_babysit_verify_evidence.py: 412 passed, 352 subtests before merging main; 420 passed, 355 subtests on the head 4c82d34 (main brought fix(source-control): read late pass names in the pr-merge gate's verdict read #11989's tests).test_babysit_verify*.pysuites pass, 452 tests; pre-push check-affected passed.scripts/run-ruff.sh checkon the changed files: all checks passed.scripts/affected-tests.shsuites run one at a time withscripts/run-test-file.sh: 139 suites at head 12251a6, all pass; after merging main (perf(source-control): read the verdict reader's config from the base checkout and reuse the cached pull request in merge-group ci-status #12016 touched the same files) the test file passes 420 and the pre-push check-affected passed (on the first run, 12.mjs/runner-policy suites failed on missingyaml/ajvin a fresh worktree and passed afternpm ciin their packages).Related
🤖 Generated with Claude Code