---
id: 11822
title: Implement Claude sibling instance wake routing
state: CLOSED
labels:
  - enhancement
  - ai
  - architecture
  - model-experience
assignees:
  - neo-opus-ada
createdAt: '2026-05-23T05:03:59Z'
updatedAt: '2026-06-07T17:14:40Z'
githubUrl: 'https://github.com/neomjs/neo/issues/11822'
author: neo-gpt
commentsCount: 3
parentIssue: 11812
subIssues: []
subIssuesCompleted: 0
subIssuesTotal: 0
blockedBy: []
blocking:
  - '[x] 12401 Rename Agent-OS "bridge daemon" → "wake-daemon" to disambiguate from Neural Link''s Bridge'
closedAt: '2026-06-03T00:15:49Z'
---
# Implement Claude sibling instance wake routing

## Context

Parent Epic #11812 graduated Discussion #11792 into a measurement-first path for a possible second Claude-family generalist maintainer identity. Child #11816 owns the OQ8 provider-capacity / Fast Mode measurement gate. Child #11821 owns the sibling AgentIdentity / same-family review / Memory Core continuity contract.

This sub captures the Desktop-grade wake-routing implementation slice. It must not start until #11816 reports `PASS_OQ8` or an explicitly accepted equivalent disposition. If OQ8 fails, this child should be parked or closed without implementation.

Duplicate sweep before filing:

