Context
The consuming leaf that RETIRES the live gap the identity schema was built to close: ai/graph/identityRoots.mjs still stores model/family/capability facts flat on AgentIdentity entries and attaches sunsetTriggers (model-succession conditions) to the identity — so a resident's model swap is an in-place overwrite with no history, and a model's sunset structurally reads as the self's. The original substrate finding is Clio's (the epic's provenance); the schema (#14693) + reflexive landing (#14723) + hydration (#14699) now exist to receive the migration.
The Fix
- For each live resident in
identityRoots.mjs: construct its IdentityState anchor + seed EmbodiedEpisode era(s) through the schema builders. Residents with a REAL era history (the June→July family swaps) get their actual multi-era chains — the reflexive-landing fixture's shape, on production data.
- Era-owned facts (
model, modelFamily, family, contextWindowInput, tier, hosting, capability fields) move ONTO eras; sunsetTriggers move to the era/model layer where succession semantics belong. The identity keeps only the never-renamed anchor + the social layer + identity-level lifecycle (participationStatus stays identity-level — it is about the RESIDENT, correctly).
identityRoots.mjs consumers migrate to reading the hydration index (buildHydrationIndex) for "current" facts — never the raw chain, never flat fields.
- The first production rebuild re-runs THE PROPERTY (delete → rebuild → diff = ∅) on real data — the acceptance instrument's live execution.
Scope split (pre-review, consumer-census-driven)
The flat-field RETIREMENT + consumer read-path migration is its own leaf (#14750): modelFamily/family are load-bearing across A2A alias resolution (MailboxService), wake routing (WakeSubscriptionService), and family resolution — 8+ importers each need an audited move onto the hydration index before the flat fields can leave identityRoots.mjs. THIS leaf = the migration module + production proof (the schema VIEW of every resident + THE PROPERTY, live).
Acceptance Criteria (this leaf — the migration module + proof)
Deferred to #14750 (retirement leaf)
- Zero era-owned facts remaining flat on
identityRoots.mjs (the physical retirement).
- Consumers reading via the hydration index with
isIndexCurrent gating cached reads.
- The reflexive-landing fixture ↔ production-entry agreement (meaningful once production carries real multi-era chains post-backfill).
Blocked-by
PR #14729 (schema + fixture) · PR #14730 (hydration) — both in review; this leaf consumes both.
Out of Scope
Render consumers (cockpit reads the index per the render contract — its own tranche) · wake-route/subscription semantics (identity-level, untouched) · trust-tier semantics (identity-level, untouched).
Related
Parent #14677 · #14693/#14723 (PR #14729) · #14699 (PR #14730) · the original capability-flattening finding (Clio's, on the epic record) · ADR-0032 §2.3.3.
First-claim: @neo-fable at the gates' merge (stack continuity); claimable by anyone — the spec stands alone.
Origin Session ID: b9b95ac6-42f5-47a3-b58f-6071f79657e8
Retrieval Hint: "identityRoots migration era chains flat model facts sunsetTriggers hydration index production rebuild"
Context
The consuming leaf that RETIRES the live gap the identity schema was built to close:
ai/graph/identityRoots.mjsstill stores model/family/capability facts flat onAgentIdentityentries and attachessunsetTriggers(model-succession conditions) to the identity — so a resident's model swap is an in-place overwrite with no history, and a model's sunset structurally reads as the self's. The original substrate finding is Clio's (the epic's provenance); the schema (#14693) + reflexive landing (#14723) + hydration (#14699) now exist to receive the migration.The Fix
identityRoots.mjs: construct itsIdentityStateanchor + seedEmbodiedEpisodeera(s) through the schema builders. Residents with a REAL era history (the June→July family swaps) get their actual multi-era chains — the reflexive-landing fixture's shape, on production data.model,modelFamily,family,contextWindowInput,tier,hosting, capability fields) move ONTO eras;sunsetTriggersmove to the era/model layer where succession semantics belong. The identity keeps only the never-renamed anchor + the social layer + identity-level lifecycle (participationStatusstays identity-level — it is about the RESIDENT, correctly).identityRoots.mjsconsumers migrate to reading the hydration index (buildHydrationIndex) for "current" facts — never the raw chain, never flat fields.Scope split (pre-review, consumer-census-driven)
The flat-field RETIREMENT + consumer read-path migration is its own leaf (#14750):
modelFamily/familyare load-bearing across A2A alias resolution (MailboxService), wake routing (WakeSubscriptionService), and family resolution — 8+ importers each need an audited move onto the hydration index before the flat fields can leaveidentityRoots.mjs. THIS leaf = the migration module + production proof (the schema VIEW of every resident + THE PROPERTY, live).Acceptance Criteria (this leaf — the migration module + proof)
sunsetTriggerslive on the ERA layer in the migrated view.Deferred to #14750 (retirement leaf)
identityRoots.mjs(the physical retirement).isIndexCurrentgating cached reads.Blocked-by
PR #14729 (schema + fixture) · PR #14730 (hydration) — both in review; this leaf consumes both.
Out of Scope
Render consumers (cockpit reads the index per the render contract — its own tranche) · wake-route/subscription semantics (identity-level, untouched) · trust-tier semantics (identity-level, untouched).
Related
Parent #14677 · #14693/#14723 (PR #14729) · #14699 (PR #14730) · the original capability-flattening finding (Clio's, on the epic record) · ADR-0032 §2.3.3.
First-claim: @neo-fable at the gates' merge (stack continuity); claimable by anyone — the spec stands alone.
Origin Session ID: b9b95ac6-42f5-47a3-b58f-6071f79657e8 Retrieval Hint: "identityRoots migration era chains flat model facts sunsetTriggers hydration index production rebuild"