Twinned from https://github.com/cfsh/ninefold/issues/769 by tools/beads/import_github.py's reconcile pass.
Found by nf-cto while operating the fleet, and corroborated independently in three reaped session transcripts. Filed unclaimed so it does not die in a transcript; surfaced during the #733 design round (design_docs/006, §2.12.6).
1. A session that removes its own worktree does not exit. nf-cto, verbatim:
> "Three separate sessions (reaper, f5-owner, design-tier) removed their own worktree as their last act and then didn't exit. I found live ~500MB processes with /proc/<pid>/cwd reading (deleted) at every single reap tick — a 'wrapped, ready for reset' state that was actually a zombie holding RAM. I had to detect and kill this by hand, every time, because nothing else would."
So the documented terminal state (wrap_up.py --remove → "wrapped, ready for reset") leaves a ~500 MB process per session alive with a deleted cwd, and the only thing that notices is a human operator looking at /proc.
2. git worktree remove silently leaves the directory behind when it holds gitignored output (a session's probe_out/), discovered only by noticing a stray directory during a later reconcile.
The moment wrap_up.py --remove deletes the worktree it is running from, the next Bash call in that session errors at the harness level — Working directory "/root/nf/devs/probe-gate" was deleted; shell cwd recovered to "/root" / pwd: error retrieving current directory: getcwd: cannot access parent directories. Seen in probe-gate and session-state. The tool pulls the rug out from under its own caller's shell as its last act, which is also why nothing downstream of it runs.
Both halves are the same class, and it is the class the fleet reported as its most common real defect (design 006 §2.12.6): a tool that finishes silently without actually finishing. Nothing is claimed until it is true (DEV_PRINCIPLES D2) is the rule being violated, and wrap_up.py is otherwise the best-designed reporter in the tier — it is the one tool that already states the bounds of its own knowledge (*"Not checked here — no tool on this box can see them"*).
Related but distinct: #731 / #736 (Gh.pr_list(head=) makes wrap_up.py exit 1 after a clean removal, so branch cleanup has never run). That is a wrong exit code on a run that worked; this is a right-looking exit on a run that didn't finish.
Unclaimed and unlabelled — backlog.
None.
No comments.