Dispose currently exits pi, runs a detached teardown script, and relaunches in the main checkout. All of that exists for one reason: the process is standing inside the directory it must delete.
An in-process switch inverts the ordering and removes the reason.
Shape worth trying
- Switch to a session whose cwd is the main checkout
- Tear down from the replacement runtime, whose cwd is now the main repo
- Report from a runtime that outlived the deletion
buildVerifiedTeardownScript and the waiter that proves ownership of the target can both go. Teardown becomes ordinary in-process work: pre-remove hooks, git worktree remove, soft git branch -d, each observable and each able to report its own failure rather than encoding the outcome into a receipt file for a successor to find.
dispose-partial gets better, not obsolete — residue is now observed directly instead of inferred from a report written by a script that has already exited.
The risk that does not go away
process.cwd() still points at the deleted directory afterwards. Pi never calls process.chdir (confirmed: no match anywhere in the dist), so the OS cwd of the process is whatever it was at launch.
Tools take an explicit cwd and are unaffected. Node APIs that resolve relative paths against the process cwd are not. Enumerate what still reads it — ours and pi's — before trusting this path. If anything material does, the switch must target a session whose cwd is the main checkout and the relaunch fallback stays reachable for dispose specifically.
Constraints
unsafeDisposeReason keeps its veto, unchanged. Uncommitted and gitignored files are still counted before anything is destroyed, and the caveat still tells the agent exactly what was lost.
Disposing a worktree that a different pi process is standing in remains undetectable. It must keep reporting remoteProcessLiveness: "unknown" rather than quietly implying it checked.
Dispose currently exits pi, runs a detached teardown script, and relaunches in the main checkout. All of that exists for one reason: the process is standing inside the directory it must delete.
An in-process switch inverts the ordering and removes the reason.
Shape worth trying
buildVerifiedTeardownScriptand the waiter that proves ownership of the target can both go. Teardown becomes ordinary in-process work: pre-remove hooks,git worktree remove, softgit branch -d, each observable and each able to report its own failure rather than encoding the outcome into a receipt file for a successor to find.dispose-partialgets better, not obsolete — residue is now observed directly instead of inferred from a report written by a script that has already exited.The risk that does not go away
process.cwd()still points at the deleted directory afterwards. Pi never callsprocess.chdir(confirmed: no match anywhere in the dist), so the OS cwd of the process is whatever it was at launch.Tools take an explicit cwd and are unaffected. Node APIs that resolve relative paths against the process cwd are not. Enumerate what still reads it — ours and pi's — before trusting this path. If anything material does, the switch must target a session whose cwd is the main checkout and the relaunch fallback stays reachable for dispose specifically.
Constraints
unsafeDisposeReasonkeeps its veto, unchanged. Uncommitted and gitignored files are still counted before anything is destroyed, and the caveat still tells the agent exactly what was lost.Disposing a worktree that a different pi process is standing in remains undetectable. It must keep reporting
remoteProcessLiveness: "unknown"rather than quietly implying it checked.