docs(fleet): define declarative config requirements
All checks were successful
ci/woodpecker/pr/ci Pipeline was successful

Refs #758
This commit is contained in:
Jarvis
2026-07-14 14:21:20 -05:00
parent 49e8a54105
commit 1c3f28ae5a
5 changed files with 315 additions and 5 deletions

View File

@@ -1100,3 +1100,139 @@ All work is **alpha** (< 0.1.0) until Jason approves 0.1.0 beta release.
10. ASSUMPTION: **Conversations and messages get their own PG tables** (not stored in brain's entity model). They follow a chat-specific schema with proper foreign keys to users and projects. Rationale: Chat has different access patterns (streaming, pagination, search) than brain entities.
11. RESOLVED: **Pi handles all target LLM providers natively.** Anthropic, OpenAI/Codex, Z.ai, Ollama, LM Studio, and llama.cpp are all supported via Pi's built-in providers or `models.json` configuration with `openai-completions` API type. No custom provider adapters needed in @mosaicstack/agent — only configuration management.
---
## Fleet Declarative Configuration Management (#758)
### Status and objective
- **Requirement ID:** `FCM-PRD-001`
- **Status:** approved architecture; M0 documentation gate in progress
- **Authority:** issue #758 and the independently approved baseline plan
Provide one understandable, schema-validated lifecycle for the local Mosaic fleet. The operator-owned YAML/JSON roster is the canonical desired-state input. Generated agent environment files, systemd enablement, tmux sessions, heartbeat state, and installed framework assets are derived or observed state. Mutations must pass through one shared compiler/reconciler and must be previewable, atomic where possible, recoverable, automation-safe, and non-destructive toward unmanaged resources.
### Normative scope
#### In scope for M0M5
1. A narrow v2 YAML/JSON roster for local tmux/systemd fleets.
2. One executable structural contract with schema/parser parity and canonical snake_case output.
3. Semantic validation through the existing baseline plus `roles.local` profile/persona/provision resolver; a parallel role resolver is forbidden.
4. Canonical classes `code`, `review`, `security-review`, `validator`, `merge-gate`, `orchestrator`, `team-leader`, `enhancer`, and `interaction`, including documented legacy aliases.
5. Read/validate/plan/apply/migrate, full local fleet-agent CRUD, lifecycle, status, verify, stable JSON output, and documented exit codes.
6. Deterministic `.env.generated` projections, a strict non-shell `.env.local` allowlist, generation/digest stamping, and fail-closed quarantine of forbidden legacy keys.
7. v1 inventory, preview, field-complete migration, canary cutover, rollback, compatibility aliases, and explicit disposition of every shipped example/profile.
8. Documentation, packaging/update checks, clean-install/cold-start dogfood, and independent correctness, security, validator, and merge gates.
#### Out of scope for M0M5
- Kubernetes-style resource envelopes.
- Remote/SSH reconciliation or distributed placement mutation.
- Connector/Matrix/Discord lifecycle mutation.
- Secret-reference or credential-provider schema.
- Arbitrary command or channel overrides.
- Gateway `/api/agents` mapping, control-plane convergence, UI configuration storage, or rename of that separate DB-backed catalog.
- Live-fleet mutation during M0.
Each excluded capability requires a separate post-M5 PRD and threat model. Existing v1 remote/connector fields are inventory-only: local apply must reject them without invoking systemd or tmux.
### Authority and identity decisions
- The roster owns fleet membership, launch policy, and persisted lifecycle intent.
- Role/persona contracts are product reference data; `roles.local` is the update-surviving local extension layer.
- Tess and Ultron are configurable instance/display names, not schema identities.
- `validator` issues the independent final validation certificate but cannot approve-to-land or merge.
- `merge-gate` remains the sole approve-to-land and merge authority after required review, security, validation, CI, and queue gates.
- `orchestrator` may apply validated owner-policy-compliant topology changes and grant/revoke bounded capacity leases.
- `team-leader` may accept/release and use a named lease but cannot change global topology, re-lease capacity, or gain merge authority.
- `review` and `security-review` provide independent correctness and security records respectively; neither authors the reviewed change.
- `interaction` is request/status only. `enhancer` proposes fleet improvements. `code` authors implementation but cannot self-review.
- Operator policy remains the exception, pause, and lease-revocation boundary.
A capacity lease names existing agents, purpose, and expiry. It never changes class, runtime, tools, credentials, roster ownership, or merge authority.
### Lifecycle and generated-state decisions
The normative dimensions are `enabled`, persisted `desired_state: running|stopped`, and observed `running|stopped|error|unknown|unmanaged`.
1. Fresh create defaults to enabled and stopped; `create --start` persists running.
2. v1 migration preserves known observed running/stopped state. Unknown state blocks apply for that entry.
3. Start/stop without `--persist` is transient and reports drift; the next apply/reboot restores persisted intent.
4. Start/stop with `--persist` atomically updates generation and converges the local unit/session.
5. Restart does not change desired state and rejects stopped entries unless explicitly started.
6. Apply acts only on local, enabled, roster-owned entries. Ownership must be proven before stale projections are quarantined or removed; fuzzy names never authorize stopping an unmanaged session.
7. Rollback restores roster/projection generation and captured unit enablement, stops processes introduced by the failed generation, and never starts an agent that was stopped before cutover.
8. The systemd unit reads only `%i.env.generated` after migration. `.env.local` is parsed as data, cannot shadow authoritative keys, and never uses shell `source`, `eval`, expansion, or command substitution.
9. `MOSAIC_AGENT_COMMAND`, channel flags, credential variables, and unknown agent keys are forbidden. Migration reports key names and content hashes only—never values—and blocks launch/apply until disposition.
### Functional requirements
| ID | Requirement |
| --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| FCM-FR-01 | Show and validate YAML/JSON using one structural contract and shared semantic role/topology validation. |
| FCM-FR-02 | Produce a deterministic, non-mutating desired-versus-observed plan covering roster, projections, units, sessions, installed assets, and orphans. |
| FCM-FR-03 | Apply under a lock with expected-generation checks, atomic writes/backups, ordered convergence, post-verification, and machine-readable recovery data. |
| FCM-FR-04 | Provide create, inspect, update, remove, list, start, stop, restart, status, validate, reconcile, doctor, dry-run, and automation-safe operations. |
| FCM-FR-05 | Validate duplicate names, unsupported classes/runtimes/models/options, topology cycles, missing role contracts, stale generated state, unmanaged sessions, unit drift, and socket ambiguity. |
| FCM-FR-06 | Generate deterministic, mode-0600, digest-stamped launch projections; safely parse only allowlisted local operational overrides. |
| FCM-FR-07 | Read v1 for one deprecation window, write v2 after migration, preserve known lifecycle intent, and provide preview/canary/rollback. |
| FCM-FR-08 | Classify every shipped example/profile as migrated, versioned compatibility fixture, or retired with replacement. |
| FCM-FR-09 | Report desired, observed, generation, drift, readiness, ownership, and failing plane without exposing privileged values. |
| FCM-FR-10 | Keep gateway-backed `mosaic agent` records explicitly separate from local `mosaic fleet` desired state. |
### Non-functional requirements
- **Security:** fail closed on command/credential/unknown overrides; reject traversal, injection, shadowing, and unauthorized topology/lifecycle actions; never expose secret or command values.
- **Reliability:** lock plus expected generation; temporary write, fsync, atomic rename, recoverable backup; deterministic idempotent replay; ordered rollback on partial failure.
- **Safety:** no destructive inference from stale names; no local actions for remote/schema-only entries; stopped agents remain stopped through migration and reboot.
- **Compatibility:** canonical snake_case serialization with bounded v1 camelCase/alias input support and explicit warnings.
- **Observability:** stable text/JSON status, drift, plan, migration, and recovery output with documented exit codes `0` success, `2` invalid, `3` drift, `4` conflict, `5` partial failure, and `6` policy denial.
- **Maintainability:** schema, roster load, profiles, provision, migration, and apply share the existing role-resolution implementation.
- **Documentation:** every field, command, transition, migration rule, recovery workflow, class power, and example is linked from the fleet docs IA and validated in CI.
### Acceptance criteria
| ID | Acceptance criterion |
| --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| FCM-AC-01 | `docs/PRD.md`, `docs/TASKS.md`, docs-IA checklist, and example/profile inventory are approved before implementation. |
| FCM-AC-02 | YAML and JSON positive/negative, round-trip, unknown-field, enum, duplicate, topology, and property/fuzz tests prove schema/parser parity and canonical serialization. |
| FCM-AC-03 | Every class resolves through the existing profile/persona resolver; authority and lease tests enforce the normative matrix. |
| FCM-AC-04 | Every shipped example/profile has a CI-valid migrate/compatibility/retire disposition with no unresolved class at M1 exit. |
| FCM-AC-05 | Validate/show/plan are deterministic and non-mutating; JSON shapes and exit codes are contract-tested. |
| FCM-AC-06 | Generated/local env precedence, mode, digest, forbidden shadowing, command injection, quarantine, and no-value diagnostics pass independent security tests. |
| FCM-AC-07 | CRUD is generation-guarded, atomic/recoverable, idempotent, concurrency-tested, and creates stopped agents unless start is explicitly persisted. |
| FCM-AC-08 | Apply/lifecycle exactly implements the transition contract, including transient/persisted operations, reboot, partial failure, and rollback. |
| FCM-AC-09 | Remote/schema-only and unmanaged entries receive zero local lifecycle calls; local targeting covers named and default tmux sockets exactly. |
| FCM-AC-10 | Status/verify/doctor expose all state planes and actionable drift without secret, credential, or privileged command values. |
| FCM-AC-11 | v1 migration handles every mapped field, known/unknown observed state, aliases, env quarantine, current 9-managed/3-unmanaged synthetic fixture, canary, and rollback. |
| FCM-AC-12 | `fleet add/remove` compatibility aliases and v1 reads remain for the approved deprecation window while v2 writers emit only v2. |
| FCM-AC-13 | Package/install/update tests prove schema, tools, units, roles, docs, and examples ship together while site-owned state survives. |
| FCM-AC-14 | Fleet documentation checklist is complete, links/format/examples validate, and operator recovery procedures match tested behavior. |
| FCM-AC-15 | Independent correctness review, security review, validator certificate, terminal-green CI, and merge-gate approval complete before issue closure. |
### Risks and mitigations
| Risk | Mitigation / verification |
| ------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| Schema and parser drift create false validation | One executable contract or bidirectional parity tests; shared semantic resolver. |
| Apply starts intentionally stopped agents | Persist separate desired state; migration preserves known observed state; reboot/rollback tests. |
| Preserved env files become a hidden control plane | Generated-only unit input; strict local allowlist; shadow rejection and quarantine before start. |
| Command, secret, or credential values leak | Values never enter v2 output; key-name/hash-only diagnostics; adversarial security tests and review. |
| Stale artifacts cause destructive cleanup | Proof-of-ownership requirement; unmanaged/remote zero-call tests; deterministic plan before apply. |
| Concurrent writers or crashes corrupt roster | Lock, expected generation, fsync/rename, backup, failure injection, and recovery plan. |
| New compiler duplicates role logic | Hard prohibition on parallel resolver; parity tests across profile, provision, roster, migration, apply. |
| Control-plane naming confuses automation | Explicit local `mosaic fleet` versus gateway DB catalog documentation; no implicit mapping in M1M5. |
| Legacy examples silently teach invalid classes | Complete disposition inventory and M1 CI exit gate. |
### Verification and milestone intent
- **M0:** requirements, authority, lifecycle, migration mapping, TASKS DAG, docs IA, and legacy inventory approved; no implementation or live mutation.
- **M1:** narrow v2 compiler, shared resolver, roles/aliases, validate/show/plan, and all shipped example/profile dispositions.
- **M2:** safe launch projection and generation-guarded atomic CRUD; command/credential quarantine proven before lifecycle.
- **M3:** local-only apply/lifecycle/status/verify/doctor implementing the full transition table.
- **M4:** field-complete v1 migration, compatibility window, orphan inventory, canary, and rollback.
- **M5:** accepted documentation IA, package/update checks, clean-install dogfood, independent correctness/security/validator evidence, and merge-gate release approval.
Detailed delivery dependencies and acceptance mappings are canonical in `docs/TASKS.md`. Documentation acceptance is tracked in [`docs/scratchpads/758-fleet-config-docs-ia-checklist.md`](scratchpads/758-fleet-config-docs-ia-checklist.md), and shipped artifact disposition is inventoried in [`docs/tasks/758-legacy-example-profile-disposition.md`](tasks/758-legacy-example-profile-disposition.md).