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.mjs — deliverOsascript (: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
- Add
'OpenCode' to the adapter allowlist at localWakeAdapters.mjs:532.
- 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.
- 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
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
Context
The wake receiver's
osascriptadapter — 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 markerconsole.logat file top is never evaluated — verified 2026-08-01 against both the v1.18.5 desktop and an isolatedopencode servefrom 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
deliverOsascriptgates on a three-name allowlist. OpenCode's desktop app is an Electron app whose process name is exactlyOpenCode, whose prompt accepts the standardcmd+a/cmd+x/cmd+v/ Return choreography the adapter's script already performs, and whose per-seatuserDataDir(ai.opencode.desktop) resolves cleanly through the existingresolveGuiInstancePidpath. Nothing in the adapter's AppleScript is Claude- or Codex-specific beyond the optionaltabShortcut/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.mjs—deliverOsascript(:527) with the allowlist at :532;buildOsascriptArgs(:574) is app-generic except the optional Codex-onlykey code 53(Esc) branch and the focus-seed options, all of which are opt-in metadata an OpenCode route simply omits.resolveGuiInstancePidalready handlesuserDataDir-shaped instance tuples for GUI apps; OpenCode's per-seat data dir follows the same convention as Claude's (Library/Application Support/<app>).The Fix
'OpenCode'to the adapter allowlist atlocalWakeAdapters.mjs:532.localWakeAdapters.spec.mjs.Contract Ledger Matrix
localWakeAdapters.mjs:532OpenCodeadmitted to the GUI delivery pathskippeduserDataDir(ai.opencode.desktop)skipped(named once #16259/#16264 lands)Decision Record impact
none. The adapter's app surface is implementation detail inside the wake lane; no ADR governs the allowlist.Acceptance Criteria
harnessTargetMetadata: {adapter: 'osascript', appName: 'OpenCode', addressType: 'userDataDir', instanceAddress: <seat data dir>}dispatches through the osascript path instead of returningskipped— spec-pinned.deliveredand the wake visible in the OpenCode desktop — recorded as PMV.Out of Scope
Avoided Traps
Related
skippedoutcomesOrigin Session ID: a9c25413-6846-4dee-a4e7-513e7600e0af
Retrieval Hint:
osascript adapter OpenCode allowlist GUI wake delivery Electron desktop seat