LearnNewsExamplesServices
Frontmatter
id16279
titleosascript wake adapter refuses OpenCode by name, leaving desktop seats undeliverable
stateClosed
labels
bugai
assigneesneo-kimi-phoebe
createdAtAug 1, 2026, 7:06 PM
updatedAtAug 1, 2026, 9:14 PM
githubUrlhttps://github.com/neomjs/neo/issues/16279
authorneo-kimi-phoebe
commentsCount1
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtAug 1, 2026, 9:14 PM

osascript wake adapter refuses OpenCode by name, leaving desktop seats undeliverable

neo-kimi-phoebe
neo-kimi-phoebe commented on Aug 1, 2026, 7:06 PM

Context

The wake receiver's osascript adapter — the only GUI-app delivery path that needs no plugin, no envelope, and no per-boot credential — refuses OpenCode by name: localWakeAdapters.mjs:532 (if (!['Antigravity', 'Claude', 'Codex'].includes(appName)) return 'skipped'). The result: every OpenCode desktop seat is undeliverable through the GUI path, and the only remaining adapter (opencode-server) depends on the wake-envelope plugin, which has never been observed arming in the desktop app (no load-time log line in any log source, and a marker console.log at file top is never evaluated — verified 2026-08-01 against both the v1.18.5 desktop and an isolated opencode serve from a project-level plant).

The full chain diagnosis this ticket closes is on the record: route published and live (401-on-forged-signature), receiver delivering to the route, and the dispatch dying at the adapter — the same seat-class as the kimi CLI seats this lane already treats as first-class.

Live latest-open sweep: checked latest 20 open issues at 2026-08-01T16:55Z; no equivalent found. A2A in-flight claim sweep over the last 30 messages at the same timestamp: no competing [lane-claim] on OpenCode adapter support.

The Problem

deliverOsascript gates on a three-name allowlist. OpenCode's desktop app is an Electron app whose process name is exactly OpenCode, whose prompt accepts the standard cmd+a / cmd+x / cmd+v / Return choreography the adapter's script already performs, and whose per-seat userDataDir (ai.opencode.desktop) resolves cleanly through the existing resolveGuiInstancePid path. Nothing in the adapter's AppleScript is Claude- or Codex-specific beyond the optional tabShortcut / focusSeedSequence / Codex-Esc branches — the generic path (activate → frontmost assert → clear-and-preserve prompt → paste payload → Return → restore user input) applies to OpenCode unchanged. The only barrier is the allowlist line.

Verified on this machine: the receiver delivered a real wake to my route at 13:06Z today (signature verified, dispatch attempted), and it failed in the opencode-server adapter for envelope reasons that the osascript path does not have.

The Architectural Reality

  • ai/daemons/wake/localWakeAdapters.mjsdeliverOsascript (:527) with the allowlist at :532; buildOsascriptArgs (:574) is app-generic except the optional Codex-only key code 53 (Esc) branch and the focus-seed options, all of which are opt-in metadata an OpenCode route simply omits.
  • resolveGuiInstancePid already handles userDataDir-shaped instance tuples for GUI apps; OpenCode's per-seat data dir follows the same convention as Claude's (Library/Application Support/<app>).
  • The receiver, manifest, generator, and route for my seat are all proven live (the 13:06Z record); the missing link is strictly the adapter allowlist.
  • The Accessibility permission for the receiver's controlling terminal was already exercised on this host this morning (Ada's cohort wakes), so the TCC gate is not new surface.

The Fix

  1. Add 'OpenCode' to the adapter allowlist at localWakeAdapters.mjs:532.
  2. Spec: an OpenCode-named route passes the gate (dispatch reaches the osascript spawn with the generic arg vector), and the existing three names keep passing — asserted via the adapter's existing fake-effects harness in localWakeAdapters.spec.mjs.
  3. No OpenCode-specific script branches: the generic choreography is the contract; if live proof shows an Electron quirk (e.g., prompt not focused), that lands as a follow-up with the quirk named, not preemptively.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
osascript app allowlist localWakeAdapters.mjs:532 OpenCode admitted to the GUI delivery path unsupported names keep returning skipped adapter JSDoc spec: OpenCode route dispatches via the generic arg vector
OpenCode instance tuple per-seat userDataDir (ai.opencode.desktop) resolves through the existing GUI-instance pid path unresolvable → skipped (named once #16259/#16264 lands) manifest docs spec or live record names the outcome

Decision Record impact

none. The adapter's app surface is implementation detail inside the wake lane; no ADR governs the allowlist.

Acceptance Criteria

  • A route with harnessTargetMetadata: {adapter: 'osascript', appName: 'OpenCode', addressType: 'userDataDir', instanceAddress: <seat data dir>} dispatches through the osascript path instead of returning skipped — spec-pinned.
  • The existing three app names keep their behavior (positive control).
  • Post-merge live proof on this machine: a high-priority non-suppressed DM to @neo-kimi-phoebe delivers through the receiver with state delivered and the wake visible in the OpenCode desktop — recorded as PMV.

Out of Scope

  • The wake-envelope plugin's desktop loading (the opencode-server adapter's dependency; upstream-level, tracked separately).
  • The desktop internal server's per-boot credential behavior (proven to not accept env-provisioned creds; the osascript path needs no credentials).
  • TCC/Accessibility provisioning for the receiver's controlling context (already exercised on this host; documented in the runbook for fresh hosts).

Avoided Traps

  • Preemptive Electron-specific script branches — the generic path is proven for two other Electron-family apps; adding quirks before the live proof invents requirements.
  • Widening the opencode-server envelope contract instead — the desktop internal server demonstrably does not accept env-provisioned credentials (every endpoint 401 with byte-equal spawn-env values), and per-boot generated credentials are only discoverable from inside the app process; the osascript path has no credential surface at all.

Related

  • #16233 / PR #16249 — the manifest generator whose routes this unblocks for OpenCode seats
  • #16259 / PR #16264 — the failure-reason surfacing that will name future skipped outcomes
  • #16267 / PR #16271 — SIGHUP manifest reload (route adoption without restart)
  • #16180 — the signed receiver this adapter serves

Origin Session ID: a9c25413-6846-4dee-a4e7-513e7600e0af

Retrieval Hint: osascript adapter OpenCode allowlist GUI wake delivery Electron desktop seat

tobiu referenced in commit ce57ce4 - "feat(wake): admit OpenCode to the osascript delivery adapter (#16279) (#16281) on Aug 1, 2026, 7:43 PM
tobiu closed this issue on Aug 1, 2026, 7:43 PM
tobiu referenced in commit cf5f366 - "feat(wake): admit OpenCode at the route-declaration and registration gates (#16279) (#16293) on Aug 1, 2026, 9:14 PM
tobiu closed this issue on Aug 1, 2026, 9:14 PM