Repository navigation
fix(source-control): bind a review re-run after a kill-switch skip - #10188
Conversation
A review run whose attempt 1 a kill switch stopped (the caller's kill-switch job succeeded with its lane's notice, and no lane job ran) left no verdict. ci-status tells a person to re-run it once the switch is off, but the binder refused that attempt 2 as rerun-not-allowed, and a kill-switched run on any head unbound the lane as no-lane-job. rerun_binds now takes attempt 1 and is the one rule for both: a failed attempt on a rate limit or rejected credential, or a successful attempt the kill switch stopped. The lane-run collector reads the kill-switch job's annotations only for an attempt with no lane job. The merge gate still re-runs only on rate limits, a subset of what binds, now pinned by a test. 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 this pull request. critical-findings: 0 Scope. The change touches the babysit-prs review-evidence binder. It decides whether a second attempt of a review lane run counts as the review of a head, and the merge gate reads that. The files are Trust boundary: can a PR forge the new "kill-switch stopped attempt 1" evidence? I judged it cannot, for these reasons:
Merge gate. The gate still starts only re-runs that Cost. No billing or paid-plan change. The only extra spend is one extra API read per kill-switched attempt, which is not a hold. |
|
claude-review reviewed No findings. I read the full diff (7 files) and the PR context. I also read What I checked
|
Refs: #10142
Summary
Review runs that started during the 2026-10-25 20:55-20:59Z breaker trip were stopped by the kill switch. On #10092, run 40233053957 concluded
successat attempt 1. Its jobs werekill-switch(success, with noticea kill switch stops this review (lanes: kill-switch, CLAUDE_REVIEW_DISABLED: false)),resolve-model(success) andpr-review(skipped). ci-status says "Once it is off, re-run all jobs of ". The review-evidence binder then refused that attempt 2 asrerun-not-allowed, because it accepted a second attempt only after a failed first attempt with a rate-limit or auth line on the lane job. Following ci-status's instruction therefore produced a second hold. Attempt 1 left no verdict, the same reason auth and credit failures already bind.Fix
babysit_review_evidence.rerun_binds(lane, run_id, first)is now the single rule for whether attempt 2 binds, and the conclusion test moved into it.failureattempt binds on a rate-limit or auth line on the lane job, as before.successattempt binds only when_kill_switch_stoppedholds:kill-switch, which concludedsuccessand belongs to this run and attempt;noticeannotation opening with its own lane's text (a kill switch stops this review (ora kill switch stops this security review ()._open_findingsskips a kill-switched attempt through the same helper. Before this, any kill-switched run of the lane (on any head of the PR) unbound it asno-lane-job.The constraints that still hold:
rerun-not-allowed);babysit_gh.collect_lane_runsreads thekill-switchjob's annotations only for an attempt that has no lane job and whosekill-switchjob succeeded. Normal runs make no extra API call; a kill-switched attempt makes one.The merge gate does not auto-re-run kill-switch skips:
rerun_rate_limited_reviewsnever sees it;babysit_merge.py--lane-kill-switchhelp);The gate's trigger set (
rate_limited) stays a subset of the binding set (rerun_binds). The new testtest_every_rerun_the_gate_starts_bindspins that, so Issue Triage pr-review: the bubblewrap install step times out at 1 minute and fails review lanes with no outcome #9073 can cite it.Verification
KillSwitchRerunTestsreproduce fix(app-control): find plugin control skills at manifest-declared paths #10092's attempt-1 job set. Before the fix, binding both lanes gave{'claude-review': (False, 'rerun-not-allowed'), 'claude-security-review': (False, 'rerun-not-allowed')}. The positive test and the missing-annotations test failed: 3 failures in 13.python3 -m unittest discover -s plugins/source-control/skills/babysit-prs/scripts/tests -p "test_*.py"reports 2993 tests, OK.scripts/run-ruff.sh check(pinned) passes.scripts/check-affected.sh --testsreports 13 passed, 1 skipped (shellcheck, no shell changed).(, capitalised);kill-switch;kill-switchjob that failed, was cancelled or was skipped;kill-switchjobs;evidence-missing);lane-source-changed).kill-switchjob's own check-run annotations. A job's annotations are written by that job's steps.refs/heads/mainsparsely, withpersist-credentials: falseandcontents: read. It runscheck-kill-switchfrom that main checkout and echoes onlysteps.kill.outputs.reasonand avars.*value (.github/workflows/pr-review-hosted.ymlkill-switchjob;pr-review-security-hosted.ymlthe same). No PR text reaches the notice.pull_requestrun takes its caller workflow from the head, so a head that edits a caller could write the notice itself, aspr-require-checks.yml"Require both review lanes" notes. Any change under.github/workflows/unbinds every lane aslane-source-changed(LANE_SOURCE_PREFIXES, checked at the start ofbind). The testtest_a_changed_caller_workflow_still_binds_no_lanepins that for this shape.Report the kill switchstep'sifis the exact negation of theproceedoutput the review job needs, so a genuine notice means the review job could not run. The binder also requires that no lane job exists in attempt 1.Related
🤖 Generated with Claude Code