# Worktree census AND REAP — doyle's + todlando's trees on hfenduleam (2026-09-24)

## RESULT (reap executed 17:54:18–17:55:20Z)

**51 removed, 17 refused, 95 → 44 worktrees.** Every one of the 17 refusals was
`contains modified or untracked files, use --force to delete it`. No `--force` was passed
anywhere, so those trees stand: a refusal means unverified content, and the safe direction is to
leave it. They are listed in `reap-refused.txt` and want a per-tree read, not a flag.

Sizes over the reaped set (not the whole `.worktrees`): apparent **1,683,327,886**, allocated
**1,832,480,768**, escaped **0 inodes / 0 B**. This escaped zero is **VACUOUS, not forced**: the
population behind it was captured and it is EMPTY — 0 files at nlink>1, 0 distinct multi-link
inodes in the entire set. Source checkouts contain no hard links. The clause stays unexercised.

**Free-space delta: −5,368,799,232 B — free space FELL by 5.4 GB while the reap removed 1.8 GB.**
It is uninterpretable, and the writer census says why: the pre-reap census caught `cargo.exe`,
four `rustc.exe` and `Runner.Worker.exe` **in Services session 0** — a CI job (run 36035629802,
head `fe81540c`, PR #272's own run) building on this box through the whole window. This is a
CENSUSED ambiguity, which is a result; it is not an unexplained gap, and it gets no mechanism
invented for it after the fact.

**MY PROCEDURAL ERROR, recorded because it is the reusable part: I put the writer census INSIDE
the script it was supposed to gate.** The census ran first and printed the runner — but its
output only reached me when the whole job finished, minutes after the removals. A census that
reports after the action cannot gate the action; it can only annotate it. I had also told two
agents to census writers before capturing, and then took my own capture without reading mine.
Next time the census is a SEPARATE call whose result is read before the reap is launched.

The earlier estimate in this file — "expected reclaim ≈ 7.8 GB" — was **wrong as applied**: it
described reaping everything, while the evidence-based set is 68 of 95 trees and measures 1.8 GB
allocated. The 27 kept trees hold the balance. Corrected here rather than left standing.


Census only. **Nothing was deleted.** The reap is HELD until the volume has a readable
writer set (todlando's W6 cargo legs were live during the measurement; hertz's #271 PR run
takes the Windows leg after). Captured by doyle, session post-W5-landing, main `2e52677a`.

## Sizes — IR-150's three numbers, whole `.worktrees` tree

| number | bytes | command |
|---|---|---|
| apparent | 7,555,161,221 | `du -sb --apparent-size .worktrees` |
| allocated | 8,001,377,280 | `du -sB1 .worktrees` |
| escaped (inodes, bytes) | 0, 0 | `find .worktrees -type f -links +1 -printf '%i %n %s\n' \| sort \| uniq -c \| awk '$1 < $3 {n++; b+=$4} END {print n+0, b+0}'` |

Escaped 0 here is **not** the forced zero todlando measured on a cargo pool: these trees are
source checkouts, not build pools, so the multi-link population is small by construction. The
population behind it was not captured; treat the clause as UNEXERCISED, exactly as the
three prior zero-escape samples.

Expected reclaim of a full reap ≈ allocated − escaped − the live lanes ≈ **7.8 GB**.
A free-space delta was NOT taken and must not be reconstructed later: during the window
todlando's W6 build was writing the volume (measured 17:0x: 1 `cargo.exe`, 2 `rustc.exe`,
0 `Runner.Worker.exe`), so a whole-volume instrument reads uninterpretable here. Take the
delta at reap time, with a fresh writer census, or take none and claim none.

## Build pools: there are almost none

96 worktrees; only **3** carry a `target/` dir, and two of those are empty stubs:

- `304-release-note-s4/target` — 0 B
- `307-relay-journal-before-emit/target` — 146 B
- `w6-divulge/target` — 166,165,244 B and growing — **todlando's LIVE W6 lane**

So the reap's value is the checkouts themselves, not artifacts. No `pool-release` is owed by
any tree but `w6-divulge`, which is todlando's to release.

## Classification — 96 trees (95 + the main checkout, which is excluded)

| class | count | reapable | basis |
|---|---|---|---|
| DETACHED | 15 | yes | gate rigs and RCA rigs; carry no lane |
| MERGED | 30 | yes | branch is an ancestor of main (`git branch --merged main`) |
| EQUIV | 23 | yes | `git cherry main <branch>` shows 0 `+` lines — landed by squash/rebase |
| REAL | 27 | **no — decide per tree** | `git cherry` shows unlanded commits |

