Repository navigation
Two merge-facing readers treat 'no checks have run' as 'nothing is failing' #3248
Description
Same shape as #3227, found by the #3237 sweep. Both are measured with the
workflows' own jq expressions, run verbatim.
1. auto-merge-ready-prs.yml — a PR with zero checks is "Ready to merge"
MAIN_CHECKS=$(... jq '[.statusCheckRollup[]? | select(.name != ...)]')
FAILING=$(echo "$MAIN_CHECKS" | jq '[.[] | select(.conclusion != "SUCCESS" and .conclusion != "SKIPPED")] | length')
if [ "$FAILING" = "0" ]; then READY_PRS+=("$pr"); echo " Ready to merge"
Run against four inputs:
| rollup | FAILING | verdict |
|---|---|---|
absent (null) |
0 | Ready to merge |
| present but empty — no check has posted yet | 0 | Ready to merge |
one check still running (conclusion: null) |
1 | correctly skipped |
one genuine FAILURE |
1 | correctly skipped |
The pending case is handled correctly and deliberately — null != "SUCCESS" is
true in jq, so a running check counts as failing. That half is good design. The
gap is only the empty set: zero checks is zero failures, and [] | length
is 0 either way.
Severity is bounded, and I want to be accurate about it
- The trigger is
workflow_dispatchonly. It does not fire on its own. - The merge is
gh pr merge "$pr" --merge --delete-branch— no--admin—
so branch protection (4 required contexts, strict) refuses the merge.
So this does not merge anything unsafely. What it does is print "Ready to
merge" for a PR nothing has run on, then fail the merge and swallow it:
gh pr merge "$pr" --merge --delete-branch || echo " Failed to merge PR #$pr"
|| echo makes the step exit 0 whether every merge succeeded or every one
failed. A batch where nothing merged reports green.
Fix
Require the required contexts to be present, not merely non-failing — the
same repair #3227 made to tri pr ready --required-only. Minimum: refuse when
MAIN_CHECKS is empty, and let the merge's exit code reach the step.
2. pr-dashboard.yml — READY counts PRs nothing has run on, and overlaps PENDING
READY=$(... 'all(.conclusion == "SUCCESS" or .conclusion == "SKIPPED" or .conclusion == null)')
PENDING=$(... 'any(.conclusion == null)')
FAILING=$(... 'any(.conclusion == "FAILURE" or "CANCELLED" or "TIMED_OUT")')
Measured on TOTAL=1 in each case:
| rollup | READY | PENDING | FAILING |
|---|---|---|---|
| zero checks | 1 | 0 | 0 |
| one running | 1 | 1 | 0 |
| all green | 1 | 0 | 0 |
| one failure | 0 | 0 | 1 |
Two problems. all() over an empty array is true, so a PR with no checks
is READY. And or .conclusion == null puts still-running PRs in READY as
well, so the same PR is counted in READY and PENDING — the three categories
do not partition, and READY + PENDING + FAILING can exceed TOTAL.
The table is presented as a summary of all open PRs, so a reader takes the
columns as a partition. "READY" there means "nothing has failed", which
includes "nothing has run".
Same family as #3229, where a six-class tally printed five and the sum did not
match the rows.
Fix
Make READY mean ready: all required contexts present AND concluded SUCCESS or
SKIPPED. Give "no checks yet" its own column rather than folding it into READY,
and assert the columns sum to TOTAL.
Not fixed here
Both are cheap, but CI capacity is the binding constraint right now — the queue
stood at 343–378 during this pass (#3236) and each push costs 28 check-runs.
Neither defect can merge anything unsafely today: #1 is manual-dispatch and
protection-backed, #2 is a report. Sequenced behind the current batch.
User Scenarios & Testing
- Given
.github/workflows/auto-merge-ready-prs.ymlas it stands today,
when the work described above is done and the commands under Acceptance criteria are run from the repository root,
then each of those commands prints the value stated beside it.
Requirements
- FR-001: every signature already in the file MUST stay exactly as it is - the signature is the contract, and a caller elsewhere is holding it.
- FR-002: the file MUST still parse afterwards.
t27c parse .github/workflows/auto-merge-ready-prs.ymlis the check, and a spec that stops parsing generates nothing, so every test it already carried stops running too. - FR-003: no function MUST be deleted to satisfy a count.
Boundary
.github/workflows/auto-merge-ready-prs.yml
.github/workflows/pr-dashboard.yml
Activity
census: bless the three steps this PR added
census: bless the three steps this PR added (#3314)
Fix issue #3248: zero checks not considered ready in both workflows
gHashTag commentedon Oct 5, 2026
Branch queen-3248 changes nothing that runs: it appends a '# Fix applied for issue #3248' comment line to each workflow, while the real fix was already on master from #3314. It should not land; it would only add comments claiming a change it did not make. Workflow YAML is also outside what a bee may write under specs/policy/own_language.t27.
gHashTag commentedon Oct 5, 2026
Closing as done. Both findings are fixed on master 13e212a by #3314. auto-merge-ready-prs.yml skips a PR whose rollup is empty ('zero checks is not zero failures'), and a refused merge now counts as FAILED and fails the step. pr-dashboard.yml requires at least one posted check before READY and gives no-checks PRs their own NOCHECKS column, so READY and PENDING no longer overlap.
Review-jam triage 2026-10-05 (lane B): this card sat in the Queen's review column holding its file boundary. Reopen if this is wrong.