LearnNewsExamplesServices
Frontmatter
id10624
titleWake subscription canonicalization: one canonical appName per identity, retire stale duplicate
stateClosed
labels
bugairegressionarchitecture
assigneesneo-opus-4-7
createdAtMay 3, 2026, 12:34 PM
updatedAtMay 9, 2026, 11:23 PM
githubUrlhttps://github.com/neomjs/neo/issues/10624
authorneo-opus-4-7
commentsCount0
parentIssue10601
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[x] 10625 All-agent-idle detection at heartbeat layer (substrate primitive for trio liveness)
closedAtMay 3, 2026, 1:15 PM

Wake subscription canonicalization: one canonical appName per identity, retire stale duplicate

Closedbugairegressionarchitecture
neo-opus-4-7
neo-opus-4-7 commented on May 3, 2026, 12:34 PM

Context

Live substrate evidence (2026-05-03) shows @neo-gemini-3-1-pro has two active WAKE_SUBSCRIPTION rows that differ only in harnessTargetMetadata.appName casing:

  • WAKE_SUB:2ac01429-f3e7-4396-9198-780e3b7db1c1appName: \"Antigravity\" (created 2026-04-29T21:37:27Z)
  • WAKE_SUB:b9211b22-f4e6-4405-9203-c33d8bdc4281appName: \"antigravity\" (created 2026-05-02T23:24:58Z, recent)

The same case-handling inconsistency is now manifesting in PR #10621's normalization patch as agentIdentity: '@antigravity' — an invented graph identity that is NOT a seeded AgentIdentity and conflicts with canonical wake-route direction (per @neo-gpt's Cycle 3 review).

This is the root substrate gap that produced @tobiu's empirical observation of duplicate wakes for Gemini.

The Problem

bridge-daemon.mjs logs appName verbatim and dispatches via osascript to that exact app name. macOS app names are typically case-sensitive — "Antigravity" matches the actual app, "antigravity" either falls through silently or matches a different app.

When the subscription-creation/update path silently accepts both case forms as distinct entries, downstream consumers (bridge-daemon, MailboxService dispatch) split the wake delivery into two parallel routes. The agent appears to receive duplicate wakes, AND one of the two routes may be silently dropping (operationally indistinguishable from "working" until empirical inspection).

This is a substrate-truth defect of the same family as #10619 Cycle 1 (AGENT_MEMORY vs MEMORY label drift) and #10623 Cycle 1 (\$.type vs \$.label query drift). All three are "silently-accepted-but-wrong-form" patterns where the substrate doesn't enforce canonical input at the write boundary.

The Architectural Reality

  • Subscription writes flow through the wake-subscription service path (specifically the subscribe / update actions of manage_wake_subscription MCP tool).
  • The MCP tool descriptor at mcp__neo-mjs-memory-core__manage_wake_subscription accepts harnessTargetMetadata.appName as a free-form string; no validation exists.
  • bridge-daemon.mjs reads the appName field and passes it directly to osascript -e 'tell application \"<appName>\"' — verbatim.
  • No seeded AgentIdentity registry / harness registry validation gate exists at sub-creation time.

The Fix

Enforce canonical-form validation at subscription creation/update boundary:

  1. Validation: manage_wake_subscription action subscribe / update MUST validate harnessTargetMetadata.appName against an explicit allow-list (currently: \"Antigravity\", \"Claude\"; future identities added as harness registry expands). Lower-case or otherwise non-canonical values MUST throw at the MCP-tool boundary, not silently persist.
  2. Migration / cleanup: existing duplicate row WAKE_SUB:b9211b22-f4e6-4405-9203-c33d8bdc4281 (appName: "antigravity") MUST be retired/unsubscribed. Operator-driven cleanup; not auto-run as part of validation rollout.
  3. Test coverage: spec asserts both directions — canonical accepted, non-canonical rejected with explicit error message identifying the allowed values.

Acceptance Criteria

  • manage_wake_subscription subscribe / update MCP tool rejects non-canonical appName values with explicit error
  • Spec test: positive (canonical accepted) + negative (lowercase rejected with helpful error)
  • Stale WAKE_SUB:b9211b22-... retired (post-merge operator step, NOT auto-migration)
  • PR body cites empirical anchor (Gemini duplicate-wake observation) as ground-truth proof of fix necessity

Out of Scope

  • Migration sweep over all existing subscriptions (only the one known stale row is in scope; bulk migration is a separate concern if more drift is discovered)
  • Identity-input normalization elsewhere (e.g., checkSunsetted.mjs accepting neo-opus-4-7 vs @neo-opus-4-7) — that's a separate substrate hardening lane
  • The @antigravity invented-graph-identity issue surfacing in PR #10621 — that's a separate concern in Gemini's lane; this ticket addresses the WAKE_SUBSCRIPTION layer specifically

Avoided Traps

  • Auto-normalize via lowercasing — silently rewriting input is a discoverability nightmare. Throw instead so the caller knows their input was wrong.
  • Add \$.type fallback / accept both (parallel to the trap from PR #10623 review) — silently accepting wrong forms is the failure mode this ticket fixes; doing the same thing one layer up would defeat the purpose.
  • Bundle stale-row cleanup with validation rollout — operator-coordinated cleanup is safer than autonomous deletion.

Related

  • Substrate-stack lane #5 (canonical routes) — parallel prerequisite to all-agent-idle detection (#1)
  • @neo-gpt coordination note 2026-05-03 [MESSAGE:ee05f910 Antigravity vs antigravity duplicate sub]
  • @neo-gpt PR #10621 Cycle 3 Request Changes — the @antigravity invented identity is the same case-handling defect manifesting in #10621's normalization claim

Origin Session ID: b1839431-cba1-4b6d-913f-27b09e472e67

Retrieval Hint: query_summaries("heartbeat liveness substrate-stack convergence trio coordination 2026-05-03") + query_raw_memories("Antigravity antigravity duplicate wake subscription canonicalization")

tobiu referenced in commit f329177 - "feat(memory-core): enforce canonical appName for wake subscriptions (#10624) (#10628) on May 3, 2026, 1:15 PM
tobiu closed this issue on May 3, 2026, 1:15 PM
tobiu referenced in commit b2071d5 - "fix(memory-core): include Codex in wake subscription canonical appNames (#10636) (#10637) on May 3, 2026, 4:31 PM