Files
stack/docs/fleet/how-to/create-update-delete-agent.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.9 KiB

kind, status
kind status
guide active

Create, Inspect, Update, and Delete a Local Fleet Agent

Use the local roster-v2 control plane only. These commands change desired state and derived environment projections; they never start, stop, reconcile, inspect, or otherwise act on systemd, tmux, sessions, or runtimes.

Read and plan first

mosaic fleet get <name>
mosaic fleet plan create --expected-generation <n> --agent '<json>'
mosaic fleet plan update <name> --expected-generation <n> --agent '<json>'
mosaic fleet plan delete <name> --expected-generation <n>

plan create takes the name from --agent. plan update and plan delete require the target name immediately after the operation. A plan is deterministic and side-effect free: it validates the complete proposed roster and projection targets without changing files. Use --dry-run on create, update, or delete for the same no-write result.

Every successful command prints JSON. get returns { "generation", "agent" }; mutation results contain plan, applied, authoritativeRoster, and projections.

Create safely

mosaic fleet create --expected-generation 7 --agent '{
  "name":"coder0",
  "alias":"Coder 0",
  "className":"code",
  "runtime":"pi",
  "provider":"openai",
  "model":"gpt-5.6-sol",
  "reasoning":"high",
  "toolPolicy":"code",
  "workingDirectory":"/srv/mosaic",
  "persistentPersona":false,
  "resetBetweenTasks":true,
  "launch":{"yolo":true}
}'

Create defaults to enabled: true and desired_state: stopped. It does not start a process. Add --persisted-start only to persist desired_state: running; that still does not start a runtime in this M2 command. The JSON payload is an allowlist of the roster-v2 fields shown above plus launch.yolo; command, channel, secret-reference, and other unknown keys are rejected rather than ignored. The JSON error exposes only a stable code, never the rejected value.

Update and delete safely

mosaic fleet update <name> --expected-generation <n> --agent '<complete JSON agent payload>'
mosaic fleet delete <name> --expected-generation <n>

Updates require a complete agent JSON payload and preserve the stable name. Delete removes only the exact roster-owned coder0.env.generated projection. It retains coder0.env.local, legacy coder0.env, coder0.env.quarantine, and every unrelated projection. A delete dry-run leaves all of those files byte-identical.

Handle generation conflicts

Every mutation requires the current authoritative --expected-generation. A stale value returns JSON error.code: "stale-generation" with a non-zero exit. Reload with mosaic fleet get or reread the roster, plan again using the returned generation, then retry. A concurrent mutation returns concurrent-mutation; do not force or bypass the lock.

Interpret partial failures

The roster is authoritative and is written before derived projections. A late projection I/O failure returns non-zero with redacted, actionable JSON:

{
  "applied": false,
  "authoritativeRoster": "committed",
  "projections": "incomplete",
  "recovery": {
    "code": "projection-apply-failed",
    "action": "regenerate-projections-from-roster"
  }
}

This is not a rollback and not a no-op: reload the roster because its generation and membership were committed, regenerate projections from that roster, then plan a new mutation. Recovery output never contains environment values, credentials, or command text.

Exit and boundary behavior

Handled validation errors and partial projection failures exit non-zero. plan/--dry-run and normal mutation JSON make the state explicit; scripts should use both the exit code and authoritativeRoster/projections, not applied alone.

The commands operate only on /fleet/roster.yaml, the local roster desired-state authority. They do not accept arbitrary commands, channels, secrets, remote/connector actions, migration/canary actions, or runtime lifecycle operations.