LearnNewsExamplesServices
Frontmatter
id10402
titleBootstrap wake subscription from identity template at session start
stateClosed
labels
enhancementaiarchitecturecore
assigneesneo-gemini-pro
createdAtApr 27, 2026, 8:17 AM
updatedAtJun 7, 2026, 7:21 PM
githubUrlhttps://github.com/neomjs/neo/issues/10402
authorneo-opus-ada
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtApr 27, 2026, 10:03 AM

Bootstrap wake subscription from identity template at session start

Closed v13.0.0/archive-v13-0-0-chunk-6 enhancementaiarchitecturecore
neo-opus-ada
neo-opus-ada commented on Apr 27, 2026, 8:17 AM

Context

Session 80ce4e52-071b-4087-ac79-21bfab4b35e7 (this session, 2026-04-27) and the immediately-preceding session arc surfaced three distinct subscription-state failures that all share the same root shape — wake subscription metadata is fragile across session boundaries:

  1. appName default-to-Claude footgun. @neo-gemini-pro's bridge-daemon subscription WAKE_SUB:255dfb15-... was created without explicit harnessTargetMetadata.appName. Per ai/scripts/bridge-daemon.mjs:271, missing appName defaults to 'Claude'. Result: the osascript wake adapter activated my Claude.app instead of her Antigravity IDE. Her wakes silently routed to my session until she patched the metadata via raw SQL.

  2. Wrong-identity-prefix scratch-script bug. Earlier in the same session arc, after the #10384 Playwright test wipe, a re-subscription script created my subscription with agentIdentity: 'neo-opus-ada' (no @ prefix). Bridge daemon's target === agentIdentity evaluation silently returned false. Wakes existed in SQLite but never matched. Silent identity mismatch required cross-family debugging to surface.

  3. Test-wipes-prod-subscription class (#10384). The original failure that triggered the scratch-script: Playwright tests targeting clearAll() interact with the real SQLite database and wipe production subscriptions on teardown. Re-subscription via ad-hoc scripts is brittle (see #2).

All three share one root: subscription metadata is replicated into ad-hoc creation paths and drifts. Identity-level metadata that SHOULD persist across sessions has no canonical home.

The Problem

Subscription state is currently authored fresh each session. Each session must re-derive harnessTarget, harnessTargetMetadata.appName, harnessTargetMetadata.tabShortcut, and other platform-specific fields from local context (env vars, IDE detection, hand-typed scripts). Re-derivation has three failure surfaces:

  • Default fallbacks (appName ||= 'Claude') silently route wakes to wrong destinations
  • Hand-typed identity strings can omit the @ prefix, breaking the bridge-daemon filter
  • Test-wipes of subscription tables force re-derivation via scripts that are themselves fragile

The Phase 3 wake substrate (#10357) is now empirically operational (PR #10401 merged), but the metadata-state-management around it is the next failure surface.

This ticket addresses Phase 1: footgun closure dimension only. Phase 2 (lazy-presence registry) is being explored separately by @neo-gemini-pro via /ideation-sandbox Discussion (per session A2A convergence). Phase 3 (cross-agent re-subscription) was dropped during brainstorm — see Avoided Traps below.

The Architectural Reality

  • ai/mcp/server/memory-core/services/WakeSubscriptionService.mjs — service-layer entry point for subscription mutation
  • ai/mcp/server/memory-core/openapi.yamlmanage_wake_subscription tool exposes subscribe/unsubscribe/update/list/resync actions today
  • ai/scripts/bridge-daemon.mjs:255-298 — Shape C dispatch reads harnessTargetMetadata from each subscription's properties at dispatch time. The footgun line: const appName = meta.appName || 'Claude';
  • AGENT identity nodes carry an existing properties bag in the memory-core graph (created/maintained via the existing identity-management surface; sibling-file pattern already established per AGENTS.md §23)
  • Subscription nodes (WAKE_SUBSCRIPTION:<uuid>) are currently session-ephemeral and reference agent identity but don't inherit metadata from it

The architectural shift proposed:

  • AGENT identity nodes carry a new subscriptionTemplate property: {harnessTarget, harnessTargetMetadata} — the persisted, platform-correct shape for that identity
  • A new bootstrap action on manage_wake_subscription reads the template and creates a subscription with the correct metadata
  • Templates are first-class identity properties: editable, versioned in the graph, queryable, auditable

The Fix

A. Identity-level template storage

  • Add subscriptionTemplate property to AGENT identity nodes
  • Shape:
      {
        trigger: 'SENT_TO_ME' | 'TASK_STATE_CHANGED' | 'PERMISSION_GRANTED',
        harnessTarget: 'bridge-daemon' | 'mcp-notifications' | 'a2a-webhook',
        harnessTargetMetadata: {
            appName: 'Antigravity' | 'Claude' | <vendor-specific>,
            tabShortcut: '3' | '' | <chord>,
            // adapter / coalesceWindow / url / daemonSocketPath as applicable
        }
    }
  • Persist via a new MCP action OR an extension of an existing identity-management surface — pick whichever fits the prevailing pattern in IdentityService.mjs per the §23 sibling-file-lift discipline

B. bootstrap action on manage_wake_subscription

manage_wake_subscription({
    action: 'bootstrap',
    // Optional override: explicitly pass triggering metadata for first-time setup
    overrideMetadata: { ... }
})

Behavior:

  1. Read calling agent's identity node
  2. If subscriptionTemplate exists, create a subscription with template-derived metadata
  3. If no template exists, return a clear error indicating the identity needs initial template setup — never silently default
  4. Idempotent: if a subscription matching the template's (trigger, harnessTarget) already exists for the calling identity, return it instead of creating a duplicate

C. AGENTS_STARTUP.md integration

The boot mandate (§6 Memory Core check, or §1 wherever fits the existing init sequence) invokes manage_wake_subscription({action: 'bootstrap'}) as part of session initialization. Cross-harness symmetry preserved: both Claude Code and Antigravity load AGENTS_STARTUP.md-equivalent boot path per the existing pattern.

D. Migration path for existing subscriptions

  • Existing bridge-daemon subscriptions that lack explicit harnessTargetMetadata.appName are migrated by reading the AGENT identity's subscriptionTemplate and patching harnessTargetMetadata accordingly
  • One-shot migration script in ai/scripts/ (per the AGENTS.md §23 sibling-file-lift pattern: standalone scripts directory, raw substrate access OK)
  • Migration is idempotent — re-running on already-correct subscriptions is a no-op

Acceptance Criteria

  • AGENT identity nodes support a subscriptionTemplate property persisted in the memory-core graph (queryable via get_node and any new dedicated MCP action)
  • manage_wake_subscription({action: 'bootstrap'}) creates a subscription from the calling identity's template
  • bootstrap is idempotent — second call returns the existing subscription instead of creating a duplicate
  • Missing-template case returns an explicit error (not a silent default to 'Claude' or any other vendor)
  • AGENTS_STARTUP.md boot sequence invokes bootstrap so new sessions self-heal to a known-good subscription
  • Existing bridge-daemon subscriptions lacking explicit appName are migrated via a one-shot script in ai/scripts/
  • Playwright unit tests cover: (a) template-create then bootstrap reads it; (b) bootstrap is idempotent; (c) missing-template returns error not silent default; (d) overrideMetadata path still works for ad-hoc first-time subscriptions
  • Post-merge validation: new session boots auto-bootstrap their subscription; bridge daemon dispatches to the correct app per the templated appName. Verify by terminating + restarting both harnesses; both wake substrates should self-heal without manual scratch-script intervention.

Out of Scope

  • Phase 2 — Presence registry / query_agent_presence — separate /ideation-sandbox Discussion owned by @neo-gemini-pro per session A2A convergence (MESSAGE:f40396a2-...MESSAGE:d035ced5-...)
  • Phase 3 — Cross-agent re-subscription via permission grant — dropped during brainstorm; see Avoided Traps
  • Test-isolation 3-layer ticket (env-driven test DB, destructive-op self-defense, identity validation) — addresses the upstream cause of subscription wipes; orthogonal substrate work; separate ticket when filed
  • Subscribe-time schema validation (e.g., requiring appName for bridge-daemon target outside the bootstrap path) — adjacent footgun-prevention but different shape (validation-layer, not template-layer); could be added later as ratchet
  • Cross-process coherence gap fix (manage_wake_subscription({action: 'list'}) and get_node returning empty/null while raw SQL has the row) — separate diagnostic ticket; bootstrap's idempotency makes the gap less catastrophic but doesn't close it

Avoided Traps

  • Hardcoding platform defaults in the daemon (appName ||= 'Claude') — the original footgun. This ticket replaces hardcoded defaults with template-driven values. Templates are queryable, auditable, editable; daemon defaults are buried in code and require code-touch to change.
  • Cross-agent subscription rescue (Phase 3) — explored in the brainstorm and dropped per @neo-gemini-pro's analysis: split-brain risks (two agents trying to subscribe a third simultaneously), permission-authority complexity, race conditions on simultaneous session boot. Self-bootstrap from persisted identity template forecloses this entire complexity class.
  • Heartbeat-based presence — over-fits NL's ephemeral-connection topology onto the wake substrate's persistent-identity model. Different durability contracts. Phase 2 explores lazy-presence via existing GraphLog activity instead — see Gemini's forthcoming Discussion.
  • New AGENT_PRESENCE node primitive — Gemini's analysis preferred extending existing Session nodes for Phase 2 presence. Same principle applies HERE at the schema layer: lift existing AGENT identity nodes via property addition, don't invent parallel node types. Per AGENTS.md §23 sibling-file-lift discipline.
  • Default fallback "but with a warning log" — silent failure with a warning is still silent failure to the agent; warnings live in daemon logs the agent doesn't see. Explicit error-on-missing-template forces the agent to handle the case at boot, not silently route wakes wrong for hours.

Related

  • Sibling brainstorm (this session): A2A thread MESSAGE:b1279575-14c7-4791-85ef-575d646ffc7c (initial 3-phase sketch) → MESSAGE:f40396a2-e1c3-40f2-8c96-0d71642e884e (Gemini's three load-bearing refinements) → MESSAGE:d035ced5-28a8-4a8d-93a8-4d74d8f1abe4 (convergence + handoff)
  • Phase 2 Discussion (forthcoming, Gemini-owned): Lazy-presence via GraphLog activity (separate ideation-sandbox Discussion)
  • Phase 3 wake substrate epic: #10357 (now functionally complete; this ticket is post-epic hardening)
  • Empirical predecessors merged this session: PR #10394 (AGENTS.md §22+§23), PR #10397 (pump-coalescing), PR #10398 (rhetorical-drift §7.4), PR #10401 (raw-delivery bypass + bridge-daemon platform default)
  • Bridge daemon footgun source line: ai/scripts/bridge-daemon.mjs:271 (appName ||= 'Claude')
  • Cross-process coherence gap (parallel substrate concern): #10260 (mailbox vicinity-cache invalidation; same shape, different table)
  • Test-isolation upstream ticket: #10384 (Playwright test-wipe class — caused the original subscription-wipe that triggered the wrong-identity-prefix scratch-script)

Origin Session ID: 80ce4e52-071b-4087-ac79-21bfab4b35e7

Handoff Retrieval Hints

  • query_raw_memories(query='wake subscription bootstrap identity template appName default footgun session boot self-heal')
  • query_summaries(query='post-restart wake substrate verification appName mismatch tabShortcut bridge daemon Antigravity Claude')
  • Commit anchor: f57f041ea (PR #10401 merge — empirical predecessor that revealed the metadata-fragility class)
  • File anchor: ai/scripts/bridge-daemon.mjs:271 (the ||= 'Claude' line being designed out)
  • A2A thread anchor: MESSAGE:b1279575-...MESSAGE:f40396a2-...MESSAGE:d035ced5-... (3-message brainstorm-to-convergence chain)
tobiu referenced in commit 306e0ce - "feat(memory-core): stabilize wake subscription bootstrap and resolve test regressions (#10402) (#10404) on Apr 27, 2026, 10:03 AM
tobiu closed this issue on Apr 27, 2026, 10:03 AM
tobiu referenced in commit 09984a9 - "fix(memory-core): auto-invoke wake subscription bootstrap on MCP server boot (#10437) (#10438) on Apr 27, 2026, 9:21 PM
tobiu referenced in commit b38ef32 - "fix(graph): set Gemini's identity-root appName to 'Antigravity' (#10440) (#10441) on Apr 27, 2026, 9:42 PM