* feat(agent-launch): simplify the new-tab agent launch menu
Drop Permissions and Arguments from the launch-mode setup panel; they are
agent defaults edited in Agent settings. Put effort levels (unlabeled) and
Fast mode on one row, and make the Launch chat/terminal buttons fill the
row at a larger size with icons. Select-mode pickers (automations, new
workspace, source control, continuation) keep both controls.
* fix(agent-launch): let current Agent settings win over launch-menu speed edits
A Fast or speed-tier edit copies the current Permissions and Arguments into the
launch draft. With no Arguments editor in the launch menu, a later settings
change was silently ignored. Launch drafts now drop Arguments stamped by older
settings; the speed choice still applies. Also stop pointing hosts without a
model list at the removed Arguments editor.
* fix(agent-launch): show Fast as a button in the launch menu
Matches the mock: an outlined Fast chip with the lightning icon in place of the
"Fast mode" switch. The chat composer keeps its switch.
* feat(mobile): keep screen data on the phone between launches
* feat(mobile): keep the repo list snapshot id across launches
* fix(mobile): don't read a key again that the boot read just found empty
* fix(mobile): late-restored strips, revocation fence and reads never built on stored data
* test(mobile): give the session startup recording the late strip watch
* fix(mobile): remember Workspace options, keep the revocation fence until reauth, store no terminal output
* test(mobile): give the view settings recording its remember hook
* docs(mobile): say what a restored key means to a fetch
* style(mobile): format host-query after rebase onto Q11
* refactor(main): organize runtime implementation owners
* test: retire wall-clock CLI title recovery case
* refactor: route new folder mutation to runtime store owner
* test: import folder mutation store contract from its owner
Both would go over budget once converted. The send-target ordering and
the resume tree's group node move to their own modules first, then the
codemod converts the menu, its target rows and the resume tree nodes.
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* feat(chat): /btw asks a side question in a fork beside the chat
In a Chat UI chat that can fork, /btw <question> (or /side) forks the chat
through its newest finished response, sends the question there, and moves the
fork beside the chat the way dragging it does. The source chat is untouched;
the draft clears only once the question went out. Agents that cannot fork keep
their own /btw.
* fix(chat): type-guard the side chat command names
* fix(chat): side chats own the screen from Send and never place an unsent question
- Placement starts at Send, retires for good on any other selection in the
workspace or on leaving it, and looks only at the requesting workspace.
- A question that never went out leaves its fork in the background; an
unconfirmed one says to check the side chat before asking again; a failure
the new chat already reported is not repeated.
- The command menu shows "Available after the first reply" / "when this reply
finishes" while it is open, using the drawn turn order.
- File pills count as attachments; picking /btw completes the row.
* fix(chat): /btw reads the newest response the drawn transcript offers Fork on
The menu reason and Send now follow the transcript's own Fork rule as drawn,
reported when it changes, instead of rebuilding turn membership in the composer.
* fix(chat): side chat failures always reach the source; watch window starts when the fork opens
- A failed side question toasts in the source even when the fork recorded it,
since the fork stays in the background.
- The 60 s placement window starts once the fork exists, not at Send.
- The fork-point scan stops at a /clear and, for tip-only agents, at the
newest turn; split placement looks only in the requesting workspace.
* fix(chat): /btw forgets a fork point the transcript no longer offers
- Send and the menu reason refuse a reported response that is no longer
forkable, and an unmounted transcript reports nothing to fork.
- The fork-point scan skips subagent sections before its early stops.
* perf(chat): /btw steps over a running turn instead of walking its rows
The slot builder groups root responses by turn in its existing pass; the side
chat's fork point reads those groups newest first and skips a running turn
whole, so streamed replies add no per-row work.
* fix(chat): /btw looks past responses outside any turn and skips the scan when nothing is forkable
* perf(chat): find the /btw fork point while laying out the transcript
Per the review ruling: the slot builder keeps the newest row that offers Fork
in its existing pass, only when /btw listens, and returns one point; the
response groups and their second search are gone.
* test(chat): /btw fork point contract through the transcript and Send hooks
* refactor(chat): response rows and /btw share one Fork rule
* test(chat): /btw fork point ignores pending-only renders and an emptied conversation
* test(chat): /btw contract counts every eligibility lookup and covers an undrawn transcript
* fix(chat): /btw shows ahead of agent commands, sends on one Enter, and focuses the side chat
- Side-chat rows lead the slash menu, so a long agent catalog no longer
pushes them past the menu's row limit.
- Enter on a fully typed /btw sends it instead of only completing the row.
- Placing the side chat also moves keyboard focus to its composer.
* fix(chat): picking /btw completes the row again, as the common pattern does
Sending a fully typed /btw from the menu bypassed a same-named skill's
release and sent on a mouse click; a pick now always leaves '/btw ' to
add a question to.
* fix(chat): on layout-owner builds the moved side chat keeps its composer focus
Main selects a tab it moved once its frame shows it there, so placement no
longer selects it first in the source pane; moveTabToNewPaneColumn reports
whether main or this window moved it, as moveTabToGroup does.
* fix(chat): side chat placement owns main-drawn moves through to the drawn result
Per the review ruling: the placement claim stays alive while main draws the
move, reads the side chat's own new pane and selection as its own, and selects
and focuses the side chat once the frame shows it moved, in place when main
refuses, and never after the user selected elsewhere. The owner command takes
an optional completion in place of its own moved-tab selection.
* fix(chat): selecting the side chat in the pane it is leaving still retires the claim
Only what main's move changes elsewhere (a new pane holding only the side
chat, another pane showing it) reads as the request's own; the selection
counter in the placement contract reads every pane's selection, and the move
helpers' completion is exercised through main's frame transport.
* fix(chat): a side chat main never moves is selected where Fork put it
When main neither draws nor answers the move before the watch ends, the
side chat is selected in place rather than left hidden; the owner command's
completion path (no moved-tab intent, hand-back asks first) is tested.
* fix(chat): a side chat this window moves keeps its focus request
The move's own changes count as the request's from before the move starts,
so a synchronous move no longer retires the claim before the side chat is
selected and focused.
* fix(chat): picking an unavailable /btw row does nothing, as the common pattern does
* refactor(native-chat): keep /btw hooks compilable by React Compiler
* fix(chat): say side chats aren't ready while a fork from the chat is opening
* test(chat): assert the opening-fork refusal without its copy
* fix(native-chat): share one latest-turn scan between /btw and transcript rows
Without the provider useTranslate() falls back to the stable module
translate(), so `t` never changes in the test and only an unmemoized
render could pass it. Mount it the way the app does.
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* perf(mobile): open the PR tab with its last state and refresh only what a write changed
* fix(mobile): allow the phone's comment re-read and settle review findings
* fix(mobile): keep PR reads current across path switches and overlapping writes
* refactor(mobile): share PR query keys and simplify PR write rollbacks
* chore(mobile): list every PR action and comment write kind explicitly
* fix(mobile): read the push-time PR reread through an effect event
* fix(mobile): report a comment write interrupted by a path switch as unconfirmed
* fix(mobile): settle a comment write whose reply was lost from the re-read comments
* style(mobile): format host-query after rebase onto Q12
Applies pnpm i18n:reactive-translate --helpers. Output is unchanged: t delegates
to translate() and helpers default the threaded parameter.
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Three tests only counted how often facet, measurement and query passes
ran, and a fourth checked a zero count beside its real assertion.
AGENTS.md bans work-count tests, and they fail under React Compiler,
which memoizes differently. The behavior checks stay.
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* perf(mobile): show the last task list per filter while it refreshes
* perf(mobile): read Tasks repos six at a time
* fix(mobile): hold Tasks paging while kept rows re-read
* test(mobile): pin Tasks paging held during a query switch
* perf(mobile): read Tasks repos four at a time, the desktop's gh limit
* test(mobile): give the Linear connect recording the revalidating input
* perf(mobile): open Tasks on its kept hydration and lists through host query families
* fix(mobile): keep the desktop's newer Tasks state and only cancel screen-read queries
* fix(mobile): type the Jira refresh harness and Tasks list read for CI
* feat(runtime): confirm a structured chat send by clientMessageId past the first journal page
* fix(mobile): ask the send's own chat before handing it back
* fix(mobile): read send-recorded support when the deadline fires and settle rows that land mid-lookup
* fix(mobile): re-subscribe Home and the follow-up preference after the client event stream ends
* fix(mobile): try a refused client event wire once per connected edge
* refactor(mobile): mark replayed client event readies in the shared stream
* test(e2e): give the phone feed socket client a state listener
* fix(mobile): re-probe an empty "+" agent list and derive the sheet state
* refactor(mobile): mark the agent refresh sent from the transport's beforeSend
Applies pnpm i18n:reactive-translate --helpers. Output is unchanged: t delegates
to translate() and helpers default the threaded parameter.
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* refactor(git): share the .gitattributes ancestor stamp paths
* perf(git): reuse the branch-compare changed-files list per commit pair
* perf(git): charge cached change lists for the stdout their paths retain
* perf(git): bound branch change-list reuse to five minutes for unstamped system attributes
* refactor(git): share the deadline-bounded stamp probe
* perf(git): bound branch change-list attribute stamps by a 2s deadline and 4096 paths
A Smart-sort save rewrote every listed worktree's rank whenever the order
changed, so every repository on the host got an order-only
worktreesChanged event. planWorktreeSortOrderUpdates now keeps the
longest run of rows whose ranks already descend in the requested order
and re-ranks only the rest. It falls back to the full re-rank when a gap
is too tight for distinct whole ranks, or when the planned ranks would
not descend strictly (float rounding at huge ranks).
When the requested order holds a row the write cannot save (WSL-move
fenced or unknown host), the write keeps the full re-rank, since that
row's unqualified rank may belong to a same-ID twin and must never
anchor a partial re-rank.
Replaces #37142.
Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: BTForIT <223167996+BTForIT@users.noreply.github.com>
* feat(cli): set and rm folder workspaces through the folder workspace RPCs
worktree set and rm on folder:<id> (or a path:/name: selector that matches a
folder) now call folderWorkspace.update and folderWorkspace.delete after the
runtime confirms the folder id is unique. Flags with no folder meaning are
refused before any change, a missing method reports incompatible_runtime, and
worktree activate refuses folder workspaces as not supported yet.
* test: read mocked method names without a cast
* fix(runtime): refuse shared folder ids inside folder update and delete
The CLI's show preflight could not make the id-only folder RPCs safe: an older
show could select one of two same-id rows, and a twin added during teardown was
deleted too. folderWorkspace.update/delete now take requireUniqueId, which
refuses a shared id before any side effect, and delete removes only the row it
checked. Hosts advertise folder-workspace.unique-id-mutation.v1; the CLI
requires it and reports incompatible_runtime otherwise.
* fix(runtime): refuse a folder delete when a twin appears during teardown
Two rows that share a folder id share every record keyed by it, so delete
can't keep one row's sessions while removing the other. After the awaited
terminal teardown, delete checks the id again before any cleanup or removal
and refuses with the duplicate-id error; only the stopped terminals remain as
an effect. Removal by row identity is no longer needed and is dropped.
* fix(cli): give only the repair step for a duplicated folder id
The generic ambiguity recovery told agents to pass folder:<id>, which can't
name one of two folders sharing that id.
Its placeholder and submit labels defaulted through translate() in the
parameter list, which runs before a hook can bind. Resolve them from
`t` in the render instead.
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Cap merged atlas pages at FORCED_MAX_TEXTURE_SIZE instead of the device
MAX_TEXTURE_SIZE (16384 on Apple Silicon), stop the link render layer
from acquiring the shared atlas with a mismatched 2048 texture size, and
reset GL texture slots of removed atlas pages to the 1x1 placeholder.
Mirrors xtermjs/xterm.js#6187, #6156 and #6306 in the addon-webgl source
patch and regenerates the runtime patch and lock hash.
Co-authored-by: FlamingoPg <1106310035@qq.com>
Applies pnpm i18n:reactive-translate --helpers. Output is unchanged: t delegates
to translate() and helpers default the threaded parameter.
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
- Admin tokens with a jti (16-128 chars) are single use, enforced inside the target
HostRelay (one storage key, expired ids pruned on each call, capped); a repeat is 409
'replay'. Tokens without a jti are still accepted (metric admin_no_jti) unless
ADMIN_REQUIRE_JTI=1.
- ADMIN_SIGNING_KEY_NEXT / ERASE_SIGNING_KEY_NEXT: second accepted key for rotation;
validated >= 32 chars when set.
- Metrics auth_refresh (extended/unchanged/invalid/identity_changed) and
auth_expired_close (seconds since the last extending refresh).
Restored tabs whose local daemon session is gone no longer mount and
respawn a shell at startup; they park and respawn on open.
- Separate pty:getGoneSessionIds probe, started unawaited at startup so
it never gates reconnect; the authoritative-capability call is unchanged.
- Binding a PTY id (spawn, cold restore, attach) clears its gone mark so a
revived pane gets parked exit/byte watchers again; late answers for bound
ids are ignored.
- Agent tabs (launchAgent or sleeping record) and mixed live/gone splits
keep the mounted restore path.
Replaces #37410.
Co-authored-by: m4air <m4air@Mac.localdomain>
Co-authored-by: thefrikidude <100475418+thefrikidude@users.noreply.github.com>
The usage chart test called both charts as plain functions, which kept
them on translate() and getIntlLocale(). Render them instead and
convert the charts. The pull request page's back label moves from a
parameter default into the render.
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* refactor(terminal): own multiplex ACK window accounting in one module
* perf(terminal): pace alternate-screen multiplex output to the measured link BDP
Slow SSH links queued up to 2MB of superseded TUI frames ahead of keystroke
echo. orcad now estimates delivery rate and base RTT from existing output ACK
timing, caps in-flight output for alternate-screen streams near 2x BDP on links
under 4 MB/s, and replaces a backlog larger than that budget with the existing
recovery snapshot. Normal-screen streams and fast links keep the legacy
windows. ORCA_TERMINAL_ADAPTIVE_ACK_WINDOW=0 restores legacy behavior.
* perf(terminal): back off unavailable superseding snapshots and bound legacy echo checks
* perf(terminal): gate ACK pacing to measured remote links and keep supersedes history-neutral
Pacing now needs a base RTT of at least 40ms, 16 fresh window-limited samples,
and a sample within 15s, so LAN/local links and stale estimates keep the legacy
windows. Superseding snapshots are screen-only, only replace frames that never
switch screen mode (rechecked after serializing), and leave client history
untouched. Paced streams keep today's total buffering before overflow, so
overflow recovery fires no earlier than with legacy windows.
* fix(terminal): close supersede gaps found in review
Scan for screen switches and OSC side effects across frame and send
boundaries (raw and JSON-escaped), back off after an aborted supersede so it
cannot re-serialize in a loop, and keep paced pending headroom until the queue
drains so leaving the alternate screen cannot force an overflow recovery.
* fix(terminal): judge supersedable backlogs on decoded text across every seam
Scan the joined text of the whole queue (plus the sent tail) so screen
switches split across any frame, send, or covered/retained boundary are
seen; never supersede span frames; reject bells (via the shared bell
detector), OSC clipboard/notification writes and 8-bit OSC; back off for 1s
after a rejected scan instead of rescanning on every ACK.
* perf(terminal): make backlog superseding opt-in and forget the sent tail after snapshots
Every recovery snapshot makes current clients replay their reattach reset
(cursor shape/visibility, focus reporting), which is visible when it fires
routinely, so superseding is opt-in via ORCA_TERMINAL_SUPERSEDE_ALT_BACKLOG=1
until clients can skip it. Pacing stays on by default: on a slow link the
existing overflow recovery then reaches the client promptly instead of queuing
behind a 2MB window. After any snapshot the sent tail is unknown (it can end
inside an escape), so superseding waits for the next text frame.
* test(terminal): cover default pacing and opt-in superseding separately
* perf(terminal): read the supersede switch once per connection and skip its bookkeeping when off
* perf(terminal): make adaptive ACK pacing opt-in and fix review findings
- Default off: ORCA_TERMINAL_ADAPTIVE_ACK_WINDOW=1 enables it; when off every
new path is a single flag check, so behavior matches legacy windows.
- Base RTT is a windowed minimum kept honest by periodic probes that drain our
own queue; a paced RTT beyond what our window can add means the path changed,
so legacy windows hold while the base re-learns (no more self-tightening to
64KiB after an RTT increase).
- Paced pending headroom is capped by the connection window legacy would have
used and released on drain, pause and detach.
- Superseding refuses snapshots that end inside an escape.
- Replace the latency-threshold unit test with hardcoded estimator tests and
move the link simulation to bench:terminal-multiplex-ack-pacing.
* perf(terminal): drop backlog superseding and harden opt-in ACK pacing
- Remove the opt-in backlog-superseding snapshot path (code, env switch,
frame classifier and tests); it needs a client capability to skip the
reattach reset before it can ship.
- Paced-ness is decided once at admission (alt screen checked before the
estimate) and reused by the send, so a probe starting in between cannot
mislabel a sample.
- Base RTT is fed only by sends with a near-empty connection queue; probes end
only on such samples from paced streams, and a probe that cannot drain backs
off. A path change forgets the base and holds legacy windows until a drained
sample re-learns it.
- Paced pending headroom is sized from the steady window (never a probe's
zero) and released whenever the queue drains back within the legacy cap.
- Flow-level tests: disabled pacing keeps legacy frames on a measured slow
link; drained headroom returns so later output overflows at the legacy cap.
* fix(terminal): release paced headroom whenever the queue drains, including after recovery
Applies pnpm i18n:reactive-translate --helpers. Output is unchanged: t delegates
to translate() and helpers default the threaded parameter.
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Import MAX_BLOCKS/MAX_PROMPT_BYTES from the module that defines them and
move automationCanonicalLaunchSetup into automation-launch-setup-source
(re-exported) so mobile shared readers skip unrelated RPC schema modules.
Carries #39022 unchanged.
Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: gentslava <14369958+gentslava@users.noreply.github.com>
* feat(cli): match folder workspaces by path: and name:, and keep same-id ps rows apart
Adds one runtime matcher for worktrees and folder workspaces. With the new
matchFolderWorkspaces opt-in (advertised as workspace-selector.folder-match.v1),
path: and name: also match folder workspaces; branch:, issue: and identity:
stay repo-backed. Several matches refuse with each choice's kind, host, path
and selector; a folder id shared by two folder workspaces refuses with the
repair step. The CLI resolves path:/name: through it, so terminal, file and
ports commands reach a folder workspace, and create/set parents record a
folder parent. Explicit ambiguous parents report LINEAGE_PARENT_AMBIGUOUS.
worktree ps now keeps rows that share an id on different hosts apart, with
their own host, identity, metadata and activity; activity whose host can't
be proven attaches to neither.
* test: let the cross-version ps harness pass the host-qualified summary lookup
* fix(cli): read each ps row's own host session; qualify folder selector help
* fix(runtime): refuse unscoped duplicate folder ids; hand lineage the matcher's typed result
Unscoped folder:<id> refuses a duplicated id even when only one copy's host
is derivable; a host-scoped lookup still picks that host's copy. A wsl: hook
stamp counts as local host evidence. The lineage controller receives the
worktree-or-folder candidate directly instead of re-deriving the kind.
* docs(cli): guide the ambiguity fallback through truncated ps and id: selectors
* fix(cli): report an ambiguous parent by its own choices; cover per-host sessions
* fix(cli): send parents to the runtime parent resolver as typed; translate WSL paths for folders too
Parent selectors skip the CLI's show-based folder lookup, so worktree.create
and worktree.set classify them with parent rules: a folder spanning hosts is
a valid parent, and ambiguity reports LINEAGE_PARENT_AMBIGUOUS. Caller-distro
Linux path translation now also matches folder workspaces.
* chore(rpc): import the computer-use recovery data directly instead of through an alias
* fix(runtime): report a missing set parent as LINEAGE_PARENT_NOT_FOUND, as create does
worktree set and worktree create now share one explicit-parent error
conversion: several matches give LINEAGE_PARENT_AMBIGUOUS and none give
LINEAGE_PARENT_NOT_FOUND, so a missing parent is no longer reported as a
bare selector_not_found that could mean the child.
ChecksTabActions is called as a plain function, so it now takes the
checks tab's `t` instead of reading translate(). EditorFileTab would go
over budget once converted, so its mode icon choice moves to its own
module first.
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* refactor(git): move porcelain status streaming into its own module
* perf(git): let status use the untracked cache and expand collapsed directories
-uall never matches the untracked cache's stored mode, so every poll rescanned the whole tree. Scan in the configured mode and list only the collapsed '? dir/' rows with ls-files, reapplying the entry cap so results match -uall exactly. Ignored reads and status.showUntrackedFiles=no keep -uall.
* refactor(git): let the settled diff cache and stamp serve multi-path reads
* perf(git): reuse status numstat passes while their stamped inputs are unchanged
Each poll re-ran up to two whole-worktree numstat diffs even when nothing changed. Cache each pass in a SettledDiffCache validated by the worktree diff stamp (HEAD, index, .gitmodules, plus every unstaged working file for the unstaged pass); racy writes, mutations and submodule rows still recompute.
* perf(git): defer status while index.lock is held
A status read during an agent's commit sees a half-written state and is immediately redone. Wait (up to 1s, abortable, inside the shared lease) for the lock in the worktree's own gitdir to go away; a lock that survives a full wait is remembered as stale so later reads skip waiting.
* perf(git): pick the untracked scan from config and fall back to -uall when expansion cannot win
Read status.showUntrackedFiles and core.untrackedCache in one config call, remember worktrees that need -uall so polls do not scan twice, and rescan with -uall when rows sit outside cwd, need more than one ls-files chunk, or list empty.
* refactor(git): keep numstat cache limits beside the file diff limits
* refactor(git): stamp host settings files and resolve the common gitdir
* perf(git): read untracked-scan config from a stamped snapshot, with a rollback switch
Cache 'git config --list --show-origin' per worktree while every config file it named (plus repo, worktree and global candidates) keeps its stamp, so steady-state polls spawn no config read. WSL and UNC checkouts keep -uall: their config cannot be stamped from the host and network mtimes cannot vouch for the untracked cache. ORCA_GIT_STATUS_UNTRACKED_EXPANSION=0 restores the plain -uall scan.
* fix(git): stamp config and attributes before reusing status numstat
Numstat output also depends on Git config (including includes) and on .gitattributes, info/attributes and core.attributesFile. Stamp all of them, plus every .gitattributes that can apply to a changed path, and skip reuse under WSL. ORCA_GIT_STATUS_NUMSTAT_REUSE=0 recomputes every pass.
* fix(git): stamp include targets and onbranch HEAD in the config snapshot, and share one read
Include and includeIf targets (and HEAD for onbranch conditions) are now stamped, so a branch switch or a filled-in include re-reads config. Concurrent cold reads coalesce, both numstat passes share one config read, folders without their own gitdir skip the snapshot, aborted reads keep the cached entry, and Windows HOME follows Git's HOMEDRIVE/HOMEPATH order.
* perf(git): expand untracked directories only when the untracked cache is opted in
Git's default core.untrackedCache=keep only reuses a cache someone already built, and fresh repos have none, so status plus ls-files cost more than one -uall scan. Expand only for core.untrackedCache=true or feature.manyFiles=true without an override.
* fix(git): bound config stamps on dead mounts and share commondir resolution
Config file stats run under the same 2s deadline as local-git-config-signature, coalesced per file set, so a hung home or network mount skips reuse instead of stalling status. readHeadComponent now uses resolveGitCommonDir.
* test(git): pin the -uall truncation contract of untracked directory expansion
* fix(git): treat an unreadable commondir as unstampable config
main's resolveGitCommonDir rethrows non-missing errors; the config snapshot must fall back to -uall rather than reject the status read.
Applies pnpm i18n:reactive-translate --helpers. Output is unchanged: t delegates
to translate() and helpers default the threaded parameter.
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* feat(claude): sync the terminal theme into Claude Code
* fix(claude): retry missed theme reloads, keep settings key order, search entry
* fix(claude): persist theme ownership before settings writes, skip deliberate themes, restore only on toggle
* fix(claude): gate theme sync on Claude Code 2.1.119, follow Orca's Claude config dirs, keep restores owed
* refactor(theme): point markdown Monaco rules at the shared contrast helpers
* fix(claude): lock theme ownership edits across Orca processes, retry missed theme reloads with backoff
* test(e2e): opt-in real Claude Code theme sync journey; retry theme reloads for up to five minutes
* fix(claude): keep theme takeover recoverable when settings writes or the lock fail; steadier e2e journey
* fix(claude): serialize theme publication with takeover and restore, per-file reload retries; record the real-Claude e2e in the isolated home
* fix(claude): retry an owed restore publish, stop off-state retries, reread settings right before writing
* fix(claude): republish theme files under the cross-process lock
* refactor(theme): point chat selection contrast at the shared helpers
* feat(claude): default theme sync on for new profiles; offer it once to existing users at their next Claude launch
* fix(claude): offer theme sync to every existing profile, confirm only after the save, honest offer copy
* fix(claude): right-align the theme sync offer's two actions, primary last
* perf(mobile): tick only agent rows on the host list and keep repo looks across polls
* fix(mobile): refresh the shared clock when a list comes back within one interval
A clock stopped less than one interval ago kept its old time and started a new full interval, so a quickly reopened host list could show agent ages up to about a minute old.
IssueDialog's team list named its map parameter `t`, so the codemod
skipped the dialog; rename and convert. The run history's count label
memo reads the component's `t` and recomputes on a language switch.
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
The registered pty-connection specs called vi.resetModules() in every
beforeEach, so each case re-evaluated the whole connect-pane-pty graph
(~90-300ms per case, even for trivial ones). Suites now share one graph
and the harness clears the module state tests leave behind.
- restoreTerminalTestGlobals imports the live module instances and runs
their existing reset hooks (delivery claims, completion identity,
startup delivery, side-effect fact consumers, hidden restore scheduler,
pane recovery, ...). It also discards queued output and cancels an
output drain left armed under abandoned fake timers.
- New loadFreshTerminalModules() gives a fresh graph to tests that stub
import-time globals (navigator UA -> CLIENT_PLATFORM) or depend on
once-per-load subscriptions (serializer IPC listener, completion
settings subscription). Teardown resets again so later tests never
reuse that graph.
- notification-settings-gating keeps a fresh graph per test (shared
settings subscription, no reset hook).
No production code changes, no tests deleted, expected values unchanged.
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
RpcDispatcher now requires its method list, so these suites can no longer consume
the default manifest. Suites that still reach the registry through the RPC server
keep the guard.
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* relay: edge export skip on sustained outage, evacuation drain sweep, account allow scoped by region
- Leaving hosts skip the edge export once it has been unavailable for 120 s
(ORCA_RELAY_EDGE_EXPORT_SKIP_AFTER_MS), keeping Postgres devices and
fencing best effort, instead of 503ing until the edge is back.
- Directors drain edge hosts that left the cohort (POST /__admin/drain,
20 per jittered 60 s tick) so connected desktops re-ask and move off.
- Account-allowlisted hosts must also be in the edge regions.
- Tests for the invite-socket edge branch.
* relay: export skip needs continuous failures; evacuation sweep runs soon after start, then every 10 min
Failures more than 30 s apart restart the unavailable clock, so one old failure cannot skip an
export. The sweep reads the edge rows (cell_id has no index): first pass 45-75 s after start (a
cohort change is a new revision), every 45-75 s while hosts are queued, else every 7.5-12.5 min.
Applies pnpm i18n:reactive-translate --helpers. Output is unchanged: t delegates
to translate() and helpers default the threaded parameter.
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
SshStatusSegment's target maps named their parameter `t`, so the
codemod skipped it; rename and convert. The owner usage, resource
merge and runtime host notice memos pass their hook's `t` into the
helpers they call and recompute on a language switch.
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
BrowserAddressBar, AgentCapabilitiesSetupAction and FeatureWallTourSurface
would go over budget once converted. Move the address bar's form-unmount
timer clearing, the capability setup rows and the tour's skill reads to
their own modules first, then convert. The tour's parameter-default copy
moves into the render; an explicit null footer still hides it.
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* relay-edge: any inbound control frame refreshes control liveness
A control that keeps sending commands or auth refreshes is alive even when
its pongs are late. Every inbound frame from an active control now refreshes
lastPongAt (field name kept so hibernated attachments read the same field);
pong_rtt_ms is still recorded for pongs only.
* relay-edge: signed admin op drain
POST /__admin/drain { relayHostId }, signed like assign/export/erase with
op 'drain'. Every control of the host gets the lease-expiry drain frame
(graceMs 0, resolve-director), closes 4503 'host leaving edge' and goes
through the normal socket-gone path. Returns 200 { outcome: 'idle' } or
{ outcome: 'drained', controls }. Assignment, devices and splices untouched.
* relay-edge: alerts that fire at small volume, and an edge probe
Absolute-count rules regardless of MIN_VOLUME: admin-failures (>= 3 admin
calls per 15 min whose label is not an expected outcome) and
auth-refusals-low-volume (>= 5 4401s below MIN_VOLUME). Optional
EDGE_PROBE_URL: each run sends an unauthenticated control upgrade and
alerts unless it gets 401 within 5 s (stateless: every failing run alerts).
* relay-edge: MVP checks for control liveness and the drain op
* fix(ssh): finish the move to the managed server once the last bridged relay terminal exits (#29626)
When a host stayed connected and unmoved only because the legacy relay
bridge served relay-era terminals, nothing retried the move after they
ended. The registry now notes relay-proven exits and, once the bridge
serves no pane (live or unverifiable) and owes no stop, runs one
automatic connect through the existing decision path. Lost contact keeps
panes unverifiable, so it never triggers the retry.
* fix(ssh): keep a bridged host as it was when the automatic move retry is refused (#29626)
The retry now runs as a quiet automatic connect. Its attempt shows no
setup progress, so the kept bridged status is never replaced mid-way.
A refusal or failed decision republishes the kept connected status
instead of an error, and never abandons the reused transport or stops
the bridge. It also refuses to run when it would replace a pending
transport, or once the host is no longer connected and bridged. Only a
finished move publishes a new status.
* fix(ssh): keep a quiet move retry from changing what the user or host already has (#29626)
- A user's connect joining a quiet retry upgrades it to an ordinary
connect, so refusals surface and progress shows; a quiet refusal no
longer clears move-anyway consent.
- A quiet retry rotates the provider authority only once its move
succeeds, so a refusal cancels no in-flight provider requests.
- On refusal, re-read the host status and republish only a still-bridged
host, as connected only while its transport is connected.
- Exits are tracked per bridge, so a replaced bridge's exit never counts
for its successor.
* refactor: key move-retry exits by a named bridge type
Keep default underline and strikeout colors visible while hiding block font glyphs, including link-hover shorthand resets. Restore only owned decoration overrides and preserve explicit colors.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* refactor(git): share common-dir resolution and stat stamps from worktree-diff-stamp
* perf(git): cache branch-compare merge-base and ahead/behind by commit OID pair
* fix(git): only store a commit-pair answer when its scope survived the walk
* refactor(git): type commit-pair stores per answer kind and pin test mtimes
* fix(git): skip the commit-pair cache whenever replace refs, grafts or relocating env could apply
Applies pnpm i18n:reactive-translate --helpers. Output is unchanged: t delegates
to translate() and helpers default the threaded parameter.
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>