Repository navigation
fix(pr-merge): route repeated-fail and too-old verdicts to the lanes, not a person - #10481
Conversation
… not a person Owner rule 2026-10-27: needs-human only for an intent or design change or a CRITICAL security issue, trust holds kept. NEEDS_HUMAN is now verify:untrusted-spec alone. verify:repeated-fail and verify:too-old still refuse the merge for good; they get the lane comment and the failing pr-merge/unarmed status (#10249's route) and no label. clear-escalations.mjs LANE_CAUSES.verdict adds both, so labels already placed for them come off at their head (#10198's refusal-cleared lift). The pin test now also checks LANE_CAUSES.verdict against NEEDS_HUMAN. The repeated-fail escalation's summary quote is unreachable and removed: _fail_summary, _carried_quote, VERIFY_SUMMARY_MAX, Reader.fail_summary, SummaryUnreadable and the report's headFail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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 No findings. I read the full 1286-line diff and the PR context. I did not run any tests; the suite results in the PR description are author-claimed and I did not re-run them. Checked against the change
Trusted paths touched ( Closing issue: none (the PR states an owner rule, not an issue), so there are no acceptance criteria to check. Cost: no billing change. The change only removes Manifests: no |
|
claude-security-review reviewed No security findings in PR #10481 (head 7d8367c). critical-findings: 0 What changed. Trust-control check (merge hold weakened?). I read the changed trusted-path files and the code they gate. The change does not weaken any merge hold.
Removed quote path. The deleted code ( Manifests. No Spend note. With the label gone, a pull request at the repeated-fail cap can still get address-feedback rounds on verifier notes. These use prepaid credit and are bounded by I did not read |
Post-merge mutation testingKilled 4, survived 1, timeout 0, no coverage 0, invalid 0, not run 3.
Surviving mutants
The run's summary has the full report. |
No related issue: owner rule 2026-10-27 on needs-human (intent, design-altering findings, HIGH/CRITICAL security only)
Summary
Under the owner rule of 2026-10-27, a person is pulled in only for an intent change, a finding that alters intent or the primary design, or a HIGH or CRITICAL security issue.
verify:repeated-failandverify:too-oldare none of these, but pr-merge still putneeds-humanon them. This PR routes both to the lanes. It reuses the paths #10249 and #10198 built and adds no new route.merge-holds.mjsevidenceHoldholds on every refusal except the three a pass decides, and it never readsneedsHuman.merge.lane-prs: native, lanes App pull requests). The reader now reportsneedsHuman: false, soverifyClearsreturnslane. The pull request stays unarmed with the lane comment. Once the refusal stands formerge.risk-escalation-minutes, a failingpr-merge/unarmedstatus goes on the head. It gets no label. This is fix(pr-merge): route non-h38 needs-human holds to bounded retries and a failing status #10249's route.pr-merge / gatecheck run shows the refusal, as it already does forverify:spec-changed.LANE_CAUSES.verdictinclear-escalations.mjsadds both reasons. On its next tick, pr-merge's clear step removes a native label for either one at its head (refusal-cleared) when the reader names only lane causes there. This is fix(pr-merge): clear a native gate's needs-human label once its cause is gone #10198's lift.verify:untrusted-specdoes: an untrusted spec is a trust boundary. It is now the whole ofNEEDS_HUMAN.How the repeated-fail bound holds. The cap still refuses the merge, and pr-merge spends nothing on a lane refusal beyond its scheduled read. Nothing dispatches from the status: fix-ci reacts only to check runs, and no workflow runs on status events (checked in #10249). Fix rounds on verifier notes stay bounded by address-feedback's own cap:
loop.review-rounds(default 2) plusFRESH_FIXER_ROUNDS1 (address-feedback.mjs:42-49).Fix
babysit_verify_evidence.py:NEEDS_HUMAN = (UNTRUSTED_SPEC,). The module docstring and the constant's comment now state the new rule.clear-escalations.mjs:LANE_CAUSES.verdictaddsverify:repeated-failandverify:too-old. The comment now says why both are lane-class.lane-causes-person-codes.test.mjsalso readsNEEDS_HUMAN. It asserts thatLANE_CAUSES.verdictshares nothing with it, thatverify:untrusted-specstays in it, and that both reasons are lane causes.enable-auto-merge.mjsheader and theverifyClearscomment; the pr-pipeline README (refusal-cleared row, native-path label list, verifier-verdict section);pr-pipeline.schema.jsonmax-verify-fails; thepr-pipeline.yamlcomment; andbabysit_merge_policy.pymax_verify_fails.escalate_verifyruns only onneedsHuman, and the quote applied only toverify:repeated-fail. That coversbabysit_merge._fail_summary,_carried_quote,_QUOTE_RE,VERIFY_SUMMARY_MAX, the summary arguments ofverify_escalation_bodyandescalate_verify,Reader.fail_summary,_listed_id,SummaryUnreadable,Evidence.head_fail, and the report'sheadFailfield. No consumer in.github/readheadFail..changes/source-control/and.changes/pr-pipeline/.Verification
Each test below fails against main's sources and passes on this branch. They were run by copying the branch's test files into a checkout of main.
test_babysit_verify_evidence.py: 23 failures on main.test_only_an_untrusted_spec_goes_to_a_personLaneRequiresAVerdict.test_the_cap_and_an_old_pull_request_hold_with_no_escalation: gate path, no comment and no label for either reasonneeds_humanassertionsTheByIdFetchDecidesAsGhRunDownloadDid, whose docstring now names its two changed fieldsclear-escalations.test.mjs: "enable-auto-merge's label comes off when the reader now reads a refusal the lanes clear for the same cause" now includes refactor(guardrails): resolve the commit convention from docs conventions source-control.yaml #10134's shape: a repeated-fail label lifted at its head while the reader still refuses repeated-fail, and the same for too-old.lane-causes-person-codes.test.mjs: "the repeated-FAIL cap and an old pull request are lane causes the clear lifts".enable-auto-merge.test.mjsfixture flips (needsHuman: false, lane comment, no label) pass on main as well, because the fixtures set the flag directly. They keep the tests in line with the contract. The Pythonneeds_humantests and the clear and pin tests above are the actual proof.Suites, run locally on 2026-10-27:
python3 -m unittestinbabysit-prs/scripts: 3174 tests OK.node --testin.github/scripts/pr-merge: 526 pass, 0 fail.scripts/ci-lanes-pr-hold.test.sh: PASS=215 FAIL=0.scripts/check-affected.sh --tests: 13 passed, 2 skipped.scripts/run-ruff.sh check: clean.format --diffon the changed Python shows the same 6 hunks on main and on this branch, so none of them come from this change.scripts/check-changelog-fragments.sh --check-required origin/main: OK.Security check: nothing decides a merge from
needsHuman. It is read only byenable-auto-merge.mjsverifyClears, which chooses between a label and a comment, and bybabysit_merge.unattended_writes, which decides whether to escalate.verifyHoldandmerge-holds.mjsevidenceHoldhold on the refusal itself.Related
pr-merge/unarmedstatus, no label). It kept both reasons with a person as C1a and C1b. Owner rule 2026-10-27 reverses that.refusal-clearedlift, whichLANE_CAUSESdrives.Left out, for the owner:
verify:repeated-fail. #10377, #10414 and #10439 hold on a hold path, which is a person's by design. A trusted approval at their heads lifts them (fix(pr-merge): arm a hold-path pull request a trusted person approved at its head #10397).TOO_OLD_DAYS. Such a pull request stays open with the failing status. Closing it and re-admitting the issue would not help at the cap: the count follows the issue across pull requests (README, Verifier verdict), so a new pull request for the same issue is refused again as soon as a pass decides. Whether to add a close step is the owner's decision.address-feedback.mjs:84-93,feedback-round-cap). The result isneeds-humanon the pull request, notneeds-decisionon the issue. Under the same owner rule, that looks like the next candidate.{verdict, summary, notes}, so this PR adds no reason-2 (needs-decision) detection.head-moved. The same-head lift applies on the native path only.🤖 Generated with Claude Code