---
name: worktree-pin-holder-triage
description: "A pinned worktree dir has two holder classes — an orphan surviving descendant process (kill) vs a LIVE agent's own persistent shell cwd (cd out); the blocked-delete error looks identical, and killing the second ends your own session."
metadata: 
  node_type: memory
  type: feedback
  originSessionId: 67bc78b2-3745-47a8-885a-91376d8e3b69
  modified: 2026-08-02T09:30:10.408Z
---

A directory that is some process's **current directory** cannot be deleted or renamed, while files
inside it stay writable — so it never looks like a file lock. That is the `.worktrees` pin class
(hertz's diagnosis, 2026-08-01): cargo runs test binaries with cwd = the package root, a console child
inherits it — and so does every grandchild; any descendant that survives the kill pins the dir.
(Mechanism corrected 2026-08-02: the holder is a surviving DESCENDANT, never the conhost, whose cwd is
OS-assigned `C:\WINDOWS` — see [[orphan-conhost-cwd-pins-worktree]].)

**Find the holder** with hertz's read-only PEB reader (`NtQueryInformationProcess` → PEB+0x20 →
RTL_USER_PROCESS_PARAMETERS+0x38); no Sysinternals needed, modifies nothing:
`find-cwd-holders.ps1 -Match worktrees`.

**But the finder answers "who pins this", NOT "is it safe to kill" — those are different questions.**
Two holder classes produce the *identical* "used by another process" error:

1. **Orphan descendant** (parent pid DEAD, e.g. a stray `PING.exe`/`cmd.exe` a test spawned) → kill.
   Verify the profile before firing: parent dead, headless, no children. Then `Stop-Process -Force`.
2. **A live process — above all an agent's own tool shell** → `cd` out; do NOT kill. My doc worktree
   was pinned by `pwsh`, my own PowerShell tool session, because its working directory persists
   between calls and I had `Set-Location`'d there to build. Pattern-matching the conhost one-liner
   onto it would have killed my own session mid-task. A second holder sat behind it: the **Bash tool
   keeps an independent persistent cwd**, so the dir stayed blocked until that shell moved too.

**How to apply:** read the holder's identity before acting, every time; never fire a kill recipe at a
pid someone routed you without re-verifying the profile yourself. When *you* are the holder, the fix
is free — move both shells out (`cd` in Bash and `Set-Location` in PowerShell are separate cwds), then
delete. Prove the mechanism with two arms rather than asserting it: attempts blocked N/N before, clean
first-try after.

Also: `git worktree remove` failing with `Permission denied` still leaves the branch ref intact —
removing a worktree never endangers its commits. Verify with `git worktree list` after `prune` and
confirm the shas are ancestors of `origin/main` before removing anything.

Related: [[worktree-target-junction]], [[reap-subtree-not-session-dir]], [[live-agents-lock-target-debug-spt-exe]].
