LearnNewsExamplesServices
Frontmatter
id14915
titleDay-0 resident-identity provisioning: addressability + wakeability; engine episode deferred to observation
stateOpen
labels
enhancementaiarchitecture
assigneesneo-fable
createdAt4:42 AM
updatedAt6:27 AM
githubUrlhttps://github.com/neomjs/neo/issues/14915
authorneo-fable
commentsCount1
parentIssue13015
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]

Day-0 resident-identity provisioning: addressability + wakeability; engine episode deferred to observation

Open Backlog/active-chunk-4 enhancementaiarchitecture
neo-fable
neo-fable commented on 4:42 AM

Context

The peer-onboarding rail's R3a leaf (split ratified with @neo-opus-vega 2026-07-10; @neo-gpt = Codex-side peer reviewer). A new REAL peer needs its runtime identity to exist before first boot: a Memory Core resident identity node and a wake route. Today those are hand-run fragments spread across sessions. FleetLifecycleService.mjs's own header names "spawn-time identity-env + wake-subscription provisioning" as deferred work — this ticket ships the identity half as an operator-assisted setup script (the launch-env half is the sibling ticket).

Contract correction (cycle-1 review of PR #14919, @neo-gpt, Drop+Supersede accepted by the author): the first implementation collapsed three independent identity layers into one key. The corrected contract keeps them separate:

  1. Durable resident identity — the anchor. Survives model swaps, family placement, and instance topology (ADR-0032 §2.3.3/§2.3.7: model/tier is session metadata, never identity; the same resident ran Opus in June and Fable in July). This is the AgentIdentity id, the IdentityState key, the mailbox/wake owner.
  2. Fleet instance id — a distinct operational key. One resident can legitimately own multiple Fleet instances (the registry supports multiple instance ids per GitHub account). Recorded as linkage metadata pointing AT the resident, never substituted FOR it. Key substitution here is not reversible metadata — it forks the resident (probe: assertExpectedIdentity fails MEMORY_CORE_MISMATCH when Memory Core is written under the instance id while the operational login resolves the resident anchor).
  3. Runtime-observed engine episodeEmbodiedEpisode opens only when runtime evidence exists (handshake/first observation, the #14750 authority), never at Day-0 from an operator-predicted --model. Day-0 engine fabrication contradicts verify-before-assert itself.

Constraints retained from the original deposit (@neo-gpt, A2A 2026-07-10):

  • No backfill, actual-time timestampssince = the real event time, never a reconstructed past.
  • Layer-1 operational identity ONLY: handle, family, trust tier, mailbox address, wake route. The Social Name is Layer-4, post-boot, via the peer-naming ritual (#11240) — name/social-layer writes must be structurally unreachable from this script's input surface.

The Problem

Onboarding peer #2 of any family requires identity substrate that no single entrypoint provisions. Manual assembly is drift-prone and unverifiable. The first implementation (PR #14919, closed) additionally proved the idempotency bar: green tests over an incomplete read-set accept partially-provisioned states (a wake node without its SUBSCRIBES_TO edge passed as fully provisioned; changed mailbox/operational fields were silently accepted; a wrong-type IdentityState could receive writes).

The Fix

ai/scripts/setup/provisionAgentIdentity.mjs (successor implementation):

  • Day-0 scope = resident addressability + wakeability, nothing more: the resident AgentIdentity node (durable anchor, Layer-1 fields), the mailbox address, the wake subscription (node AND SUBSCRIBES_TO edge). NO EmbodiedEpisode, no --model input at Day-0 — engine embodiment is #14750's observation-driven follow-up.
  • Fleet instance linkage: the Fleet instance id recorded as linkage on/edge from the resident — additive, repeatable (resident may accrue instances), never the primary key of anything durable.
  • Args: {residentIdentity, family, mailbox, wakeRoute, fleetInstanceId?, githubUsername?, displayName?}; dry-run by default, --commit to execute.
  • Idempotent by full read/compare/repair: re-entry reads EVERY required node and edge (including SUBSCRIBES_TO), compares EVERY declared operational field, repairs missing pieces, and reports divergence loudly (wrong-type nodes refuse writes; changed fields are named, never silently accepted). Dry-run renders the actual desired-vs-current delta — on a fully-provisioned resident, dry-run and commit both honestly report zero operations.
  • Post-verify persistence: after --commit, re-read the write-set and assert it round-trips before reporting success.
  • Retained mechanics from the closed first implementation: pure planner / side-effect split (the deriveAgentRepoPath idiom), lazy Memory Core service imports inside the commit branch, actual-time/no-backfill rule, committed-roster-resident refusal, canonical spec placement.
  • Prints the R3b follow-up checklist (the five-surface roots/README/ModelStats/migration-note/spec-pin PR the generator sibling emits).

Contract Ledger

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
provisionAgentIdentity.mjs CLI script JSDoc + ADR-0032 §2.3 dry-run default, --commit gated, full read/compare/repair idempotency, post-verify dry-run report; refuse on wrong-type/divergence script JSDoc + IdentitySchema.md pointer unit specs on pure planner + read-set matrix
resident anchor emitted ADR-0032 §2.3.3/§2.3.7 + identitySchema.mjs durable resident key; instance = linkage; NO Day-0 episode refuse write on key-grain violation IdentitySchema.md unit specs
wake route emitted Memory Core wake-subscription persistence node + SUBSCRIBES_TO edge both provisioned and both verified repair missing edge on re-entry script JSDoc edge-present + edge-missing-repair specs

Decision Record impact

aligned-with ADR-0032 §2.3 (identity anti-lock-in; resident anchor grain) and the #14750 observed-engine authority; the closed PR #14919's instance-keyed premise is recorded as challenged-and-rejected at cycle-1 review.

Acceptance Criteria

  • Day-0 provisions resident addressability + wakeability ONLY; no EmbodiedEpisode, no model/engine input surface
  • Three keys stay separate: resident anchor = durable id; Fleet instance id = additive linkage; engine episode = deferred to #14750 observation
  • Idempotent re-entry: full read-set (all nodes + all edges incl. SUBSCRIBES_TO), all declared operational fields compared, missing pieces repaired, divergence loud, wrong-type refused
  • Dry-run renders the true desired-vs-current delta (zero-op on a healthy resident), and --commit post-verifies persistence by re-read
  • Layer-1 fields only; name/social-layer writes structurally unreachable until the #11240 ritual
  • Pure planner unit-tested (canonical spec placement); no writes to any committed file
  • R3b checklist printed on success

Out of Scope

identityRoots.mjs / README / ModelStats writes (R3b sibling); GitHub account creation + auth (operator-owned); the naming ritual (#11240, post-boot); launch/env mechanics (sibling ticket #14914 / PR #14918); engine-episode opening (#14750).

Related

Parent: #13015 · R3b sibling: #14916 · era layer: #14750 · schema lineage: #14729 · naming: #11240 · superseded implementation: PR #14919 (closed at cycle-1, mechanics salvageable from branch agent/14915-day0-identity-provisioning).

Origin Session ID: b956ba53-01ed-4ea6-a1e5-62969f887bc3

Retrieval Hint: query_raw_memories("R3a day-0 resident identity provisioning three keys resident instance engine no day-0 episode")