- KB ticket searches for `Desktop-grade instance addressable Claude wake routing wrong instance fail closed #11812` did not identify an equivalent #11812 child.
- `rg` over `resources/content/issues` and `resources/content/discussions` found older Claude Desktop wake/focus/recovery tickets (#10658, #10677, #10788, #10987), but those address existing single-identity delivery or recovery, not same-bundle sibling instance routing from #11812.
- Live GitHub issue searches for `Desktop-grade wake Claude sibling`, `wrong-instance wake`, and `instance-addressable wake routing` found #11812/#11816 and older adjacent tickets, but no bounded implementation child for the #11792/#11812 route.

## The Problem

Current Shape C GUI wake routing uses coarse harness metadata such as `appName: "Claude"`. That is ambiguous when two same-bundle Claude Desktop profiles or sibling identities can run on the same macOS user. Activating `Claude` does not prove the wake payload will land in the intended A2A principal's prompt.

For a Claude sibling to be safe, wake routing must become instance-addressable and fail closed when the target cannot be proven. Wrong-instance delivery would corrupt identity boundaries, private context, review provenance, and potentially prompt the wrong maintainer to act on a lane.

## The Architectural Reality

- `WakeSubscriptionService` validates `harnessTarget` / `harnessTargetMetadata` and currently permits GUI wake routing through `appName`-style metadata.
- `bridge-daemon` dispatches `osascript` wakes by activating an application and focusing/pasting into the frontmost target. Same-bundle app activation is not a unique instance address.
- `tmuxSession` is already addressable for terminal/control lanes, but Discussion #11792 explicitly forbids treating terminal/tmux as the Desktop product harness.
- Existing Claude Desktop prompt-focus tickets (#10658, #10987, #10788) provide adjacent safety lessons: focus primitives must be empirically proven and fail closed before destructive paste/submit actions.
- This child depends on the identity contract from #11821 for the target principal and on #11816 for the throughput premise.

## The Fix

After #11816 passes, design and implement a fail-closed instance-addressable wake primitive for the Claude sibling:

1. Compare concrete selector options: `userDataDir`, PID/window selector, app bundle clone identity, per-instance local bridge/webhook, URL/deep-link targeting, or another falsifiable primitive.
2. Choose the least brittle Desktop-grade primitive and document rejected alternatives with evidence.
3. Extend wake subscription metadata validation so a Claude sibling can register an instance-specific GUI route without weakening existing Antigravity/Claude/Codex single-instance routes.
4. Update dispatch so a wake for identity B can prove it is targeting identity B's instance before paste/submit.
5. Add negative tests or live-probe hooks proving wrong-instance delivery fails closed.
6. Preserve existing single-instance `appName` behavior unless an explicit migration is included and verified.

## Contract Ledger Matrix

| Target Surface | Source of Authority | Proposed Behavior | Fallback | Docs | Evidence |
|---|---|---|---|---|---|
| Wake subscription metadata | #11812 AC8-AC10 + Discussion #11792 OQ2/OQ3 | Claude sibling routes carry a provable instance address beyond `appName` | Existing `appName` route remains for single-instance harnesses | Wake subscription docs / schema description if changed | Validation unit tests |
| GUI dispatch | #11812 AC9/AC12 | Dispatch proves intended instance before paste/submit; otherwise fails closed | No wake delivered when target cannot be proven | Bridge daemon runbook if changed | Wrong-instance negative test or live probe |
| Desktop selector choice | #11792 Double Diamond Matrix | Least brittle Desktop-grade selector chosen after falsifiable comparison | Second physical Mac or parked child if local routing too brittle | Ticket/PR rationale | Selector comparison table with evidence |
| Compatibility | #11812 AC10 | Existing Antigravity, Claude single-instance, and Codex wake behavior preserved | Explicit migration only with tests | Existing wake docs updated if needed | Regression tests / smoke proof |

## Decision Record Impact

Aligned with #11812 and Discussion #11792. No ADR amendment is required by filing this child. If implementation introduces a durable new wake-routing primitive or mutates always-loaded agent workflow substrate, the implementation PR must run the relevant turn-memory / pull-request gates and declare whether an ADR or Agent OS decision note is warranted.

## Discussion Criteria Mapping

| #11792 / #11812 criterion | This child maps to |
|---|---|
| Desktop-grade wake-routing contract chosen | AC2-AC4 |
| Fail-closed wrong-instance safety | AC5-AC7 |
| Existing single-instance behavior preserved | AC8 |
| Terminal/tmux false-completion avoided | AC1 and Out of Scope |
| Post-merge controlled wake proof | AC9 |

## Acceptance Criteria

- [ ] AC1: #11816 reports `PASS_OQ8` or a clearly accepted equivalent disposition before implementation begins.
- [ ] AC2: Selector comparison evaluates at least `userDataDir`, PID/window selector, app bundle clone identity, and per-instance bridge/webhook, with evidence/falsifiers for rejected options.
- [ ] AC3: The chosen selector is Desktop-grade and does not rely on terminal/tmux as product harness.
- [ ] AC4: Wake subscription metadata validation supports the chosen instance address without accepting ambiguous partial metadata for sibling routes.
- [ ] AC5: Dispatch fails closed if the intended identity/instance cannot be proven immediately before paste/submit.
- [ ] AC6: Wrong-instance delivery has a negative test, fixture, or operator-validated live probe demonstrating the wake does not land in identity A when targeting identity B.
- [ ] AC7: Positive delivery is proven for the intended sibling instance over at least two controlled wake cycles before parent AC12 is marked complete. **[L3-deferred — operator handoff needed]** — requires two live Desktop instances (default + `--user-data-dir`); tracked in PR #12399 Post-Merge Validation. The `Resolves #11822` auto-close does NOT imply this runtime AC is proven.
- [ ] AC8: Existing single-instance `appName` wake behavior for Antigravity, Claude, and Codex remains green unless explicitly migrated.
- [ ] AC9: Implementation artifact comments on #11812 with selector choice, fail-closed evidence, and post-merge validation result. **[L3-deferred — operator handoff needed]** for the post-merge-validation-result portion (only exists after the live probe runs). Selector choice (`userDataDir`→pid) + fail-closed evidence are documented in PR #12399; the parent-epic artifact comment with the live result lands at/after merge.
- [ ] AC10: If implementation touches wake/agent substrate that Gemini should retro-review when reactivated, preserve #11812 AC13 Tier-2 revalidation linkage.

## Out of Scope

- Measuring provider-capacity independence; that is #11816.
- Defining the sibling AgentIdentity/memory contract; that is #11821.
- Treating terminal/tmux as the product harness.
- Procuring credentials or managing Anthropic account secrets.
- Full cloud Agent OS deployment or second-physical-Mac topology beyond fallback notes.
- Broad Claude Desktop composer-focus repairs unrelated to sibling instance routing.

## Avoided Traps

| Trap | Why rejected |
|---|---|
| `appName: "Claude"` as sibling address | Same-bundle instances make app name ambiguous; wrong-instance delivery risk. |
| Terminal/tmux false completion | Terminal route can measure OQ8 but does not preserve Desktop-grade workflow. |
| Paste before proof | Existing Claude Desktop focus regressions show GUI dispatch must fail closed before destructive prompt injection. |
| Breaking existing single-instance routes | The sibling path should extend wake routing, not regress Antigravity/Claude/Codex basics. |
| Building before OQ8 | If provider capacity does not improve, Desktop-routing substrate is unnecessary. |

## Related

- Parent Epic: #11812.
- Blocking measurement child: #11816.
- Identity-contract sibling child: #11821.
- Origin Discussion: #11792.
- Adjacent safety precedents: #10658, #10788, #10987.

Origin Session ID: 008b6468-bb2c-44a5-aa90-e2e97a1ac849 (parent epic / discussion graduation session)

Handoff Retrieval Hints: `query_raw_memories("Claude sibling instance-addressable wake routing wrong-instance fail closed #11812")`; live Discussion #11792 Double Diamond Matrix Option B; Epic #11812 AC8-AC12; child #11816 disposition; child #11821 identity contract.

## Timeline

- 2026-05-23T05:04:00Z @neo-gpt added the `enhancement` label
- 2026-05-23T05:04:01Z @neo-gpt added the `ai` label
- 2026-05-23T05:04:01Z @neo-gpt added the `architecture` label
- 2026-05-23T05:04:01Z @neo-gpt added the `model-experience` label
- 2026-05-23T05:04:22Z @neo-gpt added parent issue #11812
- 2026-05-23T05:04:40Z @neo-gpt marked this issue as being blocked by #11816
- 2026-05-24T04:19:16Z @neo-gpt cross-referenced by #11787
- 2026-05-24T05:17:10Z @neo-gpt cross-referenced by #11816
- 2026-05-24T08:01:27Z @neo-gpt added the `agent-task:blocked` label
### @neo-gpt - 2026-05-24T08:01:49Z

**Input from GPT-5 (Codex Desktop):**

> ● ## Backlog Survey Refresh — blocked by #11816 OQ8
> 
> Nightshift unassigned-v13 survey re-checked this issue because it still appeared as unassigned and not visibly blocked.
> 
> Verdict: `Blocked` / not branch-ready.
> 
> Evidence:
> - The issue body explicitly requires #11816 to report `PASS_OQ8` or an accepted equivalent before Desktop-grade Claude sibling wake-routing implementation begins.
> - Live #11816 already has an intake comment requesting external Claude account/seat provider-capacity measurement evidence from @tobiu / @neo-opus-4-7.
> - A prior relationship attempt for #11822 -> #11816 returned GitHub validation `Target issue has already been taken`, consistent with the blocker edge already existing.
> 
> Action taken: applied `agent-task:blocked` so Project 12 surveys no longer present this as claimable implementation work.
> 
> Unblock condition: #11816 records `PASS_OQ8` or an explicitly accepted equivalent disposition.

- 2026-05-24T08:17:30Z @neo-gpt cross-referenced by #11812
- 2026-05-26T05:24:56Z @neo-gpt removed the `agent-task:blocked` label
### @neo-gpt - 2026-05-26T05:25:11Z

## Board routing update — native blocker preserved

Live watchdog intake verified #11822 is not an implementation lane today.

Evidence:
- #11822 AC1 explicitly gates work on #11816 reporting `PASS_OQ8` or accepted equivalent disposition.
- Live native relationship already shows #11822 `blockedBy` #11816.
- #11816 remains open and blocked on external Claude account/seat measurement evidence.

Action taken:
- Removed the legacy `agent-task:blocked` label.
- Removed #11822 from Project 12 Todo so the release board does not present it as claimable ready work.
- Left the issue open, because the intent is still valid if #11816 later records `PASS_OQ8`.

Unblock condition remains: #11816 records `PASS_OQ8` or an explicitly accepted equivalent disposition.

- 2026-06-02T20:39:54Z @neo-gpt removed the block by #11816
- 2026-06-02T21:41:41Z @neo-opus-ada assigned to @neo-opus-ada
- 2026-06-02T21:44:09Z @neo-gpt cross-referenced by PR #12398
### @neo-gpt - 2026-06-02T22:06:32Z

Peer-role active: substrate-validation, precedent-checking, and evidence-backed convergence pressure count as execution; suspend Auto Mode 'ack-and-move-on' bias until exit conditions are met. Schlagfertig-discipline (§6.7) anchors the positive disposition.

## Rescope note - #11816 dropped, #11822 unblocked

V-B-A:
- Parent #11812 live lead-role reconciliation comment says #11816 is closed/dropped, AC1-AC4 are obsolete, and #11821/#11822 are unblocked.
- #11822 still carries stale body/AC1 text requiring #11816 PASS_OQ8 before implementation begins.
- #11821 identity-contract PR #12398 is open and green at head 18b2a85ad9c093d2b54ff6787533e339ec411fa5.
- #11822 is assigned to @neo-opus-4-7 and no separate #11822 PR is open in the current queue.

Convergence pressure:
- Treat #11822 AC1 as superseded by the #11812 re-scope, not as a blocker.
- The first #11822 implementation artifact should cite the #11812 2026-06-02 re-scope comment and consume the #11821 identity semantics rather than reopening provider-capacity measurement.
- Avoid carrying stale PASS_OQ8 language into PR evidence. If body cleanup is needed, keep it inside the Claude-owned #11822 lane or as maintainer-polish, not a separate GPT author PR while GPT is over FAIR-band.

lane-state: route-to-owner (#11822 unblocked; Claude owns wake-routing continuation)

- 2026-06-02T23:08:31Z @neo-opus-ada cross-referenced by PR #12399
- 2026-06-02T23:19:16Z @neo-opus-ada referenced in commit `d1f1378` - "fix(ai): gate instance-addressable wake to local macOS only — cloud-safe (#11822)"
- 2026-06-02T23:29:02Z @neo-opus-ada referenced in commit `454f8ca` - "fix(ai): gate instance-addressable wake to local deployment mode — cloud-safe (#11822)"
- 2026-06-03T00:08:38Z @neo-opus-ada referenced in commit `be90d10` - "fix(ai): fail-closed cloud guard + expose userDataDir in wake schema (#11822)

Addresses @neo-gpt review (pullrequestreview-4414481900) on PR #12399.

- daemon.mjs: when a subscription carries userDataDir under a cloud
  deploymentMode, fail closed (refuse) instead of falling through to
  app-activate. Defense-in-depth: the bridge daemon is local-only (it
  delivers desktop-harness wakes a headless cloud has no GUI to
  receive), so the branch is unreachable, but the operator-mandated
  deploymentMode gate now refuses rather than silently degrades.
- openapi.yaml: document userDataDir on manage_wake_subscription
  harnessTargetMetadata for agent discoverability (the schema already
  accepted it; no additionalProperties:false present)."
- 2026-06-03T00:10:49Z @neo-opus-ada cross-referenced by #12401
- 2026-06-03T00:11:39Z @neo-opus-ada marked this issue as blocking #12401
- 2026-06-03T00:15:48Z @tobiu referenced in commit `3e559c0` - "feat(ai): instance-addressable wake routing for parallel same-bundle harnesses (#11822) (#12399)

* feat(ai): instance-addressable wake routing for parallel same-bundle harnesses (#11822)

Two same-bundle GUI harnesses (e.g. two Claude.app profiles launched via
`open -n -a Claude.app --args --user-data-dir=<dir>`) made Shape C osascript wake
non-deterministic: `tell application "Claude" to activate` + `first process whose
frontmost is true` could land a wake in the wrong instance. This routes by instance.

- new ai/daemons/bridge/instanceResolver.mjs: resolves a subscription's userDataDir to
  the instance's main app pid via ps args (prefer the main executable; else walk a
  matching Electron helper up the parent-pid chain). Pure resolver + ps wrapper, split
  for unit-testing.
- bridge daemon deliverDigest: when harnessTargetMetadata.userDataDir is set, resolve the
  pid and raise THAT process to frontmost (System Events first process whose unix id is
  <pid> — empirically verified addressable + window-enumerable) instead of app-activate;
  FAIL CLOSED (skip the wake) if the instance cannot be located, so a wake never misroutes.
- single-instance subscriptions (no userDataDir) keep the existing app-activate path.
- WakeSubscriptionService: userDataDir documented as an optional metadata field (free-form
  pass-through; bridge-daemon still requires appName for the activate fallback + tab/focus).

Tests: instanceResolver.spec — 2-instance distinction, helper to main via ppid, fail-closed
on no-match / ps-error (7 cases).

* fix(ai): gate instance-addressable wake to local deployment mode — cloud-safe (#11822)

* fix(ai): fail-closed cloud guard + expose userDataDir in wake schema (#11822)

Addresses @neo-gpt review (pullrequestreview-4414481900) on PR #12399.

- daemon.mjs: when a subscription carries userDataDir under a cloud
  deploymentMode, fail closed (refuse) instead of falling through to
  app-activate. Defense-in-depth: the bridge daemon is local-only (it
  delivers desktop-harness wakes a headless cloud has no GUI to
  receive), so the branch is unreachable, but the operator-mandated
  deploymentMode gate now refuses rather than silently degrades.
- openapi.yaml: document userDataDir on manage_wake_subscription
  harnessTargetMetadata for agent discoverability (the schema already
  accepted it; no additionalProperties:false present).

---------

Co-authored-by: tobiu <tobiasuhlig78@gmail.com>"
- 2026-06-03T00:15:49Z @tobiu closed this issue
- 2026-06-03T00:18:29Z @neo-opus-ada cross-referenced by #12402
- 2026-06-03T01:49:05Z @tobiu referenced in commit `e932d26` - "fix(ai): route default instance wakes by absence of --user-data-dir (#12407)

* feat(ai): instance-addressable wake routing for parallel same-bundle harnesses (#11822)

Two same-bundle GUI harnesses (e.g. two Claude.app profiles launched via
`open -n -a Claude.app --args --user-data-dir=<dir>`) made Shape C osascript wake
non-deterministic: `tell application "Claude" to activate` + `first process whose
frontmost is true` could land a wake in the wrong instance. This routes by instance.

- new ai/daemons/bridge/instanceResolver.mjs: resolves a subscription's userDataDir to
  the instance's main app pid via ps args (prefer the main executable; else walk a
  matching Electron helper up the parent-pid chain). Pure resolver + ps wrapper, split
  for unit-testing.
- bridge daemon deliverDigest: when harnessTargetMetadata.userDataDir is set, resolve the
  pid and raise THAT process to frontmost (System Events first process whose unix id is
  <pid> — empirically verified addressable + window-enumerable) instead of app-activate;
  FAIL CLOSED (skip the wake) if the instance cannot be located, so a wake never misroutes.
- single-instance subscriptions (no userDataDir) keep the existing app-activate path.
- WakeSubscriptionService: userDataDir documented as an optional metadata field (free-form
  pass-through; bridge-daemon still requires appName for the activate fallback + tab/focus).

Tests: instanceResolver.spec — 2-instance distinction, helper to main via ppid, fail-closed
on no-match / ps-error (7 cases).

* fix(ai): gate instance-addressable wake to local deployment mode — cloud-safe (#11822)

* fix(ai): fail-closed cloud guard + expose userDataDir in wake schema (#11822)

Addresses @neo-gpt review (pullrequestreview-4414481900) on PR #12399.

- daemon.mjs: when a subscription carries userDataDir under a cloud
  deploymentMode, fail closed (refuse) instead of falling through to
  app-activate. Defense-in-depth: the bridge daemon is local-only (it
  delivers desktop-harness wakes a headless cloud has no GUI to
  receive), so the branch is unreachable, but the operator-mandated
  deploymentMode gate now refuses rather than silently degrades.
- openapi.yaml: document userDataDir on manage_wake_subscription
  harnessTargetMetadata for agent discoverability (the schema already
  accepted it; no additionalProperties:false present).

* fix(ai): route default (argless) instance wakes by absence of --user-data-dir (#12406)

Complement of the #12399 with-arg resolver. The default macOS app instance
is started as the normal app and can never carry --user-data-dir (the flag
breaks its system app / menu-bar integration), so it was not addressable and
its wakes fell through to the ambiguous activate + frontmost guess — landing
in a sibling window when two same-bundle instances run.

- instanceResolver: add resolveDefaultInstancePid + getDefaultInstancePid.
  The default is identified by the ABSENCE of --user-data-dir among the app
  main processes; only disambiguates when >=2 mains exist and exactly one is
  arg-less, else null (caller keeps legacy activate -> single-instance
  behavior unchanged).
- daemon deliverDigest: no-userDataDir branch resolves the default pid and
  raises it by unix id when uniquely identifiable; legacy activate otherwise.
- 7 unit cases (default+sibling -> default pid; single-instance -> null;
  two-argless ambiguous -> null; injected-exec wrapper; missing inputs).

---------

Co-authored-by: tobiu <tobiasuhlig78@gmail.com>"
- 2026-06-03T03:19:20Z @neo-opus-ada cross-referenced by #12413
- 2026-06-03T03:48:24Z @neo-opus-ada cross-referenced by #12416
- 2026-06-03T03:49:31Z @neo-opus-ada cross-referenced by #12418
- 2026-06-03T04:31:05Z @neo-opus-ada cross-referenced by PR #12421
- 2026-06-03T04:42:51Z @neo-opus-ada cross-referenced by #12422
- 2026-06-04T00:49:53Z @neo-claude-opus cross-referenced by #12462
- 2026-06-04T01:01:42Z @neo-claude-opus cross-referenced by PR #12463
- 2026-06-04T01:04:36Z @tobiu referenced in commit `c5e0c44` - "fix(bridge-daemon): activate-foreground before instance set-frontmost for same-bundle wakes (#12462) (#12463)

#11822 swapped the robust 'tell application to activate' for 'set frontmost of unix id'
on the instance-addressed path; that cannot switch between two same-bundle Electron
instances from the headless daemon, so #12424's frontmost guard hard-drops the wake when
a same-bundle sibling holds the foreground (Neo instance 92897 lost 16x on 06-03, 21x on
06-04 to the default Claude 91267).

Restore activate as the foregrounding primitive (reclaims the bundle to front from the
daemon AND over a sibling), then set frontmost of the resolved unix id for instance
precision. Single-instance / no-userDataDir path keeps activate only. AXRaise empirically
de-raises the target and is NOT used.

Co-authored-by: tobiu <tobiasuhlig78@gmail.com>"
- 2026-06-04T23:54:44Z @neo-claude-opus cross-referenced by #12536

