Repository navigation
fix(pr-pipeline): ci-status rejects a review lane's no-change skip after a base merge #9822
Description
Problem
A pull request whose only push after a full review is a base merge can never pass ci-status.
The review lanes skip that push: claude-review-key sets skip=no-change with the reason "no file of this pull request changed since the review of ", and the status job ends success with SUB_RESULT: skipped. The skipped path never runs the Apply the hold step.
ci-status ("Require both review lanes on this head", .github/workflows/pr-require-checks.yml around line 4080) counts a lane only when its status job succeeded and its Apply the hold step succeeded. Otherwise the verdict is uncounted, which fails with:
'pr-review / claude-review-status' passed in , but its 'Apply the hold' step did not run: the lane ran in summary mode or without a hold label, so it is not a review that counts.
So the lane's own no-change skip, which carries the earlier review forward, is rejected by the gate that requires the review. The only way out is a push that changes a file of the pull request.
Evidence
- feat(app-control): add /app-control:map create with config, driver CLI and safety sections #9628, head 800d314 (a merge of
origin/mainonto e9f3154, whose lanes had run in full): pr-review run 40117023042 and pr-review-security run 40117022991 both loggedSKIP: no-change/ "No hold applies: no new model spend and no trust-gate files"; ci-status job 120941082529 failed with the twouncountederrors above. - The verdict rule:
if any($s.steps[]?; .name == "Apply the hold" and .conclusion == "success") then "pass" else "uncounted" endin the same step.
Fix
Either the no-change skip runs (or reports) a counted hold result that ci-status accepts, as the kill-switch path already does with its "Report the kill switch" step, or ci-status treats a status job whose skip is no-change against a review of an ancestor head as pass. A test in scripts/ci-review-lanes.test.sh should cover a merge-only push after a full review.
No related issue: found by the app-control session while landing #9628.
Activity
github-actions commentedon Oct 24, 2026
Proposed work class: work-class: scoped
Basis: automated intake triage; the lanes App applied this class.
Size: Small
Complexity: Medium
Uncertainty: Knowable
Flags: none
Understood: when a pull request's only push after a full review is a base merge, the review lanes correctly skip with
no-change. That skip never runs theApply the holdstep, soci-statusmarks both lanesuncountedand fails. The PR can't merge until a push changes one of its files. #9628 is the evidence. The issue proposes two fixes: make the skip report a counted result, or haveci-statusaccept ano-changeskip against an ancestor head. It also asks for a test inscripts/ci-review-lanes.test.sh. The choice between the two fixes is left to the implementer. I found no likely duplicates in the open issues.Automated triage, applied by the lanes App.
melodic-automation-lanes commentedon Oct 24, 2026
Not admitted to the issue lane: no trusted-human acceptance criteria: a listed human must put the confirmed
- [ ]criteria in the body or post them as their own comment (owner Q9, #8999). A recorded decision does not change these rules (.github/actions/resolve-config/admission-rules.json); a person who wants it worked addsagent-ready.melodic-automation-lanes commentedon Oct 24, 2026
Refinement. A read-only run explored this repository, searched its issues and pull requests, and read the allowed docs to draft what follows. It is model text, to check, not instructions.
Intended outcome: ci-status counts a review lane whose status job succeeded with a no-change skip against a counted full review of an ancestor head, and scripts/ci-review-lanes.test.sh covers a merge-only push after a full review.
Related work
Open questions
RECOMMENDED: Fix it in ci-status: pass a lane whose status job succeeded with a no-change skip, but only after verifying the named earlier head had a counted full review. Basis: .base/.github/workflows/pr-require-checks.yml:4084
RECOMMENDED: Treat the lane side as out of scope unless the owner says the reusable workflow is editable from this repository. Basis: judgment
RECOMMENDED: Have the lane emit a marker ci-status can read, such as the skip=no-change through=<sha> record that babysit_review_evidence.py parses, and require the through sha to be an ancestor of the head with a counted run. Basis: .base/plugins/source-control/skills/babysit-prs/scripts/babysit_review_evidence.py:90
Sources read
Automated refinement by the lanes App. Answer with a comment whose first line is
**Decision recorded.**.kyle-sexton commentedon Oct 24, 2026
Broader than the no-change skip. After the review callers moved to ci-workflows v0.65.7 (#9803), a push that DOES change files also comes out
uncounted: the status job logsSKIP:empty,SKIP_REASON:empty andSUB_RESULT: skipped(theclaude-review-subscriptionjob skipped), soApply the holddoes not run and ci-status fails.plugins/app-control/skills/map/SKILL.md): pr-review run 40118074923, pr-review-security run 40118074918; ci-status run 40118074624.uncountederrors at 17:55Z.Cause UNVERIFIED: the subscription job's condition under v0.65.7. Every PR whose lanes run under that pin may be blocked from merging until it is fixed.
kyle-sexton commentedon Oct 24, 2026
Correction to my last comment: the
SUB_RESULT: skippedline is likely the normal path (the review runs in the key job), not a skipped review. The failures on #9628 b2662e7 and #9823 match melodic-software/ci-workflows#883 instead: GitHub's jobs API returned empty or partial step lists, so ci-status cannot findApply the holdand reads the lane as uncounted. At 18:0xZ the jobs API still lists only 2 steps for run 40118074923's status job. The original no-change-skip report above still stands on its own.