Skip to content

Clean up a completed custom worktree

If a completed WU’s worktree remains after cleanup, run the recovery command from the primary checkout:

pnpm wu:recover --id WU-XXXX --action cleanup

When the WU records an explicit worktree_path and claimed_branch, recovery uses those exact bindings. A custom suffix or branch name does not require renaming the worktree or deleting the branch. The default lane/id path is used only for older records that never recorded a worktree path. Both worktree and worktree-pr local claim modes use these checks. A branch-only or branch-pr record does not authorize local-worktree removal.

The recorded path must be confined beneath the configured worktrees directory. Its native registration and its own WU record must agree with the canonical claim. Cleanup checks status, leases, recent activity, local changes, settled branch state and a positively confirmed zero-ahead count. It preserves active, unlanded, mismatched or uncertain targets and honors configured worktree retention. Resolve the reported condition before trying again; there is no new force flag for this recovery.

Successful cleanup promotes memory, makes the native verified quarantine copy, and records the cleanup audit before removing the selected directory and Git registration. It preserves the branch and its history, the canonical WU YAML, and the DONE stamp. Other worktrees remain untouched.

Memory files may be Git-ignored local evidence or tracked project data. Before promotion, Git must confirm every untracked file is ignored in both the source worktree and destination; tracked files do not exempt unignored siblings. Ignored files are mirrored locally only after that check. Tracked memory is merged from the latest integration snapshot and published through the normal push-only transaction; cleanup refuses local-only mode or a rejected publication, leaving the source worktree available for retry. The checked-out main tree is not modified by tracked memory promotion. Archive paths are also resolved against each checkout’s own migration sentinel, so cleanup can safely handle a migrated primary checkout and an unmigrated worktree.

For an already removed recorded worktree, recovery reports a successful no-op only when neither the path nor a registration for its recorded branch remains. A recorded custom worktree with a broken registration refuses for diagnosis. The legacy interrupted-cleanup fallback remains available for older records without a recorded path.

LumenFlow never creates a worktree inside another worktree. The host git adapter refuses a worktree path that lies at or inside a registered linked worktree, and refuses a relative path when its directory is a subdirectory of a checkout (git would resolve it against that subdirectory). Create worktrees from the primary checkout root, or pass an absolute path.

A nested registration left by an older version cannot be cleared by the claim-binding proof, because its record names the top-level path. Retire it from the primary checkout:

pnpm wu:recover --id WU-XXXX --action retire

Retire removes a nested worktree only when all of these hold: the WU record on the freshly fetched delivery branch is done and its done stamp is there; the recorded worktree path is this registration with the nesting removed; the worktree is on the WU’s lane branch with a clean tree and a HEAD that is already on the delivery branch; the delivery remote advertises no claim marker for the WU; and no live process has the worktree as its working directory (on Linux and macOS the process list is read; on Windows retire renames the directory to a unique sibling and straight back, and a refused rename (EBUSY, EPERM or EACCES) means a process holds it; any other failure, or a failed restore, refuses and is reported with both paths). The process check cannot see root, other-user or container processes, so it reduces accidents without proving absence; the clean tree and landed-commit checks are what protect your work. Retire also refuses, for any worktree, while another registered worktree lies inside it, and so does every other removal path (wu:prune, wu:cleanup, wu:done, wu:recover): the git adapter itself refuses to remove a worktree that holds another registered worktree, because the removal would delete that worktree and its unlanded work. Retire or move the inner worktree first. Anything else refuses and changes nothing, and a refusal by git never deletes the directory (wu:recover --action nuke and --action cleanup report the refusal and keep the directory).

A done WU’s leftover directory that git no longer registers, or reports prunable (for example a broken admin link after an interrupted wu:done cleanup), is cleared by the same command, pnpm wu:recover --id WU-XXXX --action retire. It deletes the directory only when its real path is strictly inside the worktrees root and is not the main checkout, the WU is done with its stamp on the delivery branch and no claim marker, no worktree is registered inside it, and no live process uses it. The directory’s .git must be a file whose gitdir points into this repository’s .git/worktrees/ (a full clone or a foreign checkout is never deleted), and neither the directory nor any component under the worktrees root may be a symbolic link or junction. On Windows the delete never follows a link and a failed delete is audited as partial. Anything unproven refuses with RETIRE_LEFTOVER_UNPROVEN and the exact reason, and the lane branch is left alone. A retire of a nested worktree appends audit records with the actor and session: an attempt before the removal and the outcome after it. wu:prune follows the same rule: its orphan sweep refuses a directory that still holds a registered worktree, and the tmp-worktree sweep reports git’s refusal instead of deleting the tree. If a Windows probe could not rename a worktree back, a <worktree>.wu-probe-* directory remains; retire, wu:prune and the orphan sweep refuse while one exists and name it. Rename it back by hand.

A registered worktree inside the worktree being removed counts even when its directory is missing, because that is what a stranded Windows probe leaves (the inner worktree renamed to <name>.wu-probe-*, still registered, holding uncommitted work). The scan for stranded probes covers the directory beside every registered worktree, nested ones included. wu:recover --action cleanup and the consistency repairs also refuse their repository-wide stale-metadata prune while a stranded probe, or an unrelated registration with a missing directory, exists; run wu:prune to clear stale registrations first.