* 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
* fix(sidebar): keep discovered worktrees hidden when adding a project
Adding a project no longer switches it to show worktrees Orca didn't create
(Conductor workspaces and other tools' worktrees). They stay behind the
sidebar's "Hiding N discovered worktrees" line, the same as every other
way a project is added.
* fix(sidebar): open a picked linked worktree instead of revealing its siblings
When the folder added as a project is itself a linked worktree, its main
checkout is hidden. Open the picked worktree instead of switching the whole
project to show worktrees Orca didn't create.
* fix(repos): register clone and create paths with symlinks resolved
Git reports checkout paths with symlinks resolved. Clone and create saved the
typed path, so a project cloned under a symlinked folder (e.g. /tmp on macOS)
did not recognise its own checkout and hid it as a discovered worktree. Resolve
the existing part of the destination before registering, as adding an existing
folder already does.
* fix(repos): keep finding projects saved under a symlinked clone or create path
Projects cloned or created before paths were resolved keep the typed
spelling. Match both spellings so retrying the same clone or create reuses
the saved project instead of failing on its non-empty folder.
* fix(repos): keep Windows clone and create paths as typed
Windows Git reports the typed spelling, and resolving would turn mapped
drives into UNC paths. Runtime clone/create tests now use resolved temp
roots, matching what registration saves.
* fix(repos): register Git's checkout path for clone and create
Replace the parent-symlink resolution with the path Git reports after clone
or git init, as adding an existing folder already does. This also covers a
symlink at the target folder itself and WSL paths, leaves plain folders and
Windows spellings unchanged, and matches saved projects by both the typed and
the resolved spelling.
* fix(sidebar): keep opening projects whose own checkout isn't recognised
Projects saved through a symlinked path by older builds or paired hosts don't
recognise their own checkout. Keep main's behaviour for that case: show the
project so the add still opens it.
* fix(repos): match resolved paths when importing a folder of repos
Clone and create now save Git's resolved checkout path, so a nested import
through a symlinked folder must also match that spelling instead of
registering a duplicate project.
* fix(repos): find saved projects through a symlink before the clone target exists
Resolve a missing clone target through its existing ancestors, reusing the
worktree-create alias resolver, and read the lookup keys inside the clone
lock. Queued clones through a symlinked folder reuse the first clone, and a
different repository at a saved project whose folder is gone is refused
before cloning, as on main.
* fix(repos): match a folder import's resolved path only to local projects
The resolved spelling names this machine's folder, so a remote (SSH) project
at the same path string must not be treated as the import.
* fix(repos): limit a desktop folder import's resolved-path match to this machine
Runtime-owned and SSH projects can share the path string; only projects on
this machine may match the import's resolved folder.
* fix(repos): read a nested import row's connection through the host helper
* fix(repos): match only this machine's projects when creating a local project
* Give unconfirmed chat messages explicit recovery actions
* Resolve receipt settlement code quality findings
* Complete recovery copy localization and callback types
* Align send lifecycle contracts with explicit recovery actions
* Include the unconfirmed opener in the restart fixture type
* fix(chat): preserve recovery ownership across lifecycle boundaries
* Preserve send ownership across context replacement and recovery
* Separate history ingestion from live send settlement
* Preserve original send truth and reconcile acquired history
* Use summary-shaped history responses in acquisition coverage
* Preserve queued image recovery for released readers
* Prove independent late receipt recovery across reopen
* Preserve queued image sources in bounded catch-up projection
* Keep queued input and explicit chat retries in their original domains
* Preserve reader lifetime across main session interfaces
* Fix static checks after main integration
* Migrate retained recovery Stop contracts to current lifecycle
* test: use typed access for journal population counters
* fix: consolidate history page bounds type imports
* test: exercise legacy snapshot reuse through selected handoff
* Fix attachment draft typing and document test boundary casts
* Repair current journal integration types and contract fixtures
* Keep uncertain send recovery in queue reorder reopen contract
* Repair mobile contract boundaries and exact queue lookup
* Align input finalization contracts with current Stop ordering
* Keep recovery copies independent of queued message barriers
* Reconcile Stop and replay contracts with current lifecycle
* Update recovery tests for current module and draft APIs
* Align Stop recovery contracts with independent queue policy
* Expose independent recoveries to current queue controls
* Cover sending-only queue Resume visibility
* Adapt recovery contracts to shared queue projection
* Use current history and failure-word contracts in recovery tests
* test: retain released reader source contracts through queue settlement
* Keep uncertain sends in ordinary history and preserve saved queue choices
* test: prove mobile draft leaf subscription isolation
* Use typed operation instrumentation in mobile recovery test
* Align lifecycle test boundary typing with static rules
* Repair test module typing and retained runtime copy catalog
* Remove unused chat delivery notice translations
* test(chat): retain legacy handback without uncertainty notice
* fix(chat): omit saved uncertainty card captions
* test: bind released readers to exact queue wire and proof
* Replace archived reader evaluator with exact recorded contracts
* Mark queued edit test hook import as type-only
* Isolate queued card tests from native inline composer imports
* Complete structured mobile resolution in queued edit test
* Align mobile attachment cleanup lifetime test with send outcomes
* fix: restore journal prototype delegation methods
* Keep uncertain sends as ordinary messages in memory
* Release notes admission after uncertain opening completes
* fix: end opening selection operations at uncertain completion
* fix: derive selection admission from live requests and repair integration tests
* test: consolidate send imports and use a supported locale
* Fix CI test types and synchronize retired delivery catalogs
* Type exported test fixture mocks through the public Vitest API
* test: align selection and journal verification contracts
* Reconcile acquired history before journal projection
* Preserve saved invocation facts during history catch-up
* Repair journal recovery consumers and CI contracts
* Keep failed legacy import displays serializable and bounded
* Preserve journal owner boundaries in CI import cleanup
* Fix typed test fixtures for session recovery contracts
* fix: align history and recovery contract types
* test: verify logical rewind across released chats
* Bound retained queue and status reads
* Bound Stop and delivery reads to relevant journal inputs
* Bound subscriber catch-up and stopped-history reads
* test: align journal read fixtures and operation counts
* Bound automatic chat reads to current input evidence
* fix: align journal reader contracts and test fixtures
* test: type historical dispatch rejection fixtures
* fix: restore merged session projection and fixture types
* fix: preserve resumed queues across logical fork rewind
* Preserve queue pause chronology across logical rewinds
Keep original Stop and Resume coordinates while retaining matching warm failure evidence in the journal owner. Keep historical fixture authoring separate from current production writes.
* End historical fixture authoring before current queue actions
* Keep answer operations separate from retained messages
* Fix resting chat attention context
* Fix attention regression fixture provenance
* Validate retained RPC test frame reads
* Fix retained attention and RPC contract fixtures
* Keep send observations on canonical delivery evidence
Prepare requested immutable historical snapshots before timed extraction and direct reads, using the existing acquisition/process helpers and local-only consumers. Move four suites' historical module setup into per-pin hooks without changing pins, compatibility assertions, workers, extraction/assertion deadlines or publication ownership.
Independent reviews and the binding design settlement passed. The cold comparison and normal uninstrumented final-head CI each passed49files197tests; normal Checkout62s/job276s. All temporary probes removed; brennan-ready READY.
Tracked in STA-13683. Outer-hook failure attribution limitation tracked in STA-13703. No application, saved-data or wire behavior change.
* refactor(mobile): keep phone list facts beside the desktop's worktree row
The phone wrote its own list facts (lineage depth, host labels, list keys
and so on) onto the worktree.ps row object it got from the desktop, so a
desktop field with one of those names would be read as the phone's own.
List items are now { row, view }: the row is the desktop's, typed from the
shared RuntimeWorktreePsSummary contract, and view holds what the phone
works out. Host labels are a lookup beside the rows instead of fields on
them. A type test fails if the desktop row gains a view field's name or a
type the phone row would not accept, and a contract test feeds rows from
the desktop's own worktree.ps builder through the phone list.
* fix(mobile): type desktop replies from shared contracts and reject unchecked rows (#37923)
* wip: contract guards
* fix(mobile): type desktop replies from the shared contracts and ban unchecked z.custom
Session tabs, the createSupport reply and native-chat frames were typed by
hand on the phone, so a desktop change could leave the phone compiling
against a stale shape. They are now Pick/Partial of shared types; the
createSupport reply and native-chat transcript frames gain shared types the
desktop uses too, which also gives the phone the 'chat-program' reason it
was missing. Type tests fail when a desktop tab gains a phone-only name or
a field type the phone would not accept.
Catalog rows were admitted with z.custom<Worktree>() and no check. They now
need a string worktreeId, and an ast-grep rule rejects a z.custom with no
check anywhere in mobile/src.
* test(mobile): the desktop contract check also catches a null the phone would not accept
* fix(terminal): a local file link opens in the workspace it was clicked in
Clicking a terminal link to a file inside another local workspace switched to
that workspace: the editor loader moved the absolute-path tab to the workspace
containing the path (#11369), and link routing jumped to a sibling tab already
showing the file (#16544). This computer reads absolute paths directly, so
local tabs now stay where they were opened, editable. SSH and server hosts,
which read only workspace-relative paths, keep moving to the owner.
Refs #32158, #25838
* fix: merge duplicate editor store import
Keep the GitHub Tasks source picker, rows, totals, searches and issue creation tied to the selected project, host and source. Ignore outdated replies and wait for source preference saves before creating an issue. Preserve support for older paired servers.
Tracked in #8726. Tracked in STA-1815.