Skip to content

docs(agents): reap spent branches every tick and return to the default branch#2200

Draft
devantler wants to merge 5 commits into
mainfrom
claude/branch-hygiene-every-tick
Draft

docs(agents): reap spent branches every tick and return to the default branch#2200
devantler wants to merge 5 commits into
mainfrom
claude/branch-hygiene-every-tick

Conversation

@devantler

Copy link
Copy Markdown
Contributor

🤖 Generated by the Daily AI Engineer

Why

You told me I never clean up old branches, locally or on the remote, and that you expect cleanup and a
return to the default branch after every tick. You were right: nothing ever reaped them, so every tick's
branch survived it. The first sweep found ~1,140 spent branches — monorepo alone had 589 stale
local branches, and .github had 35 stale remote ones. It is noise in every branch list, and it hides
the handful of branches that actually matter.

What

Makes the sweep a standing end-of-tick duty and adds the script that does it. The one thing that makes it
safe: deleting a remote branch closes its open PR, so open-PR branches are never touched — a branch is
only reaped with positive evidence that it is spent.

Already run against the live portfolio: 1,137 branches reaped across 15 repos, zero PRs harmed, with
every deletion recorded so it can be restored.

Fixes nothing user-facing; this is agent-definition upkeep.

…t branch

Maintainer direction 2026-07-16: "You never clean up old branches locally or
on the remote. I expect you to always clean up and switch back to the default
branch after a tick."

Every tick's worktree branch survived the tick and nothing reaped it, so the
first sweep found ~1,140 spent branches (monorepo alone: 589 local; .github:
35 stale remote).

Adds branch-cleanup.sh and makes the sweep an end-of-tick duty. The safety
property is the keep-set: deleting a remote branch closes its open PR, so
open-PR heads, worktree-held branches, the default branch and non-claude/*
branches are never touched. Notably `git branch --merged main` cannot be used
here — the portfolio squash-merges, so a merged branch's commits are never in
main and the PR state is the only authoritative signal.

Verified by running it: 1137 branches reaped across 15 repos, zero open PRs
harmed (delete-set asserted to intersect open-PR heads in zero places, and
every remote deletion carries MERGED/CLOSED or >14d-no-PR evidence).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Daily AI Engineer

@codex review

1 similar comment
@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Daily AI Engineer

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8adfd16fa7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .claude/scripts/branch-cleanup.sh Outdated
Comment thread .claude/scripts/branch-cleanup.sh Outdated
Comment thread .claude/scripts/branch-cleanup.sh Outdated
Comment thread AGENTS.md Outdated
Comment thread .claude/scripts/branch-cleanup.sh Outdated
Comment thread .claude/scripts/branch-cleanup.sh Outdated
Comment thread .claude/scripts/branch-cleanup.sh Outdated
Comment thread .claude/scripts/branch-cleanup.sh Outdated
Comment thread .claude/scripts/branch-cleanup.sh Outdated
Comment thread .claude/scripts/branch-cleanup.sh Outdated
…flagged

Fetch/PR-query/manifest failures now ABORT (an empty keep-set from a failed
query would have deleted every open PR's branch); remote deletes require PR
evidence at the branch's CURRENT sha and are CAS-guarded with
--force-with-lease; the open-PR keep-set is re-fetched just before the delete
loop; the no-PR age heuristic is removed entirely (commit time is not push
time) in favour of report-only candidates; delete/checkout failures propagate
via exit 3. AGENTS.md ordering fixed: remove your own worktree BEFORE the
sweep. RED/GREEN: bogus-slug run aborts with 0 deletions; monorepo dry-run
keeps all 42 worktree/open-PR branches.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Daily AI Engineer

@codex review

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Caution

Review failed

An error occurred during the review process. Please try again later.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6bae508dd6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .claude/scripts/branch-cleanup.sh
Comment thread .claude/scripts/branch-cleanup.sh Outdated
Comment thread .claude/scripts/branch-cleanup.sh Outdated
…mmit loss, per-delete TOCTOU

PR evidence now binds to devantler-tech-owned heads (a fork PR sharing a
branch name can no longer license deleting the origin branch); local -D
requires the tip to be reachable from a remote ref (unpushed-only work is
kept and reported); and each remote deletion re-checks for a just-opened PR,
failing closed on query failure.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Daily AI Engineer

@codex review

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Caution

Review failed

An error occurred during the review process. Please try again later.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e1c85c63b8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .claude/scripts/branch-cleanup.sh Outdated
Comment thread .claude/scripts/branch-cleanup.sh
Comment thread .claude/scripts/branch-cleanup.sh
Comment thread .claude/scripts/branch-cleanup.sh
Comment thread .claude/scripts/branch-cleanup.sh Outdated
Comment thread .claude/scripts/branch-cleanup.sh Outdated
Comment thread .claude/scripts/branch-cleanup.sh
@devantler devantler closed this Jul 17, 2026
@devantler devantler reopened this Jul 17, 2026
…als, trap-based return, rejection counter

Local deletes now use update-ref -d with the expected sha (CAS) and accept
MERGED/CLOSED PR evidence at the exact sha (a squash-merged branch whose
remote ref was already pruned is remote-reachable from nothing and would
have piled up forever); return-to-default runs first AND on every abort via
the EXIT trap, which also un-keeps the tick's own checked-out branch;
remote rejections get their own surfaced counter; the evidence bound is
1000 and documented fail-closed; the final-guard residual TOCTOU window is
documented as accepted (no server-side conditional delete exists).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Daily AI Engineer

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5cf5e9eba6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .claude/scripts/branch-cleanup.sh
Comment thread .claude/scripts/branch-cleanup.sh
…ore update-ref -d

A detached start (an initialized submodule at its superproject pin) is now
left exactly as-is — checking out the default branch there silently moved
the submodule off its pin. And since update-ref -d bypasses the
checked-out-branch refusal git branch -D has, each local delete now
re-checks the live worktree list first.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Daily AI Engineer

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 436f673c2c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

# has, so re-check the live worktree list right before deleting — a
# concurrent session may have checked the branch out since the keep-set
# snapshot.
if git worktree list --porcelain 2>/dev/null | grep -Fxq "branch refs/heads/$b"; then

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Abort when worktree enumeration fails

When git worktree list --porcelain fails, such as during a transient read or worktree-metadata error, this pipeline returns nonzero and the if condition is treated as false, so execution falls through to git update-ref -d. Because that command bypasses checked-out-branch protection, the script can delete a claude/* branch active in another worktree and subsequently remove its matching closed-PR remote, leaving the live worktree with a dangling/unborn HEAD; capture and validate the worktree-list result separately and abort on failure.

Useful? React with 👍 / 👎.

Comment on lines +28 to +30
if ! git fetch origin --prune -q 2>/dev/null; then
echo "$SLUG: ABORT — git fetch failed; refusing to act on stale refs" >&2
exit 1

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restore the checkout when the initial fetch fails

When this runs from an attached claude/* checkout during a network, authentication, or origin outage, the fetch failure exits before START_BRANCH, return_to_default, and the EXIT trap are established, so the repository remains on the spent branch. That branch is then worktree-protected on the next sweep, defeating the explicit end-of-tick return-and-reap guarantee; install the checkout-restoration path before fetching while still aborting cleanup when the fetch fails.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant