On this page
Service reconciliation receipts
stado optimize run and scheduled autonomy ticks record service reconciliation
under state/autonomy/services/. The immutable receipt is
runs/<timestamp>.json; latest.json selects a receipt for
stado optimize status, GET /api/service/reconciliation and Desktop's
Services → Reconciliation view. The document remains schema_version 1,
with its mode, created_at, summary and complete per-service outcomes.
Shared read contract
The CLI, report API and version-pinned writer decode the same native report model and validate the supported schema and RFC3339 timestamp. Missing required fields, incompatible field types or modes, invalid metadata and unreadable JSON remain errors rather than arbitrary JSON presented as a healthy report. Ordinary display reads retain configured read failover and report the failed operation, object and original cause without manufacturing an empty report.
No stored report remains API HTTP 404; an unreadable or unsupported report is HTTP 503, and CLI status returns its actual error. Desktop retains the API's sentence in The report could not be read, rather than displaying stale success underneath it. Its read-only outcome list shows native beacon/endpoint evidence and uses snapshot positions, keeping repeated rows visible without delimiter IDs or an extra array. An empty list means no per-unit outcomes were recorded, not that no service was evaluated. Layout uses platform content sizing.
Version-pinned publication
Before this service reconciliation stage acts, it reads the prior latest report and its opaque storage version together from the write authority. The shared decoder applies the same report checks as display readers; an empty conditional version additionally refuses the stage before repair. An absent report is different from a failed read.
The stage serializes its completed report once and creates the immutable run receipt without replacing an existing object. It then selects latest only by:
- Compare-and-swap against the exact version read before the stage's work.
- Create-if-absent when that prior read proved latest absent.
A concurrent change refuses publication with StorageConflict; there is no
retry, read-then-unconditional replacement or fallback upload. This includes
another writer creating latest after an absent read. The immutable run remains
acknowledged when it was created before the conflict. A losing run can have a
later timestamp and still lose that race; a later independent run begins with
its own snapshot.
If a run's created_at is not later than the observed prior report, it is
archived but does not replace latest or announce superseded transitions.
Successful latest publication compares transition alerts against the same
version-pinned prior report, not a separate unversioned read.
Ordering follows the reported start timestamps, parsed as instants rather than
compared as strings. It does not establish globally synchronized host clocks,
a transactional snapshot of the fleet, or rollback of host actions. A run that
finishes later is not necessarily the report with the later created_at.
Versioned reads always consult the primary write authority, even when ordinary reads may fail over. A backup's opaque token cannot authorize a conditional write to primary. See Storage authority.
Listener handoff observations
A failed replacement-process inspection is unknown evidence, not a fabricated
empty process. Listener standing and the repair-exclusion guard use the same
strict query. Failed inspection or read-only handoff standing reports
evidence_read_failed; it authorizes neither repair nor handoff/restore action,
including after lease admission, and is not fed as a failed host mutation.
Lease finalization still runs. Errors after a handoff mutation is chosen retain
their operation cause; a failed mutation does not prove rollback or no change.
Bootout and retirement evidence
For one exact native unit, the scoped command is:
stado service bootout LABEL --host HOST --domain user --json
The positional label, registry host and selected native scope identify the
request. The JSON receipt includes evidence: confirmed acknowledged
operations, unconfirmed requested operations whose effect could not be
established, the stated failure provenance, and independent host_mutation
and host_failed facts. A pending request proves neither execution nor no
change. Handoff-record acknowledgements remain distinct from verified native
unit mutations; a bootout scope enters confirmed only after its required
postcondition read succeeds. Earlier scopes survive later read or action errors.
Malformed later fields retain validated scope acknowledgements and native refusal
phases without claiming completion. See Incomplete bootout receipts.
Launchd job absence requires a readable containing domain, including after bootout. A failed or unavailable domain read is an observation refusal, not an absent job or permission to fall through to another scope. No login or domain is created to obtain that observation; earlier effects remain in the receipt.
| Native failure provenance | Reconciliation classification |
|---|---|
preparation |
preparation_failed |
observation |
evidence_read_failed |
mutation or postcondition |
repair_failed |
execution_unconfirmed |
mutation_unconfirmed |
Classification is not inferred from the diagnostic sentence. A read refusal
does not itself count as a failed host mutation. An opaque mutation transport
or unusable action result keeps the request unconfirmed rather than guessing
whether execution failed. Known native failures remain independent of
the row's primary cause. A failed row can therefore have changed: true and
count both an acknowledged change and a failure without claiming completion.
Earlier repair and later partial-retirement acknowledgements retain their order.
JSON refusals print their receipt and still return non-success. Their command
state is refused, or unconfirmed when execution cannot be established; printing
JSON does not turn either into success. Native booted_out means an action was
acknowledged and its postconditions read back. absent means no exact unit was
found; systemd already_correct means it was already inactive and not enabled,
so no stop/disable was requested or credited as a change. Retirement retains
already_correct rather than claiming that such a unit is absent; an inactive,
disabled installed definition can remain when there was nothing to withdraw.
The exact label is inserted after scope-template expansion, never reinterpreted
as a template token.
Autostart inspection requires complete, exact-scope native evidence. Native read failures never become an empty set of enabled scopes; no-op setters require a usable matching observation. See Autostart evidence for manager states, refusals and retained lifecycle progress.
Predecessor completion and rollback
Replacement activation and API-listener takeover judge predecessor completion
from typed failure and pending-effect evidence, not from a display word such as
failed. An unknown prerequisite read therefore blocks starting the
replacement too. Its error says that safe retirement could not be established;
it does not invent a still-running predecessor.
Reversible retirement records a rollback handle only for known native changes, known native failures that may have effects, or unresolved native requests. Read-only preparation/observation refusals and matching no-ops do not trigger a compensating load of an untouched predecessor. Earlier changed units remain eligible for recovery when a later unit's prerequisite observation fails.
Recovery captures native activation intent and definition paths separately from autostart policy, bound to the observed manager and calling account. It does not start originally inactive systemd units or assume a registered launchd job needs a running PID. A failed replacement must be verified inactive before old units are reloaded. Recovery outcomes retain partial changes and refusals rather than asserting that every predecessor was given back. See Recovering retired predecessors for preparation, exact-scope restoration, Desktop presentation and limitations.
Full-scope retirement proof
Automatic predecessor retirement requires complete final observations of native inactivity and disabled autostart in every expected system/calling-account scope, bound to one observed manager and UID. A successful scoped stop or disabled policy alone is not completion.
Before action, a system definition together with an active calling-account
scope refuses retirement: system-preferred bootout any cannot establish full
inactivity, and the same label does not prove that broader stopping is safe.
An installed inactive systemd definition still counts as native presence.
Public bootout scope selection is unchanged; no broader stop is substituted.
Later drift, remaining activation or an unreadable final observation refuses
completion while retaining earlier acknowledged effects. The same result feeds
ensure failures and autonomy receipts, including Desktop reconciliation rows.
Explicit service retire/remove retain their separate declared-unit contract;
these automatic predecessor checks do not replace that workflow.
The final reads are observations, not an atomic native-manager transaction.
Retirement admission
During autonomy, ordinary predecessors and idle strays use the same mutation gate as repairs and listener handoffs: live pause, action permits, host breaker and a lease for the exact old unit. Read-only kept/unknown predecessor decisions do not acquire a mutation permit. The native predecessor decision is repeated under the lease. Strays are rediscovered there and their idle, undeclared and unowned status rechecked; a newly live, declared or catalog-owned unit is kept.
Permits count admitted attempts, not successful host changes: a decision can become read-only after admission. Known no-ops and record-only changes do not reset the host breaker, and an unconfirmed request is not counted as a native failure. Partial acknowledgements and lease-release failures remain visible together. Report/emergency-paused mode still executes no retirement. These outcomes use the same CLI status, report API and Desktop reconciliation rows; no separate graphical action or alternate mutation path is introduced.
Interrupted cycles
stado optimize run can fail after earlier units already changed. Once service
inventory is known, every mutation stage appends into the same report owner.
A later control-read, lease-acquisition or outcome-recording error does not
discard preceding rows or the current acknowledged native result. Lease-release
observation is applied even when recording the native outcome also fails.
An interrupted pass adds an alert-eligible cycle_failed row for the failed
product operation. Its action identifies control loading, lease acquisition,
outcome recording or the actual catalog/role prerequisite; host and unit are
retained when known. Empty host/unit fields indicate cycle scope, not a native
identity. This row's changed: false is not proof earlier changes were absent
or a failed write had no effect. Native acknowledgements remain in their own rows;
failed acquisitions/writes stay unconfirmed. Retirement reuses the cycle's validated host-catalog name.
services is the known inventory count. Other tallies and rows describe
progress observed before interruption, not evaluations of unvisited services.
If inventory itself cannot be read, mutation stages are not entered and no
empty inventory report is fabricated; the actual operation/cause is logged.
The partial report uses the same immutable-first, version-pinned publisher.
An acknowledged partial publication names its actual immutable_object and
latest_selected in the cycle log. It does not turn the failed command into
success: the original storage error is still returned. If publication also
fails, its operation/key/cause and all retained rows are logged separately,
without replacing that original error. No write retry or blind latest upload
is introduced. Transition alerts still require acknowledged latest selection.
CLI status, the report API and Desktop's reconciliation view expose these
same partial rows. Read the cycle_failed row and timestamp before treating
a readable report as a completed pass.
Managed stop preparation
Managed-service stops validate the credential requirement, unit and path and render the native prelude/body before any privileged bootout. Execution consumes those prepared inputs for the bound target and checks the existing stopped postcondition; a prepared value alone is not execution or postcondition proof. Credential input remains on stdin, with one execution buffer shared by the existing privileged jobs rather than a new copy for each job.
An explicitly declared per-login recovery label is stopped only after observing Darwin, through the calling account's native user scope, keeping a system sibling. The scope's absent/removed result is verified before reporting success. A failed UID read or invalid UID is refused with the actual exit/output cause instead of being mistaken for an empty namespace; unsupported managers are not substituted.
Launchd inspection and verification failures are not absence. Native success and the shared declared absence statuses determine the result; other exit/output is a refusal, including after bootout. An unreadable system scope does not authorize silently falling through to a user-scope action. Resident handover also requires exact native services-table membership, never a matching metadata value.
Standby pre-stop refusals
A standby's missing authoritative unit or managed-service declaration is
declaration_incomplete, with the reason nothing was stopped. Target resolution,
missing required credentials or invalid local stop definitions are
preparation_failed, naming the host, unit and actual cause; they do not feed a
failed host mutation to the breaker.
Resolved or unjudged rechecks keep their existing non-mutation handling.
Native stop/refused-postcondition errors retain the stop's own cause; neither
the stop_standby action label nor a failed attempt proves the unit stopped.
Actions, transitions and publication failures
What a planned action label proves, how an alert's identity is read, and what a failed publication retains are on Reconciliation actions, transitions and publication failures.
Return to Missing service reconciliation for repair, ownership, lease-finalization and failure-classification behavior.
Source: this website