* test: stop unit tests from running the developer's real agent CLIs
A live relay test reached the host's real `claude --version` through the
inherited PATH. On a machine whose claude wrapper never exits, each run left
an orphaned loop behind (14 were found on one host, running for days).
- Add a unit-test setup guard that shadows agent CLI names on PATH with
stand-ins that fail the test which ran them.
- Give the live relay test its own claude/codex stubs.
- Kill the whole process tree when the WSL guest's version probe times out.
* test: keep structured-session tests off the real codex CLI
These hosts get a scripted transport, but the at-rest `/` command read
spawns the resolved codex command directly, so on a machine with codex
installed each run started a real `codex app-server`. Point them at a
missing binary, as on CI.
* test: isolate agent discovery in session fixtures
* fix(automations): Run now returns the saved pending row; quiet, titled, retained run terminals
Run now answers with the durable pending row instead of waiting behind
the automation's lane; one detached handler records a launch failure.
Existing-workspace launches no longer surface their owner, a new
workspace's startup tab carries the run title, and finished-run cleanup
keeps a terminal a user opened after its process started.
* fix(automations): keep launched runs and user-opened run terminals intact
A failed flush after a launch no longer rewrites a dispatched run as a launch failure.
A user tab open marks the pane activation shows, read after any spawn it starts.
* fix(automations): own launch-failure recording in the service; quiet pending pane notice on mobile
* perf(mobile): share one clientEvents stream per host connection
* perf(mobile): keep the shared clientEvents stream across a same-tick rejoin
* fix(mobile): let a later subscriber retry after the shared clientEvents open throws
* fix(mobile): guard the shared clientEvents cleanup after a throwing open
* test(e2e): give the phone list's socket client the shared clientEvents shape
* fix(files): open a granted host file the way a workspace file opens
A plain click on a host file outside every workspace opened it in the
editor through the grant's whole-file text read, so a video, a large
image or any text past 512 KiB failed with "too large to open from its
host". Granted files now go through the same reads as workspace files:
media streams to its viewer by range, images and PDFs page past one
reply, and large text pages into the editor. A host file is addressed
either by workspace path or by its grant, and the host gains
files.statTerminalArtifact to pair with files.readTerminalArtifactChunk.
The host names a large binary as binary before refusing its size, as
files.read does, and a streaming player renews a lapsed grant the way
the editor's reads do. Hosts without these methods answer
method_not_found, which the paged reads already turn into an
update-the-host message.
Refs #35968
# Conflicts:
# src/main/media/media-preview-protocol.test.ts
* fix(files): page a granted binary with the grant that served it
A content read renews a lapsed grant without telling the tab, so a bytes
editor paged the file with the dead grant and failed on every reload. The
read now reports the grant that served it; the bytes editor uses that grant
and the tab keeps it, as a save that renews one already does.
Refs #35968
* fix(files): renew a granted preview on every host call and keep unsavable grants read-only
Review: renewal ran only before a media response returned, so a grant that
lapsed under a streamed chunk or a pdf.js range read over IPC failed instead.
Every host call for a remote preview now goes through one helper that renews a
lapsed grant once. A grant saves only text within one write, so a granted
binary or text past 512 KB now opens read-only instead of failing to save.
Refs #35968
* fix(editor): show an unsavable granted copy read-only in every view
Review: read-only reached only the edit surface, so a large granted notebook
or markdown file still opened its editable rich view. The editor panel now
treats the copy as a read-only tab, so rich views fall back to the raw source
view as they do for other read-only tabs. A renewed read-only grant also reads
as read-only and stays off the tab.
Refs #35968
* fix(files): renew a granted bytes read whole and never splice versions mid-stream
Review: a bytes editor opened after its grant expired kept failing, since its
paged read never renewed. It now renews and restarts the whole read. A stream
or PDF range that renews mid-read now continues only if the renewed grant sees
the same file version, so a rewritten file can't splice into one response.
Refs #35968
# Conflicts:
# src/main/media/media-preview-protocol.test.ts
* fix(files): keep each preview response on its own grant and pin a bytes read's pairing
Review: a stream crossed to a grant another request had renewed without
checking the file version, and a bytes read that renewed during a re-pair
could read from the new host. Each response now keeps the grant it started
on and moves to a renewed one only after checking the version it serves, and
a bytes read pins its pairing before the first call.
Refs #35968
* fix(files): bind a preview's stat to the grant that saw it
Review: a stat cached from the old grant could start a response on a grant
another request had just renewed onto a rewritten file. The cache now keeps
each stat with the address that produced it, a response starts on that
address, and a renewal checks the version by stating the renewed grant
itself.
Refs #35968
* fix(files): keep a pinned read's pairing on its paged address
Review: the paged-read address dropped a caller's pinned pairing, so a re-pair
between a grant renewal and its retry could send the retry to the new host.
The address now carries the pinned revision.
Refs #35968
* test(e2e): give the granted video spec's timeout its reason
Refs #35968
* test(media): keep the granted preview renewal tests in their own file
Main trimmed media-preview-protocol.test.ts to local previews, so the tests
for renewing a granted preview's lapsed grant (burst, streamed chunk, rewritten
file, PDF range over IPC) now live in media-preview-protocol-granted.test.ts.
Refs #35968
* refactor: group structured session modules by owner
* test: retire status history work-count oracle suite
* refactor(main): organize journal storage and projection owners
* Consolidate restart recovery fixture imports
* Consolidate concrete session option model imports
* fix(terminal): a host with a window keeps a pane a client moved to a new tab
Dragging a split pane onto the tab strip in a paired worktree whose host runs
the desktop app with a window flickered and snapped back. The client draws the
new tab and calls session.tabs.movePaneToNewTab, but the host answered
not_held whenever it had a window, because the window owns the layout and only
headless hosts committed the move. The client reverted, and even without the
revert the host window's next snapshot would have rebuilt the old tab.
Main now asks its window to make the move and waits for the answer, the way
other client requests reach a window-owned host. The window moves the pane
with its own drag-out path under the tab id the client already drew, at the
client's drop position, mounting a parked source tab first. A pane the window
cannot reach is refused, so the client puts it back; a host without the
window bridge still answers not_held. Older clients and hosts are unaffected.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(web): rely on the optional pane-move bridge instead of no-op stubs
The web client never receives host pane-move requests, and the bridge
already skips registration when these members are absent; dropping the
stubs keeps web-ui-api.ts under the line limit after rebasing on main.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test(e2e): a window host keeps a pane a paired client moved to a new tab
The window-host case asserted the old refusal, where the client drew the new
tab and put the pane back. It now drags a pane out on a paired client and
checks the pane stays in the tab the client drew: the host window holds the
leaf alone under that tab id, no snapshot pulls it back, and the source keeps
one pane. It fails on main, where the tab count falls back after the drop.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(terminal): refuse a pane move the host window cannot answer
When a paired client asks a host with a window to move a pane to a new
tab, the host relays the request to that window. If the window is gone,
closes, or does not reply within 10 seconds, the relay rejects. The
host returned that rejection as an RPC error instead of a move result.
The host now answers { status: 'refused', reason: 'pane_unavailable' }
in that case. The client already puts the pane back on a refusal, and
this is the reply the relay timeout was sized for.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(terminal): fence a window's pane move once the client heard it timed out
The relay told the client "refused" after 10s but left the window's move
running, so a late commit moved the pane on the host after the client had
put it back. Main now fences the commit: a move the client was told timed
out commits nothing, and a commit answers the client at once, before the
deadline can turn it into a refusal.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(terminal): keep the pane-move fence Electron-free and let a claimed commit answer
The leaf-move IPC is shared with the plain-Node runtime, so the fence moves to its own
Electron-free module. A window that goes away mid-commit no longer refuses a move its commit
landed, and a second move cannot replace a fence a timed-out move still holds.
Fixes#37082
* chore(terminal): follow moved shared modules after rebasing the pane-move relay
Refs #37082
* fix(terminal): hold a client's pane move's source tab mounted until the move settles
The timed split-mount lease could expire while the window was still moving the
pane, so cold parking could unmount the source tab after main had already told
the client the move landed. The move now holds the tab mounted for its whole
duration and releases it when it settles.
Fixes#37082
* fix(terminal): don't toast the host window for a pane move another client asked for
Fixes#37082
* fix(terminal): relay a client's pane move only to a window that owns the layout
Where main owns the layout (the dark ORCA_LAYOUT_OWNER=main path), the window's
move goes back through main, which names its own tab, so the client's tab id
could not be kept. Main answers not_held there, as before this change.
Fixes#37082
* fix(terminal): name the renderer a relayed pane move belongs to
Fixes#37082
---------
Co-authored-by: Seunghwan <hyunsh.cycle@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Paired clients now publish the chat actually selected on the desktop as the active tab; saved layouts, CLI-created chats, closes and restarts keep it consistent. Carries community PR #34526.
Co-authored-by: Jurassic Knights <jurassicknights@gmail.com>
* fix(codex): remove Orca-created pre-trust entries when a worktree is removed
Records which [projects."<path>"] tables Orca's preflight trust created in a
managed Codex config (with the exact bytes written), and on worktree removal
deletes only those, inside the existing trust-config mutation queue. Removal
paths await the purge so a removal is never reported before the entry is gone.
Ported from #24803 (commits 88d5469c, c1ffc5a4, 11b0bd74, f85606b3) onto
current main: conflicts resolved, stray re-export wrappers dropped, and tests
trimmed to AGENTS.md rules (ordering/timing, private-state, Cartesian and
lower-layer duplicate cases removed).
Co-authored-by: Neil <neil@stably.ai>
* fix(antigravity): drop Orca-added trustedWorkspaces entries on worktree removal
Generalizes the Codex pre-trust ownership ledger into a small factory
(agent-trust-ownership-ledger.ts) and uses it for agy: when Orca appends a
worktree path to ~/.gemini/antigravity-cli/settings.json trustedWorkspaces, it
records the exact entry, and worktree removal removes only that recorded entry.
Entries that already existed before Orca's grant are never recorded or removed.
* fix(trust): keep folder-workspace trust on session removal; isolate trust test userData
Only checkout-deleting removal paths drop Orca-created agent trust now.
Folder-workspace sessions and forgotten orphans leave the directory on
disk, so removing one must not strip the grant siblings still rely on.
Also point the execution-host trust test at a temp userData so the new
ownership ledger never writes to the real Orca config, and make the e2e
removeWorktreeMetadataAndHistory stub return its Promise.
---------
Co-authored-by: ggbdpq <ggbdpq@gmail.com>
* fix(editors): launch Open In editors by id from settings
* test(editors): drop settings casts by narrowing the shell store type
* fix(editors): import shell-open types from their moved path
* test(editors): type the shell test settings instead of casting
* perf(native-chat): one chat's status change wakes only that chat
The renderer status feed copied every retained summary and called every
listener on each one-session update, and the status bridge walked every
open tab. Adopt the common keyed-entity pattern: update the session in
place, wake only readers registered for that session, and give the bridge
a session-to-tabs index. Option state now reads only the runtime
permission answer, so a reply preview no longer re-renders the chat.
* fix(native-chat): keep the phone's permission projection and prune stale retry members
Restore projectRuntimePermission for the phone app, ignore a malformed
conversation-name list as the names fold does, drop superseded bridge
members from the retry set, key resume-run ids by the run's start, and
update the continuation test mock.
* perf(native-chat): retry and resume-run checks look only at the touched host and chats
Keep the bridge's retry set per host so another host's update never scans
it, and check only the resume-run entries an update touched.
* test: give the launch create-message feed fake the per-chat subscription
* test: drop call-count assertions from the bridge contact-loss test
Keep the behavior it guards: no throw, revocation applied, later listeners
still notified, and the reconnect snapshot projects.
* fix(plugins): say that full-access plugins can also control Orca
Worker plugins can use Orca's local runtime API, so the consent text now
mentions terminals and agents alongside files, network and programs.
* fix(plugins): keep the glossary term in the Japanese full-access warning
* test(e2e): expect the updated plugin full-access text
* test(e2e): expect the updated full-access text in the plugin demo spec
Terminals a paired desktop or mobile client opened on a headless serve
host got a workspace-less serve-<uuid> session id, so the host inferred
their owner from the cwd. Folder workspaces that share a path then traded
those terminals whenever one was listed, and deleting a workspace stopped
terminals shown in another.
Serve ids now carry the workspace like every other daemon id. Inventory
refresh keeps a persisted layout binding even when a targeted listing does
not include its workspace, so restored serve-<uuid> terminals stay put.
A cwd guess is recorded as such and never drives a worktree-scoped stop.
Fixes#36716
Reported-by: Guy Shechter (@shechter)
Co-authored-by: Bing.Z <zzb@gxsmjx.com>
Keep Claude plugin status and toast frames out of native chat, and give terminal-input requests an actionable failure with safe conversation recovery. Preserve genuine outside replies while hiding internal repair content.
Tracked in STA-13468. Built on #37480 by @agustin2606.
Co-authored-by: agustin2606 <agustinvarela2606@gmail.com>
Closing a tab whose bound shell Orca can't inspect now asks first
(#38697). The managed SSH journey closed a disconnected tab and expected
it gone without answering that prompt, so it timed out behind the modal.
Expect the prompt, confirm the tab is still there, Stop and Close, then
assert removal as before.
A server learns of a desktop that can host its browser pages only after that
desktop opens a browser tab, so open-url failed until one existed. Desktops now
opt in on their client-events subscription. When a server-initiated page needs
a host and no lease exists, the server asks the newest such desktop to start
hosting and places the page on the lease it names. Only an explicit decline
moves on to the next desktop, so a slow desktop can never leave two leases; a
desktop that stays silent is named in the error.
When several desktops already host, the page goes to the one showing this
workspace's pages, then the newest lease, instead of failing as ambiguous, and
no desktop without a lease is asked.
Managed SSH desktops do not opt in, so their hosts keep using the desktop
browser bridge. Leases stay lazy, so an idle desktop holds none and bridge and
tab-query routing are unchanged.
Fixes#35066
Co-authored-by: coolwindX <45729206+coolwindX@users.noreply.github.com>
* fix(browser): Escape typed in a page exits grab, find and the password list
A focused page keeps its keys, so the renderer's Escape listeners for
element grab/annotate, the find bar and the saved-password list never
fired. Main now hands Escape from browser and HTML preview guests back
to the renderer for that page; during a grab pick the page doesn't
also get it, like C/S.
* test(browser): say why the grab Escape test waits out the toast
* refactor(browser): share one page-Escape subscription hook
* feat(mobile): show the context usage ring in the chat composer
Desktop's ring reads the structured session's context facts; the phone
never read the host's contextUsage answer. The summary rules move to
src/shared so both read the same numbers, and the title card's anchored
card machinery is generalized so the ring's breakdown opens above the
composer without dropping the keyboard.
* refactor(native-chat): share the context ring's critical threshold
* test(mobile): stub the context ring where composer tests stub its siblings
* fix(mobile): keep the context card with the composer and the keyboard up
Touching the card no longer takes focus from the draft, the open card
moves with the composer as the keyboard or draft resizes it, and the
composer's own menu closes it.
* fix(mobile): close the context card when the composer hides, and let long titles wrap
* refactor(mobile): share the anchored card layer and the ring readout
* test(e2e): pass the new options arg in the permission publication test
* Show background completion mail as its command source
* Use minted sender handles in identity regression fixtures
* Verify command source labels in translated chat views
* Preserve command-only queued source regression coverage
* Use a minted terminal identity in host sender coverage
* Reuse command sender labels across unchanged message and queue reads
* Keep sender performance contract within the shared typecheck boundary
* Keep command reports in the background surface and preserve observed sender identity
* Use the shipped phone background report translation namespace
* Settle the prior dispatch before testing terminal reuse
* Keep live worker status tied to its recorded agent invocation
* Withdraw worker invocation proof when identity refresh fails
* Drop unproved worker associations at the failed refresh boundary
* Cover ordinary and remote sender rows during failed refresh
* Assert preserved session and peer content on failed sender reads
* Align sender navigation and relay tests with observed provenance
* Keep background report sources neutral and bound sender snapshot caches
* Construct readonly phone report fixture without mutation
* Keep callback-free federated transport assertions exact
* Keep orchestration sender identity separate from endpoint activity
* Validate mailbox receipt fixture shapes without casts
* Keep current Crew endpoint status separate from saved message activity
* Keep sender activity fixtures within lint contracts
* Avoid repeated serialization for fitting relay pages
* Use the valid workspace sidebar value in scale coverage
* Keep operation-count SQL expectation in sync with main
Double-clicking a file or folder name no longer starts inline rename.
The second click of a fast pair on a folder now toggles it back, and a
file name double-click pins the preview like the rest of the row.
Rename stays on Enter and the context menu.
* fix(terminal): paint a new WebGL canvas inside a synchronized frame instead of leaving it blank
A replaced WebGL renderer's first paint went through terminal.refresh(), which
xterm buffers while DEC 2026 synchronized output is held. The old canvas is
already gone, so the pane showed an empty canvas until the program closed its
frame. Over a remote link Codex's frames often span packets, so revealing a
remote worktree flashed blank/content for under a second, only with WebGL.
Paint a just-attached or just-resized canvas at once. A canvas created while
its renderer is paused (hidden worktree) is remembered until its first paint,
so the reveal present paints it through the open frame instead of waiting.
Also drop the WebGL rebuild after every reattach replay: it worked around an
atlas problem that no longer exists and replaced the renderer on every reveal.
* fix(terminal): limit a never-painted canvas to one mid-frame paint
* test(terminal): prove a swapped WebGL canvas paints through spinner sync frames
* fix(terminal): clear the never-painted mark on any forced paint; drop e2e casts
* test(terminal): keep the spinner repro inside the flaky-pattern ratchet
* fix(agents): paired-host agent tabs use the host's launch settings
Agent tabs opened on a paired host were replacing that host's permissions and Arguments with the desktop's settings. Let the host plan fresh launches, carry the user's choices separately, and preserve existing prepared launches when an older host cannot express them. Action Arguments replace configured Arguments while inheriting the host's permission settings; resumed sessions keep their recorded recipe.
* fix(agents): paired-host agent tabs use the host's launch settings
Preserve per-launch permissions on older paired hosts by compiling picks they cannot apply from their own settings. Keep authored Arguments separate from saved model defaults so a command's pinned model wins. Use the host's reported shell and execution platform for argument quoting, and remove unused prompt-delivery wrappers.
* fix(agents): paired-host agent tabs use the host's launch settings
Replace recognized permission flags from older paired hosts when a launch picks another permission, while preserving unrelated Arguments and ambiguous prepared launches. Keep multiline drafts working on Command Prompt hosts and omit chat-only permissions from terminal requests.
* fix(agents): paired-host agent tabs use the host's launch settings
Preserve per-launch permission choices that suppress the paired host's Full access flag even when the choice emits no flag itself. Compile these choices from the host snapshot when older launch preferences cannot carry them, while keeping unsupported OpenCode terminal permissions filtered out.
* test: merge duplicate imports in paired launch options test
* test: drop type assertions in paired launch options test
* chore: lower focus-read ratchet baseline after removing creation wrappers
* fix(agents): paired-host agent tabs use the host's launch settings
Keep accepted inline fork drafts delivered when their mirrored tab is unavailable, and cancel launches whose pairing changes during negotiation. Keep action Arguments metadata on the tab route so injected workspace launch callbacks retain their contract. Update consumer fixtures to run lazy compatibility preparation and verify the final launch inputs and cancellation boundary.
* fix(agents): paired-host agent tabs use the host's launch settings
Keep pairing changes during legacy launch preparation silent and preserve the prompt for retry. Make picker tests exercise structured model picks on modern hosts while retaining prepared-command coverage for older hosts.
* fix(agents): paired-host agent tabs use the host's launch settings
A permission pick on an older paired host could turn desktop-configured Arguments into a launch override, including the desktop's model. Keep settings-seeded text out of the paired picker request so the host snapshot supplies defaults, while preserving explicitly edited launch Arguments.
* fix(agents): paired-host agent tabs use the host's launch settings
Keep permission-control choices separate from Arguments the user edited.
Fresh paired terminal launches now share that ownership projection in the
new-tab picker and continuation dialog, so a control change preserves the
host's executable and environment settings. Explicit Arguments edits,
including clearing the field, keep their existing launch behavior.
Cover old-host and modern requests, explicit terminal/chat edits, and the
continuation Start handler. Workspace creation keeps its existing path.
* fix(agents): paired-host agent tabs use the host's launch settings
Older paired hosts could inherit the desktop's model and permission defaults when the launch picker was configured or reopened. Read picker defaults and prepared launch recipes from the executing host, and compile edited Arguments using its settings. Preserve explicit empty edits, narrower permissions and draft prompts.
Keep inherited choices neutral while host settings are unavailable, retaining the existing compatibility launch when no usable host recipe exists.
* chore: merge duplicate type import and drop dead test branch
* fix(agents): paired-host agent tabs use the host's launch settings
Actions with explicit permission choices could unnecessarily read host settings and fall back to desktop preparation when those reads failed. Keep representable action Arguments on the host's authoritative launch path, and read inherited permissions only when the action needs them.
Cover an explicit empty Arguments override and Ask with unavailable settings, preserving the host executable and environment without a permission bypass.
* fix(agents): paired-host agent tabs use the host's launch settings
Supply the paired host's default agent in the shortcut test instead of
assuming the desktop's default applies. Keep a conflicting desktop default
so the shortcut continues to verify the paired host owns its selection.
* fix(ci): run the release skill-sharing Electron install step in bash
#38130 turned this step into a POSIX path fallback, but the skill sharing
release gate also runs on windows-2022, where the default shell is
PowerShell. The step failed with a ParserError, so release-preflight
skipped every build for the v1.4.250 cut.
* test(e2e): keep the one-time Codex notice out of golden runs
The v1.4.250 golden e2e on Linux timed out clicking New Terminal: the
'Orca now runs Codex without its shared server' toast fires once when the
golden stub (a Codex terminal) appears, and here it landed while the +
menu was open and closed it. Mark it seen in the completed-user fixture
like the other one-time notices, and restore that fixture from the
workflow ref in the release golden job so a recovered tag uses it.
---------
Co-authored-by: m4air <m4air@Mac.localdomain>
Tokenize visible diff-pane lines when a diff editor's model, hidden areas or layout change, so outer-scrolled combined-diff sections paint coloured (STA-12770).
closeTerminalTab defaulted a missing reason to 'user', so programmatic
closes (a withdrawn launch pane, a host-retired pane) reached a paired host as session.tabs.close reason:'user' and
killed its live terminal. The reason is now required; only gestures
declare 'user', CLI/RPC/phone closes forwarded by main declare
'requested', and housekeeping declares 'cleanup', which never kills a
paired host's live terminal. A launch pane closed by housekeeping no
longer tells main the user stopped its launch.
Refs #37245
relaunch() already lets a scenario declare terminalsRestart and passes it to
oracle.step, but compareRestart masked PTY ids only for coldDaemon, so
sleep-quit-resume reported its permitted terminal restart as a PTY id change.
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
v1.4.249 is the first release with the reorganized src/shared layout, so the checkout wire-surface check rejected it and every baseline suite failed to extract. Module imports already resolve moved files by name.
* Add Chat UI choice to onboarding and tailor agent tours
* Add setup guide controls for Chat UI and Yolo permissions
* Refresh native chat agents and improve surface radio controls
- Re-read the host inventory alongside workspace refreshes, including WSL
- Recognize downloaded, ready chat runtimes without a CLI on PATH
- Standardize onboarding and checklist surface choices on accessible radio variants
* Show full-access agent overrides in Yolo mode settings
* Polish Chat UI onboarding and clarify terminal fallbacks
- Group agents by launch surface and refresh selection previews
- Add scroll-edge fades to reveal clipped onboarding content
* Recognize ready custom Chat commands and nested scroll changes
* Advance agent tour after selecting a new tab type
* Install onboarding skills for selected chat providers
- Route Chat UI setup to local provider-specific skill roots
- Improve tour focus, Escape handling, and delayed target transitions
* Keep split lesson while a new pane mounts; update renamed skill in test
* Assert agentDefaultSurface in Chat UI onboarding e2e
* Open the chosen Chat UI agent when a new project's default checkout opens
* Make the onboarding chat preview match native chat
- Soften the selected preview tile styling.
- Accept a leading separator in dev:fresh arguments.
* Fix scrolling in the onboarding agent step
* Preserve initial working directory when opening empty workspaces
Also check only remaining tour steps for unfinished actions.
* Fix tour resumption after completed split steps