Summary
Destroying a managed worktree removes the checkout and its Git worktree metadata but leaves the generated bb/<slug>-<threadId> local branch in the source repository. The worktree guide promises that the branch is removed with the worktree, so every completed managed environment currently leaves a permanent branch behind.
Versions and environment
- bb 0.40.0 from source at
f4bbc2fe81a9b7639ff9a7396e172bddd89109e4 (origin/main)
- macOS 27.0, Apple silicon
- Node.js 22.19.0
- Local host, fresh dev data directory, managed worktree environment
- Provider: codex CLI 0.151.0; provider choice is not involved in cleanup
Steps to reproduce
-
Create a scratch Git repository and register it as a project:
repo=$(mktemp -d /tmp/bb-managed-branch-repro.XXXXXX)
git -C "$repo" init -b main
git -C "$repo" config user.name "BB Repro"
git -C "$repo" config user.email bb-repro@example.com
touch "$repo/README.md"
git -C "$repo" add README.md
git -C "$repo" commit -m initial
project_id=$(bb project create --name "Managed branch cleanup repro" --root "$repo" --json | jq -r .id)
-
Spawn a thread in a managed worktree, then wait for it to become idle:
thread_id=$(bb thread spawn --project "$project_id" --new-environment worktree --provider codex --permission-mode accept-edits --title "Branch cleanup repro" --prompt "Reply only with ok." --json | jq -r .id)
bb thread show "$thread_id" --json
-
Record the generated branch, archive the thread, and wait until its environment reaches destroyed after the managed-environment retirement grace and cleanup sweep:
branch=$(bb thread show "$thread_id" --json | jq -r .environment.branchName)
bb thread archive "$thread_id" --json
bb thread show "$thread_id" --json
-
Inspect the source repository:
git -C "$repo" worktree list --porcelain
git -C "$repo" branch --list "$branch"
The smallest direct reproduction is the same createWorktree → removeWorktree sequence in @bb/host-workspace; no provider process is required for the leak.
Expected vs actual
Expected after environment status becomes destroyed:
$ git -C "$repo" worktree list --porcelain
worktree /private/tmp/bb-managed-branch-repro.BDoFHZ
HEAD 35593bf58c11ea9e593760e003feb05206f10971
branch refs/heads/main
$ git -C "$repo" branch --list 'bb/branch-cleanup-repro-thr_wzberxex69'
Actual:
$ git -C "$repo" worktree list --porcelain
worktree /private/tmp/bb-managed-branch-repro.BDoFHZ
HEAD 35593bf58c11ea9e593760e003feb05206f10971
branch refs/heads/main
$ git -C "$repo" branch --list 'bb/branch-cleanup-repro-thr_wzberxex69'
bb/branch-cleanup-repro-thr_wzberxex69
The managed worktree is gone, but its local branch remains.
Evidence
What you ruled out
Suggested priority and effort (optional)
Medium — affects every successfully destroyed managed worktree and accumulates stale refs indefinitely; manual git branch -D is the only cleanup workaround. The fix is localized to host-workspace destruction but needs detached-HEAD and non-fatal deletion-failure handling.
Checks
AGENT GENERATED
Summary
Destroying a managed worktree removes the checkout and its Git worktree metadata but leaves the generated
bb/<slug>-<threadId>local branch in the source repository. The worktree guide promises that the branch is removed with the worktree, so every completed managed environment currently leaves a permanent branch behind.Versions and environment
f4bbc2fe81a9b7639ff9a7396e172bddd89109e4(origin/main)Steps to reproduce
Create a scratch Git repository and register it as a project:
Spawn a thread in a managed worktree, then wait for it to become idle:
Record the generated branch, archive the thread, and wait until its environment reaches
destroyedafter the managed-environment retirement grace and cleanup sweep:Inspect the source repository:
The smallest direct reproduction is the same
createWorktree→removeWorktreesequence in@bb/host-workspace; no provider process is required for the leak.Expected vs actual
The managed worktree is gone, but its local branch remains.
Evidence
thr_wzberxex69, environmentenv_x8skdy9bid, and projectproj_8myi5vfrh6in a fresh local dev instance. To avoid waiting for the five-minute unarchive grace during the source repro, I backdated onlyretire_requested_atand restarted the server; the normal destroy command then completed and set the environment todestroyed.removeWorktreeresolves the common Git directory and runsgit worktree remove, but never deletes the checked-out branch.What you ruled out
origin/mainatf4bbc2fe81a9b7639ff9a7396e172bddd89109e4.worktree branch,delete branch worktree, andbranch archive worktreefound no issue for this cleanup failure.Suggested priority and effort (optional)
Medium — affects every successfully destroyed managed worktree and accumulates stale refs indefinitely; manual
git branch -Dis the only cleanup workaround. The fix is localized to host-workspace destruction but needs detached-HEAD and non-fatal deletion-failure handling.Checks
main, or I say above that I could not.> AGENT GENERATEDand links the thread or report.