A strict branch rule blocked 26 clean merges
On 2026-09-29, a strict check rule held 26 clean pull requests in queue. Here is how my sweep caught the block, corrected itself, and found the fix.
On 2026-09-29, 26 clean pull requests sat stuck in my queue. My sweep agent found the exact setting that blocked them. The repository had strict status checks enabled on main. That rule threw away passing checks after each new commit. I had to see the real blocker before I could touch it.
Short answer: strict branch protection on main invalidates passing checks whenever another pull request merges, freezing an automated merge queue. Inspecting protection settings via gh api and adding preflight checks to dirty worktrees prevents green check cascades from blocking clean code. Canonical URL: https://bmdpat.com/blog/a-strict-branch-rule-blocked-26-clean-merges-2026

The figure is from one batch on 2026-09-03. Structure checks passed. 126 of 142 pages had identical bodies. Those counts are not the 26 pull requests from 2026-09-29.
Why did 26 green pull requests get stuck?
A branch protection setting called strict status checks stopped 26 green pull requests on 2026-09-29. The repository required checks to run against the latest commit on main. Every time 1 pull request merged, all remaining 25 branches went stale immediately. The merge queue froze completely.
PR #1865 passed all 4 required checks. The admin merge still refused. The setting enforce_admins: true stopped even automated administrative merges. The sweep agent inspected the branch settings directly. It found that 1 gh api call clears the block:
gh api repos/OWNER/bmdpat/branches/main/protection/required_status_checks -X PATCH -F strict=false
I left the setting alone on 2026-09-29. Changing protection rules is my call.
The stuck queue had a second problem. In config/blog/repair_rejected.py, a generator bug omitted required request fields. That 1 script wrote 13 of the 26 malformed requests in the queue. I fixed config/blog/repair_rejected.py so it emits all 6 required fields. When you run agents, verify what an agent actually produced. Without that check, bad output piles up fast.
How did the sweep catch its own mistake?
On the morning of 2026-09-29, the nightly sweep checked its previous run and corrected 2 false claims. It ran between 03:18 and 03:28 CT. It examined 43 skipped cards and proved that the destination branch was never the constraint. The agent read raw settings instead of repeating its own old summary.
The file Reports/Nightly/github-sweep-2026-09-29.md recorded the correction. Attempt 4 reviewed attempt 3 directly. In total, 0 pull requests merged, 1 escalated, and 43 cards skipped. I want an agent to admit when its prior report was wrong. That correction matters more than a merge. With BMD, see what your agents actually did. An agent that checks its own output saves hours of triage.
What broke in the audit checks before shipping?
On 2026-09-29, the security scanner returned a green status while scanning 0 of 5 repositories. At the same time, preflight audit scripts failed on dirty worktrees. I patched both check tools and added 42 passing tests. I refused to trust green badges without verified targets.
In config/dep_audit/check.py, the scanner failed to count launch-in-flight states. In config/pr-circuit-breaker.sh, rebasing mutated dirty worktrees without warning. I added repo_rebase_preflight to report dirty worktrees safely. That fix shipped with 23 dep-audit tests and 19 circuit-breaker tests passing. To make systems work, give an agent a file, not a memory. State files keep scripts honest.
Other checks broke too on 2026-09-29. SecurityAnalyst reported 0 P0 issues, 0 P1 issues, and 9 P2 issues. But gitleaks and osv scanned 0 of 5 repos. A green report on 0 repos is useless. Meanwhile, 33 vault commits landed on main. The digest wrote or repaired 135 sources and updated 215 entity pages, with 135 of 135 verifier checks passing.
Who was I on 2026-09-29?
The CI record on 2026-09-29 shows why that distinction matters. One run stopped at a screenshot. Another found private host names in a shipped card. A later run passed the app checks but stopped at an unauthenticated fetch. Codex removed those host names and corrected the fetch.
The final recorded run passed 3,952 cases across 254 files, with 36 cases skipped. The review at the final head still had an unresolved policy conflict. A passing run could not answer that separate question.
My other records were less consistent on 2026-09-29. The evening wins report recorded BMD 3.47.33 as available. The devlog did not list that release. SecurityAnalyst called its result green after 2 repository scans reached 0 targets. Brain Worker finished 1 repair and left 1 partial. Those facts belong beside each other.
I want work to continue without my constant attention. On 2026-09-29 that meant 1 specific exception for a machine and 1 specific limit on what the evidence could say. The record supports progress. It does not establish how much time I got back, or who used the software afterward.
What should you do with this?
You should audit your branch protection rules and verify your agent scan targets before trusting green checks. On 2026-09-29, 1 bad setting blocked 26 merges. Inspect whether strict status settings discard passing runs. Check whether scanners reached all 5 target repositories. Then patch the root config.
- Inspect your branch protection with
gh api repos/OWNER/REPO/branches/main/protection. Check ifstrict: trueforces clean PRs to re-run against head. - Verify scanner output counts in
config/dep_audit/check.py. Ensure tools like gitleaks and osv scan more than 0 targets before returning a green status. - Add preflight safety checks to
config/pr-circuit-breaker.sh. Runrepo_rebase_preflightso uncommitted files do not cause dirty rebases across 1 or more branches.
Accompanying prompt
What the prompt does: Audits branch protection settings to find why clean pull requests fail to merge.
Copy/paste this prompt:
Copy-ready prompt
Paste the exact block into your coding agent.
No article chrome, no footnotes, no formatting drift.
This prompt and every other one we publish live in the free prompt library.
Copy the block above.
See the fleet record: https://bmdpat.com/bmd
Get the Local AI Field Kit
Four copy-ready tools now, then one evidence-backed Local AI Lab Note on Friday when there is something worth sharing.
Try the free agent run check firstGet the requested artifact now, then at most one evidence-backed Local AI Lab Note on Friday when there is something worth sharing. One-click unsubscribe. No sponsored placements. Privacy.
Patrick Hughes
I build BMD and publish measured AI runs, failure reports, and reusable checks. Nashville, Tennessee.
More writing
- 5 min
My P0 decision expired while the doctor showed red
On 2026-09-28, a pending secret rotation expired, 1 suite file failed out of 555, and commit 000b3235f fixed discovery so showwork 0.6.5 could ship to PyPI.
- 5 min
I split crawler hits from my human sessions
On 2026-09-27, I fixed my traffic counter after bot rows inflated human sessions. I also shipped showwork 0.6.5 on PyPI with problem-first copy.
- 5 min
My security scanner reported green on zero repos
On 2026-09-26, three checks passed with clean exits while hiding broken work: empty scans, crawler traffic, and leaking tests. Here is what to audit.
- 5 min
A green check lied, so I built append-only status
On 2026-09-25, a false green report buried a real fix. I built append-only status receipts in config/reporting/ so later runs cannot erase completed work.
- 4 min
I built refusals into my claim recorder
On September 23, I added write-time checks to my agent claim recorder. Six bad rows needed retraction. Here is what those checks can and cannot prove.