chore: remove 22 abandoned agent worktrees (RD-15)

The repository carried 22 abandoned agent worktrees under
.claude/worktrees/, left behind by past agent runs. They are
gitignored, so they never reached a commit, but they stayed on disk
and every unqualified repository-wide grep or find walked all 22
copies of the source tree.

Measured before: 48,005 files under .claude/worktrees/, against 856
tracked in the repository. An unqualified search walked 56 times more
files than the repository contains.

The verification gate confirmed both safety conditions before removal:
all 22 worktree-agent-* branch tips were already ancestors of main, and
all 22 worktrees were clean (unmerged: 0, dirty: 0).

Removal steps:
- git worktree remove for each of the 22 worktrees (no rm -rf, so the
  registrations in .git/worktrees/ stay consistent)
- git branch -d for each worktree-agent-* branch (lowercase -d, so an
  unmerged branch would block deletion instead of being force-deleted)
- git worktree prune to clear administrative entries

Measured after: 0 files under .claude/worktrees/, .claude/ shrank from
4.7 GB to 72 KB. The 856 tracked files are unchanged. HEAD is unchanged
from before the removals. npm run ci exits 0.

This ticket changes no tracked source file. The diff is this ticket
file and the README row, because the work is entirely in gitignored
paths and local branch refs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
eho
2026-09-04 18:48:52 +02:00
co-authored by Claude Sonnet 5
parent c45d1bc0ff
commit fb7b531fdf
2 changed files with 143 additions and 1 deletions
@@ -0,0 +1,142 @@
# 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-<hex>` 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/<name>`.
3. For each branch: `git branch -d worktree-agent-<hex>` (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.
+1 -1
View File
@@ -109,7 +109,7 @@ two. Note that RD-15 exists because 22 abandoned agent worktrees are still on di
| RD-12 | `ActionState` becomes `action` on `BriefState.Loaded` | 11 | | done |
| RD-13 | Same for org-template, folding `pendingPublish` in | 12 | | done |
| RD-14 | Move `SaveState` to `debounced-save.ts`; delete `action-state.ts` | 13 | | done |
| RD-15 | Remove 22 abandoned agent worktrees (4.7 GB) | 01 | | todo |
| RD-15 | Remove 22 abandoned agent worktrees (4.7 GB) | 01 | | done |
| RD-16 | `parseDashboardView` returns `BigProfile`; delete `DashboardView` | 01 | | todo |
| RD-17 | `successOf`/`successOr` sweep — 10 sites, 8 files | 01 | | todo |
| RD-18 | Ticket-reference sweep, frontend — 181 refs, 100 files | 01 | | todo |