# 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 ` | Read one authoritative agent | no | One JSON object | | `mosaic fleet plan ...` | 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 ... [--dry-run]` | Replace mutable agent fields | required | One JSON object | | `mosaic fleet delete ... [--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: ```text mosaic fleet apply --expected-generation [--dry-run] mosaic fleet reconcile --expected-generation [--dry-run] mosaic fleet start [name] --expected-generation [--dry-run] mosaic fleet stop [name] --expected-generation [--dry-run] mosaic fleet restart [name] --expected-generation [--dry-run] mosaic fleet status [name] mosaic fleet verify mosaic fleet doctor mosaic fleet migrate-v1 preview --source --decisions --observations ``` `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 `/fleet/roster.yaml` desired state. Remote/SSH reconciliation, connector mutation, arbitrary commands/channels, secret references, and gateway convergence are rejected or outside scope.