Commit Graph
20429 Commits
Author SHA1 Message Date
OrcaWinandOrcaWin f4e4862f00 test: remove low-value terminal coordination and startup cases (#40512)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-09 15:11:59 -08:00
Kelvin AmoabaandWenhao 2783f8e461 fix(mobile): keep a finished agent tab's icon when its name mentions another agent (#40513)
* fix(mobile): stop reading a tab's name as its agent's terminal title

The host publishes a terminal tab's name (custom name, quick-command
label or agent session name) in place of its live title. Mobile fed
that name to the shared tab-agent resolver as title evidence, so a
finished Claude tab named "Agy status bar item" was read as a reused
Antigravity pane. Desktop resolves from the raw title and shows Claude.

Fixes #40084

Co-authored-by: Wenhao <4804785+Manho@users.noreply.github.com>

* fix(mobile): re-render a terminal tab when only its name changes

---------

Co-authored-by: Wenhao <4804785+Manho@users.noreply.github.com>
2026-11-09 23:10:07 +00:00
Brennan Benson 50ecb96893 Offer only the speeds the model lists (#40257)
A speed the chat reports that no model lists, in practice Flex from the
user's own Codex config, is no longer added to the Speed choices. It
still runs and is still sent. A chat with no model of its own keeps its
saved speed when some model lists it, so Standard can still turn it off.
2026-11-09 15:08:48 -08:00
Jinjing 2fca8c3e6f docs: slim CONTRIBUTING.md to the essentials (#40272)
* docs: slim CONTRIBUTING.md to the essentials for getting a PR merged

Move dev-environment reference into docs/development.md and the maintainer
release process into docs/releasing.md.

* docs: match CONTRIBUTING visual-proof guidance to the PR template

* docs: cut dev-environment internals and drop the stale release doc

Trim docs/development.md to the setup steps people actually hit, drop
docs/releasing.md in favor of the self-documenting Cut Release workflow,
and move the RC Homebrew cask into the README.

* Document Node compatibility and dev profile cleanup
2026-11-09 15:07:39 -08:00
Brennan Benson 9174df298d fix(claude): isolate new launches from parent sessions (#40281)
* fix(claude): isolate independent launches from parent session environments

* test(claude): use supported account environment fixture
2026-11-09 15:06:28 -08:00
Kelvin Amoaba 1f63f18a45 feat(browser): simplify the toolbar to one Annotate button and one menu (#40501)
Grab, Annotate and Draw become one Annotate split button. DevTools, open
in default browser, hard reload, find and extensions move into the menu,
with the profile list, new profile and cookie import under Profile. Zoom,
viewport size, password offers and file actions show as chips inside a
flat address field, and the Import hint moves to the new tab page. The row
drops from 50 to 40 px and the fold from nine stages to two.
2026-11-09 23:03:58 +00:00
Kelvin Amoaba f0733cc86e fix(mobile): keep unchanged lines in diffs of large files (#40511)
Files past the LCS cell budget fell back to prefix/suffix diffing, so two
edits at the ends of a 450-line file showed every line as rewritten. Use
jsdiff's Myers diff bounded by edit count for those files, keeping the
prefix/suffix fallback for mass rewrites.
2026-11-09 23:03:00 +00:00
Kelvin AmoabaandEng. Mahmoud Bek ElNemer bd8138b231 fix(mobile): keep the selected GitHub project when switching projects (#39964)
* fix(mobile): keep the selected GitHub project when switching projects

Picking another GitHub Project on the phone snapped back to the first one.
A remembered desktop Board view made the pick throw before it committed,
and a committed pick wrote picker rows (title, summary) into settings,
which the host's strict schema refused, so the next hydration restored
the old project.

Commit only identity fields, ask for a view when the remembered one is
not a table, keep the candidate project's views out of the active list
until it commits, drop late view replies from an earlier pick, and key
Browse rows by project identity.

Co-authored-by: Eng. Mahmoud Bek ElNemer <tt21913@gmail.com>

* fix(mobile): keep github.com implicit in project refs and error on projects with no table view

---------

Co-authored-by: Eng. Mahmoud Bek ElNemer <tt21913@gmail.com>
2026-11-09 22:53:54 +00:00
Kelvin Amoaba a5dbd1cb2f feat(mobile): read dictation progress to VoiceOver and TalkBack (#40504)
* feat(mobile): announce dictation to VoiceOver through the shell

* feat(mobile): speak dictation from the host, so leaving the session and the pill's toasts are announced too

* fix(mobile): say dictation outcomes where they are known, and re-read a repeated live message

* fix(mobile): leave a setup refusal to its setup sheet instead of reading the raw code

* fix(mobile): say cancelled when a kept recording is discarded
2026-11-09 22:52:59 +00:00
3acd6ede7c fix(automations): reopen a reused automation chat tab in the background (#40271)
* fix(automations): reopen a reused automation chat tab in the background

An automation that reuses its last chat queued the prompt into that
session even after the user closed its tab, but never brought the tab
back. After a reused send is accepted (including a lost or refused reply
recovered from the run receipt), reveal the session and publish its tab
with activate:false so it reappears without taking focus. A publish
failure is logged and never undoes the accepted send.

Extract the reveal + background publish pair into
publishChatTabInBackground and share it with reopenWorkerChat.

Fixes #40260

Co-authored-by: Wooseong Kim <innocarpe@gmail.com>

* test(automations): use the string workspace id in the chat-reuse harness

---------

Co-authored-by: Neil <neil@stably.ai>
2026-11-09 22:45:14 +00:00
OrcaWinandOrcaWin cdcb7c5e67 test: remove 36 low-value terminal lifecycle cases (#40503)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-09 14:43:03 -08:00
OrcaWinandOrcaWin 62adb576a6 test: remove 54 low-value chat and terminal tests (#40500)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-09 14:31:31 -08:00
Kelvin Amoaba b49fa738e9 fix(speech): skip a canceled dictation's queued decodes, also during Finish (#40483)
* fix(speech): drop a canceled dictation's queued decodes, also during Finish

A cancel during "Finishing…" never reached the speech process, and a cancel
that did waited in line behind every decode queued before it, so the next
dictation sat behind audio nobody wanted. The host now sends the discard during
Finish too, and the speech process answers it at once and skips the stream's
queued work.

* fix(speech): close an audio port whose stream was canceled before it attached

* fix(speech): restart the speech process when a canceled decode outlasts a short grace

A cancel now answers at once, so a decode already running for the canceled
stream (hung in native code, or just long) could hold the queue for the next
dictation. The host waits up to 2 s for the speech process to reach the
discard; past that, with no other dictation on it, the process restarts, and a
dictation starting meanwhile waits for that instead of reusing it.

* fix(speech): skip a canceled stream's remaining chunks inside one feed or finish

* fix(speech): keep a failed restart after a cancel from failing the next dictation
2026-11-09 22:30:08 +00:00
OrcaWinandOrcaWin d6e6355a70 test: remove low-value chat surface suites and cases (#40495)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-09 14:20:24 -08:00
OrcaWinandOrcaWin 1500ba4153 fix(acp): reset reply digest when a subagent restarts (#40496)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-09 14:18:35 -08:00
Kelvin Amoaba f9a10a75f1 feat(native-chat): bring back the New divider behind a setting (#40490)
Restores the line above messages that arrived while you were away, the scroll to it on return and the screen-reader announcement, all removed in #38044. A new Chat > Behavior switch, "Mark new messages when returning to a chat" (on by default), turns it off; off tracks nothing.
2026-11-09 22:16:18 +00:00
Jinwoo Hong bd56be7146 feat(orchestration): mail an agent on a paired server with send --on; its reply comes back by itself (#40106)
* feat(orchestration): mail agents on a paired server with send --on, replies come back by themselves

* fix(orchestration): gate --on on the carrying Orca, ack retried deliveries, refuse payloads and federated workers

* chore(orchestration): annotate peer-mail row casts and drop a wall-clock wait in its test

* chore(orchestration): name mail-between-servers codes server_mail_unsupported and mail_requires_server_pairing

* docs(cli): list --on in the orchestration reply usage

* fix(orchestration): name --environment, the flag on main, in agent mail refusals and the guide

* chore(orchestration): mark the two deliberate agent-kind branches mail between servers needs

* docs(cli): leave --on out of the reply usage; it is accepted only to refuse it

* fix(orchestration): keep peer conversations to peer ids, survive resets and re-pairs, keep pulling on a registry error

- A server takes only peerconv_ conversation ids, so a paired computer cannot name another Orca's dispatch in the relay.
- A replayed reply after a mail reset is acknowledged, not retried forever; reset tasks keeps replies waiting to be pulled.
- A re-paired server starts a new conversation instead of refusing every later send and reply.
- A failed registry read keeps the pull loop retrying.
- Drop the two ast-grep-ignore lines that only #40193's rule needed.

* fix(orchestration): worker-start --on runs on the caller's own Orca, like send --on

An inherited ORCA_ENVIRONMENT sent worker-start --on to that server, so the
--on command the agent refusal suggests did not work. One rule now keeps
send, reply and worker-start with --on on the caller's own Orca.

* fix(orchestration): refuse reply --on on both sides of a conversation between servers

The side that opened the conversation still took --on when it named the right
server; the reply usage says --on is accepted only to refuse it.
2026-11-09 17:00:11 -05:00
Brennan BensonandClaude Opus 5.5 b7ac7e5178 perf(native-chat): keep streaming chats from re-projecting their whole transcript (#40251)
* perf(native-chat): keep streaming chats from re-projecting their whole transcript

Each stage of the streaming transcript pipeline (reducer merge, question
pass and receipts, message projection, desktop list fold) keeps its
previous input and output and re-derives only revised or appended rows,
falling back to the existing full projection whenever another row could
change. Desktop folds through the phone's fold units, now shared, and live
trims batch by a bounded slack so appends keep row positions.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* perf(native-chat): reuse appended subagent rows and batched revisions

Appended rows in chats with subagent rows extend their turn chunk when
earlier turn inputs are unchanged; batch merges and multi-row revisions
do one pass each; rows without journal positions keep in-place reuse.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* perf(native-chat): look up subagent chunks once per appended batch

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* test(native-chat): pin the live trim slack

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-11-09 13:46:36 -08:00
Brennan Benson bfa33f6c1c perf(agents): release completed helper payloads and avoid history scans (#40171)
* perf(agents): release published child payloads and index live work

* perf(codex): preserve live task order on membership changes

* fix(codex): preserve parent-first helper interruption

* test(codex): assert public helper task identities

* fix(codex): keep helper roots in original stop order

* fix(codex): retain complete live helper ancestry for Stop

* Preserve sibling order when reasserting helper ownership
2026-11-09 13:46:19 -08:00
Kelvin Amoaba b491746314 fix(agent-picker): apply a model or effort picked in a form's setup panel (#40494)
* fix(agent-picker): apply a model or effort picked in a form's setup panel

* fix(agent-picker): keep the open setup panel when the form takes its pick

* fix(agent-picker): keep a form's accepted pick across scope resets and panel close

* fix(agent-picker): stage Arguments chip edits and keep picks compiler-safe
2026-11-09 21:39:57 +00:00
OrcaWinandOrcaWin a6538f08e1 test: remove 12 low-value paste and split tests (#40491)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-09 13:33:03 -08:00
OrcaWinandOrcaWin 471fb019e5 test: remove 16 low-value chat tests (#40488)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-09 13:31:22 -08:00
OrcaWinandOrcaWin 7eb868339c test: remove 21 low-value tests and two suites (#40479)
* test: remove 21 low-value tests and two suites

* test: remove Claude test-only background roster getter

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-09 13:29:53 -08:00
Kelvin Amoaba 854928969e feat(mobile): add Shift, Ctrl and Alt latches and opt-in agent keys to the terminal key row (#38776)
* feat(mobile): smart rail keys for the terminal agent's state, with Shift/Ctrl/Alt latches

* fix(mobile): cancel key presses only when the key row really moves

* fix(mobile): keep Smart rail on through Reset Defaults and finish two-write keys

* fix(mobile): only a finger scrolling the key row cancels its presses

* fix(mobile): hold the smart group until the tap's press lands, and drop clicks on keys that moved

* refactor(mobile): simplify the smart rail touch hook and layout read

* chore(mobile): allowlist the Shift, Ctrl and Alt key names

* feat(mobile): Codex async question keys on the smart rail

* fix(mobile): drop the Codex Always key, whose key differs by approval

Codex binds "don't ask again" to p for a command-prefix rule and a for session and file approvals (0.136 through 0.166). The permission hook doesn't say which one is on screen.
2026-11-09 21:19:11 +00:00
Kelvin Amoaba 1899653040 feat(settings): manage dictation vocabulary in Voice settings, per user and per repo (#40471)
* feat(settings): add a Vocabulary group to Voice settings for personal and repo terms

* feat(speech): use the repo name as a dictation hint without recasing one-word names

* fix(settings): use Input and Button styling as the design system defines it

* fix(settings): chain quick repo-term edits, report a host that drops them, keep the hint off phone replies

* fix(settings): key a pending repo-term write by host too

* refactor(settings): catch a dropped repo-term write in updateRepo and keep the name hint out of stored terms

* fix(settings): one vocabulary chip per term with its aliases, and no repo suffix on the scope tab

* fix(settings): skip a bare vocabulary term that already has an entry
2026-11-09 21:18:14 +00:00
Kelvin Amoaba 313fb8733e fix(speech): reload the warm recognizer once the VAD download lands (#40477)
A recognizer that loaded before the Silero VAD file existed kept cutting text
only at stop until its next restart. When the VAD lands, the speech service now
unloads that recognizer once no dictation uses it and warms it again, so pause
cuts start on first use. A running dictation is never interrupted.
2026-11-09 21:18:06 +00:00
Kelvin Amoaba c55bee0485 refactor(claude): move the kill-delivered receipt check out of the session adapter (#40481)
The adapter crossed the 300-line cap after #40069 and main's lint fails. The same receipt check ran twice in it; one shared predicate brings the file back under the cap with no behaviour change.
2026-11-09 21:06:44 +00:00
Brennan Benson ab9f29c1da Fork Codex replies after rewinding a chat (#40140)
* Fork Codex replies from the current history after rewind

* Strengthen Codex fork preparation failure coverage

* Preserve Codex fork compatibility and original chat guidance

* Explain when Codex cannot start for a fork
2026-11-09 12:57:55 -08:00
Kelvin Amoaba 4e42cc2a3f fix(speech): keep a slow GPU model load on the GPU while it still makes progress (#40472)
The GPU stall watch gave the whole model load one 25 s budget, so a cold disk
or busy machine restarted a healthy load on the CPU and could miss the 60 s
start limit. The speech process now reports each load step, and the watch
restarts on it; a step that hangs for 25 s still moves to the CPU.
2026-11-09 20:49:37 +00:00
Kelvin Amoaba 81e5e5a9ef feat(settings): redesign Voice settings around a setup card and a rated model list (#40452) 2026-11-09 20:46:25 +00:00
Kelvin Amoaba acf3aead78 fix(agent-status): show Codex's mid-turn async question as waiting for the user (#39087)
* fix(agent-status): show Codex's mid-turn async question as waiting for the user

* fix(agent-status): keep Codex's async question waiting on paired hosts under its working title

The phone's PTY-title renewal turned the waiting row back into working, because Codex keeps its working title while the question waits.

* fix(agent-status): clear Codex's open async questions when the user sends a plain message

Orca's chat card answers an async question as a quoted message, not Codex's reply wrapper, so the pane stayed waiting until the turn ended.

* refactor(agent-status): move the legacy status test seed out of listener-state
2026-11-09 20:42:22 +00:00
Kelvin Amoaba fe1620cdf5 fix(chat): always show copy and fork under a finished agent turn (#40474) 2026-11-09 20:39:58 +00:00
OrcaWinandOrcaWin 387fe35bfb test: remove low-value mobile and attachment cases (#40475)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-09 12:36:29 -08:00
Brennan Benson 2e1c6475ee Use Claude CLI titles for default native chat naming (#40069)
* Reuse Claude CLI titles for default chat naming

* Preserve independent naming while fencing Claude title reuse

* Keep optional title account lookup from blocking chat naming

* Clarify deferred preparation in naming tests

* Bind first chat naming to its ready handover

* Exercise title cleanup through a real queued command

* Use the timestamped operation fixture for compaction

* test: exercise naming fallback through Send now

* test: exercise terminal naming fallback after final starts
2026-11-09 12:35:26 -08:00
Brennan Benson c804008e4f Show friendly advice for Codex turn failures (#39959)
* Show friendly Codex turn failure advice

* Match terminal failure callback to status row type

* Keep terminal diagnostics in Details and clarify unknown failure advice

* Preserve usage-limit diagnostic metadata

* Validate custom host advice in phone renderer fixture

* Check categorized compaction failures and retained diagnostics

* Complete localized model-unavailable notices

* test(mobile): keep the failure notice helpers main's test cleanup removed
2026-11-09 12:34:12 -08:00
Brennan Benson 3ee128db1a Keep Claude background tasks attached to their subagent after restart (#39958)
* Keep Claude background tasks linked to their subagent across restarts

* Keep task ownership scoped to each Claude invocation

* Keep partial task events scoped to their invocation

* Distinguish pending task facts from admitted invocations

* Wait for saved task ownership before interpreting Claude events

* Verify journal binding order and saved task liveness

* Keep owned task updates from reopening Claude root turns

* Exercise owned historical notifications with provider identity
2026-11-09 12:33:19 -08:00
Brennan Benson b602376e8b Show AskUserQuestion option previews on desktop and phone (#40109)
* Show AskUserQuestion option previews on desktop and phone

Claude can attach a preview (a mockup or snippet) to each option of a
single-select question. Orca dropped it, so users chose between bare labels.
Options now carry the preview through the journal, terminal asks and the
phone, and the question card shows the selected option's preview as plain
monospace text. Questions with previews confirm explicitly instead of
auto-advancing, so the preview stays readable.

* Keep phone previews bounded and digit focus on the named option

Phone previews get a capped height with their own vertical scroll, and
opening one never scrolls past its top. A digit always focuses its row
before the chosen-row check, so Enter confirms the option the user named.
Tighter preview line height, a stable phone row root, and a persistence
test whose expected previews come from the fixed input.

* Narrow the reopened question with a type guard instead of a cast
2026-11-09 12:31:52 -08:00
Kelvin Amoaba c66199ab94 feat(tab-group): make the split pane landing rows outline buttons (#40469) 2026-11-09 20:26:57 +00:00
OrcaWinandOrcaWin 3a8b100f92 test: remove low-value speech, sidebar and composer checks (#40470)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-09 12:24:06 -08:00
Jinjing f9816d8c73 fix(i18n): avoid gendered review labels in Spanish (#40442) 2026-11-09 12:22:59 -08:00
Brennan BensonandClaude Opus 5.5 376cf18634 perf(native-chat): addressed tab-map transitions for chat membership (#40098)
* perf(native-chat): project structured chat tabs per workspace bucket

The shared chat-tab list was keyed on the whole unifiedTabsByWorktree
identity, so every tab write anywhere (terminal title batches included)
rescanned all tabs and handed every consumer a new list. Rebuild only the
buckets whose identity changed and return the previous list while no chat
tab changed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* perf(native-chat): reconcile chat status membership per changed tab

The status bridge rebuilt every member and host group and captured every
chat on any tab-map or owner-input change, and recaptured every chat on any
launch notification. Membership now updates only the tabs whose identity
changed; owner-input changes re-resolve only unstamped tabs, the only ones
whose host depends on them; launch notifications name their session so only
its tabs are recaptured (unaddressed ones still recapture all). The sleep
and launch-directory companions of one projection land in one store write.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* chore(ratchets): guard whole tab-map triggers and hot-map listeners

Add a count ratchet for identity comparisons of the whole
unifiedTabsByWorktree/tabsByWorktree map in renderer code (counts may only
fall), wired into pnpm lint, run-ratchets discovery and changed-check
selection. Extend the advisory no-whole-hot-map-selector rule to inline
store listeners that compare a whole hot map and to effect bodies that use
one whole from getState().

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* revert(lint): drop the hot-map listener/effect extension

The guard stays scoped to the repaired seams; no repository-wide rule change.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(native-chat): capture chat status on semantic tab changes; address tombstone retirement

Focus, preview and order-only tab writes no longer recapture a chat's
status: membership and the projection fences compare the fields the
projection reads. Absent-tombstone retirement now names the sessions it
retired, so no launch producer sends an unaddressed notification.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* feat(store): keyed-record transition seam for tab maps and companion records

Writers build next tab buckets and keyed companion records through
replaceTabBuckets / replaceRecordEntries (or name the keys of a record they
already built), which record exactly which keys and tab IDs changed against
the produced record. Readers ask readTabMapChanges / readRecordChanges for
an addressed delta; any unannotated link reads as a full resync. Adds
subscribeTabTransitions and a store-observer installer registry. The
chat-tab list and the status bridge now consume addressed deltas and keep
the whole-list walk only as the cold path.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* feat(store): annotate every shared tab-map writer through the seam

Shared tabsByWorktree/unifiedTabsByWorktree writers (tab, editor, browser,
worktree, ssh, terminal create/close/navigation/title-batch/reconnect/
hydration, web-session mirroring and layout frames) now build or annotate
their next tab buckets and companion records with the exact workspace and
tab IDs they changed; full hydration, full frame builds and reconnect
inventories are named full resyncs. Writers that copied every bucket for
one tab (preview promotion, dirty-file preview clear, worktree removal
filters, sleeping-record identity rename) now keep unchanged buckets.

Replace the renderer-wide tab-map comparison ratchet with a narrow seam
guard: the repaired consumers may walk a whole tab map only in named cold
paths, and the pinned writer modules may not build raw seam records.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* chore(store): name seam fields once; type seam records; record moved respawn writes

Writers stop repeating tracked field names (centralized in
seam-record-fields.ts), the seam takes a named KeyedSnapshot record type
instead of casts, and the layout-writer baseline records the respawn
helpers moved unchanged out of worktree-layout-lifecycle.ts.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* chore(store): drop seam field cast; record the seam field list in the layout-writer baseline

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(native-chat): keep chat-tab list in source workspace order (C3/F1)

Every source workspace keeps a projection slot, even without chats, and the
seam reports when a write added or deleted a workspace key or moved a
surviving bucket, so the incremental list never reorders first-match
consumers; those transitions take the cold rebuild.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(native-chat): keep projection and retirement debt awake (C2, F3)

A member is owed from attach or semantic change, members without a host
feed keep their own debt, and every reconciliation drains existing owed or
retired work even when no new member changed, including a closed last chat
whose feed is gone.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(store): stop inferring host-mirror companion IDs from visible tabs (C1)

A host retraction can delete PTY or layout records for tabs neither
inventory lists, so the mirror funnel marks its tab-keyed records full
resync instead of advertising an incomplete addressed set.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* chore(ratchets): close indirect paths in the tab-map seam guard (C4)

The guard now rejects ordinary callers of the bridge cold path, value
imports the repaired consumers have not reviewed, and raw seam records built
into a local binding without a seam helper annotating it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* test(native-chat): drive real tab actions through the status bridge (F2)

Close, session rebind with a late old-session tick, and a legacy owner
change, through createUnifiedTab/setTabLabel/closeUnifiedTab, so the
addressed reconciliation path is exercised.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* chore: exempt seam field-name constants from the layout-writer ratchet; drop dead setters (F4)

The seam's SEAM_*_FIELDS lists name fields without writing them, so the
ratchet skips them and the raised baseline row is gone (renderer total 569,
main 571). setStructuredChatSleptAt and the two launch-directory setters
lost their last callers to the batched companion write.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* feat(store): Map provenance and source-ordered change keys in the seam (PR A addenda)

replaceMapEntries gives Map-typed fields (runtimeStatusByEnvironmentId) the
same weak provenance and readRecordChanges protocol. Change keys compose
forward through a chain, oldest write first, so added keys come out in
source order (index keys first for records, as Object.keys orders them). A
surviving key deleted and re-added, in one write or across a chain, and a
record builder that moves a surviving key, read as a 'reordered' full
resync.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(store): writers declare key order; seam reports ordered additions (N1c, N1a)

The seam no longer scans both records to rediscover order on every
annotation. replace* helpers know insertion order by construction; annotate*
takes a declared order ('appended' by default, 'reordered' for a builder
that moves keys, read as a full resync), verified only under test.
Addressed changes now report keys, source-ordered added keys and deleted
keys, so a reader holding its own key ranks places changes in O(changed).
Worktree removal declares its editor-transfer records reordered.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* perf(native-chat): scope the chat-tab projection to chat-bearing workspaces (N2c)

The projection keeps chat subsets only for workspaces that have chats, plus
per-workspace source ranks that change only when a workspace is added or
deleted. A focus, label or title write costs O(that workspace); the
ordered list is materialized lazily, only for full-list readers, and keeps
its identity while no chat changed. Workspace adds and deletes are
addressed through the ranks instead of a cold rebuild.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* chore(ratchets): resolve aliases and require annotation before publication (C4)

Any reference to a cold helper or Object enumerator outside its named
callers counts, including aliases and callbacks; writer values are followed
through local aliases and must be annotated before the write that
publishes them.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* test(native-chat): scoped hydration keeps the warm chat list equal to a cold read (D1)

Drives the real scoped hydrateTabsSession on early/later chats of one
session: source order, list order and first-match precedence match a cold
rebuild, including when the selection order differs from hydrated order.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* perf(native-chat): cache the chat-workspace order across chat edits (D1 item 5)

The lineage keeps chat-bearing workspaces in rank order and only inserts or
removes one when it gains its first or loses its last chat; a chat object
change re-flattens the list without re-sorting. Full resyncs rebuild it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* chore(ratchets): the seam guard recognizes only construction helpers and cold marks (D1)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* refactor(store): addressed provenance only from constructing helpers (D1)

Remove annotateRecordReplacement/annotateTabBucketReplacement and their
caller-declared order: only replace*/recordDraft/tabBucketDraft, which
perform the construction, derive changed keys, additions and deletions from
their operations (delete-then-reinsert reads as reordered); opaque
reconstructions use markFullResync. Every former annotate caller is
migrated: ordinary local writes build their records once through helpers
or drafts with today's operations and order; scoped tab and terminal
hydration, the reconnect inventory, host-mirror application and layout
flush are full resyncs. Change readers move to keyed-record-change-reads.ts.
Renderer layout-writer total 567 (main 571).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* test(native-chat): type the hydration fixture without a cast

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(store): seam record writes define own entries, even __proto__ (N5c)

replaceRecordEntries and drafts assigned through the inherited __proto__
setter, so a tab id '__proto__' lost its own PTY, layout and startup
entries. Both now define an own data property, as the computed-key literals
they replaced did; contract test included.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* perf(terminal): build each createTab record once (N4c)

createTab took ensureGroup's and insertSplitGroup's whole records and the
orphan cleanup's seam records, then rebuilt them through the seam. It now
takes the per-worktree group and split results and gives the orphan
cleanup only the bucket it reads, so every seam record is constructed once
with its ordered operations.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* chore(ratchets): record createTab's orphan-cleanup input view (renderer total 570, main 571)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* refactor(terminal): split orphan cleanup so createTab cleans only companion caches (N6c)

buildOrphanTerminalCompanionCleanupPatch holds the per-tab cache, tab-bar
order and selection cleanup; buildOrphanTerminalCleanupPatch adds the seam
record deletes on top, unchanged for reconciliation. createTab calls only
the companion part with real state and deletes the seam entries through its
single construction, so the stub input view and its layout-writer baseline
rise are gone (terminal-tab-creation.ts back to 10).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* perf(terminal): filter the orphan cleanup's kept bucket once (N7c)

The full cleanup filters the workspace's tabs once and hands the kept
bucket to the companion part, which takes its replacement active tab from
it; createTab's companion-only call still makes its single find pass.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(tabs): keep removed worktrees' group entries deleted on removal

The second emptied-group collapse in removeWorktreeLayout also visited
removed worktrees and wrote their deleted groupsByWorktree entry back as
an empty list, a delete-then-set the seam read as a reordered full resync.
It now visits only surviving workspaces, so removal stays addressed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* chore(tabs): closeEmptyGroup collapses through the shared builder again

collapseGroupLayout takes the record builder, and the renderer passes the
seam's replaceRecordEntries, so the per-worktree collapse publishes with
provenance without new counted layout writes (tabs-group-actions back to 12).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* chore(tabs): reconciliation names its draft fields once (2 + 4 <= 9)

The written-field sets come from SEAM_ field-name constants instead of
string literals, so the reconciliation split no longer raises the combined
layout-writer count (tabs-reconciliation 2, tabs-reconciliation-batch 4,
against the original 9).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* chore(tabs): publish reconciliation drafts with explicit field writes (N9c)

Revert the SEAM_ field-name constants: the drafts are held under their own
names and finishReconciliationDrafts publishes each written draft as an
explicit unifiedTabsByWorktree/groupsByWorktree/activeGroupIdByWorktree/
layoutByWorktree property, so the counter sees every real write and the
split totals 2 + 4 against the original 9, with no exemption.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-11-09 12:19:13 -08:00
Kelvin Amoaba 98bc1acf16 feat(dictation): pulse three dots in the pill while spoken words are still on their way (#40443)
* feat(dictation): show pending dots while the engine holds speech it hasn't committed

The VAD pause segmenter already knows when a phrase is open. The recognizer
now posts speech-pending when a phrase opens and clears it once that phrase's
text is posted, and the desktop pill shows three dots after the text while it
is on. Only pause-cut on-device streams send it, so cloud, the paired web
client and phones keep today's pill.

* fix(speech): keep a lone click from turning the pending dots on
2026-11-09 20:14:48 +00:00
Kelvin Amoabaandzhangxaochen 4783b08ae5 fix(mobile): close the details card when you touch the terminal (#38823)
* fix(mobile): close the details card when a touch lands outside it

Co-authored-by: zhangxaochen <3416677+zhangxaochen@users.noreply.github.com>

* fix(mobile): explain the pointerdown listener and drop a focus check that can't fail

---------

Co-authored-by: zhangxaochen <3416677+zhangxaochen@users.noreply.github.com>
2026-11-09 20:12:31 +00:00
Kelvin Amoaba 1d92f6fcdb fix(speech): let a slow on-device finish run while the engine still answers (#40460)
* fix(speech): let a slow on-device finish run while it still returns text

The stop timeout counted 60 s from Finish however much audio the engine still had
to decode, so a CPU model on a busy machine failed a dictation it was still
transcribing. It now fails only after 60 s without text for that dictation.

* fix(speech): count any engine answer as progress while a dictation finishes
2026-11-09 20:09:25 +00:00
Kelvin Amoaba 035de0a70c feat(speech): record each model's languages, licence and measured error rates in the catalog (#40431)
Error rates come from Orca's speech bench (transcribe-cpp 0.4.1, Metal, pinned GGUFs):
LibriSpeech for English, 5 FLEURS dev clips for de, es, fr, ja, ko, pt, ru, tr and zh.
speechModelQuality turns them into the Voice settings word scale.
2026-11-09 20:08:43 +00:00
Brennan Benson 90a0748576 Source Control's Codex model menu lists your account's models even when Codex's catalog is large (#40117)
* Source Control lists Codex models from app-server model/list instead of debug models

The Codex text-action picker read 'codex debug models', a dump of Codex's whole
catalog with prompt templates (40-90 KB per model). Once it passed the 4 MiB
output cap discovery failed and the picker kept Orca's built-in list, and the
dump's hidden entries were selectable. List models with app-server model/list
(hidden rows excluded), over Source Control's own launch, lock and teardown,
with the same 4 MiB input budget and 60 s deadline.

* Bound Codex model discovery input in bytes, key its cache case-insensitively on Windows, and stop the app-server only when it ignores stdin EOF

- Count raw bytes from both streams against the 4 MiB budget.
- Read CODEX_HOME (and other account dirs) case-insensitively on Windows for the host cache key.
- Skip the post-listing kill when the app-server already exited; fail waiting listing requests once discovery settles.
- Report an incomplete model list as such.
- Tests: fake-timer grace and successor admission after a successful listing, method-not-found and unreadable-page fallbacks.

* Key the Codex discovery cache on the env spelling Windows spawn uses

Windows env names ignore case and Node's spawn takes the lexicographically first spelling, so
CODEX_HOME wins over codex_home; the cache key now picks the same one.

* Narrow Codex app-server records with the provider record guard instead of type assertions

* Read Source Control action model picks under the repo's host key, as the picker saves them

Local repos resolved generation under the 'unknown' host key because their connection id is undefined, so the saved pick was skipped and the agent default ran.

* Key Source Control model picks by connection until the repo record loads, and test with a real local repo

* Key a native Codex listing's cache on process.env when no agent env was resolved
2026-11-09 12:08:24 -08:00
bfa941aa06 fix(native-chat): honor Windows environment overrides consistently (#40301)
* fix(native-chat): apply Windows environment overrides consistently

Use the same case-aware composition for native chat launches, preflight,
model discovery and naming. Canonicalize configured Windows names before
account readers and preserve account pins and POSIX case distinctions.

Tracked in #39075.

Co-authored-by: 김태겸 <oharapass@gmail.com>
Co-authored-by: Vitalii Kulish <mancunianez@gmail.com>

* test(native-chat): cover effective Windows catalog changes

* test(native-chat): retain child environment test import after sync

* test(native-chat): verify Windows child environment precedence

---------

Co-authored-by: 김태겸 <oharapass@gmail.com>
Co-authored-by: Vitalii Kulish <mancunianez@gmail.com>
2026-11-09 12:04:26 -08:00
Brennan BensonandSeaBee 55fb5584c0 OpenCode subagents show in Chat UI and keep a chat open while they run (#40141)
* fix(native-chat): show OpenCode subagents and keep a chat open while they run

OpenCode reports each subagent as a child session when the client opts in.
Orca now opts in, files each child's tool calls and replies under its own
subagent, and keeps the subagent open until the child reports that it
completed, failed or was interrupted, including after the parent turn ends.

Co-authored-by: SeaBee <85791528+seabee33@users.noreply.github.com>

* fix(native-chat): keep a subagent's tool context when its rows are read back from the journal

Co-authored-by: SeaBee <85791528+seabee33@users.noreply.github.com>

* fix(native-chat): a Stop also ends running OpenCode subagents, and each subagent can be stopped from the strip

Co-authored-by: SeaBee <85791528+seabee33@users.noreply.github.com>

* fix(native-chat): only a chat Stop closes OpenCode subagents, an early subagent Stop stays available, and the close request has a deadline

Co-authored-by: SeaBee <85791528+seabee33@users.noreply.github.com>

* fix(native-chat): a subagent Stop that the subagent confirms while the request is out reads stopped

Co-authored-by: SeaBee <85791528+seabee33@users.noreply.github.com>

* refactor(acp): close child sessions from the agent connection

Keeps the session runtime under the line limit after the main merge.

* test(acp): read a child command through a type guard

* fix(native-chat): a subagent that reports its ending reads stopped even when the close request fails

A child Stop's session/close now asks the agent to drop the call on timeout instead of withdrawing the write.

* test(native-chat): OpenCode subagent calls group with other agents' subagent calls

---------

Co-authored-by: SeaBee <85791528+seabee33@users.noreply.github.com>
2026-11-09 12:03:55 -08:00
Jinjing ec3f01bc61 fix(i18n): translate browser password prompts (#40446)
* fix(i18n): translate browser password prompts

* fix: wrap localized password save actions
2026-11-09 12:03:45 -08:00
Brennan BensonandEng. Mahmoud Bek ElNemer 0f89de5276 Save a pasted workspace directory as the path it names (#40347)
* Save a pasted workspace directory as the path it names

A workspace directory with a leading space (" /Users/me/dev") was saved as
typed. Readers treat it as relative, so Orca resolved it inside every
registered repository and created an empty " /Users/me/dev" tree in each.
Normalize the saved value once where settings are written and loaded, as
the leading ~ fix did: leading whitespace before an absolute or home path is
dropped, while relative paths and trailing characters stay exact. A value
repaired on load keeps its old spelling in history so checkouts under the
old root stay visible. The settings field shows the saved value.

Co-authored-by: Eng. Mahmoud Bek ElNemer <ElNeMeR70@users.noreply.github.com>

* Expand ~\ only where it is a home path; drop type casts

* Classify the padded path with the host's own path rules

On macOS and Linux a leading backslash is part of a relative name, so only
Windows treats \work as absolute.

---------

Co-authored-by: Eng. Mahmoud Bek ElNemer <ElNeMeR70@users.noreply.github.com>
2026-11-09 12:03:33 -08:00