Commit Graph
3915 Commits
Author SHA1 Message Date
OrcaWinandOrcaWin 8482a3fbb1 fix(i18n): localize source control count and force-push tooltips (#34639)
Shared remote dropdown builders take count/force-push sentence builders
through RemoteDropdownCopy; English defaults keep mobile and older callers
byte-identical. Desktop uses whole-sentence {{count}} plural keys, also for
the primary action tooltip. Refs #34144.

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-27 17:51:44 -07:00
BingZandOrcaWin 64c12b0f89 feat(plugins): allow language packs to declare a native display name (#13140)
* feat(plugins): allow language packs to declare a native display name

Plugin language packs can set contributes.languagePacks[].displayName so
the Settings language picker shows 中文(繁體) instead of
`zh-TW — pluginKey`. Omitted names keep the previous fallback label.

Fixes #13031

* refactor(plugins): inline language-pack picker label and guard displayName

Inline the one-line picker label fallback, type-check displayName in the
registration guard, drop issue refs from comments, and trim tests.

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-27 17:34:16 -07:00
Neil ea532813b1 refactor: group native chat turn presentation (#34629) 2026-10-27 17:33:03 -07:00
Pandu dwi PutraandBrennan Benson ec49e9fac0 fix(native-chat): list OMP skills in the / menu as /skill:<name> (#31999)
* fix(native-chat): list OMP skills in the / menu as /skill:<name>

* test(native-chat): OMP now carries the Pi-shaped skill profile

* Publish native OMP skills with compatible command catalogs

* Index native skill descriptions once per picker build

* Combine catalog test composer imports

* Correct native catalog test types and project inputs

* Run cross-platform picker scaling contract with mobile tests

* fix: discover native commands before the first chat message

* test: isolate native command discovery from mobile typechecking

* fix: release command discovery ownership after managed root exit

* refactor: reuse the ACP child owner during shutdown drain

* test(acp): load filesystem implementation before test execution

* test: drive discovery close completion explicitly

* test: await discovery admission cleanup between demand waves

* test: control discovery close ordering in demand waves

---------

Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
2026-10-27 17:14:20 -07:00
OrcaWinandOrcaWin 99199b2bd2 fix(i18n): localize GitHub project view errors and states (#34621)
* fix(i18n): localize GitHub project view errors and states

Main now tags Orca-authored project-view failures with an optional
reason code plus host, rate-limit numbers and diagnostic detail; the
English message is unchanged for mobile, older clients and logs. The
renderer maps type/reason to translated copy in the error state, picker,
item dialog and mutation toasts, falling back to the English message for
older hosts and GitHub's own text. Also wraps the layout labels,
unsupported-layout, not-found/too-large copy, picker partial-failure
summaries and the gh sign-in help.

Closes #34589

* test: expect input_too_large reason on oversized project refs

* fix: make project view error copy switches exhaustive

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-27 17:11:45 -07:00
EvgeniiandOrcaWin 16547ff203 fix(i18n): localize the rest of the source control dropdown (#34145)
* fix(i18n): localize the rest of the source control dropdown

The Commit & Push, Push, Force Push, Pull, Fast-forward, Sync, Publish,
abort and Push-before-PR rows and their tooltips were English literals
next to rows that already go through translate(). Route them through
translate(), reusing the primary button's and the conflict card's keys
where the words match, and add 42 keys to the English catalog.

Commit blockers stay English inside eligibility, which compares them,
and are translated only when the dropdown shows them.

* test(i18n): pin the other two commit blockers under the pseudo-locale

The pseudo-locale test only reached the stage-file blocker, so an English
return for the conflict or commit-message blocker still passed. The new
case checks both in the Commit, Commit & Push and Commit & Sync titles.

* i18n: translate source control dropdown keys; trim duplicate pseudo-locale test

Add zh/ko/ja/es/fr/pt translations for the 42 dropdown keys this PR adds to en.json,
matching each catalog's existing source-control glossary. Drop the second pseudo-locale
test; the first already covers commit-blocker titles through the active locale.

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-27 17:03:13 -07:00
Neil acec0e7aa0 test: remove two load-dependent CI flakes (#34613)
- git-binary-compatibility: give the docker image runs of the ref-pairing case
  a 90 s budget; each Git call is a docker exec and the case normally takes
  22-25 s of the 30 s default.
- claude-transcript-catch-up: fire the 5 ms catch-up deadline with fake timers
  only after the fallback lookup has started, instead of racing a real timer.
2026-10-27 16:38:25 -07:00
Brennan Bensonandbeduldul 47018d4844 fix(source-control): decode Kimi generated text by selected format (#34237)
* fix(source-control): read the Kimi answer from stream-json

Kimi Code's text mode prefixes thinking and hook output with a bullet, so the
commit message arrived mixed with narration. The recipe now asks for
--output-format stream-json and the answer is taken from the last assistant
record, which is the commit message (#33556).

A record that requests a tool is narration rather than an answer, so it clears
the candidate: a stream that ends on a tool call yields no answer, which
finalizeFromAgentOutput already treats as a failed run. Only a body whose every
non-empty line is a record counts as stream output, so a plain answer that
happens to contain a JSON line is left alone.

* fix(source-control): decode Kimi output only for the selected protocol

* fix(source-control): satisfy generation hook checks

* Preserve Kimi generation failures and normalize options linearly

* Fix Kimi argument failure messages

* Bound Kimi option failure recognition

* Fix Kimi generation test fixture types

---------

Co-authored-by: beduldul <alkaysan07@gmail.com>
2026-10-27 16:33:33 -07:00
Neil 90c713af1f fix(wsl): refuse Windows drive folders on a WSL host, offer Add on this computer (#34530)
* fix(wsl): refuse Windows drive folders on a WSL host and offer to add them on this computer

A /mnt/<drive> project on a WSL host shows false line-ending changes, misses
edits made from Windows, and searches slowly. Add Project refuses typed,
picked and dropped Windows drive folders for a WSL host and shows the refusal
inline with Add on this computer, which switches the open dialog to this
computer. The WSL-host orcad re-checks by /proc/self/mountinfo (after
resolving symlinks) in repo.add, repo.create, repo.clone, explicit
folderWorkspace.create and the nested scan/import, answering with the
existing runtime_error code plus optional data, so older clients still show a
readable message. Everything is behind the WSL hosts gate; SSH is untouched.

* test(wsl): hold the e2e's this-computer add instead of racing its failure

On the Linux CI host the switched local add of a Windows path fails its nested
scan and hands off to the Open as Folder modal, closing Add Project before the
test looked. The refusal itself already came before any scan. The e2e now
records the local add at its scan step and asserts it went to this computer
with the Windows path; a unit test pins that a refused pick never reaches the
host path step.

* test(wsl): type the e2e's held-scan window hooks instead of Reflect
2026-10-27 16:29:54 -07:00
EvgeniiandOrcaWin 6c469aea6d fix(plugins): reject locale ids Intl cannot parse (#12533)
* fix(plugins): reject locale ids Intl cannot parse

`pluginLocaleIdSchema` checks the shape of a locale id but not its grammar,
and the shape check is looser than BCP 47 in one direction: `en-US-US`
(duplicate region) and `en-aaa` (a subtag that is neither region nor script)
both match it. A pack declaring one installs, loads, and translates every
string — and then `Intl.DateTimeFormat` throws inside `getIntlLocale()`, which
swallows the error and falls back to English. Nothing is logged, so the pack
author sees a working pack with English dates and no way to tell why.

Delegate the grammar to `Intl.getCanonicalLocales` in a `.refine`, so the tag
is rejected at install where the author can still act on it. The bundled
`pt-BR` pack and every other well-formed tag are unaffected.

* Condense this branch's comments to one line

AGENTS.md asks for one-line comments that say why, and main's comment
cleanup (#33249) applied that across the repository. This brings the
comments this branch adds in line with it. No code changes.

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-27 16:22:09 -07:00
Neil 5e49b6dd11 refactor: group native chat context usage (#34595) 2026-10-27 15:47:15 -07:00
Neil f3adb8f85a refactor: group native chat work-run boundaries (#34528) 2026-10-27 15:18:29 -07:00
Kelvin Amoaba 917ef9c737 feat(browser): install Chrome extensions from the Web Store into Orca's browser (#30940) 2026-10-27 22:04:12 +00:00
OrcaWinandOrcaWin 649dc1a6fb test: remove 113 low-value tests (#34541)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-27 14:45:01 -07:00
Neil 8fe31c930e feat(wsl): note why an idle distro stays held, and fail the holder's scan closed (#34534)
* feat(wsl): note why an idle distro stays held, and fail the holder's scan closed

When user work keeps the holder from releasing, it writes the first few process names (at
most 5) to ~/.orca/wsl-holder-blocked, replaced whole and cleared on release, for the desktop
to read later. A /proc without the holder's own entry, or a status file it cannot parse, now
keeps the hold instead of reading as idle.

* fix(wsl): count an unreadable /proc entry only when it is the user's own

Review of #34534: under hidepid=noaccess root's status files are unreadable, so each read as
this user's work and the distro never released. An unreadable entry now counts only when its
directory belongs to this user. The holder also clears a half-written note on start and
rewrites the note only when it changed.
2026-10-27 14:42:00 -07:00
OrcaWinandOrcaWin 9fd9cd7362 test: remove 260 low-value tests (#34535)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-27 14:24:21 -07:00
Jinjing a2b378018a Withhold virtual review tabs from mobile sessions (#34254) 2026-10-27 14:09:22 -07:00
Brennan Benson e71d4358c1 Native chat tabs can hand off work from their right-click menu (#34504)
* Add native chat hand-off menu on main

* Fix saved chat hand-off observations and RPC exports

* Reuse indexed chat tabs for hand-off subscriptions

* Match saved-chat clear fixture to current journal API
2026-10-27 14:06:57 -07:00
OrcaWinandOrcaWin 1d2778fa99 test: remove 150 low-value tests (#34520)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-27 13:57:27 -07:00
Brennan BensonandWooseong Kim 287a34c0e5 fix(github-project): show linked PRs and sub-issue progress (#34185)
* fix(github-project): render linked PR and sub-issue progress values

* fix(github-project): probe schema support for project column values

* fix(github-project): preserve independently supported project fields

* Preserve nullable project values and unsupported fetch concurrency

* Exercise project relation payloads through unchanged consumers

* Combine project coordination test cache imports

* Use checked project payload types in consumer tests

* Place project provider column contract in cross-layer tests

---------

Co-authored-by: Wooseong Kim <innocarpe@gmail.com>
2026-10-27 13:48:54 -07:00
6ecd992f44 Correct GitLab MR checks for failed and manual pipelines (#34176)
* Correct GitLab MR check status for failed and manual pipelines

Use the same single-MR read for linked and branch-discovered reviews so a
list summary cannot hide a failed pipeline. Preserve lookup failures for
strict callers and keep detail reads within the existing branch cache.

Set mergeable manual pipelines to neutral without claiming an unrun stage
passed; keep blocking manual pipelines pending.

Co-authored-by: Son of Odin <2700975-son-of-odin@users.noreply.gitlab.com>
Co-authored-by: Emily <hadikcze@gmail.com>

* test: cover GitLab MR check status consumers

* test: type GitLab MR fixtures from mapper input

* chore: document GitLab MR boundary assertion exceptions

* test: share GitLab MR producer and consumer fixtures

---------

Co-authored-by: Son of Odin <2700975-son-of-odin@users.noreply.gitlab.com>
Co-authored-by: Emily <hadikcze@gmail.com>
2026-10-27 13:47:24 -07:00
Neil f57d00f045 refactor: group shared native-chat upgrade-tip audience (#34509) 2026-10-27 13:17:14 -07:00
OrcaWin fbe08ba14d test: remove 134 redundant tests (#34511)
Removes 134 redundant test registrations across native-chat projection, sidebar ordering, and palette matching. Deletes two entire suites: notice appearance mapping and ordering scenarios whose test-owned Host supplies the behavior being asserted.

Retains 154 registrations covering state transitions, competing inputs, FIFO tool pairing, sidebar feed application, and search ranking. Production code is unchanged. Removes the two deleted suites’ timing entries and lowers the wall-clock baseline only for the deleted Date.now assertion.

Validation: isolated static registration/body preservation, formatting, lint, discovery, runtime routing, and metadata checks. Full PR CI must verify 275 expanded cases across 17 owning test roots, including the transcript-contract aggregator; 185 cases belong to retained selected sources and required counterparts. No local runtime tests were run.
2026-10-27 13:00:29 -07:00
Sojiro.OandBrennan Benson 9802866ed5 fix(editor): Copy Remote URL links to the code the workspace is on, with the selected line range (#33597)
* fix(editor): Copy Remote URL links to the code the workspace is on, with the selected line range

The gutter menu's Copy Remote URL always built the link on the default
branch and dropped any multi-line selection. Prefer the HEAD commit when
origin already has it, then the origin branch the current branch tracks,
then the default branch; carry an optional end line through IPC, RPC and
the git provider so a selection becomes a line range.

* fix: pair remote file links with published repository refs

* fix: prepare exact remote file fallback before publication scan

* test: consolidate remote file URL integration coverage

* test: document real-clock cancellation deadline proof

* test: handle optional cancellation signal in assertion

* test: reuse spawned child fixture across runtimes

---------

Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
2026-10-27 13:00:23 -07:00
Brennan BensonandOrca Worker f0eb0949d0 fix(windows): delete again succeeds after a held file is released (#34058)
* fix(windows): stop recursive deletes from retry-storming when a file is held open

Node's async recursive rm retries every nested entry separately and orphans
sibling walkers when it rejects, so deleting a workspace holding a live
browser profile multiplied filesystem work per directory level until the
main process hung. Delete Windows host trees with a walker that retries
whole passes from one shared budget and leaves nothing running on failure.

Also bound and log detached worktree removal, and fail a file transaction
whose proper-lockfile lock is compromised instead of throwing from its timer.

* fix(windows): retry a locked delete as whole passes instead of a custom walker

Replace the hand-rolled tree walker with Node's own recursive rm and no
per-entry retries. Async rm gives each nested entry its own retry counter and
never stops siblings, which is what multiplied the work; with retries off each
pass is one bounded walk, and a transient Windows lock repeats the whole pass
from the existing 250/500/1000/2000 ms budget, checking the job's signal
between passes.

A failed delete now names the file another program holds open instead of
Node's EBUSY/EPERM text. Drop the 30-minute background deadline. The lost-lock
error no longer embeds the library's message and says the write may or may not
have been saved.

* test: cover bounded deletion failure and recovery contracts

* test: prune unchanged cleanup coverage

* fix(worktrees): give truthful failed-delete cleanup advice

* test: document fake-clock retry adapter

* fix(windows): preserve checkout ownership until files are removed

* fix: preserve worktree ownership checks across metadata aliases

* test: make checkout retry clock completion explicit

* Keep failed Windows workspace deletions retryable

* test: correct removal fixture imports and path formatting

* fix: retain failed removal until a retry is accepted

* test: identify the mocked backoff clock

* test: preserve failed removal records and recreate marker fixtures

* test(worktrees): preserve exact checkout bytes in refusal contract

* test(worktrees): exercise current native deletion contracts

* test(windows): prove long-path deletion through native checkout removal

* test(windows): preserve real Git runner exports in removal fixture

---------

Co-authored-by: Orca Worker <orca-worker@localhost>
2026-10-27 12:31:10 -07:00
OrcaWinandOrcaWin 0294e1118a test: remove 47 low-value tests (#34505)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-27 12:20:50 -07:00
Neil 55dffb479a refactor: group shared native-chat empty-state copy (#34503) 2026-10-27 11:55:40 -07:00
OrcaWinandOrcaWin 05fc67ff51 test: remove 69 low-value syntax, script, policy and chat tests (#34497)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-27 11:30:19 -07:00
Neil 8414076859 refactor(shared): group native chat notice presentation (#34481) 2026-10-27 11:23:49 -07:00
Brennan Bensonandm4air 4a39d186da Extract conversation switch foundations without activating them (#34384)
Co-authored-by: m4air <m4air@Mac.localdomain>
2026-10-27 10:27:58 -07:00
Kelvin Amoaba 5429d20f43 fix(mobile): show files named like constructor as plain text instead of failing diffs (#34475)
Mobile kept its own copy of the language tables and looked file names up
on plain objects, so constructor, toString or __proto__ returned an
Object member and lowlight threw. Mobile now uses desktop's shared
detector, which only reads own keys; .make moves into the shared table
so mobile keeps its Makefile highlighting.
2026-10-27 17:21:27 +00:00
Neil 1c8c0685fb refactor: group shared native chat appearance settings (#34469) 2026-10-27 10:16:32 -07:00
BingZ efd0a09f69 fix(native-chat): resolve /D:/ chat file links to the drive in Windows workspaces (#34367)
In a drive-letter workspace, strip the leading slash from URL-style
/X:/ file hrefs before resolving, so links like /D:/Temp/report.txt
open D:/Temp/report.txt. POSIX, WSL UNC, and UNC hrefs are unchanged.

Fixes #34310
2026-10-27 09:48:32 -07:00
Kelvin AmoabaandNico Hu 3ddaa8df6f fix(mermaid): keep flowchart labels readable on custom node fills (#34452)
Mermaid draws every flowchart label in the theme's text colour, so a
`style` or `classDef` fill can hide it: light text on a pale node in dark
mode, dark text on a deep one in light mode. After rendering, labels that
fall below 4.5:1 on their node's fill switch to whichever theme colour
reads better, on desktop previews, chat and the phone.

Co-authored-by: Nico Hu <haoyu.hu@lexmount.com>
2026-10-27 16:38:00 +00:00
Kelvin Amoaba 53e6a7d4a9 feat(mobile): copy button on shell command rows in chat (#34432)
* feat(mobile): copy button on shell command rows in chat

* test(mobile): stub the copy button where chat tests count tool row presses

* fix(chat): decode the login-shell script the way the shell does

Codex joins argv by switching quote styles, so stripping only the outer
quotes left \" escapes and quote splices in about a fifth of real
commands. Argv arrays are now shell-quoted when joined.

* fix(chat): keep the shell-path match to the outer command; reuse the label's full command

Argv arrays go back to a plain join: no argv-shaped shell calls exist in
real transcripts, and quoting them broke PowerShell and cmd.exe argv.

* test(mobile): leave quote decoding to the shared unwrap test

* refactor(chat): slice double-quoted runs and name the row's command fields plainly

* style(mobile): format copy button mocks in chat row tests
2026-10-27 16:34:48 +00:00
Kelvin Amoaba e310a63624 fix(mobile): use desktop's rules for queued messages, turn status, Stop and the chat composer (#34000)
* refactor(mobile): share the queued-card projection with desktop

Image-only queued drafts showed a blank card on the phone.

* fix(mobile): honor the host's Queue follow-ups setting

With it off, a mid-turn send from the phone still queued while desktop sent it into the running turn.

* fix(mobile): keep a queued-card edit when the card leaves the queue

The phone closed the editor and dropped the typing; it now goes to the chat box as on desktop.

* fix(mobile): hold /clear and /compact for background work and sends

The phone fired the command where desktop holds it, showed start failures twice, and left the agent unnamed in failures.

* fix(mobile): hand a queued edit back to the chat it came from

* fix(mobile): scope a command's send hold to its own chat

* fix(mobile): read a published null queue as empty

* refactor(mobile): share the returned queued-card caption rule

* test(mobile): drop queued-card tests the shared rules already own

* refactor(native-chat): share the needs-attention rule and drop leftover wrappers

* fix(mobile): type the structured sends mock, drop the moved queued-cards path and ship queued edit copy at boot

* fix(native-chat): drop the queued card's unused image-label import after the rebase

* fix(mobile): order the phone's queue reorder preview by position, as the shared cards sort

* test(mobile): keep the queued-messages test within its line budget

* fix(mobile): settle terminal chat working state and turn timing with desktop's rules

Move desktop's live-status merge, Stop suppression, hook-state resolver and
terminal turn timing to src/shared/native-chat. Mobile reads the transcript
lifecycle the host already sends, so a provider turn end settles Working the
same way desktop does. Terminal chats now get the turn bar, timer and folding,
and the streaming preview uses the shared deriveNativeChatStreamingText.

* fix(mobile): send desktop's terminal Stop keys, a second Escape only for OpenCode

Desktop sends one Escape on Stop. It adds a paced second Escape only for
OpenCode, which confirms an interrupt that way. Claude Code and Codex read
Esc-Esc at an idle prompt as rewind. The rule moves to
native-chat-agent-support, and the phone now paces the second Escape at
desktop's answer step instead of 80ms.

* fix(mobile): word Orca-stop and usage-limit notices like desktop

Move desktop's Orca-stop sentences to src/shared with an English table that
desktop translates. The phone names the Orca host it pairs with, and when
that host is unnamed it says "the remote server". Usage-limit rows rebuild
desktop's sentence from the failure fact. The usageLimitLineText fallback,
which only the phone used, is deleted.

* test(mobile): pass the overlay's host name in the prompt controller harness

* test(mobile): re-record Stop goldens at desktop's step, split status-notice tests, pin the turn clock and ship notice copy at boot

* fix(mobile): offer structured Stop while a send is out and read queue-sends-next as working

Move desktop's structured Stop rule, its Stop-joining helpers and the
queue-sends-next rule to src/shared. Both sides now use them. The phone
counts its in-flight sends, so a conversation-stop host offers Stop before
the turn opens. Between queued turns the phone reads as working, and
commands that can't wait in line hold like they do on desktop. Untargeted
Stops are no longer joined on legacy hosts.

* fix(mobile): offer terminal Stop again when its Escape went nowhere

Stop hides Working on the phone like it does on desktop. The phone's Escape
can fail outright, though, while desktop writes to a local PTY. When no Escape
could have landed, the phone now drops that suppression. The streaming preview
also treats a pending echo as the transcript's tail, as desktop does, so an
earlier reply can't hide a new preview.

* fix(mobile): hold structured Stop while a send it covers is in flight

On desktop, Stop's held and Stopping state depends on whether the chat can
stop, and that includes a send still in flight. The phone now does the same.
Once Stop is pressed before the turn opens, the button holds and repeated
presses send no more untargeted cancels.

* fix(mobile): end the terminal Stop hold when a new message is sent

Desktop clears Stop's working suppression on an optimistic send, so a new turn
that keeps the same hook epoch (Claude with working subagents) still offers
Stop. The phone now does the same when a new pending echo appears.

* refactor(mobile): trim chat turn wiring after the desktop rule move

Drop the controller's unread nativeChatAgentWorking field. Re-render only when
a chat starts or stops having a send out. Keep the structured turn indicator
stable across stream frames. Type the Stop test table instead of casting.

* refactor(mobile): track structured sends in flight once for Stop and command holds

* test(mobile): re-record Stop goldens now that Stop settles with its Escape delivery

* fix(mobile): escape terminal image paths like desktop drops

* fix(mobile): keep launch-draft prefill over older user turns

* fix(mobile): rank @ file matches with desktop's fuzzy Quick Open search

* fix(mobile): use desktop's composer triggers for mid-prompt / and $ picks

Picked @ files are now quoted when the path has spaces.

* fix(mobile): send picked skill paths on structured chats

* fix(mobile): list the host's disk-scanned skills in the / and $ menus

The phone names the workspace and the host resolves its folder, refusing SSH
workspaces as desktop does; hosts without skills.discover-workspace.v1 list none.

* fix(mobile): forget a picked skill once its token is deleted

* fix(mobile): drop a picked skill as soon as its token is deleted, and retry failed skill scans

* fix(mobile): treat a picked leading skill as chat and stop failed skill scans from refiring

* test(mobile): drop the menu ranking case the shared picker tests own

* refactor(mobile): keep skill picks on the draft record and reuse shared send rules

A rejected send now keeps its picks and leading-skill origin on both send paths.

* fix(mobile): replace a re-picked skill's file and restore picks with a rejected send

* fix(mobile): read the chat agent for the skill catalog from the active resolution

* style(native-chat): format the composer autocomplete files

* fix(native-chat): import the picker's apply and send-classify rules from the shared composer module

* refactor(mobile): import the composer's draft-store hooks once

* style(mobile): format the notice row's style import
2026-10-27 15:34:56 +00:00
Kelvin Amoaba f776923c04 fix(mobile): use desktop's rules for chat tool rows, pending echoes and session option picks (#33977)
* fix(mobile): resolve terminal chat agents in desktop's order

Mobile now uses the shared detected-then-launch precedence and transcript-readability check; the phone's remembered agent only fills in after them.

* fix(mobile): hide Codex foreground commands from the background-task strip

* refactor(native-chat): share diff-card gutter, basename and task count

* fix(mobile): show clipped tool output sizes in KB/MB like desktop

* refactor(native-chat): share the tool-run header rules with mobile

* fix(native-chat): share tool-line detail rules; skip unsafe-only search hits

* fix(mobile): copy message text with desktop's rule

Copy now leaves out roster and background-task fallback twins and wordless provider frames.

* refactor(native-chat): memoize shared tool-line view and output sizes; share result preview

* fix(native-chat): read a lone result's preview from its narrowed body

* chore(i18n): ship chat tool and stop copy in the runtime English catalog

* refactor(native-chat): move the pending-send echo rule to shared

Mobile reuses it instead of its own matcher.

* fix(mobile): match chat echoes after their send boundary, sink unmatched ones

Uses desktop's rule: rows before the send no longer retire an echo, a send that
never lands no longer lets later glued sends retire, and an unmatched echo sits
below later turns.

* fix(mobile): keep glued photo captions and folded boundaries in echo matching

* fix(mobile): give image preview echoes the send time the occurrence rule reads

* fix(mobile): match echoes on image-normalized rows and cap open sends at eight

Same input and bound as desktop; each open send rescans the transcript.

* test(mobile): drop a pending-order case the tail test already covers

* refactor(mobile): read the send boundary once and skip echo normalization when idle

* test(native-chat): type the occurrence case's pending send

* test(mobile): drop the pending-echo wall-clock entry from the flaky-test baseline

* refactor(native-chat): share session option labels with mobile

Mobile's options pill now shortens effort levels (Med, XHigh, Min) and names
choices and options the way desktop does, from one English table that desktop
translates.

* refactor(native-chat): run mobile terminal chat options on the desktop surface

The terminal-chat option surface, its appliers, the option cache and the
dispatch types move to src/shared, and the phone builds its pickers from them.
Grok and every other agent with a catalog now get model and effort pickers on
the phone, picks are saved as the host's launch defaults, the OMP live switch
gate and discovery mapping come from one copy, and authoritative discovery
retires persisted models it no longer lists. The option stamp moves to shared.

* refactor(mobile): merge the session option type imports

* fix(mobile): keep terminal chat option picks on their own chat

The phone keeps one option surface per chat, so a pick that lands after leaving
and returning shows there, and a picker command only switches the chat it came
from. Discovered models merge with the seed catalog as on desktop, so Grok keeps
its effort picker. A Claude model switch the phone cannot confirm is never
saved as a launch default.

* fix(mobile): start terminal chat options over when a tab changes agent

A tab that runs another agent drops its kept option surfaces, report markers
and cached record, so a fresh session shows its own model. A pick that lands
after the phone moved to another chat is not saved as a launch default.

* fix(mobile): fence retired terminal chat option surfaces

A write that lands after its tab started another agent no longer publishes the
old agent's record, and a changed OMP switch capability rebuilds the chat's
surface from the cache instead of reviving an older one.

* refactor(native-chat): simplify the shared session option wiring

Desktop translation pieces use literal English defaults so the localization gate can read them, the selected-choice lookup is shared once, and the phone keeps one option surface per tab with the agent change detected from the cached record.

* refactor(mobile): return no option surface for an agent without a catalog

* test(native-chat): expect the shared Effort label in the startup picker test

* test(native-chat): keep only the label cases main still checks after the rebase

* refactor(native-chat): import the session option snapshot rules once in the PTY option surface

* refactor(native-chat): share structured option pick bookkeeping with mobile

Desktop and the phone now track picks per option through one shared book: a
repeat of an option on its way waits, other options go together, a lost reply
is not a pick done, and a stale reply only commits its own option. The phone
also re-reads options each turn and after the provider starts, and shows picks
at once while the host is still starting the provider.

* refactor(native-chat): share the option pick blocking rule

* fix(native-chat): read in-flight option picks from the shared book for launch send options

* fix(native-chat): keep the structured options hook within its line budget and pass the phone turn in the e2e harness
2026-10-27 15:00:27 +00:00
Kelvin Amoaba c903d30283 fix(mobile): build the Source Control action sheet from desktop's menu rows (#34047)
* fix(mobile): build the Source Control action sheet from desktop's menu rows

Adds Force Push and desktop's order, enable rules and hints.

* fix(mobile): rebase from desktop's effective base and keep the Force Push warning in the action sheet

* fix(mobile): keep the rebase row's base when the branch compare fails

* fix(mobile): keep upstream compares working when the default base lookup fails

* fix(mobile): keep the rebase target apart from the branch compare so failed or unsupported compares keep it

* fix(mobile): leave force pushes to desktop when the linked review has its own push target

* refactor(mobile): rebase onto the shown base and share the force-push block with the primary action
2026-10-27 13:13:25 +00:00
27a8963806 fix(windows): probe fnm's real default alias dir for Node fallback (#11359)
* fix(windows): probe fnm's real default alias dir for Node fallback

On Windows, fnm stores the default alias under FNM_DIR, else
%APPDATA%\fnm (legacy ~\.fnm), and node.exe sits directly in
aliases\default with no bin subdir. Probe those dirs and append them to
PATH so fnm's default only backfills a missing Node instead of shadowing
an inherited one.

Fixes #11356

Co-authored-by: niceSprite <16523864+iFwu@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>

* test: keep onTestFinished callbacks returning void

---------

Co-authored-by: Neil <neil@stably.ai>
Co-authored-by: Claude <noreply@anthropic.com>
2026-10-27 06:08:14 -07:00
mmarabelandNeil ad4b814018 fix(orchestration): drop the subshell parens from typed setup commands (#22537)
The observed (`worker-start --setup run`) and sequenced (`wait-for-setup`) setup
commands are typed into the user's interactive shell. Pair-inserting line
editors such as zsh-autopair rewrite the `( ` of the `( bash runner )` wrapper
into `(  )`, so bash -lc receives a stray `)` and rejects the whole line: setup
never runs, no completion marker is printed, and the worker stays at
setup_state: running (or the agent gate waits out its timeout).

The runner command is always a single external command (bash/cmd.exe/
powershell.exe), so the subshell added nothing; run it directly.

Fixes #18059

Co-authored-by: Neil <neil@stably.ai>
2026-10-27 05:41:00 -07:00
5b9073344a fix(terminal): detect Codex footer when shortcut help sits under the status row (#24338)
Codex can render a separate `? for shortcuts` row below its status row. The
composer classifier returned on the first nonblank bottom row, so it never
examined the real status row above the hint and the IME placeholder mask
never activated, leaving the placeholder beside composing text.

Fixes #24337

Co-authored-by: Neil <neil@stably.ai>
Co-authored-by: Andy Zhang <16486422+v01dstar@users.noreply.github.com>
2026-10-27 05:30:24 -07:00
Seiji KoharaandNeil 9b0170cbfa fix(i18n): localize hosted review creation errors (#33368)
Main now tags each Orca-authored PR/MR create failure with a reason code
(the English error is unchanged for mobile, older clients and logs), and
the renderer maps the reason to translated copy in the Source Control
notice, the Checks panel and the pre-create blocked notice. Sign-in steps
are single-sourced across providers.

Fixes #33321

Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-10-27 05:02:01 -07:00
Neil 295ed991dd refactor: group shared native-chat session options (#34356) 2026-10-27 04:14:07 -07:00
e49cab0a92 fix(workspace-board): paired hosts keep their own custom status columns (#34362)
* fix(workspace-board): paired hosts keep their own custom status columns

A desktop client grouped a paired host's workspaces with its local column
list, so cards in host-only columns (e.g. status-6) fell back to the default
column. Fetch each host's workspaceStatuses via the existing ui.get RPC and
merge them after the local columns for grouping, without persisting them.

Fixes #34227

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(workspace-board): keep paired host columns safe from local column edits

- Removing a local column resolves cards against the merged board list, so a
  host card in a host-only column is never rewritten.
- New column ids are unique against the merged list, not just local ones.
- The context menu status submenu and the closed-sidebar order use the merged
  columns too; the shared-status helper moves to the menu policy module.
- A host that sends no columns adds none instead of the defaults; identical
  replies keep the stored identity and out-of-order replies are dropped.
- The merged list is named boardStatuses and tolerates stores without the
  host fields, so the earlier WorktreeList fixture edits are reverted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(workspace-board): keep host cards whose host still defines a removed id

Removing a local column whose id a paired host also defines rewrote that
host's cards to the local fallback. Skip runtime-host cards when their own
host still has the column.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(workspace-board): keep host column ids in the composer and drop a retired host's columns

Creating from a host-only lane now keeps that column's status, a host that is
removed or re-paired to another machine no longer leaves its columns behind,
and the new tests use checked fixtures instead of casts.

Co-authored-by: Kooooojun <edisonhuang1122@gmail.com>

* fix(workspace-board): deliver a host's workspaceViewChanged so its columns refresh

Co-authored-by: Kooooojun <edisonhuang1122@gmail.com>

* fix(workspace-board): show and offer a paired host's columns only for that host's cards

The board adds a host's column only when one of that host's own cards uses it,
never the host's copy of the default column, so local cards keep falling back
to the local list. The context menu offers host columns only when every card
is on that host, the composer applies a lane's host column only when creating
on that host, and status writes drop another host's column id.

Co-authored-by: Kooooojun <edisonhuang1122@gmail.com>

* fix(workspace-board): read cards through the record selectors and skip foreign-lane drops

Board lanes and the context menu now leave out a host's copy of the default
column, so a host card's menu matches its lane. Lanes skip the card scan when
no host adds a column. A drop into another paired host's lane is ignored
instead of re-ranking the lane.

Co-authored-by: Kooooojun <edisonhuang1122@gmail.com>

* fix(workspace-board): sync tasks against every offered column and test host-lane drops

Task-status sync now finds a paired host's column that no card uses yet, as the
card's menu offers it. A write left empty after dropping another host's column
is skipped. New tests cover board and sidebar drops into a host-only lane.

Co-authored-by: Kooooojun <edisonhuang1122@gmail.com>

* fix(workspace-board): resolve host columns by runtime owner and compare mixed selections per card

A paired host's SSH workspace, which the host's runtime owns, now gets that
host's columns like its other cards. A mixed selection marks and moves each
card against its own host's columns. A status write for a card the store does
not know yet passes through unchanged.

Co-authored-by: Kooooojun <edisonhuang1122@gmail.com>

---------

Co-authored-by: Kooooojun <edisonhuang1122@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 03:02:14 -07:00
HansssandNeil 433d044d65 fix(i18n): localize every contextual tour step (#12713)
Only the automations and client-hosted-browser steps had an id-keyed
entry in the localized step copy map, so every other contextual tour
(workspace board, agent sessions, browser, tasks, floating workspace,
workspace creation) rendered English titles, bodies, and action labels
next to localized Back/Next/Done controls.

Give every tour step a required stable id and move the copy lookup into
contextual-tour-step-copy.ts. The map `satisfies` a record over all step
ids, so a new step without localized copy is a type error. Primary and
secondary action labels (Split terminal, Got it, Browser settings) are
localized through the same entry. Existing automations and
client-hosted-browser keys are unchanged so shipped translations keep
resolving.

Add the new strings to en and translate them for ko, es, ja, zh, fr,
and pt.

Co-authored-by: Neil <neil@stably.ai>
2026-10-27 02:34:54 -07:00
Brennan Benson 6708d27687 Cookie import adds cookies without signing you out of sites (#34113)
* Import cookies without clearing existing sessions

* fix(browser): keep new cookie imports merge-only

* fix(browser): admit native cookie preparation through session lock

* fix(browser): retire superseded shipped cookie imports

* test(browser): make cookie expiry fixtures deterministic

* test(browser): restore cookie clear mock type import

* fix(browser): show skipped cookies in import result toast

* test(browser): expect native cookie imports to preserve existing coordinates

* fix(browser): report only successfully imported native cookie domains
2026-10-27 01:50:25 -07:00
Neil c8823b4c6f refactor: group shared native chat composer input (#34328)
* refactor: group shared native chat composer input

* refactor: consolidate concrete composer imports
2026-10-27 01:50:08 -07:00
Neil ab9532ecd8 feat(wsl): let an idle WSL distro stop once its server idle-exits (#33084)
* feat(wsl): let an idle WSL distro stop once its orcad idle-exits

The WSL host's holder kept the distro (and the WSL VM) running after Orca quit, even with
nothing running in it. orcad now leaves a release request in ~/.orca when a managed idle stop
retired its terminal daemon; the holder waits for that orcad to exit, claims the request and
ends, so WSL can stop the distro. Live terminals, working agents, enabled automations or a
returning client keep the distro held as before. A host whose distro is stopped at startup
reads as stopped instead of unreachable, and the real-WSL lane gains a phase that proves the
release and records memory.

* fix(wsl): key the holder release on the WSL-host launch marker; name the lane phase

The real-WSL lane showed orcad idle-stopping with its daemon retired while the distro stayed
up: the setsid'd orcad's environment is not guaranteed to carry WSL_DISTRO_NAME, so the
release request was never written. Use ORCA_WSL_ORCAD_HOST, which only WSL-host launches set.
Phase 3 now carries its phase name and path filter, and records what kept a distro running.

* test(wsl): dispose the idle-release lane's guest transports

Each guest command left its exec loop running, a wsl.exe client that kept the distro up after
the holder had already let go (the receipt showed no holder, no orcad, no request left).

* test(wsl): record which wsl.exe clients keep the idle-release lane's distro up

* test(wsl): satisfy the flaky-test ratchet; feed the new idle port in the release test

* test(wsl): snapshot guest processes after launch to find what holds the session

* test(wsl): locate the step that leaves the zombie holding the idle distro

* test(wsl): log the idle-release lane's guest commands with times to place the zombie

* test(wsl): follow the remote runtime client's move

* test(wsl): record when each leftover WSL session init started

* fix(wsl): keep the distro while the user still runs anything, and never trip on the request file

Review of #33084:
- The holder now checks, before claiming a release, that no process of the user runs outside
  the holder itself (session plumbing aside: systemd --user, (sd-pam), dbus-daemon). A detached
  tmux, nohup job or dev server keeps the distro; it fails toward holding.
- A new holder drops any request left from before it started, so an older orcad's request can
  never end a holder a client just asked for.
- orcad touches the request file only for WSL-host launches and never throws over it.
- The real-WSL lane proves a detached job keeps the holder and its request, and the distro
  stops once the job ends.

* fix(wsl): a running container keeps the distro, whoever owns its shim

Docker's containerd-shim processes run as root, so the user-only scan missed them and a
release would have stopped running containers. Any containerd-shim process now keeps the hold.

* fix(wsl): read each process status only up to Uid; document what keeps the hold

Delta review of #33084: dash reads a status file a byte at a time, so stop at Uid. Document
that a root default user never releases, that per-user agents hold it, and the hidepid
exception. The lane's pkill no longer matches the shell running it.
2026-10-27 01:28:40 -07:00
Neil 0ed5f4bb21 fix(orcad): materialize the app's agent-browser driver into the local slot (#34150)
* fix(orcad): materialize the app's agent-browser driver into the local slot

Replaces #34111's ORCA_AGENT_BROWSER_DRIVER hand-off, Windows profile copy and
claimed snapshot store. Packaging now references the app's own
resources/agent-browser-<target> from the orcad template manifest
(packagedBrowser, like packagedRipgrep), so the materialized slot carries it and
every local orcad launch finds it beside orcad-server.js. macOS signs the driver
before hashing; Windows reseals it after SignPath. The resolver now also tries
the musl driver name on Linux.

Refs #33846

* build(orcad): let a checkout keep template drivers with ORCAD_OMIT_AGENT_BROWSER=0
2026-10-27 01:28:20 -07:00
OrcaWinandOrcaWin 755bbfaa13 test: remove 53 low-value cases and eight suites (#34302)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-27 01:16:41 -07:00