---
name: worktree-remnant-pinned-at-crates-spt-daemon
description: "Two independent signet-era worktree teardowns (doyle gate-signet-w1, todlando signet-w1) both left a remnant pinned by a live handle at exactly crates/spt-daemon — same subpath, same day (2026-08-25). Holder NAMED 2026-09-08 (rust-analyzer pid 47316): three more instances, promoted to mechanism — rust-analyzer holds a dir handle at the watched crate dir, the 0-byte remnant is not worth a force."
metadata: 
  node_type: memory
  type: project
  originSessionId: c0945444-626d-41ff-87fa-e231e710c441
  modified: 2026-08-25T06:17:09.321Z
---

Two worktree removals on 2026-08-25, independent agents, both stuck at the SAME subpath:

- doyle: `git worktree remove .worktrees/gate-signet-w1` → "Permission denied"; retry via
  `Remove-Item -Recurse -Force` → "cannot access ... crates\spt-daemon: being used by another
  process". Full checked-out tree remains; git metadata pruned. No process BINARY resides under
  the worktree (Get-Process Path scan empty) ⇒ pin is a handle, likely a cwd.
- todlando: same day, `.worktrees/signet-w1` unregistered, all files gone EXCEPT one EMPTY dir
  `crates/spt-daemon` — "Device or resource busy". No pool, no files.

**Why:** something live on HFENDULEAM holds a directory handle at `<worktree>\crates\spt-daemon`
specifically — two instances, same node, is a pattern wearing a coincidence's clothes. Neither
holder was hunted (see [[no-diagnostics-in-identity-blast-radius]]); both slated for retry-later
per the worktree mandate ("retry later if a handle pins it").

**How to apply:** a worktree remove refusing at `crates/spt-daemon` is this class — do NOT kill
candidate processes to free it (spt.exe hosts are live agents), just leave the remnant and retry
after the next daemon/agent cycle. If a THIRD instance appears, promote this from pattern to
mechanism and find the holder deliberately (e.g. after a planned daemon restart, check whether the
pin releases). See [[live-agents-lock-target-debug-spt-exe]] for the adjacent exe-lock class.

## 2026-09-08 — THIRD, FOURTH and FIFTH instance; holder NAMED

todlando, reaping `.worktrees/ws272-w0`, `ws272-w1`, `ws272-w2` under doyle's word. All three
refused at exactly `crates/spt-daemon`: `rm: cannot remove '.worktrees/ws272-wN/crates/spt-daemon':
Device or resource busy`. Each dir was 0 files / 0 bytes — nothing but the empty chain
`<worktree>/crates/spt-daemon` — and unregistered in git (the sibling `ws272-w3-drift`, a FULL
checkout, deleted without complaint in the same loop).

**Holder found, cheaply, no blast radius:** `Get-Process | ? ProcessName -match 'rust-analyzer'`
→ pid 47316 `rust-analyzer` and pid 23440 `rust-analyzer-proc-macro-srv`, both started
2026-09-07 03:50. Nothing spt-hosted was involved, so the 2026-08-25 caution
([[no-diagnostics-in-identity-blast-radius]]) never applied to this class — a one-command
ProcessName census would have named it then too.

Promoted from pattern to **mechanism**: rust-analyzer indexes every worktree under the project
root and holds a directory handle at the crate dir it is watching; the handle outlives the files,
which is why the remnant is always an EMPTY `crates/spt-daemon`.

**How to apply (supersedes the retry-later advice above):** the remnant is 0 bytes — it costs
nothing and it is not a disk-floor input. Do NOT kill the editor server to delete 0 bytes; doyle
ruled the same 2026-09-08 ("a git refusal halts, it does not authorise a force"). Name the holder
in the report so the next reader does not re-hunt it, leave the dirs, and let them go with the
next rust-analyzer restart.
