On this page
Recovering retired predecessors
A failed replacement must not start every old unit it discovers. Reversible retirement retains the predecessor's observed activation intent, native manager, calling-account identity, definition paths and normalized autostart flags before it stops anything. Recovery uses that captured plan rather than searching for a currently installed definition with the same label.
Entry points
Replacement handling is part of the existing ensure operation:
stado service ensure PRODUCT --host HOST --reason "ensure the declared service" --json
There is no separate recovery flag or command to run after a failed ensure. When ensuring the replacement or verifying its serving route fails, the failure retains its original cause and appends Predecessor recovery outcomes. That heading does not assert that every recovery step succeeded. If retirement cannot be established safely, the replacement is not started and earlier changed predecessors remain eligible for recovery.
In Desktop's Declare a service → Preconfigured Wisent services, Run PRODUCT on HOST invokes the same ensure command. Its Service operation refused banner carries the command's error, including recovery outcomes; Desktop does not perform a second, independent reload. This interactive error is not a promise of a separate autonomy reconciliation receipt.
Before retirement
Stado requires complete native observations for the calling account: system, GUI and user domains on launchd, or system and user managers on systemd. A missing or unreadable observation is not an empty list of active units.
- On launchd, activation intent means an exact registered job and its reported definition path. A registered job with no running process is still registered; recovery does not infer intent from a PID.
- On systemd, intent comes from
ActiveState, not a unit-specificSubState. Active units retain their actualFragmentPath. Inactive or failed units are not enrolled for a compensating start merely because they are installed. - Every captured active or registered scope must have a usable autostart
observation and a readable definition. Launchd definitions must have the exact
Labeland a correctly typed optionalDisabledvalue. Active systemd units need a durable absolute fragment, must not be transient or masked, and must report that starting is supported. That capability is not proof of privilege. - Transitional native states, unsupported output profiles, ambiguous paths, missing files, conflicting metadata and failed native reads refuse preparation. Stado rechecks activation after preparation and policy observation; drift does not authorize retirement from an obsolete snapshot.
A system definition together with a loaded/active calling-account scope is a pre-action refusal: system-preferred bootout cannot establish full retirement, and matching labels do not prove that another scope runs the same work. An installed inactive systemd definition is present, not absent. Stado does not broaden stop authority to make this check pass. Final retirement requires usable all-scope inactivity and disabled-policy observations; later drift or a read failure retains partial progress and blocks replacement activation.
Read, set, stop and recovery operations are bound to the observed manager and calling-account UID. A different account or manager refuses the operation rather than applying the same scope spelling in another native context.
During recovery
Before starting an old unit, Stado must establish that the failed replacement is inactive across the expected native scopes. A stop refusal, incomplete native result or remaining activation blocks reloading predecessors beside it.
For each predecessor, Stado restores the captured normalized autostart policy. It restores activation only in originally active or registered scopes, using the captured native scope and definition path. A matching usable native observation is a no-op, not a credited host mutation. A changed or additional activation is not silently accepted as the captured state.
Launchd may have a registered job whose autostart policy is disabled. Since a disabled job cannot be bootstrapped, recovering that job temporarily enables its scope, requests bootstrap, then restores the captured disabled policy. The policy restoration is still attempted if temporary enablement or bootstrap fails. Ordinary systemd starts do not unmask units, recreate transient units or install packages. Neither platform adds a retry loop, wait, new login or forced kickstart to conceal a refused operation.
A successful recovery result requires complete final observations matching both the captured activation intent and normalized autostart map. It does not claim to recreate exact PIDs, systemd failure history, every native enablement flavor, link topology, or the manager's entire persistent database. See Autostart evidence for normalization.
Interpreting a refusal
Native acceptance alone does not prove the requested state. Recovery retains ordered earlier acknowledgements, unresolved native requests, the earliest failure phase and independent known host failures. Later failures add their actual operation, scope, error and observed state without replacing the first cause. A failed step can therefore retain a confirmed change without claiming that recovery completed.
Preparation refusals happen before the relevant action. Observation failures mean that the state could not be established. A known failed native command is a mutation failure; a verified wrong result is a postcondition failure. Transport loss or an unusable action transcript leaves execution unconfirmed instead of inventing a successful stop, load or no-op. Read-only failures do not gain host-mutation credit.
Recovery is compensating work, not a transaction: one scope may have changed before another fails. Do not read an outcome heading, a healthy process, or one successful command as proof of complete restoration. The error's retained observations describe what was actually established.
Native references: systemd unit properties,
systemctl,
and the host's launchctl(1), launchd.plist(5) and plutil(1) manuals.
Source: this website