7.0 KiB
Fleet Roster v2 Structural Contract
Status: FCM-M1-001 local-tmux structural compiler contract. This document describes parsing, strict structural validation, normalized in-memory representation, and deterministic rendering only. It does not authorize role resolution, lifecycle reconciliation, mutation, migration, remote placement, connector configuration, secret references, arbitrary commands, channels, gateway mapping, or any live-fleet change.
The executable schema is roster-v2.schema.json. The compiler exports
the same schema and its test parses this file and compares it structurally with the executable contract.
Format and canonical shape
The compiler accepts YAML or JSON. It reads only snake_case source fields and renders canonical, snake_case YAML. Rendering sorts runtime keys and agents by stable name. Agent names, class names, and tool-policy names are structural identifiers; whether a class or policy resolves is a later shared-resolver concern.
version: 2
generation: 1
transport: tmux
tmux:
socket_name: mosaic-fleet
holder_session: _holder
defaults:
working_directory: ~/src
runtime: pi
runtimes:
pi:
reset_command: /new
agents:
- name: coder0
alias: Coder 0
class: code
runtime: pi
provider: openai
model: gpt-5.6-sol
reasoning: high
tool_policy: code
working_directory: ~/src
persistent_persona: false
reset_between_tasks: true
lifecycle:
enabled: true
desired_state: stopped
launch:
yolo: true
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 |
M1–M5 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. |
Nested fields
| Path | Required | Constraint |
|---|---|---|
tmux.socket_name |
yes | non-empty [A-Za-z0-9_.-]+; an explicit named socket prevents default-versus-named socket ambiguity |
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 |
Fail-closed boundary
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
ignore v1 camelCase input, version 1, or a source that does not parse to an object.
The v2 compiler is intentionally isolated from the existing v1 loader. Existing v1 rosters and current examples/profiles continue on their current path; FCM-M4 owns explicit inventory, preview, migration, and rollback. FCM-M2 owns generated-file/local-override quarantine, and FCM-M3 owns runtime lifecycle and reconciliation.