Skip to content

feat(native-chat): require Codex 0.136.0 for chats - #26684

Merged
brennanb2025 merged 28 commits into
mainfrom
brennanb2025/codex-minimum-version
Oct 12, 2026
Merged

brennanb2025 merged 28 commits into
mainfrom
brennanb2025/codex-minimum-version

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 20 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​696 $\color{#cf222e}{\Huge{\mathbf{−}}}$​88 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​608
Prod 26 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​307 $\color{#cf222e}{\Huge{\mathbf{−}}}$​64 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​243

ELI5

Orca's Codex chats run whatever Codex you have installed. Codex older than 0.136.0 doesn't understand the message id Orca sends with every chat turn, so a chat on an old Codex used to fail later with an error that didn't say why or what to do. Now, when a chat starts Codex, Orca checks its version first. If it's too old, the chat says so in one plain line and keeps your message. Update Codex, press Send again, and it works.

What Changed

Before: a native Codex chat started on any Codex version. On an old one it failed later with a confusing error, and Orca kept a special fallback (resuming chats without excludeTurns) just for old versions.

After:

  • When a chat starts Codex, normally when you press Send, Orca checks the Codex version on the machine that runs the chat. It uses the same command, folder and environment the chat would use.
  • Too old: the send is refused with one plain row, "Codex 0.135.0 is too old for chats. Update to 0.136.0 or newer.". Your message stays in the chat and no Codex process starts.
  • After you update Codex (however you installed it): press Send again. The next start checks again. Nothing is retried or re-sent automatically.
  • Missing Codex: unchanged. Main's existing "Codex wasn't found…" message appears.
  • Version can't be read (odd output, a timeout): nothing is blocked. Orca logs it and starts the chat.
  • Terminal Codex tabs: unchanged.
  • Main's old-Codex fallback that resumed chats without excludeTurns is removed.

Mechanism:

  • The check lives in the Codex launch resolver, which already runs on the execution host before Orca spawns codex app-server for a chat.
  • It runs codex --version once per new chat process, with a 5-second limit. Nothing is cached, so the first Send after an update is always checked fresh.
  • A known-too-old version throws a typed refusal. That refusal goes through the existing start-failure path, the same one a "not signed in" failure already uses, so the chat shows it in the existing failure row and keeps the message.

Why

An earlier version of this PR also:

  • kept the check result on the client and re-checked when the window regained focus;
  • retried automatically once Codex was fixed;
  • blocked new-workspace creation;
  • offered Install/Update buttons.

Live QA found that machinery was where the bugs were; for example, the "too old" notice never appeared until you pressed Send. It was also most of the code. The common pattern is simpler: check on the machine that runs the agent when the agent starts, report a refusal like any other start failure, and check again on the next attempt. This PR follows that mechanism. Install Codex in Settings → Agents was split out of this PR and is on hold.

How the floor was chosen: from Codex's tagged 0.135.0 and 0.136.0 protocol schemas. clientUserMessageId, which Orca sends on every turn start and steer, first appears in 0.136.0. 0.136.0 also accepts excludeTurns, and approvalsReviewer (which #26116's "Approve for me" needs).

Differences from the common pattern:

  • Intended: an unknown version is allowed and logged, not refused. A version Orca can't read is no evidence of an old Codex, and a check shouldn't block someone whose Codex may work.
  • Intended: Orca's refusal row states the version and the fix in plain words, rather than a generic "command failed" title with the advice hidden in details.
  • Intended: no result is cached. One codex --version per new chat process (normally the first Send, or after a long idle) is cheap, and a cached refusal could block the first Send right after an update.
  • Intended: only chat processes are checked; terminal Codex tabs keep working with any version.

Not changed here: Codex chat rewind uses thread/revert, which 0.136.0 doesn't have. On a Codex without it, Orca already reports rewind as unsupported instead of failing, and this PR doesn't change that.

Linked Issue

Maintainer request (no issue): require a minimum Codex version for native chats. Related: #26116 (chat permission modes) depends on this floor.

Visual Proof

Too old: refused once, message kept After updating: the next Send just works
too old recovered

Captured in a hidden Electron app with the real Codex and a real login: 0.159.0 for the working chat, and a real 0.135.0 installed into a test-only folder and set as Codex's Command in Settings → Agents for the refusal. No stand-ins.

Testing

  • I manually tested these changes locally (macOS, real Codex)
  • Automated tests added/updated

Live, with the real Codex:

  • A working chat on 0.159.0 got its reply.
  • With Codex's Command pointed at a real 0.135.0, Send was refused with exactly one row, the message was kept, and no Codex process started.
  • Sending again gave one row per send and no automatic retries.
  • After resetting Command to 0.159.0, the next Send worked immediately and nothing was re-sent.
  • With Command pointed at a path that doesn't exist, main's existing Command-setting failure appeared once.

Automated:

  • version boundaries and odd version output;

  • the refusal's wording and facts;

  • queued messages survive a refusal and are never re-sent automatically;

  • a refusal is never reused (an update followed by an immediate Send succeeds);

  • folder-relative commands;

  • resume no longer retries without excludeTurns.

  • After the final merge with main (88a82c0): tc:node, tc:web, 1,899 tests passed (11 skipped), changed-code quality, localization and the mobile typecheck ratchet passed; orca-ci-checks 22/23 locally, the one failure being the mobile dependency-cycle warnings that also fail on main locally.

Not verified: Windows, Linux, WSL and SSH execution; live mixed client/host versions.

Agent skill upstream boundary

  • Not applicable, or this change copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

  • Security: no new commands beyond codex --version, which runs without a shell through the shared child-process runner.
  • Cross-platform: Windows .cmd shims are handled by that runner.
  • Remote/SSH: the check runs only on the machine that runs the chat; there is no substitute check on the client.
  • Backwards compatibility: no new wire fields or stream opcodes. The refusal carries optional typed facts plus plain host text, so older clients still show a readable failure.
  • Performance: one short version probe per new chat process.

Checklist

  • This PR is small and focused
  • I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred)

…nimum-version

# Conflicts:
#	src/shared/child-process/process-tree-termination.ts
…ct; keep the registry out of the relay

Runtime tests that drive a scripted Codex app-server still ran the new
version check against whatever codex was on the machine's PATH: refused
on CI (no codex), and on a dev machine it ran the real codex --version.
A scripted transport now must state the Codex it stands for
(readCodexInstallation), asserted at install, and the tests get it from
one scriptedCodexTransport fixture.

The relay's Codex maintenance path reached @orca/windows-registry through
resolvePathEnvKey's re-export in windows-environment-path; import it from
its registry-free module instead.

Also update the catalog-probe test for the shared child environment.
@brennanb2025

Copy link
Copy Markdown
Contributor Author

Review summary

This PR got six adversarial code-review rounds, two live QA rounds in a hidden Electron app, and a final CI pass.

Fixed during review

  • Round 1 (8):
    • the check now uses the Codex command from Settings and its environment, not stock Codex;
    • cache identity;
    • the chat's working folder;
    • the update's whole process tree is supervised;
    • store retries;
    • codex update isn't offered on versions too old to have it;
    • version-output parsing;
    • stale results are dropped.
  • Rounds 2–4 (10): relative command paths, environment parity between check and launch, global npm layout detection, expiry of saved results, cleanup of a superseded update, and mixed-version capability negotiation.
  • Live QA:
    • the tab-bar chat now shows the same notice as the composer;
    • the refused chat recovers by itself after an update;
    • the wording is plain.
  • Round 5 (2): a dead Retry button, and failure diagnostics that never reached the log.
  • Round 6 (2):
    • UTF-8 characters split across output chunks;
    • an unused host-detection helper removed.
    • The round was otherwise clean.
  • After merging main:
    • updating Codex over a paired-runtime connection now needs host-admin permission;
    • the missing-Codex explanation is shown once, not twice.
  • CI:
    • scripted-Codex runtime tests now supply their installation fact instead of reaching the machine's codex;
    • a Windows-registry import is out of the SSH relay bundle.

