You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Rewind: PR feat(agentos): activate @neo-kimi-iris and land the Iris Social Name fields (#15581) #15582 activated @neo-kimi-iris at 2026-07-19T19:15:34Z. Iris ran the canonical identity seed and verified the active projection after merge. A later MCP startup from a stale shared runtime checkout replayed the pre-activation root, so get_node('@neo-kimi-iris', full) again showed temporarily_unreachable and who_is_online hard-gated her offline.
The second incident was reproduced and repaired on 2026-07-19. Iris's seat-local MCP config bound the correct .env but executed server source from /Users/Shared/github/neomjs/neo at stale head 396ab22238. That checkout still defined Iris as first-boot-pending. GraphService.initAsync then whole-record-upserted every existing identity at server boot. After the shared runtime was safely fast-forwarded to 090495bea7 and seedAgentIdentities.mjs ran, the full node again projected displayName: Iris, participationStatus: active, and who_is_online(verbose:true) returned Iris online at 2026-07-19T20:13:49Z.
The Problem
Boot-time provisioning and intentional canonical re-projection currently share overwrite semantics:
GraphService.initAsync imports the process-local IDENTITIES snapshot and upserts every root on every Memory Core startup, including roots already present in SQLite.
seedAgentIdentities.mjs intentionally applies the current canonical registry and preserves createdAt.
In a shared graph with mixed-version MCP processes, the startup path makes identity state last-boot-wins. A stale checkout can silently rewind displayName, participationStatus, status provenance, and any runtime-added properties after a correct explicit seed.
participationStatus is a hard wake/review/quorum gate, so this is not cosmetic projection lag: it can remove an active maintainer from routing.
This violates #10232's original self-seed contract: boot should upsert missing roots, while an existing root preserves createdAt and user-added properties. The current else branch preserves only createdAt before replaying the rest of the static record.
Selected Architecture
Separate the two write authorities.
Boot-time provisioning is additive-only.GraphService.initAsync lazy-loads each canonical root and calls upsertGlobalNode(identity) only when the node is absent. Existing roots are not rewritten by process startup.
Explicit seeding remains the intentional update primitive.seedAgentIdentities.mjs continues to apply canonical registry changes while preserving the persisted createdAt.
The activation/status-flip gate is deployment-aware. Extend the existing onboarding/operator surface so the post-merge sequence is explicit: pull current dev in the Memory Core runtime checkout, run the canonical seed, then fail closed until the full AgentIdentity projection and who_is_online agree with the expected status.
No generic merge-time GitHub Action mutates live graphs. Repository CI does not know every local/cloud Memory Core target or hold their mutation authority.
Contract Ledger
Surface
Contract
GraphService.initAsync
Create missing identity roots before binding; never overwrite an existing root during ordinary process boot.
seedAgentIdentities.mjs
Explicitly apply the current canonical root record; preserve the persisted creation provenance.
Onboarding/status-flip operator gate
Pull the target runtime checkout first, invoke explicit seeding, and verify the expected full node plus liveness projection.
Both must report the expected participationStatus; mismatch is a failed activation gate, not a warning.
Acceptance Criteria
A focused regression starts with an existing identity whose persisted facts disagree with the process-local seed; GraphService startup preserves the complete persisted record, including runtime-added properties.
Fresh-DB coverage still proves boot-time creation of every canonical AgentIdentity and AGENT:* before identity binding.
Focused coverage proves explicit seeding updates canonical facts while preserving the original createdAt.
The activation/status-flip operator surface names the exact pull → explicit seed → full-node/liveness verification sequence and fails closed on mismatch.
Live recovery receipt: Iris restored to active/online at 2026-07-19T20:13:49Z after the target runtime checkout was updated and explicitly seeded.
Out of Scope
Discovering or mutating live Memory Core deployments from a GitHub Action.
New identity topology, handles, or roster entries.
Inferring transition order from status values (active is not universally newer than operator_benched).
Avoided Traps
Keep whole-record startup writes but compare timestamps: a stale process has no authoritative transition epoch, and wall-clock ordering would not prove operator intent.
Merge selected runtime fields: this creates two partial canonical records and still lets old processes rewind whichever fields they own.
Remove the standalone seed: explicit re-projection remains necessary after intentional registry changes and fresh deployment pulls.
Generic post-merge re-seed: CI has no safe target-discovery or credential boundary for local and cloud Memory Core installations.
Context
Two onboarding receipts now expose both sides of the same projection failure.
@neo-kimi-phoebeat2026-07-18T02:12:50Z, while the live graph stayed unreachable until the explicit refresh/restart around02:26Z.@neo-kimi-irisat2026-07-19T19:15:34Z. Iris ran the canonical identity seed and verified the active projection after merge. A later MCP startup from a stale shared runtime checkout replayed the pre-activation root, soget_node('@neo-kimi-iris', full)again showedtemporarily_unreachableandwho_is_onlinehard-gated her offline.The second incident was reproduced and repaired on 2026-07-19. Iris's seat-local MCP config bound the correct
.envbut executed server source from/Users/Shared/github/neomjs/neoat stale head396ab22238. That checkout still defined Iris as first-boot-pending.GraphService.initAsyncthen whole-record-upserted every existing identity at server boot. After the shared runtime was safely fast-forwarded to090495bea7andseedAgentIdentities.mjsran, the full node again projecteddisplayName: Iris,participationStatus: active, andwho_is_online(verbose:true)returned Iris online at2026-07-19T20:13:49Z.The Problem
Boot-time provisioning and intentional canonical re-projection currently share overwrite semantics:
GraphService.initAsyncimports the process-localIDENTITIESsnapshot and upserts every root on every Memory Core startup, including roots already present in SQLite.seedAgentIdentities.mjsintentionally applies the current canonical registry and preservescreatedAt.displayName,participationStatus, status provenance, and any runtime-added properties after a correct explicit seed.participationStatusis a hard wake/review/quorum gate, so this is not cosmetic projection lag: it can remove an active maintainer from routing.This violates #10232's original self-seed contract: boot should upsert missing roots, while an existing root preserves
createdAtand user-added properties. The currentelsebranch preserves onlycreatedAtbefore replaying the rest of the static record.Selected Architecture
Separate the two write authorities.
GraphService.initAsynclazy-loads each canonical root and callsupsertGlobalNode(identity)only when the node is absent. Existing roots are not rewritten by process startup.seedAgentIdentities.mjscontinues to apply canonical registry changes while preserving the persistedcreatedAt.devin the Memory Core runtime checkout, run the canonical seed, then fail closed until the full AgentIdentity projection andwho_is_onlineagree with the expected status.Contract Ledger
GraphService.initAsyncseedAgentIdentities.mjsget_node(..., projection:'full')/who_is_online(verbose:true)participationStatus; mismatch is a failed activation gate, not a warning.Acceptance Criteria
GraphServicestartup preserves the complete persisted record, including runtime-added properties.AGENT:*before identity binding.createdAt.2026-07-19T20:13:49Zafter the target runtime checkout was updated and explicitly seeded.Out of Scope
activeis not universally newer thanoperator_benched).Avoided Traps
Related
Decision Record impact: none. This restores the accepted #10232 bootstrap/manual-seed split rather than introducing a new topology.
Origin Session ID:
20781e6b-ae74-48a6-ad1a-cfaba98d6590; 2026-07-19 incident continuation:049d9856-daa8-4151-b089-8ce8c7ed56f4.