LearnNewsExamplesServices
Frontmatter
id12459
titleBridge daemon drops wakes on focus contention — no osascript retry
stateClosed
labels
bugaiarchitecture
assignees[]
createdAtJun 4, 2026, 1:38 AM
updatedAtJun 4, 2026, 2:01 AM
githubUrlhttps://github.com/neomjs/neo/issues/12459
authorneo-opus-grace
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtJun 4, 2026, 2:01 AM

Bridge daemon drops wakes on focus contention — no osascript retry

Closed v13.0.0/archive-v13-0-0-chunk-16 bugaiarchitecture
neo-opus-grace
neo-opus-grace commented on Jun 4, 2026, 1:38 AM

Context

Wake delivery (bridge daemon → osascript GUI-focus-paste) drops wakes silently when another app holds frontmost during the multi-second delivery sequence. Operator surfaced this live (2026-06-04, nightshift): "@neo-opus-grace does not get wake-ups." Observed stderr:

Target app lost frontmost status after activation (pid 91267 != 92897) (-2700)
Target app lost frontmost status before user input restore clipboard set (pid 703 != 91267) (-2700)

pid 703 = Google Chrome (verified ps -p 703). The targeted Claude/Neo instance (userDataDir .../Neo) never reliably reaches/holds frontmost while Chrome is active.

The Problem

A background daemon raising a specific instance to frontmost, while another app holds focus, with a strict single-shot assertion and zero retry:

  1. macOS focus-stealing prevention makes set frontmost of (process whose unix id is <pid>) to true best-effort — it often sets the flag without actually raising when another app is active → assertTargetFrontmost("after activation") fails immediately.
  2. The sequence is multi-second (tab-switch → focus-seed → select-all/cut → paste → Enter → restore → restore-clipboard with delays). Any focus-steal mid-sequence trips a later assert → -2700, aborting the whole delivery.
  3. No retry: the catch logs Failed to deliver via osascript and drops the wake. Under any focus contention, wakes are lost — the autonomous swarm silently stops getting woken.

The Architectural Reality

  • ai/daemons/bridge/daemon.mjs:744-866 — the osascript delivery script (assertTargetFrontmost helper :745-762).
  • :777-779 — single delay 0.5 + hard assert after activation (the weak link).
  • :866 — single await spawnAsync('osascript', …), no retry.
  • :873-875catch logs + drops (silent wake loss).
  • Helpers available: wait(ms) (:157), spawnAsync (:583, rejects with stderr in err.message → matchable on lost frontmost/-2700), escapeAppleScriptString (:606).
  • ⚠️ Anchor & Echo (:729-733): the activate/keystroke FORMS (tab shortcut, key code 36 Enter, focus seed) are empirically validated across Claude/Antigravity/Codex — must not be reshaped without cross-harness validation.

The Fix (additive robustness only — forms unchanged)

  1. JS-level retry on frontmost-loss/-2700: wrap the spawnAsync in an N-attempt loop (≈4×) with wait() backoff; retry only on the frontmost-race error class, re-throw others; exhausted attempts → existing log+drop. Focus contention is transient → a retry usually lands a clear window.
  2. AppleScript poll-re-activate loop: replace the single delay 0.5 + assert (:777-779) with a repeat ~12 times { activateLine; delay 0.25; try assert → exit } loop, final assert raising the real error if never raised. Gives the contended transition multiple chances within one run.

Acceptance Criteria

  • osascript delivery retries on lost frontmost/-2700 (≈4 attempts, wait() backoff); non-race errors re-throw immediately.
  • "after activation" uses a poll-re-activate loop, not a single delay+assert.
  • The load-bearing activate/keystroke forms (instance set frontmost/activate, tab shortcut, key code 36, focus seed, undo cleanup) are unchanged.
  • Exhausted retries still log the drop (no silent regression of the failure path).
  • (post-merge, evidence) wakes deliver to the targeted instance with another app (e.g. Chrome) frontmost.

Out of Scope

  • #3 forceful-raise reshape (bundle-activate + AXRaise combo) — touches the validated activation form → separate empirical-validation follow-up.
  • Moving wake delivery off GUI-focus-paste to a non-focus channel (file/MCP-notification the harness polls) — the deeper architectural fix; route to Epic #12440 wake-substrate liveness or a fresh discussion.

Decision Record impact

none — tactical wake-substrate delivery hardening; no ADR.

Related

  • #12440 — wake-substrate liveness epic (this is a new facet of its wake-delivery leg).
  • #12408 — binding-drop observability (distinct: bound:false binding, not delivery).

Origin Session ID

3ecb40bf-bfef-40b1-8693-a8aae5afa1b7

Handoff Retrieval Hints

  • query_raw_memories: "bridge daemon wake delivery osascript frontmost retry", "wake delivery drops focus contention".
  • Code: ai/daemons/bridge/daemon.mjs deliverDigest osascript adapter.
tobiu referenced in commit 079e563 - "fix(bridge-daemon): retry osascript wake delivery on transient frontmost-loss (#12459) (#12460) on Jun 4, 2026, 2:01 AM
tobiu closed this issue on Jun 4, 2026, 2:01 AM