Verified

  • Full CI is green on 4436b0a1a5a.
  • Live QA used a stand-in Codex, with no real Codex or npm:
    • the too-old notice;
    • Update with its log;
    • recovery of the same chat;
    • sending afterwards;
    • an unknown version is allowed;
    • the Settings row.

Not verified:

  • native Windows, Linux, WSL and SSH execution;
  • real installers;
  • live mixed-version client/host pairs.

Left as is, on purpose:

  • the log window stays open after a successful update;
  • a missing custom command path shows the existing "command not found" settings error.

@brennanb2025
brennanb2025 marked this pull request as ready for review October 9, 2026 04:37
@coderabbitai

coderabbitai Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: b6a5e521-d162-4270-a092-913d98206e70

📥 Commits

Reviewing files that changed from the base of the PR and between fe68bd3 and aff57f9.


📒 Files selected for processing (25)
  • src/main/codex/codex-cli-installation-error.ts
  • src/main/codex/codex-minimum-version.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-codex-version-recovery.test.ts
  • src/main/preflight/codex-cli-installation.test.ts
  • src/main/preflight/codex-cli-installation.ts
  • src/main/preflight/codex-workspace-relative-path.test.ts
  • src/main/runtime/structured-agent-launch-parity.test.ts
  • src/main/runtime/structured-agent-runtime-registrations.ts
  • src/main/runtime/structured-agent-session-integration.test.ts
  • src/main/runtime/structured-agent-session-runtime.ts
  • src/main/runtime/structured-child-records-switch.test.ts
  • src/main/runtime/structured-codex-child-work-runtime.test.ts
  • src/main/runtime/structured-codex-session-rpc-test-harness.ts
  • src/renderer/src/components/native-chat/NativeChatNoticeRow.test.tsx
  • src/renderer/src/components/native-chat/NativeChatStructuredSession.approval-and-start-failure.test.tsx
  • src/renderer/src/components/native-chat/agent-session-availability-words-text.ts
  • src/renderer/src/i18n/en-runtime-required.json
  • src/renderer/src/i18n/locales/en.json
  • src/renderer/src/i18n/locales/es.json
  • src/renderer/src/i18n/locales/fr.json
  • src/renderer/src/i18n/locales/ja.json
  • src/renderer/src/i18n/locales/ko.json
  • src/renderer/src/i18n/locales/zh.json
  • src/shared/agent-session-failure-copy.ts
  • src/shared/agent-session-failure-words.ts

🚧 Files skipped from review as they are similar to previous changes (7)
  • src/renderer/src/i18n/en-runtime-required.json
  • src/renderer/src/i18n/locales/en.json
  • src/renderer/src/i18n/locales/ko.json
  • src/renderer/src/i18n/locales/ja.json
  • src/renderer/src/i18n/locales/fr.json
  • src/renderer/src/i18n/locales/zh.json
  • src/renderer/src/i18n/locales/es.json

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 3 remain after this review.



📝 Walkthrough
📝 Walkthrough

Walkthrough

The changes add Codex CLI version parsing and probing, then check the resolved binary, working directory, and environment before structured launches. Unsupported installations become structured-session failures with missing-CLI or too-old-CLI details and localized notices. Tests cover launch admission, workspace-relative commands, failure recovery, and notice rendering. Thread resume requests now send excludeTurns: true without retrying when the server rejects that field.


Priority: ➖ Normal

Merge Risk: 🔵 Low · up to aff57

A wrapped Codex installation failure may show generic guidance instead of the version-specific explanation. The remaining risk is bounded, but the lookup should be fixed or explicitly accepted before merging.

