Skip to content

Reconciliation

Reconciliation is Hostwright’s core loop: deterministic, observable, and designed to fail closed.

Reconciliation cycle: observe actual state, diff against desired, plan actions, then the confirmed apply step, looping back to observe; dry-run stops after plan.

  1. Load desired state from the manifest.
  2. Observe runtime state through the RuntimeAdapter.
  3. Compute drift.
  4. Produce a dry-run plan with a deterministic hash.
  5. Mutate only through a confirmed lifecycle plan.
  6. Record events.

The planner maps the supported manifest subset to runtime-shaped desired state, accepts optional adapter-shaped observed state, runs policy checks, and emits typed drift records, typed issues, typed planned actions, and a deterministic plan hash.

  • hostwright plan renders desired-state and policy diagnostics. It does not perform live runtime observation by default, and it says so explicitly in its output.
  • hostwright up, down, run, start, stop, restart, rm, and update each recompute their own plan against a live observation, require a matching --confirm-plan hash, persist operation intent before mutation, then execute the plan’s ready nodes with bounded parallelism. apply is a compatibility alias for a confirmed up plan. See Lifecycle commands.
  • hostwright cleanup is separate from the lifecycle commands, with its own dry-run token gate, and never removes anything a lifecycle command would manage. See the safety model.
  • hostwrightd --foreground runs the observe, plan, and record loop continuously. It never calls a lifecycle command itself; mutation stays with an operator running one explicitly. See Daemon.

The planner detects:

  • missing desired services;
  • unmanaged observed services;
  • stopped, exited, failed, and missing lifecycle states;
  • image drift, port drift, mount drift;
  • unhealthy or unknown health state where policy requires health;
  • duplicate observed identities;
  • unsupported unknown observed lifecycle states;
  • unavailable observation.

Each drift record maps to a typed planned action (create, start, stop, restart, remove, or update) scoped to one service. A plan can carry more than one such action; what makes an action executable is passing every policy and precondition check, not being the only action in the plan. An action that fails a check is still rendered in the plan, marked unavailable and blocked from execution, so the operator can see exactly what would not happen and why.

  • Planning is deterministic: same inputs, same plan, same hash.
  • Desired state and observed state remain separate inputs.
  • Drift must be explainable: every record carries a typed reason.
  • Plan rendering must not expose raw secrets.
  • Mutation must require plan-hash confirmation.
  • Operation intent must be persisted before mutation.
  • Failures must be observable through events.
  • Managed restart requires Hostwright ownership, live observed running state, a fresh persisted unhealthy health result, and recovery records.