Background
Lesson banked in dotclaude/CLAUDE.md (2026-05-12 burn on techrecon#147) framed this as:
claude-author-automerge.yml's update-branch step rebased the install PR (merged main into the feature branch via github-actions[bot]), advancing HEAD SHA from 360d460 to 2b942bd. ... claude-author-automerge would need a PAT for the branch-update push.
On closer inspection, there is no update-branch step in claude-author-automerge.yml. The merge commit attributed to github-actions[bot] is generated by GitHub's server-side auto-merge service, which kicks in automatically when a PR with gh pr merge --auto enabled has stale base. That service:
- Uses
GITHUB_TOKEN (no caller override possible)
- Subjects all spawned pushes to GitHub's recursion-prevention rule (no
pull_request workflows fire on the new SHA)
- Result: PR sits
BLOCKED with empty check rollup forever
What does NOT fix this
- Adding
secrets.automerge_pat to the Enable auto-merge step — doesn't help, the bad rebase happens server-side AFTER auto-merge is enabled, not in our workflow
- Pre-rebasing with PAT before enabling auto-merge — only solves the "PR opened against stale base" case; doesn't help if base advances AFTER our workflow finishes
Three architectural fix options
Option A — Proactive rebase on push:main
Add on: push: branches: [main] trigger to claude-author-automerge.yml. For every open Claude-authored PR with a stale base, force-update with PAT. Keeps branches fresh proactively. Drawback: bursty load when many PRs are open + main moves rapidly.
Option B — Reactive self-heal on stuck PRs
New workflow claude-pr-self-heal.yml triggered on check_suite: completed. When it detects mergeStateStatus=BLOCKED + empty rollup + last commit by github-actions[bot], push an empty user-attributed commit using PAT. This is the canonical manual workaround, just automated. Drawback: reactive — PR sits stuck for one check_suite cycle before self-healing.
Option C — Replace gh pr merge --auto with merge-when-ready
Don't use GitHub's auto-merge service. Add a workflow that listens to check_run: completed / check_suite: completed events, polls all required-check states, and calls gh pr merge --squash directly (with PAT) when everything is green. Eliminates GitHub's auto-merge service from the critical path entirely. Drawback: larger architectural shift; ~100+ lines of new workflow; more failure modes to test.
Current workaround
Push an empty user-attributed commit to the stuck branch:
git clone --depth 5 --branch <branch> https://github.com/<repo>.git
cd <repo>
git commit --allow-empty -m "ci: retrigger"
git push
Documented in lesson #235 in dotclaude/CLAUDE.md.
Recommendation
Option B is the smallest viable fix and matches what we already do manually. Open this issue and accept the latency cost (one check_suite cycle before self-heal). Options A and C are bigger lifts that can come later if Option B proves inadequate.
Not blocking — manual workaround works fine for low-frequency occurrence. The lesson on dotclaude/CLAUDE.md gives the diagnosis pattern (BLOCKED + empty rollup + github-actions[bot] last commit). Filing this issue so the architecture decision is captured for whoever picks this up next.
🤖 Auto-filed during test-ratchet Wave 2 close-out
Background
Lesson banked in
dotclaude/CLAUDE.md(2026-05-12 burn on techrecon#147) framed this as:On closer inspection, there is no
update-branchstep in claude-author-automerge.yml. The merge commit attributed togithub-actions[bot]is generated by GitHub's server-side auto-merge service, which kicks in automatically when a PR withgh pr merge --autoenabled has stale base. That service:GITHUB_TOKEN(no caller override possible)pull_requestworkflows fire on the new SHA)BLOCKEDwith empty check rollup foreverWhat does NOT fix this
secrets.automerge_patto theEnable auto-mergestep — doesn't help, the bad rebase happens server-side AFTER auto-merge is enabled, not in our workflowThree architectural fix options
Option A — Proactive rebase on push:main
Add
on: push: branches: [main]trigger to claude-author-automerge.yml. For every open Claude-authored PR with a stale base, force-update with PAT. Keeps branches fresh proactively. Drawback: bursty load when many PRs are open + main moves rapidly.Option B — Reactive self-heal on stuck PRs
New workflow
claude-pr-self-heal.ymltriggered oncheck_suite: completed. When it detectsmergeStateStatus=BLOCKED+ empty rollup + last commit bygithub-actions[bot], push an empty user-attributed commit using PAT. This is the canonical manual workaround, just automated. Drawback: reactive — PR sits stuck for one check_suite cycle before self-healing.Option C — Replace
gh pr merge --autowith merge-when-readyDon't use GitHub's auto-merge service. Add a workflow that listens to
check_run: completed/check_suite: completedevents, polls all required-check states, and callsgh pr merge --squashdirectly (with PAT) when everything is green. Eliminates GitHub's auto-merge service from the critical path entirely. Drawback: larger architectural shift; ~100+ lines of new workflow; more failure modes to test.Current workaround
Push an empty user-attributed commit to the stuck branch:
Documented in lesson #235 in
dotclaude/CLAUDE.md.Recommendation
Option B is the smallest viable fix and matches what we already do manually. Open this issue and accept the latency cost (one check_suite cycle before self-heal). Options A and C are bigger lifts that can come later if Option B proves inadequate.
Not blocking — manual workaround works fine for low-frequency occurrence. The lesson on dotclaude/CLAUDE.md gives the diagnosis pattern (
BLOCKED+ empty rollup + github-actions[bot] last commit). Filing this issue so the architecture decision is captured for whoever picks this up next.🤖 Auto-filed during test-ratchet Wave 2 close-out