68 of 95 are reapable on evidence today. `git worktree list --porcelain | grep -c prunable` = 0,
so every record points at a directory that exists — none of this is pruning, all of it is removal.

Ancestry alone would have called 50 trees unlanded; the patch-id arm cut that to 27. Do not
skip it — `--merged` cannot see a squash-landed lane, and a tree deleted on that basis is
a lane deleted.

### The 27 REAL trees, with their unlanded/equivalent commit counts

Two are LIVE and must not be touched:

- `feat/331-w6-divulge` (+1) — todlando's W6 lane, activation commit unpushed
- `ci/185a-census-test-attribution` (+1) — hertz's #271, open and awaiting its run

One is an operator referral, and its tree is evidence:

- `docs/golden-head-intake` (+2) — PR #135. The +2 corroborates the standing finding: its
  content is on main as a SUPERSET, so the merge button would delete 233 ruled lines.
  Keep the tree until the operator closes the PR.

The remaining 24, all uncensused as to intent:

```
build/304-w2-bootstrap-tcp   +2      diag/302-meet-offload-field   +2
diag/302-net-worker-stamps   +2      diag/302-portmapper-off-field +3
ci/traceable-reqs-v0.4       +1      docs/register-locksmith-followups +3
docs/seam-consumers-refusal  +1      feat/autostart-emit-carrier   +1 -2
feat/emit-single-write       +3 -3   fix/206-is-locked-posture     +1 -4
fix/208-session-scoped-briefing +1 -2  fix/209-er-inbound-local-bypass +1 -1
fix/74-interior-space-runs   +1      fix/ir21-samepkg-bin-edges    +1
fix/w3-line-safety-attr      +1 -17  golden/307-v071               +1
spec/access-model            +13     spec/brain-handoff-pilot      +4
spec/brain-handoff-pilot-rebase +7   spec/sealed-code-grill        +2
test/fixture-prebuild-hardening +2   test/rig-stop-identity-scrub  +1
test/twohost-seal-barrier    +2 -7   test/w2-rig-fixups            +2
```

A mixed count (`+1 -17`) means most of the lane landed and a remainder did not — those are the
ones worth reading before removal, since the remainder is either a deliberate drop or a lost
fix. **Removing a worktree does not delete its branch**, so a tree whose branch is kept loses
nothing but the checkout. That is the cheap path for all 24: remove the tree, keep the branch,
decide the branch's fate separately and never under disk pressure.

## Procedure when the box is quiet

1. Confirm the writer set: ask every agent whether its leg WRITES this volume (not whether it
   reads the pool), and check `cargo.exe` / `rustc.exe` / `Runner.Worker.exe` on the box.
2. ~~Expect **IR-153**~~ **DONE 2026-09-24, before the quiet window, because it writes only admin
   bytes and the quiet window is the scarce resource.** 17 records carried the backslash spelling —
   exactly the 17 IR-153 left standing as "other agents'", and they are mine and todlando's.
   `git worktree repair` on all 17 at once: **rc 0, 17 `repair: gitdir incorrect` lines naming
   exactly its targets, 17/17 verified individually at 0 backslashes, repo-wide rows 17 → 0, and
   `git worktree list` now shows no `\.git` row.** Predicate controlled both ways before the call:
   the backslash grep found 17 (positive), and `w6-divulge`'s record read clean forward-slash
   (negative). Neither live lane was among them.
   Refinement for IR-153: its batched call exited **1** with 38 stderr lines about records it
   declined; naming every malformed record and nothing else exits **0** with one line per repair.
   The per-tree gate stands regardless — the rc is not what was trusted here either.
3. Capture the three sizes per tree before `rm`, then measure the reclaim against
   allocated − escaped. A gap outside the band is recorded UNEXPLAINED, never given a
   mechanism after the tree is gone.
4. Reap the worktree subtree only. Move cwd out first (todlando's W5 teardown needed that).
   `git worktree prune` after.

## Not filed on the board

This is infrastructure debt, so it belongs in `docs/INFRA-REGISTER.md`, never the
spt-bs-releases board. The register entry is deliberately NOT opened as its own docs PR while
two lanes are in flight — it rides the next docs lane, pointing here.
