Skip to content

feat(agents): pre-trust the folder wherever Orca starts an agent - #23744

Merged
brennanb2025 merged 45 commits into
mainfrom
brennanb2025/claude-worktree-trust
Sep 29, 2026
Merged

brennanb2025 merged 45 commits into
mainfrom
brennanb2025/claude-worktree-trust

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 44 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1785 $\color{#cf222e}{\Huge{\mathbf{−}}}$​1308 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​477
Prod 83 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1164 $\color{#cf222e}{\Huge{\mathbf{−}}}$​845 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​319

What this fixes

When Orca starts a coding agent in a folder the agent has never seen, many agents stop at their own "Do you trust this folder?" question and wait for a key press. Claude Code always did this in Orca. Cursor, Copilot, Qoder and Antigravity did it on Orca's most common launch path (a new tab, quick launch, the dashboard, source control, fix-checks), because that path never ran Orca's trust step. An unattended launch (an orchestration worker, an automation, the phone, orca worktree create --agent …) had nobody to press the key, so it sat there until Orca reported it as blocked (#22927). And the agents didn't behave the same: whether you got the question depended on which agent and which button you used.

Scope: agent terminals that Orca itself starts, for agents with a trust preset (Claude Code, Claude Agent Teams, Codex, Cursor, Copilot, Qoder, Antigravity), in any worktree, main checkout or folder workspace, on macOS, Linux, Windows and SSH hosts, and for Claude also inside WSL. Not affected: an agent you type yourself in a plain terminal, and agents without a trust preset. Structured (native) chats never show the question; a structured Codex chat still gets Orca's Codex trust write before it starts, as on main.

ELI5

Some agents ask "do you trust this folder?" the first time they run somewhere. Orca now answers "yes" for them, ahead of time, whenever Orca is the one starting the agent in your workspace, the same way for every agent. One switch in Settings turns it off.

What Changed

After, with the new setting on (the default): when Orca starts an agent with a trust preset, Orca writes that agent's own "trusted" record for the workspace just before the agent's process starts, so the agent opens straight to its prompt. Per agent:

Agent Before After
Claude Code and Claude Agent Teams Always asked in a new folder. Doesn't ask in workspaces Orca starts it in, locally, over SSH and inside WSL (except the cases under "What Orca never does" and the known gaps below).
Codex Trusted on local launches through its own launch preparation; over SSH only on some launch paths, and there it trusted the worktree path and ignored CODEX_HOME. Trusted on every launch path Orca starts, locally and over SSH. Over SSH it now trusts the same folder as locally (the repository's main checkout) and honours CODEX_HOME. Inside WSL it still asks, as before.
Cursor, Copilot, Qoder Trusted on some launch paths only; a new tab, quick launch, the dashboard and source control asked. Trusted on every launch path Orca starts, locally and over SSH. Inside WSL they still ask (Orca never writes the Windows home for them).
Antigravity Same gaps as above; the desktop create-with-agent path left it out entirely. Trusted on every local launch path. Over SSH it still asks (no verified remote writer yet, unchanged).
Any agent you type yourself in a plain terminal Asked. Still asks. Nothing is written.

Setting: Settings → Agents → "Trust the folder when Orca starts an agent", on by default, translated for es, fr, ja, ko and zh. Its text: "Agents Orca starts skip their "Do you trust this folder?" prompt, so the project's agent hooks and settings run right away. Without this, each agent asks the first time it runs in a folder. Agents running without you watching, such as orchestration workers, automations and agents started from your phone, will wait at that question until you answer it in their terminal. Folders already trusted stay trusted." It is hidden in the paired web client, like the other host-machine settings.

What Orca never does:

  • For agents whose trust on a folder also covers every folder below it, it never pre-trusts your home folder, a folder that contains a home (such as /Users), or a disk root, however the path reaches it (a symlink or ..). That is Claude Code (its trust check walks up parent folders; outside a git repository it goes all the way to the disk root), Copilot and Qoder (any trusted folder above the current one counts). The check runs on the exact path each agent would store, on the machine that runs the agent. Codex, Cursor and Antigravity are trusted there exactly as before this PR: Codex checks only the exact folder and then its repository root, Antigravity only the exact folder, and Cursor itself refuses to inherit trust from a home.
  • It never writes a WSL agent's trust into the Windows home. Claude writes only the WSL guest's own config; the other agents skip WSL, as Codex already did.
  • It never removes trust. Turning the setting off stops new writes; what is already trusted stays, exactly as if you had answered "Yes" yourself.

Worth knowing: Claude Code and Codex treat every worktree of a repository as trusted once its main checkout is. So after Orca (or you) trusts a repository's main checkout, its worktrees don't ask either, even with this setting off, and that includes worktrees of pull requests from forks. That is how those agents work, and it is why this PR has no fork-specific exception: one could not hold for the two most-used agents.

Where an agent now asks that didn't on main: only Copilot and Qoder when the workspace is your home folder, a folder above a home, a disk root or a symlink to one of these (main pre-trusted those on some launch paths; since both agents extend a trusted folder to everything below it, that entry would have trusted every folder you own). With the setting turned off, every agent asks, by your choice. Everywhere else, every agent is trusted wherever it was on main, and on more launch paths.

Mechanism

  1. One place, at process start. Both paths that start an agent's terminal process (the desktop one and the runtime one used by the CLI, the phone, orchestration and automations) now run one trust step just before the process starts. The step reads the agent the launch declares, which survives a repository's setup script wrapping the command. It runs only when the launch starts the agent's command; it doesn't run when Orca reattaches to a tab whose agent is still running (a restored tab that re-runs the agent, such as a resume, is a fresh launch and does write). Plain shells and agents without a preset add no wait; a Claude launch in an already-trusted folder still reads its config once (about 11 ms for a 5.9 MB file).
  2. One writer module per host. applyWorkspaceTrustOnThisHost works out the exact path the agent's existing writer will store, refuses it if it is too broad (above), then calls that writer with what it needs from the launch (the final environment, the managed Claude account, the WSL distro). The desktop uses it for local and WSL launches, and the SSH relay uses the same code on the remote machine. It replaces three copied switches; one of them had left Antigravity out.
  3. One owner. The renderer's trust IPC channel, its seven callers, the main-process pre-launch trust calls and Codex's separate launch-prep trust write are deleted. Every launch they served reaches the new step (the per-path trace is in the review notes below).
  4. Claude's writer. Claude's record is projects[<folder>].hasTrustDialogAccepted in the config file that Claude process reads (CLAUDE_CONFIG_DIR, managed accounts, the legacy .config.json rule, a WSL guest's own file). The writer takes Claude's own <file>.lock and never breaks a held lock, re-reads under it, renames atomically, never creates a missing file, refuses a file it can't parse, keeps the file's mode and follows a symlinked config. Writes to the same file queue inside Orca, so a burst of parallel launches doesn't lose any to lock contention.
  5. SSH. The desktop sends a new optional agentWorkspaceTrust field with the spawn request, and the relay (Orca's helper on the SSH host) writes the agent's trust on its own disk with the same module, for every agent except Antigravity (no verified remote writer yet). This replaces the desktop writing Codex, Cursor, Copilot and Qoder trust over SFTP, which was unlocked, not atomic and took several network round trips. The relay is always the same build as the desktop (its install folder and handshake are keyed to a hash of its own code), so the field is never sent to a relay that doesn't understand it.
  6. Time limits. A trust write never fails a launch. A local Codex write keeps the existing 20 s limit (it waits on Codex's shared config lock, as before this PR); every other write, including every SSH write, gets 1.5 s. If a write misses its limit, the agent starts anyway and asks.

Why

The missing piece was a saved fact each agent looks for; writing it is each agent's own documented way to skip the question. Orca already had those writers for five agents. The problem was where they ran: seven renderer call sites and several main-process ones, each asking with a path it chose, and none on the most common launch path. Moving the decision to the one step every Orca-started agent passes through makes every agent behave the same, covers every launch path including ones added later, and removes the copies that had drifted apart.

Alternatives rejected:

  • Adding Claude to the existing call sites. It would still miss the new-tab launch, the most common one.
  • A Claude-only setting with a fork exception and cleanup on removal (this PR's first version). Agents should act the same for Orca; the fork exception can't hold for Claude or Codex (above); and cleanup kept producing new edge cases while neither the comparable tools we checked nor Orca's existing presets remove trust.
  • A fork-specific check at launch: fork pull-request worktrees created from a bare commit (GitLab fork merge requests, or a GitHub fork whose push target couldn't be found) leave no trace to check.

Linked Issue

Refs #21867. Follows #22927.

Visual Proof

Live QA on a second Mac, driving a background dev build of this branch through the Chrome DevTools protocol, with a throwaway Claude config directory, a dummy API key, no network for Claude, and Claude Code 2.1.284. Antigravity ran as a stub program behind Orca's command override, so Orca still launched it as Antigravity and wrote its trust file, without starting (and self-updating) the real agy. Every Claude launch used Orca's default arguments, claude '--dangerously-skip-permissions'. Round 3 (9/9 pass) ran at f3709c08b8e; round 4 (8/8 pass) ran at 5a9865a6ae9, after the change that guards the stored path and moves SSH writes to the relay; round 5 (6/6 pass) ran at e0323411778, after the home guard became per agent, with Codex also as a stub. The only code changes after round 4 besides round 5's subject are one more guard form (a path climbing back through ..), a relay ordering test, and the structured Codex trust write. The real Claude and Antigravity settings files on that machine were unchanged, and no QA path was added to its real ~/.claude.json.

A worktree Orca created, launched by Orca: Claude opens straight to its prompt, and its config gained {"hasTrustDialogAccepted": true} for that worktree.

Claude opens straight to its prompt in a worktree Orca created

A folder workspace: Claude now opens straight to its prompt there too (before this PR it asked).

Claude opens straight to its prompt in a folder workspace

Antigravity (stub) in a new worktree: Orca added the worktree to Antigravity's trustedWorkspaces. The folder workspace was added the same way.

Antigravity launched by Orca; its trust file gained the worktree

The home folder as a folder workspace (and a symlink to it): Claude still asks, and nothing is written for it, because Claude's trust would then cover everything under your home.

Claude still asks when the workspace is the home folder

Codex started from a floating terminal whose folder is the home (round 5): trusted exactly as on main; Codex checks only that exact folder, so this does not trust anything below it. Codex in a home-folder workspace and Antigravity in the home were trusted the same way, while Claude still asked there.

Codex (stub) launched from a floating terminal in the home folder

Setting off: Claude asks in a new worktree of a repository nobody has trusted, and Orca writes nothing. Entries written earlier stay.

With the setting off, Claude asks and nothing is written

claude typed by hand in a plain terminal: Claude asks, as before.

A hand-typed claude still asks

The setting (screenshot taken before the description was reworded to the text above):

Settings → Agents → Trust the folder when Orca starts an agent

Also checked live: a Claude tab reattached after restarting the app wrote no trust again, and the main checkout is trusted like any other workspace. Not run live, covered by unit tests only: SSH (the rig has no SSH host), WSL, Windows, the real Codex binary, Cursor, Copilot, Qoder, Agent Teams, and structured Codex chats.

Testing

  • I manually tested these changes locally
  • Automated tests added/updated, or explained why not below

New tests cover:

  • the spawn step on both spawn paths: every preset agent against a worktree, main checkout, folder workspace, setting off, a restored pane, SSH and WSL, and that the process doesn't start until trust settles;
  • the host module with the real writers for all six presets: which agents refuse a home, a folder above a home, a root, a symlinked home and .. back to home, and that Codex, Cursor and Antigravity are trusted there as before;
  • the relay: the preset from the launch's declared agent, each preset, Antigravity and WSL-shell early returns, a missing field, and that pty.spawn waits for trust before starting the agent;
  • Claude's writer: keeps other keys, no-op when trusted, refuses corrupt or unreadable files, never creates the file, keeps 0600 and symlinks, never breaks a held lock, queued writes under a burst of parallel launches, NFC and Windows key forms;
  • the setting row and its search entry.

Each key mechanism was ablated and its test went red.

Local gates at the head: tc:node, tc:web and tc:cli pass; the changed-code quality gate (type-aware rules, React Doctor, design system, casting rationale), oxlint and the anti-slop rules pass on every changed file; the max-lines ratchet, reliability-gate check and localization catalog, extraction and coverage checks pass; the relay bundle builds for every platform with no Electron import. Tests, run with explicit files and a throwaway HOME and CLAUDE_CONFIG_DIR: every test file in this PR plus orca-runtime.test.ts, 1854 passed, 1 skipped. Not run locally: e2e suites.

Platforms: macOS (unit tests and gates on one machine, live dev-build QA on a second). Windows, WSL and SSH are covered by unit tests only.

Review

Reviewer notes:

  • Launch-path coverage: every launch path reaches one of the two spawn paths as a fresh launch with its agent declared: a desktop new tab (quick launch, tab menu, dashboard, source control, fix-checks), background sessions and automations, work-item launches, continuation and fork, worktree create with an agent (desktop, CLI, runtime, SSH, folder), the folder composer, the CLI and phone terminal commands, agent-session create and resume, orchestration worker-start, setup-script launches, Codex resume and the Agent Teams leader. Agent Teams teammates start in the folder the leader just trusted.
  • Structured chats: Claude's runs in print mode, which has no trust dialog (from Claude's documented behaviour, not a binary check). A structured Codex chat gets the same Codex trust write before it starts as on main, through the same module and setting; the Codex app-server records trust itself only when the chat may write the folder.
  • Known gaps:
    • Antigravity over SSH still asks (no verified remote writer; unchanged).
    • When Orca starts Codex in a subfolder of a workspace, the subfolder is trusted (as main's quick launch did); some other main launch paths also trusted the workspace root, so a Codex you later start yourself at the root of a non-git folder may ask.
    • A CLAUDE_CONFIG_DIR exported only in a shell rc is invisible to Orca, so Claude asks.
    • Not verified on Windows: whether a write into a WSL guest's .claude.json through \\wsl.localhost keeps its 0600 mode.
    • Agent Teams teammates get no write of their own; they start in the folder the leader's launch just trusted (as on main, where teammates were never trusted).

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

Security: Orca only writes trust for a workspace it is starting an agent in; for agents whose trust covers subfolders (Claude, Copilot, Qoder) never for a home folder, a folder above one, or a disk root; and it never removes anything. Cross-platform: Windows keys use forward slashes as Claude does; WSL agents never get the Windows home. SSH: each remote host writes its own files through Orca's relay, which is always the same build as the desktop, so the new spawn field is never sent to a relay that doesn't understand it. Performance: a launch with nothing to write adds no wait; a local Claude launch reads and parses its config file once (about 11 ms for a 5.9 MB file).

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)

Claude Code asks "Do you trust this folder?" on first launch in any folder it
has not seen, which blocks unattended launches in worktrees Orca itself made.
Orca now records where a worktree's content came from when it creates it, and
before each Claude launch writes Claude's own folder-trust entry for that
worktree's root (never the main checkout) when the new setting is on and the
content is the user's repository. Forks, bare commits, folder workspaces and
external checkouts keep Claude's prompt. The write takes Claude's lock, never
creates or breaks the file, runs on the SSH host itself, and is revoked when
the worktree is removed or the setting is turned off.

Launches that already pass --dangerously-skip-permissions also skip the trust
prompt for that one process only, via CLAUDE_CODE_SANDBOXED=1 on the command.
A WSL worktree's Claude reads the guest's own config. Two paths still wrote
its trust into the Windows host's ~/.claude.json instead: the Claude auth prep's
fallback (runtime 'wsl' but the host config dir, when the WSL home cannot be
resolved), which wrote a Linux-path key the removal revoke can never delete;
and the Agent Teams leader, which passes no auth or distro and wrote a UNC key.
Require the guest's own config dir, and treat any WSL worktree path as guest-only.
Pre-trust stays limited to worktrees Orca creates from the user's own
repository. The per-launch CLAUDE_CODE_SANDBOXED prefix skipped Claude's
trust question in every folder for launches carrying the skip-permissions
flag (Orca's default Claude args), including the user's own folders and fork
PR worktrees, and the setting could not turn it off. Remove the prefix, the
inherited-variable strip that existed only for it, and the Agent Teams
leader-to-teammate propagation; restore the tests that pinned the prefixed
launch string.
At spawn the relay resolves Claude's config from the launch env, which carries
a CLAUDE_CONFIG_DIR set in Orca's Claude default env. claudeTrust.converge had
only the relay's own process env, so removing the worktree or turning the
setting off revoked in the default file and the grant outlived the worktree.
Send the config-file keys with the request, as the local revoke already uses.
The description said Claude skips its trust prompt in any worktree Orca
created. Trust is written only when Orca itself starts Claude there, so a
`claude` typed by hand in a fresh worktree still asks. Say that, and bring
the es/fr/ja/ko/zh translations in line with the new text.
…tent

A worktree based on a named ref was always stamped as the repository's own
content, so picking the fork remote Orca adds for a pull request (or a local
branch tracking it) as the base made a fork's code eligible for Claude trust.
At create time, read the repo's `remote.<name>.orca-created` markers and each
branch's tracked remote in one `git config` call; a base on such a remote is
stamped as a fork's content, and a read failure is not vouched for. Remotes
the user added, such as `upstream`, stay first-party.
…ktree

Turning "Trust worktrees Orca creates for Claude" off read and parsed the
whole Claude config once per Orca worktree on the main process. Group the
revocations by config file locally and by SSH connection, and make
claudeTrust.converge take a batch of requests.
…orktree-trust

# Conflicts:
#	src/main/runtime/orca-runtime-resolve-worktree-removal-target.ts
@brennanb2025

Copy link
Copy Markdown
Contributor Author

Review status: ready for your review (still a draft, not merged)

Head c5babd01ff7. Five review loops, an architecture challenge, readiness checks at the start and the end, and two rounds of live QA on a second Mac. Loops 3 and 5 came back clean, and in between loop 4 made the one change the architecture challenge recommended. tc:node, tc:web and tc:cli pass, the lint and localization gates pass on the changed files, and CI on this head is green so far (30 passed, 11 skipped by change filters).

What changed during review

  • Removed the skip-permissions shortcut (CLAUDE_CODE_SANDBOXED=1 in front of any --dangerously-skip-permissions launch). That flag is Orca's default Claude argument, so the shortcut skipped Claude's trust question for nearly every user: in fork pull-request worktrees, in your own folders, and even with the new setting off. That contradicted the setting's own text and the fork exclusion. Launches outside eligible worktrees are now exactly as on main: the launch-command, environment and agent-recognition code are byte-identical to main, and live QA shows the question in a folder workspace and the main checkout with the default arguments. This was a coordinator decision applying the approved scope, and you can overrule it.
  • Setting text now says it applies "when Orca starts Claude in a worktree it created", with es/fr/ja/ko/zh translations. Typing claude yourself in a plain terminal still shows Claude's question. That is also a coordinator decision (the problem being solved is unattended launches, and writing earlier would touch ~/.claude.json for worktrees never used with Claude, possibly in the wrong config file), and you can overrule it too.
  • Fork detection: a base on a fork remote Orca itself added (or a branch tracking one) now counts as fork content. If Orca can't read the repo config, it treats the worktree as unverified and Claude asks.
  • WSL: a WSL worktree's trust is never written into the Windows host's ~/.claude.json.
  • SSH: removal revokes in the same config file the launch wrote, and the request carries that launch's config folder.
  • Performance: turning the setting off now does at most one locked write per config file, and one relay request per SSH connection. Before, it re-read the whole config once per worktree on the main process.

Architecture challenge

One issue class came up in every loop: "trust entries outlive their worktree". A separate review challenged the design against alternatives: revoking at every place Orca forgets a worktree, a config-wide sweep, and a durable record of what Orca wrote. Verdict: keep the design (decide again at every Orca launch, and revoke on delete and on setting-off). A sweep is unsafe, because the entry shape isn't unique to Orca and Claude's own hint text tells users to write it. The leftover entries are almost all for folders that no longer exist. The one change it recommended, batching the setting-off revocation, is in.

Live QA (second Mac, throwaway Claude config, dummy key, no network)

Round 1 at e8ba4bf43b6, 7 of 7 pass: an Orca worktree opens straight to Claude; a folder workspace, the main checkout and a hand-typed claude still ask; setting off removes Orca's entries and new worktrees ask; deleting a worktree removes its entry; the setting text shows correctly. Round 2 at c5babd01ff7, 4 of 4 pass, after the batching change: three entries were removed by one switch-off click, and Claude's own entry stayed byte-identical. The real ~/.claude/settings.json on that machine was unchanged in both rounds, no QA path was added to its real ~/.claude.json, and in round 2 both files' hashes were unchanged.

Not run live, covered by unit tests only: SSH, WSL, Windows, Agent Teams and a real fork pull request.

Known gaps, all listed in the PR body

  • A WSL worktree whose repo has a setup script still gets the question. Those launches skip Claude's account preparation on every host today (not caused by this PR), and Orca refuses to guess the guest's config file.
  • Unverified: whether writing a WSL guest's config through \\wsl.localhost from Windows keeps its 0600 mode. Orca's existing WSL credential writes use the same path. One stat on the Windows box would settle it.
  • Leftover entries: a worktree deleted outside Orca, a WSL worktree deleted in Orca, SSH deletes while disconnected, a config folder you switched away from, and worktrees of a repo removed from Orca.
  • Ownership is decided by exact entry shape, so a hand-written { "hasTrustDialogAccepted": true } at an Orca worktree path is removed along with Orca's.
  • Nit, not changed: the trust write's 1.5 s timeout has its own small race helper rather than reusing awaitAgentTrustWriteWithinDeadline. That helper is typed to the existing presets and returns no outcome.

Found during review, not caused by this PR

  • Worktree metadata is keyed by path, so a folder re-created by hand at the path of a worktree deleted outside Orca inherits the old Orca provenance.
  • vitest has no global HOME isolation: the runtime suite writes $HOME/.orca.
  • A sidebar attention dot stays after you exit Claude or decline its trust question.

@brennanb2025
brennanb2025 marked this pull request as ready for review September 29, 2026 04:08
@greptile-apps

greptile-apps Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 1/5

[High risk] Restructures workspace trust handling across agent spawn paths.

The PR does not appear safe to merge while queued drafts or orchestration mail can be lost, stranded, or duplicated.

Findings

  1. P1 Security Granted trust cannot be revoked. ▶
  2. P1 Security Short hashes bypass fork classification. ▶
  3. P1 Late revocation removes fresh trust. ▶
  4. P1 Managed Codex home stays untrusted. ▶

Summary

The PR moves workspace trust writes to agent spawn and adds a setting controlling them. Changes since the previous review also introduce structured-chat queueing, orchestration mail routing, Codex shell wrapping, and UI updates.

  • The structured mail changes can retry a rejected pointer without a new send or duplicate an ambiguous pointer after restart.
  • A failed queued-draft carry can leave a cleared chat’s accepted message on its superseded session.
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Orca agent launch] --> B{Trust setting and preset}
  B -->|Local or WSL| C[Host trust writer]
  B -->|SSH| D[Relay trust writer]
  C --> E[Agent process starts]
  D --> E
Loading

Reviews (3) · Last reviewed commit: "fix(settings): plainer folder trust sett..."

Comment on lines +103 to +108
for (const key of args.folderKeys) {
const entry = projects[key]
projects[key] = isPlainObject(entry)
? { ...entry, hasTrustDialogAccepted: true }
: { hasTrustDialogAccepted: true }
}

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 security Granted trust cannot be revoked. If Claude already has a worktree entry with other fields and hasTrustDialogAccepted: false, this code preserves those fields while granting trust. Revocation deletes only entries containing exactly the trust field, so turning the setting off or deleting the worktree leaves Orca’s grant active. Claude can later skip the trust question at that path despite the attempted withdrawal.

How this was verified: The grant merges into a multi-field entry, while every revoke path uses the one-field entry check.

Comment thread src/shared/worktree/content-origin.ts Outdated
Comment on lines +72 to +77
if (args.forkRemoteConfig === null) {
return 'unverified-commit'
}
return isBaseOnOrcaForkRemote(base, args.forkRemoteConfig)
? 'cross-repo-review-head'
: 'repo-ref'

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 security Short hashes bypass fork classification. A user can use an abbreviated hash of a fetched fork commit as the worktree base. This classifier recognizes only full-length hashes, so it treats the abbreviation as a named base and labels it repo-ref when it matches no Orca-marked fork remote. Orca can then pre-trust third-party content, allowing its Claude hooks to run without the trust question.

How this was verified: The full-length-only hash check sends an abbreviated commit through the named-base branch, whose unmatched result is eligible for pre-trust.

Comment on lines +76 to +79
worktreeId: string
): void {
// Why: cleanup must never gate the removal, so it runs detached and swallows failures.
void revokeWorktrees(store, [worktreeId]).catch(() => {})

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 Late revocation removes fresh trust. Removal and setting-off revocations run in the background and identify entries only by worktree path. If the setting is turned back on, or a worktree is recreated at the same path, a new Claude launch can grant trust before the older revocation gets the config lock. The older revocation then deletes the fresh grant, leaving an unattended launch at Claude’s trust question.

@coderabbitai

coderabbitai Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

📝 Walkthrough

Walkthrough

The change moves workspace trust writes from renderer and worktree preflight paths to fresh PTY launches and structured Codex session creation. It adds host-specific trust handling for local launches, Claude config files, WSL paths, and SSH relays. It also adds an enabled-by-default setting to control new trust writes, removes the former trust IPC bridge and remote trust writers, and updates tests, translations, and supporting documentation.

Priority: ➖ Normal

Merge Risk: 🟡 Moderate · up to 0291d

A cancelled relay launch can leave a folder trusted even though no agent started. The setting description also overstates when the trust prompt is skipped. Fix the cancellation ordering and qualify the copy before merging.

Security Architecture Review

Security architecture risk: 🟡 Moderate · up to 0291d

Starting a coding session now grants lasting folder trust by default, allowing project hooks and settings to run without their usual confirmation. An opt-out and broad-path checks limit exposure, but disabling the feature does not revoke existing trust.

Retained concerns

  • Medium · security · inferred: Default-on launch trust replaces folder-specific consent on additional launch paths. Repository-controlled hooks and settings can consequently become active when a user or automation starts a supported session, with trust persisting for later invocations using the same configuration. Path-breadth guards limit which folders are trusted but do not establish that their contents are trustworthy. This is an inferred design risk of the expanded policy, not a verified exploit.
Security review details

Security Blast Radius

  • inferred — The directly affected assets are workspace-trust decisions in the execution user's configuration files. A grant can affect later sessions that read the same files, beyond the originating terminal. Repository-controlled hooks then have the authority available to the launched process; the inspected change does not demonstrate new administrator, cross-tenant or infrastructure privileges.

Security Findings and Attack Paths

  • inferred — A repository contributor controlling project hooks or settings could benefit when a user or automation launches a supported session in that repository: automatic persistence removes the usual folder-confirmation step. Exploitation still requires reaching an eligible launch and depends on the coding tool's hook behavior. This is a potential attack path, not a verified vulnerability or evidence of unauthenticated relay access.

Trust Boundaries and Controls

  • inferred — The normal desktop path controls whether trust metadata is emitted. Although the relay accepts an independently supplied trust path, the inspected endpoint already accepts shell, command and environment inputs for process execution. An additional privilege escalation from the new field is therefore not established; transport authorization remains unverified rather than presumed safe or vulnerable.

Resilience and Maintainability Implications

  • observed — Trust persistence precedes later local validation and the relay's final cancellation check and native spawn. A successful grant can therefore survive a failed or cancelled launch. Claude grants preserve existing configuration under locking and atomic replacement, and Codex grants serialize in-process, but neither makes the entire trust-and-launch transition transactional.

Hardening Proposals

  • proposed — Consider an explicit per-workspace consent policy for unattended launches and a separate revocation operation. If launch cancellation is intended to prevent new grants, track newly created trust separately from pre-existing trust and coordinate pending writers; blindly deleting a record could invalidate another session's legitimate grant.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 39.53% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 129 functions across 78 files. (7 skipped… 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: Orca pre-trusts folders when it starts supported agents.
Description check ✅ Passed The description is complete and directly matches the template. It explains the user impact, mechanism, rationale, linked issues, visual proof, testing, known gaps, cross-platform behavior, security co…
Full details: Docstring Coverage

Explanation

Docstring coverage is 39.53% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 129 functions across 78 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

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: 5d2d4efc-bd1e-44bb-910b-0b147202a54b

📥 Commits

Reviewing files that changed from the base of the PR and between a5ce825 and c5babd0.

📒 Files selected for processing (45)
  • src/main/claude/claude-folder-trust-file.test.ts
  • src/main/claude/claude-folder-trust-file.ts
  • src/main/claude/claude-worktree-trust-eligibility.ts
  • src/main/claude/claude-worktree-trust-host.ts
  • src/main/claude/claude-worktree-trust-lifecycle.test.ts
  • src/main/claude/claude-worktree-trust-lifecycle.ts
  • src/main/claude/claude-worktree-trust-spawn.test.ts
  • src/main/claude/claude-worktree-trust-spawn.ts
  • src/main/ipc/pty/ipc/spawn-options-claude-trust.test.ts
  • src/main/ipc/pty/ipc/spawn-options.ts
  • src/main/ipc/pty/runtime/spawn-options.ts
  • src/main/ipc/worktree-content-origin.test.ts
  • src/main/ipc/worktree-content-origin.ts
  • src/main/ipc/worktree-remote.ts
  • src/main/ipc/worktrees/removal/worktree-removal-ownership.ts
  • src/main/providers/pty-provider-contract.ts
  • src/main/providers/ssh-pty-spawn-request.ts
  • src/main/runtime/orca-runtime-resolve-terminal-split-source-authority.ts
  • src/main/runtime/orca-runtime-resolve-worktree-removal-target.ts
  • src/main/runtime/orca-runtime-tests/worktree-creation-content-origin.spec.ts
  • src/main/runtime/orca-runtime.test.ts
  • src/main/runtime/runtime-local-worktree-materialization.ts
  • src/main/startup/main-process-ready-foundation.ts
  • src/main/worktree-removal-safety.ts
  • src/relay/claude-folder-trust-spawn.test.ts
  • src/relay/claude-folder-trust-spawn.ts
  • src/relay/pty-handler.ts
  • src/relay/relay-runtime-services.ts
  • src/renderer/src/components/settings/AgentsPane.test.tsx
  • src/renderer/src/components/settings/AgentsPane.tsx
  • src/renderer/src/components/settings/agents-search.ts
  • src/renderer/src/components/settings/claude-worktree-trust-copy.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/claude-folder-trust-spawn-request.ts
  • src/shared/default-global-settings.ts
  • src/shared/global-settings-types.ts
  • src/shared/worktree/content-origin.test.ts
  • src/shared/worktree/content-origin.ts
  • src/shared/worktree/meta-types.ts

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

Comment on lines +50 to +51
null,
null

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.

🔒 Security & Privacy | 🛡️ Detected with Advanced Tier | 🟠 Major | 🏗️ Heavy lift

Security Misconfiguration

Reachability: External
Exploitability: Difficult
CWE: CWE-863 — Incorrect Authorization

Resolve the WSL guest config for revocation.

For a WSL worktree, resolveLocalClaudeTrustRequest requires WSL authentication. Passing null makes it return null, so removal and setting disablement never enqueue a revocation. The previously accepted folder-trust entry remains in the guest config. A later Claude launch using that config can skip the trust prompt after the user has turned the setting off. Resolve the guest config before metadata removal and submit a trusted: false request. (code.claude.com)

View in Security blast radius

Comment on lines +116 to +120
{
title: getClaudeWorktreeTrustTitle(),
description: getClaudeWorktreeTrustDescription(),
keywords: getClaudeWorktreeTrustSearchKeywords()
},

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

Hide this search entry when the switch is unavailable.

In a paired web client window, AgentsPane omits ClaudeWorktreeTrustSetting, but getAgentsPaneSearchEntries still returns this entry. A search result can therefore lead to a pane with no matching control. Filter the entry for paired web client windows, as the catalog already does for other conditional settings.

@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 — one rough edge inline and one narrow gap worth a look.

Reviewed changes

  • Folder-trust writer — new claude-folder-trust-file.ts writes/removes projects[<worktree>].hasTrustDialogAccepted in Claude's global config: atomic tmp+rename, mode + symlink preserved, never creates a missing file, refuses unparseable configs, and takes Claude's <file>.lock without ever breaking a held one.
  • Eligibility + origin gate — claude-worktree-trust-eligibility.ts trusts only git worktrees with Orca creation provenance, deciding trusted from settings and a new orcaCreationContentOrigin stamped at creation in worktree-content-origin.ts (repo-ref / same-repo-review-head = first-party; fork / unverified = not).
  • Spawn integration — both PTY spawn paths and the Agent Teams leader converge trust just before spawn; SSH forwards a claudeFolderTrust field on the spawn request and the relay applies it on its own disk.
  • Revocation — removed worktrees and the setting being turned off withdraw Orca-shaped entries, locally and over a new claudeTrust.converge relay RPC (old relays reject it harmlessly).
  • UI — new default-on claudeTrustOrcaWorktrees setting (Settings → Agents) with copy, search keywords, and translations.

I verified the two load-bearing invariants myself: fork push targets always carry remoteUrl while same-repo targets never do (getPullRequestPushTarget), and both spawn paths merge the Claude account envPatch into the env before the trust call, so the writer sees the account's CLAUDE_CONFIG_DIR. The lock/write path also releases on every return, including the uncancelled timeout, and cannot clobber a Claude-shaped entry.

ℹ️ Named-base fork detection leans on a marker some SSH relays never write

isBaseOnOrcaForkRemote decides "third-party content" solely from the remote.<name>.orca-created git config marker. On SSH that marker is written through the git.markRemoteOrcaCreated RPC, which an older relay rejects with a one-time warning and no retry — so the marker is permanently absent. If Orca added a fork remote while connected to such a relay and a later worktree is created from that fork branch by name as the base, no pushTarget is present, the marker lookup misses, and the worktree is stamped repo-ref and pre-trusted. The normal PR review-head flow always carries a fork pushTarget, so it is unaffected; reachability needs the old relay plus a by-name base selection. It is the one path I found where fork content can be stamped first-party, so it may be worth hardening (e.g. compare the named base's remote URL against the repo's own remotes, not just the marker).

Technical details
# Named-base fork classification only trusts Orca's `orca-created` marker

## Affected sites
- `src/shared/worktree/content-origin.ts:37-54` — `isBaseOnOrcaForkRemote` matches only `remote.<name>.orca-created` / `branch.<name>.remote`
- `src/main/ipc/worktree-content-origin.ts:17-22` — reads the marker only for a named base
- `src/main/ipc/worktree-remote.ts:1336-1345` — SSH marker write goes through `git.markRemoteOrcaCreated`
- `src/main/providers/ssh-git-worktree-provider.ts:158-172` — old relay: method-not-found → warning, marker never set

## Required outcome
- A fork remote Orca itself created must not let a by-name base be classified first-party, even when the marker RPC did not land.

## Open questions for the human
- Is the old-relay + by-name-base path acceptable as a known limitation, or should classification fall back to comparing the named remote's URL against the repository's own remotes?

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

const legacyFile = join(configDir, '.config.json')
const configFile = existsSync(legacyFile)
? legacyFile
: claudeAuth.envPatch.CLAUDE_CONFIG_DIR

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.

WSL resolution ignores a launch-env CLAUDE_CONFIG_DIR override. This branch keys the config file only off claudeAuth.envPatch.CLAUDE_CONFIG_DIR and never consults env. When a WSL launch carries CLAUDE_CONFIG_DIR from the Claude agent env (visible to Orca and forwarded into the guest via WSLENV), the guest reads $CLAUDE_CONFIG_DIR/.claude.json while system WSL auth has envPatch: {} and this writes <guest-home>/.claude.json — the grant silently misses and Claude still asks. The non-WSL branch at lines 80-89 does read the same override out of env, so the two disagree.

Technical details
# WSL branch should resolve the config file the guest will read

## Affected sites
- `src/main/claude/claude-worktree-trust-spawn.ts:67-71` — config file chosen from `claudeAuth` only; `env` is unused
- `src/main/claude/claude-worktree-trust-spawn.ts:80-89` — host branch honors `env.CLAUDE_CONFIG_DIR`
- `src/main/claude-accounts/runtime-auth/runtime-auth-preparation.ts:44-55` — system WSL prep has `envPatch: {}`
- `src/main/providers/local-pty-windows-spawn-environment.ts:54-57` — forwards `CLAUDE_CONFIG_DIR` into the guest

## Required outcome
- For a WSL launch whose effective env carries a guest `CLAUDE_CONFIG_DIR`, resolve the UNC path for that dir (the `wslDistro` argument already names the distro) so grant/revoke act on the file the guest reads, instead of falling back to the guest home.

## Open questions for the human
- Is a user-set `CLAUDE_CONFIG_DIR` meant to be out of scope for WSL (like the documented shell-rc limitation), or should this branch honor the launch env the way the host branch already does?

@brennanb2025
brennanb2025 marked this pull request as draft September 29, 2026 07:23
… > Agents

Replace the Claude-only worktree trust toggle with a single setting,
agentWorkspaceTrustEnabled (on by default; unreleased, so no migration).
The row says what it does for every agent: agents Orca starts skip their
"trust this folder?" prompt in that worktree or folder, turning it off
stops new trust while existing trust stays, and while it is off unattended
launches (orchestration workers, automations, the phone) stop at the
agent's trust question until someone answers.

Translations for es/fr/ja/ko/zh. Also restores the `awaitingUnnamed` chat
catalog keys an earlier merge of main dropped from this branch.
…PTY spawn

Every Orca-started agent PTY passes through one of the two spawn builders
with its declared launchAgent, which survives setup-script wrapping. The
builders now call one hook that, for a fresh launch (never a reattach or
restored pane) with the setting on, applies the agent's trust preset to
the worktree, folder workspace or main checkout it starts in.

- One dispatcher, applyAgentWorkspaceTrust(preset, workspacePath, launch
  context), carries what a writer needs: the final spawn env, the Claude
  managed-account auth prep, the WSL distro and the SSH connection.
- Claude joins the presets on both the claude and claude-agent-teams
  entries. Its writer stays grant-only in claude-folder-trust-file.ts:
  the file Claude reads (CLAUDE_CONFIG_DIR / custom-OAuth suffix / legacy
  .config.json / a WSL guest's own file), Claude's <file>.lock never
  broken and taken only when a write is due, atomic temp+rename keeping
  mode and symlinks, never creating the file, NFC + realpath keys.
- SSH Claude launches forward the optional claudeFolderTrust spawn field
  so the relay grants with its own spawn env; old relays ignore it and
  Claude asks. Other presets keep the SFTP writer. A WSL launch never
  writes the Windows home: non-Claude presets skip it, Claude writes the
  guest's file or nothing.
- Codex keeps the 20 s deadline its shared config lane needs; every other
  preset gets 1.5 s. A miss means the agent asks; trust bookkeeping never
  fails or blocks a launch.

Removes the Claude-only machinery this replaces: the eligibility/host/
lifecycle/spawn modules, the persisted creation content-origin field and
its classification, revoke-on-removal, the setting-off sweep, the
claudeTrust.converge relay method and the Agent Teams leader special case
(the leader pane now spawns through the hook with the claude preset).
The agent config types move to tui-agent-config-types.ts so the config
table stays under the line budget.
…ok replaces

The spawn hook is now the only owner of agent folder trust, so remove
every other writer:

- the agentTrust:markTrusted IPC channel, its preload bridge and types,
  and all renderer callers (agent-trust-preflight and its callers in the
  background session, work-item direct launch, session continuation,
  worktree creation, folder workspace composer and session fork);
- the main pre-spawn sites: the createdWithAgent preflight in
  worktree-remote.ts, markLocalWorktreeTrusted/markRemoteWorktreeTrusted
  and the runtime's markWorkspaceTrustedForAgent family with the
  markTrusted ports of the runtime create flows;
- Codex's own launch-prep and resume-prep trust writes.

Each of those launches reaches a spawn builder with launchAgent set, so
the hook covers it. This also fixes a live gap: the worktree-remote.ts
copy of the preset switch omitted Antigravity, so an agy agent started
from a desktop worktree create still asked; the single dispatcher covers
it. Trust is also written on the host the PTY actually spawns on, which
removes the #11163 class of writing the wrong host's config.
…e spawn waits for trust

The builder test passed untyped args (a string launchAgent) and cast its deps,
which failed tc:node. It now builds both spawn states from a fully typed deps
fixture and a typed restored pane, with no casts.

Adds a case that holds the trust write pending and checks the builder does not
finish until it settles, the ordering the deleted renderer and launch-prep
tests used to cover.
The dispatcher gave every non-Codex preset a 1.5 s budget, including the SSH
writers for Cursor, Copilot and Qoder, which make several round trips over the
link. Before this PR those writes had 20 s (desktop) or no limit (runtime), so
on a slow link an unattended SSH worker would now stop at the agent's trust
question. SSH writes get the 20 s deadline back; local non-Codex writers keep
the short budget, and Codex keeps 20 s.

The relay's Claude grant keeps the short budget: it writes the relay host's own
disk and does not cross the link.
A folder workspace can be the user's home folder or a disk root. Claude and
Copilot let a trusted folder cover every folder under it, so pre-trusting one
of those would silently trust everything on the machine for those agents.

One check, isHomeOrFilesystemRoot, now refuses them for every preset: the
dispatcher checks roots and this machine's homes (including the spawn env's
HOME and a cached WSL guest home), the SSH writer checks the remote home it
already resolves, and the relay checks its own home. The agent then asks, as
it would without Orca.
…ed trust

The spawn hook replaced the trust writes in Codex launch prep and resume prep,
which left the fields that fed them unread: CodexHomeLaunchContext.workspacePath
and .launchAgent, the resume prep's workspacePath, and the structured Codex
launch input's workspacePath (plus the extra target lookup that produced it).
Remove them and their plumbing; unavailableManagedHomePath stays.

Also removes test stubs of runtime trust methods this PR deleted, whose
not-called assertions could no longer fail, and two comments that still
described the old trust preflight.
…t tests

The agent-session trust gate still listed three test files this PR deleted
(the renderer preflight, the Codex launch-prep deadline and the e2e trust
completion suites), so check:reliability-gates, which runs in PR CI and in
pnpm lint, failed on missing files. Its invariant also described the deleted
IPC handler and pre-spawn writers.

The gate now covers what replaced them: the spawn builders holding the spawn
until trust settles, the fresh-launch and setting gates, the per-preset
deadlines, and the home and root refusal.
On a Windows SSH host whose pane shell is wsl.exe, Claude runs inside the WSL
guest and reads the guest's config. The relay still granted trust in the
Windows host's own .claude.json, writing the Windows home for a WSL launch,
which the local path never does. The relay now skips the grant there, so that
Claude asks, as a local WSL launch does when Orca cannot reach the guest file.
Both spawn builders awaited the trust hook on every spawn, including plain
shells, reattaches and agents without a preset. Awaiting even a resolved
promise adds microtask ticks ahead of the pane-spawn reservation check, and
this handler already keeps non-Codex spawns off an await because an extra tick
reorders those reservation races.

The hook now returns null when there is nothing to write, and the builders
await only a real trust write.
@brennanb2025
brennanb2025 marked this pull request as ready for review September 29, 2026 13:03
Comment on lines +51 to +55
export function getLocalCodexTrustConfigFiles(): string[] {
return [
join(getOrcaManagedCodexHomePath(), 'config.toml'),
join(getSystemCodexHomePath(), 'config.toml')
]

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 Managed Codex home stays untrusted. When a managed account launches Codex from its own CODEX_HOME, this list writes trust only to the shared Orca home and ~/.codex. Launch preparation has already copied the account’s config before this write, so the selected home does not receive the grant and an unattended launch can stop at Codex’s trust question.

@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: 1c626dca-7f7f-480d-95ac-e7a71516b049

📥 Commits

Reviewing files that changed from the base of the PR and between c5babd0 and e032341.

📒 Files selected for processing (127)
  • config/reliability-gates.jsonc
  • docs/reference/qoder-integration.md
  • src/main/agent-trust-presets.test.ts
  • src/main/agent-trust-presets.ts
  • src/main/agent-trust-write-deadline.ts
  • src/main/agent-workspace-trust-guard-failure.test.ts
  • src/main/agent-workspace-trust-spawn.test.ts
  • src/main/agent-workspace-trust-spawn.ts
  • src/main/agent-workspace-trust.test.ts
  • src/main/agent-workspace-trust.ts
  • src/main/claude/claude-folder-trust-file.test.ts
  • src/main/claude/claude-folder-trust-file.ts
  • src/main/codex-accounts/runtime-home-read-only-launch-resolution.test.ts
  • src/main/codex/codex-home-paths.ts
  • src/main/codex/codex-trust-config-concurrent-launch.test.ts
  • src/main/execution-host-workspace-trust.test.ts
  • src/main/execution-host-workspace-trust.ts
  • src/main/ipc/agent-trust.ts
  • src/main/ipc/pty-daemon-spawn-agent-home-env.test.ts
  • src/main/ipc/pty-ipc-daemon-provider-fixtures.ts
  • src/main/ipc/pty-ipc-spawn-drivers.ts
  • src/main/ipc/pty-spawn-env-agent-overlays.test.ts
  • src/main/ipc/pty/host-env/codex-resume.ts
  • src/main/ipc/pty/host-env/types.ts
  • src/main/ipc/pty/ipc/spawn-env-codex.ts
  • src/main/ipc/pty/ipc/spawn-options.ts
  • src/main/ipc/pty/ipc/spawn-types.ts
  • src/main/ipc/pty/provider/local-configure.ts
  • src/main/ipc/pty/runtime/controller-deps.ts
  • src/main/ipc/pty/runtime/spawn-options.ts
  • src/main/ipc/pty/runtime/spawn-preflight.ts
  • src/main/ipc/pty/spawn-options-agent-workspace-trust.test.ts
  • src/main/ipc/register-core-handlers/register-core-handlers.test.ts
  • src/main/ipc/register-core-handlers/register-core-handlers.ts
  • src/main/ipc/worktree-remote.ts
  • src/main/providers/pty-provider-contract.ts
  • src/main/providers/ssh-pty-spawn-request.ts
  • src/main/qoder/workspace-trust.ts
  • src/main/remote-agent-trust-presets.test.ts
  • src/main/remote-agent-trust-presets.ts
  • src/main/runtime/agent-terminal-launch-host.test.ts
  • src/main/runtime/agent-terminal-startup-prompt.test.ts
  • src/main/runtime/managed-worktree-create-execution-host.test.ts
  • src/main/runtime/orca-runtime-activate-managed-worktree.ts
  • src/main/runtime/orca-runtime-agent-session-operation.test.ts
  • src/main/runtime/orca-runtime-create-agent-session.ts
  • src/main/runtime/orca-runtime-create-managed-remote-worktree.ts
  • src/main/runtime/orca-runtime-create-managed-worktree.ts
  • src/main/runtime/orca-runtime-get-agent-session-execution-namespace.ts
  • src/main/runtime/orca-runtime-get-structured-agent-session-create-support.ts
  • src/main/runtime/orca-runtime-preserved-branch-cleanup.ts
  • src/main/runtime/orca-runtime-resolve-mobile-session-terminal-command.ts
  • src/main/runtime/orca-runtime-resolve-worktree-removal-target.ts
  • src/main/runtime/orca-runtime-state-fields.ts
  • src/main/runtime/orca-runtime-structured-agent-session-create-intent.test.ts
  • src/main/runtime/orca-runtime-terminal-create-deduplication.ts
  • src/main/runtime/orca-runtime-tests/terminal-creation-and-readiness-part-02.spec.ts
  • src/main/runtime/orca-runtime-tests/terminal-creation-and-readiness-part-03.spec.ts
  • src/main/runtime/orca-runtime-tests/worktree-setup-and-startup-part-05.spec.ts
  • src/main/runtime/runtime-folder-worktree-create.test.ts
  • src/main/runtime/runtime-folder-worktree-create.ts
  • src/main/runtime/runtime-local-worktree-terminal-startup.test.ts
  • src/main/runtime/runtime-local-worktree-terminal-startup.ts
  • src/main/runtime/runtime-remote-managed-worktree-create.test.ts
  • src/main/runtime/runtime-remote-managed-worktree-create.ts
  • src/main/runtime/runtime-worktree-agent-startup.test.ts
  • src/main/runtime/runtime-worktree-agent-startup.ts
  • src/main/runtime/structured-agent-account-home.ts
  • src/main/startup/codex-launch-preparation.ts
  • src/main/startup/codex-launch-trust-write-deadline.test.ts
  • src/main/startup/codex-session-resume-daemon-guard.test.ts
  • src/main/startup/codex-session-resume-launch.ts
  • src/main/startup/main-process-runtime-service.ts
  • src/main/workspace-trust-test-fixtures.ts
  • src/main/wsl-home-cache.ts
  • src/preload/api-types.ts
  • src/preload/api/agent-status-api.ts
  • src/preload/api/agent-trust-bridge.ts
  • src/preload/index.ts
  • src/relay/agent-workspace-trust-spawn-guard-failure.test.ts
  • src/relay/agent-workspace-trust-spawn.test.ts
  • src/relay/agent-workspace-trust-spawn.ts
  • src/relay/pty-handler-agent-workspace-trust.test.ts
  • src/relay/pty-handler.ts
  • src/renderer/src/components/agent-session-continuation/AgentSessionContinuationDialog.tsx
  • src/renderer/src/components/settings/AgentsPane.test.tsx
  • src/renderer/src/components/settings/AgentsPane.tsx
  • src/renderer/src/components/settings/agent-workspace-trust-copy.ts
  • src/renderer/src/components/settings/agents-search.ts
  • src/renderer/src/components/sidebar/folder-workspace-composer-submit.test.ts
  • src/renderer/src/components/sidebar/folder-workspace-composer-submit.ts
  • src/renderer/src/components/terminal-pane/terminal-agent-session-fork.test.ts
  • src/renderer/src/components/terminal-pane/terminal-agent-session-fork.ts
  • src/renderer/src/hooks/settings-navigation-capability-sections.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/agent-background-session-test-state.ts
  • src/renderer/src/lib/agent-trust-preflight.test.ts
  • src/renderer/src/lib/agent-trust-preflight.ts
  • src/renderer/src/lib/codex-session-restart.ts
  • src/renderer/src/lib/launch-agent-background-session-remote.test.ts
  • src/renderer/src/lib/launch-agent-background-session.test.ts
  • src/renderer/src/lib/launch-agent-background-session.ts
  • src/renderer/src/lib/launch-agent-session-continuation.test.ts
  • src/renderer/src/lib/launch-agent-session-continuation.ts
  • src/renderer/src/lib/launch-work-item-direct-agent-routing.test.ts
  • src/renderer/src/lib/launch-work-item-direct-agent-routing.ts
  • src/renderer/src/lib/launch-work-item-direct-route-preparation.ts
  • src/renderer/src/lib/launch-work-item-direct.test.ts
  • src/renderer/src/lib/worktree-creation-flow-execute.ts
  • src/renderer/src/lib/worktree-creation-flow.test.ts
  • src/shared/agent-workspace-trust-spawn-request.ts
  • src/shared/default-global-settings.ts
  • src/shared/global-settings-types.ts
  • src/shared/home-or-filesystem-root.test.ts
  • src/shared/home-or-filesystem-root.ts
  • src/shared/terminal-startup-cwd.ts
  • src/shared/tui-agent-config-types.ts
  • src/shared/tui-agent-config.ts
  • tests/e2e/agent-trust-completion.unit.test.ts
  • tests/e2e/helpers/electron-home-isolation.ts
  • tests/e2e/helpers/electron-home-isolation.unit.test.ts
💤 Files with no reviewable changes (41)
  • src/renderer/src/lib/launch-agent-background-session.test.ts
  • src/preload/index.ts
  • src/main/ipc/register-core-handlers/register-core-handlers.ts
  • src/main/runtime/orca-runtime-create-managed-remote-worktree.ts
  • src/main/runtime/orca-runtime-tests/terminal-creation-and-readiness-part-03.spec.ts
  • src/renderer/src/lib/worktree-creation-flow.test.ts
  • src/main/ipc/register-core-handlers/register-core-handlers.test.ts
  • src/renderer/src/lib/agent-trust-preflight.ts
  • src/main/runtime/runtime-remote-managed-worktree-create.test.ts
  • src/preload/api/agent-trust-bridge.ts
  • src/main/runtime/orca-runtime-resolve-worktree-removal-target.ts
  • src/renderer/src/components/sidebar/folder-workspace-composer-submit.ts
  • src/main/runtime/orca-runtime-get-agent-session-execution-namespace.ts
  • src/preload/api/agent-status-api.ts
  • src/main/ipc/agent-trust.ts
  • src/renderer/src/components/agent-session-continuation/AgentSessionContinuationDialog.tsx
  • src/main/runtime/orca-runtime-resolve-mobile-session-terminal-command.ts
  • src/renderer/src/lib/agent-trust-preflight.test.ts
  • src/renderer/src/lib/launch-agent-background-session.ts
  • src/main/startup/codex-launch-trust-write-deadline.test.ts
  • src/renderer/src/lib/launch-work-item-direct-agent-routing.ts
  • src/renderer/src/components/terminal-pane/terminal-agent-session-fork.ts
  • tests/e2e/agent-trust-completion.unit.test.ts
  • src/main/runtime/runtime-folder-worktree-create.test.ts
  • src/renderer/src/lib/launch-agent-background-session-remote.test.ts
  • src/main/runtime/runtime-local-worktree-terminal-startup.ts
  • src/main/runtime/runtime-local-worktree-terminal-startup.test.ts
  • src/main/ipc/pty/runtime/controller-deps.ts
  • src/main/remote-agent-trust-presets.test.ts
  • src/main/runtime/runtime-remote-managed-worktree-create.ts
  • src/main/runtime/orca-runtime-create-agent-session.ts
  • src/main/ipc/pty/host-env/types.ts
  • src/main/runtime/runtime-folder-worktree-create.ts
  • src/renderer/src/lib/launch-work-item-direct-route-preparation.ts
  • src/main/ipc/pty/ipc/spawn-types.ts
  • src/main/startup/codex-launch-preparation.ts
  • src/renderer/src/lib/agent-background-session-test-state.ts
  • src/main/remote-agent-trust-presets.ts
  • src/renderer/src/lib/launch-agent-session-continuation.test.ts
  • src/renderer/src/lib/launch-agent-session-continuation.ts
  • src/main/runtime/orca-runtime-state-fields.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/ja.json
  • src/renderer/src/i18n/locales/en.json
  • src/renderer/src/i18n/locales/zh.json
  • src/renderer/src/i18n/locales/ko.json
  • src/renderer/src/i18n/locales/fr.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; 9 remain after this review.

Comment on lines +48 to +80
/**
* Pre-trusts `workspacePath` for the agent Orca is about to start, on the host that runs
* it. Never throws and never waits past the preset's deadline: a miss means the agent asks.
*/
export async function applyAgentWorkspaceTrust(
preset: AgentTrustPreset,
workspacePath: string,
context: AgentTrustLaunchContext
): Promise<AgentTrustSpawnFields> {
if (context.connectionId) {
// Why: the SSH host's relay writes on its own disk, under its own homes and the agent's final env.
return { agentWorkspaceTrust: { workspacePath } }
}
// Why: the other writers target this host's home, which a WSL guest agent never reads.
if (preset !== 'claude' && isWslLaunch(workspacePath, context)) {
return {}
}
await applyWorkspaceTrustOnThisHost(preset, workspacePath, () => ({
homes: localHomePaths(workspacePath, context),
claudeConfig: () =>
resolveLocalClaudeTrustConfig({
workspacePath,
env: { ...process.env, ...context.env },
claudeAuth: context.claudeAuth,
wslDistro: context.wslDistro
}),
codexConfigFiles: getLocalCodexTrustConfigFiles,
// Why: Codex queues behind a config lane it shares with Orca's hook installs.
deadlineMs:
preset === 'codex' ? AGENT_TRUST_WRITE_DEADLINE_MS : SHORT_AGENT_TRUST_WRITE_DEADLINE_MS
}))
return {}
}

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.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

🔎 Supported by static analysis

🏁 Script executed:

sed -n '45,80p' src/main/agent-workspace-trust.ts
sed -n '40,65p' src/main/codex/codex-home-paths.ts
sed -n '110,145p' src/main/execution-host-workspace-trust.ts
rg -n 'CODEX_HOME|getLocalCodexTrustConfigFiles' src/main/ipc/pty/provider/local-configure.ts src/main/agent-workspace-trust.ts src/main/codex

Repository: stablyai/orca

Length of output: 22192


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- trust module outline and callers ---'
ast-grep outline src/main/agent-workspace-trust.ts
rg -n -C 5 'applyAgentWorkspaceTrust|applyWorkspaceTrustOnThisHost|getLocalCodexTrustConfigFiles|localHomePaths' src/main src
printf '%s\n' '--- codex home paths and trust writer ---'
ast-grep outline src/main/codex/codex-home-paths.ts
rg -n -C 8 'markCodexProjectTrusted|codexConfigFiles|configFiles|config\.toml|CODEX_HOME' src/main/codex src/main/agent-workspace-trust.ts -g '*.ts'
printf '%s\n' '--- PTY/custom-home launch path ---'
rg -n -C 8 'applyAgentWorkspaceTrust|AgentTrustLaunchContext|CODEX_HOME|customCodexHome|codexHome' src/main/ipc src/main -g '*.ts' | head -n 500

Repository: stablyai/orca

Length of output: 45667


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- agent workspace trust ---'
cat -n src/main/agent-workspace-trust.ts
printf '%s\n' '--- codex home paths ---'
cat -n src/main/codex/codex-home-paths.ts
printf '%s\n' '--- trust writer entrypoints ---'
rg -l 'function markCodexProjectTrusted|export.*markCodexProjectTrusted|codexConfigFiles' src/main -g '*.ts' | sort
printf '%s\n' '--- trust spawn adapter ---'
cat -n src/main/agent-workspace-trust-spawn.ts
printf '%s\n' '--- PTY production callers ---'
rg -l 'applyAgentWorkspaceTrust|registerPtyHandlers|pty:spawn' src/main/ipc -g '*.ts' | sort

Repository: stablyai/orca

Length of output: 25391


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- trust dispatch call sites ---'
rg -n -C 12 'applyAgentWorkspaceTrustToSpawn|applyStructuredCodexWorkspaceTrust' src -g '*.ts'
printf '%s\n' '--- custom CODEX_HOME launch resolution ---'
rg -n -C 12 'getCustomCodexHomeOverrideForLaunch|environmentHomeOverride|custom-home|custom CODEX_HOME|CODEX_HOME.*env|env.*CODEX_HOME' src/main/ipc src/main/codex -g '*.ts' | head -n 700
printf '%s\n' '--- PTY spawn sequencing ---'
rg -n -C 20 'agentWorkspaceTrust|spawnOptionsAgent|applyAgentWorkspaceTrust' src/main/ipc/pty src/main/ipc/pty.ts src/main/ipc -g '*.ts' | head -n 700
printf '%s\n' '--- Codex trust consumer and config contract ---'
rg -n -C 12 'markCodexProjectTrusted|projects\\.|trust_level|config\.toml|runtime home|CODEX_HOME' src/main/agent-trust-presets.ts src/main/codex/codex-config-mirror.ts src/main/codex/codex-trust-config-concurrent-launch.test.ts src/main/execution-host-workspace-trust.test.ts -g '*.ts' | head -n 1000

Repository: stablyai/orca

Length of output: 42877


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- non-test trust call sites ---'
rg -n -C 18 'applyAgentWorkspaceTrustToSpawn|applyStructuredCodexWorkspaceTrust' src -g '*.ts' -g '!*.test.ts'
printf '%s\n' '--- custom-home resolver definitions and callers ---'
rg -n -C 20 'getCustomCodexHomeOverrideForLaunch|environmentHomeOverride|homeRoute|CODEX_HOME' src/main/codex/codex-real-home-path.ts src/main/ipc/pty*.ts src/main/ipc/pty -g '*.ts' -g '!*.test.ts' | head -n 900
printf '%s\n' '--- workspace host and writer contracts ---'
cat -n src/main/execution-host-workspace-trust.ts | sed -n '1,180p'
rg -n -C 20 'markCodexProjectTrusted|function writePreset|codexConfigFiles' src/main/agent-trust-presets.ts src/main/execution-host-workspace-trust.ts

Repository: stablyai/orca

Length of output: 42775


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- exact IPC spawn trust sequence ---'
cat -n src/main/ipc/pty/ipc/spawn-options.ts | sed -n '30,125p'
printf '%s\n' '--- runtime spawn trust sequence ---'
rg -n -C 20 'applyAgentWorkspaceTrustToSpawn' src/main/ipc/pty -g '*.ts' -g '!*.test.ts'
printf '%s\n' '--- final environment construction ---'
rg -n -C 18 'type PtyIpcSpawnState|interface PtyIpcSpawnState|ctx\.env|spawnEnv|buildPtyIpcSpawnOptions' src/main/ipc/pty/ipc src/main/ipc/pty/provider src/main/ipc/pty -g '*.ts' -g '!*.test.ts' | head -n 1000
printf '%s\n' '--- custom-home launch resolver exact source ---'
cat -n src/main/codex/codex-real-home-path.ts | sed -n '1,145p'

Repository: stablyai/orca

Length of output: 42732


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- selected Codex home contract ---'
rg -n -C 20 'getSelectedCodexHomePath|selectedCodexHomePath|getCompatibleSelectedCodexHomePath|resolve.*Codex.*Home' src/main src/shared -g '*.ts' -g '!*.test.ts' | head -n 1200
printf '%s\n' '--- custom-home config references ---'
rg -n -C 12 'custom.*config\.toml|config\.toml.*custom|CODEX_HOME.*config\.toml|config\.toml.*CODEX_HOME|Every config\.toml|configFiles' src/main/codex src/main/agent-trust-presets.ts -g '*.ts' -g '!*.test.ts'
printf '%s\n' '--- changed hunk and related baseline ---'
git diff --unified=25 31012aeb09283dc901a2c7417747e5a081f33cbf -- src/main/agent-workspace-trust.ts src/main/codex/codex-home-paths.ts src/main/execution-host-workspace-trust.ts src/main/agent-trust-presets.ts

Repository: stablyai/orca

Length of output: 42198


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- selected home override consumer ---'
rg -n -C 24 'codexHomePathOverride' src/main -g '*.ts' -g '!*.test.ts'
printf '%s\n' '--- local provider configuration ---'
cat -n src/main/ipc/pty/provider/local-configure.ts | sed -n '1,260p'
printf '%s\n' '--- spawn option/provider types ---'
rg -n -C 15 'codexHomePathOverride|PtySpawnOptions|spawnOptions' src/main/ipc/pty/provider src/main/ipc/pty -g '*.ts' -g '!*.test.ts' | head -n 900

Repository: stablyai/orca

Length of output: 41965


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- selected-home definitions only ---'
rg -n -C 8 'getSelectedCodexHomePath|getCompatibleSelectedCodexHomePath' src/main --glob '*.ts' --glob '!*.test.ts' | grep -E '^[^:]+:[0-9]+|getSelectedCodexHomePath|getCompatibleSelectedCodexHomePath|return|CODEX_HOME|custom|managed|system' | head -n 500
printf '%s\n' '--- provider custom-home selection and final env ---'
cat -n src/main/ipc/pty/provider/local-configure.ts | sed -n '35,115p'
cat -n src/main/providers/local-pty-spawn-environment.ts | sed -n '1,80p'

Repository: stablyai/orca

Length of output: 12875


Write trust to the selected Codex home.

When a fresh local Codex PTY uses a distinct CODEX_HOME, the trust dispatch writes only the managed and system config.toml files. Codex can therefore read the custom home without the new project entry and may show its trust prompt.

Pass the selected home to the trust dispatcher and include <CODEX_HOME>/config.toml in the write list.

Suggested fix
diff --git a/src/main/agent-workspace-trust.ts b/src/main/agent-workspace-trust.ts
@@
 export type AgentTrustLaunchContext = {
   /** The final spawn env, before the host's own process env. */
   env: Record<string, string | undefined> | undefined
+  /** The home selected for this launch, when PTY preparation has resolved one. */
+  codexHomePath?: string | null
@@
-    codexConfigFiles: getLocalCodexTrustConfigFiles,
+    codexConfigFiles: () =>
+      getLocalCodexTrustConfigFiles(context.codexHomePath ?? context.env?.CODEX_HOME),
diff --git a/src/main/codex/codex-home-paths.ts b/src/main/codex/codex-home-paths.ts
@@
-export function getLocalCodexTrustConfigFiles(): string[] {
-  return [
+export function getLocalCodexTrustConfigFiles(codexHomePath?: string): string[] {
+  const configFiles = [
     join(getOrcaManagedCodexHomePath(), 'config.toml'),
     join(getSystemCodexHomePath(), 'config.toml')
   ]
+  const customHome = codexHomePath?.trim()
+  if (customHome) {
+    const customConfig = join(customHome, 'config.toml')
+    if (!configFiles.includes(customConfig)) {
+      configFiles.unshift(customConfig)
+    }
+  }
+  return configFiles
}
diff --git a/src/main/agent-workspace-trust-spawn.ts b/src/main/agent-workspace-trust-spawn.ts
@@
   return applyAgentWorkspaceTrust(preset, workspacePath, {
     env: args.env,
+    codexHomePath: args.codexHomePath,
     claudeAuth: args.claudeAuth,
diff --git a/src/main/ipc/pty/ipc/spawn-options.ts b/src/main/ipc/pty/ipc/spawn-options.ts
@@
     settings: ctx.deps.getSettings?.(),
     env: ctx.spawnEnv,
+    codexHomePath: ctx.selectedCodexHomePath,
     claudeAuth: ctx.claudeAuth,
diff --git a/src/main/ipc/pty/runtime/spawn-options.ts b/src/main/ipc/pty/runtime/spawn-options.ts
@@
     settings: ctx.deps.getSettings?.(),
     env: ctx.env,
+    codexHomePath: ctx.selectedCodexHomePath,
     claudeAuth: ctx.claudeAuth,

export function getAgentWorkspaceTrustDescription(): string {
return translate(
'auto.components.settings.agent-workspace-trust-copy.description',
'Agents Orca starts skip their "trust this folder?" prompt in that worktree or folder, so the project\'s agent hooks and settings run without asking first. Turning this off stops new trust; folders already trusted stay trusted. While it is off, agents Orca starts unattended, such as orchestration workers, automations and agents started from your phone, stop at the trust question until someone answers it.'

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:

sed -n '1,42p' src/renderer/src/components/settings/agent-workspace-trust-copy.ts
sed -n '44,55p' docs/reference/qoder-integration.md
sed -n '15,48p' src/relay/agent-workspace-trust-spawn.ts
sed -n '115,141p' src/main/execution-host-workspace-trust.ts

Repository: stablyai/orca

Length of output: 4801


🏁 Script executed:

printf '%s\n' '--- relevant files ---'
git ls-files | rg '(^|/)(agent-workspace-trust-copy|qoder-integration|agent-workspace-trust|i18n|translation|localization)'
printf '%s\n' '--- trust-copy and Qoder text occurrences ---'
rg -n -i 'Trust the folder when Orca starts an agent|Every launch Orca starts|pre-trusts the workspace|trust this folder|qodercli|qoder' src docs --glob '!**/node_modules/**' | head -240
printf '%s\n' '--- relay trust bindings and preset definitions ---'
rg -n 'TUI_AGENT_CONFIG|preflightTrust|AGENT_TRUST_INHERITS_FROM_A_HOME|wouldTrustAHome|antigravity|wslShell' src/relay src/main src --glob '*.ts' | head -260
printf '%s\n' '--- changed files in PR ---'
git diff --stat 31012aeb09283dc901a2c7417747e5a081f33cbf e0323411778075e9238eaae448af559dd29bc564 -- src/renderer/src/components/settings/agent-workspace-trust-copy.ts docs/reference/qoder-integration.md src/relay/agent-workspace-trust-spawn.ts src/main/execution-host-workspace-trust.ts

Repository: stablyai/orca

Length of output: 41575


🏁 Script executed:

printf '%s\n' '--- execution-host trust implementation ---'
cat -n src/main/execution-host-workspace-trust.ts | sed -n '1,175p'
printf '%s\n' '--- trust preset configuration and home policy ---'
cat -n src/main/agent-trust-presets.ts | sed -n '1,155p'
cat -n src/shared/tui-agent-config.ts | sed -n '1,90p'
printf '%s\n' '--- relevant trust tests ---'
cat -n src/main/execution-host-workspace-trust.test.ts | sed -n '1,145p'
cat -n src/relay/agent-workspace-trust-spawn.test.ts | sed -n '190,230p'
printf '%s\n' '--- documentation diff ---'
git diff --unified=12 31012aeb09283dc901a2c7417747e5a081f33cbf e0323411778075e9238eaae448af559dd29bc564 -- docs/reference/qoder-integration.md src/renderer/src/components/settings/agent-workspace-trust-copy.ts

Repository: stablyai/orca

Length of output: 29999


Qualify the prompt-free trust guarantee.

The setting description omits reachable exceptions. Antigravity over SSH, non-Claude agents in WSL, and Qoder launches from a home folder or its ancestor can still show the trust prompt. Apply the same qualification to the English, Spanish, French, Japanese, Korean, and Chinese catalog entries.

Suggested copy update
-    'Agents Orca starts skip their "trust this folder?" prompt in that worktree or folder, so the project\'s agent hooks and settings run without asking first. Turning this off stops new trust; folders already trusted stay trusted. While it is off, agents Orca starts unattended, such as orchestration workers, automations and agents started from your phone, stop at the trust question until someone answers it.'
+    'For supported launch paths, agents Orca starts skip their "trust this folder?" prompt in that worktree or folder, so the project\'s agent hooks and settings run without asking first. Antigravity over SSH, non-Claude agents started in WSL, and Qoder agents started in a home folder or an ancestor of a home folder can still show the trust prompt. Turning this off stops new trust; folders already trusted stay trusted. While it is off, agents Orca starts unattended, such as orchestration workers, automations and agents started from your phone, stop at the trust question until someone answers it.'
-Every launch Orca starts (New Tab, workspace and draft launches, automations)
-pre-trusts the workspace at spawn while the agent-wide "Trust the folder when
-Orca starts an agent" setting is on. A hand-typed `qodercli` in a plain terminal
-can still show Qoder's trust dialog.
+Supported Orca launches (New Tab, workspace and draft launches, automations)
+pre-trust the workspace at spawn while the agent-wide "Trust the folder when
+Orca starts an agent" setting is on. Qoder does not pre-trust a workspace that
+is a home folder or an ancestor of a home folder. Those launches can still show
+Qoder's trust dialog. A hand-typed `qodercli` in a plain terminal can also show
+Qoder's trust dialog.
📝 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
'Agents Orca starts skip their "trust this folder?" prompt in that worktree or folder, so the project\'s agent hooks and settings run without asking first. Turning this off stops new trust; folders already trusted stay trusted. While it is off, agents Orca starts unattended, such as orchestration workers, automations and agents started from your phone, stop at the trust question until someone answers it.'
'For supported launch paths, agents Orca starts skip their "trust this folder?" prompt in that worktree or folder, so the project\'s agent hooks and settings run without asking first. Antigravity over SSH, non-Claude agents started in WSL, and Qoder agents started in a home folder or an ancestor of a home folder can still show the trust prompt. Turning this off stops new trust; folders already trusted stay trusted. While it is off, agents Orca starts unattended, such as orchestration workers, automations and agents started from your phone, stop at the trust question until someone answers it.'

@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 launch-path migration and the guard hold up under a full read. One narrow edge in the folder-trust guard and a comment nit are inline below.

Reviewed changes

  • One spawn-time trust step: applyAgentWorkspaceTrustToSpawn runs in both PTY spawn builders (ipc/pty/ipc/spawn-options.ts, ipc/pty/runtime/spawn-options.ts) and now also backs the structured-Codex path, replacing the deleted renderer preflightAgentTrust and its seven callers, the agentTrust:markTrusted IPC + preload bridge, markLocal/RemoteWorktreeTrusted, markWorkspaceTrustedForAgent and the Codex launch-prep writes. I traced each deleted site to a spawn that declares launchAgent with a defined command, so none lose coverage.
  • One dispatcher/host writer: applyAgentWorkspaceTrust routes SSH to the relay and everything else through applyWorkspaceTrustOnThisHost, which picks the stored path, applies the breadth guard for the inheriting agents (Claude, Copilot, Qoder) and calls the existing per-preset writers. The new Claude writer is lock-respecting, atomic and never creates a missing config; markCodexProjectTrusted now takes the config-file list. The guard's segment-boundary check means home / ancestor-of-home / root / .. / symlink / drive-case / WSL-UNC-alias spellings are refused without false-positives.
  • SSH relay: a new optional agentWorkspaceTrust field rides the existing pty.spawn request and the relay writes on its own disk before the process starts, replacing the multi-round-trip SFTP writer. Old relays ignore the field.
  • Setting + UI: agentWorkspaceTrustEnabled defaults on, sits in Settings → Agents, and is hidden from paired web clients and their settings search.
  • Testing: new unit suites for both builders, the dispatcher, the host writer, the Claude writer (mode, symlink, corrupt file, held lock, a 12-way burst), the relay handler and the structured-Codex intent; the old e2e unit file is deleted and the e2e harness now strips CLAUDE_CONFIG_DIR.

ℹ️ Nitpicks

  • src/relay/agent-workspace-trust-spawn.ts:43 says "each preset gets the local budget", but deadlineMs is the 1.5s short budget for every preset including Codex. The PR body and the reliability gate both describe the 1.5s SSH budget as intended, so the comment is the misleading part; say "the short budget", or mirror the local preset === 'codex' ? long : short split if that was the actual intent.

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

const wslWorkspace = parseWslUncPath(workspacePath)
// Why: a WSL guest agent reads trust under the guest's home; an uncached one means write nothing.
return wslWorkspace
? [getCachedWslHome(wslWorkspace.distro)]

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.

The breadth guard compares the stored path against the homes in their host spelling, but for a WSL launch these two sides can land in different path spaces. getCachedWslHome returns whatever getWslHome cached, which is a Windows UNC path for a normal guest home but a drive path when the guest's $HOME is a drvfs mount (toWindowsWslPath prefers toWindowsWslDrivePath). Meanwhile the writer stores the Linux path via toClaudePath. When they differ, normalizeRuntimePathForComparison never bridges c:/users/alice with //wsl/<distro>/mnt/c/Users/alice, so a home or an ancestor can slip past the guard.

Technical details
# WSL home spelling diverges from the stored key in the breadth guard

## Affected sites
- `src/main/agent-workspace-trust.ts:41-45` — `localHomePaths` keys the guard home on `getCachedWslHome(distro)`, the host spelling.
- `src/main/claude/claude-folder-trust-file.ts:263-282` — the WSL writer maps the workspace through `toClaudePath` (`parseWslUncPath(...).linuxPath`) and stores that Linux key.
- `src/main/wsl.ts:274-297` — `getWslHome` caches `toWindowsWslPath(home, distro)`, which for `/mnt/<drive>/...` returns a drive path (`C:\Users\alice`) rather than the UNC alias.

## Preconditions (all required, so this is narrow)
1. The WSL guest's `$HOME` is under `/mnt/<drive>` (uncommon; default is `/home/<user>`).
2. A managed WSL Claude account is selected, so `ClaudeRuntimeAuthPreparation` returns `runtime: 'wsl'` with a `wslLinuxConfigDir` and a config dir the writer can target. The system-WSL branch bails when `parseWslUncPath(getWslHome(distro))` is null, so a non-managed WSL Claude launch writes nothing here.
3. The workspace is the drvfs home itself or a folder above it, spelled as a WSL UNC path.

## Required outcome
- The guard must refuse a drvfs guest home or an ancestor of it exactly as it refuses a `/home/...` guest home, i.e. both sides of `wouldTrustAHome` must be expressed in one path space.

## Suggested approach (optional)
- Add the workspace distro's home in the same space as the workspace to `localHomePaths` (for example the UNC alias of the cached home), or run the guard over the `toClaudePath`-mapped forms so it compares `//wsl/<distro>/...` to `//wsl/<distro>/...`.

## Open questions for the human (optional)
- Is a managed WSL Claude account with a `$HOME` on `/mnt/<drive>` a configuration Orca intends to support? If not, a note that the guard is best-effort for that layout may be enough.

…orktree-trust

# Conflicts:
#	src/main/startup/codex-launch-trust-write-deadline.test.ts
#	src/main/startup/codex-session-resume-launch.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: 3630002f-fdce-48b4-a527-7d107f16ad99

📥 Commits

Reviewing files that changed from the base of the PR and between e032341 and 0291db9.

📒 Files selected for processing (17)
  • src/main/ipc/pty/host-env/types.ts
  • src/main/ipc/pty/ipc/spawn-env-codex.ts
  • src/main/ipc/pty/provider/local-configure.ts
  • src/main/ipc/pty/runtime/spawn-preflight.ts
  • src/main/startup/codex-launch-preparation.ts
  • src/main/startup/codex-launch-trust-write-deadline.test.ts
  • src/main/startup/codex-session-resume-launch.ts
  • src/relay/pty-handler.ts
  • src/renderer/src/components/settings/AgentsPane.test.tsx
  • src/renderer/src/components/settings/agent-workspace-trust-copy.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
💤 Files with no reviewable changes (4)
  • src/main/startup/codex-launch-trust-write-deadline.test.ts
  • src/main/ipc/pty/host-env/types.ts
  • src/main/startup/codex-launch-preparation.ts
  • src/main/startup/codex-session-resume-launch.ts
🚧 Files skipped from review as they are similar to previous changes (6)
  • src/renderer/src/i18n/locales/ko.json
  • src/renderer/src/i18n/locales/en.json
  • src/renderer/src/i18n/locales/ja.json
  • src/renderer/src/i18n/locales/fr.json
  • src/renderer/src/i18n/locales/es.json
  • src/renderer/src/i18n/locales/zh.json

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

Comment thread src/relay/pty-handler.ts
Comment on lines +1926 to +1928
await applyRelayAgentWorkspaceTrust(params.agentWorkspaceTrust, launchAgent, spawnEnv, {
wslShell: isRelayWslShell(shell)
})

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.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Check cancellation before writing persistent trust.

If the client disconnects during loadPty() or buildSpawnEnv(), this call can still persist the folder’s trust record. The check at Line 1976 then rejects the launch with client_disconnected. No agent starts, but the folder remains trusted.

Check context.signal.aborted and context.isStale() before this call. Keep the existing check before native spawn.

@brennanb2025
brennanb2025 merged commit 21d4ae9 into main Sep 29, 2026
41 of 43 checks passed
brennanb2025 added a commit that referenced this pull request Sep 29, 2026
…3789, #23812, #23852) into brennanb2025/codex-home-single-writer

#23744 moves every agent's folder pre-trust into the PTY spawn hook (and
the structured Codex chat create), removing Codex's launch-prep and
resume-prep trust writes. markCodexProjectTrusted now takes the config
files to write.

Conflicts:
- agent-trust-presets.ts: #23744's configFiles signature and nested lane
  acquisition, with this branch's lane rationale (hook installs read and
  rewrite across awaits); main's "capture->restore window" wording
  described the grant snapshot this branch removed.
- agent-trust-write-deadline.ts: the Codex writer waits only on
  managed-home installs' inline grant; the real-home background approval
  holds no lane. #23744's SSH/SFTP writer is gone, so it is no longer
  named; its 1.5 s short deadline is kept.
- codex-trust-config-concurrent-launch.test.ts: this branch's tests
  (a launch's write lands while a grant session runs; the renamed
  sibling-failure case) with #23744's new call signature.

Outside the conflicts: codex-launch-during-real-home-grant.test.ts passed
launchAgent/workspacePath into launch prep, which #23744 removed; its
launch helper now runs launch prep and then applyAgentWorkspaceTrust, as
the spawn builder does, so it still proves a launch and its project trust
land while the real-home approval hangs.
Jinwoo-H added a commit that referenced this pull request Sep 29, 2026
Keeps #23744's exported resolveCodexProjectTrustRoot and its
configFiles-based markCodexProjectTrusted, with this branch's
Codex-mirroring root rule.

Drops main's "trusts the main repository root for a linked worktree
without reading commondir" test: its fixture has no commondir, a layout
Codex's resolve_root_git_project_for_trust rejects (it keys trust on the
worktree), so it encoded behaviour Codex does not have. The branch's
real-git layout tests cover the case instead.

linkGitWorktree now writes commondir as git does, so the
execution-host trust tests describe a worktree Codex would recognise.
brennanb2025 added a commit that referenced this pull request Sep 30, 2026
Main (#23744, #23937) moved every agent trust write into one dispatcher,
applyWorkspaceTrustOnThisHost, run on the host that starts the agent: main
for local and WSL launches, the SSH relay for remote ones. The desktop SFTP
trust writer, the trust IPC and the per-call-site launch-prep writes are gone.

Re-applied on top:
- markCodexProjectTrusted attempts every config.toml it is given, so a file
  Orca refuses to edit never leaves another Codex home untrusted.
- The dispatcher reports refused Codex config edits once per file and message.
- smol-toml is loaded with a literal require so the relay's esbuild bundle
  inlines it; relay hosts have no node_modules, and createRequire made the
  relay fail to load.
- Remote trust tests ported to the relay writer; hook-status log-once test
  moved out of the test file main deleted.
brennanb2025 added a commit that referenced this pull request Sep 30, 2026
…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.
Jinwoo-H added a commit that referenced this pull request Sep 30, 2026
…er (#23929)

* feat(settings): add a setting to run Codex terminals on Codex's shared server

Off injects ORCA_CODEX_ISOLATE=0 into new terminals on every host (local,
daemon, SSH relay, WSL), which the codex shell wrapper from #23900 reads
to skip --no-daemon. On (the default) injects nothing.

* feat(terminal): announce per-terminal Codex servers once

Shows a one-time toast the first time a Codex terminal starts, with an
Open Settings action that lands on the new Codex server setting. The
seen flag persists in UI state and is set when the toast is shown.

* fix(settings): drop the status warning from the Codex server setting

* fix(terminal): simplify the Codex shared-server notice

* fix(terminal): say agent status in the Codex notice

* fix(settings): hide the Codex server setting from paired web search

Gives its search entry an id and gates it with
includeCodexTerminalServerIsolation, as the other host-only rows are, so
a paired web client cannot find a row it never renders. Its search
keywords now use catalogued agents-search keys instead of missing ones;
CODEX_ISOLATE_ENV is no longer exported; the toast id comment names the
case it guards.

* test(settings): assert the Codex server search gate through the metadata builder

Calling getAgentsPaneSearchEntries directly stayed green with the web
gate deleted; the metadata builder test fails without it.

Backport: #23744 (workspace trust setting) is not on this branch, so its adjacent setting, search entry and test are left out.

(cherry picked from commit a0abcb6)
kiwidream added a commit to SwapLabsInc/orca that referenced this pull request Sep 30, 2026
Upstream stablyai#23744 removed runtime.markWorkspaceTrustedForAgent, which the host
resume called while preparing its launch. On the merged tree the call threw
and every resume fell back to a plain shell. A resume re-opens a conversation
that already ran in that folder, so it drops its own trust write, the input
that carried it and the tests that pinned it. The spawn itself goes through
upstream's spawn builder like upstream's own ensureAgentSession resume.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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