v0.15.18 — feat(doctor,task): report disk headroom, and reclaim a closed task's worktree node_modules (DIVE-1967)
The durable half of DIVE-1966, where the control plane hit 100% of 75G with 184 worktrees live and app-wt-*/node_modules alone was ~7.7GB. A full disk never announces itself — it surfaced as an ENOSPC mid-edit and a shell losing stdout, both of which read as 'that tool is broken'.
doctor --category=host reports free space per filesystem, warn <10 GiB / error <3 GiB, as ABSOLUTE FLOORS not percentages: 10% of 75G is 7.5G, which on that host would have read healthy while the tripwire was already firing. An unreadable df reports UNKNOWN, never ok.
task done / task cancel now reclaims that task's worktree node_modules, DEFAULT-ON. Opt-in was considered and rejected: an opt-in cleanup is one somebody has to remember, and the disk filled precisely because nobody remembered. Only the structurally data-loss-free half is automated — node_modules is gitignored and npm-ci-regenerable, so no commit can live there. The worktree DIRECTORY is never deleted, only reported, and the prune verdict FAILS CLOSED: no upstream, unreadable, or dirty all come back as a blocker, because a reclaim that guesses wrong about unpushed work is the one mistake that is not recoverable.
Guards: an ANCHORED number match (closing DIVE-196 cannot touch app-wt-1960), a .git-must-be-a-FILE test at every call site so a primary clone is skipped, and --all skips in_progress/blocked. Escape hatches --keep-worktree and FIVEDIVE_NO_WT_RECLAIM=1 each carry a NEGATIVE CONTROL — same fixture, same close, hatch removed, must reclaim — so a hatch assertion cannot pass on a reclaim that is broken outright. Every skip is NAMED on the acting path, not only in --dry-run JSON, because a reclaim that silently declines to act is indistinguishable from one that found nothing to do.