Pre-merge checks | Passed 4 | Failed 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 20.59% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 102 functions across 100 files. (7 skippe… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
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.
Title check Passed The title clearly and concisely describes the primary change: requiring Codex 0.136.0 for native chats.
Description check Passed The description is complete and aligned with the changes. It includes the user impact, mechanism, rationale, linked-issue context, visual proof, testing, platform limitations, and checklist status.

Full details: Docstring Coverage

Explanation

Docstring coverage is 20.59% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 102 functions across 100 files. (7 skipped: 7 unsupported.)


  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR

  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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: 2


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 8ccef85c-6e6f-46fe-b78a-b81abace6dee
📥 Commits

Reviewing files that changed from the base of the PR and between 820277c and 4436b0a.

⛔ Files ignored due to path filters (1)
  • src/shared/rpc-contract/rpc-params-catalog.generated.ts is excluded by !**/*.generated.*
📒 Files selected for processing (137)
  • src/main/agent-cli-version-probe.ts
  • src/main/cli/orca-cli-child-path.test.ts
  • src/main/cli/orca-cli-child-path.ts
  • src/main/codex/codex-cli-installation-error.ts
  • src/main/codex/codex-minimum-version.test.ts
  • src/main/codex/codex-model-catalog-probe.test.ts
  • src/main/codex/codex-structured-launch-resolution.test.ts
  • src/main/codex/codex-structured-launch-resolution.ts
  • src/main/codex/codex-structured-thread-open.test.ts
  • src/main/codex/codex-structured-thread-open.ts
  • src/main/codex/configured-codex-invocation.ts
  • src/main/ipc/command-path-resolver.ts
  • src/main/ipc/local-command-path-search.test.ts
  • src/main/ipc/local-command-path-search.ts
  • src/main/ipc/preflight.ts
  • src/main/ipc/pty/host-env/path.ts
  • src/main/ipc/register-core-handlers/register-core-handlers.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-codex-version-recovery.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-failed-create-refusal.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-failure-text.ts
  • src/main/preflight/codex-cli-installation-cache.ts
  • src/main/preflight/codex-cli-installation.test.ts
  • src/main/preflight/codex-cli-installation.ts
  • src/main/preflight/codex-maintenance-command.test.ts
  • src/main/preflight/codex-maintenance-command.ts
  • src/main/preflight/codex-maintenance-configured-command.test.ts
  • src/main/preflight/codex-maintenance-diagnostic.ts
  • src/main/preflight/codex-maintenance-environment.test.ts
  • src/main/preflight/codex-maintenance-host.test.ts
  • src/main/preflight/codex-maintenance-host.ts
  • src/main/preflight/codex-maintenance-process.test.ts
  • src/main/preflight/codex-maintenance-process.ts
  • src/main/preflight/codex-maintenance-process.utf8.test.ts
  • src/main/preflight/codex-maintenance-runner.diagnostics.test.ts
  • src/main/preflight/codex-maintenance-runner.termination.test.ts
  • src/main/preflight/codex-maintenance-runner.test.ts
  • src/main/preflight/codex-maintenance-runner.ts
  • src/main/preflight/codex-maintenance-windows-supervisor.test.ts
  • src/main/preflight/codex-maintenance-windows-supervisor.ts
  • src/main/preflight/codex-npm-installation-files.ts
  • src/main/preflight/codex-npm-installation-layout.test.ts
  • src/main/preflight/codex-npm-installation-layout.ts
  • src/main/preflight/codex-workspace-relative-path.test.ts
  • src/main/runtime/orca-runtime-get-worktree-ps.ts
  • src/main/runtime/rpc/methods/preflight.ts
  • src/main/runtime/rpc/preflight-codex-maintenance-permission.test.ts
  • src/main/runtime/runtime-rpc/runtime-rpc-mobile-method-allowlist.ts
  • src/main/runtime/scripted-codex-transport.test-fixture.ts
  • src/main/runtime/structured-agent-launch-args-wiring.test.ts
  • src/main/runtime/structured-agent-runtime-registrations.ts
  • src/main/runtime/structured-agent-session-codex-interrupt-order.test.ts
  • src/main/runtime/structured-agent-session-codex-opening-send-hold.test.ts
  • src/main/runtime/structured-agent-session-codex-settlement-order.test.ts
  • src/main/runtime/structured-agent-session-codex-stopped-send-order.test.ts
  • src/main/runtime/structured-agent-session-codex-turn-end-settlement.test.ts
  • src/main/runtime/structured-agent-session-integration.test.ts
  • src/main/runtime/structured-agent-session-runtime-exit.test.ts
  • src/main/runtime/structured-agent-session-runtime.ts
  • src/main/runtime/structured-chat-coordinator-mail-rig.test-fixture.ts
  • src/main/runtime/structured-child-records-switch.test.ts
  • src/main/runtime/structured-codex-child-work-runtime.test.ts
  • src/main/runtime/structured-codex-session-rpc-test-harness.ts
  • src/main/runtime/structured-foreground-command-strip.test.ts
  • src/main/runtime/structured-session-child-identity-env.ts
  • src/preload/api/preflight-api.ts
  • src/preload/api/preflight-bridge.ts
  • src/relay/codex-maintenance-relay.test.ts
  • src/relay/preflight-codex-version.test.ts
  • src/relay/preflight-command-version.ts
  • src/relay/preflight-handler.ts
  • src/renderer/src/App.tsx
  • src/renderer/src/components/NewWorkspaceComposerCard.codex-maintenance.test.tsx
  • src/renderer/src/components/NewWorkspaceComposerCard.tsx
  • src/renderer/src/components/NewWorkspaceComposerModal.tsx
  • src/renderer/src/components/native-chat/CodexMaintenanceLogDialog.tsx
  • src/renderer/src/components/native-chat/NativeChatComposerNotices.tsx
  • src/renderer/src/components/native-chat/NativeChatNoticeRow.codex-maintenance.test.tsx
  • src/renderer/src/components/native-chat/NativeChatNoticeRow.test.tsx
  • src/renderer/src/components/native-chat/NativeChatNoticeRow.tsx
  • src/renderer/src/components/native-chat/NativeChatStructuredSession.codex-recovery.test.tsx
  • src/renderer/src/components/native-chat/NativeChatStructuredSession.start-failure-notice.test.tsx
  • src/renderer/src/components/native-chat/NativeChatStructuredSession.tsx
  • src/renderer/src/components/native-chat/NativeChatStructuredSessionControls.tsx
  • src/renderer/src/components/native-chat/agent-session-failure-words-text.ts
  • src/renderer/src/components/native-chat/codex-maintenance-copy.ts
  • src/renderer/src/components/native-chat/codex-maintenance-failure-copy.test.tsx
  • src/renderer/src/components/native-chat/codex-maintenance-recovery-notice.ts
  • src/renderer/src/components/native-chat/codex-maintenance-ui.test.tsx
  • src/renderer/src/components/native-chat/native-chat-composer-notice.ts
  • src/renderer/src/components/native-chat/native-chat-notice-row.test-fixture.tsx
  • src/renderer/src/components/native-chat/native-chat-structured-session-notices.ts
  • src/renderer/src/components/native-chat/use-native-chat-availability-notice.test.tsx
  • src/renderer/src/components/native-chat/use-native-chat-availability-notice.ts
  • src/renderer/src/components/native-chat/use-native-chat-codex-maintenance.test.tsx
  • src/renderer/src/components/native-chat/use-native-chat-codex-maintenance.ts
  • src/renderer/src/components/native-chat/use-structured-agent-session-start-failure-facts.test.ts
  • src/renderer/src/components/native-chat/use-structured-agent-session-start-failure-facts.ts
  • src/renderer/src/components/new-workspace/NewWorkspaceComposerFooter.tsx
  • src/renderer/src/components/new-workspace/use-new-workspace-codex-maintenance.ts
  • src/renderer/src/components/settings/AgentCatalogRow.tsx
  • src/renderer/src/components/settings/AgentsPane.tsx
  • src/renderer/src/components/settings/CodexMaintenanceRow.tsx
  • src/renderer/src/hooks/useCodexMaintenance.evidence.test.tsx
  • src/renderer/src/hooks/useCodexMaintenance.ts
  • src/renderer/src/i18n/en-runtime-required.json
  • src/renderer/src/i18n/locales/en.json
  • src/renderer/src/i18n/locales/es.json
  • src/renderer/src/i18n/locales/fr.json
  • src/renderer/src/i18n/locales/ja.json
  • src/renderer/src/i18n/locales/ko.json
  • src/renderer/src/i18n/locales/zh.json
  • src/renderer/src/lib/codex-maintenance-activity.ts
  • src/renderer/src/lib/codex-maintenance-client.test.ts
  • src/renderer/src/lib/codex-maintenance-client.ts
  • src/renderer/src/lib/codex-maintenance-host-contact.test.ts
  • src/renderer/src/lib/codex-maintenance-host-contact.ts
  • src/renderer/src/lib/codex-maintenance-observation.ts
  • src/renderer/src/lib/codex-maintenance-snapshot.ts
  • src/renderer/src/lib/codex-maintenance-store.test.ts
  • src/renderer/src/lib/codex-maintenance-store.ts
  • src/renderer/src/web/preload-api/web-host-capability-api.ts
  • src/shared/agent-session-failure-copy.ts
  • src/shared/agent-session-failure-words.ts
  • src/shared/agent-session-refusal-details.ts
  • src/shared/agent-session-refusal-notice.ts
  • src/shared/agent-session-visible-failures.ts
  • src/shared/agent-session-write-failure.ts
  • src/shared/browser-client-host-capabilities.ts
  • src/shared/child-process/process-tree-termination.test.ts
  • src/shared/child-process/process-tree-termination.ts
  • src/shared/codex-cli-installation.test.ts
  • src/shared/codex-cli-installation.ts
  • src/shared/codex-cli-maintenance.test.ts
  • src/shared/codex-cli-maintenance.ts
  • src/shared/codex-installation-failure-words.ts
  • src/shared/codex-maintenance-recovery.ts
  • src/shared/protocol-version.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 6 remain after this review.

Comment on lines +20 to +31
export function codexInstallationProblemOf(
error: unknown,
depth = 0
): CodexInstallationProblem | undefined {
if (depth >= 6 || !(error instanceof Error)) {
return undefined
}
if (error instanceof CodexCliInstallationError) {
return error.codexInstallation
}
return codexInstallationProblemOf(error.cause, depth + 1)
}

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Traverse AggregateError in codexInstallationProblemOf, as argumentProblemOf does.

argumentProblemOf in src/main/native-chat/structured-agent-arguments-error.ts:25-44 checks each entry of AggregateError.errors. codexInstallationProblemOf checks only error.cause. The acquisition path uses both helpers in failedAcquisitionDetails, failedAcquisitionRefusal, and providerStartupFailureFact. If any layer wraps a CodexCliInstallationError in an AggregateError, the codexInstallation fact is lost. The chat then shows the generic "couldn't start" text, and the renderer has no fact to offer Update Codex. Use the same traversal in both helpers.

🐛 Proposed fix
   if (error instanceof CodexCliInstallationError) {
     return error.codexInstallation
   }
+  if (error instanceof AggregateError) {
+    for (const inner of error.errors) {
+      const problem = codexInstallationProblemOf(inner, depth + 1)
+      if (problem) {
+        return problem
+      }
+    }
+  }
   return codexInstallationProblemOf(error.cause, depth + 1)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export function codexInstallationProblemOf(
error: unknown,
depth = 0
): CodexInstallationProblem | undefined {
if (depth >= 6 || !(error instanceof Error)) {
return undefined
}
if (error instanceof CodexCliInstallationError) {
return error.codexInstallation
}
return codexInstallationProblemOf(error.cause, depth + 1)
}
export function codexInstallationProblemOf(
error: unknown,
depth = 0
): CodexInstallationProblem | undefined {
if (depth >= 6 || !(error instanceof Error)) {
return undefined
}
if (error instanceof CodexCliInstallationError) {
return error.codexInstallation
}
if (error instanceof AggregateError) {
for (const inner of error.errors) {
const problem = codexInstallationProblemOf(inner, depth + 1)
if (problem) {
return problem
}
}
}
return codexInstallationProblemOf(error.cause, depth + 1)
}

Comment on lines +67 to +72
return {
command,
environment: structuredSessionCliEnvironment(
withCliRuntimeOnPath(command, { ...process.env, ...environment })
)
}

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.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🔎 Supported by static analysis

🏁 Script executed:

#!/bin/bash
# Check how the persistent child environment is built from launch.env
ast-grep outline src/main/codex --match 'buildCodexStructuredChildEnvironment' --view expanded
rg -nP -C8 'export function buildCodexStructuredChildEnvironment' src/main/codex
rg -nP -C4 'process\.env' src/main/codex/codex-structured-child-environment.ts
# Check whether any test asserts that a policy-excluded variable stays out of the child
rg -nP -C3 'nativeChatInheritShellEnvironment|shellEnvironmentPolicy' src/main/runtime/structured-agent-session-integration.test.ts | head -60

Repository: stablyai/orca

Length of output: 3565


🏁 Script executed:

set -e
printf '%s\n' '--- child environment ---'
nl -ba src/main/codex/codex-structured-child-environment.ts | sed -n '1,120p'
printf '%s\n' '--- resolver and launch consumer references ---'
rg -n -F --glob '*.ts' -- 'buildCodexStructuredChildEnvironment' src/main
rg -n -F --glob '*.ts' -- 'launch.env' src/main/codex src/main/runtime
printf '%s\n' '--- resolver ---'
nl -ba src/main/codex/codex-structured-launch-resolution.ts | sed -n '1,170p'
printf '%s\n' '--- policy test ---'
nl -ba src/main/runtime/structured-agent-session-integration.test.ts | sed -n '720,775p'

Repository: stablyai/orca

Length of output: 16676


🏁 Script executed:

set -e
printf '%s\n' '--- changed resolver diff ---'
git diff 820277c20778e45e3b314f128464686dea701377 4436b0a1a5a9e08fec3b8e60fc906aec30f77557 -- src/main/codex/codex-structured-launch-resolution.ts src/main/codex/codex-structured-child-environment.ts
printf '%s\n' '--- resolveEnvironment wiring ---'
rg -n -F --glob '*.ts' -- 'resolveEnvironment:' src/main/codex src/main/runtime
rg -n -F --glob '*.ts' -- 'nativeChatShellEnvironmentPolicy' src/main
printf '%s\n' '--- policy resolver definitions ---'
rg -n -P -C10 'function .*ShellEnvironment|resolveShellEnvironmentPolicy|inheritAll' src/main/runtime src/main/native-chat src/main | head -240

Repository: stablyai/orca

Length of output: 34757


Keep the persistent Codex environment policy-filtered.

resolveCodexStructuredInvocation adds process.env to the environment returned by resolveEnvironment. The launch resolver stores that object in launch.env, and buildCodexStructuredChildEnvironment copies launch.env into the persistent Codex child. This can pass process variables that nativeChatShellEnvironmentPolicy excludes.

Keep launch.env based on the policy-filtered environment. Add process.env only to the version-probe and maintenance environments that require it.

…nimum-version

# Conflicts:
#	src/renderer/src/components/native-chat/NativeChatStructuredSession.tsx
#	src/renderer/src/components/native-chat/use-native-chat-availability-notice.test.tsx
#	src/renderer/src/components/native-chat/use-native-chat-availability-notice.ts
@brennanb2025

Copy link
Copy Markdown
Contributor Author

CI status on a80b83a84fb (after merging main to resolve conflicts):

… a missing Codex

A too-old Codex now gets only the plain message ("Codex X is too old for
chats. Update to 0.136.0 or newer.") with no button and no job. The
existing rechecks (window focus, the <=30 s expiry of a saved result)
retry the refused chat once the user has updated Codex themselves.

A missing Codex keeps the Install Codex button: `npm install -g
@openai/codex` with the npm on the chat's PATH, as a host-run job with
its log, then a recheck and recovery. A configured Command that is
missing gets the message only, since a global npm install would not
land at that path.

Removed: the `codex update` command and its 0.126 floor, manual
instructions, npm layout and launcher identity detection, the action
descriptor (install|update) and its titles, the legacy capability, and
the SSH relay maintenance path (structured chat never runs over SSH or
WSL), so the relay preflight handler is back to main's.

@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


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 18ed304c-92be-42e1-b439-1380c26ebfcf
📥 Commits

Reviewing files that changed from the base of the PR and between 4436b0a and e4fcbf1.

⛔ Files ignored due to path filters (1)
  • src/shared/rpc-contract/rpc-params-catalog.generated.ts is excluded by !**/*.generated.*
📒 Files selected for processing (50)
  • src/main/cli/orca-cli-child-path.test.ts
  • src/main/cli/orca-cli-child-path.ts
  • src/main/preflight/codex-cli-installation.ts
  • src/main/preflight/codex-maintenance-command.test.ts
  • src/main/preflight/codex-maintenance-command.ts
  • src/main/preflight/codex-maintenance-configured-command.test.ts
  • src/main/preflight/codex-maintenance-environment.test.ts
  • src/main/preflight/codex-maintenance-host.test.ts
  • src/main/preflight/codex-maintenance-host.ts
  • src/main/preflight/codex-maintenance-runner.diagnostics.test.ts
  • src/main/preflight/codex-maintenance-runner.termination.test.ts
  • src/main/preflight/codex-maintenance-runner.test.ts
  • src/main/preflight/codex-maintenance-runner.ts
  • src/main/preflight/codex-workspace-relative-path.test.ts
  • src/main/runtime/rpc/preflight-codex-maintenance-permission.test.ts
  • src/renderer/src/components/NewWorkspaceComposerCard.codex-maintenance.test.tsx
  • src/renderer/src/components/native-chat/CodexMaintenanceLogDialog.tsx
  • src/renderer/src/components/native-chat/NativeChatNoticeRow.codex-maintenance.test.tsx
  • src/renderer/src/components/native-chat/NativeChatNoticeRow.tsx
  • src/renderer/src/components/native-chat/NativeChatStructuredSession.codex-recovery.test.tsx
  • src/renderer/src/components/native-chat/NativeChatStructuredSession.start-failure-notice.test.tsx
  • src/renderer/src/components/native-chat/NativeChatStructuredSession.tsx
  • src/renderer/src/components/native-chat/NativeChatStructuredSessionControls.tsx
  • src/renderer/src/components/native-chat/codex-maintenance-copy.ts
  • src/renderer/src/components/native-chat/codex-maintenance-failure-copy.test.tsx
  • src/renderer/src/components/native-chat/codex-maintenance-ui.test.tsx
  • src/renderer/src/components/native-chat/native-chat-composer-notice.ts
  • src/renderer/src/components/native-chat/native-chat-structured-session-notices.ts
  • src/renderer/src/components/native-chat/use-native-chat-availability-notice.test.tsx
  • src/renderer/src/components/native-chat/use-native-chat-availability-notice.ts
  • src/renderer/src/components/new-workspace/use-new-workspace-codex-maintenance.ts
  • src/renderer/src/components/settings/CodexMaintenanceRow.tsx
  • src/renderer/src/hooks/useCodexMaintenance.evidence.test.tsx
  • src/renderer/src/hooks/useCodexMaintenance.ts
  • src/renderer/src/i18n/locales/en.json
  • src/renderer/src/i18n/locales/es.json
  • src/renderer/src/i18n/locales/fr.json
  • src/renderer/src/i18n/locales/ja.json
  • src/renderer/src/i18n/locales/ko.json
  • src/renderer/src/i18n/locales/zh.json
  • src/renderer/src/lib/codex-maintenance-client.test.ts
  • src/renderer/src/lib/codex-maintenance-client.ts
  • src/renderer/src/lib/codex-maintenance-host-contact.test.ts
  • src/renderer/src/lib/codex-maintenance-host-contact.ts
  • src/renderer/src/lib/codex-maintenance-store.test.ts
  • src/renderer/src/lib/codex-maintenance-store.ts
  • src/renderer/src/web/preload-api/web-host-capability-api.ts
  • src/shared/codex-cli-maintenance.test.ts
  • src/shared/codex-cli-maintenance.ts
  • src/shared/protocol-version.ts
🚧 Files skipped from review as they are similar to previous changes (6)
  • src/renderer/src/i18n/locales/en.json
  • src/renderer/src/i18n/locales/ja.json
  • src/renderer/src/i18n/locales/zh.json
  • src/renderer/src/i18n/locales/fr.json
  • src/renderer/src/i18n/locales/es.json
  • src/renderer/src/i18n/locales/ko.json

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 4 remain after this review.

Comment on lines +42 to +48
return codexMaintenanceNotice
? { ...codexMaintenanceNotice, key: 'launch' }
: {
key: 'launch',
kind: 'error',
text: codexMaintenanceReason(facts)
}

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Keep a Retry action on the fallback Codex installation notice.

The fallback branch runs when codexMaintenanceNotice is null. It returns a notice with text only and no action. useNativeChatCodexMaintenance supplies a notice only in two cases: a current check reports missing/unsupported, or a current check reports ready. In every other state the user has no Retry control, and the chat stays failed:

  • The recheck reports unknown, for example when the updated build prints an unparseable version. Launch admission does not block an unknown version, so a Retry would succeed.
  • The status read fails, for example on host contact loss or when a configured Command cannot be resolved.
  • The evidence is legacy or has expired.

The auto-retry in useNativeChatCodexMaintenance fires only on ready. The test "does not automatically retry an unrelated start failure or an unknown check" confirms that an unknown check does not recover the chat. Add the existing Retry action to the fallback branch.

🐛 Proposed fix
--- "a/src/renderer/src/components/native-chat/native-chat-structured-session-notices.ts"
+++ "b/src/renderer/src/components/native-chat/native-chat-structured-session-notices.ts"
@@ -39,13 +39,17 @@
       version: installation.installedVersion,
       minimumVersion: installation.minimumVersion
     }
     return codexMaintenanceNotice
       ? { ...codexMaintenanceNotice, key: 'launch' }
       : {
           key: 'launch',
           kind: 'error',
-          text: codexMaintenanceReason(facts)
+          text: codexMaintenanceReason(facts),
+          action: {
+            label: translate('auto.components.native.chat.NativeChatLaunchRetry.retry', 'Retry'),
+            onClick: onRetry
+          }
         }
   }
   const message =
     lifecycle === 'failed'

