On this page
Storage root handoff and space reclaim
Storage root authority handoff
Inspect a durable handoff before choosing an action:
stado repair stado --step storage-root <target> --transaction <id> --phase status --json
The CLI and Desktop enter the same storage reconciliation report/outcome
implementation. Desktop sends
GET /api/host/storage-root-reconcile?target=<host>&transaction=<id>&phase=status
for Status and POST to the same path for Run, Resume, Rollback or Finalize;
neither method accepts a body. GET requires the independent
storage-reconcile-read registry action and POST requires
storage-reconcile-apply.
HTTP 200 means a product report exists, not that the requested phase succeeded:
the response preserves exit_code, refusal and the complete report.
Malformed, duplicate, empty or unknown query fields, a body, or the wrong
method for a phase return 400. A missing or unauthorized action returns 401;
unavailable verifier state returns 503. Failure before a product report exists
also returns 503, with STORAGE_RECONCILIATION_FAILED and the actual error.
Desktop captures the selected dashboard address and host when its sheet opens,
shows the equivalent CLI command without launching it, and retains the HTTP
status, raw API bytes, product exit, refusal and full report after errors.
Run, Resume, Rollback and Finalize first return accepted after the
target-resident native worker owns the globally locked operation. Acceptance is
not completion. Neither the API nor Desktop issues Status or another phase
automatically; explicitly read Status for the same transaction ID after every
accepted action.
Run and Resume automatically capture the queue and native-service state, acquire placement leases, pause and drain the queue, stop storage writers while retaining the transport and current runner, acquire the storage-write fence, and checkpoint both complete physical roots before constructing the additive union on fixed primary root A. Checkpoint and apply are internal stages, not operator-selectable phases.
The object API's captured loaded route at the fenced preflight pins one conflict winner for the whole transaction. If it serves A, A's bytes and metadata win every shared-path conflict and only B-only objects are imported. If it serves B, B wins shared-path conflicts and A-only objects remain in the union. The immutable checkpoint receipt records that source-selected authority; data application, post-commit correlation and the effective lifecycle snapshot must all agree with it.
Typed lifecycle handling examines records that become newly authoritative: B-only lifecycle records when A was serving, or A-only records when B was serving. This prevents an imported queued job, retained outcome, or live lock from bypassing the same classification that guards the rest of the handoff.
Before the data-commit boundary, Rollback is resumable and restores A to its exact physical checkpoint, including removal of transaction-created imports and now-empty directories, before restoring the captured route and native service state. After that boundary, Resume the same transaction to complete its recorded activation rather than starting a second transaction or reversing the winner.
Run or Resume owns the remaining core stages through declared-runtime
activation, exact native-service and queue restoration, write-fence release and
an activated_pending_lifecycle receipt. Ordinary lifecycle handling must then
resolve the typed queued cancellations and retained outcomes. Select Finalize
only after that cleanup; it validates the final typed observations and records
complete, which a later explicit Status read proves.
Space reclaim
Every host follows one built-in rule, and nothing about cleanup is declared in
the registry: when the volume holding the host's home is at least 80% used,
the janitor deletes everything the fleet put on the host; below 80% it deletes
nothing. It keeps ~/.ssh and everything outside a cleaner's area (the user's
data), a backup copy whose primary cannot be proven identical, the release
versions the registry declares or the host runs, and the tree of a running job.
The cleaners, what each takes and what each keeps are listed in
Space.
The fleet's space-reclaim rule is not a per-target setting. A stored generation with retired memory settings still runs the rule; an ordinary registry write removes those settings.
When a pass runs
Two writers run the same pass against the same lock and state file: the host's
standing health watch at its declared --health-interval-seconds, and the
queue agent at its own poll cadence. Every report names its writer and binary
version so the last outcome is not mistaken for a host-wide verdict.
Under 80% a pass is one statvfs: it writes healthy_noop and opens nothing.
At or above 80% every cleaner runs over its whole area with no age, count, byte
or scan limit, local_snapshots last so the blocks the others freed are
returned on a Mac. The report carries rule (full_percent, used_percent,
triggered), total_bytes, free_bytes_before, free_bytes_after,
used_percent_before, used_percent_after, per-cleaner scanned, eligible and
deleted counts with exact skipped reasons, and errors.
An outcome is one of never_run, healthy_noop,
reclaimed_below_threshold, still_full, no_eligible_items,
blocked_running_jobs, partial_error, report_only, volume_unreadable,
lock_busy, lock_busy_workloads, lock_busy_unattributed or
lock_recovery_report_only. The kernel's live lock is never taken over because
of an old owner timestamp; lock_recovery_report_only means a retired lock is
still held and nothing was scanned or deleted.
While the volume is full the agent claims no new work
(admission_reason: disk_pressure_active) and writes disk-cleanup-turn.json
beside the lock, so running jobs drain and the next pass gets the exclusive
lock.
Operating it
stado space report <target> --json
stado space reclaim <target> --stage registry_cleanup --dry-run --json
stado space reclaim --local --dry-run
stado space reclaim --local --apply --reason "reviewed cleanup"
stado space reclaim <target> --apply --reason "reviewed cleanup" --json
space reclaim --local --dry-run runs every janitor scanner and deletes
nothing: it reports what a pass at the threshold would remove. An applied
fleet reclamation records its reason and result on the affected host. space report retains the full recorded pass under cleanup_state.report. See
Space for every field and refusal sentence.
The reclaim engine runs inside the host's Stado process: the queue agent
checks it on its own poll and the host health watch follows its declared
cadence. stado space report <target> names the last pass and promise.
stado service list --json reports the owning unit's observed state; a silent
or unowned process is not evidence that a reclaim pass worked.
Source: this website