feat(cloud): machine hygiene reclaims by liveness, not age

Merged
TE
18d ago
+177-12

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-days says. Live checkouts keep the old rule: idle for --min-age-days and no process in the project.
  • New build-incremental category. In live checkouts, rustc's target/<profile>/incremental goes whenever no cargo, rustc, rustdoc, clippy-driver or sccache process has its cwd in that checkout. It is reported as skipped building while a build runs there.
  • Claude Code worktrees under <repo>/.claude/worktrees/ are now scanned. The rest of .claude stays 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


View with [code]smith Autofix with [code]smith
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-incremental category that removes rustc target/<profile>/incremental caches 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 .claude stays 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.