mirror of
https://github.com/stablyai/orca.git
synced 2026-10-31 09:07:40 +00:00
284411d8934890ff84e285b22f1368b84c19bfa3
16816
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
284411d893 |
fix(wsl-host): uninstall and startup release WSL holders; a partial Remove keeps the host pending (#33843)
* fix(wsl-host): uninstall and startup release the WSL distro holders Orca left running The detached wsl.exe holder outlives the app, so an uninstall left its distro, orcad and shells running. The uninstaller now runs Orca with --orca-uninstall-release-wsl-holders after killing the app and its daemon; it ends only the holders this profile recorded, each verified by pid, start time and command line, and keeps any it cannot verify. At startup the WSL host service now releases holders whose distro is no longer a host (a failed add or remove), and every holder while WSL hosts are off; a closed gate releases them too. Co-Authored-By: Claude <noreply@anthropic.com> * fix(wsl-host): a Remove that can't prove the server stopped keeps the host, pending A partial Remove dropped the host anyway, leaving a server whose live terminals block the next add's activation. Remove now drops the host only on a proven stop; otherwise it records a pending stop on the WSL record, keeps the host listed and says why (live or unverifiable). Remove again retries without ever booting a stopped distro (it says to start it); Connect or Add on the same distro keeps the host; a distro that is no longer registered finishes. Nothing reconnects a pending host on its own. Co-Authored-By: Claude <noreply@anthropic.com> * fix(wsl-host): E11 review — keep holders when records are unreadable; finish removals a stopped or renamed distro proves - Startup keeps every holder when the WSL host records can't all be read (unverifiable), and no longer re-adopts a pending host's holder. - Remove matches a renamed distro by GUID (isWslDistroRegistered), and a stopped distro finishes a pending Remove: the cold probe proves the stop. - Only the user's Connect or Add withdraws a pending Remove; other connects are refused, and re-adding respects startIfStopped. - Settings' Remove carries the kept result, so it warns instead of 'Removed'. - A holder record without a start time is never killed on its command line alone, except the one this process just spawned. Co-Authored-By: Claude <noreply@anthropic.com> * fix(wsl-host): E11 review 2 — a closed gate keeps live hosts' holders; stop a renamed distro by its current name - With the gate closed, a launch releases only orphan holders (no host record, or a pending Remove), under the same keep rule as startup; a user with no holder records costs one folder check, nothing else. - The keep rule re-reads host records per holder and keeps an Add in flight. - Remove resolves the distro's current name from its GUID and stops it there. - The uninstall command arms its exit timer first and exits 1 if setup throws; NSIS launches it only when a userData holder folder exists. Co-Authored-By: Claude <noreply@anthropic.com> * fix(wsl-host): never boot a host whose Remove is pending at the next launch Early wake built its host list from every record, so a host focused when its Remove ended pending was booted at each launch, undoing the stop's proof. It now skips pending records, and Remove forgets the host's early wake whatever the outcome. Co-Authored-By: Claude <noreply@anthropic.com> * fix(wsl-host): no wake for a pending host; the e2e fake stops an unbridged server like the real one - mayWake skips a host whose Remove is pending, so a due automation can't boot it (focus already couldn't). - The e2e fake connector read a host with no bridge as stopped. Since E9 a re-enable connects nothing, so Remove after off/on left the host's shells running. Like the real connector, it now reconnects the always-running fake distro to stop its server. - Status bookkeeping moves to WslHostStatusBoard, and the pending-host connect rule to admitConnectToPendingHost, to keep the service under max-lines. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
ea1cb2f18f |
fix(terminal): a WSL bridge pane that lost its distro keeps its session across a relaunch (#34200)
#34095 turns a bridge pane's exit into host loss (code -1) when its distro is gone, so the window keeps the tab and the history stays unended. But main's exit handling still retired the pane's surface from the saved workspace session, as for any provider-observed exit, so the next launch found no session id for the tab and started a fresh shell instead of cold-restoring. The adapter now labels that exit hostLost, the pty listener forwards it, and the runtime keeps the surface, as it already does for a sleep or an SSH loss. Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
f4103b8d3e | test(accounts): cover the workspace-folder fallback for account-restart resume cwd (#34203) | ||
|
|
e79235371f | fix: restore main typecheck after concurrent merges (#34202) | ||
|
|
01db1c6326 |
feat(orchestration): let users choose the worker heartbeat interval (#34071)
* feat(orchestration): add a Settings switch to turn worker heartbeats off Dispatched workers are told to send a heartbeat every 5 minutes. A new "Worker heartbeats" switch under Settings > Agent Orchestration (on by default) lets users turn that off: newly dispatched workers are no longer told to send heartbeats, and the stale-heartbeat check is skipped. The interval the brief states and the stale check both derive from one resolver over the live setting, read from the runtime's own store like the other orchestration settings. * feat(orchestration): let users choose the worker heartbeat interval While worker heartbeats are on, Settings > Agent Orchestration now shows a "Heartbeat interval" field (1-60 minutes, default 5). Newly dispatched workers are told to check in at that interval, and the stale-heartbeat check uses twice it. The description explains the tradeoff: shorter gives more frequent check-ins and more messages, longer gives fewer messages and longer gaps. Out-of-range or malformed values fall back to 5, both when saved and when read. Both heartbeat settings now live in a settings group owned by the heartbeat module, composed into GlobalSettings like other feature groups. * Test heartbeat preferences across settings and worker dispatch * Keep focused heartbeat preference contracts * test(orchestration): cover saved heartbeat intervals and runtime consumers * Explain partial runtime fixture assertion * Correct CLI integration fixture contracts * fix(settings): indent the heartbeat interval under Worker heartbeats |
||
|
|
07b5c083bd |
AI fix actions use the + menu's agent picker and remember chat or terminal (#31310)
* Source control actions start chats and terminals on their saved model A "start an agent" action's model lived only in free-text CLI arguments, which a native chat never reads, so AI Fix opened a chat on the default model. Each action now saves a structured model and effort that both routes apply: chat create options, or the agent's own flags in a terminal (winning over the same flag in CLI arguments). Desktop, dialog, fix-checks and mobile launches carry it; Settings rows get Model/Effort selects and the CLI arguments field says it is terminal-only. Tracked in STA-11102. * Name the model in the repository override note * Type the dialog's model hand-off; keep Agent in English in Japanese copy * fix: preserve action chat model choices through launch * Preserve action selection ownership across chat launches * Keep terminal host contract fixtures aligned with preflight * fix: wait for action Settings agent inventory * fix: consolidate direct agent routing imports * fix: use standard action option labels * fix: align action launch contracts with shared types * fix: sync action option localization metadata * test: provide action Settings inventory in mounted fixtures * Keep action options row height stable while loading * Let each Source Control action choose its chat permission mode An action's saved chat choice may now carry a permission mode, with or without a model; "Same as new chats" saves nothing. A model is replaced only when the action names one, so a permission-only choice keeps the chat's remembered model and options. * fix(native-chat): leave older hosts their own permission mode and keep action options readable - An action's saved permission mode is sent only to hosts that advertise agentSession.create.options-mode.v1. Older hosts get no mode, in create options or a later setOption, so the chat starts on that host's new-chat default, as a phone launch to such a host already does. Hosts from 1.4.225 to 1.4.227 refused a mode their tables lacked (OpenCode, Grok, OMP), leaving the action unable to start. - Settings action rows give Model and Permissions full rows in the options column so saved values are readable; the loading placeholder reserves the same rows. - Remove two unused locale keys; fix two stale comments. - Tests: the older-host create carries no permission mode; a permission mode picked alone keeps the remembered model on an acquired create. * fix(settings): reserve one options row while loading an action with nothing saved Terminal and permissions-only rows no longer shrink when loading ends; a chat agent with a model list may grow by its Model row once known. * fix(native-chat): keep the create options mode a checked literal type * fix(settings): share verified action option fields * fix(settings): keep action selectors on standard typography * feat(agents): Create worktree and continuation pickers offer chat or CLI per agent, like the "+" menu The Create worktree, Create folder and session-continuation agent pickers now list the same rows as the tab bar "+" menu: chat agents first, each with a terminal button that picks the agent's CLI instead, then the agents that only run in a terminal, labelled "(CLI)". A terminal pick shows as "Claude (CLI)" and starts the agent in a terminal even when chats are the default. A continuation into a subfolder shows chat as unavailable there. * fix(agents): picker rows keep the combobox item spacing instead of restyling CommandItem * chore: drop accidental lockfile churn * fix(agents): type the surface picker's props and the composer's agent rows * fix(agents): submit the picker selection captured by each form * test(agents): include repository identity in continuation fixture * Keep the launch files under their length limits after the main merge The structured route imports its result types where they are defined, and the two older-host action-launch tests share one setup helper. * feat(source-control): Source Control AI actions pick chat or CLI with the unified agent picker, and saved actions remember it The shared Source Control AI action dialog (commit/push failure fix, checks fix, resolve conflicts, resolve comments, PR-page fix checks) now lists the same rows as the tab-bar "+" menu: chat rows with a hover terminal button, and "(CLI)" rows. The pick carries chat-or-terminal into the launch. - One inventory: the dialog's own detection is gone; agent list, default selection, status copy, Start gating and auto-start all read the same host observation the "+" menu reads (the worktree's host, or the repo's host for the PR page's not-yet-created workspace). - The captured launch choice threads through runSourceControlAgentActionStart into launchAgentInNewTab, and on the PR page through the fix dialog into both launchWorkItemDirect planning sites. - Saved recipes gain optional `surface: 'chat' | 'terminal'`, bound to the recipe agent like launchPreferences: normalized, inherited, copied on Customize, dropped on agent change, compared for receipts and matches. A pick saves a surface only where the agent had a chat row. - Default paths (split-button primary, fix checks with and without a workspace, saved auto-start) request a terminal only for a saved terminal; a saved chat follows the settings route so it can still fall back to a terminal. - Settings rows are unchanged here; the dialog layout keeps following the settings route. * Import Source Control action ids and the agent setter once in the recipe test * One action settings section for chat and terminal launches A Source Control action's Model, model options and Permissions now apply whether it opens a chat or a terminal; terminals receive them as the agent's own flags, and a repository's own CLI arguments keep the flags it sets. Extra CLI arguments stay terminal-only. * Make saved source control starts explicit and preserve recipe intent * fix(source-control-ai): one terminal projection for saved action choices Ask in a terminal now states its permission instead of leaving it to the user's own config: Claude and Grok pass --permission-mode default, Codex passes -a on-request -s read-only -c approvals_reviewer="user" (the interactive CLI has no untrusted policy, so a read-only sandbox is what asks before edits). Agents whose CLI has no flag for a mode show the existing "Applies to chats only" hint. The strict launch-preferences projection now requires the launch agent at every caller, composes model ids through the resolver's own step, carries a mode only where the agent's terminal has a flag for it, and the local string wire keeps booleans as 'true'/'false', so Cursor Thinking/Fast reach the terminal and an OpenCode permission-only choice is not refused. The argument parser knows flag arity, so removing a boolean permission flag keeps other options' values, following positionals and '--'. Pre-admission and executor share one terminal admission check on the options the terminal will receive. Customize with Save launches the recipe as it will resolve once saved; legacy partial repository overrides are edited as the complete recipe they resolve to. Empty Extra CLI arguments start collapsed. * fix(source-control-ai): an edited repository action saves complete Every Settings edit of a repository action (agent, model, permission, prompt or arguments) now starts from the complete recipe the action resolves to, whether its stored override is owned or a legacy partial. The resolved agent selection is kept (never an agent only detected to run a default), an explicit null args clear stays null, and empty args stay empty instead of being dropped. Clearing the last preference therefore means the action agent's own defaults rather than re-inheriting Global. The action text draft is lossless: unset or cleared prompt and args stay so until the user types, and the inputs show them as empty, so saving a prompt no longer writes empty args that suppress the agent's default flags. Untouched sibling actions are not rewritten by the edit. * Keep source control correction and completion independent of launch eligibility * fix(settings): style the Extra CLI arguments toggle through Button's own variant and size CI's changed-code quality check refuses restyle classes on Button and CollapsibleContent. Use the ghost variant at size xs with a margin, and put the content spacing on a plain inner wrapper. * Verify saved action launches and lossless repository reloads * Update review refresh consumer after React commit * Preserve independent source control actions and phone option precedence * Repair launch contract test fixtures * Save source control action choices before starting the agent * Report source control recipe write failures without holding agent launch * fix: keep saved action and restart launch recipes consistent * Report pull request action save failures and correct recipe boundary types * fix: describe inherited arguments and chat-only permissions accurately * test: check repository action settings fixture type * test: map saved action options into terminal compiler inputs * Strip Unicode format characters from check log excerpts * test: remove redundant source control action runner cases * fix: retain saved action controls during agent detection * fix(i18n): retire obsolete Portuguese action labels * test: align folder launch fallback mock with outcome export * test: complete source control recovery controller fixture * Keep action argument visibility aligned with selected launch route * fix: carry resolved connector launch intent and mode together * fix: share host agent preferences across source control actions * fix: keep preference refresh tied to observation inputs * Fix optional agent preference contracts and typed fixtures * Require preference keys while preserving undefined values * test: pin shared action launch branches to recorded agent output * test: preserve saved source control choices through detection and migration * test: align launch fixtures with integrated result contract * test: retain recipe and restart contracts after main integration * Unify Source Control action permission settings * Keep native Ask copy with its owning change * Preserve action drafts and old-host permission intent * Consume rejected Source Control action saves * Follow the moved Settings persistence fixture * Keep permission integration contracts in the cross-version test project * Include the action permission inheritance label in English catalogs * Align launch contracts with shared permission recipes * Preserve settings snapshot for Source Control recovery * Align saved action persistence fixture with shared agent picker * Keep Source Control action controls within their Settings columns * Use primitive variants for compact action settings controls * Avoid returning from the launch test store setter * Show action arguments only for terminal defaults and widen recipe rows * Apply terminal-only action arguments visibility to repository overrides * Align action permission control with model controls * Use shared settings label for action permissions * Hide action model controls until argument migration ships * Show action arguments for explicit CLI picks * Preserve Unicode joiners in check log excerpts |
||
|
|
89e272abc5 |
fix(mobile): use desktop's merge gating and PR link rules in the PR panel (#33982)
* fix(mobile): gate PR merge and linking on desktop's shared rules Merge state moves to src/shared so the phone stops offering Merge on drafts, conflicts and blocked PRs, and stops letting branch PRs override explicit links. * fix(mobile): keep stack merges and stale-link recovery in the PR panel Mobile now applies desktop's stack override and drops a linked PR the branch has moved past, and only offers Ready for review when a relaying desktop also forwards it. * fix(mobile): persist stale PR link clears and add a merge recheck The phone now writes desktop's link clear instead of rereading the stale link, and a blocked Merge can be rechecked since nothing on mobile polls PR state. * fix(mobile): guard stale PR link clears like desktop Re-reads the worktree before clearing so a link chosen after the lookup survives, and localizes the merge-state strings the lift exposed to the coverage gate. * test(mobile): drop identity test for worktree link params * refactor(mobile): share one stack-merge decision and trim PR panel wiring * fix(mobile): default worktree bare/archived flags for the stale-link guard * fix(mobile): label the PR merge button from its default merge method |
||
|
|
9c0d30df5e |
fix(native-chat): keep the model an agent actually runs, not its startup report (#32006)
* fix(native-chat): save only the model a chat's turn ran, never a startup report OpenCode's session/new names a model before its catalog loads; that report became the chat's saved model and later sends switched to it. * refactor(acp): move option proof with the agent's own late report * test(pi): expect ranOptions on model-only sends * fix(acp): follow the agent's model after an effort-only pick An effort pick stopped the native model from tracking the agent's later report, so a send with no model wrote the stale startup model back. * test(acp): assert the agent's late model report arrives * fix(pi): read run evidence at the prompt write * refactor(acp): move the option write lifecycle into its own module Keeps acp-structured-options.ts under the 300-line cap after the agent's late report is adopted. |
||
|
|
29a5f89b8a |
Keep same-machine folders with matching Git remotes in separate projects (#32272)
* WIP: same-host same-remote checkouts keep their own project id * WIP: claim the shared project id per checkout surface; drop the display-only clone split * WIP: index derived ids by repo in the hydration normalizer * Resolve workspace project affiliation from current checkout owners * fix: preserve concrete project ownership across catalogs and operations * fix: combine recent project selector imports * fix: enforce canonical catalog reads and preserve search continuity * fix: scope catalog lint exceptions to renderer files * Resolve project search ownership before native candidate limits * Combine duplicate session scope imports * fix: derive returned history row ownership on the host * Reconcile full session history replies by content * Require authoritative project catalogs for terminal snapshots * Preserve registered project claims and partial history results * test: check orphaned setup cleanup state without assertions * fix: align catalog callers and native search fixture contracts * test: check full repo shapes in runtime routing fixtures * Fix checked catalog inputs in compiler regression fixtures * Keep checked PTY fixture repos mutable * test: align catalog fixtures with canonical readers * test: check catalog and runtime fixture inputs * test: check catalog fixtures without outer assertions * test: follow persistence harness relocation * Adapt catalog test inputs to integrated main checks * Test History hashing across cached depth revalidation * test(settings): expect host-qualified setup removal * test: capture host split listings and scope relay recovery * ci: regenerate merge ref * test: type host-split listing diagnostics |
||
|
|
cf381255c4 |
perf(wsl): return orcad's startup compile memory with a malloc mmap threshold (#34187)
V8 frees ~70 MB after compiling orcad's bundle, but glibc keeps it stranded in the main arena. WSL launches of this build's own slot now set GLIBC_TUNABLES=glibc.malloc.mmap_threshold=16384; orcad and its daemon remove it at startup and orcad hands it only to the daemon, so shells, agents and git keep the user's malloc. Older slots never get it. |
||
|
|
584b11288d |
fix(agent-hooks): the WSL hook relay stays down while its distro is stopped (E9) (#34195)
* fix(agent-hooks): the WSL hook relay stays down while its distro is stopped (E9)
verify-15b: after `wsl --terminate`, the relay link died ("mux disposed
(connection_lost); scheduling restart") and about 10 s later a `wsl.exe … launch.sh`
restart booted the stopped distro. The restart already asked whether the distro
runs, but any running-list answer would do, including one from a read that started
before the link died. Now:
- only a confirmed running-list read started after the link died can allow the
restart (the shared startedAfter rule; a failed read counts as stopped);
- while the distro is stopped the relay stays down, and it comes back on its own once
something else confirms the distro runs again (deferUntilWslDistroRunning), or when
a WSL terminal re-ensures it as before. Nothing in recovery boots a distro.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(agent-hooks): keep the Codex home and pi/omp setups across a deferred relay restart
A stopped verdict dropped the relay state before the deferred restart ran, so the
relay came back without the managed Codex home or the pi/omp launch setups.
Capture them first and pass them through. Also re-probe once after 30 s so a
failed running-list read while the distro is up does not leave the relay down.
* fix(agent-hooks): anchor the relay restart check at check time and keep all relay config
The running-list read must start when the restart check runs, not when the link
died: a read begun right after a terminate can still list the distro. A deferred
restart now seeds every relay config field (Codex home, Claude agent view and
config dirs, OpenCode overlays, pi/omp setups) so ensure brings them back.
---------
Co-authored-by: Claude <noreply@anthropic.com>
|
||
|
|
7f846fd4f9 |
Codex restarts keep the configured command before a session is recorded (#33629)
* fix(codex): honor configured command on unrecorded restarts * test: update account restart startup consumers |
||
|
|
028f609b5a |
Keep chat thinking before its answer across history loads (#33628)
* fix(chat): preserve transcript source order across history windows * test(chat): use template literal for mobile transcript fixture * test(chat): place composed transcript contracts across project boundaries * test(chat): move reader-to-phone contract across project boundaries * test(chat): reuse transcript input setup and caller contracts * test(chat): align mobile recordings with source-order capability * test(chat): scope phone transforms and await history snapshot |
||
|
|
5ad2d09ee4 |
fix(terminal): a slept pane wakes in its own folder, with its prompt on a fresh row (#34172)
* fix(terminal): a slept native pane wakes in its own folder, with its prompt on a fresh row On a WSL host (orcad on Linux, bash, no OSC 7) Sleep then Wake reopened the pane in the project root with the new prompt joined to the restored one: - Sleep recorded the shell's folder only for WSL bridge panes. A native shell's checkpoint kept its spawn folder, so Wake started there. Sleep now reads the live shell's cwd (OSC 7, else its process cwd) for the final checkpoint. - The runtime's copy of a cold-restored pane, which a paired host's desktop (and a phone) paints, was seeded without the fresh-shell viewport the window adds, so the new prompt landed on the last restored row. Co-Authored-By: Claude <noreply@anthropic.com> * fix(terminal): skip the process cwd lookup at Sleep on Windows The lookup falls back to lsof, which Windows lacks, so every native pane Sleep would spawn a missing binary. Windows keeps the OSC 7 cwd only. * fix(terminal): bound the Sleep folder read and drop deleted folders The live cwd read now gets min(1.5s, 25% of the remaining Sleep deadline), the same share as the WSL read, so a busy daemon can't eat the final checkpoint's window. A /proc cwd ending in ' (deleted)' maps to null. * test(terminal): pin the Sleep folder read budget without the wall clock * test(restore): read cold-restored history from scrollback above the fresh viewport --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
6e3c10c835 |
Honor browser preferences and modifiers for HTML preview links (#33622)
* fix(browser): honor preview link destinations and modifiers * Clarify the source browser provider contract * test(browser): check preview guest before reporting modifiers * fix(browser): report system link failures and cover preview routes * test(browser): combine HTTP link destination imports * refactor(browser): require source ownership for preview links * test(browser): type the forbidden Active Server getter * fix(i18n): retain required preview error catalog entry |
||
|
|
28b4c555ee |
fix(native-chat): keep successful launches usable when tab lists lag (#33620)
* fix(native-chat): confirm launches from successful create replies * test(native-chat): align launch guards with successful create replies |
||
|
|
a43b07625f |
Restored floating editors share file edits with ordinary tabs (#33617)
* Unify editor owner routes across restore and save * Avoid unrelated catalog traversal in editor owner routing * Complete editor regression test fixture types * Narrow initialized settings in editor regression fixture * Align editor save test mocks and folder catalog fixtures |
||
|
|
8c071149e4 | build: serialize bundled guides one markdown line at a time (#33712) | ||
|
+1 |
891f7e6880 |
fix(source-control): fit local argv prompts to Windows and Linux limits (#34123)
* fix(source-control): fit argv agent prompts to the local command line by truncating the diff Antigravity and the other promptDelivery: 'argv' agents pass the whole commit or PR prompt on the command line. The prompt builders capped the diff at 200,000 characters, but runLocalSourceControlPlan refuses argv over 30,000 UTF-16 units on Windows (and any argument over 120 KiB on Linux), so a large branch diff failed before the agent started. For local targets, when the planned argv would exceed that limit, pick the largest diff budget whose prompt fits (binary search, so Windows units and Linux bytes are both measured on the real plan) and rebuild the prompt with it. This covers the default action template path as well as plain prompts. WSL targets are left to the existing guard because the WSL launcher re-wraps the command. The pre-spawn guard stays as the backstop when the non-diff sections alone are too large. Fixes #34109 * Unify Source Control action permissions and card layout (#30449) * Source control actions start chats and terminals on their saved model A "start an agent" action's model lived only in free-text CLI arguments, which a native chat never reads, so AI Fix opened a chat on the default model. Each action now saves a structured model and effort that both routes apply: chat create options, or the agent's own flags in a terminal (winning over the same flag in CLI arguments). Desktop, dialog, fix-checks and mobile launches carry it; Settings rows get Model/Effort selects and the CLI arguments field says it is terminal-only. Tracked in STA-11102. * Name the model in the repository override note * Type the dialog's model hand-off; keep Agent in English in Japanese copy * fix: preserve action chat model choices through launch * Preserve action selection ownership across chat launches * Keep terminal host contract fixtures aligned with preflight * fix: wait for action Settings agent inventory * fix: consolidate direct agent routing imports * fix: use standard action option labels * fix: align action launch contracts with shared types * fix: sync action option localization metadata * test: provide action Settings inventory in mounted fixtures * Keep action options row height stable while loading * Let each Source Control action choose its chat permission mode An action's saved chat choice may now carry a permission mode, with or without a model; "Same as new chats" saves nothing. A model is replaced only when the action names one, so a permission-only choice keeps the chat's remembered model and options. * fix(native-chat): leave older hosts their own permission mode and keep action options readable - An action's saved permission mode is sent only to hosts that advertise agentSession.create.options-mode.v1. Older hosts get no mode, in create options or a later setOption, so the chat starts on that host's new-chat default, as a phone launch to such a host already does. Hosts from 1.4.225 to 1.4.227 refused a mode their tables lacked (OpenCode, Grok, OMP), leaving the action unable to start. - Settings action rows give Model and Permissions full rows in the options column so saved values are readable; the loading placeholder reserves the same rows. - Remove two unused locale keys; fix two stale comments. - Tests: the older-host create carries no permission mode; a permission mode picked alone keeps the remembered model on an acquired create. * fix(settings): reserve one options row while loading an action with nothing saved Terminal and permissions-only rows no longer shrink when loading ends; a chat agent with a model list may grow by its Model row once known. * fix(native-chat): keep the create options mode a checked literal type * fix(settings): share verified action option fields * fix(settings): keep action selectors on standard typography * Keep the launch files under their length limits after the main merge The structured route imports its result types where they are defined, and the two older-host action-launch tests share one setup helper. * One action settings section for chat and terminal launches A Source Control action's Model, model options and Permissions now apply whether it opens a chat or a terminal; terminals receive them as the agent's own flags, and a repository's own CLI arguments keep the flags it sets. Extra CLI arguments stay terminal-only. * fix(source-control-ai): one terminal projection for saved action choices Ask in a terminal now states its permission instead of leaving it to the user's own config: Claude and Grok pass --permission-mode default, Codex passes -a on-request -s read-only -c approvals_reviewer="user" (the interactive CLI has no untrusted policy, so a read-only sandbox is what asks before edits). Agents whose CLI has no flag for a mode show the existing "Applies to chats only" hint. The strict launch-preferences projection now requires the launch agent at every caller, composes model ids through the resolver's own step, carries a mode only where the agent's terminal has a flag for it, and the local string wire keeps booleans as 'true'/'false', so Cursor Thinking/Fast reach the terminal and an OpenCode permission-only choice is not refused. The argument parser knows flag arity, so removing a boolean permission flag keeps other options' values, following positionals and '--'. Pre-admission and executor share one terminal admission check on the options the terminal will receive. Customize with Save launches the recipe as it will resolve once saved; legacy partial repository overrides are edited as the complete recipe they resolve to. Empty Extra CLI arguments start collapsed. * fix(source-control-ai): an edited repository action saves complete Every Settings edit of a repository action (agent, model, permission, prompt or arguments) now starts from the complete recipe the action resolves to, whether its stored override is owned or a legacy partial. The resolved agent selection is kept (never an agent only detected to run a default), an explicit null args clear stays null, and empty args stay empty instead of being dropped. Clearing the last preference therefore means the action agent's own defaults rather than re-inheriting Global. The action text draft is lossless: unset or cleared prompt and args stay so until the user types, and the inputs show them as empty, so saving a prompt no longer writes empty args that suppress the agent's default flags. Untouched sibling actions are not rewritten by the edit. * fix(settings): style the Extra CLI arguments toggle through Button's own variant and size CI's changed-code quality check refuses restyle classes on Button and CollapsibleContent. Use the ghost variant at size xs with a margin, and put the content spacing on a plain inner wrapper. * fix: keep saved action and restart launch recipes consistent * fix: describe inherited arguments and chat-only permissions accurately * test: check repository action settings fixture type * test: map saved action options into terminal compiler inputs * fix: retain saved action controls during agent detection * fix(i18n): retire obsolete Portuguese action labels * test: align folder launch fallback mock with outcome export * fix: carry resolved connector launch intent and mode together * test: pin shared action launch branches to recorded agent output * test: preserve saved source control choices through detection and migration * test: align launch fixtures with integrated result contract * test: retain recipe and restart contracts after main integration * Unify Source Control action permission settings * Keep native Ask copy with its owning change * Preserve action drafts and old-host permission intent * Consume rejected Source Control action saves * Follow the moved Settings persistence fixture * Keep permission integration contracts in the cross-version test project * Include the action permission inheritance label in English catalogs * Align launch contracts with shared permission recipes * Keep Source Control action controls within their Settings columns * Use primitive variants for compact action settings controls * Show action arguments only for terminal defaults and widen recipe rows * Apply terminal-only action arguments visibility to repository overrides * Align action permission control with model controls * Use shared settings label for action permissions * Hide action model controls until argument migration ships * feat(wsl-host): start a WSL host's distro when one of its automations comes due (E9 B) (#33839) * feat(wsl-host): start a WSL host's distro when one of its automations comes due E9 connect policy, part 2. A WSL host's automations run inside its distro, so a distro that is off (a reboot, an idle release) missed them. While a host is connected the desktop now reads its enabled automations' next run (on connect and every 15 min) and keeps the soonest one per host in userData. When that time comes with the host off, it boots the distro once, and orcad's startup catch-up fires the run within its missed- run grace. A run due while the computer was off fires once Orca starts. Nothing wakes past the grace window, and a connected host is left to its own scheduler. Co-Authored-By: Claude <noreply@anthropic.com> * test(wsl-host): a due automation boots a parked host once, never with WSL hosts off Co-Authored-By: Claude <noreply@anthropic.com> * fix(wsl-host): keep the following run, and forget changed automations (E9 review) Review of #33839: - A run handled while connected dropped the host's next due time. The wake now keeps each host's enabled schedules and computes the following run locally whatever happens to this one (wake failed, past grace, handled by the host), and re-reads the real one from a connected host. - A deleted, disabled or rescheduled automation kept waking the distro at its old time. A successful automation.create/update/delete from this desktop now re-reads the host's automations, as do the 15-minute re-read and every connect. Nothing boots a distro to check: on wake, a distro already running is just reconnected. - wakeForAutomation/isConnected live here now (moved out of #33838); isConnected reads the host's reachability, never booting. Co-Authored-By: Claude <noreply@anthropic.com> * refactor(wsl-host): say isConnected answers for this process; keep the service in bounds isConnected reports whether the host answers through this process; false is not "stopped" (a fresh process has no bridge yet, and the wake just connects). The service's quiet record read moves beside the other record helpers so the file stays within its line limit after the E9 additions. Co-Authored-By: Claude <noreply@anthropic.com> * refactor(wsl-host): give the connector contract its own file; one wake path for focus and automations After rebasing onto #34063, #34093 and #33110 the WSL host service was over its line limit. The connector contract (what the service drives) moves to wsl-host-connector-contract.ts, re-exported from the service, and the focus entry and the automation wake share one private wake step: lift the park, then reconnect unless the host answers, read with #33110's focusReachability so neither pays a WSL round trip when this process has no bridge yet. An automation wake no longer reconnects a host that already answers. Co-Authored-By: Claude <noreply@anthropic.com> * test(wsl-host): an automation wake with no bridge skips the reachability probe Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com> * test(connector): freeze the shipped connector schema behind an upgrade test (#34115) Freezes the connector's shipped table definitions: later schema changes must be additive statements. Adds a baseline fixture and an upgrade test (baseline, then current schema, compared with a fresh database on SQLite and Postgres), plus the statement-shape check relay already uses. No runtime change. * test: remove 30 low-value cases and seven suites (#34120) Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> * test(terminal): a pinned parked tab's process exit asks first, then closes as a pty-exit (#34121) Co-authored-by: Claude <noreply@anthropic.com> * fix(ssh): move enabled SSH automations to the host's Orca server (#34044) * fix(ssh): move enabled SSH automations to the host's Orca server Connecting an SSH host moves its saved state to the host's managed Orca server. An enabled SSH automation refused that move on every Connect ("automations (1), automation runs (4)"), leaving the host unconnectable; Move anyway connected it but stranded the automation on the desktop, where it no longer ran. An enabled automation whose runs have all finished now moves with its run history. The manifest still carries it disabled, which every server version accepts; once the move commits the desktop disables its retained copy and turns the server's copy back on through automation.update, re-sending its start time so the next run is the next future occurrence. A server that can't is noted in Settings; an unreachable one is retried on the next Connect. While a move fences the host, the desktop scheduler, Run now and the launch re-check write nothing for its automations, so a tick can no longer break the fenced export; releasing the fence resumes them. A run still in flight keeps blocking and the refusal now says to wait for it. Fixes #29083 * test(ssh): mock the server automation enabler in the delta-move handler test * test(e2e): keep the Move anyway specs refusing now that enabled automations move The inline Move anyway spec seeded an enabled automation to force a refusal, which this branch now moves instead. It seeds one pinned to an earlier registration of the host, which still stays behind. The relay bridge spec's Move anyway lookup also matched the refusal toast's button since #34041; it now takes the pane's own. * fix(connector): one turn id from the host's stamp everywhere (#33909) The host's turn-start timestamp is the only turn id the connector uses: snapshots, turn ends and replies all carry it, and the desktop's separate turn cache is gone, so they can no longer disagree. The unused turn-bound cancel was removed (Stop is parked). The hook server reads the main agent state through the same shared accessor. * feat(orchestration): add a Settings switch to turn worker heartbeats off (#34070) * feat(orchestration): add a Settings switch to turn worker heartbeats off Dispatched workers are told to send a heartbeat every 5 minutes. A new "Worker heartbeats" switch under Settings > Agent Orchestration (on by default) lets users turn that off: newly dispatched workers are no longer told to send heartbeats, and the stale-heartbeat check is skipped. The interval the brief states and the stale check both derive from one resolver over the live setting, read from the runtime's own store like the other orchestration settings. * Test heartbeat preferences across settings and worker dispatch * Keep focused heartbeat preference contracts * Explain partial runtime fixture assertion * Correct CLI integration fixture contracts * fix(wsl-host): a cold wake that loses orcad recovers by itself instead of leaving a dead pane (#33147) * fix(wsl-host): a cold wake that loses orcad recovers by itself; stopped-distro refusals stay final * fix(wsl-host): identity and pairing refusals stay final; no second wake after a stop; settling is retryable * fix(files): open host files outside workspaces for any client with terminal access (#33958) * fix(files): open host files outside workspaces for any client with terminal access Paired clients that can open terminals on a host can already read and write anything its user can, so the per-terminal provenance gate on files outside workspaces protected nothing. The host now grants any existing file outside its workspaces; older hosts get a clear update message instead of a refusal. Co-Authored-By: Claude <noreply@anthropic.com> * fix(files): refuse SSH, device and WSL-home paths instead of misreporting them Co-Authored-By: Claude <noreply@anthropic.com> * perf(files): size grant digests to the file and skip status checks for local fallbacks Co-Authored-By: Claude <noreply@anthropic.com> * fix(files): read procfs files whose stat reports size 0 Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com> * fix(mobile): resume history sessions with desktop's resume and host rules (#33943) * fix(terminal): keep ConPTY's viewport top through a width change (#34061) * fix(terminal): keep ConPTY's viewport top through a width change, checked against a captured transcript A captured ConPTY 1.23 resize (wsl.exe) shows it keeps the line at the top of its viewport through every resize and repaints only that viewport. xterm keeps the cursor's rows instead: a wider grid that rejoins wrapped rows pulls rows out of scrollback (ConPTY's repaint then overwrites them), and a narrower one that rewraps pushes rows into it (the repaint then repeats them). The windowsPty row rule covered neither. ConPTY-backed emulators now put the top line back on its row after a resize. * fix(terminal): ConPTY resize correction respects unfinished escapes and history replay - Skip the widen correction while the parser is inside an escape sequence, so a resize landing mid-SGR/OSC no longer aborts the app's sequence. - Skip it when an app set a scroll region. - Replay daemon history (cold restore from log, durable rebuild) with the live emulator's ConPTY model, so replayed and live screens agree. - Keep the saved cursor with its text when rows come back on narrowing, and never drop a background-coloured blank row. * fix(terminal): replay a saved log with the resize model of the daemon that wrote it - A daemon now stamps resizeModel into each session's meta; the history reader uses the ConPTY replay model only for a stamped session and keeps xterm's for one an older daemon recorded. - Fix the DECSC adjustment: xterm keeps savedY absolute, so popping a blank row already keeps DECRC on its text; the old +1 sent it to the top row. - Tests: narrow-direction replay, older-daemon replay, DECSTBM skip, DECSC/DECRC after narrowing, a background-coloured blank row kept. * fix(terminal): take the history resize model from the daemon hosting the session Main writes history and rebuilds durable checkpoints, but a daemon outlives an app update, so main's own code is not what the live emulator ran. The daemon now reports its resize model in hello (older daemons omit it, meaning xterm's); main stamps it into meta on open, restamps it when a checkpoint starts a fresh log, and rebuilds durable history with it. The client's token read moved to its own module to keep client.ts under the line limit. Also clamps a saved cursor (DECSC) on a popped row to the new bottom row, as xterm's reflow does. * fix(terminal): a disconnect leaves the history resize stamp alone The client keeps the last daemon's reported model through a disconnect (the next hello replaces it); undefined, before any daemon has answered, now means unknown and skips the restamp instead of reading as an older daemon. Tests: a disconnect mid-commit keeps the stamp, and a Sleep-cache wake onto a newer daemon restamps with its first checkpoint (#34060). * fix(terminal): read the rebuild's resize model through the history manager The durable rebuild called client.getDaemonResizeModel() in the checkpoint path, which tests that fake the client with only request() could not answer, so the rebuild fell back to the live snapshot. The history manager already holds the hosting model's provider; the rebuild reads it there, keeping the checkpoint path's client use to request(). * refactor(connector): the desktop takes Discord and Linear conversations as well as Slack (#33927) The desktop's connector accepts conversations from Slack, Discord and Linear and lists all three sources in its hello; per-source details (the Sent from line) come from one table. Nothing changes until those adapters are configured; behind the experimentalConnectors setting. * fix(settings): show cookie import as available before skill setup (#34097) * Linux cookie import says when secret-tool is missing instead of blaming the keyring (#34099) * fix(browser): report why Linux cookie keys cannot be read * test: cover cookie warning forwarding across import hosts * test: place wire fixture cast rationale at assertion start * fix: declare Linux cookie import warning translations * test: extract WSL host connector fixture to restore lint (#34132) Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> * Size tabs to titles and preserve floating panel drag space (#34025) * Size tabs to titles and preserve floating panel drag space * Stabilize agent tab layout during activity changes * Balance tab widths across titles and tab types * Reserve terminal tab icon space before agent detection * Run floating header drag E2E in the isolated headful project * Prevent native text selection on the floating panel drag handle * Cap expanded tab width at 24rem * Let tabs expand to fit titles in available space * test: remove 81 low-value cases and 12 suites (#34130) Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> * fix(agents): launch Claude Agent Teams as plain orca on Orca servers (#34116) * fix(agents): launch Claude Agent Teams as plain orca on Orca servers A paired Orca server has no SSH connection id, so client launches treated it as a local Linux desktop and typed `orca-ide claude-teams`. Headless servers only put `orca` on PATH. Client launches now read the resolved execution host (SSH or server, except WSL workspaces), and launches built on a headless Linux server use the launcher that server publishes. Fixes #33920. Reported by @williamhrs. Client-side approach from #33987 by @coolwindX; #33975 by @Shubham-Padkonde showed the host-built launch gap. * fix(orcad): keep orca-ide working for older clients on Linux servers Older clients type the desktop orca-ide claude-teams into server terminals. Write an identical orca-ide launcher beside orca. Idea and test from #33975 by @Shubham-Padkonde. * fix(ssh): Stop and remove keeps an SSH host's managed server removed across reload and restart (#34107) * fix(ssh): Stop and remove keeps the managed server removed across reload and restart (#34003) * fix(ssh): recheck the removal hold after a queued Stop settles * fix(ssh): a new managed-server claim lifts the Stop and remove hold * fix(web): a TUI copy the browser refuses offers a Copy button (#34135) Browser clipboards need a recent user gesture, and an OSC 52 copy from a TUI arrives after a host round trip that can outlive it. The web client now shows a replaceable toast whose Copy click writes the refused text. Desktop keeps its existing failure toast. Refs #33937 * fix(editor): let desktop edit host files outside workspaces (#34119) * fix(files): open host files outside workspaces for any client with terminal access Paired clients that can open terminals on a host can already read and write anything its user can, so the per-terminal provenance gate on files outside workspaces protected nothing. The host now grants any existing file outside its workspaces; older hosts get a clear update message instead of a refusal. Co-Authored-By: Claude <noreply@anthropic.com> * fix(files): refuse SSH, device and WSL-home paths instead of misreporting them Co-Authored-By: Claude <noreply@anthropic.com> * perf(files): size grant digests to the file and skip status checks for local fallbacks Co-Authored-By: Claude <noreply@anthropic.com> * fix(files): read procfs files whose stat reports size 0 Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): let desktop edit host files outside workspaces Paired clients with terminal access can already write any file on the host, and phones can now save these files, so desktop grant tabs open editable too. Saves go through the host grant, renewing it when it lapsed and keeping the disk-change check; a grant tab never falls back to writing this computer's same path. Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): renew lapsed host grants for reads, banners and restored tabs Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): ask older hosts for an update instead of reporting a lapsed grant as deleted Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): keep grant tabs read-only on hosts that cannot renew grants Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): check a discarded save right before the grant write is sent Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): pin grant saves to one pairing and grant restored tabs before saving Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): open grant tabs read-only when the host cannot be asked, and restore read-only grants as read-only Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): pin a restored tab's grant request to the save's pairing Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): treat only a proven not-found as a missing granted file Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): keep restored drafts by refusing read-only grant saves instead of locking the tab Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): read a restored grant on the pairing that issued it and keep read-only grants off the tab Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): let every reader of a restored host-file tab ask its host for a grant Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): add no await before ordinary reads and saves pin their pairing Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): explain unrecreatable deleted host files and hide rename for grant tabs Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): move the grant capability probe out of the store-importing module to break an import cycle Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): renew grants without cross-workspace retargeting and settle saves whose reply was lost Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): read back a lost write reply through a fresh grant after a disconnect Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): trust only an unanswered write with byte-exact readback as saved Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): read back only sent writes that lost their connection, including desktop timeout envelopes Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com> * fix(runtime-environments): keep session partitions of saved servers the listing hides (#34134) The registry watcher now reconciles orphaned runtime sessions on every write, so the reconcile must only drop hosts the file proves are gone. It read the filtered listing, which omits newer-format records and servers hidden by an unreadable sidecar or WSL overlay, and checked file presence before reading, so a file vanishing in between read as an empty registry. Build the known set from every raw record id, fail closed on a missing file or an id-less record, and keep the catalog broadcast running if the reconcile throws. Follow-up to #34101. * fix(session-tabs): keep the server's per-device tab pick on the tab the desktop shows (#34082) * fix(session-tabs): keep the server's per-device tab pick on the tab the desktop shows The server hands its remembered pick back whenever the desktop has no tab groups of its own for a workspace. A desktop that kept its groups never reported what it showed, so that pick went stale and such an open landed on the wrong tab. * fix(session-tabs): report only a ready visible pane, and retry after an error answer Name the pane the desktop shows and require it ready, so a report never starts a pending sibling's terminal. A failure envelope no longer marks the pick as reported. * fix(session-tabs): report a desktop's pane once per change and connection Two windows sharing one device id could steer the pick back and forth. Report again only when this desktop's own pane changes, scope the record to the pairing and connection, and resolve the visible tab with the existing helper. * fix(session-tabs): report only the on-screen workspace, compare panes, and remember agreement Reports stay with the workspace on screen, whose pane attaches anyway, so a report never starts a terminal elsewhere. The pick is compared pane for pane, and an agreeing frame records the pane so a later change of this desktop's pane reports again. * fix(session-tabs): settle before reporting, report on opening a workspace, and only to its owner A click records its activation after an async hop, so a report now waits until the pane settles and compares against the latest frame. Opening a workspace reports from its latest frame. A workspace id two servers share is reported only to its owner. The e2e now drives the real flow: a stale pick, then a desktop restart. * fix(session-tabs): keep one outstanding pick check per workspace, fenced to its connection A busy workspace's frames no longer postpone the check. A frame from a replaced pairing or connection is dropped, and a frame without the per-device projection clears the cached one. * fix(session-tabs): bound the pick report caches and clear them on mirror teardown One record per workspace, with the connection in the value. Environment teardown drops reports, frames and timers. The tests use checked types, and the e2e notes why it waits and why it needs more time. * fix(session-tabs): check again when the user moved on before a report finished The host does not order activations, so a report that completes after the user picked another pane may have landed last. Clear its record and recheck from the latest frame. * fix(session-tabs): type the visible pane's leaf as optional * fix(session-tabs): send a browser or chat pick again when a late report landed after it A terminal report that completes after the user picked a browser or chat tab may have had the last word. Re-send that pick the way a click does. * fix(session-tabs): recheck a late report against the host's answer, and fence it to teardown The activate answer is the host's per-device frame after the report, so a late landing is checked against it instead of a cached frame. A report answered after mirror teardown or a new connection does nothing. * test(session-tabs): drop the in-connection suppression check from the restart e2e Whether the desktop repairs a stale pick within the connection depends on which frames settle first; the guarded outcome is the pick after a restart. * fix(session-tabs): reconcile the user's newer pick after any report outcome, timeouts included A report whose answer timed out may still have landed after the user's newer pick. Settle every outcome the same way: retry on failure, then reconcile with what the desktop shows. * fix(source-control): stream large Antigravity generation prompts over stdin (#34148) * fix(rate-limits): show agy's own error when Antigravity usage can't be read (#34106) When agy refuses a usage read with its own error envelope (for example the location eligibility rejection), Orca now shows agy's text, redacted and bounded to one line, instead of the generic "did not report a quota" message. Existing failure precedence and the last good quota bars are unchanged. Fixes #33426 * fix(antigravity): save an agy account whose credential has no id_token (#33580) agy 1.4.7 stores no id_token, so Save current account stayed disabled and the account could not be saved. Save now asks Google's userinfo endpoint which account owns the current access token (only on the Save click), then saves it, or updates the saved account with the same Google subject. The credential is re-read after the lookup, and nothing is saved if it changed. Fixes #33323 * Refine lint performance and safe process execution (#34147) Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> * fix(agent-status): keep an Antigravity run working while its helper agents finish (#34128) When an Antigravity parent ends its turn to wait for invoke_subagent helpers, agy reports the parent's Stop as fullyIdle=false, but its own terminal status says done at each turn end. After two minutes of hook silence Orca let that terminal done replace the hook row, so automations completed while helpers were still working. The parent's busy Stop now marks the row as held open for helpers, and a program's non-boundary done can no longer settle a row held open for child work. Late helper hooks after a completed turn are rejected before they touch parent state. Verified with real agy 1.4.7: helpers slower than two minutes ended runs early on main (3/3) and complete with all helper output and the final report on this change. Fixes #33973 * fix(mobile): match history sessions and scope paths with desktop's rules (#33955) * test: load real modules before timed waits, and ratchet in-test vi.importActual (#34151) * test: load real modules before timed waits, and ratchet in-test vi.importActual Two tests paid a cold real-module load inside their timed wait: - the empty-remote wake test's 1s vi.waitFor raced the post-create refresh's lazy session-tabs import; it now loads those modules in beforeAll; - the runtime label-only create tests called vi.importActual inside each test (19-23s of the 30s budget on the first case); it now runs in beforeAll. test-no-in-test-import-actual flags vi.importActual outside vi.mock/doMock/ hoisted factories, beforeAll and module scope; the 50 existing findings are grandfathered in the flaky-test ratchet baseline. * test: flag vi.importActual in a doMock factory registered inside a test * test: flag vi.importActual in any vi.doMock factory; its load runs on the next import * test: remove 47 low-value cases and 13 suites (#34136) * test: remove 37 low-value cases and 3 suites * test: delete ten more renderer wiring and copy suites * test: drop deleted suite from its contract entry point --------- Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> * Compact worktree project and host pickers with stacked details (#34098) * Compact worktree project and host pickers with stacked details * Align worktree picker markers and action gutters * Extract WSL connector fixture to satisfy file length limit * Restart CI after resolving upstream fixture conflict * refactor: group remote runtime client modules (#34133) * Revert benchmark-only startup loading study (#33912) (#34162) Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> * test: remove 294 low-value cases and 12 suites (#34156) Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> * fix(connector): the Discord gateway sends queued posts, so its replies don't wait for the API to wake (#34131) The always-on Discord gateway worker now runs the same background sweeps as the API (queued posts, held starts, cleanup), so Discord replies go out at once instead of waiting for the scaled-to-zero API to wake. Posts are claimed with leases, so running the sweeps in both services never sends one twice. * refactor(mobile): share agent child-row text and favicon domains with desktop (#33962) * refactor(mobile): share child-row detail text and agent favicon domains with desktop * refactor: share the agent tool preview line with child rows * refactor: translate the child-row Ended label only when shown * fix(mobile): show chat images stored on the host as thumbnails (#33731) * fix(mobile): show chat images stored on the host as thumbnails Fixes #33554 * fix(mobile): read stored chat images two at a time A burst of megabyte replies over a slow link overflows the host's outbound queue and drops the phone's socket. * refactor(mobile): tidy stored chat image read * fix(mobile): skip stored image reads for rows that already left Also ignore a result read through a different host client. * feat(connector): each Slack app verified with its own signing secret at its own URL (#34125) Groundwork for per-company Slack apps. Each Slack app gets its own row with encrypted secrets, and Slack posts to /slack/apps/<app id>/..., where the address only selects which secret to check; a request acts only in a workspace where that app is installed. Rate limits are per address and per app, so one workspace can't hold up another's posts. Schema changes are additive. The existing staging app keeps working on the old route until a documented cutover. Inert for users. * test: remove 368 low-value cases and 4 suites (#34157) Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> * fix(source-control): account for Windows quoting when fitting argv prompts --------- Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com> Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Jinwoo Hong <73622457+Jinwoo-H@users.noreply.github.com> Co-authored-by: OrcaWin <alpha-eng@stably.ai> Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com> Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com> Co-authored-by: Manan <100475418+thefrikidude@users.noreply.github.com> Co-authored-by: Neil <neil@stably.ai> |
||
|
|
0f47bb16e8 |
refactor(mobile): organize native chat prompts and permissions (#34189)
* refactor(mobile): organize native chat prompts and permissions * fix(mobile): preserve extensionless test fixture imports |
||
|
|
0cee6cbd86 |
test: remove 368 low-value cases and 4 suites (#34157)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
53c426f6b4 |
feat(connector): each Slack app verified with its own signing secret at its own URL (#34125)
Groundwork for per-company Slack apps. Each Slack app gets its own row with encrypted secrets, and Slack posts to /slack/apps/<app id>/..., where the address only selects which secret to check; a request acts only in a workspace where that app is installed. Rate limits are per address and per app, so one workspace can't hold up another's posts. Schema changes are additive. The existing staging app keeps working on the old route until a documented cutover. Inert for users. |
||
|
|
57aa892951 |
fix(mobile): show chat images stored on the host as thumbnails (#33731)
* fix(mobile): show chat images stored on the host as thumbnails Fixes #33554 * fix(mobile): read stored chat images two at a time A burst of megabyte replies over a slow link overflows the host's outbound queue and drops the phone's socket. * refactor(mobile): tidy stored chat image read * fix(mobile): skip stored image reads for rows that already left Also ignore a result read through a different host client. |
||
|
|
72f8c87154 |
refactor(mobile): share agent child-row text and favicon domains with desktop (#33962)
* refactor(mobile): share child-row detail text and agent favicon domains with desktop * refactor: share the agent tool preview line with child rows * refactor: translate the child-row Ended label only when shown |
||
|
|
8d32eb0c3b |
fix(connector): the Discord gateway sends queued posts, so its replies don't wait for the API to wake (#34131)
The always-on Discord gateway worker now runs the same background sweeps as the API (queued posts, held starts, cleanup), so Discord replies go out at once instead of waiting for the scaled-to-zero API to wake. Posts are claimed with leases, so running the sweeps in both services never sends one twice. |
||
|
|
4e0f391c38 |
test: remove 294 low-value cases and 12 suites (#34156)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
5b4c77906d |
Revert benchmark-only startup loading study (#33912) (#34162)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
7a9abe48f3 | refactor: group remote runtime client modules (#34133) | ||
|
|
05bbbb9582 |
Compact worktree project and host pickers with stacked details (#34098)
* Compact worktree project and host pickers with stacked details * Align worktree picker markers and action gutters * Extract WSL connector fixture to satisfy file length limit * Restart CI after resolving upstream fixture conflict |
||
|
|
77130982fa |
test: remove 47 low-value cases and 13 suites (#34136)
* test: remove 37 low-value cases and 3 suites * test: delete ten more renderer wiring and copy suites * test: drop deleted suite from its contract entry point --------- Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
acf1a8c6e0 |
test: load real modules before timed waits, and ratchet in-test vi.importActual (#34151)
* test: load real modules before timed waits, and ratchet in-test vi.importActual Two tests paid a cold real-module load inside their timed wait: - the empty-remote wake test's 1s vi.waitFor raced the post-create refresh's lazy session-tabs import; it now loads those modules in beforeAll; - the runtime label-only create tests called vi.importActual inside each test (19-23s of the 30s budget on the first case); it now runs in beforeAll. test-no-in-test-import-actual flags vi.importActual outside vi.mock/doMock/ hoisted factories, beforeAll and module scope; the 50 existing findings are grandfathered in the flaky-test ratchet baseline. * test: flag vi.importActual in a doMock factory registered inside a test * test: flag vi.importActual in any vi.doMock factory; its load runs on the next import |
||
|
|
1d8072173e | fix(mobile): match history sessions and scope paths with desktop's rules (#33955) | ||
|
|
52f4db7196 |
fix(agent-status): keep an Antigravity run working while its helper agents finish (#34128)
When an Antigravity parent ends its turn to wait for invoke_subagent helpers, agy reports the parent's Stop as fullyIdle=false, but its own terminal status says done at each turn end. After two minutes of hook silence Orca let that terminal done replace the hook row, so automations completed while helpers were still working. The parent's busy Stop now marks the row as held open for helpers, and a program's non-boundary done can no longer settle a row held open for child work. Late helper hooks after a completed turn are rejected before they touch parent state. Verified with real agy 1.4.7: helpers slower than two minutes ended runs early on main (3/3) and complete with all helper output and the final report on this change. Fixes #33973 |
||
|
|
875d89af50 |
Refine lint performance and safe process execution (#34147)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
653908a652 |
fix(antigravity): save an agy account whose credential has no id_token (#33580)
agy 1.4.7 stores no id_token, so Save current account stayed disabled and the account could not be saved. Save now asks Google's userinfo endpoint which account owns the current access token (only on the Save click), then saves it, or updates the saved account with the same Google subject. The credential is re-read after the lookup, and nothing is saved if it changed. Fixes #33323 |
||
|
|
fdd9151e17 |
fix(rate-limits): show agy's own error when Antigravity usage can't be read (#34106)
When agy refuses a usage read with its own error envelope (for example the location eligibility rejection), Orca now shows agy's text, redacted and bounded to one line, instead of the generic "did not report a quota" message. Existing failure precedence and the last good quota bars are unchanged. Fixes #33426 |
||
|
|
19b930e8d8 | fix(source-control): stream large Antigravity generation prompts over stdin (#34148) | ||
|
|
6fe0476443 |
fix(session-tabs): keep the server's per-device tab pick on the tab the desktop shows (#34082)
* fix(session-tabs): keep the server's per-device tab pick on the tab the desktop shows The server hands its remembered pick back whenever the desktop has no tab groups of its own for a workspace. A desktop that kept its groups never reported what it showed, so that pick went stale and such an open landed on the wrong tab. * fix(session-tabs): report only a ready visible pane, and retry after an error answer Name the pane the desktop shows and require it ready, so a report never starts a pending sibling's terminal. A failure envelope no longer marks the pick as reported. * fix(session-tabs): report a desktop's pane once per change and connection Two windows sharing one device id could steer the pick back and forth. Report again only when this desktop's own pane changes, scope the record to the pairing and connection, and resolve the visible tab with the existing helper. * fix(session-tabs): report only the on-screen workspace, compare panes, and remember agreement Reports stay with the workspace on screen, whose pane attaches anyway, so a report never starts a terminal elsewhere. The pick is compared pane for pane, and an agreeing frame records the pane so a later change of this desktop's pane reports again. * fix(session-tabs): settle before reporting, report on opening a workspace, and only to its owner A click records its activation after an async hop, so a report now waits until the pane settles and compares against the latest frame. Opening a workspace reports from its latest frame. A workspace id two servers share is reported only to its owner. The e2e now drives the real flow: a stale pick, then a desktop restart. * fix(session-tabs): keep one outstanding pick check per workspace, fenced to its connection A busy workspace's frames no longer postpone the check. A frame from a replaced pairing or connection is dropped, and a frame without the per-device projection clears the cached one. * fix(session-tabs): bound the pick report caches and clear them on mirror teardown One record per workspace, with the connection in the value. Environment teardown drops reports, frames and timers. The tests use checked types, and the e2e notes why it waits and why it needs more time. * fix(session-tabs): check again when the user moved on before a report finished The host does not order activations, so a report that completes after the user picked another pane may have landed last. Clear its record and recheck from the latest frame. * fix(session-tabs): type the visible pane's leaf as optional * fix(session-tabs): send a browser or chat pick again when a late report landed after it A terminal report that completes after the user picked a browser or chat tab may have had the last word. Re-send that pick the way a click does. * fix(session-tabs): recheck a late report against the host's answer, and fence it to teardown The activate answer is the host's per-device frame after the report, so a late landing is checked against it instead of a cached frame. A report answered after mirror teardown or a new connection does nothing. * test(session-tabs): drop the in-connection suppression check from the restart e2e Whether the desktop repairs a stale pick within the connection depends on which frames settle first; the guarded outcome is the pick after a restart. * fix(session-tabs): reconcile the user's newer pick after any report outcome, timeouts included A report whose answer timed out may still have landed after the user's newer pick. Settle every outcome the same way: retry on failure, then reconcile with what the desktop shows. |
||
|
|
8bd6e36d6c |
fix(runtime-environments): keep session partitions of saved servers the listing hides (#34134)
The registry watcher now reconciles orphaned runtime sessions on every write, so the reconcile must only drop hosts the file proves are gone. It read the filtered listing, which omits newer-format records and servers hidden by an unreadable sidecar or WSL overlay, and checked file presence before reading, so a file vanishing in between read as an empty registry. Build the known set from every raw record id, fail closed on a missing file or an id-less record, and keep the catalog broadcast running if the reconcile throws. Follow-up to #34101. |
||
|
|
bec8276291 |
fix(editor): let desktop edit host files outside workspaces (#34119)
* fix(files): open host files outside workspaces for any client with terminal access Paired clients that can open terminals on a host can already read and write anything its user can, so the per-terminal provenance gate on files outside workspaces protected nothing. The host now grants any existing file outside its workspaces; older hosts get a clear update message instead of a refusal. Co-Authored-By: Claude <noreply@anthropic.com> * fix(files): refuse SSH, device and WSL-home paths instead of misreporting them Co-Authored-By: Claude <noreply@anthropic.com> * perf(files): size grant digests to the file and skip status checks for local fallbacks Co-Authored-By: Claude <noreply@anthropic.com> * fix(files): read procfs files whose stat reports size 0 Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): let desktop edit host files outside workspaces Paired clients with terminal access can already write any file on the host, and phones can now save these files, so desktop grant tabs open editable too. Saves go through the host grant, renewing it when it lapsed and keeping the disk-change check; a grant tab never falls back to writing this computer's same path. Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): renew lapsed host grants for reads, banners and restored tabs Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): ask older hosts for an update instead of reporting a lapsed grant as deleted Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): keep grant tabs read-only on hosts that cannot renew grants Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): check a discarded save right before the grant write is sent Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): pin grant saves to one pairing and grant restored tabs before saving Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): open grant tabs read-only when the host cannot be asked, and restore read-only grants as read-only Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): pin a restored tab's grant request to the save's pairing Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): treat only a proven not-found as a missing granted file Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): keep restored drafts by refusing read-only grant saves instead of locking the tab Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): read a restored grant on the pairing that issued it and keep read-only grants off the tab Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): let every reader of a restored host-file tab ask its host for a grant Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): add no await before ordinary reads and saves pin their pairing Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): explain unrecreatable deleted host files and hide rename for grant tabs Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): move the grant capability probe out of the store-importing module to break an import cycle Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): renew grants without cross-workspace retargeting and settle saves whose reply was lost Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): read back a lost write reply through a fresh grant after a disconnect Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): trust only an unanswered write with byte-exact readback as saved Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): read back only sent writes that lost their connection, including desktop timeout envelopes Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
a37c15904c |
fix(web): a TUI copy the browser refuses offers a Copy button (#34135)
Browser clipboards need a recent user gesture, and an OSC 52 copy from a TUI arrives after a host round trip that can outlive it. The web client now shows a replaceable toast whose Copy click writes the refused text. Desktop keeps its existing failure toast. Refs #33937 |
||
|
|
a8c871a271 |
fix(ssh): Stop and remove keeps an SSH host's managed server removed across reload and restart (#34107)
* fix(ssh): Stop and remove keeps the managed server removed across reload and restart (#34003) * fix(ssh): recheck the removal hold after a queued Stop settles * fix(ssh): a new managed-server claim lifts the Stop and remove hold |
||
|
|
43097c517b |
fix(agents): launch Claude Agent Teams as plain orca on Orca servers (#34116)
* fix(agents): launch Claude Agent Teams as plain orca on Orca servers A paired Orca server has no SSH connection id, so client launches treated it as a local Linux desktop and typed `orca-ide claude-teams`. Headless servers only put `orca` on PATH. Client launches now read the resolved execution host (SSH or server, except WSL workspaces), and launches built on a headless Linux server use the launcher that server publishes. Fixes #33920. Reported by @williamhrs. Client-side approach from #33987 by @coolwindX; #33975 by @Shubham-Padkonde showed the host-built launch gap. * fix(orcad): keep orca-ide working for older clients on Linux servers Older clients type the desktop orca-ide claude-teams into server terminals. Write an identical orca-ide launcher beside orca. Idea and test from #33975 by @Shubham-Padkonde. |
||
|
|
a1418865f3 |
test: remove 81 low-value cases and 12 suites (#34130)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
316b1887fd |
Size tabs to titles and preserve floating panel drag space (#34025)
* Size tabs to titles and preserve floating panel drag space * Stabilize agent tab layout during activity changes * Balance tab widths across titles and tab types * Reserve terminal tab icon space before agent detection * Run floating header drag E2E in the isolated headful project * Prevent native text selection on the floating panel drag handle * Cap expanded tab width at 24rem * Let tabs expand to fit titles in available space |
||
|
|
7782fd5171 |
test: extract WSL host connector fixture to restore lint (#34132)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
1b64adbaad |
Linux cookie import says when secret-tool is missing instead of blaming the keyring (#34099)
* fix(browser): report why Linux cookie keys cannot be read * test: cover cookie warning forwarding across import hosts * test: place wire fixture cast rationale at assertion start * fix: declare Linux cookie import warning translations |
||
|
|
823ca6870f | fix(settings): show cookie import as available before skill setup (#34097) | ||
|
|
c1198d2f41 |
refactor(connector): the desktop takes Discord and Linear conversations as well as Slack (#33927)
The desktop's connector accepts conversations from Slack, Discord and Linear and lists all three sources in its hello; per-source details (the Sent from line) come from one table. Nothing changes until those adapters are configured; behind the experimentalConnectors setting. |
||
|
|
0b30b284c6 |
fix(terminal): keep ConPTY's viewport top through a width change (#34061)
* fix(terminal): keep ConPTY's viewport top through a width change, checked against a captured transcript A captured ConPTY 1.23 resize (wsl.exe) shows it keeps the line at the top of its viewport through every resize and repaints only that viewport. xterm keeps the cursor's rows instead: a wider grid that rejoins wrapped rows pulls rows out of scrollback (ConPTY's repaint then overwrites them), and a narrower one that rewraps pushes rows into it (the repaint then repeats them). The windowsPty row rule covered neither. ConPTY-backed emulators now put the top line back on its row after a resize. * fix(terminal): ConPTY resize correction respects unfinished escapes and history replay - Skip the widen correction while the parser is inside an escape sequence, so a resize landing mid-SGR/OSC no longer aborts the app's sequence. - Skip it when an app set a scroll region. - Replay daemon history (cold restore from log, durable rebuild) with the live emulator's ConPTY model, so replayed and live screens agree. - Keep the saved cursor with its text when rows come back on narrowing, and never drop a background-coloured blank row. * fix(terminal): replay a saved log with the resize model of the daemon that wrote it - A daemon now stamps resizeModel into each session's meta; the history reader uses the ConPTY replay model only for a stamped session and keeps xterm's for one an older daemon recorded. - Fix the DECSC adjustment: xterm keeps savedY absolute, so popping a blank row already keeps DECRC on its text; the old +1 sent it to the top row. - Tests: narrow-direction replay, older-daemon replay, DECSTBM skip, DECSC/DECRC after narrowing, a background-coloured blank row kept. * fix(terminal): take the history resize model from the daemon hosting the session Main writes history and rebuilds durable checkpoints, but a daemon outlives an app update, so main's own code is not what the live emulator ran. The daemon now reports its resize model in hello (older daemons omit it, meaning xterm's); main stamps it into meta on open, restamps it when a checkpoint starts a fresh log, and rebuilds durable history with it. The client's token read moved to its own module to keep client.ts under the line limit. Also clamps a saved cursor (DECSC) on a popped row to the new bottom row, as xterm's reflow does. * fix(terminal): a disconnect leaves the history resize stamp alone The client keeps the last daemon's reported model through a disconnect (the next hello replaces it); undefined, before any daemon has answered, now means unknown and skips the restamp instead of reading as an older daemon. Tests: a disconnect mid-commit keeps the stamp, and a Sleep-cache wake onto a newer daemon restamps with its first checkpoint (#34060). * fix(terminal): read the rebuild's resize model through the history manager The durable rebuild called client.getDaemonResizeModel() in the checkpoint path, which tests that fake the client with only request() could not answer, so the rebuild fell back to the live snapshot. The history manager already holds the hosting model's provider; the rebuild reads it there, keeping the checkpoint path's client use to request(). |