If you apply this fix, update the assertion in codex-maintenance-failure-copy.test.tsx ("states a too-old Codex in the start-failure notice without a button"). That test expects no button on this fallback.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return codexMaintenanceNotice
? { ...codexMaintenanceNotice, key: 'launch' }
: {
key: 'launch',
kind: 'error',
text: codexMaintenanceReason(facts)
}
return codexMaintenanceNotice
? { ...codexMaintenanceNotice, key: 'launch' }
: {
key: 'launch',
kind: 'error',
text: codexMaintenanceReason(facts),
action: {
label: translate('auto.components.native.chat.NativeChatLaunchRetry.retry', 'Retry'),
onClick: onRetry
}
}

When Codex isn't installed, main already hides Codex from the New tab menu,
so the in-chat Install button was almost never reachable. Settings → Agents
already shows "Codex isn't installed." with Install Codex.

- Chats and the new-workspace composer now only state "Codex isn't
  installed." (no button, no install job from the chat).
- The Install action, its busy spinner and the host-busy subscription move
  into the Settings Codex row, the only place that starts the job.
- The store no longer re-checks every other workspace context when a job
  finishes. A refused chat recovers through the same re-check a too-old
  Codex uses (window focus, or the <=30 s expiry of a saved result).
- The chat recovery key no longer includes the install job id.
- Tests: Settings drives the install; a new test proves a chat refused for
  a missing Codex recovers through focus after a Settings install, not
  through the job; the expiry recovery test covers missing and too old.
