Skip to content

fix(codex): Orca's Codex hook stays on, is recognised, and trust reaches every home (2/2) - #23931

Closed
brennanb2025 wants to merge 11 commits into
brennanb2025/codex-config-checked-writerfrom
brennanb2025/codex-hooks-trust-ownership
Closed

brennanb2025 wants to merge 11 commits into
brennanb2025/codex-config-checked-writerfrom
brennanb2025/codex-hooks-trust-ownership

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 10 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​539 $\color{#cf222e}{\Huge{\mathbf{−}}}$​9 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​530
Prod 16 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​289 $\color{#cf222e}{\Huge{\mathbf{−}}}$​53 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​236

ELI5

Orca installs a small status hook into Codex so it can show what Codex is doing. Three things went wrong around it:

  • Orca approved its hook but never switched it on.
  • Codex's "import from Claude Code" copied Orca's Claude hook into Codex, and Orca didn't recognise it as its own.
  • Orca trusted a worker's folder in the wrong Codex home for per-account launches, leaving the worker stuck behind Codex's trust prompt.

This PR fixes the first, fixes the second in the Codex homes Orca owns, and makes trust reach the Codex home a launch actually reads. It respects Orca's own per-agent switch for turning the Codex integration off, and moving hooks around never costs you an approval you already gave.

What Changed

This PR is step 2 of 2, stacked on #23930. The plan fixes how Orca edits Codex's config, trust and hooks:

1. Orca's hook stays off (#23289). Codex keeps an on/off switch for each hook. Orca approved its own status hook but never switched it on, and nothing re-checked it. For some users it stayed off, so Orca couldn't see Codex's status, and orchestration workers on remote hosts stalled at readiness.

  • After: every time Orca prepares a Codex launch, it switches its own hook entries on along with their trust hash. That covers the app-server grant, the ledger shortcut, and the local and WSL writers. On SSH hosts it happens each time Orca connects to the host, not on every launch. Your other hooks are never touched.
  • Orca's own switch is the off switch. If you turn Orca's hook off inside Codex's /hooks screen, the next Orca launch turns it back on. To turn it off, use Orca's per-agent Codex setting (fix(codex): turning Codex off per agent keeps its hook entry off #23667) or the global status-hooks setting.
  • When you turn Codex off per agent in Orca (fix(codex): turning Codex off per agent keeps its hook entry off #23667), the hook stays off, because every one of those paths only runs while hooks are enabled for Codex. A test runs launch prep with Codex hooks on and then off, starting from a disabled Orca entry each time.
  • This supersedes Provision managed Codex accounts with enabled Orca hooks #23292, which switched the hook on once, at account creation, with nothing re-checking it later.

2. A copied Claude hook runs in Codex (#22434). Codex's "import from Claude Code" copied Orca's Claude hook into Codex's hook file. Orca only recognised its Codex hook script there, so the copy stayed, and Codex warned at startup about cutting its 10-second timeout to 3 seconds.

  • After: any command running a script from Orca's .orca/agent-hooks/ folder counts as Orca's. In Orca-owned Codex homes, a copied Claude entry isn't mirrored in, its trust isn't carried over, and stale copies are removed.
  • Not changed yet: the copy in your own ~/.codex/hooks.json. On macOS and Linux, Codex launched from Orca reads your real ~/.codex by default (no managed account and no custom CODEX_HOME), so on that default setup the startup warning continues until that pending decision is made. This PR therefore only refers to Codex warns about a 10s SessionEnd entry calling Orca’s Claude hook #22434 instead of closing it. It is fixed where Codex runs on an Orca-owned home: Windows, managed accounts, and the fallback home.

3. Worker trust misses the account's own Codex home (#23847, partly). worker-start --agent codex could stall at Codex's "trust this folder?" screen. Main (with #23930) now writes trust once per launch on the host that runs the agent, but locally it wrote only ~/.codex and Orca's shared Codex home, never the per-account home a launch actually reads.

  • After: local trust also reaches the Codex home the launch's own CODEX_HOME names, as the SSH relay already does. If a write fails at the OS level, the log names that config.toml instead of a temporary file.
  • Moved to a follow-up: making worker-start say why a worker stopped at the trust screen. That needs main's new trust writer to return its outcome (including an answer from the SSH relay), so it gets its own PR. Until then a stalled worker still reports Agent startup blocked: agent-trust-workspace.

4. Moving hooks never costs you an approval. When Orca's install in a WSL-managed Codex home removes a copied Claude hook, or puts its own entry first, your later hooks move to new positions, and Codex keys approvals by position. Orca now carries each moved hook's approval (trusted_hash and on/off) to its new position when the hook is unchanged, so Codex doesn't ask you to review hooks you already trusted. If it can't prove that, it leaves the approval alone and logs once.

Why

  • Switching the hook on at every launch is a re-derivation, not a one-time step. A stuck enabled = false can't outlive the next launch. Orca's per-agent setting remains the real off switch.
  • One Orca identity (the hooks folder) instead of a list of script names, so the next hook Orca adds is recognised without another list edit.
  • Trust stays a file write, so it works however Codex is launched. This PR makes it reach every home and makes failure visible, rather than moving it to a per-launch option.
  • Trust re-homed onto main's single trust writer. Main now writes trust in one place per launch, so this PR adds only the missing per-account home instead of keeping its own parallel writes.

Linked Issue

Fixes #23289
Refs #22434 (fixed for Orca-owned Codex homes; the default macOS/Linux setup that reads your real ~/.codex is a pending decision, see above)
Refs #23847 (per-account home fixed here; the worker-start cause message is a follow-up)

Visual Proof

No UI change. The changes are to Codex's hook and config files and to worker-start's failure message. Live QA ran on a separate Mac against an isolated copy of Orca built from this branch (its own home folder and settings; the machine's real ~/.codex was checked by hash and never changed). A stand-in codex program showed Codex's trust screen.

The folder-trust screen an unattended worker cannot answer. This PR makes trust reach the Codex home a per-account launch actually reads; explaining this screen when it still appears is the follow-up:

Worker terminal stopped at the folder-trust screen

The per-agent Codex switch (Enabled / Disabled) that turns Orca's Codex hook off and keeps it off:

Settings, Agents, Codex Enabled and Disabled switch

Testing

  • I manually tested these changes locally

  • Automated tests added/updated, or explained why not below

  • Every test file under src/main/startup, src/main/codex, src/main/agent-hooks, src/relay, the PTY spawn code and the orchestration worker code, plus the trust and runtime suites: 572 files, 7,235 tests pass. Two tests timed out under heavy machine load and pass on their own. The process-spawning integration suites were not run locally.

  • New tests (each fails without its fix):

    • the hook is switched on at every launch prep, on every writer;
    • fix(codex): turning Codex off per agent keeps its hook entry off #23667's per-agent off, in both directions;
    • a copied Claude entry is recognised and filtered;
    • local Codex trust also reaches the launch's own per-account home, and each home is written once;
    • an OS write failure names config.toml;
    • in a WSL-managed home, a moved user hook keeps its approval, a changed one does not, and nothing moves when nothing was removed.
  • Typecheck clean (node, cli); oxlint, oxfmt and the changed-code quality gate clean. No package or lockfile changes.

  • Live QA on a separate Mac (see Visual Proof) with a stand-in codex, before the merge with fix(codex): edit Codex config.toml through one parser-checked writer (1/2) #23930; not run against a real Codex, a real SSH host, WSL or Windows. The worker-start screenshot shows the trust screen the follow-up will explain.

AI Disclosure

Review

Agent skill upstream boundary

  • Not applicable, or this change follows docs/reference/agent-skill-sharing-upstream-boundary.md and copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

Ensure no issues in: Security, Cross-platoform support (Linux, Windows, Mac), Remote SSH, Mobile, general backwards compatibility, performance

  • WSL launches still skip the trust write, as before. Trust writes still share a queue with hook installs; taking them off it risks an older bug.

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)

Fixes the Orca part of #23289. A Codex worker could sit forever at
Codex's hooks screen: Orca's own hook entry had the right trusted_hash
but `enabled = false`, so the SessionStart event Orca waits for never
fired. Orca only ever granted the hash and never re-checked `enabled`
(the ledger fast path compared hashes only, the text fallback kept an
existing `enabled = false`, and the SSH installer passed no value), so a
stale `enabled = false` at the position Orca's entry occupies stuck.

Now every launch prep that installs Orca's hook re-derives it: the Codex
app-server grant writes `{ trusted_hash, enabled = true }` for Orca's
exact managed keys and verify fails if one is still disabled; the ledger
fast path misses when the entry is disabled; the local, WSL and SSH
fallbacks write `enabled = true` for Orca's entries. Project and user
hooks are never touched, so their review stays the user's decision.

Orca's own settings stay the only off switch: all of these writes run
only on the install path, which launch prep, session resume, startup and
the SSH/WSL installs take only when status hooks are on for Codex
(#23667's per-agent check). With Codex turned off, launch prep takes the
refresh-user-hooks path, which never writes Orca's hook state, so a
disabled entry stays off; turning Codex back on re-enables it on the next
launch. Supersedes #23292, which enabled the hook once at account creation
with nothing to re-derive it later.
…tity

Fixes #22434. Codex 0.156.1+ warned at every start that it was clamping a
10 s SessionEnd hook to 3 s. The hook was Orca's Claude status hook:
Codex's own "import from Claude Code" copies Claude hooks into
~/.codex/hooks.json, and Orca recognised its entries there only by the
Codex hook's script name, so it treated the copied entry as the user's,
mirrored it into Orca's managed Codex homes, carried its trust state, and
Codex ran Orca's Claude hook from a Codex pane.

Orca now recognises its hook entries by one identity: the command runs a
script from Orca's `.orca/agent-hooks/` directory, whatever the agent.
In Orca-owned Codex homes (the managed runtime home, its user-hook
mirror, trust promotion, and WSL runtime homes) such an entry is Orca's:
it is not mirrored, its trust is not carried, and stale copies are swept.
The user's real ~/.codex/hooks.json is left as it is; removing Orca's
copied entry there is an owner decision given the rule that restricts
real-home removals.
…y why a worker stalls

#23847: worker-start --agent codex could stall at Codex's folder-trust screen
with no cause. Trust was written to only some Codex homes and failures were
dropped.

- Each Codex home is written on its own, including the per-account home a
  launch actually reads; the shared runtime home is written once. Launch
  prep's two trust writes share one 20 s budget.
- A failed write throws the original refusal (or all of them), so Codex
  config refusals are still reported once per file; an OS error names
  config.toml, not the atomic writer's temp file.
- When a worker stalls at an agent's trust screen, worker-start re-runs that
  agent's own trust write for the same folder and host (bounded at 5 s) and
  reports what it returns: written, failed with the file and reason, still
  waiting, or not pre-trusted. Nothing is stored, so a cause can never come
  from another launch, account, agent or host.
- Remote trust writes report when nothing was written (no remote home, or no
  remote writer for the agent).
@brennanb2025
brennanb2025 force-pushed the brennanb2025/codex-hooks-trust-ownership branch 2 times, most recently from d6bca18 to 2263d3f Compare September 29, 2026 22:34
…eck; honest worker trust messages

- Launch prep checks it is a Codex launch before resolving the per-account
  home, so non-Codex launch prep never touches it (base per-agent opt-out
  tests were red).
- The trust-write test now asserts the original refusal, which refusal
  reporting relies on.
- An OS error that already names config.toml is not prefixed twice.
- Worker trust messages no longer promise a retry works when the write may
  land in a config the agent never reads, no longer blame a config lane for an
  SSH timeout, and point at 'the cause above' when no file was named.
A substring check let config.toml.bak and rename errors through without saying
which write failed; naming the file twice is harmless.
@brennanb2025
brennanb2025 marked this pull request as ready for review September 29, 2026 23:09
@brennanb2025

Copy link
Copy Markdown
Contributor Author

Review status (head b2dccaead29)

The problem. Orca's Codex status hook was left in three broken states. Orca approved its own hook but left it switched off, so it never saw Codex's status and remote workers stalled (#23289). Codex's "import from Claude Code" copied Orca's Claude hook into Codex, and Orca didn't recognise it as its own (#22434). And a worker started with --agent codex could stall at Codex's "trust this folder?" screen with no cause given, because trust reached only some Codex homes and failures were dropped (#23847).

What changes for you.

  • Orca switches its own Codex hook back on every time it prepares a Codex launch (on SSH hosts, each time it connects). Your other hooks are never touched. Orca's per-agent Codex switch is the real off switch: with Codex off, the hook stays off.
  • In Codex homes Orca owns, a Claude hook that Codex copied across is recognised as Orca's and is not carried in. The copy in your own ~/.codex/hooks.json is left alone for now (see below).
  • Trust is written to every Codex home a launch uses, including the per-account home. When a worker still stops at the trust screen, worker-start runs that agent's trust write again for the same folder and host (for at most 5 s) and says what happened: the file it could not write and why, that trust has now been written, that the write didn't finish in time, or that Orca doesn't pre-trust that agent. Orca never answers the dialog for you.

Review. Two full rounds and a narrow review of every fix commit, plus an architecture challenge. Round 1 found no P0/P1. Seven smaller bugs all came from one new part, an in-memory record of recent trust failures. The challenge showed that record could not know which launch, Codex account or host a failure came from. It was replaced by re-running the trust write at the moment a worker stalls, so nothing is stored and nothing can be misattributed. Round 2 (full PR, after that change and a rebase onto the updated #23930) found no P0/P1.

Fixed during review.

  • Other agents' trust failures, or another account's or host's, could be reported as this worker's cause (design replaced).
  • The cause was lost for folder workspaces on Windows or with a trailing slash (design replaced).
  • Launch prep could wait up to 40 s on two trust writes; they now share one 20 s budget.
  • An OS write failure named the atomic writer's temporary file instead of config.toml.
  • The "switched on per agent" test passed without the fix; it now starts from a disabled entry and fails without it.
  • After the rebase, trust errors keep their original form, so step 1's once-per-file reporting of a refused config.toml still works.
  • Launch prep resolved the Codex home before checking this was a Codex launch, which failed an existing per-agent opt-out test.
  • Worker messages no longer promise that retrying will work, and no longer name a file that doesn't exist.

Deferred (all minor).

  • The copy of Orca's Claude hook in your own ~/.codex/hooks.json is left alone. On macOS and Linux, Codex launched from Orca reads that file by default, so the startup warning continues there. This PR now says "Refs Codex warns about a 10s SessionEnd entry calling Orca’s Claude hook #22434" rather than closing it, pending a decision.
  • On Windows, a worker whose shell is WSL but whose folder is a Windows path can be told trust "has now been written" for a home it doesn't read. The message no longer promises that a retry works.
  • A worker started on a connected remote Orca server still gets the plain "Agent startup blocked" message.
  • Resuming a Codex session doesn't write trust to the per-account home it resumes into. That session already ran there, so trust is normally present.
  • In 1 of 4 QA runs, the trust screen was classified as a generic prompt, so the new cause text was missing. That detector is outside this PR and needs a real Codex screen recording to fix.
  • Log and message wording: a "0 ms" deadline note, and a dropped SSH link reported as "could not resolve the home directory".
  • The runtime wiring of the stalled-worker check has no direct test.
  • In WSL-managed homes, removing a copied Claude hook can make one of your approved hooks need re-approval once.

Verified.

  • Tests: every test file under src/main/startup, src/main/codex, src/main/agent-hooks and the orchestration worker code, plus the trust and runtime suites. 372 files, 5,253 tests pass locally. The two integration suites that spawn processes were not run.
  • Each new test was run without its fix and failed.
  • Typecheck (node and CLI), oxlint, the changed-code gate and the max-lines ratchet are clean.
  • Live QA ran twice on a separate Mac against an isolated build of this branch. It used its own home and settings, a stand-in codex, and hash checks proving the machine's real ~/.codex never changed.
    • Round 1 (at df799956bd1): the hook is switched on, your disabled hook stays off, Codex off keeps it off, a copied Claude hook is filtered out, and ordinary launches were not delayed.
    • Round 2 (at d2e5c095361, the new design): a read-only Codex home gives Orca could not pre-trust it: could not write …/codex-runtime-home/home/config.toml: EACCES …, with recovery text, in about 2.2 s. A restored home gives "Orca has now written trust for it …", and the entry really landed in the launch's home.
    • The final commit only changes how an OS error is wrapped, and QA saw the same text before it.

Not verified.

Not merged; marked ready for review only.

@greptile-apps

greptile-apps Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 3/5

[High risk] Codex hook trust and identity system changes across 26 files.

The PR does not appear safe to merge while the earlier user-hook removal and per-account trust findings remain unresolved.

Findings

  1. P1 User hooks can be removed ▶
  2. P1 Per-account trust home missed ▶
  3. P2 Trust errors can name wrong home ▶

Summary

This PR re-enables Orca’s Codex hooks during launch preparation, recognizes imported Orca hooks, carries approvals when WSL hook positions move, and extends local workspace-trust targets to a launch-supplied Codex home.

  • Local, SSH, WSL, and app-server hook paths now check the managed hook’s enabled state.
  • WSL hook rewrites attempt to preserve approvals for unchanged user hooks.
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Launch[Codex launch preparation] --> Hooks[Install or refresh Orca hooks]
  Hooks --> Approval[Enable and trust Orca entries]
  Launch --> Trust[Write workspace trust]
  Trust --> Homes[Managed, launch-supplied, and agent homes]
Loading

Reviews (3) · Last reviewed commit: "Merge codex-config-checked-writer (01030..."

// Why (#22434): every Orca agent hook script lives in Orca's `.orca/agent-hooks`
// directory, so that directory is Orca's one identity in any agent's hook file,
// including an entry another agent's importer copied across.
const ORCA_AGENT_HOOK_SCRIPT = /(?:^|[/'"\s=])\.orca\/agent-hooks\/[^/'"\s]+/

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 User hooks can be removed

If a user’s Codex hook command merely references a file under .orca/agent-hooks/—for example, to check whether it exists—this matcher treats the entire command as an Orca hook. The next install or refresh then removes it from the Codex hooks mirrored into Orca’s home, so that user hook no longer runs there. Identify the script being executed rather than any mention of the directory.

Knowledge Base Used: Agent integrations and hooks

Comment on lines +86 to +101
const results = await Promise.allSettled([
markCodexProjectTrusted(workspacePath),
resolveLaunchHome().then((home) =>
isSeparateCodexLaunchHome(home)
? markCodexProjectTrustedInHome(workspacePath, home)
: undefined
)
])
const failures = results.flatMap((result) =>
result.status === 'rejected' ? [result.reason] : []
)
if (failures.length === 1) {
throw failures[0]
}
if (failures.length > 1) {
throw new AggregateError(failures, `Orca could not mark ${workspacePath} trusted`)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Trust errors can name wrong home

When a stalled Codex worker uses a valid per-account home or the real ~/.codex, this retry still includes failures from the shared home. If that unused home has a broken config.toml, the worker’s recovery message names it as a reason trust could not be written. That sends the user to fix a file the worker does not read; report failures for the worker’s actual launch home instead.

Knowledge Base Used: Agent integrations and hooks

@pullfrog pullfrog 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.

ℹ️ No critical issues — two rough edges in the stalled-worker messages, plus one nitpick.

Reviewed changes

  • Hook re-enable (#23289): every Orca-owned Codex write now stamps enabled: true (managed install, WSL runtime, remote/SSH); the app-server grant sends enabled: true and fails post-grant verify if the entry is still disabled; and the ledger shortcut declines when hooks.state.enabled === false.
  • Hook identity (#22434): isOrcaAgentHookCommand treats any command referencing .orca/agent-hooks/ as Orca's, so an importer-copied Claude hook is filtered out of Orca-owned Codex homes; the user's real ~/.codex is deliberately left alone.
  • Per-home trust + stalled-worker cause (#23847): trust writes now succeed or fail per config.toml instead of all-or-nothing, launch prep also writes the exact per-account launch home, and a stalled worker re-runs that write and fails with a named cause and recovery step.

I verified that enabled participates in no trust key, hash, signature, or ledger record (so forcing it on cannot corrupt ledger matching), that the grant's matchManaged cannot enable a user hook, and that the new writes target disjoint config.toml files with no lock-order inversion.

ℹ️ Nitpicks

  • In src/main/startup/codex-launch-preparation.ts:106, the per-account launch-home write is handed deadlineMs: trustWaitBudgetMs, which is 0 once the first write has consumed the full 20 s budget. A free config lane still wins the microtask race, but a busy one returns 'expired' immediately and launch prep stops waiting on the exact write #23847 is about (the write itself still lands uncancelled). A small floor would guarantee that path always gets a few hundred milliseconds.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

Comment thread src/main/runtime/agent-workspace-trust-diagnosis.ts Outdated
Comment thread src/main/remote-agent-trust-presets.ts Outdated
…ves their hooks

Codex keys hook approvals by position in hooks.json. When the WSL runtime
install removed a Claude hook Codex's importer copied (or first prepended
Orca's entry), the user's later hooks moved to new keys with no approval,
so Codex asked the user to review hooks they had already trusted. The
install now carries each moved hook's recorded approval (trusted_hash and
enabled) to its new key when the recorded hash still matches the hook,
drops the removed copies' approvals, and logs once when it cannot prove
an approval belongs to the hook.
…ership

#23930 merged current main, whose #23744/#23937 moved trust writing into
applyWorkspaceTrustOnThisHost (local) and the SSH relay. Resolved by taking
that design and dropping what it already covers: the per-home trust writes,
the launch-prep trust writes and their shared budget, and the worker-start
trust diagnosis (moved to a follow-up; #23847 is now referenced, not fixed).

Kept on top of it:
- Local Codex trust also reaches the per-account home the launch reads: the
  launch env's CODEX_HOME joins getLocalCodexTrustConfigFiles, as the relay
  already does.
- An OS error that stops a trust write names config.toml, not the atomic
  writer's temp file; config refusals pass through unchanged.
- The WSL hook-trust relocation now logs through warnCodexConfigOnce and
  writes through withConfigPath, the base's single refusal and write rules.

@pullfrog pullfrog 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.

ℹ️ No critical issues — the new relocation logic is sound; one gap in the reverse (disable) direction.

Reviewed changes

  • Added planCodexHookTrustRelocation / relocateCodexHookTrust (new src/main/codex/codex-hook-trust-relocation.ts): maps handlers across an Orca rewrite of a WSL-managed hooks.json by object identity and carries a moved handler's trusted_hash / enabled to its new positional trust key when the recorded hash still matches, drops a removed copy's approval only when its hash proves ownership, and refuses (leaves the old key) otherwise.
  • Added replaceHookTrustEntries to config-toml-trust.ts to remove old keys and write carried entries in one checked, atomic write.
  • Wired the relocation into installManagedHooksIntoWslRuntimeExclusively after writeCodexHooksJson and before the app-server grant / fallback, passing Orca's new managed keys as keepKeys.
  • Added hook-service-wsl-runtime-trust-relocation.test.ts (4 cases) and listed the new module in config/tsconfig.cli.json.

ℹ️ Disabling the Codex integration does not reverse the relocation

installManagedHooksIntoWslRuntimeExclusively now carries a user approval from a hook's old index to its new index, but the disable path refreshWslRuntimeUserHooks removes the managed entry and returns the user's hooks to their original indices without carrying their approvals back. While Orca's Codex integration is off, a user hook therefore sits at its original key with its approval still at the shifted key, so Codex asks to review a hook the user already trusted — the outcome this PR set out to avoid. Re-enabling shifts the hook back onto the shifted approval and self-corrects, so the impact is confined to the disabled period.

Technical details
# Disable path leaves relocated user approvals at stale positions

## Affected sites
- `src/main/codex/codex-hook-wsl-runtime.ts:103-109` — install relocates user approvals to the post-rewrite positions.
- `src/main/codex/codex-hook-wsl-runtime.ts:156-198` — `refreshWslRuntimeUserHooks` removes Orca's managed entries, shifting the user's hooks back, but only calls `removeWslRuntimeManagedHookTrustEntries` (managed keys only) and never relocates the user's approvals.
- `src/main/codex/codex-hook-service-implementation.ts:169-172` — the disable branch is reached via `prepareRuntimeHomeForLaunch(..., hooksEnabled: false)`.

## Required outcome
While Orca's Codex integration is off, the user's own hooks in the WSL runtime home stay trusted, exactly as they did before the enable-side relocation existed.

## Suggested approach
Call `relocateCodexHookTrust(plan.tomlPath, { sourcePath: plan.trustConfigPath, before: config.hooks ?? {}, after: nextHooks, keepKeys: [] })` in `refreshWslRuntimeUserHooks`, mirroring the install call. The plan's removed-copy loop will drop the managed approvals and its carry loop will move each surviving user approval back to its new index.

Pullfrog  | Fix it ➔ | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

Comment thread src/main/agent-workspace-trust.ts Outdated
wslDistro: context.wslDistro
}),
codexConfigFiles: getLocalCodexTrustConfigFiles,
codexConfigFiles: () => getLocalCodexTrustConfigFiles(context.env?.CODEX_HOME),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Per-account trust home missed

For a local Codex launch using a managed account, this trust write takes the account home from context.env?.CODEX_HOME. The local spawn path selects the account home separately and adds it to the process environment only after the trust write. If the incoming spawn environment has no CODEX_HOME, Orca writes trust to the shared and system homes but not the per-account home Codex opens. The removed launch-preparation write previously covered that home, so a worker can stop at Codex’s folder-trust prompt again.

Knowledge Base Used: Agent integrations and hooks

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@brennanb2025

Copy link
Copy Markdown
Contributor Author

Status update: merged the finished #23930 (head 54c8086cce1, CI green)

#23930 merged current main. Main's #23744 and #23937 moved all agent trust writing into one place per launch, on the host that runs the agent (the SSH relay for remote hosts). So this PR now builds on that writer instead of keeping its own. The merge was done with the base branch, not main.

What this PR now changes for you

Moved out of this PR (follow-ups)

Verified at 54c8086cce1

  • CI: 34 checks pass, 12 skipped, none failing, including static analysis, the five unit test shards, typecheck, the Node 18 managed-hooks check and e2e.
  • Locally: node and CLI typecheck; 572 test files across the startup, Codex, agent-hooks, relay, PTY spawn and orchestration worker code. Two tests timed out under heavy machine load and pass on their own.
  • Each new test fails without its fix.
  • This PR adds nothing the relay bundles that needs Node 20.

Not verified: the M4Air live QA ran before this merge, so the re-homed trust path and the WSL approval carry-over are covered by tests only. Nothing was run against a real Codex, a real SSH host, WSL or Windows.

Not merged; ready for review.

…ust-ownership

Main now resolves the ~/.codex trust file from the launch env's home
(launchedAgentHome) instead of the process home. getLocalCodexTrustConfigFiles
takes that agent home and still adds the launch's per-account CODEX_HOME
between the managed and system homes, each home once (#23847).

@pullfrog pullfrog 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.

✅ No new issues found.

Reviewed changes

  • Added the per-account CODEX_HOME a launch reads to getLocalCodexTrustConfigFiles(agentHome, launchCodexHome?), kept in the hook installer's lock order and deduped with normalizeRuntimePathForComparison, so a home named twice (trailing slash, Windows case, WSL-UNC alias) is written once.
  • Threaded launchedAgentHome(context.env) and context.env?.CODEX_HOME through applyAgentWorkspaceTrust so local Codex trust reaches the exact home a per-account launch resolves.
  • Updated the codex-home-paths and agent-workspace-trust tests to pin the insertion and dedupe behavior; focused run passes (48 tests).

I verified the dedupe collapses to the prior [managed, ~/.codex] list when CODEX_HOME is unset or equals a listed home, and that all callers pass an agent home (none still position a Codex home as the first argument). Two prior inline threads were retired: remote-agent-trust-presets.ts and agent-workspace-trust-diagnosis.ts no longer exist after the base refactor and the worker-start-cause split.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@brennanb2025

Copy link
Copy Markdown
Contributor Author

Closing this older combined hook and trust rewrite. #25742 and #25743 replace the approval work; copied Claude hooks remain tracked in #22434.

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