Commit Graph
17402 Commits
Author SHA1 Message Date
OrcaWinandm4air dd0c4cf35e Keep inactive tabs clickable in narrow docked strips (#34881)
* Keep inactive tabs clickable when active dock crowds the strip

* Fix narrow tab dock state after drag cancellation

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
2026-10-28 13:51:55 -07:00
Brennan Benson 6e2b245ac6 Recover brief Linear read failures and retain network causes (#35074)
* Recover brief Linear read transport failures

* Preserve safe diagnostics across runtime Linear reads

* Match existing attachment metadata in read contract

* Use a checked runtime in Linear CLI integration tests

* Keep Linear CLI integration coverage in the backend test graph

* Use integration test ownership for Linear CLI recovery coverage

* Observe empty Linear recovery traces before the first sink write
2026-10-28 13:51:44 -07:00
Brennan Benson d0bfbd22ac Keep host-removed rows out of desktop and phone chats (#34996)
* Keep removed chat rows out of coalesced updates

* test: bound destructive history burst work

* test: verify removed history through transcript projection

* test: count retained row reads with typed getters
2026-10-28 13:50:25 -07:00
Neil 7b3fb541f4 Built-in syntax highlighting for .env files (#34542)
* feat(editor): built-in syntax highlighting for .env files

.env, .env.* and *.env files now open as a dedicated dotenv language with
comment, key, export, value, quoted-string and ${VAR} colouring instead of
INI. .envrc opens as shell, since it is sourced as a shell script.

* fix(mobile): map dotenv to the ini grammar for mobile highlighting

* fix(editor): keep quotes after the first dotenv value character literal
2026-10-28 13:40:03 -07:00
Kelvin Amoaba 6c54b4fac5 fix(mobile): show the chat mic busy while a stopped dictation transcribes (#35320)
Fixes #35313
2026-10-28 20:38:01 +00:00
OrcaWinandOrcaWin 33800f8c8b fix(mobile): stop bundle work after caller cancellation (#34793)
* fix(mobile): stop bundle work after caller cancellation

* test(mobile): use a type import for the fflate mock

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 13:37:53 -07:00
OrcaWinandOrcaWin 9fecb29aa9 fix(mobile): batch notification catch-up ledger writes (#34785)
* fix(mobile): batch notification catch-up ledger writes

* test(mobile): use a fixed expiry in catch-up storage test

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 13:37:47 -07:00
Neil 751e974f88 feat(plugins): download sources without checkout and pin catalog releases in a v2 manifest/catalog (#30636)
* plugins: download Git sources without checkout, within a protocol allowlist and size cap

Plugin and marketplace sources were a real clone/checkout, so user hooks,
smudge filters and core.hooksPath ran, insteadOf rules could reach any
transport, and nothing bounded the download. Now a --no-checkout depth-1
clone (or exact-commit fetch) runs with an empty hooks path, only the https
and ssh transports, and Orca writes the commit's exact blobs from ls-tree +
cat-file --batch. Symlinks, submodules, .git aliases, colliding portable
paths and SHA-256 repositories are refused. A size watcher stops the whole
Git process tree once the pack outgrows an approximate cap.

The exact argv lives in shared code and joins the real-Git compatibility
matrix, so the Git 2.25 lane runs it. Tests reach fixtures over an SSH
shim, since file transports are now refused.

* plugins: manifest v2 declares an execution profile

data < instructional < sandboxed-ui < trusted-worker. A v2 manifest is
strict and fails when it carries contributions beyond its profile; v1
manifests keep loading with the least profile inferred from what they
declare.

* plugins: pin exact catalog releases in orca-marketplace.v2.json

A v2 catalog entry carries the release it vouches for: commit, content
hash, version, profile, minimum Orca and contribution types. Preview and
install fetch that commit directly and refuse bytes that differ. The v1
file stays strict and frozen for shipped clients; v2 entries strip unknown
keys, and entries this client cannot install are dropped at parse time.

Catalog fetches read only the index blobs under their own download cap,
so a catalog repository is not held to one plugin's limits. Release-bearing
snapshots are cached under a new key, so an older build never reads them
and simply refetches.

readMarketplaceJson and parseMarketplaceFile from #30612 are replaced by
parsePluginMarketplaceIndex: catalogs are now read as Git blobs, so the
on-disk JSON read has no caller left.

* test(plugins): serve marketplace e2e fixtures over SSH

Plugin downloads now refuse the file transport, even through an insteadOf
rewrite, so the fresh-profile marketplace journey reaches its fixture
repositories through the GIT_SSH_COMMAND shim the unit tests use.

* test(plugins): give the Git compatibility plugin source its own identity

* test(plugins): record the plugin fixture's executable bit in the Git index on every platform
2026-10-28 13:36:49 -07:00
OrcaWinandm4air 51c1fca90b perf(build): bundle the startup YAML dependency (#35225)
Co-authored-by: m4air <m4air@Mac.localdomain>
2026-10-28 13:36:11 -07:00
NeilandClaude 0a1f35e011 refactor(pty): one neutral isWslTerminalSpawn for relay presence and the Codex home (#35316)
The hook relay's bridge-terminal presence borrowed the Codex-home helper; both now call a
neutral isWslTerminalSpawn, so a Codex-only change can't alter relay presence.

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-28 13:33:46 -07:00
OrcaWinandm4air f70c29b6e9 fix(sidebar): prefetch the pressed workspace instead of switching to it (#35300)
* fix(sidebar): prefetch the pressed workspace instead of switching to it

Rows are dragged to reorder them, so a press must not switch. Press activation
from #34594 is removed; a plain mouse press now starts the hover warm mount
immediately, and the click switches as before.

* fix(sidebar): start the press prewarm a task later and skip modified presses

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
2026-10-28 13:33:04 -07:00
OrcaWinandOrcaWin ade67ab1f2 fix(browser): expire abandoned extension menu snapshots (#35167)
* fix(browser): expire abandoned extension menu snapshots

* Keep menu snapshot expiry cases in a focused host suite

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 13:32:13 -07:00
Pr1pandJinjing 8e9a08b543 fix(preflight): skip probing agents disabled in Settings (#34832)
* fix(preflight): skip probing agents disabled in Settings

Background worktree-startup detection now passes settings.disabledTuiAgents
(which it already held for agent selection) into detectInstalledAgents, so
disabled agents are neither probed nor reported. The preflight:detectAgents
and preflight:refreshAgents handlers keep probing every agent so Settings →
Agents still reports real install status.

Fixes #34635

* test(preflight): cover disabled agent detection forwarding

* fix(preflight): skip disabled agents in background inventory

* fix(preflight): restore native inventory after settings changes

---------

Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
2026-10-28 13:32:08 -07:00
Brennan Benson 7c57ad6a55 Reuse equations while chat replies stream (#34819)
* perf(chat): typeset each unchanged formula once instead of on every streamed update

A streaming paragraph or list re-parses on each revealed prefix, and every
complete formula in it went through KaTeX again, as did every formula on a
virtual-row remount. Keep a bounded cache of typeset results keyed by what
the typesetter reads (tag, math classes, formula text), hand each tree its
own copy, and remember failures so invalid formulas still show their source.

* test(chat): import the typeset module type at the top of the math test

* fix(chat): evict the oldest cached formula without a type assertion

* fix(chat): type the readable math fallback without an assertion

* Cache immutable math results with bounded retention
2026-10-28 13:27:53 -07:00
bbd635e1d7 fix(watcher): prune nested ignored dirs on macOS and bound the flush fan-out (#12067)
* fix(watcher): prune nested ignored dirs on macOS and bound the flush fan-out

macOS was the only platform still watching nested node_modules/.git/dist/build
churn: the darwin branch passed the first 8 ignore dirs as plain @parcel/watcher
`ignore` entries, which the daemon resolves to `<root>/<dir>` only, and built
`ignoreGlobs` from the *remainder* of the list. Nested copies were therefore
pruned by neither layer, while Linux/Windows already got the full
component-anchored regex. Build the glob from the full list; the 8 plain paths
stay as-is because FSEventStreamSetExclusionPaths silently drops every exclusion
past its cap.

The resulting storms then hit an unbounded amplifier in the main process:
flushBatch stat'd every coalesced path with Promise.all (up to 5,000 in flight
against a 4-thread libuv pool), and scheduleBatchFlush could start another flush
for the same root while the previous one was still awaiting stats. Bound the
fan-out to the same limit the watcher child already uses and serialize per root,
keeping one flush running plus at most one queued so bursts coalesce instead of
multiplying. A queued flush is delayed, never dropped.

Fixes #11218

Co-authored-by: Orca <help@stably.ai>

* fix(watcher): share one stat budget process-wide and fence flushes on teardown

The per-batch cap multiplied by watched root, so N roots ran 8N stats; extract
the child's limiter and have both consume it. Teardown now fences and drains a
root's flush machinery so a queued flush cannot start, or emit, after close.
Also stop the queued flush from dropping a newer trailing timer's handle.

Co-authored-by: Orca <help@stably.ai>

* fix(filesystem): abort queued metadata when WSL watcher stops

* test(filesystem): satisfy watcher stat casting quality checks

---------

Co-authored-by: Orca <help@stably.ai>
Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
2026-10-28 13:24:32 -07:00
Kelvin Amoaba 88662806c0 fix(mobile): explain dictation setup before asking for the microphone (#35248)
A mic tap opened capture, and with it the OS permission prompt, before
anything asked the host whether it could transcribe; the setup sheet only
appeared after the host refused dictation.start. The session screen now
gates the start on the setup read it already does, opens the setup sheet
when setup is missing, and hands the next tap back to the host and re-reads
when the sheet closes. A host that never had a model selected now offers
the mic. The sheet's switch uses MobileSwitch.

Fixes #35203
2026-10-28 20:14:39 +00:00
Brennan Benson f869c5580c fix(agents): preserve Kanban verdicts and AI Vault monitoring (#34649)
* fix(agents): preserve turn verdicts and monitoring in secondary views

* fix(agents): publish accepted native status changes to dashboard

* fix(agents): suppress equal rebuilt status notifications

* test(agents): explain proxy read forwarding in perf fixture

* test(agents): type production status fixtures completely

* test(agents): stabilize status fixture formatting

* Align web session test mocks with status transactions
2026-10-28 13:11:13 -07:00
Kelvin Amoaba 1f45c87c50 fix(dictation): say dictation is in use elsewhere instead of dictation_already_active on desktop (#35269)
Move the host dictation error map from mobile to src/shared so the desktop start toast and the phone read the same sentences.
2026-10-28 20:10:43 +00:00
Brennan Benson 31e66a9812 Offer Open as Folder before running Git for plain folders (#34660)
* Offer plain folder opening before Git discovery

* Preserve nested repository marker short circuit

* Verify folder handoff parity and ancestor scan bounds

* Format folder handoff verification test

* Use complete settings fixture for folder handoff test
2026-10-28 13:10:00 -07:00
Brennan Benson 7e0eca67c2 Keep saved folder workspaces under groups without a folder (#34652) 2026-10-28 13:09:13 -07:00
Kelvin Amoaba a419c4a3da fix(browser): stop an abandoned orca eval from blocking later commands on its page (#35284)
* fix(browser): free the page queue when an eval's caller disconnects

A local orca eval whose caller gave up (CLI timeout, Ctrl-C) kept the
page's serial command queue until its script settled, so a never-settling
script blocked every later browser command on that page. The unix socket
now forwards its disconnect signal to browser.eval, and the eval stops
waiting on abort; the abandoned script keeps running.

* test(runtime): pin local disconnect forwarding for browser.eval

* refactor(runtime): name the methods that get the local disconnect signal
2026-10-28 20:08:35 +00:00
OrcaWinandOrcaWin be7a6eecc7 perf(quick-open): preserve scans across worktree metadata updates (#34838)
* perf(quick-open): preserve scans across worktree metadata updates

* test(quick-open): collapse duplicate metadata-update case

* fix(quick-open): key exclude request by state instead of render-time ref

React Doctor rejects mutating a ref during render. Hold the nested-worktree
exclude request in state and replace it only when its key changes, so
metadata-only worktree updates keep the same object identity.

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 13:06:19 -07:00
OrcaWinandOrcaWin 09bd3b96d4 Avoid host-frame registry scans and retained frame wrappers (#35275)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 13:00:39 -07:00
Brennan Benson 30bb30e25c Long chat replies stream with less stutter: parse each block once (#34821)
* Reduce stuttering while long chat replies stream

* Keep streaming markdown pipeline within lint limits

* Type the streaming parser meter without a cast

* Type the streamed markdown test reveal state

* Preserve markdown render domains when configured syntax cannot reuse discovery
2026-10-28 12:56:11 -07:00
OrcaWinandOrcaWin 58a175f928 perf(files): skip generated churn before Windows tree refreshes (#34859)
* perf(files): ignore generated churn before Windows refreshes

* test(files): trim Windows watch filter tests to behavior-bearing cases

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 12:55:54 -07:00
Jinjing 8eab52c114 fix(native-chat): stop multi-agent Codex chats from bloating the journal (#35226)
A long Codex command in a multi-agent chat could write gigabytes to the
agent-session journal and freeze Orca on the next launch while it replayed
them. One 16 MiB `rg` was saved 661 times in 163 s, 8.3 GB for one tool call.

Two things compounded:

- Every event from any Codex thread force-saved every other thread's
  in-flight stream, bypassing its x1.125 checkpoint cadence. The command's
  own thread wrote nothing else during that span; other sub-agents' events
  drove all 661 saves.
- Since #29982 a running Codex command saved its whole output on each
  revision, though the journal's contract (and ACP/Pi) keep a running call
  to a 16 KiB preview and save it whole only on the closing revision.

Forced flushes now re-save only the event's own thread. flushAll still
writes every other stream's first row first, so nothing is journaled ahead
of the text it follows. The journal enforces the running-preview contract
where item rows are built, so it holds for every provider; completed,
failed and interrupted rows stay whole.

Replaying the incident's shape (an 8 MiB command while another thread is
active) through the real translator and row builder: 354 command rows and
1,370 MiB before, 51 rows and 1.8 MiB after (1 MiB of it the completed
output), with translator time down from 1,043 ms to 47 ms.
2026-10-28 12:55:33 -07:00
Brennan Benson 5f314d05c3 @file mentions and Quick Open keep up with typing in large repositories (#34820)
* perf(quick-open): rescore only the previous matches while a file query is typed

Each keystroke in a native chat @file mention or Quick Open ranked the whole
workspace listing (up to 20,001 paths) on the UI thread and rebuilt a set of
every path. A path that matches a longer term always matches its prefix, so
when the new query only extends the old terms, score just the old matches;
cache the listing's membership set per listing. Results are identical.

* refactor(quick-open): keep separator-variant matching beside the other separator matching

* test: cover mention ranking reuse and inventory replacement

* test: type mention query props for rerenders
2026-10-28 12:55:08 -07:00
OrcaWinandOrcaWin 3ca198857d perf(files): share Windows runtime watches by root (#34858)
* perf(files): share Windows runtime watches by root

* test(files): trim duplicate Windows watch pool cases

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 12:54:57 -07:00
OrcaWinandOrcaWin 6d745ad1b9 perf(explorer): bound deferred filesystem watch events (#34857)
* perf(explorer): bound deferred filesystem watch events

* test(explorer): drop duplicate watch buffer storm and GC retention tests

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 12:54:49 -07:00
OrcaWinandOrcaWin dcc0daf9ba fix(watchers): stop stat admission without listeners (#34870)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 12:51:51 -07:00
OrcaWinandOrcaWin 278b02b27a fix(files): preserve WSL filenames in watcher snapshots (#34855)
* fix(files): preserve WSL filenames in watcher snapshots

* test(files): drop shell-producer WSL snapshot test

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 12:51:45 -07:00
OrcaWinandOrcaWin 4ce1e18930 fix(search): publish capped results without waiting for process exit (#34861)
* fix(search): publish capped content results before process exit

* test(search): drop duplicate queued kill-error variant

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 12:51:40 -07:00
OrcaWinandOrcaWin 7d29cd0839 fix(mobile): recover host profile reads without discarding cached bundles (#34806)
* fix(mobile): retry unavailable host profiles without discarding cache

* fix(mobile): cancel startup work on terminal shell failures via flow advance

Merging main pushed use-mobile-web-shell-session.ts over max-lines; move
the host-profile cancellation into the reducer so the flow-change cancel
path from #34780 handles it.

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 12:48:17 -07:00
OrcaWinandOrcaWin e0420b3b58 fix(mobile): skip queued generation stages after cancellation (#34809)
* fix(mobile): skip queued generation stages after cancellation

* test(mobile): fold canceled queued-stage case into download suite

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 12:48:11 -07:00
OrcaWinandOrcaWin d4b6e928ac fix(mobile): index reusable bundle assets once per generation (#34789)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 12:48:05 -07:00
Kelvin Amoaba c79c3a890b fix(computer-use): give each element its own index after browser tab compaction on Linux and Windows (#35272)
* fix(computer-use): keep Linux element indexes unique after browser tab compaction

Dropping inactive tabs shrank the records list mid-walk, so later nodes took len(records) and reused a retained tab's index; elementParam then acted on the tab.

* fix(computer-use): keep Windows element indexes unique after browser tab compaction
2026-10-28 19:41:41 +00:00
Neil d9aa941f6f fix(ssh): offer Remove from Orca for SSH workspaces this app cannot delete (#35271)
* fix(ssh): offer Remove from Orca for SSH workspaces this app cannot delete

Refs #34677

* fix(ssh): retire delete-remote copy for unserved SSH workspaces

Refs #34677

* fix(ssh): retire delete-remote copy in the German catalog

Refs #34677

* fix(ssh): drop a stale host-removal comment

Refs #34677

* test(ssh): pin that an unserved SSH twin is only forgotten

Refs #34677

* test(ssh): build the unserved-twin store without a cast

Refs #34677

* test(ssh): type the unserved-twin store state

Refs #34677
2026-10-28 12:40:56 -07:00
92a754a088 fix(mobile): suspend hidden and background terminal gestures (#31468)
* fix(mobile): suspend gestures in hidden and background terminals

Adapt the retained-pane interaction lifecycle from community PR #30324.
Restore policy across readiness/recovery and keep output/query replies flowing.
Release cancelled gesture frames, discard touches interrupted by suspension,
and restore the resting pinch transform on every gesture cancellation.

Co-authored-by: Wooseong Kim <innocarpe@gmail.com>
Co-authored-by: Neil <nwparker@users.noreply.github.com>

* test(mobile): stub route focus where the web mount renders terminal panes

* test(mobile): send production-shaped file taps and the clipboard prop in activity tests

* fix(mobile): keep inactive and interrupted terminal moves away from xterm

---------

Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com>
Co-authored-by: Wooseong Kim <innocarpe@gmail.com>
Co-authored-by: Neil <nwparker@users.noreply.github.com>
2026-10-28 18:53:58 +00:00
6caa44eefb fix(mobile): keep the terminal reading position when resize snapshots overlap (#31350)
* fix(mobile): keep the reading position when resize snapshots overlap

A snapshot that overtook a hidden replay took its scroll anchor from the
hidden terminal, which sits at the bottom, so the reader jumped down. The
newer replay now keeps the anchor the overtaken one would have restored,
unless live output, a clear or an alternate screen made the hidden buffer
the source. A superseded replay also hands the live terminal back before
theme painting reads it.

Co-authored-by: Neil <neil@stably.ai>
Co-authored-by: ogarciarevett <ogarciarevett@gmail.com>

* fix(mobile): keep the overtaken anchor when live output arrives during a replay

* test(mobile): use T[] for the replay harness completions

---------

Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com>
Co-authored-by: ogarciarevett <ogarciarevett@gmail.com>
2026-10-28 18:38:00 +00:00
OrcaWinandOrcaWin d009fab98a fix(browser): abort rejected Web Store downloads (#35158)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 11:37:35 -07:00
OrcaWinandOrcaWin 797e549b54 perf(browser): group extension frame event delivery (#35079)
* perf(browser): group extension frame event delivery

* test(browser): type event dispatch fixture collections

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 11:33:59 -07:00
OrcaWinandOrcaWin 6e7db575d0 fix(speech): abort model requests after pipeline failure (#35154)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 11:31:24 -07:00
OrcaWinandOrcaWin 02b6bde705 Retire extension notification records on native activation (#35139)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 11:29:23 -07:00
Neil 80bbbaff7f refactor: give native chat readability one concrete owner (#35231) 2026-10-28 11:28:03 -07:00
Brennan Benson 28d6883756 fix(mobile): grey the queue's other controls while Clear all or Resume is on its way (#29219)
* feat(native-chat): one queue header that becomes the pause row; no composer Resume or send dialog

The queued cards now sit under one header row on desktop and phone: "Queued"
and the count normally, and "Paused" with the count, Clear all and Resume
while the host holds the queue after a Stop. A chevron folds only the cards;
the choice is local to the view and resets when the queue empties.

The composer's Send no longer turns into a second Resume, and a message sent
into a paused queue no longer asks "Send message?": it sends, its accepted
turn lifts the pause, and the cards follow it. Clear all deletes every card
through the existing per-card delete. No wire or host change.

* test(mobile): find the background-tasks strip's toggle inside the strip, not the queue header's

* Make queued Clear all atomic across clients

* Show queued message failures in collapsed headers

* Use per-card delete for paused queue Clear all

* Join repeated paused queue Clear actions

* fix(mobile): grey the queue's other controls while Clear all or Resume is on its way

On the phone, Resume and each card's Steer and Delete stayed tappable while
Clear all was still deleting the cards, so Resume could start sending cards
Clear was deleting, and a card's Steer could race its own delete. Clear all
and Resume now share one in-flight key, so each greys during the other, and
Clear all holds every card it deletes, leaving out a card whose own action
is already running. Same mechanism as the desktop fix.

* fix(mobile): wait for pending cards before clearing the queue

* style(mobile): format queue control contract test

* fix(mobile): Clear all and Resume share the queue's pending key, as on desktop

Clear all holds every card it deletes and greys Resume until it settles, and
waits for any card's own action instead of starting over it.

* test(mobile): bound queued message conflict work
2026-10-28 11:08:46 -07:00
844c7f6d96 fix(mobile): preserve Korean 10-Key live-input syllables (#31388)
* fix(mobile): preserve Korean 10-Key live-input syllables

Hold unsent conjoining jamo until committed so grapheme-deleting editors do not erase preceding syllables. Based on community PR #24821; verified real current iOS shell keyboard taps and actual Claude PTY replay.

Co-authored-by: Hojin <hojinkim971597@gmail.com>

* test(mobile): cover held Korean jamo editing boundaries

* test(mobile): keep held-jamo commit tests that add coverage

Boundary cases (Tab, accessory Enter, external send, tab switch, disconnect) already run through the existing held-text tests; the jamo hold reaches them the same way.

---------

Co-authored-by: Hojin <hojinkim971597@gmail.com>
Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com>
2026-10-28 18:07:21 +00:00
NeilandKelvin Amoaba e0b5a42852 fix(mobile): handle invalid pairing links and start fresh for each invite (#31705)
* fix(mobile): validate pairing routes and isolate invite lifetimes

Repeated code parameters crash parsing, and replacing an invite retains old attempts and callbacks. Validate route input and key confirmation state by invite; allow confirmation content to scroll on short screens.

* fix(mobile): retire pairing immediately when Back is pressed

* fix(mobile): keep the pair confirmation layout unchanged

The ScrollView wrapped ConnectionLog's own vertical scroller without nested
scrolling on Android and was not needed for the invite-lifetime fix. The
repeated-code case is covered by the route-state test.

---------

Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com>
2026-10-28 17:57:24 +00:00
Neil 121eb3bc84 fix(runtime): resolve folder workspaces wherever a command can be given one (#35223)
* fix(runtime): resolve workspaces, not only Git worktrees, wherever a folder id can arrive

The Git-only selector resolver never matches project-group folder
workspaces (no repo row), so worktree show/sleep, terminal list by
workspace key, the active-terminal fallback, scrollback reads, Kitty file
reads, Linear --current, browser commands, plugin context and the session
tab fallbacks failed with selector_not_found for them. Route those
callers through resolveWorkspaceSelector and rename the Git-only resolver
to resolveGitWorktreeSelector so it reads as the repo-backed catalog only.

Refs STA-12562

* test(runtime): follow the workspace resolver rename in host fakes

Refs STA-12562

* test(runtime): keep partial browser host fakes and mail-routing stubs on the renamed resolver

Refs STA-12562

* test(runtime): drop an accidental copy of the folder selector suite

Refs STA-12562

* fix(runtime): keep folder workspaces off the skill worktree fence and the Linear meta backfill

Skill installs fence a worktreeId by repo rows, so a folder id there must
come through folderWorkspaceId, where its own host fence applies. Linear
--current answers a folder's legacy link without writing a worktreeMeta
row keyed by the folder id.

Refs STA-12562
2026-10-28 10:52:37 -07:00
Neil e03057de40 fix(native-chat): name a chat start that failed preparing its launch, with the host error in Details (#35186)
A start that failed on the host while Orca resolved or prepared the launch
(workspace or launch folder, command or account home, ACP prepare or temp
folder) reached the chat only as "Claude couldn't start" with no Details.
The adapters now mark that failure where it happens as the typed reason
launchPreparationFailed, and the host error is shown behind Details. A
reason already named there is kept, and a start withdrawn by Stop or close
keeps today's words. Older clients drop the unknown reason and kind.

Refs #34795
2026-10-28 10:47:58 -07:00
OrcaWinandm4air 40822e2c4e perf(switch): prewarm hovered and neighbor workspaces; coalesce held step keys (#35222)
* fix(terminal): don't count a PTY reattach as workspace activity

A remount (hidden prewarm, background mount) reattaching the tab's own live PTY bumped
lastActivityAt and sortEpoch, re-sorting the sidebar on hover. Also keep store map
identity on that no-op path so subscribers skip re-rendering.

* perf(terminal): prewarm hovered and keyboard-neighbor workspaces before the switch

A row hovered for 120 ms, and the previous/next workspaces in sidebar order (local hosts,
500 ms after a switch settles), take a prewarm lease: hover holds one, neighbors two.
A lease mounts only each group's visible snapshot-restorable terminal plus live tabs,
never wakes sleeping agents, and lays out and warms WebGL in separate idle tasks.
Hover stays laid out until it ends; a neighbor hides again once warm. Held leases are
exempt from ordinary cold parking (the retention budget still applies), individually
parked sibling tabs stay unmounted, a narrowed live mount is handed back on release,
and prewarm is off when hidden-view parking is disabled.

* perf(sidebar): coalesce held workspace-step keys

Auto-repeated Cmd+Shift+Up/Down and list arrows move only the sidebar highlight (and the
listbox's active descendant); the workspace under it switches once the repeat stops, on
keyup or a missed repeat since macOS withholds keyup while Cmd is held. Single presses
still switch synchronously. Keyboard navigation also publishes its sidebar neighbors to
the prewarm lease.

* perf(palette): close Cmd+J without the exit fade after a selection

A selection already moved the user to the new surface; the 150 ms overlay fade only
dimmed it. Escape and outside dismissals keep the fade.

* fix(terminal): undo a prewarm narrowing only while the lease still owns it

Releasing a lease after its workspace was activated (or after another mount replaced the
restriction) stripped the deferred tab ids that activation now owns, so over-cap tabs
stayed on the restoring placeholder and lost parked watchers. The undo now runs only
when the lease's restriction is still installed and the workspace was not activated.
Simulator workspaces also get no restriction on any unrestricted mount, parked included,
so the emulator overlay stays mounted.

* fix(terminal): prewarm never reattaches a session the daemon has not confirmed live

After a daemon loss a parked shell tab keeps its PTY id and snapshot capability, and its
reattach spawns a replacement process. A lease now asks main (pty:hasPty, authoritative
true only) for the revealable tabs it would reattach and admits only confirmed sessions;
unknown or remote-runtime answers decline. Workspaces with a simulator tab never take a
lease, since any restriction unmounts the emulator overlay and its local state.

* fix(terminal): confirm every split leaf and keep parked siblings out after a lease ends

A split tab reconnects each leaf on mount, so prewarm now confirms every resolved leaf
session (re-resolved after the answer; any change fails) instead of only the tab's
first PTY. Releasing a narrowed lease ends its measurement, which starts tab cold
parking's 30 s cool-down with an empty park set; the narrowing now outlasts that
cool-down so individually parked siblings stay unmounted after an abandoned hover.
Prewarm target selection moves to its own file.

* fix(terminal): hold a prewarm narrowing through any newer measurement cool-down

A mount that measures the worktree after the lease ended starts its own tab cold-park
cool-down; lifting the narrowing on the original deadline would remount parked
siblings while parking is still off. The undo now re-waits while the worktree is
measuring or inside its park cool-down. Teardown cancels pending undos after the final
releases, which would otherwise schedule timers past the unmount.

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
2026-10-28 10:42:08 -07:00