Repository navigation
fix(cli): orca file open no longer moves your view unless you pass --focus - #24244
Conversation
…w and are for user requests only Refs #9944
|
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
Help-text-only change with no behavioral surface, so this is a coverage confirmation rather than a deep review.
- Root help summaries (
src/cli/root-help-text-primary.ts) —file open/file diff/file open-changednow say "Show … to the user (switches Orca to its worktree)" instead of "Open … in the Orca editor". - Per-command summaries (
src/cli/specs/file.ts) — reworded to "Show … to the user" for all three commands. - New leading
notesline on all three specs — states the command switches the Orca window to the target worktree, interrupts the user, and should run only when the user asked to see it.
I confirmed no test or docs page pins the old or new wording (grep across the repo and docs/ found no references), and the hand-written CLI docs in docs/site/content/docs/cli/reference.mdx and overview.mdx describe these commands in prose without restating the summaries, so nothing diverges.
DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (2)
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 4 remain after this review. 📝 WalkthroughWalkthroughFile commands now accept Priority: ⬇️ Low Merge Risk: ⚪ Minimal · up to File opens are intended to leave the current view unchanged unless Security Architecture ReviewSecurity architecture risk: 🔵 Low · up to The change controls whether opening a file moves the current view. Existing file-target checks remain in place, and no expanded file-access privilege was identified. Risk is low, although authorization and mixed-version recovery behavior were not fully verified. Retained concerns Security review detailsSecurity Blast Radius
Trust Boundaries and Controls
Resilience and Maintainability Implications
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…ess --focus `orca file open`, `file diff` and `file open-changed` always switched the desktop to the target worktree, selected the tab and revealed it in the sidebar. An agent skill that opens its answer pulled the user out of whatever they were typing in (#9944), and a phone opening a file moved the desktop too. The commands now add the tab in its worktree without changing anything on screen, including when that worktree is the one being viewed: the new tab is added to the tab bar but the active tab, tab type and focus stay put. In a worktree the user is not viewing, the tab becomes that worktree's selection so it is in front when they go there. `--focus` keeps today's behavior. files.open / files.openDiff take an optional `navigation` target (the existing RUNTIME_NAVIGATION_TARGETS vocabulary); the CLI sends 'all' for --focus, like `worktree create --activate`, and nothing otherwise. The renderer moves the host view only when the target reaches the host; a missing field (phones, older CLIs) leaves it still. Editor opens for a worktree other than the on-screen one no longer write the global activeFileId/activeTabType. Refs #9944
| if (activate) { | ||
| // Why: sidebar preview reopens focus the tab without promoting it; explicit activation still promotes previews by default. | ||
| state.activateTab?.(existing.id, { preservePreview: isPreview }) | ||
| } | ||
| return existing.id |
There was a problem hiding this comment.
Preview tab remains replaceable When
orca file open without --focus reopens a file that is already a preview, openFile marks the file as non-preview, but this path skips activateTab and leaves its tab marked as a preview. The next preview open removes that tab while leaving the file in openFiles, so the existing editor tab disappears and an orphaned file record remains.
There was a problem hiding this comment.
ℹ️ No code issues found — one description mismatch to correct.
Reviewed changes
This re-review covers commits 4fafdcc and d00ffcd, which turn the earlier help-text-only change into a behavior change: orca file open / file diff / file open-changed no longer move the Orca window by default, and a new --focus flag opts back in.
- Added
--focusand reworded the root help, command specs, and CLI docs so the default reads "open as a tab without changing your view". - Threaded an optional
navigationparam throughfiles.open/files.openDiffvia a newFileOpenTabschema, down to the renderer notifier. - Renderer moves the host view only for
navigation: 'all' | 'host'; other or absent values open the tab in its worktree without touching the current view. - Gated the editor store's global active-file write on
worktreeId === activeWorktreeId, with a newactivateoption to add a tab without selecting it. - Added tests across the CLI, RPC, window lifecycle, and renderer bridge/store.
ℹ️ PR description describes the opposite of what the code now does
The PR body still says "Scope: CLI help text only", "No behavior change", "This PR keeps the behavior and makes the help text say what the commands do", and "Notes: Security, cross-platform, SSH, mobile, performance: no runtime change." The head commits do the opposite: they change these commands to leave your view alone by default, add --focus to switch it, and change the renderer notifier, RPC schema, and editor store. The title ("file open says it switches your view") is now inverted too.
This is more than tidiness. The body's "Alternative considered" paragraph rejects exactly the per-request switching this branch now implements, and it makes no mention that mobile file-opens (which send no navigation) also stop moving the desktop. A reviewer or merger reading only the description would be approving a different change than the one on the branch.
Technical details
# Stale PR description
## Affected sites
- PR #24244 body — "Scope: CLI help text only ... No behavior change ... keeps the behavior" contradicts `src/cli/handlers/file.ts:120-126` (`getFileOpenNavigation`) and `src/renderer/src/hooks/ipc-events/mobile-terminal-close-ipc-bridge.ts:16-31` (navigation-gated view switch).
- PR #24244 title — "file open says it switches your view and is only for when you ask to see a file" describes the pre-`4fafdcc` wording.
- PR body "Notes" — "mobile ... no runtime change" contradicts the new `mobile-terminal-close-ipc-bridge.test.ts` case for phone opens with no navigation field.
## Required outcome
- Title and body describe the shipped behavior: default opens a tab without moving the view; `--focus` moves it.
- Body notes the mobile/paired-client behavior change (the host desktop no longer moves on a phone file-open).
- The LoC summary and checklist sections reflect the now ~33-file diff.
## Open questions for the human (optional)
- Is this still intended as a docs change, or should it be re-scoped/retitled as a CLI + renderer behavior change?DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Advanced
Run ID: 35adae03-127b-4db9-aa45-abf1292f21d3
⛔ Files ignored due to path filters (1)
src/shared/rpc-contract/rpc-params-catalog.generated.tsis excluded by!**/*.generated.*
📒 Files selected for processing (32)
docs/site/content/docs/cli/overview.mdxdocs/site/content/docs/cli/reference.mdxsrc/cli/handlers/file.test.tssrc/cli/handlers/file.tssrc/cli/root-help-text-primary.tssrc/cli/root-help-text-secondary.tssrc/cli/specs/file.tssrc/main/runtime/orca-runtime-file-commands.tssrc/main/runtime/orca-runtime-files-mobile-explorer-reads.test.tssrc/main/runtime/rpc/methods/files-open-navigation.test.tssrc/main/runtime/rpc/methods/files.test.tssrc/main/runtime/rpc/methods/files.tssrc/main/runtime/runtime-file-command-host.tssrc/main/runtime/runtime-file-commands-constructor.tssrc/main/runtime/runtime-notifier-contract.tssrc/main/runtime/runtime-rpc-mobile-method-allowlist.test.tssrc/main/window/runtime-window-lifecycle-file-open.test.tssrc/main/window/runtime-window-lifecycle.tssrc/preload/api/ui-bridge-clipboard-and-window-controls.tssrc/preload/api/ui-bridge-terminal-and-session-tabs.tssrc/preload/api/ui-command-event-api.tssrc/renderer/src/hooks/ipc-events/mobile-terminal-close-ipc-bridge.test.tssrc/renderer/src/hooks/ipc-events/mobile-terminal-close-ipc-bridge.tssrc/renderer/src/store/slices/editor-recently-closed-tabs.test.tssrc/renderer/src/store/slices/editor/actions/open-file-action.tssrc/renderer/src/store/slices/editor/actions/open-file-apply.tssrc/renderer/src/store/slices/editor/actions/open-unstaged-diff.tssrc/renderer/src/store/slices/editor/tabs/editor-open-target-group.tssrc/renderer/src/store/slices/editor/tabs/workspace-editor-item.tssrc/renderer/src/store/slices/editor/types/editor-files-slice.tssrc/renderer/src/store/slices/new-markdown.test.tssrc/shared/rpc-contract/files-params.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- src/cli/root-help-text-primary.ts
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 1 remain after this review.
| // Why: only the on-screen worktree owns the main editor; a background or floating open updates only the per-worktree maps. | ||
| ...(worktreeId === FLOATING_TERMINAL_WORKTREE_ID || worktreeId !== state.activeWorktreeId |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🔎 Supported by static analysis
🏁 Script executed:
#!/bin/bash
rg -nP --type=ts -C4 'setActiveWorktree\s*:\s*\(' src/renderer/src/store
rg -nP --type=ts -B6 -A2 '\.(openFile|openDiff)\(' src/renderer/src -g '!**/*.test.ts' | rg -n 'setActiveWorktree|openFile\(|openDiff\(' | head -80Repository: stablyai/orca
Length of output: 3153
🏁 Script executed:
#!/bin/bash
set -e
printf '%s\n' '--- diff ---'
git diff --no-ext-diff --unified=30 3ab3c9239fba5eaa36c3c4ce10aab4cf346ee812 d00ffcd459fd442a0e3b77b2d4ed45a5819416e1 -- src/renderer/src/store/slices/editor/tabs/editor-open-target-group.ts
printf '%s\n' '--- changed file ---'
cat -n src/renderer/src/store/slices/editor/tabs/editor-open-target-group.ts | sed -n '1,180p'
printf '%s\n' '--- setActiveWorktree declaration and implementation ---'
rg -n -C18 'setActiveWorktree\s*[:=]\s*(async\s*)?\(' src/renderer/src/store/slices/worktree-helpers.ts src/renderer/src/store
rg -n -C10 'setActiveWorktree\s*\(' src/renderer/src/store/slices/worktree-helpers.ts src/renderer/src/store | head -240
printf '%s\n' '--- active editor state symbols ---'
rg -n -C8 'active(FileId|TabType)(ByWorktree)?' src/renderer/src/store/slices/editor src/renderer/src/store/slices/worktree-helpers.ts | head -320
printf '%s\n' '--- named caller terms ---'
rg -n -i -C8 'notification|Cmd|Control|Shift|new-markdown|rename|recently.closed|markdown.*link|setActiveWorktree|openDiff|openFile' src/renderer/src/hooks src/renderer/src/store/slices src/renderer/src/components -g '*.ts' -g '*.tsx' | head -500Repository: stablyai/orca
Length of output: 41950
🏁 Script executed:
#!/bin/bash
set -e
printf '%s\n' '--- all setActiveWorktree definitions/usages ---'
rg -n -g '*.ts' -g '*.tsx' 'setActiveWorktree' src/renderer/src | head -400
printf '%s\n' '--- helper usages ---'
rg -n -C12 'buildEditorActiveResult' src/renderer/src
printf '%s\n' '--- exact active editor restoration assignments ---'
rg -n -C12 'activeFileId\s*[:=]|activeTabType\s*[:=]' src/renderer/src/store/slices | rg -n 'activeWorktree|activeFileIdByWorktree|activeTabTypeByWorktree|setActiveWorktree|openFile|openDiff|restore' | head -400
printf '%s\n' '--- likely implementation files ---'
rg -n -i -C20 'function setActiveWorktree|const setActiveWorktree|setActiveWorktree\s*\(|activeWorktreeId\s*:' src/renderer/src/store -g '*.ts' | head -600Repository: stablyai/orca
Length of output: 41712
🏁 Script executed:
#!/bin/bash
set -e
printf '%s\n' '--- set-active-worktree implementation ---'
cat -n src/renderer/src/store/slices/worktrees/session/set-active-worktree.ts | sed -n '1,280p'
printf '%s\n' '--- worktree slice wiring ---'
cat -n src/renderer/src/store/slices/worktrees.ts | sed -n '80,130p'
printf '%s\n' '--- helper callers ---'
rg -n -C18 'buildEditorActiveResult' src/renderer/src/store/slices/editor src/renderer/src | head -320
printf '%s\n' '--- tab-surface restoration ---'
cat -n src/renderer/src/store/slices/editor/tabs/tabs-surface.ts | sed -n '1,180p'
printf '%s\n' '--- relevant open actions ---'
cat -n src/renderer/src/store/slices/editor/actions/open-file-apply.ts | sed -n '1,170p'
cat -n src/renderer/src/store/slices/editor/actions/open-unstaged-diff.ts | sed -n '1,120p'
cat -n src/renderer/src/store/slices/editor/actions/markdown-preview-actions.ts | sed -n '70,130p'Repository: stablyai/orca
Length of output: 41744
🏁 Script executed:
#!/bin/bash
set -e
printf '%s\n' '--- activated surface resolver ---'
rg -n -C30 'resolveActivatedWorktreeSurface' src/renderer/src/store/slices/worktrees src/renderer/src/store/slices | head -260
printf '%s\n' '--- reopen and rename flows ---'
rg -n -i -C18 'recently.closed|closed.*tab|reopen|new.*markdown|markdown.*rename|rename.*markdown|open.*notification|notification.*open|Cmd|Control.*Shift|Shift.*T' src/renderer/src -g '*.ts' -g '*.tsx' | head -600
printf '%s\n' '--- openFile/openDiff caller context excluding tests ---'
rg -n -B12 -A18 '\.(openFile|openDiff)\s*\(' src/renderer/src -g '*.ts' -g '*.tsx' -g '!**/*.test.ts' -g '!**/*.test.tsx' | head -700Repository: stablyai/orca
Length of output: 42337
🏁 Script executed:
#!/bin/bash
set -e
printf '%s\n' '--- derive active surface ---'
cat -n src/renderer/src/store/slices/tabs/tabs-surface.ts | sed -n '1,260p'
printf '%s\n' '--- recently closed editor tabs ---'
cat -n src/renderer/src/store/slices/editor/actions/recently-closed-editor-tabs.ts | sed -n '1,150p'
rg -n -i -C18 'recently.closed|reopen.*tab|reopen.*editor|open.*recently|Cmd.*Shift.*T|Control.*Shift.*T|Shift.*T' src/renderer/src -g '*.ts' -g '*.tsx' | head -360
printf '%s\n' '--- markdown creation and rename ---'
rg -n -i -C20 'rename.*markdown|markdown.*rename|rename.*file|new.*markdown|create.*markdown|openMarkdown|activateAndReveal' src/renderer/src -g '*.ts' -g '*.tsx' | head -500Repository: stablyai/orca
Length of output: 41824
🏁 Script executed:
#!/bin/bash
set -e
printf '%s\n' '--- reopen symbol callers ---'
rg -n -B12 -A20 'reopenClosedEditorTab' src/renderer/src -g '*.ts' -g '*.tsx'
printf '%s\n' '--- focused markdown action callers ---'
rg -n -B12 -A24 'createUntitledMarkdownFile|openMarkdownFile|openMarkdownPreview|rename.*file|file.*rename' src/renderer/src/components src/renderer/src/hooks src/renderer/src/store/slices -g '*.ts' -g '*.tsx' | head -500
printf '%s\n' '--- focused markdown-link callers ---'
cat -n src/renderer/src/store/slices/editor/actions/markdown-link-action.ts | sed -n '80,190p'Repository: stablyai/orca
Length of output: 42489
🏁 Script executed:
#!/bin/bash
set -e
cat -n src/renderer/src/store/slices/recently-closed-tabs.ts | sed -n '130,215p'
rg -n -B20 -A20 'reopenMostRecentClosedTab|reopen.*closed.*tab|recentlyClosedTabKinds' src/renderer/src -g '*.ts' -g '*.tsx' | head -260Repository: stablyai/orca
Length of output: 31981
Activate focus-sensitive opens before openFile.
When activeWorktreeId is null or differs from the target, buildEditorActiveResult updates only the per-worktree maps. reopenClosedEditorTab calls openFile without activating the target, so reopening from the landing state can leave the global editor selection stale or empty. Activate the target before focus-sensitive reopen and rename flows. Keep background opens non-activating.
…or 'caller' Phone opens send no `navigation` field, and the phone's diff-review "Open in session" relies on the desktop selecting the diff it opened. A missing field now keeps the original switch exactly; the CLI says what it wants instead: 'caller' (no host move) by default and 'all' for --focus. Older CLIs, which send nothing, keep switching as they always have. Refs #9944
There was a problem hiding this comment.
ℹ️ No new code issues found in this delta.
Reviewed changes
This re-review covers commit 83dc90a since the prior pullfrog review (d00ffcd). It fixes a regression the prior revision introduced for paired phone clients and makes the CLI name its navigation intent explicitly.
- Restored the legacy host switch for an absent
navigation—openRuntimeEditorTabnow moves the host view whennavigationisundefined, so phone/paired file-opens (which send no field) switch the desktop again; only an explicit non-host target (caller/clients) opens without moving it. - CLI names its target explicitly —
getFileOpenNavigationsendscallerby default andallunder--focus, replacing the previous "omit the field" encoding, so a missing field no longer doubles as the CLI's quiet request. open-changed --focusswitches once — the first tab that actually opens carriesall; after one opens, later tabs fall back tocaller(a skipped/open-failed entry correctly passes focus to the next).- Tests — new CLI cases pin
callervsall, the leave-alone behavior against a paired remote runtime, and open-changed's switch-once; the renderer bridge test now asserts a phone open switches the desktop while a CLIcalleropen does not.
The FileOpenTab/FileOpenDiff schema split and the notifier/window-lifecycle plumbing read consistently with the new encoding, and no other caller of files.open/files.openDiff relies on the old absent-means-quiet rule.
DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
…visit
A CLI open into a worktree the user is not viewing selected the new tab with
the same activation a user click uses, which stamps lastFocusedAt and the
group's recency list. The worktree jump palette sorts recent tabs by that
time, so every agent `orca file open` into another worktree jumped to the top
of the user's recent tabs.
Editor opens now take a selection mode: 'focus' (default, unchanged),
'background' (select within its worktree without recording focus or recency)
and 'none' (add only). createUnifiedTab and activateTab gain recordFocus:false
for the background case.
Also: tests for reopening an already-open file or diff without --focus, a
comment that file opens move only the host window ('all' acts as 'host'),
root help lines back under 100 columns, and an accurate remote test title.
Refs #9944
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
This incremental re-review covers commit 3c9c2a5 since the prior pullfrog review at 83dc90a. It refines how a CLI file open into a worktree you are not viewing selects its tab.
- Replaced the
activate: booleanplumbing with a three-stateEditorTabSelection('focus' | 'background' | 'none') threaded throughopenFile/openDiffandopenWorkspaceEditorItem. - Background opens now select the tab inside their own worktree without stamping
lastFocusedAtor adding it to the group'srecentTabIds, via a newrecordFocus: falseoption oncreateUnifiedTabandactivateTab. - Added renderer tests for reopening an already-open file and diff with
navigation: 'caller', and for a background open not recording a visit (lastFocusedAtundefined,recentTabIdsunchanged). - Reworded the CLI
getFileOpenNavigationcomment, the notifieropenFileJSDoc, and the root help lines.
I traced the palette path (orderRecentWorkspaceTabs treats an unknown visit time as 0, and use-worktree-jump-palette-recent-tabs reads tab.lastFocusedAt), so the gating is causally connected to the reported "jumped to the top of recent tabs" symptom. The viewed-worktree ('none') and phone/absent-navigation paths are behaviorally unchanged from 83dc90a.
DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
recordFocus:false skipped both the focus-time stamp and the group's recentTabIds append while still making the tab the group's active tab. Ctrl+Tab looks the active tab up in that history, so after a background CLI open it did nothing (or went to the wrong tab) once the user switched to that worktree, and hydrate kept the broken history across a restart. Only the focus-time stamp is skipped now; the jump palette's recent rows sort by that alone, so the palette fix stands. Refs #9944
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
This incremental re-review covers commit 15c11a5 since the prior pullfrog review at 3c9c2a5. It keeps a background CLI open in its group's tab history so Ctrl+Tab can return to what the user was on, while still not marking the tab as visited.
- Background open keeps the group MRU —
createUnifiedTabgatesnextRecentonshouldActivate(notrecordsFocus), andactivateTabalways pushes to the group'srecentTabIds; onlylastFocusedAtis skipped whenrecordFocus: false. - Ctrl+Tab regression coverage — a new parametrized renderer test drives the real
handleSwitchRecentTabfor both a newly created and a reopened background file tab, asserting it switches back to the previous terminal tab. - Recency assertion sharpened — the "no visit" test now checks
lastFocusedAtis unstamped andrecentTabIdsends on the active tab, for both the first open and a reopen. - Doc/comment rewording — the
EditorTabSelection/recordFocusJSDoc now states the group history still updates.
I confirmed the only recordFocus: false caller is workspace-editor-item.ts (the background selection path), and worktree-jump palette ordering (orderRecentWorkspaceTabs) reads lastFocusedAt only, so re-admitting the tab to recentTabIds does not reintroduce the palette jump that motivated the earlier exclusion. Ran the renderer bridge, ipc-tab-switch, and the store's tabs/editor tests; all pass.
DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
… user to the file
The three commands borrowed the shared --focus line written for terminal
create ("Reveal the created terminal session in Orca"). They now use the
per-command flag help table; terminal create's line is unchanged.
Refs #9944
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
This incremental re-review covers commit 9e170df since the prior pullfrog review at 15c11a5. It gives the three orca file commands their own --focus help line, which they had been borrowing from terminal create.
- Per-command
--focushelp —src/cli/command-scoped-flag-help.tsadds aFILE_OPEN_FOCUS_HELPentry forfile open/file diff/file open-changed;formatCommandFlagHelpconsults the scoped table before the sharedFLAG_HELP_TEXT, soterminal create --focusis untouched. - Regression test — new
src/cli/specs/file.test.tspins the exact rendered line for all three file commands and assertsterminal create --focusstill reads "Reveal the created terminal session in Orca". It would fail if the override were dropped, so it is real coverage.
I traced the lookup path (formatCommandFlagHelp → formatCommandScopedFlagHelp) and confirmed the help text matches the shipped --focus behavior. Ran src/cli/specs/file.test.ts (4 tests) — pass. No open prior review threads to retire.
DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
Review status (head
|
Measured from the post-stage-3 main: 794 commits, 22 conflicting files, only 2 of them in the PTY delivery subsystem. The wall this staged plan existed to isolate is behind us; this stage is identity, usage accounting and renderer surface. Three upstream commits produce most of the conflicts: `9700030689` (headless renderer delivery), `82412dab8b` (profile state in SQLite), `d443320af2` (terminal handoff removal), plus `d2dbe2c385` and `f1463683ee` below. ## The two decisions this merge turned on **OpenCode field meanings: adopt upstream's.** The fork's distinguishing behaviour was counting cache writes in token totals. Upstream `f1463683ee` now does that itself — its `scanner.test` expects 1775, which is the fork's number. What remained was bucketing: upstream has `inputTokens` = uncached+read+write, `cachedInputTokens` = read+write, `cacheWriteInputTokens` for the write subset. Keeping the fork's narrower meanings would have left four cleanly-merged upstream files silently wrong, one of them producing a negative telemetry `input_tokens` that the schema rejects — and the divergence would be invisible to typecheck, since the field names match and only the meanings differ. All five cluster files are therefore byte-identical to `b601b98644`, and every asserted total in `cache-write-tokens.test.ts` is unchanged (1120, 2000, 3125): the feature is preserved, only its composition moved. Fork files adapted: `snapshot-rollups.ts`, `usage-provider-normalization.ts` (restored to upstream — otherwise cache is counted as new input and writes are counted twice), `usage-overview-model.test.ts`, `cache-write-tokens.test.ts`. **`agent-state-rules` URL: keep the fork repo.** Upstream stablyai#24387 downloads rules from `${MAIN_RELEASE_REPO}`, which the fork rebranded to `sj900211/orcinus`. A 404 is non-fatal — the updater warns and serves the bundled rules — so the fork keeps pointing at itself rather than fetching runtime data from a repository it does not control. Upstream tests that pinned `stablyai/orca` had a premise that is false by a ratified decision (`release-channel.ts:27`), so their expectations were corrected, following the precedent of rebrand commit `222baedec6`. Each edited assertion carries a `// Why` marker so a future sync does not revert it. This is correcting a stale premise, not weakening a guard: the tests still pin how the URL is built. ## The Windows CLI launcher was replaced wholesale Upstream `d2dbe2c385` deleted `OrcaCliLauncher.cs` and shipped a Rust crate. The fork's `Orcinus.exe` fix (hidden quest ③) is ported into `native/windows-cli-launcher/src/main.rs` at the four call sites; the `.cs` is removed, which a cross-host test now requires because its MSIL image was vendor-flagged (stablyai#23383). The three `Orca CLI` strings and every `ORCA_*` environment name stay — the CLI is still named `orca`. Without this port the packaged `orca` CLI fails on every Orcinus Windows install, which is the precondition for all orchestration work in this repo. `.github/workflows/orcinus-cd.yml` gains a Rust toolchain step on the Windows leg. Deferred by decision: rebranding the launcher's `build.rs` metadata and icon (cosmetic, and the three pieces must move together). ## Defects found that no conflict marker could show Six files merged cleanly and were still wrong: - `pty/session.ts` family — carried from stage 3's pattern, handled there. - `usage-web-client-fallback.test.ts` lost two slice imports upstream narrowed. - `ui-slice-preference-actions.ts` breached `max-lines` at 302 (fork +10, upstream +12). Resolved without a disable by moving the fork's number-format action to a sibling module; the file is now identical to upstream. - `startup-window-role-reconnect.ts` and `folder-workspace-initial-terminal.ts` are fork-only extractions made for `max-lines`; upstream rewrote the originals, so stablyai#24203 and stablyai#23693 were ported into them by hand. - Upstream's new Reset Terminal bypassed owner-window routing; it now routes. - Upstream's new `terminal-intentional-stop-exit.test.ts` saw zero `pty:exit` sends until given a routed main window. - `satellite-open-interception.ts` would have raised a satellite window on a background CLI open, breaking the "change nothing on screen" guarantee stablyai#24244 added. ## Review An independent critic returned REJECT with **no production defect**: every fork behaviour present, both decisions correctly applied, every gate reproducible. The rejection was for 14 tests in 6 files that the gate's directory scope never ran — all of them new upstream tests pinning upstream identity, the same class the `agent-state-rules` decision had ruled on and which it had been applied to too narrowly. All six are fixed, test-only, each with a `// Why` marker. The critic also corrected a claim in the implementation report: the fork already carries upstream's `agent-state-rules-publish.yml`, so live rule updates need only an `agent-state-rules` environment and a `publish-next` dispatch, not new machinery. `sftp-upload.test.ts` deserves a note: upstream's new cases assert a direct `createWriteStream`, but the fork uploads atomically to `.orcinus-part-<uuid>` and publishes by rename (`sftp-upload.ts:61-63`). The fork's contract stands; the expectations moved to it. One of those cases is `skipIf(win32)` and could not be observed here, but fork CI runs on ubuntu, so it was fixed from the code. ## Gates Cold typecheck (after deleting `config/*.tsbuildinfo`): 0 errors, measured twice by different workers. oxlint: 0 warnings, 0 errors across 29,465 files. verify-orcinus-identity: OK, `upstreamRefs=0`. Unsigned smoke: OK, `icon=orcinus.icns`. Fork contract tests: 24/24. Windows CLI launcher tests: the Rust build actually runs here and passes. Attribution, using the critic's harness across three trees (this merge, main, and `b601b98644`): a 1,236-file fork-adjacent sweep and a 54-file identity sweep went from 14 merge-only failures to 1. That one is the release-tag census entry for the fork-only `verify-orcinus-release-assets.mjs`: the census builds its keys with `join()`, so on win32 they carry backslashes. Six upstream sibling cases fail the same way on the upstream baseline, a direct POSIX evaluation of the key logic passes, and a negative control confirms the entry is detected. The census's upstream key logic was deliberately left alone. Known and not addressed here: `updater-prerelease-feed.ts:156` matches only `stablyai/orca` asset URLs — present on `main`, not merge-caused, and invisible to the identity verifier. The release path has not been exercised with this merge (`build:orcad` moved from bun to node); an `orcinus-cd` dry run is advisable before the next fork release. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

ELI5
orca file open,orca file diffandorca file open-changedused to drag Orca to the file every time: switch to its worktree, swap to the editor, scroll the sidebar. In #9944 a user's own agent skill ranorca file opento show its answers, so every answer pulled them out of whatever they were typing in — even in the same worktree, where their terminal got swapped for the editor. Now these commands open the file as a tab in its worktree without changing what you're looking at. Pass--focusto be taken to it.Scope: the three
orca filecommands run from the CLI. Not changed: opening a file from the Orca phone app (it still switches the desktop), older CLIs (they send no preference, so they keep switching), and a new CLI talking to an older Orca (it ignores the preference and switches).orca worktree createandorca terminal createalready stay put unless asked (--activate/--focus) and are untouched.What Changed
Before: every
orca file open/file diff/file open-changedmade the target worktree active, switched to the editor, selected the new tab and scrolled the sidebar to it — whatever you were doing.After:
--focus: the file opens as a tab in its worktree and nothing on your screen changes — your worktree, active tab, editor, sidebar and keyboard focus stay put, including when the target is the worktree you are looking at (the tab waits in the tab bar). In a worktree you are not viewing, it is the tab in front when you go there.--focus: today's behaviour — switch to the worktree, select the tab, reveal it in the sidebar.open-changed --focusswitches once, not once per file.orca --help,orca file --help, each command's help including its own--focusline, and the CLI docs pages) says what the default does and that agents should pass--focusonly when the user asked to see the file.Mechanism: Orca already has a per-request setting for which screens a request may move (
caller/host/clients/all);orca worktree create --activatesendsall. The file-open requests now carry it as an optional field: the CLI sendscallerwithout--focusandallwith it, and the desktop moves only forhost/all— or when the field is missing, which keeps phones and older CLIs on today's path. For a no-move open, the editor store adds the tab without selecting it in the worktree you are viewing; in another worktree it selects it there without counting it as a visit (so it does not jump to the top of your recent tabs, while Ctrl+Tab history still works), and it only updates the global "what's on screen" state for the worktree on screen — the same rule terminal tabs follow since #22603.Why
Every other Orca command that can move your view only does so when asked (
worktree create --activate,terminal create --focus);file openwas the exception, and an agent calling it had no way to avoid interrupting you. Rewording the help alone (this PR's first version) would not have helped the reporter: their skill hard-codes the call.Alternatives considered:
Linked Issue
Refs #9944 — this is the remaining part. The new-workspace part was fixed in #23974; the agent-launch part was already fixed by #22603.
Visual Proof
Live QA on a separate macOS machine (isolated dev build, CLI built from this branch). Before = today's behaviour: every one of these calls switched you to worktree A.
Viewing worktree B with a file open;
orca file open d.txt --worktree A: nothing on screen changes (the before and after captures are byte-identical). The tab is in front when you switch to A.Typing in A's terminal;
orca file open README.md --worktree A: the terminal stays active and focused; README.md is added as an unselected tab.orca file diff b.txt --worktree Awhile viewing B: no move.orca file open a.txt --worktree A --focuswhile viewing B: switches to A with a.txt selected (today's behaviour, now opt-in).open-changed --focuswith four changed files switched once, with no cycling through files.Phone-style open (no preference sent): the desktop still switches, unchanged.
Testing
I manually tested these changes locally (live QA above, macOS)
Automated tests added/updated, or explained why not below
Desktop handler tests on the real store: a terminal focused in the viewed worktree stays focused and active when a file opens there without
--focus; background file and diff opens leave the viewed editor untouched and the tab is in front when you switch;--focusmoves; a request with no field (phone) still moves and selects the diff.CLI tests: what each command sends with and without
--focus, including a CLI paired to a remote server;open-changed --focusfocuses only the first opened file.Main/RPC tests: the field passes through untouched and an absent field stays absent.
Each behaviour was checked by breaking it on purpose and watching its tests fail (9 checks). CLI, node and web typechecks pass; 1485 CLI, 3248 renderer and 859 main/shared tests pass; lint and the code-quality gate are clean.
Review
Agent skill upstream boundary
docs/reference/agent-skill-sharing-upstream-boundary.mdand copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.Notes
Security: no new inputs beyond an optional enum field. Cross-platform: no platform-specific code. SSH / remote servers: a CLI paired to a remote Orca server no longer switches that server's window unless
--focus. Mobile: unchanged by design. Backwards compatibility: optional field; older peers ignore it. Performance: none.Checklist
N/Awith reasonpnpm lint,pnpm typecheck,pnpm test, andpnpm buildpass (or CI will cover; local preferred)