LearnNewsExamplesServices
Frontmatter
id13366
titleCodex app-server wakes fail when daemon PATH lacks codex
stateClosed
labels
bugaitestingregressionarchitecturemodel-experience
assigneesneo-gpt
createdAtJun 15, 2026, 6:51 PM
updatedAtJun 15, 2026, 9:01 PM
githubUrlhttps://github.com/neomjs/neo/issues/13366
authorneo-gpt
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[ ] 13287 Codex A2A message wakes may land without submitting while heartbeat wakes submit
closedAtJun 15, 2026, 9:01 PM

Codex app-server wakes fail when daemon PATH lacks codex

Closed v13.1.0/archive-v13-1-0-chunk-3 bugaitestingregressionarchitecturemodel-experience
neo-gpt
neo-gpt commented on Jun 15, 2026, 6:51 PM

Context

Release classification: post-release Agent Harness wake hardening; boardless unless the operator promotes it.

Parent / residual lane: #13287.

After #13350 / PR #13351 migrated @neo-gpt wake subscriptions to harnessTargetMetadata.adapter: codex-app-server, the live wake daemon surfaced a new route blocker instead of the prior osascript submit ambiguity. The wake log showed WAKE_SUB:7648b86c-2f1e-43a8-95a6-cc399f66a938 failing repeated codex-app-server delivery attempts with spawn codex ENOENT, then dropping the wake.

Local falsifier: this Codex Desktop session resolves the executable as /Applications/Codex.app/Contents/Resources/codex, but the long-lived daemon environment does not have bare codex on PATH.

The Problem

The Codex app-server adapter currently assumes codex is discoverable from the daemon process environment. That assumption is false for at least the live macOS daemon path: interactive shells can find Codex Desktop's bundled CLI, while the daemon's reduced environment cannot.

This blocks #13287's migrated-route validation. The subscription now selects the intended submit-capable route, but the route cannot reach the Codex CLI process at all, so no L4 prompt-submit/start-turn matrix can be collected on the migrated path.

The Architectural Reality

  • ai/daemons/wake/daemon.mjs owns live wake delivery for durable WAKE_SUBSCRIPTION rows.
  • ai/scripts/lifecycle/resumeHarness.mjs owns fresh-session harness resume and already has a sibling Codex app-server route.
  • Both surfaces resolve the Codex CLI through a bare codex default when CODEX_CLI_PATH is unset.
  • CODEX_CLI_PATH must remain the highest-priority explicit override for tests, custom installations, and cloud deployments.
  • The macOS Codex Desktop bundled CLI path is an app-local fallback, not a replacement for explicit config. Non-mac/cloud deployments should continue to use explicit CODEX_CLI_PATH or the existing bare codex command contract.
  • The codex-app-server route must fail visibly if the CLI cannot be found; it must not silently fall back to osascript, because that would reintroduce the GUI focus/Enter path this adapter is meant to bypass.

The Fix

Update both Codex app-server entry points to resolve the CLI in this order:

  1. CODEX_CLI_PATH when explicitly set.
  2. On macOS, an executable Codex Desktop bundled CLI path, with a test/relocation override for the Desktop path.
  3. Bare codex as the existing cross-platform fallback.

Add focused unit coverage proving both the wake daemon and resume harness can dispatch through a mocked Desktop-bundled CLI when PATH intentionally lacks bare codex.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
Wake daemon codex-app-server adapter #13287 live wake log + ai/daemons/wake/daemon.mjs Resolve explicit CODEX_CLI_PATH, then macOS bundled Codex Desktop CLI, then bare codex If no executable exists, delivery fails visibly; no osascript fallback Resolver JSDoc names PATH-risk rationale Focused daemon unit test with PATH lacking bare codex
Resume harness codex-app-server adapter ai/scripts/lifecycle/resumeHarness.mjs sibling route Use the same explicit-first / Desktop-fallback / bare-command resolution Live-host guard remains; tests use mock opt-in Existing live-host guard docs updated Focused resume-harness unit test
Cloud / non-mac deployments Existing explicit env contract CODEX_CLI_PATH stays authoritative; bare codex fallback remains No macOS app-path dependency outside darwin Ticket and PR body call out boundary Source review + existing mock coverage

Decision Record impact

Aligned with ADR 0002 / wake-substrate route separation. This is a route-resolution bug fix, not an architecture change.

Acceptance Criteria

  • The wake daemon codex-app-server adapter keeps CODEX_CLI_PATH as the highest-priority override.
  • On macOS, when CODEX_CLI_PATH is unset, the wake daemon can resolve an executable Codex Desktop bundled CLI path before falling back to bare codex.
  • The resume harness Codex app-server route uses the same resolution shape so fresh-session resume and wake delivery do not diverge.
  • Focused unit coverage proves the wake daemon dispatches through a mocked Desktop CLI when PATH lacks bare codex.
  • Focused unit coverage proves the resume harness dispatches through a mocked Desktop CLI when PATH lacks bare codex.
  • The implementation does not silently fall back to osascript for a configured codex-app-server route.
  • The PR does not claim #13287's L4 prompt-submit/start-turn matrix; it only unblocks the migrated route.

Out of Scope

  • Completing the #13287 L4 matrix.
  • Changing wake subscription identity templates or migration behavior from #13350 / PR #13351.
  • Reverting to osascript for Codex wakes.
  • Electron shell/build-root work; that remains #13033.
  • Cloud deployment authentication or installing Codex CLI on remote hosts.

Avoided Traps / Gold Standards Rejected

  • Auto-closing #13287: rejected. The matrix remains open after this route fix.
  • Silent osascript fallback: rejected. It would hide the configured-route failure and revive the old focus-sensitive path.
  • Hardcoding macOS for all deployments: rejected. The bundled path is darwin-only and explicit CODEX_CLI_PATH remains authoritative.
  • Fixing only wake delivery: rejected. Resume harness has the sibling Codex app-server resolver and would drift if left unchanged.

Related

Duplicate / Claim Sweep

Live latest-open sweep: checked the latest 20 open GitHub issues on 2026-06-15T16:50Z. Relevant live hits included #13287, #13012, #13033, #13289, #13362, and H2 follow-ups, but no dedicated spawn codex ENOENT / Codex Desktop CLI resolver ticket.

Targeted live GitHub searches for "spawn codex" ENOENT and "Codex Desktop CLI" "codex-app-server" returned no open duplicate.

A2A in-flight sweep: native list_messages / add_message tools are not exposed in this Codex Desktop surface (tool_search returned no A2A tools earlier in this turn), so private in-flight claim visibility is unavailable. The public GitHub state and repo/content sweep found no duplicate.

Semantic KB sweep: attempted ask_knowledge_base(query='spawn codex ENOENT codex-app-server CODEX_DESKTOP_CLI_PATH wake daemon duplicate ticket', type='ticket'), but the KB MCP is currently unhealthy (knowledgeBase:null, Failed to access collections). This failure is recorded as a live substrate limitation rather than silently omitted.

Exact repo/content sweep: rg "spawn codex|codex-app-server.*ENOENT|Codex Desktop CLI|CODEX_DESKTOP_CLI_PATH" resources/content/issues resources/content/discussions ai learn .agents/workflows found only the implementation branch edits in ai/, not an existing issue/discussion duplicate.

Origin Session ID: unavailable in this Codex Desktop surface.

Retrieval Hint: "Codex app-server spawn codex ENOENT wake daemon CODEX_DESKTOP_CLI_PATH bundled CLI"