Files
stack/docs/fleet/concepts/desired-vs-observed-state.md
T
veronica f0d2dd9920 docs(W4): stamp kind and status front matter on 104 live documents
Applies the document contract from
docs/plans/2026-08-20_stack-docs-flatten-and-alignment.md section 3, partially:
`kind` and `status` only. `parent` is deliberately held until the flatten in
section 4 lands, so that 127 documents do not have to be re-pointed by hand
when docs/fleet/NORTH_STAR.yaml moves to docs/NORTH_STAR.yaml.

Scope, measured on origin/next at 63069149:

  127 live docs   = all *.md under docs/ minus docs/archive/ minus docs/_old_structure/
  104 stamped     here
   19 held        operator judgement (plan section 9), worklist in the same PR
    3 held        the SUPERSEDED TASKS.md stamps, which cite the moving path
    1 untouched   docs/fleet/FLEET-DOCTRINE.md, already stamped in W1

Kinds applied: 54 guide, 34 record, 9 spec, 6 tracking, 1 projection.
Every row carries a confidence and a one-line rationale in the worklist.

Two collisions with the existing state, both flagged rather than resolved:

1. docs/README.md:150-160 already documents a front-matter convention
   (title/type/audience/status/source_of_truth) with its own allowed values.
   It is applied to 4 of 127 files. Its `status` vocabulary is
   current|draft|deprecated|historical; the new contract's is active|superseded-by.
   The key collides. This commit lets the new contract win and rewrites
   `status: current` to `status: active` on those 4 files, keeping their other
   legacy keys untouched. No code reads any of them: `git grep source_of_truth`
   outside docs/ returns nothing. docs/README.md still prescribes the old
   convention and is an operator row, so it is not edited here.

2. Two of the plan's 20 operator rows are YAML files, not markdown
   (docs/fleet/examples/roster-v2.yaml, docs/openapi-tess.yaml), and the
   contract's front-matter form has no defined meaning for a .yaml document.
   That gap also applies to docs/fleet/NORTH_STAR.yaml, the source of truth
   itself. Raised in the worklist.

A third row from the plan, docs/fleet/north-star.md, no longer exists: W1
renamed it to docs/fleet/FLEET-DOCTRINE.md.

Verification: 104/104 parse with the expected kind and status in front matter;
the check was shown to reject a wrong kind before it was trusted. The diff
removes 4 lines total, all of them `status: current`.
2026-08-20 19:30:25 -05:00

3.7 KiB

kind, status
kind status
guide active

Desired, Derived, and Observed Fleet State

One writable authority

The canonical local v2 roster at <MOSAIC_HOME>/fleet/roster.yaml is desired state. Membership, stable identity, class, runtime/provider/model selection, launch policy, enablement, and persisted running/stopped intent are written only through generation-guarded roster mutations.

Derived projections are reproducible consequences of that authority:

  • .env.generated;
  • exact roster-named tmux sessions on the configured socket after reconciliation;
  • systemd service targets managed by installation/reconciliation.

Current systemd unit enablement is not yet lifecycle-conformant at boot: installation can enable every agent unit, and the launcher projection does not carry enabled or desired_state. Therefore reboot preservation for stopped/disabled agents remains an FCM-M3-002 acceptance hold, not a guaranteed projection behavior.

Observed evidence available to current roster-v2 status commands includes systemd active state, tmux presence, holder ownership, and unmanaged sessions. Heartbeat files are observational in the wider fleet, but roster-v2 status, doctor, and verify do not currently read them. Observation never writes back to the roster.

Generation and ownership

generation is a positive integer concurrency fence. A mutating request must provide the current value. Successful changed CRUD increments it exactly once; stale or concurrent writers fail before mutation. Apply/reconcile rereads the canonical roster under a private exclusive lock and uses only that generation and content for effects.

Ownership is exact, never fuzzy. Reconciliation is limited to roster names, the configured socket, the exact holder session, a private installation identity, and private managed paths. An ownership mismatch, unmanaged session, unsafe path, stale generation, or ambiguous lock fails closed.

Drift decisions

Observation Interpretation Safe response
Generated file differs or is missing Derived projection drift Review apply --dry-run; regenerate from the roster.
Desired running, exact session missing missing-session Diagnose ownership/runtime, then reconcile if safe.
Desired stopped, exact session present unexpected-session Inspect; reconciliation may stop only the proven roster target.
Disabled agent running disabled-running Inspect; disabled state wins during explicit safe reconciliation.
Unknown session on the configured socket Unmanaged state Report only. Do not adopt, rename, or kill it.
Heartbeat stale in the wider fleet Liveness evidence Diagnose separately; current roster-v2 status does not read heartbeat.

status and doctor classify. verify is also observational but exits non-zero when ownership, drift, or unmanaged-state checks fail. plan/apply --dry-run validates proposed projection and lifecycle work without mutation. apply and reconcile converge only after all preconditions pass.

A partial projection failure does not roll the roster back. Treat the committed roster as authority and regenerate. A lifecycle failure after projection completion preserves both roster and projections for inspection. Sensitive legacy values are never printed; diagnostics are bounded to stable codes, key names where applicable, and hashes.