…nimum-version

# Conflicts:
#	src/packages/process-host/src/process-tree-termination.test.ts
#	src/renderer/src/components/native-chat/NativeChatNoticeRow.test.tsx
#	src/renderer/src/components/native-chat/NativeChatNoticeRow.tsx
#	src/renderer/src/components/native-chat/NativeChatStructuredSession.tsx
#	src/renderer/src/components/native-chat/native-chat-structured-session-notices.ts
#	src/renderer/src/i18n/en-runtime-required.json
#	src/renderer/src/i18n/locales/en.json
#	src/shared/rpc-contract/rpc-params-catalog.generated.ts

@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


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: df05c2bd-e33a-46ef-b96e-9207ca61cc67
📥 Commits

Reviewing files that changed from the base of the PR and between e4fcbf1 and fe68bd3.

⛔ Files ignored due to path filters (1)
  • src/shared/rpc-contract/rpc-params-catalog.generated.ts is excluded by !**/*.generated.*
📒 Files selected for processing (62)
  • src/main/agent-cli-version-probe.ts
  • src/main/codex/codex-model-catalog-probe.test.ts
  • src/main/ipc/preflight.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-codex-version-recovery.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-failure-text.ts
  • src/main/preflight/codex-cli-installation.test.ts
  • src/main/preflight/codex-cli-installation.ts
  • src/main/preflight/codex-maintenance-command.ts
  • src/main/preflight/codex-maintenance-configured-command.test.ts
  • src/main/preflight/codex-maintenance-process.test.ts
  • src/main/preflight/codex-maintenance-process.ts
  • src/main/preflight/codex-maintenance-process.utf8.test.ts
  • src/main/preflight/codex-maintenance-runner.diagnostics.test.ts
  • src/main/preflight/codex-maintenance-runner.test.ts
  • src/main/preflight/codex-maintenance-runner.ts
  • src/main/preflight/codex-maintenance-windows-supervisor.test.ts
  • src/main/preflight/codex-maintenance-windows-supervisor.ts
  • src/main/preflight/codex-workspace-relative-path.test.ts
  • src/main/runtime/orca-runtime-get-worktree-ps.ts
  • src/main/runtime/rpc/methods/preflight.ts
  • src/main/runtime/structured-agent-launch-args-wiring.test.ts
  • src/main/runtime/structured-agent-runtime-registrations.ts
  • src/main/runtime/structured-agent-session-codex-interrupt-order.test.ts
  • src/main/runtime/structured-agent-session-codex-settlement-order.test.ts
  • src/main/runtime/structured-agent-session-codex-stopped-send-order.test.ts
  • src/main/runtime/structured-agent-session-codex-turn-end-settlement.test.ts
  • src/main/runtime/structured-agent-session-runtime-exit.test.ts
  • src/main/runtime/structured-agent-session-runtime.ts
  • src/main/runtime/structured-chat-coordinator-mail-rig.test-fixture.ts
  • src/main/runtime/structured-child-records-switch.test.ts
  • src/main/runtime/structured-codex-child-work-runtime.test.ts
  • src/main/runtime/structured-codex-session-rpc-test-harness.ts
  • src/main/runtime/structured-foreground-command-strip.test.ts
  • src/packages/process-host/package.json
  • src/packages/process-host/src/process-tree-termination.test.ts
  • src/packages/process-host/src/process-tree-termination.ts
  • src/renderer/src/components/NewWorkspaceComposerCard.codex-maintenance.test.tsx
  • src/renderer/src/components/native-chat/NativeChatNoticeRow.codex-maintenance.test.tsx
  • src/renderer/src/components/native-chat/NativeChatNoticeRow.test.tsx
  • src/renderer/src/components/native-chat/NativeChatNoticeRow.tsx
  • src/renderer/src/components/native-chat/NativeChatStructuredSession.codex-recovery.test.tsx
  • src/renderer/src/components/native-chat/NativeChatStructuredSession.tsx
  • src/renderer/src/components/native-chat/agent-session-availability-words-text.ts
  • src/renderer/src/components/native-chat/codex-maintenance-failure-copy.test.tsx
  • src/renderer/src/components/native-chat/codex-maintenance-ui.test.tsx
  • src/renderer/src/components/native-chat/native-chat-notice-row.test-fixture.tsx
  • src/renderer/src/components/native-chat/native-chat-structured-session-notices.ts
  • src/renderer/src/components/native-chat/use-native-chat-codex-maintenance.ts
  • src/renderer/src/components/new-workspace/NewWorkspaceComposerFooter.tsx
  • src/renderer/src/components/settings/CodexMaintenanceRow.tsx
  • src/renderer/src/hooks/useCodexMaintenance.ts
  • src/renderer/src/i18n/en-runtime-required.json
  • src/renderer/src/i18n/locales/en.json
  • src/renderer/src/i18n/locales/es.json
  • src/renderer/src/i18n/locales/fr.json
  • src/renderer/src/i18n/locales/ja.json
  • src/renderer/src/i18n/locales/ko.json
  • src/renderer/src/i18n/locales/zh.json
  • src/renderer/src/lib/codex-maintenance-store.ts
  • src/shared/agent-session-failure-copy.ts
  • src/shared/agent-session-refusal-details.ts
  • src/shared/protocol-version.ts
🚧 Files skipped from review as they are similar to previous changes (7)
  • src/renderer/src/i18n/en-runtime-required.json
  • src/renderer/src/i18n/locales/ko.json
  • src/renderer/src/i18n/locales/fr.json
  • src/renderer/src/i18n/locales/ja.json
  • src/renderer/src/i18n/locales/zh.json
  • src/renderer/src/i18n/locales/en.json
  • src/renderer/src/i18n/locales/es.json

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 6 remain after this review.

Comment on lines +107 to +111
// The supervisor uses exit 1 when it cannot prove its descendants exited.
if ((launch.supervised && exitCode === 1) || platform === 'win32') {
termination = 'unverifiable'
error ??= 'Codex maintenance process termination is unverifiable.'
}

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🔎 Supported by static analysis

🏁 Script executed:

#!/bin/bash
rg -nP -C6 'exit\(1\)|process\.exitCode\s*=\s*1|exitCode === 1' --type=ts src/main/provider-process
ast-grep outline src/main/provider-process --items all --match 'supervisedPosixLaunch'

Repository: stablyai/orca

Length of output: 4648


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- supervisor ---'
nl -ba src/main/provider-process/provider-process-supervisor.ts | sed -n '1,190p'
printf '%s\n' '--- maintenance process ---'
nl -ba src/main/preflight/codex-maintenance-process.ts | sed -n '1,240p'
printf '%s\n' '--- relevant references ---'
rg -n -F --glob '*.ts' -- 'finishWithProviderOutcome' src/main
rg -n -F --glob '*.ts' -- 'preserves an ambiguous supervisor failure as unverifiable' .
rg -n -F -- 'termination' src/main/preflight src/main/provider-process | head -120

Repository: stablyai/orca

Length of output: 21000


Distinguish provider exit code 1 from supervisor failure.

The POSIX supervisor calls process.exit(code ?? 1) after the provider exits, so a provider exit code of 1 reaches processExit unchanged. The supervisor also uses process.exit(1) for its own failure paths. executeCodexMaintenanceProcess therefore cannot distinguish an ordinary provider failure from unverifiable termination and reports the generic termination message instead of the provider failure.

Use an out-of-band supervisor outcome marker, or another value that the provider cannot produce, before mapping termination to unverifiable.

@brennanb2025 brennanb2025 changed the title feat(native-chat): require Codex 0.136.0 for chats, with Install/Update Codex feat(native-chat): require Codex 0.136.0 for chats Oct 12, 2026
@brennanb2025

Copy link
Copy Markdown
Contributor Author

Simplified and split (head aff57f9).

  • The PR is now only the Codex 0.136.0 minimum version: the check runs when a chat starts Codex on the machine that runs it, a too-old Codex is refused through the existing failure row, and the next Send checks again. Product code is +276 / -60 (it was about +2,700).
  • Removed: the client-side check cache, focus re-check, automatic retry, "Codex is updated" recovery, and the new-workspace block. Live QA showed the bugs were in that machinery.
  • Install Codex in Settings → Agents is split out and on hold.
  • Live QA used the real Codex: 0.159.0 for a working chat, and a real 0.135.0 for the refusal and recovery. Details and screenshots are in the description.

@brennanb2025
brennanb2025 merged commit c0e2b73 into main Oct 12, 2026
35 checks passed
OrcaWin added a commit that referenced this pull request Oct 12, 2026
…#28085)

#27946 and #26684 together put agent-session-failure-words.ts at 304 lines,
over max-lines, which fails lint and the pre-commit hook on every merge of
main. The refusal-code table is standalone with one reader, so it moves out.

Co-authored-by: Orca Worker <orca-worker@localhost>
brennanb2025 pushed a commit that referenced this pull request Oct 12, 2026
…#28085)

#27946 and #26684 together put agent-session-failure-words.ts at 304 lines,
over max-lines, which fails lint and the pre-commit hook on every merge of
main. The refusal-code table is standalone with one reader, so it moves out.

Co-authored-by: Orca Worker <orca-worker@localhost>
brennanb2025 added a commit that referenced this pull request Oct 12, 2026
…e extra wait cap

CI on the merge with main failed main's new codex-workspace-relative-path
test (#26684), which mocks the login-shell module with only
resolveLoginShellEnvironment: the wrapper called captureLoginShellEnvironment
and imported the spawn-timeout constant. The wrapper only needs the env, so
it reads through resolveLoginShellEnvironment again, as on main.

The miss wait no longer races its own 5 s timer: the shell run it waits for
is already killed at the spawn timeout, so the second cap was a guard over
the same bound. The constant goes back to private, as on main.
brennanb2025 added a commit that referenced this pull request Oct 12, 2026
…27875)

* fix(browser): annotation card and outline follow the selected element

The grab overlay keeps re-measuring the picked element after the click
(scroll in any box, resize, element size changes), and the isolated
viewport bridge reports that live box so the pending card follows it,
including page zoom. The card's side pick uses its measured height.

* fix(browser): bind annotation card to selected element

* fix(browser): keep document annotation card on selection

* fix(ci): point the main sync-spawn ratchet at the shared ratchet library (#28054)

#27756's script imported baseline helpers from check-focus-read-ratchet.mjs
after #27788 had moved them into ratchet-baseline.mjs, so it crashed on start
and failed every PR that merges main. Use the library's helpers, and record the
two daemon-process launches from #27769 that the broken check never saw.

Co-authored-by: Orca Worker <orca-worker@localhost>

* fix(browser): follow selected element outer-box size

* refactor(chat): give the start-refusal resumable table its own module (#28085)

#27946 and #26684 together put agent-session-failure-words.ts at 304 lines,
over max-lines, which fails lint and the pre-commit hook on every merge of
main. The refusal-code table is standalone with one reader, so it moves out.

Co-authored-by: Orca Worker <orca-worker@localhost>

---------

Co-authored-by: OrcaWin <alpha-eng@stably.ai>
Co-authored-by: Orca Worker <orca-worker@localhost>
@brennanb2025
brennanb2025 deleted the brennanb2025/codex-minimum-version branch October 12, 2026 23:44
brennanb2025 added a commit that referenced this pull request Oct 13, 2026
Main's #26684 runs Codex through a workspace-relative PATH entry (`bin`,
`node_modules/.bin`). The lookup searches such an entry against Orca's own
directory and returns the bare name; the spawn then finds the program in the
chat's directory. Counting that bare name as missing made every such launch
wait for a login-shell reread.

The retry now fires only when the lookup truly found nothing: a bare name back
from a PATH whose entries are all absolute. Each agent's one lookup tells it
which PATH it searched.
brennanb2025 added a commit that referenced this pull request Oct 14, 2026
…#26464)

* fix: refresh host environments before structured agent command resolution

* fix: ship the owning server CLI for managed remote agents

* test: include the shipped CLI in remote install fixtures

* Bind packaged agent CLI calls to their execution host

* Keep owning-server CLI binding scoped to managed agents

* Serve the last shell environment to chat starts and refresh it in the background

Only the first chat start waits for the login shell; later starts get the last
snapshot and refresh it in the background once it is 10 s old. On Windows hosts
without the registry addon (managed server slots), the saved PATH is reread
with reg.exe. The Windows server CLI launcher stager now checks the target
architecture, and the CLI help says ambient selectors are ignored inside a
managed server.

* Keep the last good shell environment when a refresh fails, and load the Windows profile once

A login-shell capture now says whether the shell produced the env or Orca fell back
to its own, and only a real capture replaces the snapshot. Windows loads the
PowerShell profile once per process and refreshes only the saved PATH. The reg.exe
fallback queries the whole key so a missing user Path no longer drops the saved PATH.
The first capture starts when the resolvers are created.

* Keep the last good login-shell env for other readers while a forced refresh runs

* Mark the Claude launch resolver as a reviewed router-aware module

It only types the chat command resolver it injects; main's launch-routing guard (#26801) matched the name.

* Keep a settled login-shell env for readers during a refresh and share the first run

- Any settled cached entry, a fallback included, now serves other readers while a forced capture
  runs; only a real capture replaces it.
- Native chat's first capture shares a run a startup reader already began, so the login shell
  runs once per process at startup on macOS/Linux.
- Type the injected Claude resolver without naming resolveClaudeCommand.
- Cover the runtime's Claude command options, the owning-host --host check, and the PTY flag drop.

* Drop an inherited owning-host flag from daemon terminal panes

The persistent terminal daemon merges its own environment into every pane, so an inherited
ORCA_CLI_OWNING_HOST reached desktop panes even though main strips it from the spawn env.
Drop it with the other per-launch CLI variables.

* Route agents to their own server through ordinary launch defaults; start the first chat after an install

The native-chat agent environment now sets the owning server's ORCA_USER_DATA_PATH and
empty ORCA_ENVIRONMENT / ORCA_PAIRING_CODE / ORCA_REMOTE_PAIRING, which the CLI already
reads as unset; empty rather than deleted, because the spawn merges the launch overlay
over the server's own env. The ORCA_CLI_OWNING_HOST flag, the CLI's skip of ambient
selectors, the launchers' export of it, the terminal clean-up, the help-text exception
and the WSL launcher guard are gone, so a person's terminal follows their own settings
as on main.

A launch that finds no program in the shell snapshot waits for one shared refresh (at
most one shell timeout) and resolves again; create support rereads the shell once
before refusing. On Windows a failed PowerShell profile load is retried on the next
refresh instead of being kept until restart.

* One shared shell reread when an agent's program is missing

The pre-create check for OpenCode, OMP and Pi forced its own login-shell
capture on every refusal: not shared with launches, one per concurrent
check, triggered by an installed-but-too-old version too, and an older
capture finishing last could overwrite a newer cached environment. On
Windows, every launch miss also reran a failed PowerShell profile load,
bypassing the 10-second limit.

- One saved shell environment per host: chat launches, their misses, the
  pre-create check and AI commit messages read it and share one refresh.
- The pre-create check resolves the agent's program the way a launch does,
  so only a missing program waits for the refresh; registrations declare
  how to resolve their launch and check its version.
- A forced login-shell capture joins one already running for the same
  shell, so captures cannot land out of order.
- On Windows, a miss within 10 s of a failed PowerShell load rereads only
  the saved PATH.

* One owner for the cached shell environment

Review found two more races in the reread-on-miss machinery, both from the
host wrapper keeping its own snapshot beside the login-shell cache:
- A launch that found no program could join a reread that started before the
  agent was installed, and spend its one retry on the old PATH.
- On Windows, saved-PATH rereads renewed the snapshot's age, so a failed
  PowerShell profile was never retried while launches kept missing.

The login-shell cache is now the only owner of the captured environment, the
run in progress and which result wins (the newest run started; a fallback
never replaces a captured env). It takes three options instead of `force`:
- startedAfter: a lookup that found nothing waits for a run that started no
  earlier than the lookup did, joining one if it has, else starting one.
- refreshAfterMs: serve the last result and rerun in the background once the
  last attempt is older.
- keepCaptured: a captured env is kept for good; only a fallback is rerun
  (Windows' PowerShell profile).

The host wrapper keeps only policy: the 10 s interval, on Windows the saved
PATH laid over the profile env on every read (a miss forces a fresh registry
read), and the settings overlays. Its snapshot, pending promise, staleness and
Windows "loaded" bookkeeping are gone. A lookup's start time travels with the
miss (resolveAgainAfterRefreshOnMissingProgram passes it).

* Read an injected shell environment once per runtime, as main does

The previous commit read an injected environment on every acquisition, which
broke main's 'caches shell exports but re-reads configured overrides for a
resume' contract. It is read once when the resolvers are made again.

* Model lists reread the environment on a missing program, as launches do

Live QA: the first new chat after installing Claude showed "Claude wasn't
found on the computer running this chat". The chat launch itself reread the
login shell and started the new binary, but Claude's model-list check ran
first, with the environment read before the install, and never retried:
catalog probes were deliberately built without the miss refresh.

The retry now lives in each agent's one shared lookup of its binary and
environment, which a launch and a model listing both call:
resolveCodexStructuredInvocation, resolveAcpLaunchInvocation, a new shared
resolvePiRpcInvocation, and resolveClaudeChildEnvSources (which already had
it). Each catalog probe is given the runtime's refreshAfterMissingProgram,
and the catalog context no longer strips it, so a listing and a launch
reread the same single-owner environment the same way.

* Pass optional launch lookups through directly instead of conditional spreads

* Read the host shell env through resolveLoginShellEnvironment; drop the extra wait cap

CI on the merge with main failed main's new codex-workspace-relative-path
test (#26684), which mocks the login-shell module with only
resolveLoginShellEnvironment: the wrapper called captureLoginShellEnvironment
and imported the spawn-timeout constant. The wrapper only needs the env, so
it reads through resolveLoginShellEnvironment again, as on main.

The miss wait no longer races its own 5 s timer: the shell run it waits for
is already killed at the spawn timeout, so the second cap was a guard over
the same bound. The constant goes back to private, as on main.

* Test that a hung login shell holds a launch miss for at most one shell timeout

The bound lives in the one owner: the shell run is killed at the spawn
timeout (5 s) and settles to a fallback, which never replaces a captured
snapshot. A mutation raising that timeout fails this test.

* A program found through a relative PATH entry is not missing

Main's #26684 runs Codex through a workspace-relative PATH entry (`bin`,
`node_modules/.bin`). The lookup searches such an entry against Orca's own
directory and returns the bare name; the spawn then finds the program in the
chat's directory. Counting that bare name as missing made every such launch
wait for a login-shell reread.

The retry now fires only when the lookup truly found nothing: a bare name back
from a PATH whose entries are all absolute. Each agent's one lookup tells it
which PATH it searched.

* Count a relative PATH entry as found only when it holds the program; Windows miss waits for a saved PATH read started after it looked

A bare name with a relative PATH entry is checked from the launch's working
directory, so an agent in neither entry still gets its one reread. On Windows the
miss no longer joins a registry read that began before the lookup.
registered2nd pushed a commit to registered2nd/orca that referenced this pull request Oct 14, 2026
* Require Codex 0.136.0 for native chats

* Add host-owned Codex install and update actions

* Bind Codex checks and maintenance to the selected installation

* Resolve Windows updater cleanup through system helpers

* Use one child environment for Codex checks and launch

* Expire Codex readiness and reconcile current host jobs

* Resolve Codex checks against the child command search path

* Restrict global npm repair to the selected Codex install layout

* Pin the host updater directory through Windows supervision

* Synchronize Codex maintenance fixtures on readiness

* Unify Codex notices and recover version-refused chats

* Route Codex recovery to the operation that remains

* Preserve Codex setup execution errors in the job log

* Preserve UTF-8 in Codex setup logs

* Remove unused Codex host installation detector

* Require host administration for Codex maintenance

* Show a missing Codex explanation once

* test(native-chat): give scripted Codex runtimes their installation fact; keep the registry out of the relay

Runtime tests that drive a scripted Codex app-server still ran the new
version check against whatever codex was on the machine's PATH: refused
on CI (no codex), and on a dev machine it ran the real codex --version.
A scripted transport now must state the Codex it stands for
(readCodexInstallation), asserted at install, and the tests get it from
one scriptedCodexTransport fixture.

The relay's Codex maintenance path reached @orca/windows-registry through
resolvePathEnvKey's re-export in windows-environment-path; import it from
its registry-free module instead.

Also update the catalog-probe test for the shared child environment.

* refactor(native-chat): drop the Update Codex action; keep Install for a missing Codex

A too-old Codex now gets only the plain message ("Codex X is too old for
chats. Update to 0.136.0 or newer.") with no button and no job. The
existing rechecks (window focus, the <=30 s expiry of a saved result)
retry the refused chat once the user has updated Codex themselves.

A missing Codex keeps the Install Codex button: `npm install -g
@openai/codex` with the npm on the chat's PATH, as a host-run job with
its log, then a recheck and recovery. A configured Command that is
missing gets the message only, since a global npm install would not
land at that path.

Removed: the `codex update` command and its 0.126 floor, manual
instructions, npm layout and launcher identity detection, the action
descriptor (install|update) and its titles, the legacy capability, and
the SSH relay maintenance path (structured chat never runs over SSH or
WSL), so the relay preflight handler is back to main's.

* refactor(native-chat): keep Install Codex in Settings only

When Codex isn't installed, main already hides Codex from the New tab menu,
so the in-chat Install button was almost never reachable. Settings → Agents
already shows "Codex isn't installed." with Install Codex.

- Chats and the new-workspace composer now only state "Codex isn't
  installed." (no button, no install job from the chat).
- The Install action, its busy spinner and the host-busy subscription move
  into the Settings Codex row, the only place that starts the job.
- The store no longer re-checks every other workspace context when a job
  finishes. A refused chat recovers through the same re-check a too-old
  Codex uses (window focus, or the <=30 s expiry of a saved result).
- The chat recovery key no longer includes the install job id.
- Tests: Settings drives the install; a new test proves a chat refused for
  a missing Codex recovers through focus after a Settings install, not
  through the job; the expiry recovery test covers missing and too old.

* refactor(codex): check chat compatibility when acquiring the child

* Restore workspace submit guard and simplify Codex maintenance

* Keep only the Codex chat minimum version

(cherry picked from commit c0e2b73)
brennanb2025 added a commit that referenced this pull request Oct 15, 2026
* Require Codex 0.136.0 for native chats

* Add host-owned Codex install and update actions

* Bind Codex checks and maintenance to the selected installation

* Resolve Windows updater cleanup through system helpers

* Use one child environment for Codex checks and launch

* Expire Codex readiness and reconcile current host jobs

* Resolve Codex checks against the child command search path

* Restrict global npm repair to the selected Codex install layout

* Pin the host updater directory through Windows supervision

* Synchronize Codex maintenance fixtures on readiness

* Unify Codex notices and recover version-refused chats

* Route Codex recovery to the operation that remains

* Preserve Codex setup execution errors in the job log

* Preserve UTF-8 in Codex setup logs

* Remove unused Codex host installation detector

* Require host administration for Codex maintenance

* Show a missing Codex explanation once

* test(native-chat): give scripted Codex runtimes their installation fact; keep the registry out of the relay

Runtime tests that drive a scripted Codex app-server still ran the new
version check against whatever codex was on the machine's PATH: refused
on CI (no codex), and on a dev machine it ran the real codex --version.
A scripted transport now must state the Codex it stands for
(readCodexInstallation), asserted at install, and the tests get it from
one scriptedCodexTransport fixture.

The relay's Codex maintenance path reached @orca/windows-registry through
resolvePathEnvKey's re-export in windows-environment-path; import it from
its registry-free module instead.

Also update the catalog-probe test for the shared child environment.

* refactor(native-chat): drop the Update Codex action; keep Install for a missing Codex

A too-old Codex now gets only the plain message ("Codex X is too old for
chats. Update to 0.136.0 or newer.") with no button and no job. The
existing rechecks (window focus, the <=30 s expiry of a saved result)
retry the refused chat once the user has updated Codex themselves.

A missing Codex keeps the Install Codex button: `npm install -g
@openai/codex` with the npm on the chat's PATH, as a host-run job with
its log, then a recheck and recovery. A configured Command that is
missing gets the message only, since a global npm install would not
land at that path.

Removed: the `codex update` command and its 0.126 floor, manual
instructions, npm layout and launcher identity detection, the action
descriptor (install|update) and its titles, the legacy capability, and
the SSH relay maintenance path (structured chat never runs over SSH or
WSL), so the relay preflight handler is back to main's.

* refactor(native-chat): keep Install Codex in Settings only

When Codex isn't installed, main already hides Codex from the New tab menu,
so the in-chat Install button was almost never reachable. Settings → Agents
already shows "Codex isn't installed." with Install Codex.

- Chats and the new-workspace composer now only state "Codex isn't
  installed." (no button, no install job from the chat).
- The Install action, its busy spinner and the host-busy subscription move
  into the Settings Codex row, the only place that starts the job.
- The store no longer re-checks every other workspace context when a job
  finishes. A refused chat recovers through the same re-check a too-old
  Codex uses (window focus, or the <=30 s expiry of a saved result).
- The chat recovery key no longer includes the install job id.
- Tests: Settings drives the install; a new test proves a chat refused for
  a missing Codex recovers through focus after a Settings install, not
  through the job; the expiry recovery test covers missing and too old.

* refactor(codex): check chat compatibility when acquiring the child

* Restore workspace submit guard and simplify Codex maintenance

* Keep only the Codex chat minimum version

(cherry picked from commit c0e2b73)

Backport to 1.4.224: process-host imports point at src/shared/child-process; codex-minimum-version.test builds its fake piped child inline (the shared fake-spawned-child fixture came with @orca/process-host); dropped the NativeChatStructuredSession.approval-and-start-failure test edit (file absent on 1.4.224; the Codex wording is still covered by NativeChatNoticeRow.test).
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.

1 participant