Repository navigation
fix(codex): write Orca's hook into ~/.codex only when something changed - #25743
Conversation
There was a problem hiding this comment.
Important
One correctness finding in the pending-Codex stopgap path that can defeat the purpose of this stack — inline comment below.
Reviewed changes — first pass over the 8 commits from 256e90a to 532078b.
- New central reconcile (
codex-hook-reconcile.ts): the single writer of Orca's~/.codexentry, with a coalescing runner, an off-spawn schedule for every native pane, and a bounded wait for Codex launches/resumes. When Codex has not answered within 500ms it writes a stopgap approval from Orca's own hash and re-runs once Codex answers. - Install rewrite (
codex-real-home-hook-install.ts):ensureRealHomeCodexHookStatebecomesreconcileRealHomeCodexHookEntrieswithunchanged/written/unavailable/disabledoutcomes, a prune-then-write loop (MAX_PASSES), and a one-time retry onHooksJsonChangedError. - Entry plan rewrite (
codex-real-home-hook-entry-plan.ts): Orca's entry must be alone in a matcher-less group; duplicate/direct copies are pruned and user-hook positions are preserved viamutateRealHomeHooksPreservingUserTrust. - Removals:
codex-real-home-background-grant.ts,codex-real-home-entry-trust.ts,codex-real-home-hook-withdrawal.ts,runOutsideCodexTrustConfigLanes, and their tests — no dangling references remain at HEAD;tc:nodeandtc:clipass. - Status/routing wiring: no-arg
getStatus()now resolves the home the next pane uses; the real-home lane gate is now!hooksEnabled || readRealHomeHooksFileShapeProblem() === null.
ℹ️ The PR description no longer matches the change
The body describes removing background-approval options and says "Nothing a user sees changes", but the diff adds a new reconcile that writes Orca's entry into ~/.codex on every launch/resume and a status path that now reports the real home. That is precisely the user-visible behavior this PR governs, so the description under-sells (and misdirects reviewers away from) the actual surface. Worth rewriting before merge.
deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏
256e90a to
9d5efd6
Compare
532078b to
b4a574a
Compare
9d5efd6 to
668ae79
Compare
5da068f to
ff3652c
Compare
9a95263 to
4c50d0e
Compare
ed88c6d to
26945c1
Compare
|
Important Review skippedReview was skipped as selected files did not have any reviewable changes. ⚙️ Run configuration
📥 CommitsReviewing files that changed from the base of the PR and between 5eeb083f31c416d77a0b0d291a66d0e04bbfa11d and c0266f3. You can disable this status message by setting the Use the checkbox below for a quick retry:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📥 CommitsReviewing files that changed from the base of the PR and between 26945c19273e9fbfc30f3efe17d7733a879812c1 and 5eeb083f31c416d77a0b0d291a66d0e04bbfa11d. 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 7 remain after this review. 📝 WalkthroughWalkthroughThe PR replaces the real-home Codex hook grant flow with hash-based hook reconciliation. Reconciliation runs at startup and native pane spawns, and selected real-home launches and resumes can await it. Hook status now supports real and managed homes and reports file and inline-approval conditions. The PR updates opt-out trust cleanup, hook planning, and rollback checks. It also adds reconciliation and status tests, removes tests for the earlier grant flow, and updates startup and project configuration. Priority: ➖ Normal Severity of issue fixed: Medium Merge Risk: ⚪ Minimal · up to No confirmed issue in the selected changes currently prevents merging after normal checks. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 2📝 Generate docstrings 💡
🛠️ Fix failing CI checks 💡
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Repository UI
- Review profile: CHILL
- Plan: Advanced
- Run ID:
e4414838-ff4b-4b34-a2f1-74db9f58b0a2
📥 Commits
Reviewing files that changed from the base of the PR and between 8d049b5 and 26945c19273e9fbfc30f3efe17d7733a879812c1.
📒 Files selected for processing (68)
config/scripts/ci-shard-timings.jsonconfig/scripts/pr-code-change-scope.mjsconfig/scripts/pr-code-change-scope.test.mjsconfig/tsconfig.cli.jsonsrc/main/agent-hooks/managed-agent-hook-registry.tssrc/main/codex-accounts/runtime-home-real-home-lane-routing.test.tssrc/main/codex-accounts/runtime-home-retained-auth-provenance.test.tssrc/main/codex-accounts/runtime-home-service-home-routing.tssrc/main/codex-accounts/runtime-home-service-per-account-migration.test.tssrc/main/codex-accounts/runtime-home-session-migration-pass.test.tssrc/main/codex-accounts/runtime-home-status-hook-independence.test.tssrc/main/codex/codex-hook-approval-first-write.test.tssrc/main/codex/codex-hook-approval-first-write.tssrc/main/codex/codex-hook-command-form.test.tssrc/main/codex/codex-hook-file-entry-binary-contract.test.tssrc/main/codex/codex-hook-hash-lookup.test.tssrc/main/codex/codex-hook-hash-lookup.tssrc/main/codex/codex-hook-legacy-cleanup.tssrc/main/codex/codex-hook-local-install.tssrc/main/codex/codex-hook-local-maintenance.tssrc/main/codex/codex-hook-orca-approvals.tssrc/main/codex/codex-hook-real-home-status.test.tssrc/main/codex/codex-hook-reconcile.test.tssrc/main/codex/codex-hook-reconcile.tssrc/main/codex/codex-hook-service-implementation.tssrc/main/codex/codex-hook-status.tssrc/main/codex/codex-hook-trust-cleanup.tssrc/main/codex/codex-hook-trust-derivation.tssrc/main/codex/codex-hook-trust-failure-memo.test.tssrc/main/codex/codex-real-home-background-grant.tssrc/main/codex/codex-real-home-entry-trust.test.tssrc/main/codex/codex-real-home-entry-trust.tssrc/main/codex/codex-real-home-failed-grant-concurrent-edit.test.tssrc/main/codex/codex-real-home-frozen-entry.test.tssrc/main/codex/codex-real-home-hook-entries.test.tssrc/main/codex/codex-real-home-hook-entry-plan.tssrc/main/codex/codex-real-home-hook-install.test.tssrc/main/codex/codex-real-home-hook-install.tssrc/main/codex/codex-real-home-hook-key-spellings.test.tssrc/main/codex/codex-real-home-hook-removal.test.tssrc/main/codex/codex-real-home-hook-sweep.tssrc/main/codex/codex-real-home-hook-withdrawal.tssrc/main/codex/codex-real-home-hooks-json.tssrc/main/codex/codex-real-home-shared-entry.test.tssrc/main/codex/codex-real-home-slow-app-server.test.tssrc/main/codex/codex-real-home-trust-withdrawal.test.tssrc/main/codex/codex-real-home-user-hook-positions.test.tssrc/main/codex/codex-real-home-windows-key-spellings.test.tssrc/main/codex/codex-trust-config-mutation-queue.tssrc/main/codex/codex-trust-grant-ledger.test.tssrc/main/codex/codex-trust-grant-ledger.tssrc/main/codex/hook-service-legacy-cleanup.test.tssrc/main/codex/hook-service-managed-codex-hashes.test.tssrc/main/codex/hook-service-runtime-trust-repair.test.tssrc/main/codex/hook-service-windows-key-spellings.test.tssrc/main/codex/windows-hook-upgrade.test.tssrc/main/ipc/pty/host-env/assembly.tssrc/main/ipc/pty/host-env/codex-hook-reconcile-spawn.test.tssrc/main/startup/codex-account-restart-resume.test.tssrc/main/startup/codex-hook-hash-warmup-wiring.test.tssrc/main/startup/codex-hook-startup-wiring.test.tssrc/main/startup/codex-launch-during-real-home-grant.test.tssrc/main/startup/codex-launch-per-agent-hook-opt-out.test.tssrc/main/startup/codex-launch-preparation.tssrc/main/startup/codex-session-resume-daemon-guard.test.tssrc/main/startup/codex-session-resume-launch.tssrc/main/startup/main-process-account-services.tssrc/main/startup/main-process-ready-runtime.ts
💤 Files with no reviewable changes (18)
- src/main/codex/codex-real-home-hook-install.test.ts
- src/main/startup/codex-hook-hash-warmup-wiring.test.ts
- src/main/codex/codex-real-home-failed-grant-concurrent-edit.test.ts
- src/main/codex/codex-real-home-trust-withdrawal.test.ts
- src/main/startup/codex-launch-during-real-home-grant.test.ts
- src/main/codex/codex-real-home-user-hook-positions.test.ts
- src/main/codex-accounts/runtime-home-service-home-routing.ts
- src/main/codex/codex-real-home-entry-trust.ts
- src/main/codex/codex-real-home-entry-trust.test.ts
- src/main/codex/codex-real-home-frozen-entry.test.ts
- src/main/codex/codex-real-home-slow-app-server.test.ts
- config/scripts/ci-shard-timings.json
- src/main/codex-accounts/runtime-home-retained-auth-provenance.test.ts
- src/main/startup/main-process-account-services.ts
- src/main/codex/codex-trust-config-mutation-queue.ts
- src/main/codex/codex-real-home-hook-withdrawal.ts
- src/main/codex/codex-real-home-background-grant.ts
- src/main/codex-accounts/runtime-home-real-home-lane-routing.test.ts
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 7 remain after this review.
One reconcile replaces the per-launch writer and its background approval session. It runs at app start after PATH hydration, when the setting turns on, once per native pane spawn, and (with a bounded 3 s wait) on Codex launches and resumes. Orca's entry lives alone in a matcherless group, appended last unless already in place; other copies are removed and the shifted user approvals move verbatim under both key spellings. The approval, with Codex's own hash, goes in first. The routing gate closes only for a hooks.json with a bad shape.
Status reads ~/.codex (both key spellings) when launches use it, or the CLI has no selection, and the selected managed home otherwise. It explains: update Codex, Codex not found, not asked yet, approved by Orca but not yet confirmed by Codex, a hooks.json shape that moves panes to Orca's own home, and inline config.toml approvals Orca cannot add to.
…it on those files The contract now also writes Orca's entry into a throwaway ~/.codex and checks that Codex lists it trusted and enabled, turns it back on over a /hooks switch-off, lists it for review after a user inserts a hook ahead until the next check, keeps an inline config.toml loadable, and shows no review in a real TUI start. The real-binary CI job now runs when the ~/.codex writer changes.
… paths beside the contract job
…spawn trigger Adds tests that failed against mutants which survived the first pass: an entry alone in a matcher group, a current copy's approval in an event left to an older build, one run per spawn, a spawn riding a running reconcile, and the native-only spawn trigger. The opt-out's Codex-hash cleanup now runs once, after the sweep, instead of twice.
…r is pending The reconcile waits at most 0.5 s for Codex's hash. If the lookup is still running, an entry already in place keeps its approval and nothing is written; a missing entry or approval gets Orca's computed hash, approval first, inside a launch's 3 s wait, as main's did. When the lookup lands, the reconcile runs again and Codex's hash replaces it.
…cile startCodexHooks replaces the two start functions and takes the PATH wait that the reconcile request's after option carried. A spawn reconciles unless one is running, without a scheduled flag, launches call one reconcileCodexHooksForLaunch on the shared withTimeout, and the reconcile alone reads the hooks setting. The startup test now runs the ready phase instead of matching its source text.
…pproval reader The planner prunes with removeManagedCommands, as the opt-out does (so a hook that runs Orca's script through its args goes too), and returns a prune or settle union. While Codex has not answered, the kept approval comes from the shared per-event reader. The reconcile result is its outcome alone, a concurrent save spends a pass of the one bound, the opt-out removes Orca's approvals once, the approval-first writer takes the hooks path, and getRealHomeConfigTomlPath gives way to getSystemCodexConfigTomlPath.
… the app's lookup does
…its own home, hash and user data Also passes every approval to the approval-first writer, which already skips the ones in place.
…swer flag The lookup start only records the hydrated PATH; one catch, one request type, and the app config is kept as given.
Also makes the ~/.codex opt-out take Codex's hashes, as every production caller passes them.
…nswer uses the saved one, a conversion waits for a run that writes, and status and the reconcile read one home and one Orca-hash rule
…~/.codex rewrites the backslash key Codex on Windows reads
…h, and its userData exists
5eeb083 to
c0266f3
Compare
…de-probes codex-hook-trust-grant.ts takes main's side: #25743/#25744 removed the background trust-grant timeout whose comment PR 2 had updated, so that comment change is dropped. tsconfig.cli.json keeps main's edits plus PR 2's teardown-chain entries, without the two real-home grant files main deleted.

ELI5
Codex asks you to review any hook in
~/.codex/hooks.jsonthat it has no approval for. Today Orca rewrites its status hook there on every Codex launch and resume, then approves it by running a background Codex session. When many agents launch at once, those writes race, and a launch can reach Codex before the approval does. After this change, Orca checks its hook against what it would write, and touches~/.codexonly when something actually changed.What Changed
~/.codexre-added Orca's hook entry, then startedcodex app-serverin the background, for up to 30 s, to approve it.hooks.jsonandconfig.toml.codex --versionat app start), it uses the answer Codex gave last time for the same binary, so a restart writes nothing.~/.codex; status says Codex was not found./hooksswitch-off of Orca's hook is turned back on, because Orca's setting is its off switch.~/.codex. An Orca entry you edited is rewritten in place and re-approved.~/.codex. When~/.codex/hooks.jsonhas a shape Orca can't add to (it doesn't parse, has top-level keys other thanhooksanddescription, or an event that isn't a list), Orca leaves it untouched and status says why.hooks.jsonproblem, or hook approvals kept inline inconfig.toml.~/.codex, its withdrawal of unapproved entries, and the per-launch writer. WSL keeps its approval session.Why
Linked Issue
Fixes #13746
Visual Proof
N/A: no UI change. Only the hook status detail text differs.
Testing
/hooksswitch-off, Orca inside a matcher group, an edited entry;~/.codex(so not lost while hooks are off or a managed account is selected);~/.codexwrites while Codex is missing, and none on a restart with a slow version check;hooks.json, an unknown Codex, a too-old Codex, or inline approvals keep the system default on~/.codex, andhooks.jsonis left untouched;descriptionkey inhooks.jsonsurvives Orca's write;hooks.jsonsave is retried;CODEX_HOMEleave~/.codexalone;/hooksswitch-off is undone;config.tomlstays loadable;Notes
config.toml(status explains why);hooks/list(status says to update);