# RD-15 — Remove the 22 abandoned agent worktrees Status: done Source: PLAN.md 2.1 ## Why `.claude/worktrees/` holds **22 abandoned agent checkouts totalling 4.7 GB**, left behind by past agent runs. They are gitignored (`.gitignore:64`), so they never reach a commit — but they are on disk, and every unqualified repository-wide `grep -r` or `find` walks all 22 copies of the source tree. That is a real tax on every future search, by a person or an agent, and it is larger than it looks. Measured: | | files | | -------------------------------- | ---------- | | under `.claude/worktrees/` | **48,005** | | tracked in the actual repository | **856** | An unqualified `grep -r` or `find` therefore walks **56× more files than the repository contains**. This ticket removes the cause; the `git grep` habit in the ticket-authoring rules above handles the symptom. ## Read first - `.gitignore:64` — confirms the directory is ignored - `git worktree list` — 23 entries: the main working tree plus the 22 to remove - The verification block below. **Run it before removing anything.** ## Decisions (pre-made, don't relitigate) 1. **Use `git worktree remove`, never `rm -rf`.** These are **live registered git worktrees**, not orphaned directories — each has a real `worktree-agent-` branch. An `rm -rf` leaves 22 broken registrations behind in `.git/worktrees/`, which is worse than the disk usage. This correction was made while executing RD-01, where the original plan assumed they were plain directories. 2. **Delete each `worktree-agent-*` branch too**, after removing its worktree. A worktree removal does not delete the branch it had checked out, and 22 stale branches in `git branch` are their own kind of noise. 3. **Finish with `git worktree prune`** to clear any leftover administrative entries. 4. **Re-verify before removing, even though it was verified when this ticket was written.** This is the only destructive ticket in the arc. Both gates passed at authoring time — all 22 branch tips are ancestors of `main` (the RB-01..RB-33 arc was merged in `637d500`), and all 22 working trees are clean. **If either gate fails for any worktree, stop and report it; do not use `--force`.** 5. **This ticket changes no tracked file.** Its commit contains only this ticket file and the README row. That is correct and expected — the work is entirely in gitignored paths and local branch refs. ## Files - `docs/project/readable-codebase/RD-15-remove-abandoned-worktrees.md` (this file) - `docs/project/readable-codebase/README.md` (the RD-15 row) No source files. No configuration. `.gitignore` is already correct and must not change. ## Steps 1. Run the verification block below. Do not proceed unless it reports `unmerged: 0` and `dirty: 0`. 2. For each worktree: `git worktree remove .claude/worktrees/`. 3. For each branch: `git branch -d worktree-agent-` (lowercase `-d`, which refuses to delete anything unmerged — that is a second safety net, so do **not** use `-D`). 4. `git worktree prune`. 5. Confirm `.claude/worktrees/` is gone or empty. 6. Update this ticket's `Status:` to `done` and the README's RD-15 row to `done`. 7. Commit. ## The verification gate — run this first ```bash cd /home/eho/repos/atomic-design-poc unmerged=0 for b in $(git branch --list 'worktree-agent-*' --format='%(refname:short)'); do git merge-base --is-ancestor "$(git rev-parse "$b")" main 2>/dev/null \ || { echo "UNMERGED: $b"; unmerged=$((unmerged+1)); } done dirty=0 for d in .claude/worktrees/agent-*; do [ -d "$d" ] || continue out=$(git -C "$d" status --porcelain 2>/dev/null | grep -v '^?? node_modules') [ -z "$out" ] || { echo "DIRTY: $(basename "$d")"; dirty=$((dirty+1)); } done echo "unmerged: $unmerged dirty: $dirty" ``` Expected, and what was measured when this ticket was written: `unmerged: 0 dirty: 0`. ## Acceptance criteria ```bash git worktree list | wc -l # MUST be 1 (the main tree only) git branch --list 'worktree-agent-*' | wc -l # MUST be 0 ls .claude/worktrees 2>/dev/null | wc -l # MUST be 0 du -sh .claude 2>/dev/null # was 4.7G under worktrees/ ``` The repository is still intact — this is the check that matters after a destructive step: ```bash git status --short # only the two doc files git log --oneline -1 # HEAD unchanged from before your removals npm run ci # exits 0 ``` Show the payoff, since it is the reason for the ticket: ```bash find .claude/worktrees -type f 2>/dev/null | wc -l # was 48005 -> MUST be 0 git ls-files | wc -l # unchanged: 856 tracked files ``` ## Verification `npm run ci`. No source file changes, so `--full` is not required — but run plain `ci` anyway, because removing worktrees touches `.git` administrative state and the point is to prove the repository is unharmed. ## Out of scope - `.gitignore` — already correct at line 64. - Any worktree that fails a gate. Report it instead (decision 4). - Preventing future accumulation. Worth doing, but it is a change to how agents are launched, not a cleanup, and no ticket covers it yet. Note it as a follow-up. ## Risks - **This is the arc's only destructive ticket.** The two gates in decision 4 are what make it safe. Run them, and stop on any failure. - **`git branch -d`, never `-D`.** Lowercase refuses unmerged branches, which duplicates the first gate at the moment of deletion. If `-d` refuses a branch, that branch has commits not in `main` — stop and report it. - **`git worktree remove` refuses a dirty worktree** unless forced. Do not force. A refusal means the second gate missed something. - **Do not delete `node_modules` anywhere else** while cleaning up. The verification block deliberately ignores untracked `node_modules` inside a worktree, because that is build output, not work.