Repository navigation
glaeda-disk: the per-host cmux-next DEV build root goes last; its per-instance fallback states go first - #1614
Merged
Conversation
Owner
Author
|
Owned by an agent session · session |
…-instance fallback states go first cmux#25147 builds the DEV Release compile from one tree per mini, ~/Library/Caches/cmux-next-ci/dev-daily-release/host, so its compilation cache hits whichever runner instance builds. disk-policy.json's cmux_next_ci_host_roots names it. It is listed whole, never taken by the size cap, and goes after everything else (idle runners' checkouts included): once idle cmux_next_ci_host_idle_hours (48), or while free is still under the runner floor, and never while a build holds flock on its lock. The per-instance dev-daily-release/<key> states, now only its busy-lock fallback, go first, and whole over the cap once idle a job's timeout. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-cc8bff1c3ddb4ec353c5
teamleaderleo
force-pushed
the
incremental-build-glaeda-host-cache
branch
from
October 26, 2026 08:38
6de16c2 to
8d8e46a
Compare
… is the cap's; host asides count against the cap Codex review findings on the per-host cmux-next root: - the removal empties the root under its lock and leaves the lock file, so a build that opened it earlier and flocks it later still excludes every other build (a replaced lock file let two builds hold two inodes); - outside the floor hold, an owned per-instance fallback state the cap lists whole is no floor slot, so it goes instead of being skipped; - a finished aside of a host root's child is debited from the cap budget. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-cc8bff1c3ddb4ec353c5
…cap tally across main's passes Second Codex review: remove_cmux_next_host emptied a mounted host root (each child looked same-device to its parent), and a host root whose size included an aside finished in the first pass was counted again in the final pass. Both passes now share one taken-bytes tally. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-cc8bff1c3ddb4ec353c5
…r its lock Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-cc8bff1c3ddb4ec353c5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
manaflow-ai/cmux#25147 (merged
ebbefce2) builds the cmux NEXT DEV Release compile on each glaeda mini from one tree,~/Library/Caches/cmux-next-ci/dev-daily-release/host/{src,Release,lock}, so Xcode's compilation-cache keys, which include absolute paths, match whichever runner instance builds. A hostflockonhost/lockguards it. When the lock is busy, the build falls back to the old per-instance statedev-daily-release/<16-hex key>/, which is now only that fallback.glaeda-disk now handles that layout from one declarative rule in
disk-policy.json:cmux_next_ci_host_roots(default["dev-daily-release/host"],[]turns it off) andcmux_next_ci_host_idle_hours(default 48).apply()it also sorts below the floor slots. It goes only:floor_gibitself after everything else.flockonhost/lock. The removal takesLOCK_EX|LOCK_NBon it and, while holding it, removes every child exceptlockitself (each renamed aside, then deleted). The lock file keeps its inode, so a build that had already opened it still excludes every other build. While glaeda-disk holds the lock, a build that starts gets cmux's normal busy-lock fallback (it builds per instance). A build that starts afterwards sets up a fresh tree. When the root is taken for the floor alone, free space is read again under the lock, and nothing goes if the floor was met in the meantime. A host root that is a link or a mount point is refused. A process that has the tree open or names it also keeps it. An interrupted removal's aside tree is finished by the interrupted-deletions family under the same lock veto.dev-daily-release/<hex>states, a kind that now has a host root. They sort first inside the warm band (cap or floor) and inside the normal band. When the cache is over the cap, such a state idle forcmux_next_ci_unowned_idle_hours(6 h) goes whole, inputs included, the same way an unowned state does. Every veto still holds, including its runner'sRunner.Worker.docs/CMUX_NEXT_CI_RETENTION.mddocuments the rule. No change to cmux.Review
An independent Codex review (gpt-6-astra, xhigh) ran over several rounds, and every finding is fixed:
The final head has VERDICT: SHIP.
Evidence (measured 2026-10-26)
xcodebuild, against 794 s cold. The host tree there is 14 GiB:src3.0G,Build4.0G,CompilationCache.noindex2.3G,SourcePackages4.1G,ModuleCache1.1G. The idle per-instance fallbackdev-daily-release/3558a20294057360beside it is 11 GiB.dev-daily-releasewas 16 GiB (host) at 01:53Z and is 0 B at 08:05Z. Pressure runs there use target 170 GiB and floor 30 GiB, andblockedshows library-caches 43.8 / runner-checkout-build 36.5. Attribution caveat: no glaeda-disk receipt on cmux13s (~/Projects/recovery/disk-reclaim/receipts.jsonl) or in its size snapshot namesdev-daily-release/host. The deployed glaeda-disk (d9bc5c62…, current main) cannot list it either, because its state-root shapes require a hex key. The directory's mtime (2026-10-25 20:06 PDT) matches a moment when free space jumped about 12 GiB during a job-completed glaeda-disk pass (pid 84397) that wrote no run line. So the wipe is likely, but not proven, glaeda-disk's. One other candidate: cmux'sscripts/cmux-next/update-e2e.pycleanup removes every path containingcmux-nextthat was created under~/Library/Cachesup to depth 3 during its run, andcmux-next-ci/dev-daily-release/hostis depth 3. What this PR changes either way: before it, glaeda-disk never bounded the host tree, not even below the hard floor, and it counted the host tree against the 40 GiB cap while evicting only other states. The cap would therefore take every per-runner state's output first, and an abandoned host tree stayed forever.Tests
scripts/test-glaeda-disk.py:test_the_per_host_cmux_next_root_goes_last_and_only_under_the_floor:recent.test_the_per_host_cmux_next_root_is_kept_while_its_lock_is_held_and_goes_once_idle:flockkeeps the tree in both the survey and the removal.[]turns the rule off.test_main_takes_the_per_host_cmux_next_root_after_idle_runners_checkouts:main()applies the host root in its own pass after the others.test_the_host_lock_keeps_its_inode_so_a_build_that_opened_it_still_excludes_otherstest_over_the_cap_an_idle_owned_fallback_state_goes_whole_without_a_floor_holdtest_a_finished_host_aside_counts_against_the_cap, which also covers the shared tally, the re-read under the lock and the mount refusal.Risk
Medium. The change is CI-host disk policy only.
flockprobe, by the exclusive lock held across the removal, and by the open-file and command vetoes. A build that loses the race falls back per instance; it does not fail.Runner.Workervetoes that, and the next fallback build re-fetches SourcePackages.Signals
dev-daily-release/hostsurvives pressure runs that are not under the floor. Receipts showdev-daily-release/<hex>(fallback) items reclaimed before other cmux-next items, andhostreclaimed only with the reason "idle 48h+" or below the floor. Consecutive DEV compiles on one host stay warm (xcodebuild well under the 794 s cold time).dev-daily-release/hostwith free abovefloor_giband idle under 48 h, or a DEV compile step log that showshost tree setup failedright after a glaeda-disk pass.Not fixed here:
eviction_busyskipsOf the last 400 pressure run lines, most are
skipped: eviction_busy: cmux14 390/400, cmux13s 385/400. The owners are mostly other pressure passes. On cmux14 the last 400 skip receipts showglaeda-disk --pressure --apply --top 0(the runner hook's job-completed detached pass) 342 times and--floor-gib 40(the gate's floor pass) 36 times. That is 87 distinct owner pids with at most 15 skips each, and owner age p50 23 s / p90 107 s. So these are not overlapping launchd starts. Every job completion on 11-12 runner instances starts a detached pass, and the one that holdsevict.lockmakes the rest skip, as designed. The real cost is that the pressure target (170 GiB) is never reached, free space sits at 50-75 GiB, every pass runs its full 3-9 minutes, and a pass is almost always running. A fix is a policy question about whether to coalesce job-completed passes, skip without a run line, or lower the target. It is a different code path from this change (the runner hook'sdisk_pressure_detachedand the target), so it is left for its own PR.Agent session: agent session
🤖 Generated with Claude Code