Problem
After every merge the loop accumulates branches indefinitely:
- This session: 115+ branches on hadamrd/forge-loop, 46 still on remote after merges.
- Loop already uses
gh pr merge --squash --auto --delete-branch on its auto-merge path, but NOT all merge paths go through that — and the local branch in the operator's checkout never gets deleted.
- Operator must manually run
git push origin --delete <br> loops + git branch -D loops. Painful + error-prone (one slip and a non-merged branch dies).
Acceptance
- Per-merge cleanup (already partial): every successful auto-merge MUST delete the remote branch. Add the same to admin-merge and rescue-merge paths.
- Per-tick sweep: every Nth tick (default 20), call the new sweep:
- List remote branches matching
loop/*, feat/*, fix/*, refactor/*, chore/*, test/*, docs/*.
- For each: query the GitHub API for the PR. If state is MERGED or CLOSED (and > 7 days old, configurable), delete the remote branch via
gh api -X DELETE.
- Local branch cleanup: any branch with no remote tracking ref + last commit older than 30 days → delete.
- Emit typed event
branch_sweep_done with counts (deleted/skipped/error).
forge-loop sweep branches CLI command for manual runs.
Test plan
- Unit: mock GhClient with mixed MERGED/CLOSED/OPEN PRs; assert correct delete calls.
- Adversarial: a branch with no PR at all (orphan) — don't crash, log + skip.
- Adversarial: gh API rate limit during sweep — back off + resume, don't hammer.
- Regression: a branch that has an OPEN PR is NEVER deleted.
File pointers
src/forge_loop/branch_sweep.py (new)
src/forge_loop/runner/tick.py — call sweep on the maintenance_every_n_ticks cadence
src/forge_loop/cli.py — sweep branches subcommand
src/forge_loop/settings.py — maintenance.branch_sweep_every_n_ticks (default 20), maintenance.branch_min_age_days (default 7)
tests/test_branch_sweep.py (new)
Customer story
A platform team runs forge-loop on their repo for a week. Without this, they have 200+ stale branches in their list. With this, the branch list stays clean — only OPEN PRs and the default branch.
Problem
After every merge the loop accumulates branches indefinitely:
gh pr merge --squash --auto --delete-branchon its auto-merge path, but NOT all merge paths go through that — and the local branch in the operator's checkout never gets deleted.git push origin --delete <br>loops +git branch -Dloops. Painful + error-prone (one slip and a non-merged branch dies).Acceptance
loop/*,feat/*,fix/*,refactor/*,chore/*,test/*,docs/*.gh api -X DELETE.branch_sweep_donewith counts (deleted/skipped/error).forge-loop sweep branchesCLI command for manual runs.Test plan
File pointers
src/forge_loop/branch_sweep.py(new)src/forge_loop/runner/tick.py— call sweep on themaintenance_every_n_tickscadencesrc/forge_loop/cli.py—sweep branchessubcommandsrc/forge_loop/settings.py—maintenance.branch_sweep_every_n_ticks(default 20),maintenance.branch_min_age_days(default 7)tests/test_branch_sweep.py(new)Customer story
A platform team runs forge-loop on their repo for a week. Without this, they have 200+ stale branches in their list. With this, the branch list stays clean — only OPEN PRs and the default branch.