Skip to content

fix(codex): seed spawn-window agent status from launch metadata - #14222

Closed
tonite31 wants to merge 2 commits into
stablyai:mainfrom
tonite31:codex-spawn-window-seed
Closed

tonite31 wants to merge 2 commits into
stablyai:mainfrom
tonite31:codex-spawn-window-seed

Conversation

@tonite31

Copy link
Copy Markdown
Contributor

Summary

Fixes the #6643 symptom for runtime-built spawns: a Codex agent launched by Orca now appears in the agent status surface at spawn, using launch metadata, instead of staying absent until the first user message.

Root cause (measured)

Codex emits no hook at TUI startup. Captured with a captive HTTP listener replacing the managed hook endpoint (codex current, macOS):

  • Idle TUI open: zero hook posts while the TUI sits at the prompt.
  • First prompt submit: SessionStart at 05:40:22.597Z, UserPromptSubmit at 05:40:22.616Z — 19 ms apart, ~50 s after the TUI opened. session_id is stamped on every event of the turn.

Claude has no such gap because its SessionStart fires at TUI open. Orca's Codex status surface is hook-driven, and the renderer's paneStartup.initialAgentStatus seeding only covers UI-created panes. Runtime-built spawns (CLI worktree create --agent codex, automations) mount no renderer pane, so nothing seeds:

  • create with --prompt: no status row from create (05:36:16Z) until the first turn's hooks (05:36:24Z), while the TUI was already Working at 05:36:19Z
  • plain spawn: no status row indefinitely while the TUI idles

Fix

AgentHookServer.seedCodexLaunchStatus + a call in createManagedWorktree after the startup terminal spawns (git and folder-workspace branches):

  • injected prompt → working row carrying the prompt
  • plain spawn → idle done + sessionBoundary row (mirrors Claude's SessionStart row: no phantom spinner, completion-reactive consumers skip it)
  • an existing pane status always wins (a real PermissionRequest waiting is never overwritten), retired panes are not resurrected, duplicate seeds are idempotent, and any later hook/OSC status replaces the seed
  • local repos only: remote pane status arrives relay-stamped with a connectionId that a local seed row would contradict (the SSH app-server-reuse gap is [Bug]: SSH Codex sessions emit no Orca hooks when the TUI reuses an existing app-server #11941, out of scope here)
  • no wire/payload shape changes — existing optional fields only

Relationship to #8292

Builds on, does not duplicate: #8292 makes SessionStart metadata-only (identity cache + stale-row clear) and explicitly excludes startup delivery. This PR touches none of #8292's normalizer/relay/hook-service lines, and the seed behaves correctly under #8292's semantics — the first turn's SessionStart clears the seed row and UserPromptSubmit recreates it 19 ms later. Since Codex fires SessionStart only alongside the first prompt, spawn-window presence has to come from launch metadata, which #6643's notes also suggest.

Testing

  • src/main/agent-hooks/server.test.ts: 8 new state-machine tests (seed shapes, idempotence, PermissionRequest-at-spawn precedence, waiting→working recovery on first turn, first-turn replacement with providerSession caching, duplicate identical UserPromptSubmit/Stop delivery, retired-pane no-op) — 276 file tests green
  • src/main/runtime/orca-runtime.test.ts: CLI-created local worktree seeds with the injected prompt — 1082 file tests green
  • Node typecheck, targeted oxlint, oxfmt --check
  • Electron/E2E

Refs #6643

🤖 Generated with Claude Code

Codex emits no hook at TUI startup: SessionStart only fires lazily,
milliseconds before the first UserPromptSubmit (measured 19ms apart on
codex current; an idle TUI posts nothing). Claude has no such gap because
its SessionStart fires at TUI open (STA-3386). Orca's codex status surface
is hook-driven, so a runtime-built spawn (orca worktree create --agent
codex, automations) has no card row until the first turn — upstream stablyai#6643.
UI-built spawns already seed via the renderer's initialAgentStatus path.

Seed the row in main at startup-terminal spawn:
- with an injected prompt: a working row carrying that prompt
- plain spawn: an idle session-boundary done row (mirrors Claude's
  SessionStart row; no phantom spinner, no completion notifications)

The seed never overwrites an existing status (a real PermissionRequest
waiting always wins), no-ops on retired panes, is idempotent under
duplicate delivery, and any later hook/OSC status replaces it. Local
repos only: remote status arrives relay-stamped with a connectionId a
local seed row would contradict.

Refs upstream stablyai#6643; complements stablyai#8292, which keeps
SessionStart metadata-only and explicitly excludes startup delivery.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 13, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 579a572d-15e7-433f-81b5-b92f261e56ed

📥 Commits

Reviewing files that changed from the base of the PR and between 229c25a and 17d5a43.

📒 Files selected for processing (2)
  • src/main/runtime/orca-runtime.test.ts
  • src/main/runtime/orca-runtime.ts

📝 Walkthrough

Walkthrough

The change adds AgentHookServer.seedCodexLaunchStatus for validated prompt and promptless Codex pane states. Runtime terminal creation invokes it for eligible local, non-startup Codex launches and passes launch metadata. Tests cover idempotence, preservation of existing and retired pane states, hook replacement, provider-session caching, recovery, completion, and duplicate hook delivery.

Mergeability Score: 🔵 Low · up to 17d5a

The change makes Codex status appear at spawn, with bounded merge-readiness risk from a test spy that is not restored and incomplete coverage of promptless and folder-workspace launches; merge is reasonable with explicit follow-up on test isolation and those paths.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely identifies the Codex spawn-window status seeding change.
Description check ✅ Passed The description clearly explains the problem, root cause, implementation, issue reference, testing, and known test gap.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/main/runtime/orca-runtime.test.ts (1)

42921-42999: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add runtime coverage for the remaining launch paths.

This test covers only a prompt-bearing local Git worktree launch. Add tests for a promptless Codex launch and the folder-workspace terminal creation path. Verify that each path calls seedCodexLaunchStatus with the created pane and worktree metadata.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 024761cb-2bb1-4ea9-bd4a-8bd980536ec7

📥 Commits

Reviewing files that changed from the base of the PR and between 602f0cb and 229c25a.

📒 Files selected for processing (4)
  • src/main/agent-hooks/server.test.ts
  • src/main/agent-hooks/server.ts
  • src/main/runtime/orca-runtime.test.ts
  • src/main/runtime/orca-runtime.ts

Comment thread src/main/runtime/orca-runtime.ts Outdated
CodeRabbit review: a seedCodexLaunchStatus failure inside the startup-terminal
try/catch overwrote the already-successful spawn result with a misleading
"Failed to create the startup terminal" warning. Extract both duplicated call
sites into seedCodexLaunchStatusIfEligible with its own log-and-continue
catch, and add a runtime test proving a seeding throw preserves the
startupTerminal success state.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@tonite31

Copy link
Copy Markdown
Contributor Author

Closing in favor of #14611, which supersedes this and covers the two gaps it names: the renderer path being gated to command-code so UI-launched Codex panes stayed uncovered, and the skipped seed when the caller supplies startup. Thanks for carrying over the diagnosis and the sessionBoundary idle-row choice.

@tonite31 tonite31 closed this Aug 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants