Context
Closes a missed AC from #10402 (Phase 1 wake substrate self-healing). The merged implementation (#10404 + #10412) delivered the bootstrap mechanism — idempotent, restart-safe, identity-template-driven — but never wired up the auto-trigger. Every new agent session today silently has zero WAKE_SUBSCRIPTION nodes until someone manually calls manage_wake_subscription({action: 'bootstrap'}). Without the auto-invoke, the bridge daemon polls but has nothing active to deliver to → no [WAKE] events → silent wake-substrate degradation.
The original #10402 ticket explicitly scoped this auto-trigger:
"AGENTS_STARTUP.md boot sequence invokes bootstrap so new sessions self-heal to a known-good subscription"
"Post-merge validation: new session boots auto-bootstrap their subscription... Verify by terminating + restarting both harnesses; both wake substrates should self-heal without manual scratch-script intervention."
Empirical reproducer (2026-04-27 session b3c0bfb8-44e1-4646-9c62-110ef16b0fad): post-#10433 merge + harness restart, my MCP server bound @neo-opus-4-7 and ran for ~2 hours with zero WAKE_SUB for the bound identity. Bridge daemon (PID 12039) was running healthy in canonical, polling, but had nothing to deliver to. A2A read/write paths verified working; wake delivery silently broken.
The Problem
WakeSubscriptionService.bootstrap() is reachable only via the manage_wake_subscription({action: 'bootstrap'}) MCP tool dispatch path. There is no auto-invocation anywhere:
WakeSubscriptionService.init() (line 77) only initializes liveCursor from GraphLog — does NOT call bootstrap()
StdioIdentityResolver resolves identity at MCP-server startup but does not chain into wake-substrate seeding
- No identity-bind hook, no first-call interceptor, no boot-time auto-trigger
- The original #10402 AC item "AGENTS_STARTUP.md boot sequence invokes bootstrap" was never wired
The wake substrate has the lever to self-heal but nothing to pull it. Every new session needs an agent to remember to call bootstrap manually — a discipline burden that won't survive context-pruning. This affects every new session on both Claude Code and Antigravity sides.
The Architectural Reality
ai/mcp/server/memory-core/services/WakeSubscriptionService.mjs — owns the bootstrap() action (line 207). Idempotent + raw-SQL-safe per #10412.
ai/mcp/server/memory-core/server.mjs — the MCP server entry point; identity is bound here in stdio mode via StdioIdentityResolver.
ai/mcp/server/shared/services/StdioIdentityResolver.mjs — resolves the bound identity once at server boot for stdio transport.
ai/mcp/server/shared/services/RequestContextService.mjs — per-request identity binding (OIDC mode).
- AgentIdentity nodes for both
@neo-opus-4-7 and @neo-gemini-3-1-pro already carry valid subscriptionTemplate properties (verified empirically) — the data substrate for auto-bootstrap is already in place.
Precedent for the right substrate placement: #10181/#10182 (April 22) fixed identity-binding self-heal at server-side dispatch level, NOT via documentation discipline. Same problem class (lifecycle gap that requires per-session re-derivation otherwise); same right answer (substrate-level auto-trigger). Doc-layer mandates depend on agent compliance + survive context-pruning poorly; code-layer guarantees fire regardless.
The Fix
Primary path: server-side auto-invoke after identity bind.
In stdio mode (the dominant path for the swarm today), the seam is in server.mjs after StdioIdentityResolver resolves identity. Pseudo-code:
if (resolvedIdentity?.agentIdentityNodeId) {
WakeSubscriptionService.bootstrap()
.then(result => logger.info(`[WakeSubBootstrap] ${result.action}: ${result.subscriptionId}`))
.catch(err => logger.warn(`[WakeSubBootstrap] auto-invoke failed: ${err.message}`));
}
Failure modes the auto-invoke must handle gracefully:
- No
subscriptionTemplate on AgentIdentity — bootstrap throws; auto-invoke logs and continues. Boot must not gate on this (some identities legitimately don't need wake subs).
- GraphService not ready — bootstrap awaits
GraphService.ready() per existing logic; auto-invoke must fire AFTER that.
- Already-existing sub — bootstrap is idempotent per #10412's raw-SQL fix; returns the existing sub.
For OIDC mode (per-request identity), the right shape is dispatch-time self-heal mirroring #10182's pattern: on first identity-bound request, check if WAKE_SUB exists for the bound identity; if not, fire-and-forget bootstrap. Defer OIDC-mode wiring if scope warrants — stdio is the load-bearing path for the swarm today.
Why NOT the doc-only fix (AGENTS_STARTUP.md mandate alone):
- Discipline-layer mandates depend on agent compliance + survive context-pruning poorly
- Future agents won't know to call it; the substrate must self-heal regardless
- Per #10181/#10182 precedent, the right answer for lifecycle-gap class problems is server-side self-heal
The AGENTS_STARTUP.md note from the original #10402 AC is fine as defense-in-depth complement, but cannot be the sole mechanism.
Acceptance Criteria
Out of Scope
- OIDC-mode dispatch-time self-heal (defer; stdio is the dominant swarm path today; file as follow-up if/when OIDC mode is exercised)
- AGENTS_STARTUP.md mandate (the original #10402 AC item) — this can be added as defense-in-depth in a tiny follow-up, but the substrate-level auto-invoke is the load-bearing fix per #10181/#10182 precedent. Mentioning here for completeness; not blocking.
- Architectural restructuring of
WakeSubscriptionService.bootstrap() itself (already correct + idempotent + restart-safe per the merged work)
- Cross-clone topology coordination (already addressed by #10433 + #10436 — granular symlinks + canonical-root flag)
Avoided Traps
- Trap: Add the AGENTS_STARTUP.md boot mandate (the original #10402 wording) and call it done. Avoided: discipline-layer fix for a lifecycle gap is not robust per #10181/#10182 precedent — depends on agent compliance, survives context-pruning poorly, fails silently if agent skips boot read.
- Trap: Have
WakeSubscriptionService.init() call bootstrap() directly. Avoided: init() runs at service initialization time (no identity context yet); the auto-invoke must fire AFTER StdioIdentityResolver binds. Wrong lifecycle hook.
- Trap: Make boot synchronously await bootstrap completion. Avoided: bootstrap can fail (no template, GraphService not ready, etc.); fire-and-forget with try/catch + log keeps boot resilient.
- Trap: Re-derive subscription metadata from env vars / IDE-detection inside the auto-invoke. Avoided: that's exactly the footgun #10402 closed by introducing
subscriptionTemplate as canonical. Auto-invoke should ONLY consume the template; if absent, log + skip.
Related
- Predecessor (closed prematurely): #10402 (Phase 1 wake substrate self-healing — original scope included this auto-trigger)
- Implementation PR that closed #10402 without this AC: #10404 (
feat(memory-core): stabilize wake subscription bootstrap and resolve test regressions)
- Idempotency fix on top: #10412 (
fix(memory-core): bootstrap idempotency uses raw SQL) — makes auto-invoke safe to repeat
- Architectural precedent for substrate-level auto-heal: #10181/#10182 (identity-binding self-heal on dispatch)
- Cross-process coherence root cause that exposed this gap: #10424
- Substrate-level fix that restored coherence: #10433 (granular per-subdir symlinking)
Origin Session ID: b3c0bfb8-44e1-4646-9c62-110ef16b0fad
Retrieval Hint: "wake subscription auto-bootstrap server boot stdio identity resolved missing AC #10402 phase 1 completion"
Context
Closes a missed AC from #10402 (Phase 1 wake substrate self-healing). The merged implementation (#10404 + #10412) delivered the bootstrap mechanism — idempotent, restart-safe, identity-template-driven — but never wired up the auto-trigger. Every new agent session today silently has zero
WAKE_SUBSCRIPTIONnodes until someone manually callsmanage_wake_subscription({action: 'bootstrap'}). Without the auto-invoke, the bridge daemon polls but has nothing active to deliver to → no[WAKE]events → silent wake-substrate degradation.The original #10402 ticket explicitly scoped this auto-trigger:
Empirical reproducer (2026-04-27 session
b3c0bfb8-44e1-4646-9c62-110ef16b0fad): post-#10433 merge + harness restart, my MCP server bound@neo-opus-4-7and ran for ~2 hours with zero WAKE_SUB for the bound identity. Bridge daemon (PID 12039) was running healthy in canonical, polling, but had nothing to deliver to. A2A read/write paths verified working; wake delivery silently broken.The Problem
WakeSubscriptionService.bootstrap()is reachable only via themanage_wake_subscription({action: 'bootstrap'})MCP tool dispatch path. There is no auto-invocation anywhere:WakeSubscriptionService.init()(line 77) only initializesliveCursorfrom GraphLog — does NOT callbootstrap()StdioIdentityResolverresolves identity at MCP-server startup but does not chain into wake-substrate seedingThe wake substrate has the lever to self-heal but nothing to pull it. Every new session needs an agent to remember to call bootstrap manually — a discipline burden that won't survive context-pruning. This affects every new session on both Claude Code and Antigravity sides.
The Architectural Reality
ai/mcp/server/memory-core/services/WakeSubscriptionService.mjs— owns thebootstrap()action (line 207). Idempotent + raw-SQL-safe per #10412.ai/mcp/server/memory-core/server.mjs— the MCP server entry point; identity is bound here in stdio mode viaStdioIdentityResolver.ai/mcp/server/shared/services/StdioIdentityResolver.mjs— resolves the bound identity once at server boot for stdio transport.ai/mcp/server/shared/services/RequestContextService.mjs— per-request identity binding (OIDC mode).@neo-opus-4-7and@neo-gemini-3-1-proalready carry validsubscriptionTemplateproperties (verified empirically) — the data substrate for auto-bootstrap is already in place.Precedent for the right substrate placement: #10181/#10182 (April 22) fixed identity-binding self-heal at server-side dispatch level, NOT via documentation discipline. Same problem class (lifecycle gap that requires per-session re-derivation otherwise); same right answer (substrate-level auto-trigger). Doc-layer mandates depend on agent compliance + survive context-pruning poorly; code-layer guarantees fire regardless.
The Fix
Primary path: server-side auto-invoke after identity bind.
In stdio mode (the dominant path for the swarm today), the seam is in
server.mjsafterStdioIdentityResolverresolves identity. Pseudo-code:// In server boot sequence, after identity is bound: if (resolvedIdentity?.agentIdentityNodeId) { // Fire-and-forget; failure must not gate boot WakeSubscriptionService.bootstrap() .then(result => logger.info(`[WakeSubBootstrap] ${result.action}: ${result.subscriptionId}`)) .catch(err => logger.warn(`[WakeSubBootstrap] auto-invoke failed: ${err.message}`)); }Failure modes the auto-invoke must handle gracefully:
subscriptionTemplateon AgentIdentity — bootstrap throws; auto-invoke logs and continues. Boot must not gate on this (some identities legitimately don't need wake subs).GraphService.ready()per existing logic; auto-invoke must fire AFTER that.For OIDC mode (per-request identity), the right shape is dispatch-time self-heal mirroring #10182's pattern: on first identity-bound request, check if WAKE_SUB exists for the bound identity; if not, fire-and-forget bootstrap. Defer OIDC-mode wiring if scope warrants — stdio is the load-bearing path for the swarm today.
Why NOT the doc-only fix (AGENTS_STARTUP.md mandate alone):
The AGENTS_STARTUP.md note from the original #10402 AC is fine as defense-in-depth complement, but cannot be the sole mechanism.
Acceptance Criteria
StdioIdentityResolverbinds identity,WakeSubscriptionService.bootstrap()is auto-invokedsubscriptionTemplatedoes not crash boot — logged and skipped gracefullySELECT * FROM Nodes WHERE label='WAKE_SUBSCRIPTION'shows the auto-seeded sub for the bound identityWakeSubscriptionService.spec.mjs(orserver.spec.mjsif such a surface exists) asserting auto-invoke fires post-identity-bind without manual callmanage_wake_subscriptioncall, both@neo-opus-4-7and@neo-gemini-3-1-proget auto-seeded WAKE_SUB nodes. Bridge daemon delivers wake events on next A2A message — verify[WAKE]injection in receiver harness.Out of Scope
WakeSubscriptionService.bootstrap()itself (already correct + idempotent + restart-safe per the merged work)Avoided Traps
WakeSubscriptionService.init()callbootstrap()directly. Avoided:init()runs at service initialization time (no identity context yet); the auto-invoke must fire AFTERStdioIdentityResolverbinds. Wrong lifecycle hook.subscriptionTemplateas canonical. Auto-invoke should ONLY consume the template; if absent, log + skip.Related
feat(memory-core): stabilize wake subscription bootstrap and resolve test regressions)fix(memory-core): bootstrap idempotency uses raw SQL) — makes auto-invoke safe to repeatOrigin Session ID: b3c0bfb8-44e1-4646-9c62-110ef16b0fad
Retrieval Hint: "wake subscription auto-bootstrap server boot stdio identity resolved missing AC #10402 phase 1 completion"