# Fleet Control-Plane CLI

The local desired-state surface is mosaic fleet. It is distinct from the gateway-backed mosaic agent catalog and from legacy compatibility commands that act on roster v1.

## Roster-v2 desired-state commands

| Command                                                    | Effect                                         | Generation | Output                     |
| ---------------------------------------------------------- | ---------------------------------------------- | ---------- | -------------------------- |
| mosaic fleet get <name>                                    | Read one authoritative agent                   | no         | One JSON object            |
| mosaic fleet plan <create\|update\|delete> ...             | Validate proposed CRUD and projections         | required   | One JSON object; no writes |
| mosaic fleet create ... [--dry-run] [--persisted-start]    | Add desired state; default enabled/stopped     | required   | One JSON object            |
| mosaic fleet update <name> ... [--dry-run]                 | Replace mutable agent fields                   | required   | One JSON object            |
| mosaic fleet delete <name> ... [--dry-run]                 | Remove roster member/generated projection      | required   | One JSON object            |
| mosaic fleet apply ... [--dry-run]                         | Plan or converge projections/lifecycle         | required   | One JSON object            |
| mosaic fleet reconcile ... [--dry-run]                     | Alias of the same convergence contract         | required   | One JSON object            |
| mosaic fleet start\|stop\|restart [<name>] ... [--dry-run] | Exact one-shot lifecycle action                | required   | One JSON object            |
| mosaic fleet status [<name>]                               | Observe desired/managed/runtime state          | no         | One JSON object            |
| mosaic fleet verify                                        | Strict observational drift/ownership gate      | no         | One JSON object            |
| mosaic fleet doctor                                        | Classify local drift and recovery context      | no         | One JSON object            |
| mosaic fleet migrate-v1 preview ...                        | Non-mutating field-complete migration evidence | no         | One JSON object            |

CRUD syntax and full payload shape are documented in [agent mutations](agent-mutations.md). Reconciliation syntax:

```fleet-synopsis
mosaic fleet apply --expected-generation <n>
mosaic fleet reconcile --expected-generation <n>
mosaic fleet start [<name>] --expected-generation <n> [--dry-run]
mosaic fleet stop [<name>] --expected-generation <n> [--dry-run]
mosaic fleet restart [<name>] --expected-generation <n> [--dry-run]
mosaic fleet status [<name>]
mosaic fleet verify
mosaic fleet doctor
mosaic fleet migrate-v1 preview --source <path> --decisions <path> --observations <path>
```

`get` is the read/show operation for one v2 agent. Full roster parsing and semantic validation occur on every v2 mutation/reconcile path; there is no separate mutable “config store.” The executable JSON Schema and validated example provide offline structural evidence. The PRD requires an explicit programmatic mosaic fleet validate operation, but the current CLI does not expose one; do not substitute another command or claim that requirement is delivered. This remains an implementation gap for #758.

## JSON and exit behavior

Roster-v2 CRUD and reconciler precondition failures emit { "error": { "code": "..." } } and exit non-zero. Migration preview has its own result envelope: a non-ready preview emits { "status": "blocked", "blockers": [...] } and exits non-zero rather than using the CRUD/reconciler error object. Use both exit status and command-specific state fields. A partial reconciliation result distinguishes `authoritativeRoster`, `projections`, `lifecycle`, `recovery`, and optional `cleanup`; it never claims automatic rollback. `verify` exits non-zero for drift, ownership failure, or unmanaged sessions. Sensitive legacy values, credentials, and rejected command text are never printed.

## Compatibility and scope

Roster-v1 initialization, provisioning, profiles/personas, and historical fleet add/remove remain compatibility surfaces, not roster-v2 CRUD aliases. New v2 automation should use the table above. migrate-v1 preview writes nothing and has no cutover, canary, or rollback option.

mosaic agent is a separate catalog/transport surface; it does not own <MOSAIC_HOME>/fleet/roster.yaml desired state. Remote/SSH reconciliation, connector mutation, arbitrary commands/channels, secret references, and gateway convergence are rejected or outside scope.
