feat(cloud): machine hygiene reclaims by liveness, not age
cmux-machine-hygiene, the engine behind cmux vm clean and POST /api/vm/:id/hygiene, now decides by liveness first and age second (Leo, 2026-10-19). Design: manaflow-ai/cmuxterm-hq#2562.
- Idle checkouts. If a checkout (the git clone or worktree holding a project) has no process inside it, meaning no agent session, shell or build, its build output goes after a 2 h settle (
--settle-hours). This applies whatever--min-age-dayssays. Live checkouts keep the old rule: idle for--min-age-daysand no process in the project. - New
build-incrementalcategory. In live checkouts, rustc'starget/<profile>/incrementalgoes whenever no cargo, rustc, rustdoc, clippy-driver or sccache process has its cwd in that checkout. It is reported asskipped buildingwhile a build runs there. - Claude Code worktrees under
<repo>/.claude/worktrees/are now scanned. The rest of.claudestays pruned. - Size budget. The script's test budget goes from 24 KiB to 32 KiB, still half the provider's 64 KiB exec limit. The script is about 25 KiB now.
Nothing new can touch source or git state. Every removal still goes through safe_remove, which refuses repo roots, tracked files, symlinks, mounts and anything a process holds.
On Huge Blue on 10-19, these rules (run by hand) took the disk from 97% to 49% used. They removed six worktree targets with no process inside (~50 GB), incremental caches in five live worktrees with no build running (~19 GB), and a 50 GB orphaned shared target dir.
Tests: web/tests/vm-machine-hygiene.test.ts adds three cases: an idle checkout after the settle versus one just built; a live checkout keeping its target, losing incremental, but not while a process named cargo runs there; and Claude Code worktrees. They ran on Huge Blue under load ~40. All new cases pass. The two failures there were 30 s timeouts in unrelated cases (package caches, Docker), and a different case timed out on each run.
🤖 Generated with Claude Code
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
cmux-machine-hygiene now reclaims disk by liveness instead of age, so build output in abandoned checkouts is reclaimed hours after they go idle rather than after a week.
- Checkouts with no running process inside lose their build output after a 2-hour settle (
--settle-hours), regardless of--min-age-days; live checkouts keep the old age-based rule. - Adds a
build-incrementalcategory that removes rustctarget/<profile>/incrementalcaches in live checkouts while no cargo, rustc, or related build process runs there. - When run against a home the script cannot see processes in (non-root against another user's home), the age rule stays and incremental caches are left alone.
- Scans Claude Code worktrees under
<repo>/.claude/worktrees/; the rest of.claudestays pruned. - The script size budget rises from 24 KiB to 32 KiB, still half the provider's 64 KiB exec limit.
- All removals still go through
safe_remove, so source, git state, symlinks, mounts, and running-process files are untouched.
Summary by CodeRabbit
- New Features
- Added a configurable settling period before cleaning up artifacts in idle project checkouts. The default is two hours.
- Added cleanup for Rust incremental build caches when no related build process is active.
- Cleanup now also finds project artifacts in discovered Claude Code worktrees.
- Bug Fixes
- Preserved build output for active checkouts and when process working-directory information is unavailable.