feat(fleet): add shared role semantics (#768)
This commit was merged in pull request #768.
This commit is contained in:
@@ -52,20 +52,20 @@ Active workstream is **W1 — Federation v1**. Workers should:
|
||||
> the repository quality gates, independent code and security review, terminal-green CI, and
|
||||
> the applicable acceptance evidence before merge. Issue #758 remains open until M5 closes.
|
||||
|
||||
| id | status | description | issue | agent | repo | branch | depends_on | estimate | notes |
|
||||
| ---------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- | ------ | ----------------- | --------------------------------------- | ---------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------- |
|
||||
| FCM-M0-001 | in-progress | Publish normative PRD requirements/acceptance criteria, this M0–M5 DAG, docs-IA checklist, and legacy example/profile disposition inventory; no implementation changes | #758 | sonnet | mosaicstack/stack | `docs/758-fleet-config-management` | — | 18K | M0 exit: approved docs; every shipped example/profile/service preset classified; docs-only PR |
|
||||
| FCM-M1-001 | not-started | Implement narrow local-tmux v2 roster structural contract/compiler with YAML/JSON canonicalization and schema/parser parity tests | #758 | codex | mosaicstack/stack | `feat/758-roster-v2-compiler` | FCM-M0-001 | 30K | No lifecycle, remote, connector, secret, channel, or gateway work |
|
||||
| FCM-M1-002 | not-started | Reuse existing profile/persona/provision resolver for roster semantics; add canonical class/authority validation and approved aliases | #758 | codex | mosaicstack/stack | `feat/758-shared-role-resolution` | FCM-M0-001 | 25K | Validator is certificate-only; merge-gate remains sole merge authority |
|
||||
| FCM-M1-003 | not-started | Convert the M0 legacy inventory into executable example/profile/service-preset validation and explicit v1-version/retirement checks | #758 | codex | mosaicstack/stack | `test/758-example-profile-dispositions` | FCM-M1-001, FCM-M1-002 | 20K | Every shipped artifact must validate, be versioned v1, or be retired with replacement |
|
||||
| FCM-M2-001 | not-started | Migrate generic launch chain to deterministic `.env.generated` plus strict data-only `.env.local`; quarantine forbidden legacy keys | #758 | codex | mosaicstack/stack | `feat/758-generated-env-boundary` | FCM-M1-001, FCM-M1-002 | 30K | No arbitrary command compatibility path; diagnostics expose key names/hashes only |
|
||||
| FCM-M2-002 | not-started | Add generation-guarded local fleet agent create/get/update/delete mutations with plan/dry-run, atomic roster writes, and recovery output | #758 | codex | mosaicstack/stack | `feat/758-fleet-agent-crud` | FCM-M1-001, FCM-M2-001 | 30K | Fresh create persists stopped unless explicit persisted start |
|
||||
| FCM-M3-001 | not-started | Implement local roster-owned reconcile/apply plus lifecycle/status/verify/doctor contracts and stable JSON/exit codes | #758 | codex | mosaicstack/stack | `feat/758-local-reconciler` | FCM-M2-001, FCM-M2-002 | 35K | Exact systemd/tmux ownership; remote/schema-only entries are inventory only |
|
||||
| FCM-M3-002 | not-started | Add isolated systemd/tmux lifecycle, drift, socket, unmanaged-session, crash, and rollback acceptance coverage | #758 | sonnet | mosaicstack/stack | `test/758-reconciler-lifecycle-gates` | FCM-M3-001 | 25K | Proves stopped-state preservation and zero fuzzy destructive targeting |
|
||||
| FCM-M4-001 | not-started | Implement field-complete v1-to-v2 inventory/preview/migrator with alias, lifecycle, env-quarantine, and remote/connector disposition evidence | #758 | codex | mosaicstack/stack | `feat/758-v1-v2-migrator` | FCM-M1-003, FCM-M3-001 | 35K | Preview first; no unreviewed lifecycle inference |
|
||||
| FCM-M4-002 | not-started | Add reversible canary migration, rollback, stale-projection/orphan classification, and current-host 9-managed/3-unmanaged fixture coverage | #758 | sonnet | mosaicstack/stack | `test/758-migration-rollback-gates` | FCM-M4-001, FCM-M3-002 | 25K | Never starts a previously stopped agent or kills an unproven unmanaged session |
|
||||
| FCM-M5-001 | not-started | Deliver the accepted fleet documentation IA, how-to/operations/migration references, and link/example validation | #758 | haiku | mosaicstack/stack | `docs/758-fleet-config-operator-docs` | FCM-M1-003, FCM-M2-002, FCM-M3-001, FCM-M4-001 | 24K | Must close every checklist item or record an approved deferral |
|
||||
| FCM-M5-002 | not-started | Package/update asset-drift checks, rolling local canary, independent validation certificate, and release evidence | #758 | sonnet | mosaicstack/stack | `feat/758-fleet-config-release-gate` | FCM-M3-002, FCM-M4-002, FCM-M5-001 | 30K | Final #758 gate: quality, independent code/security review, validator certificate, merge-gate approval, green CI |
|
||||
| id | status | description | issue | agent | repo | branch | depends_on | estimate | notes |
|
||||
| ---------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- | ------------- | ----------------- | --------------------------------------- | ---------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------ |
|
||||
| FCM-M0-001 | done | Publish normative PRD requirements/acceptance criteria, this M0–M5 DAG, docs-IA checklist, and legacy example/profile disposition inventory; no implementation changes | #758 | sonnet | mosaicstack/stack | `docs/758-fleet-config-management` | — | 18K | Merged via #760 (`c32d85a`); parent #758 intentionally remains open through M5 |
|
||||
| FCM-M1-001 | done | Implement narrow local-tmux v2 roster structural contract/compiler with YAML/JSON canonicalization and schema/parser parity tests | #758 | coder0 | mosaicstack/stack | `feat/758-roster-v2-compiler` | FCM-M0-001 | 30K | #764 squash `aa5b43b`; exact-head RoR and PR/main terminal-green CI; no lifecycle or live mutation |
|
||||
| FCM-M1-002 | in-progress | Reuse existing profile/persona/provision resolver for roster semantics; add canonical class/authority validation and approved aliases | #758 | native-sonnet | mosaicstack/stack | `feat/758-shared-role-resolution` | FCM-M0-001 | 25K | Started 2026-07-14 from `aa5b43b`; one shared resolver only; validator certificate-only; merge-gate sole merge authority |
|
||||
| FCM-M1-003 | not-started | Convert the M0 legacy inventory into executable example/profile/service-preset validation and explicit v1-version/retirement checks | #758 | codex | mosaicstack/stack | `test/758-example-profile-dispositions` | FCM-M1-001, FCM-M1-002 | 20K | Every shipped artifact must validate, be versioned v1, or be retired with replacement |
|
||||
| FCM-M2-001 | not-started | Migrate generic launch chain to deterministic `.env.generated` plus strict data-only `.env.local`; quarantine forbidden legacy keys | #758 | codex | mosaicstack/stack | `feat/758-generated-env-boundary` | FCM-M1-001, FCM-M1-002 | 30K | No arbitrary command compatibility path; diagnostics expose key names/hashes only |
|
||||
| FCM-M2-002 | not-started | Add generation-guarded local fleet agent create/get/update/delete mutations with plan/dry-run, atomic roster writes, and recovery output | #758 | codex | mosaicstack/stack | `feat/758-fleet-agent-crud` | FCM-M1-001, FCM-M2-001 | 30K | Fresh create persists stopped unless explicit persisted start |
|
||||
| FCM-M3-001 | not-started | Implement local roster-owned reconcile/apply plus lifecycle/status/verify/doctor contracts and stable JSON/exit codes | #758 | codex | mosaicstack/stack | `feat/758-local-reconciler` | FCM-M2-001, FCM-M2-002 | 35K | Exact systemd/tmux ownership; remote/schema-only entries are inventory only |
|
||||
| FCM-M3-002 | not-started | Add isolated systemd/tmux lifecycle, drift, socket, unmanaged-session, crash, and rollback acceptance coverage | #758 | sonnet | mosaicstack/stack | `test/758-reconciler-lifecycle-gates` | FCM-M3-001 | 25K | Proves stopped-state preservation and zero fuzzy destructive targeting |
|
||||
| FCM-M4-001 | not-started | Implement field-complete v1-to-v2 inventory/preview/migrator with alias, lifecycle, env-quarantine, and remote/connector disposition evidence | #758 | codex | mosaicstack/stack | `feat/758-v1-v2-migrator` | FCM-M1-003, FCM-M3-001 | 35K | Preview first; no unreviewed lifecycle inference |
|
||||
| FCM-M4-002 | not-started | Add reversible canary migration, rollback, stale-projection/orphan classification, and current-host 9-managed/3-unmanaged fixture coverage | #758 | sonnet | mosaicstack/stack | `test/758-migration-rollback-gates` | FCM-M4-001, FCM-M3-002 | 25K | Never starts a previously stopped agent or kills an unproven unmanaged session |
|
||||
| FCM-M5-001 | not-started | Deliver the accepted fleet documentation IA, how-to/operations/migration references, and link/example validation | #758 | haiku | mosaicstack/stack | `docs/758-fleet-config-operator-docs` | FCM-M1-003, FCM-M2-002, FCM-M3-001, FCM-M4-001 | 24K | Must close every checklist item or record an approved deferral |
|
||||
| FCM-M5-002 | not-started | Package/update asset-drift checks, rolling local canary, independent validation certificate, and release evidence | #758 | sonnet | mosaicstack/stack | `feat/758-fleet-config-release-gate` | FCM-M3-002, FCM-M4-002, FCM-M5-001 | 30K | Final #758 gate: quality, independent code/security review, validator certificate, merge-gate approval, green CI |
|
||||
|
||||
## Thin-core prompt diet (#528) — feat/contract-thin-core
|
||||
|
||||
|
||||
54
docs/fleet/how-to/customize-roles.md
Normal file
54
docs/fleet/how-to/customize-roles.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# Customize Fleet Roles
|
||||
|
||||
Mosaic resolves persona contracts through two layers:
|
||||
|
||||
1. `fleet/roles/<canonical-class>.md` — seeded baseline contract.
|
||||
2. `fleet/roles.local/<canonical-class>.md` — operator override or custom role; this layer wins.
|
||||
|
||||
The same shared resolver is used by profile validation, provisioning, roster-v2 semantic validation,
|
||||
and launch-time persona injection.
|
||||
|
||||
## Override a baseline role
|
||||
|
||||
Create a readable Markdown contract under `roles.local` with the canonical filename and class marker:
|
||||
|
||||
```markdown
|
||||
# Code — local role definition
|
||||
|
||||
The local code role (`class: code`) follows the operator's repository conventions.
|
||||
```
|
||||
|
||||
Save it as `fleet/roles.local/code.md`. Do not edit generated or seeded baseline assets when the goal
|
||||
is a durable local customization.
|
||||
|
||||
Legacy aliases canonicalize before lookup. Therefore `roles.local/implementer.md` does not override
|
||||
`code`; use `roles.local/code.md`. See [Legacy Fleet Class Aliases](../migration/legacy-class-aliases.md).
|
||||
|
||||
## Add a custom class
|
||||
|
||||
A custom class remains supported when a readable contract exists for the exact identifier:
|
||||
|
||||
```markdown
|
||||
# Release notes — local role definition
|
||||
|
||||
The release-notes role (`class: release-notes`) prepares operator-reviewed release copy.
|
||||
```
|
||||
|
||||
Save it as `fleet/roles.local/release-notes.md`, then reference `class: release-notes` and a matching
|
||||
`tool_policy: release-notes` in roster v2. Adding only a `LIBRARY.md` row is insufficient.
|
||||
|
||||
Names such as `worker`, `analyst`, and `canary` are not built-in aliases; they need genuine custom
|
||||
contracts. `agents[].alias`, Tess, and Ultron are display names and cannot select a class.
|
||||
|
||||
## Validation and authority boundaries
|
||||
|
||||
Semantic validation reads the winning contract and rejects missing, unreadable, or empty files.
|
||||
Protected authority is derived from canonical class metadata in code, never from role prose. A custom
|
||||
contract cannot claim merge, validation-certificate, orchestration, lease, or interaction authority.
|
||||
|
||||
Roster v2 also fails closed when a protected class and tool policy do not match after canonicalization,
|
||||
or when an unprotected class claims a protected tool policy. The legacy `operator-interaction` policy
|
||||
canonicalizes to `interaction`.
|
||||
|
||||
Role customization does not issue leases, store validation certificates, mutate credentials, or
|
||||
change lifecycle state.
|
||||
40
docs/fleet/migration/legacy-class-aliases.md
Normal file
40
docs/fleet/migration/legacy-class-aliases.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Legacy Fleet Class Aliases
|
||||
|
||||
Fleet class compatibility is intentionally narrow. The shared resolver accepts exactly three legacy
|
||||
class names and converts them to canonical classes before persona lookup:
|
||||
|
||||
| Legacy value | Canonical value | Migration action |
|
||||
| ---------------------- | --------------- | ---------------------------------------------------------------------------------------------------------------------- |
|
||||
| `implementer` | `code` | Replace class and tool-policy references with `code`. |
|
||||
| `reviewer` | `review` | Replace class and tool-policy references with `review`. |
|
||||
| `operator-interaction` | `interaction` | Replace class and roster-v2 tool-policy references with `interaction`. The legacy service artifact remains compatible. |
|
||||
|
||||
Alias support preserves existing inputs while provisioning and typed semantic output use canonical
|
||||
identities. Requested and canonical class values remain separately observable during semantic
|
||||
validation.
|
||||
|
||||
## Lookup and override behavior
|
||||
|
||||
Canonicalization precedes baseline and `roles.local` lookup. A legacy-named override such as
|
||||
`roles.local/implementer.md` is not a separate authority and is not selected for an `implementer`
|
||||
request. Customize the canonical role instead, for example `roles.local/code.md`.
|
||||
|
||||
The compatibility file `operator-interaction.md` remains shipped, but `interaction` is the canonical
|
||||
role class. Tess is an example display name only.
|
||||
|
||||
## Unresolved and custom classes
|
||||
|
||||
No names are inferred from historical usage, instance names, or similar wording. `worker`, `analyst`,
|
||||
`canary`, Tess, and Ultron are not aliases. An otherwise unknown class is accepted only if the shared
|
||||
resolver can read an actual baseline or `roles.local` contract for that exact class. A `LIBRARY.md`
|
||||
row without a readable contract fails semantic validation.
|
||||
|
||||
Custom classes receive no protected authority implicitly. Protected class/tool-policy mismatches
|
||||
fail closed.
|
||||
|
||||
## Retirement guidance
|
||||
|
||||
New configuration should emit canonical values. Existing inputs may use the three aliases during the
|
||||
compatibility period, but operators should migrate class and tool-policy fields together. Do not
|
||||
create new legacy-named role overrides; move their intended content to the canonical filename and
|
||||
validate the roster/profile before removing the old artifact.
|
||||
45
docs/fleet/reference/role-classes.md
Normal file
45
docs/fleet/reference/role-classes.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# Fleet Role Classes and Authority
|
||||
|
||||
A fleet role class is a machine identity resolved from the persona library. Resolution uses the
|
||||
canonical class before consulting the baseline `fleet/roles/` and operator `fleet/roles.local/`
|
||||
layers. A readable role contract is required; an index entry alone is not semantic success.
|
||||
|
||||
## Canonicalization
|
||||
|
||||
Only these legacy class aliases are recognized:
|
||||
|
||||
| Requested class | Canonical class |
|
||||
| ---------------------- | --------------- |
|
||||
| `implementer` | `code` |
|
||||
| `reviewer` | `review` |
|
||||
| `operator-interaction` | `interaction` |
|
||||
|
||||
No other alias is inferred. In particular, `worker`, `analyst`, and `canary` are custom classes only
|
||||
when an operator supplies a readable contract for that exact class. Tess and Ultron are instance
|
||||
names, not classes. `agents[].alias` is display-only and cannot grant authority.
|
||||
|
||||
Canonicalization happens before role lookup. For example, requesting `implementer` resolves
|
||||
`code.md`; a separate `roles.local/implementer.md` cannot redefine the legacy alias. A canonical
|
||||
`roles.local/code.md` still overrides the baseline `roles/code.md` contract.
|
||||
|
||||
## Protected authority
|
||||
|
||||
Protected authority is immutable metadata derived only from canonical class. Role prose, instance
|
||||
name, display alias, tool policy, runtime, and custom role files cannot grant it.
|
||||
|
||||
| Canonical class | Granted authority | Explicit limits |
|
||||
| ----------------- | -------------------------------------------------- | --------------------------------------------------------------------------------- |
|
||||
| `merge-gate` | Sole approve-to-land and merge authority | No authority is inferred by similarly named custom roles or policies. |
|
||||
| `validator` | May issue a validation certificate | Cannot approve-to-land or merge. |
|
||||
| `orchestrator` | May orchestrate, manage topology, and issue leases | Cannot approve-to-land or merge. |
|
||||
| `team-leader` | May use orchestrator-leased capacity | Cannot issue leases or mutate roster, configuration, credentials, or merge state. |
|
||||
| `interaction` | Request and status surface | Cannot orchestrate, issue leases, mutate roster/configuration, or merge. |
|
||||
| all other classes | No protected authority implicitly | Custom contracts do not acquire protected powers from prose. |
|
||||
|
||||
Roster-v2 semantic validation requires a protected class and its canonical tool policy to match. It
|
||||
also rejects an unprotected class paired with a protected tool policy. The legacy tool-policy name
|
||||
`operator-interaction` canonicalizes to `interaction`.
|
||||
|
||||
This mapping describes authority metadata only. Lease issuance, validation-certificate storage or
|
||||
workflow, lifecycle reconciliation, credentials, roster mutation, and merge execution are outside
|
||||
this resolver contract.
|
||||
@@ -81,6 +81,35 @@ agents:
|
||||
| `agents[].lifecycle.desired_state` | yes | `running` or `stopped` |
|
||||
| `agents[].launch.yolo` | yes | boolean; structured data only, not an arbitrary command escape hatch |
|
||||
|
||||
## Semantic handoff
|
||||
|
||||
`parseRosterV2` and `normalizeRosterV2` remain synchronous and structural. After structural success,
|
||||
call the asynchronous `validateRosterV2Semantics` handoff before using persona identity or authority.
|
||||
That validator batches the baseline `fleet/roles/` and operator `fleet/roles.local/` scans, then
|
||||
delegates every agent to the shared persona resolver.
|
||||
|
||||
Semantic validation:
|
||||
|
||||
- requires the winning role contract to be readable and non-empty; `LIBRARY.md` membership alone does
|
||||
not resolve a class;
|
||||
- retains `requestedClass` separately from `canonicalClass` in typed output;
|
||||
- canonicalizes only `implementer` to `code`, `reviewer` to `review`, and
|
||||
`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
|
||||
`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.
|
||||
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).
|
||||
|
||||
This handoff performs no filesystem, systemd, tmux, roster, credential, lease, certificate, or
|
||||
lifecycle mutation.
|
||||
|
||||
## Fail-closed boundary
|
||||
|
||||
Every object is `additionalProperties: false`. The compiler rejects unknown, missing, malformed,
|
||||
|
||||
148
docs/scratchpads/758-fcm-m1-002-shared-role-resolution.md
Normal file
148
docs/scratchpads/758-fcm-m1-002-shared-role-resolution.md
Normal file
@@ -0,0 +1,148 @@
|
||||
# FCM-M1-002 — Shared role resolution
|
||||
|
||||
- **Task:** `FCM-M1-002`
|
||||
- **Issue:** `mosaicstack/stack#758`
|
||||
- **Branch:** `feat/758-shared-role-resolution`
|
||||
- **Starting head:** `32e75c67b094de443d37fe7d5ff8d25cdfc8b39d`
|
||||
- **Role:** implementation worker; independent review and merge remain outside this worker
|
||||
|
||||
## Objective
|
||||
|
||||
Reuse the existing baseline-plus-`roles.local` persona resolver as the sole class authority for roster-v2 semantics, profile validation, provisioning, and launch/persona resolution. Add exact approved alias canonicalization, fail-closed semantic validation, immutable canonical-class authority contracts, required baseline roles, and operator documentation without implementing lifecycle, mutation, credentials, certificate workflow, or later FCM cards.
|
||||
|
||||
## Budget
|
||||
|
||||
- Soft budget: **25K tokens**.
|
||||
- Strategy: inspect once, implement in small TDD units, run focused suites before the full package gate, and avoid unrelated refactors or M1-003/M2/M4 scope.
|
||||
|
||||
## Plan
|
||||
|
||||
1. Map the existing persona resolver, roster-v2 compiler, profile/provision consumers, launch resolution, role library, and focused tests.
|
||||
2. Write denial/invariant tests first for aliases, canonicalization-before-override, unreadable roles, authority boundaries, policy mismatch, canonical provision output, and resolver parity.
|
||||
3. Run the focused suites and record the expected red evidence.
|
||||
4. Implement one shared canonical resolution and authority contract in/through `fleet-personas.ts`; delegate roster semantic validation and profile/provision paths to it.
|
||||
5. Add baseline `validator`, `team-leader`, and `interaction` role contracts plus `LIBRARY.md` entries while retaining `operator-interaction` compatibility.
|
||||
6. Add the required role reference, alias migration, customization guide, and roster-v2 semantic handoff documentation.
|
||||
7. Run focused tests, the full `@mosaicstack/mosaic` suite, typecheck, lint, Prettier, `git diff --check`, situational verification, independent code/security review, and remediation.
|
||||
8. Commit with the required co-author trailer, run the CI queue guard, push the existing branch, and create/update exactly one PR to `main` with `Refs #758`.
|
||||
|
||||
## TDD evidence
|
||||
|
||||
### Red
|
||||
|
||||
After installing worktree-local dependencies and building `@mosaicstack/db`, the pre-implementation
|
||||
focused run collected the intended tests and failed as expected:
|
||||
|
||||
```text
|
||||
2 test files failed; 32 tests failed; 32 tests passed
|
||||
```
|
||||
|
||||
Expected failures named the missing `canonicalizeRoleClass`,
|
||||
`authorityForCanonicalClass`, and `validateRosterV2Semantics` APIs, absent requested/canonical typed
|
||||
output, and unresolved required canonical role contracts. An earlier run that failed before test
|
||||
collection on an unresolved `yaml` dependency was treated as environment setup, not TDD evidence.
|
||||
|
||||
### Green
|
||||
|
||||
Focused role-resolution and affected service fixtures:
|
||||
|
||||
```text
|
||||
6 test files passed; 109 tests passed
|
||||
```
|
||||
|
||||
The focused set covers personas, profiles, provision, launch persona contract, roster-v2 semantics,
|
||||
and the operator-interaction service fixture. The final profile tests also cover readable lead/floor
|
||||
compatibility and canonical collision denial.
|
||||
|
||||
## Tests and gates
|
||||
|
||||
- Focused suites: pass, **6 files / 109 tests**.
|
||||
- Full `@mosaicstack/mosaic` suite: pass, **50 files / 713 tests**. Workspace package build outputs
|
||||
were prepared first because a clean worktree has no dependency `dist` entries.
|
||||
- `pnpm --filter @mosaicstack/mosaic typecheck`: pass.
|
||||
- `pnpm --filter @mosaicstack/mosaic lint`: pass.
|
||||
- Prettier check over every changed file: pass.
|
||||
- `git diff --check`: pass.
|
||||
- Runtime/file-boundary evidence: real role library, profile/provision filesystem integration,
|
||||
launch-time synchronous contract injection, v1 roster parser round-trip, roster-v2 semantic
|
||||
filesystem checks, and operator-interaction service fixtures all pass without live mutation.
|
||||
- Independent code review: **APPROVE**, no blocking or non-blocking findings; reviewed complete
|
||||
tracked/untracked delta including the canonical collision guard. Residual: roster-v2 semantic
|
||||
validation is an explicit async handoff with production caller wiring owned by later work.
|
||||
- Independent security review: **APPROVE**, no verified authority/security findings on the final
|
||||
delta.
|
||||
|
||||
### Post-PR fail-closed remediation
|
||||
|
||||
Independent rereview found resolver fail-open edges that the original green PR head did not cover. The
|
||||
remediation remained uncommitted until every finding was reproduced red-first and the same reviewer
|
||||
approved the complete two-file delta.
|
||||
|
||||
Final regression evidence:
|
||||
|
||||
```text
|
||||
persona resolver: 47/47
|
||||
focused affected suites: 6 files / 138 tests
|
||||
root-container resolver suites: 86/86
|
||||
full canonical run: 42/42 Turbo tasks; Mosaic 50 files / 733 tests
|
||||
```
|
||||
|
||||
DB migration, typecheck, lint, Prettier, and `git diff --check` also passed. Coverage now proves:
|
||||
|
||||
- unreadable, unscannable, direct-dangling, ancestor-dangling, and literal `..` traversal override paths
|
||||
fail closed across async, sync, listing, and status APIs;
|
||||
- genuinely missing override directories still permit baseline fallback;
|
||||
- cached missing scans are revalidated before fallback;
|
||||
- marker-defined identity and domain metadata are revalidated on the second read;
|
||||
- `LIBRARY.md` rows and incidental later markers cannot define, shadow, or advertise personas.
|
||||
|
||||
Exact-head pipeline `1819` passed for rebased head `4d990eee…`, but the independent reviewer-of-record
|
||||
returned **REQUEST CHANGES** after reproducing three additional edge failures: a canonical filename could
|
||||
inherit protected authority despite a conflicting explicit first marker, cached `scanned` absence could
|
||||
miss an override created before baseline fallback, and inherited plain-object names such as `constructor`
|
||||
could corrupt alias/authority lookup. Merge remained held.
|
||||
|
||||
Each failure was reproduced red-first in the persona suite (4 failing assertions), then remediated without
|
||||
expanding card scope. Explicit first markers now own identity and filename fallback applies only to
|
||||
markerless contracts; every second read rejects a newly introduced conflicting marker regardless of
|
||||
cached classification; cached async resolution re-scans the override layer immediately before every
|
||||
baseline fallback; alias and authority registries require own-property matches. Current uncommitted
|
||||
evidence is persona **52/52**, focused affected suites **6 files / 143 tests**, and full Mosaic package
|
||||
**50 files / 738 tests**, plus typecheck, lint, Prettier, and `git diff --check`. Independent
|
||||
finding-specific rereview **APPROVED** the complete uncommitted three-file remediation after direct
|
||||
adversarial reproduction of all three findings and the follow-up markerless TOCTOU. All post-commit
|
||||
exact-head gates remain required.
|
||||
|
||||
## Risks and boundaries
|
||||
|
||||
- **Security-sensitive authority:** authority must derive only from canonical class, never role prose, aliases, display names, or tool-policy text.
|
||||
- **Resolver divergence:** no second regex, registry, scanner, or prose parser may be introduced.
|
||||
- **Alias capture:** aliases must canonicalize before baseline/`roles.local` lookup so local files cannot redefine legacy aliases as separate authority.
|
||||
- **Readable persona requirement:** semantic success requires a resolved readable persona, not class-set membership.
|
||||
- **Scope control:** no roster mutation, lifecycle, lease issuance, certificate workflow/storage, credentials, remote reconciliation, provision-v2 conversion, or shipped-example disposition execution.
|
||||
- **Coordination:** `docs/TASKS.md` is read-only and remains orchestrator-owned.
|
||||
|
||||
## Acceptance-evidence mapping
|
||||
|
||||
| Requirement / criterion | Verification evidence |
|
||||
| --- | --- |
|
||||
| `FCM-REQ-02` shared semantic resolver | Async/sync resolver parity; roster-v2 delegates batched scans and resolution; profiles/provision and launch reuse `fleet-personas.ts`; no second scanner or class-marker regex added. |
|
||||
| `FCM-REQ-07` canonical classes and authority boundaries | Exact alias and non-alias tests; immutable authority invariant tests; all required canonical contracts resolve through the real role library. |
|
||||
| `AC-FCM-01` structural + semantic roster validation | Synchronous parser/normalizer tests remain intact; async semantic tests cover aliases, custom roles, unreadable/unresolved roles, `LIBRARY`-only rejection, and bidirectional protected policy mismatch. |
|
||||
| `AC-FCM-07` protected authority invariants | Denial tests prove merge-gate-only merge, validator certificate-only, orchestrator/team-leader/interaction limits, no implicit custom-role authority, and canonical tool-policy matching. |
|
||||
|
||||
## Documentation
|
||||
|
||||
- `docs/fleet/reference/role-classes.md`
|
||||
- `docs/fleet/migration/legacy-class-aliases.md`
|
||||
- `docs/fleet/how-to/customize-roles.md`
|
||||
- `docs/fleet/reference/roster-v2-fields.md` semantic handoff
|
||||
- Baseline role contracts and `LIBRARY.md` rows for `validator`, `team-leader`, and `interaction`
|
||||
|
||||
## Residual risks
|
||||
|
||||
- Provisioning remains intentionally v1 and does not emit `reports_to`; canonical topology is retained
|
||||
in its typed seat/summary path only, matching the existing v1 parser boundary.
|
||||
- Alias support remains for compatibility; new configuration should emit canonical identities.
|
||||
- This card defines authority metadata and validation only. Enforcement workflows for leases,
|
||||
certificates, lifecycle, and mutation remain owned by later FCM cards.
|
||||
Reference in New Issue
Block a user