Expand description
The disk janitor: finished runs get their worktrees folded, worktrees whose run record is already gone get reclaimed too, and the shared build cache is pruned to its cap.
A run’s state being written by an older schema is not the same thing as it
being unreadable, and this module used to conflate the two: fold_due
treated any run.json its version check rejected exactly like one that
failed to parse at all, so a single schema bump silently stopped every
automatic fold in the fleet the moment it shipped, and did so with no
counter and no log line to say so. A record magi genuinely cannot parse —
missing fields, broken JSON, a schema newer than this build has ever heard
of — is still left alone here, still counted in
Housekeeping::unreadable, and still only ever removed by an explicit
operator action (magi fold, or the equivalent phone route). One written
by a schema this build merely disagrees with the meaning of is not that:
as long as it still parses, folding proceeds regardless of the number in
its schema field.
Everything policy-shaped — which statuses are foldable, how long a finished run is left alone, whether the cache is over its limit — is a pure function injected with numbers, so nothing here has to ask the operating system to be testable. The only I/O is the removal itself.
Structs§
- Housekeeping
- What one janitor pass did, for the caller’s log line.
Functions§
- abandon_
settled_ questions - Abandon every open question whose run has already settled into a status
nothing comes back from, worded with what the run became - the same
cleanup
graph::Runner::settle_questionsruns the momentstatuslands there, for questions that missed it. - cache_
report - The cache’s path, size and cap, for
magi cache showand the health view.Nonewhen the config declares noCARGO_TARGET_DIRto aggregate. - cache_
size - Size in bytes of the shared build cache.
- clear_
abandoned_ active magi fold’s recovery path for a run whose worktrees are already gone — socrate::graph::fold_runremoved nothing — but whoserun.jsonstill lists active seats nobody is left to answer for: no live daemon claims the run, and every one of those seats has overrun its own timeout (seeRunState::active_all_overrun). Clearing them and failing the run is what lets it be deleted afterward —RunState::ensure_can_deleteonly ever checks whether a live daemon is working on the run and whether its candidates are folded, notstatus, but a run stuckimplementingforever with an empty worktree still reads as unresolved everywhere else (magi show, the deck, the phone) until this runs.- due
- Is
updatedold enough, measured againstnow, that the run may fold? - fold_
due - Fold every run that is finished, older than the grace period, and not being
worked on; return
(folded, unreadable). - fold_
orphaned_ worktrees - Reclaim worktrees under
worktrees_rootthat no run record inrunsclaims anymore, and return how many were removed. - fold_
unreadable - Remove a run that cannot be read: its state directory under
runsand its worktree directory underworktrees_root. - housekeep
- Run the janitor: fold due runs, reclaim orphaned worktrees, prune stale worktree registrations, then prune the cache if it is over its cap.
- prune_
cache - Delete files from the shared build cache until it fits its cap.