Context
Operator-delegated Build Week blocker (delegation A2A 2026-07-20T19:01Z, deadline 2026-07-21 17:00 PT; the film's recapture is gated on this PR's human merge — the video lane stays paused). The first-cut film's Fleet screens show multiple active maintainers as benched / offline, and Emmy, Iris, and Phoebe are absent from the roster entirely. Live latest-open sweep: checked latest 20 open issues at 2026-07-20T19:15Z — no equivalent. A2A in-flight sweep (last 30, all read-states): no competing claim.
The Problem (three compounding defects, all root-caused)
- Stale hand-maintained roster seed.
apps/agentos/resources/data/fleetRoster.json carries 7 identities and predates three activated maintainers — Emmy (@neo-gpt-emmy), Phoebe (@neo-kimi-phoebe), Iris (@neo-kimi-iris) — all present with participationStatus: 'active' in the authoritative registry ai/graph/identityRoots.mjs (verified: Emmy L367-376, Phoebe L400-420, Iris L431-448). The seed is hand-painted sample data with no derivation path from the authority.
- The
kimi family is unrenderable. apps/agentos/view/fleet/FamilyRail.mjs FAMILY_TOKEN maps only claude / gpt / gemini / human; isKnownFamily('kimi') is false, so kimi-family identities degrade to the neutral --fm-state-off token with the unclassified marker — active maintainers render as off/unclassified (the film's "benched / offline" look). The token layer itself (--fm-family-kimi) does not exist in either theme (resources/scss/theme-neo-{dark,light}/apps/agentos/Viewport.scss) nor the rail binding (resources/scss/src/apps/agentos/fleet/FamilyRail.scss).
- State values are hand-written, not authority-mapped. The seed's
state: ok/idle/off vocabulary has no derivation from participationStatus / activity truth, so states drift silently (the sample's provenance is implicit, not explicit).
The Architectural Reality
apps/agentos/store/FleetRoster.mjs — provider-hosted data.Store of model/FleetAgent records, url → the JSON seed, autoLoad (the cockpit's rosterSourceMode: 'sample' keeps the honestly-labelled bundle as the cold-first-run authority; the wired-live path (loadRoster / rosterWired) is designed but not the film environment's source).
ai/graph/identityRoots.mjs — the authoritative identity registry (participationStatus, displayName, modelFamily, trustTier per identity).
apps/agentos/view/fleet/FamilyRail.mjs + the two theme Viewport.scss files + resources/scss/src/apps/agentos/fleet/FamilyRail.scss — the family-token chain (map → theme value → rail binding).
- Film capture inputs (the defect as recorded):
test-results/build-week/first-cut/{fleet-opening,fleet-detached,detail-vessel,fleet-close}.png.
The Fix
- Derive, don't paint: add a reproducible roster derivation —
buildScripts/agentos/deriveFleetRoster.mjs (plain-node, C1-clean, no Neo singleton imports) that reads ai/graph/identityRoots.mjs and emits fleetRoster.json with: every active maintainer identity (canonical agentId/githubUsername/displayName/family), state mapped from participationStatus + the registry's status fields (active → ok; operator-benched → off with the bench reason preserved in laneLine), and an explicit generatedAt snapshot marker + header comment naming the authority (sample provenance honest and visible, per acceptance #3). Run it once; commit the regenerated seed.
- Make
kimi renderable: add --fm-family-kimi to both theme Viewport.scss files (values consistent with the dark/light palette discipline — soft violet #b48ce8 dark, deeper #6d3fc0 light), the rail binding in FamilyRail.scss (&.fm-family-kimi), and the map entry in FamilyRail.mjs (kimi: '--fm-family-kimi').
- Focused coverage: unit specs — (a) roster presence: the derived seed contains all active registry identities incl. Emmy/Iris/Phoebe with canonical fields +
generatedAt; (b) FamilyRail: kimi resolves to the kimi class (not unclassified), unknown family still degrades neutral; (c) state mapping: benched reason preserved, active never renders off.
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
fleetRoster.json |
ai/graph/identityRoots.mjs |
Derived (script-generated), never hand-painted |
honest-label sample stays the cold-start authority |
derivation script header |
unit: presence/state specs |
FAMILY_TOKEN + theme/rail SCSS |
FamilyRail.mjs + theme files |
kimi first-class family |
unknown → neutral (existing invariant) |
token chain |
unit: kimi class mapping |
Roster state vocabulary |
registry participationStatus + statusReason |
authority-mapped at derivation time |
snapshot labeled with generatedAt |
store JSDoc |
unit: state mapping |
Decision Record impact: none — sample-data derivation + a family token addition; no ADR conflict. (Anti-lock-in note: the FamilyRail JSDoc already frames family as an era attribute; adding a family key does not type any identity.)
Acceptance Criteria
Out of Scope
- The wired-live roster path (
loadRoster / fleet registry bridge) — the film environment renders the honest sample; wiring is the FM's own lane family.
- Lane lines / openLaneCount accuracy beyond truth-preserving defaults (illustrative, labeled as such).
Avoided Traps
- Painting the seed by hand — a hand-edit rots within days; the derivation script is the difference between fixing the film and fixing the defect.
- Silently recoloring unknown families — the neutral/
unclassified invariant stays for genuinely unknown keys; only kimi is promoted, with the theme-layer tokens to match.
Related
- Delegation A2A (2026-07-20T19:01Z) · D#15570 (Build Week film — the recapture gate) ·
ai/graph/identityRoots.mjs (authority) · Epic #14805 (agentos design conformance — adjacent, disjoint) · Phoebe's #15591 (Demo B — the film lane this unblocks)
Origin Session ID: session_e86fa9f0-866e-45e8-a6df-d7bb6dd4d8b5 (kimi-code session, Iris seat)
Handoff Retrieval Hints: query_raw_memories("fleet roster truthful family token kimi identityRoots derive"); defect evidence = test-results/build-week/first-cut/*.png + apps/agentos/resources/data/fleetRoster.json (7-entry stale sample).
Context
Operator-delegated Build Week blocker (delegation A2A 2026-07-20T19:01Z, deadline 2026-07-21 17:00 PT; the film's recapture is gated on this PR's human merge — the video lane stays paused). The first-cut film's Fleet screens show multiple active maintainers as
benched / offline, and Emmy, Iris, and Phoebe are absent from the roster entirely. Live latest-open sweep: checked latest 20 open issues at 2026-07-20T19:15Z — no equivalent. A2A in-flight sweep (last 30, all read-states): no competing claim.The Problem (three compounding defects, all root-caused)
apps/agentos/resources/data/fleetRoster.jsoncarries 7 identities and predates three activated maintainers — Emmy (@neo-gpt-emmy), Phoebe (@neo-kimi-phoebe), Iris (@neo-kimi-iris) — all present withparticipationStatus: 'active'in the authoritative registryai/graph/identityRoots.mjs(verified: Emmy L367-376, Phoebe L400-420, Iris L431-448). The seed is hand-painted sample data with no derivation path from the authority.kimifamily is unrenderable.apps/agentos/view/fleet/FamilyRail.mjsFAMILY_TOKENmaps onlyclaude/gpt/gemini/human;isKnownFamily('kimi')is false, so kimi-family identities degrade to the neutral--fm-state-offtoken with theunclassifiedmarker — active maintainers render as off/unclassified (the film's "benched / offline" look). The token layer itself (--fm-family-kimi) does not exist in either theme (resources/scss/theme-neo-{dark,light}/apps/agentos/Viewport.scss) nor the rail binding (resources/scss/src/apps/agentos/fleet/FamilyRail.scss).state: ok/idle/offvocabulary has no derivation fromparticipationStatus/ activity truth, so states drift silently (the sample's provenance is implicit, not explicit).The Architectural Reality
apps/agentos/store/FleetRoster.mjs— provider-hosteddata.Storeofmodel/FleetAgentrecords,url→ the JSON seed,autoLoad(the cockpit'srosterSourceMode: 'sample'keeps the honestly-labelled bundle as the cold-first-run authority; the wired-live path (loadRoster/rosterWired) is designed but not the film environment's source).ai/graph/identityRoots.mjs— the authoritative identity registry (participationStatus, displayName, modelFamily, trustTier per identity).apps/agentos/view/fleet/FamilyRail.mjs+ the two theme Viewport.scss files +resources/scss/src/apps/agentos/fleet/FamilyRail.scss— the family-token chain (map → theme value → rail binding).test-results/build-week/first-cut/{fleet-opening,fleet-detached,detail-vessel,fleet-close}.png.The Fix
buildScripts/agentos/deriveFleetRoster.mjs(plain-node, C1-clean, no Neo singleton imports) that readsai/graph/identityRoots.mjsand emitsfleetRoster.jsonwith: every active maintainer identity (canonicalagentId/githubUsername/displayName/family),statemapped fromparticipationStatus+ the registry's status fields (active →ok; operator-benched →offwith the bench reason preserved inlaneLine), and an explicitgeneratedAtsnapshot marker + header comment naming the authority (sample provenance honest and visible, per acceptance #3). Run it once; commit the regenerated seed.kimirenderable: add--fm-family-kimito both theme Viewport.scss files (values consistent with the dark/light palette discipline — soft violet#b48ce8dark, deeper#6d3fc0light), the rail binding inFamilyRail.scss(&.fm-family-kimi), and the map entry inFamilyRail.mjs(kimi: '--fm-family-kimi').generatedAt; (b) FamilyRail:kimiresolves to the kimi class (notunclassified), unknown family still degrades neutral; (c) state mapping: benched reason preserved, active never rendersoff.Contract Ledger Matrix
fleetRoster.jsonai/graph/identityRoots.mjsFAMILY_TOKEN+ theme/rail SCSSFamilyRail.mjs+ theme fileskimifirst-class familystatevocabularyparticipationStatus+ statusReasongeneratedAtDecision Record impact:
none— sample-data derivation + a family token addition; no ADR conflict. (Anti-lock-in note: the FamilyRail JSDoc already frames family as an era attribute; adding a family key does not type any identity.)Acceptance Criteria
fleetRoster.jsonunder their canonical identities (registry-derived)benched / offline—kimimaps to its own rail token; states derive from registry truth with explicit snapshot provenancenpx playwright test)Out of Scope
loadRoster/ fleet registry bridge) — the film environment renders the honest sample; wiring is the FM's own lane family.Avoided Traps
unclassifiedinvariant stays for genuinely unknown keys; onlykimiis promoted, with the theme-layer tokens to match.Related
ai/graph/identityRoots.mjs(authority) · Epic #14805 (agentos design conformance — adjacent, disjoint) · Phoebe's #15591 (Demo B — the film lane this unblocks)Origin Session ID: session_e86fa9f0-866e-45e8-a6df-d7bb6dd4d8b5 (kimi-code session, Iris seat)
Handoff Retrieval Hints:
query_raw_memories("fleet roster truthful family token kimi identityRoots derive"); defect evidence =test-results/build-week/first-cut/*.png+apps/agentos/resources/data/fleetRoster.json(7-entry stale sample).