Context
#12399 added instance-addressable wake routing via --user-data-dir for same-bundle harnesses, but implemented only the "instance WITH a given userDataDir" half (instanceResolver.resolveInstancePid). The macOS default app instance is started without --user-data-dir (hard operator constraint: the default Claude Desktop must launch as the normal macOS app, or the OS app/menu-bar toolbar integration breaks — it can never carry the flag).
The Problem
When two same-bundle instances run — the default (@neo-opus-ada) + a --user-data-dir-launched sibling (@neo-opus-grace) — a wake whose subscription has no userDataDir (the default) falls through to tell application "Claude" to activate + first process whose frontmost is true, which is ambiguous across the two windows. Default wakes can land in the sibling window. Verified live 2026-06-03 during 2-instance bring-up.
The Fix
The default instance is uniquely identifiable by the absence of --user-data-dir. Add the complement resolver — zero flag on the default:
resolveDefaultInstancePid({appName, psOutput}) → the appName main process (bundle /<appName>.app/Contents/MacOS/, excluding Helper/Framework/crashpad) that carries no --user-data-dir. Only disambiguates when ≥2 mains exist and exactly one is arg-less; otherwise null (caller keeps the legacy activate path — safe, single-instance behavior unchanged).
- daemon
deliverDigest no-userDataDir branch: resolve the default pid and raise THAT process by unix id when it can be uniquely identified; otherwise keep the legacy single-instance activate path.
Contract Ledger
| Surface |
Source of Authority |
Behavior |
Fallback |
Evidence |
instanceResolver |
this ticket / #12399 |
new resolveDefaultInstancePid (argless-main resolution) |
null → legacy activate |
unit |
daemon no-userDataDir branch |
wake-delivery contract |
route default wake to argless instance when a sibling exists |
legacy activate when single-instance |
unit + live |
| default instance launch |
operator toolbar constraint |
NEVER carries --user-data-dir |
n/a |
n/a |
Acceptance Criteria
Related
- Follow-up to #12399 (the with-arg half); pairs with #12402 (live L3 validation).
- Origin: live wake mis-routing during 2-instance bring-up, 2026-06-03.
Context
#12399 added instance-addressable wake routing via
--user-data-dirfor same-bundle harnesses, but implemented only the "instance WITH a givenuserDataDir" half (instanceResolver.resolveInstancePid). The macOS default app instance is started without--user-data-dir(hard operator constraint: the default Claude Desktop must launch as the normal macOS app, or the OS app/menu-bar toolbar integration breaks — it can never carry the flag).The Problem
When two same-bundle instances run — the default (
@neo-opus-ada) + a--user-data-dir-launched sibling (@neo-opus-grace) — a wake whose subscription has nouserDataDir(the default) falls through totell application "Claude" to activate+first process whose frontmost is true, which is ambiguous across the two windows. Default wakes can land in the sibling window. Verified live 2026-06-03 during 2-instance bring-up.The Fix
The default instance is uniquely identifiable by the absence of
--user-data-dir. Add the complement resolver — zero flag on the default:resolveDefaultInstancePid({appName, psOutput})→ the appName main process (bundle/<appName>.app/Contents/MacOS/, excluding Helper/Framework/crashpad) that carries no--user-data-dir. Only disambiguates when ≥2 mains exist and exactly one is arg-less; otherwisenull(caller keeps the legacy activate path — safe, single-instance behavior unchanged).deliverDigestno-userDataDirbranch: resolve the default pid and raise THAT process by unix id when it can be uniquely identified; otherwise keep the legacy single-instanceactivatepath.Contract Ledger
instanceResolverresolveDefaultInstancePid(argless-main resolution)null→ legacy activateuserDataDirbranch--user-data-dirAcceptance Criteria
resolveDefaultInstancePidreturns the argless main pid when one default + N arg'd siblings exist;nullwhen single-instance or >1 argless mains.userDataDirwake to the argless instance by pid when a sibling (arg'd) instance is present; preserves the legacy activate path when single-instance.--user-data-dir(toolbar constraint upheld).Related