docs(fleet): add operator configuration guide (#789)
Some checks failed
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/push/publish Pipeline was successful

This commit was merged in pull request #789.
This commit is contained in:
2026-07-20 05:22:25 +00:00
parent 0582a8912b
commit 627cf2bb38
44 changed files with 1870 additions and 366 deletions

View File

@@ -50,36 +50,38 @@ agents:
## Root fields
| Field | Required | Constraint | Meaning |
| ------------ | -------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `version` | yes | integer constant `2` | Identifies this contract. Version `1` is explicitly rejected by this compiler and remains on the existing v1 path until M4 migration. |
| `generation` | yes | positive safe integer | Desired-state generation. M2 uses it for mutation guards; M1 does not mutate it. |
| `transport` | yes | constant `tmux` | M1M5 support local tmux only. |
| `tmux` | yes | strict object | Explicit local socket and holder-session configuration. |
| `defaults` | yes | strict object | Default work directory and one supported local runtime. |
| `runtimes` | yes | non-empty object | Declared local runtime reset policy map. |
| `agents` | yes | non-empty array | Local fleet entries. Duplicate stable names are rejected. |
| Field | Required | Default | Constraint | Meaning |
| ------------ | -------- | ------- | --------------------- | ------------------------------------------------------------------------------------------------- |
| `version` | yes | none | integer constant `2` | Identifies this contract. Version `1` stays on the compatibility path pending explicit migration. |
| `generation` | yes | none | positive safe integer | Desired-state generation and mutation/reconcile concurrency fence. |
| `transport` | yes | none | constant `tmux` | M1M5 support local tmux only. |
| `tmux` | yes | none | strict object | Explicit local socket and holder-session configuration. |
| `defaults` | yes | none | strict object | Default work directory and one supported local runtime. |
| `runtimes` | yes | none | non-empty object | Declared local runtime reset policy map. |
| `agents` | yes | none | non-empty array | Local fleet entries. Duplicate stable names are rejected. |
## Nested fields
| Path | Required | Constraint |
| ---------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------- |
| `tmux.socket_name` | yes | `[A-Za-z0-9_.-]*`; empty string means the literal default tmux server, while a non-empty value names a socket |
| `tmux.holder_session` | yes | non-empty `[A-Za-z0-9_.-]+` |
| `defaults.working_directory` | yes | non-empty string |
| `defaults.runtime` | yes | `claude`, `codex`, `opencode`, or `pi`; it must be declared in `runtimes` |
| `runtimes.<runtime>.reset_command` | yes | non-empty string; runtime key must be a supported local runtime |
| `agents[].name` | yes | unique `[A-Za-z0-9][A-Za-z0-9_.-]*` stable machine identity |
| `agents[].alias` | yes | non-empty display string |
| `agents[].class` | yes | `[a-z][a-z0-9-]*`; structural only in M1, semantic role resolution is FCM-M1-002 |
| `agents[].runtime` | yes | `claude`, `codex`, `opencode`, or `pi`; it must be declared in `runtimes` |
| `agents[].provider`, `model`, `working_directory` | yes | non-empty strings; provider/model capability resolution is a later card |
| `agents[].reasoning` | yes | `low`, `medium`, or `high` |
| `agents[].tool_policy` | yes | `[a-z][a-z0-9-]*`; structural only in M1 |
| `agents[].persistent_persona`, `reset_between_tasks` | yes | booleans |
| `agents[].lifecycle.enabled` | yes | boolean; stored now, reconciled in FCM-M3-001 |
| `agents[].lifecycle.desired_state` | yes | `running` or `stopped` |
| `agents[].launch.yolo` | yes | boolean; structured data only, not an arbitrary command escape hatch |
All nested fields in the v2 schema are required and have no implicit default. CRUD `create` is the only higher-level convenience: it records lifecycle.enabled: true and desired_state: stopped unless `--persisted-start` explicitly records running. That convenience still performs no runtime action.
| Path | Required | Constraint |
| -------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------ |
| `tmux.socket_name` | yes | [A-Za-z0-9_.-]\*; empty string means the literal default tmux server, while a non-empty value names a socket |
| `tmux.holder_session` | yes | non-empty [A-Za-z0-9_.-]+ |
| `defaults.working_directory` | yes | non-empty string |
| `defaults.runtime` | yes | `claude`, `codex`, `opencode`, or `pi`; it must be declared in `runtimes` |
| runtimes.<runtime>.reset_command | yes | non-empty string; runtime key must be a supported local runtime |
| agents[].name | yes | unique [A-Za-z0-9][A-Za-z0-9_.-]\* stable machine identity |
| agents[].alias | yes | non-empty display string |
| agents[].class | yes | [a-z][a-z0-9-]\*; structural only in M1, semantic role resolution is FCM-M1-002 |
| agents[].runtime | yes | `claude`, `codex`, `opencode`, or `pi`; it must be declared in `runtimes` |
| agents[].provider, `model`, `working_directory` | yes | non-empty strings; provider/model capability resolution is a later card |
| agents[].reasoning | yes | `low`, `medium`, or `high` |
| agents[].tool_policy | yes | [a-z][a-z0-9-]\*; structural only in M1 |
| agents[].persistent_persona, `reset_between_tasks` | yes | booleans |
| agents[].lifecycle.enabled | yes | boolean; stored now, reconciled in FCM-M3-001 |
| agents[].lifecycle.desired_state | yes | `running` or `stopped` |
| agents[].launch.yolo | yes | boolean; structured data only, not an arbitrary command escape hatch |
## Semantic handoff
@@ -97,12 +99,12 @@ Semantic validation:
`operator-interaction` to `interaction`;
- canonicalizes `tool_policy` with the same exact alias table;
- rejects protected class/tool-policy mismatches in either direction, while accepting
`class: operator-interaction` with `tool_policy: operator-interaction` as canonical
class: operator-interaction with tool_policy: operator-interaction as canonical
`interaction`;
- derives immutable protected authority only from canonical class; and
- accepts custom baseline or `roles.local` classes without granting protected authority.
`agents[].alias` remains display-only. Tess and Ultron are instance names, never semantic classes.
agents[].alias remains display-only. Tess and Ultron are instance names, never semantic classes.
Canonicalization happens before role-layer lookup, so a legacy-named override cannot redefine an
alias as separate authority. See [Role Classes and Authority](./role-classes.md) and
[Customize Fleet Roles](../how-to/customize-roles.md).
@@ -112,7 +114,7 @@ lifecycle mutation.
## Fail-closed boundary
Every object is `additionalProperties: false`. The compiler rejects unknown, missing, malformed,
Every object is additionalProperties: false. The compiler rejects unknown, missing, malformed,
and wrong-type fields before producing a model. It specifically rejects remote/SSH/host/socket
per-agent fields, connector blocks, secret references, channel fields, arbitrary command fields,
and gateway fields because they are unsupported in the local-tmux M1 contract. It does not silently