mirror of
https://github.com/stablyai/orca.git
synced 2026-11-06 03:57:35 +00:00
ea60ec5d7cb9b542d2b5b3fd986acfc8861e4560
3487
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
ea60ec5d7c |
Layout-owner builds: a phone's tab move is always the server's own; no ghost editor tabs after restart (#31925)
* Layout groundwork (switched off): main derives agent tab titles from its own hook status With the layout-owner switch on, main gives agent tabs their generated titles from the hook-server status it owns, on the desktop, headless serve and orcad: one renameTabs per status batch, so one write and one frame. It keeps the window's rules (setting, custom and quick-command titles, first title wins, dispatch labels). The window stops sending generated titles for tabs main holds; a paired server's tab, or one main has no tab-bar entry for, is still titled by the window as today. The title rules move to src/shared (agent-row-primary-text, and the new agent-generated-tab-title-rules) so both sides share them; switch-off behaviour is unchanged. * feat(layout): main applies a phone's or paired client's tab move itself, and a tab move names the tab it follows so a stale index can't misplace it (layout-owner build, L193) * fix(layout): a move in a group showing a tab main lacks goes the window's way, a twin's agent tab keeps its window title, and orcad subscribes titles through the store attach (layout-owner build) * chore(layout): main's tab move reaches the old-client translation through its compat entry * chore(layout): mark the window-only-row move fallback as bridge code (ledger L280) * test(layout): attaching the hook store follows its rows for main's tab titles once * chore(layout): the old-client move translation is a compat entry of its own, with no cyclic re-export * fix(layout): every tab a group shows is main's, so a client's tab move never falls back to the window (layout-owner build) - Main moves a client's tab itself in a workspace it owns; a row it holds no tab for (a combined diff) keeps no place, and an order must still name each row shown once (L280). - The window publishes an editor row under its tab id only; a file no group shows gets none. - Main's layout load gives a saved browser record with no tab its tab, as the window's hydration repair did, and the window no longer mints one for a workspace main owns. - Main's layout load drops the saved tabs the window's restore drops (view-less diff, conflict and check tabs, old html previews), through one shared rule; the next save writes it back (L286). - Main lists conflict-review and check-details tabs as the plain file rows the window lists, so older clients keep them once the window's rows are gone (L287). * fix(lint): drop an import the shared restore rule left unused * test: import the move translation through the folder's public path * fix(layout): review follow-ups for the move fallback removal (layout-owner build) - A transient tab stays at load while a view is held for its file, as the window's frame build keeps it, not only for its own tab id. - The repaired browser tab goes to the saved active group only while it holds a tab, as selectHydratedActiveGroupId picks it; tests that the id is stable across loads and restarts, that a window-owned build restores it once, and that a paired server's record keeps the window's repair. - Two switch-on tests keyed editor drafts by path; drafts are keyed by editorFileKey (an owned id in a layout-owner build), so they now use it. * fix(layout): the repaired browser tab skips a saved active group this load empties * test(layout): directly dialed SSH browser record is main's; a server's SSH workspace keeps the window repair * fix(layout): drop view-less editor tabs only in loads that carry main's views, so main's own edits keep a live diff * test(layout): a direct SSH partition gets the same browser repair and drop with no host contact |
||
|
|
8967b10d41 |
chore: remove verified dead code and calibrate Knip entries (#31903)
* chore: remove verified dead code and calibrate Knip entries * fix: include mjs consumers in dead-code analysis |
||
|
|
e5f2123e8d | refactor(shared): delete exports nothing reads (#31917) | ||
|
|
4165c9545c |
Layout groundwork (switched off): main tells the window whether its start resumed a pane's agent, so the restored banner and reopen count come back (#31908)
* feat(terminal): the window's store shows main's pane start status (layout-owner build) A status-only frame changes one store entry and no pane tree, so the pane's view stays mounted. * refactor(terminal): keep the frame sync within its line budget * feat(terminal): every pane main starts shows 'starting' from before it is written (layout-owner build) * feat(terminal): a pane main is starting waits and attaches; a failed start shows why (layout-owner build) Fixes owner-visible row 15: a failed agent or setup start no longer opens a plain shell. * test(terminal): iterate store listeners directly * fix(terminal): an exit that reports no code keeps its pane, as lost contact (layout-owner build) * test(terminal): a pane main started attaches to main's terminal at its own grid * test(terminal): detach census tests assert main's move and frame with the switch on * fix(terminal): a restored pane paints history only from its terminal's host, never the window's copy (layout-owner build only) * fix(terminal): main releases a painted cold restore only for the pane's current terminal (layout-owner build only) * test(terminal): typed ack args in the painted cold-restore test * test(terminal): exited-pane tests assert main's close with the switch on These 8 have failed switch-on since #31130 moved the exit close to main. * feat(layout): main starts the panes a client's startPane or wake names, through its one restored-pane starter (layout-owner build only) The model's start and stop effects reach the runtime once the command is written, never the reply. startPane starts a pane whose binding has a start status, and a slept pane from its record. A wake keeps a pane's resume record until its start binds; a failed start keeps it and shows why. With the switch on, main owns a running agent's wake even with a window open. * fix(layout): a window's wake of a pane it resumed itself is record-only, so main does not start it again (layout-owner build only) * test(layout): a client's startPane starts the pane before any other trigger * Revert "fix(terminal): a restored pane paints history only from its terminal's host, never the window's copy (layout-owner build only)" This reverts commit |
||
|
|
f6585a3916 |
Keep Session History checking totals fixed throughout a scan (#30949)
* fix(session-history): freeze scan workload before checking candidates * test(session-history): handle native fixture path separators * test(session-history): control bucket fixture enumeration order * test(session-history): preserve scoped fixture timestamps * fix(session-history): repair integrated test and locale catalog * ci: refresh history checks against current main * ci: refresh history checks after catalog repair |
||
|
|
e6ce82f676 | test: isolate Windows tree-kill load fixture startup and cleanup (#31891) | ||
|
|
7c34a48529 |
fix(native-chat): show a prompt hook's block as its own row for every agent (#30898)
* fix(native-chat): show a prompt hook's block as its own row for every agent When a prompt hook refused a message, Codex showed nothing, Claude showed an unmarked warning the turn fold could hide (with a copy of the prompt), and Grok read as the user stopping the turn. Each adapter now writes one warning row, "Blocked by hook: <reason>" or "Hook stopped: <reason>", marked with the hook-outcome presentation that the turn fold never hides: - Codex: a blocked or stopped UserPromptSubmit hook/completed frame - Claude: a warning informational frame that halts the prompt, worded from its structured prompt_submit_outcome when present - Grok: a HookDenied end, from either completion signal under one row identity; the turn ends completed instead of interrupted Nothing new is saved and nothing changes on the wire beyond the new presentation value. * fix(native-chat): end a hook-denied Grok turn on its first signal, and clean older Claude block wording Follow-ups from the size review of the hook-row change: - Grok: a hook-denied turn_completed now ends the turn and writes the row straight away, instead of waiting for the prompt's answer; a later answer changes nothing. - Claude: when an older Claude sends only its sentence, the row keeps the hook's reason and drops the hook path and the copy of the prompt. Whether the row shows still depends only on prevent_continuation. - The turn-ending shape is declared once, the Codex hook payload is read once, and the Codex hook row returns early instead of threading through the generic frame row. * test(native-chat): cover hook-block rows with real Grok frames and a preserved send - Replace the source-derived Grok fixture with frames captured from Grok 1.0.62 (session, prompt ids renamed to the test's). - One whole-flow file, three parameterized cases (Codex, Claude current and older wording, Grok in every completion order), on the shared timeline rig with a per-agent journal identity. - Each case starts with a send on record and checks it is unchanged after the reopen. * fix(native-chat): word every Claude prompt-hook refusal, and draw the Codex hook row like the others - Claude: a plugin module's dropped_by_hook / not_passed_on refusal reads "Blocked by hook" too. - Older Claude sentence: an empty reason no longer turns the prompt copy into the reason; each hook's path label goes per line, while a hook's own [TAG]: stays. - Codex: the prompt-hook row is read once, before classification, and carries no raw-frame disclosure, so it matches the Claude and Grok rows. The hook/completed table entry is back to main's. - Comments the change had made wrong are corrected. * fix(native-chat): strip only the older Claude sentence's first hook label, as before Command labels without a slash were kept and labels inside a hook's own text were removed; the first-line strip is back, with the empty-reason fix kept. * refactor(native-chat): keep a hook's block row visible as a generic turn notice The fold never hides a row presented as 'turn-notice', a host notice about the turn, instead of a hook-specific value; the hook rows write it for every agent. * fix(native-chat): report a Claude prompt hook's exit-2 block once With hook events on, Claude also sends the blocking UserPromptSubmit hook's exit 2 as an error hook_response; that is the block itself, already shown by the halting warning, so it writes no red hook-failed row. Other hook events and exit codes are unchanged. * docs(native-chat): say a prompt hook's exit 2 may also be a missing plugin script * test(native-chat): type the Claude hook-outcome frame as a record * fix(native-chat): keep a blocked Codex prompt's turn on its own message Codex never echoes a prompt its hook refused, so its turn was anchored on the send only while the send read in flight. Once the turn ended the host publishes the send as in doubt, the anchor fell back to the turn record, and the block row moved to a second turn: live, the chat drew two "Worked for" bars; after a reopen the bar sat on the row instead of the message. A send in doubt now keeps anchoring the turn it opened (the first send in flight, else the newest in doubt). * fix(native-chat): keep refused Codex hook notices outside turns * revert(native-chat): keep Claude's exit-2 prompt hook_response as main's red row A missing plugin script also reports exit 2 without blocking, so suppressing it hid a real failure main shows. With a user-added --include-hook-events an exit-2 block shows both rows (known limit). |
||
|
|
66e50e22cc | fix(images): avoid backtracking in data URI parameter parsing (#31882) | ||
|
|
9e1ffb2333 |
fix(plugins): validate example panel reply dispatch (#31877)
* fix(plugins): validate example panel reply dispatch * style(plugins): brace panel reply admission guard |
||
|
|
01db1b89af |
Main titles agent tabs and applies phone tab moves itself, and tab moves name the tab they follow (dark, layout-owner build only) (#31812)
* Layout groundwork (switched off): main derives agent tab titles from its own hook status With the layout-owner switch on, main gives agent tabs their generated titles from the hook-server status it owns, on the desktop, headless serve and orcad: one renameTabs per status batch, so one write and one frame. It keeps the window's rules (setting, custom and quick-command titles, first title wins, dispatch labels). The window stops sending generated titles for tabs main holds; a paired server's tab, or one main has no tab-bar entry for, is still titled by the window as today. The title rules move to src/shared (agent-row-primary-text, and the new agent-generated-tab-title-rules) so both sides share them; switch-off behaviour is unchanged. * feat(layout): main applies a phone's or paired client's tab move itself, and a tab move names the tab it follows so a stale index can't misplace it (layout-owner build, L193) * fix(layout): a move in a group showing a tab main lacks goes the window's way, a twin's agent tab keeps its window title, and orcad subscribes titles through the store attach (layout-owner build) * chore(layout): main's tab move reaches the old-client translation through its compat entry * chore(layout): mark the window-only-row move fallback as bridge code (ledger L280) * test(layout): attaching the hook store follows its rows for main's tab titles once * chore(layout): the old-client move translation is a compat entry of its own, with no cyclic re-export * test(config): the boundary message test names the old-client folder's configured entries |
||
|
|
8aa7f9c047 |
Combine untracked files into Changes (#31831)
* Combine untracked files into the Changes section * Localize discard warnings |
||
|
|
4c949cd111 |
fix(session-tabs): a confirmed close of a pinned tab in a server workspace closes it instead of snapping back (#31791)
* fix(session-tabs): a confirmed close of a pinned server tab closes it instead of snapping back A paired desktop sent its confirmed close of a pinned terminal tab in a server workspace over session.tabs.close, which had no force, so the server refused it (terminal_tab_pinned) and the tab came back. - session.tabs.close takes an optional `force: true`, honoured only with an explicit `reason: 'user'` and passed to the server's existing forced close (the same path worktree stop uses), in both builds. - The server advertises `session-tabs.close-force.v1` in both builds. The desktop sends force only after the pinned-tab confirmation and only to a server advertising it; an older server keeps today's refusal. - A forced close the server never received keeps its force in the held replay record, so the replay is still the confirmed close. - Moves the undelivered-close hold helpers into web-session-undelivered-close.ts unchanged, to keep the lifecycle module under the line limit. * fix(session-tabs): a pinned server tab closes when the pin confirmation is turned off A local pinned tab closes at once when confirmClosePinnedTab is off, so the close itself is the user's consent. A server workspace's pinned tab now sends that consent as force too (still only to a server advertising session-tabs.close-force.v1). Lifecycle closes (pty-exit), rejectPinned callers and bulk closes are unchanged. * test(session-tabs): load the forced-close server test once; cover held and probe-failed forced closes - session-tab-close-force.test.ts imports the runtime once and flips the layout-owner switch per case through the mock's getter, instead of resetting modules and re-importing the runtime for every case; drops the 120 s timeouts. - A forced close held while the session is inactive, and one whose capability probe failed, keep their force for the replay. - A pinned lifecycle (pty-exit) close never forces, even with the pin confirmation turned off. |
||
|
|
a53c2a2a72 |
Add onboarding language selection (#31784)
* Add onboarding language selection and system locale detection - Detect and synchronize native/browser language preferences safely - Load catalogs before rendering onboarding and support recovery - Let users choose a supported language or request another language * Add onboarding language experiment cohorts and detection recovery * Stabilize onboarding language detection tests * Test persisted onboarding language cohort behavior |
||
|
|
56143a9a5e |
feat(ssh): open a plain SSH terminal to a host whose move to its Orca server is blocked (#31716)
* feat(ssh): open a plain SSH terminal to a host whose move to its Orca server is blocked A refused or unserved host fails the whole connect, so the user had no way to reach their work there. The blocked-move banner and the SSH host row now offer an unmanaged, unpersisted ssh login in a non-modal window. Main builds the argv from the saved target (no -T, BatchMode or Orca multiplexing; the config alias stays bare so ssh_config applies) and spawns ssh with an argv array through the local PTY spawn primitive. Co-Authored-By: Claude <noreply@anthropic.com> * fix(ssh): claim a host before awaiting, wait for ssh on quit, and share the preview terminal's keys Co-Authored-By: Claude <noreply@anthropic.com> * fix(ssh): give the plain SSH terminal Orca's Unicode widths, kitty flags and spawn-helper repair Co-Authored-By: Claude <noreply@anthropic.com> * refactor(terminal): one standalone terminal for the agent preview and plain SSH Extracts the preview's xterm setup (Unicode widths, links, IME bridge, kitty flags, copy/paste and shortcut policy, user-input routing) into openStandaloneTerminal, so the plain SSH terminal reuses it instead of a second copy. Plain SSH output is now acked once rendered, and main pauses ssh while too much is unrendered. Co-Authored-By: Claude <noreply@anthropic.com> * fix(ssh): plain SSH answers terminal queries, keeps early exits, and ends a paused pty on Windows Co-Authored-By: Claude <noreply@anthropic.com> * fix(ssh): plain SSH applies theme changes live and never refits while minimized Co-Authored-By: Claude <noreply@anthropic.com> * fix(ssh): a native call on a just-exited plain SSH pty never crashes main Co-Authored-By: Claude <noreply@anthropic.com> * test(ssh): give the plain SSH test's ResizeObserver stub unobserve, which Tooltip needs Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
99d18f7a2f |
Browser, chat and simulator tabs main-first: the window asks main for each change and draws only main's update (dark, layout-owner build only) (#31516)
* The window shows each layout records frame record by record, without reading its session back (dark, layout-owner build only)
A records frame no longer re-serializes the window's whole session and runs the
Loader. Panes' terminal bindings and live titles apply alone, to the tabs the
frame names; any other record builds only its own workspace's slices, with the
view and facts read from the store. Only a workspace the store does not show
from frames yet (startup, a reopened stream, a first visit, one sent whole)
takes the full build.
Tests install an apply check that, after every flush, compares the store with
the full build for the same cache and pre-flush store; the shared layout-apply
transport now sends main's records frames and fails a flush that differs.
* A frame of only tab rows shows without reading the window's session back or running the Loader (test, layout-owner build only)
* The account-restart test's fake binding runtime carries per-pane binding generations, so it passes with the switch on (test only)
* The account-restart test types its store writes, so its five old e2e type errors are gone (test only)
* A workspace build reads the editor selection and groups through the save's own writers, as the full build does (dark, layout-owner build only)
* A tab released from the window's hold shows the binding main wrote meanwhile (test, layout-owner build only)
* The frame-apply check still checks a flush's other workspaces when it builds one in full, and the shared transport keeps a test's own check (test only)
* The frame-apply check is proven to catch a mismatch beside a full build, and the shared transport restores only the check it installed (test only)
* wip(d3a-2): a windowless host lists a file main opens on session.tabs at once
* wip(d3a-2): the record key's fields are declared where the key is made
* wip(d3a-2): main publishes an editor tab's view, and a window rebuilds the open file it lacks from it
Main's in-memory editor view now carries the file facts an open file needs; it rides the tab row
(PublishedTab.editorView) and a frame build rebuilds a diff, conflict, preview or check-details tab.
Inert with the switch off: views are set only by layout.apply (switch builds) and read only in frame-sync.
* wip(d3a-2): a switch-on window sends editor opens, closes and promotions to main and draws the tabs from its frames
Layout-owner build only; the switch-off path is unchanged. An open proposes the tab id and sends
openEditorTab with the edit file's record or the tab's view (a reopen also its index); the open
file is written at once and the tab is selected once its frame draws it. Callers that act on the
tab (focus request, link reveal, group focus) wait for that frame through layout-owner-pending-tabs.
A close sends closeTabs; the tab goes with the frame and the file's content after it, and a
refusal keeps both. A promotion sends promotePreviewTab and the frame clears the flag. Deleted:
the drawn editor senders, their before/after captures, the editor drawn-tab holds and the
window-record keep rule (a transient tab is kept by its frame view).
* wip(d3a-2): a switch-on close keeps its selection and a reopen, a link names its group, and main stamps an open's time
Layout-owner build only. After main's frame drops a closed editor tab, the window selects the
group's previous tab and its surface through activateTab and focusGroup, after closeFile's
content cleanup rather than before it; a reopen sent while the close was in flight keeps the
file. openFileForLink's proposed view names the group the open asked for. The window's
openEditorTab sends no createdAt: main stamps the tab's time (ledger L186). Preview promotion
writes no tab itself: the window ends a preview only where a paired server owns the layout.
* wip(d3a-2): editor tests assert switch-on tabs through main's command and frame (test only)
Each store and hook test that assumed an immediate editor-tab draw now runs with main's model
through the T1 transport in apply mode and its frames (tabs-drawn-from-main.test-fixture), and
asserts the tab, its selection and its content after main's frame. The fixture fills the frame
slices a partial editor-and-tabs store lacks.
* wip(d3a-2): main takes a restored move as a command, renames a view tab's path, and keeps one tab per file per group
Layout-owner build only (the switch gates every change; shipped builds unchanged). moveTabToWorkspace no
longer skips a tab "the window's save got there first" (L160): window saves no longer carry the move, so
a repeat is tab_not_found; tab_exists and invalid_params stay. A move or rename may carry a non-plain
tab's new view (its file under the new path or owner), which replaces editorViews[tab] (L180). Main
refuses a moveTab or moveTabToWorkspace that would put a second tab for a file into a group (tab_exists),
and its loader folds a saved session's duplicate into the first, as the window's restore does
(dedupeEditorTabsWithinGroups): the window's frame dedupe hid the second, which no close could reach.
* wip(d3a-2): a switch-on restored move and disk rename are main's commands, and the frame that shows them rekeys the content
Layout-owner build only; the switch-off path is unchanged. A restored editor tab re-owned by its
file's workspace (L157, L158) sends moveTabToWorkspace (a re-own in place sends renameEditorFiles)
under the ids and group the window proposes, with each view tab's new view; a disk rename (L180)
sends renameEditorFiles per workspace and draws nothing first. The window's content rekey (open
file records, drafts, buffers, the editorBuffers echo gate, pendingLiveDiskVerification and
pendingSelfMoveEcho) waits in layout-owner-content-rekeys and the frame flush that first shows main's
change applies it, in the same store update as the frame (a flush now writes one patch). A change no
tab shows is rekeyed on main's answer; a refusal drops it and changes nothing. The move coordinator
and the restored-owner loader wait for that outcome; a refused rename rolls the disk move back.
A rename picks a runtime-owned or floating file's owned id, as main's frames restore it.
Deleted: recordRestoredEditorMoveInLayoutOwner, recordRenamedEditorFilesInLayoutOwner, the
reparent's before/after capture and the drawn-tab holds for moves and renames. Tests that assumed
the window moves or renames first now run through main's T1 transport in apply mode and its frames.
* wip(d3a-2): the static gate's casts and layout-writer ratchet hold for the switch-on move, rename and gap fixes
Layout-owner build only. The content rekey's pure store change stays in rekey-open-files-action
(its writer count drops 4 -> 2, pruned); a twin tab main routes to a paired server ends its
preview through patchTab, the existing tab writer, instead of a new one; a frame-only editor tab
takes its label through the frame build's tab-label facts, read from its view or file record; the
moved file's activation names the moved tab, writing no surface field. Test casts are typed or carry
a SAFETY note.
* wip(d3a-2): the switch-on rename takes the window's pure rekey as an argument, so the two modules do not import each other
Layout-owner build only; no behaviour change. Clears the static gate's no-cycle finding.
* wip(d3b): a switch-on window sends browser, chat and simulator opens, closes and page changes to main and draws them from its frames
Main places the chats its host lists (twin h), a local cancel keeps no tombstone (L155), and the
listing no longer writes chat tab structure where frames draw it (L153).
Co-Authored-By: Claude <noreply@anthropic.com>
* wip(d3b): a switch-on browser, chat or simulator close waits for main's frame, lands an emptied workspace as today, and its tests read main's frames
* wip(d3b): the stale-listing and cross-version chat tests check a switch-on local cancel through main, with a presence precondition and per-test resets
* wip(d3b): main places a tab whose group it lacks in the workspace's first group, not beside the window's anchor (L150)
* wip(d3b): tests for main's chat tab commands from a host's chat changes
* wip(d3b): main's windowless chat tab and chat fork tests apply a switch-on host's chat tab through main's layout
* wip(d3b): the switch-on close and open keep their layout writes in the files the writer ratchet counts them in, and a drawn browser close carries its position instead of a rebuilt layout
* Editor tabs main-first: the window sends each editor action to main and draws editor tabs only from main's frames (dark, layout-owner build only)
With ORCA_LAYOUT_OWNER_IS_MAIN on, editor open (preview replace, open to the side), reopen at
its position, close, close-all, promote, the resolved conflict placeholder, a restored-editor
move and a disk rename are layout commands the window sends before it draws anything. Window
content (open file records, drafts, buffers, the autosave gate) is written at once for an open,
and rekeyed in the same store update as the frame for a move or rename. Main publishes each
non-edit tab's view, keeps views in memory across applies and partition changes, stamps the
tab's time, folds same-file duplicates, and republishes a windowless host's session.tabs after
its own file open. The switch-off path is unchanged.
* wip(d3b): a switch-on close main answers workspace_not_found drops the tab's content as tab_not_found does, and placement reads a missing active-group map safely
* wip(d3b): switch-on browser and chat tests open and close through main's command and draw from its frame (test only)
* wip(d3b): a switch-on chat listing writes no tab structure of a workspace main's frames draw; a host chat title changes only the drawn tab's label
* wip(d3b): main's phone rows show a diff tab and a markdown preview as the window's do, with the preview's source named by the window's open-file id
* wip(d3b): the cleanup close's page-read guard counts its named linear passes, so a per-entry rescan still fails switch-on (test only)
* wip(d3b): the static gate's compat entry, focus-read ratchet and formatting hold for the switch-on test conversions and phone rows
* test(d3a-2): the buffer view index follows a rename main answers
* wip(d3b): placement reads the active-group map the real store always holds; the browser test store seeds it
* wip(d3b): a switch-on background browser open leaves the worktree's remembered browser tab unset, as with the switch off
* wip(d3b): a switch-on chat open selects the chat in its group without moving the focused group, as the window's own open does; its test counts the chats main draws
* wip(d3b): the converted simulator, launch-cancel, cleanup-close and chat-listing tests assert what the window's draws asserted, through main's command and frame (test only)
* wip(d3b): main fences a chat's create on its close even when the close fails for want of the chat host, so a cancelled launch never shows
* wip(d3b): a frame keeps the window's hidden chat launch slot after its neighbour, so a resumed chat keeps its saved place through main's frames
* wip(d3b): a declined chat's terminal is placed after the chat and pinned as it is in one main move, and shown before main closes the chat
* wip(d3b): a switch-on chat close the host refuses asks main to open the chat again, as the window's re-read shows it with the switch off
* wip(d3b): a paired server's workspace, its row naming the server, opens and closes browser and chat tabs without main's layout (test only)
* wip(d3b): a refused chat close comes back only while this machine's host still lists the chat, and a close main answers workspace_not_found removes the window-only tab
* wip(d3b): the twin chat close test names what each build stops: no host off, main's host on (test only)
* wip(d3b): the refused-close reopen takes only a chat agent it can launch
* wip(d3b): a frame's browser selection keeps an unchosen workspace's unset through the restore projection's own rule, not a second write
* wip(d3b): the simulator and paired-server tests type their mock stores without assertions (test only)
* wip(d3b): the switch-off declined-chat placement runs as before, with no wait; only the switch-on move waits for main
* chore(d3b): drop the frame-binding helper the main merge left without a caller
* chore(d3b): drop the import the deleted helper used
* wip(d3b): a chat this machine's window creates is placed only by the window's own open, so a reserved chat slot keeps its place (switch-on)
* wip(d3b): main reads a chat tab change against its layout when its queue reaches it, through the one rule the switch-off save uses, so a close right after an open closes it
* wip(d3b): a declined chat's terminal moves to its index among the tabs main draws, not past a hidden launch slot, so it still replaces the chat (switch-on)
* wip(d3b): main's phone-row comments say which rows the window's own row wins, and a test shows a window-listed diff keeps its dirty state (comments and test only)
* wip(d3b): a switch-on chat open returns only the tab's id and chat, the fields main's frame keeps; no caller reads more
* chore(d3b): the unit-routing census registers the browser suites' drawn-from-main store fixture as a support bridge (test only)
* chore(d3b): the chat tab rule's comment wraps and names its two callers (comment only)
* wip(d3b): main's chat tab queue asks a worktree's host only once it has a saved session, and one failed change no longer stops the ones after it (switch-on)
* wip(d3b): a chat tab batch whose changes cannot be read is logged, and the batches after it still land (switch-on)
* test(d3b): a CLI-chat resume's tab is opened once, by the window through main, after the tab before its hidden slot (test only)
* test(d3b): an SSH worktree has no host to run a chat on, so none of the chat open, close or fix paths reach it (test only)
* chore(d3b): the content tab placement reads folder workspaces through main's workspace-record selector, as the new ratchet requires
* fix(merge): put back main's
|
||
|
|
5793b05f39 |
fix(ssh): keep the enrolled pairing across a managed server's update, rollback and recovery (#31684)
* fix(ssh): keep the enrolled pairing across a managed server's update, rollback and recovery orcad's startup offer names a pending device, which it re-mints once a client has paired with it. Update, rollback and recovery re-paired the desktop from that offer, so the desktop became a new device to its host after each one. They now keep the enrolled grant, as WSL does since #29042. * fix(orcad): count WSL incumbent terminals with the enrolled pairing, and warn on a changed host key The WSL incumbent's terminal count authenticated with the startup offer, which marked that pending device used, so every orcad start enrolled another device. It now uses this desktop's enrolled pairing. After an SSH update, rollback or recovery, a server that names a host key other than the pinned one is reported with a warning instead of a plain success. * fix(ssh): keep a pairing the terminal count repaired; leave the host-key warning to a follow-up The census can repair a refused pairing before the update re-pairs, so the enrolled grant is re-read from the store rather than taken from the copy read first. The host-key warning goes back out: only the CLI would show it, and surfacing it in the desktop lifecycle UI is a separate change. * refactor: keep two touched files under the line limit after rebasing onto main refreshPairing reads the enrolled offer in one statement, and the WSL connection error classes move into their own file. |
||
|
|
7a912a3a24 |
Autosave relies on the guarded save instead of pause flags; identical saves don't rewrite; non-UTF-8 files aren't autosaved (#31768)
* Autosave relies on the guarded write instead of pausing restored or moved tabs Delete the pendingDiskBaselineVerification and pendingLiveDiskVerification pause flags. Every editor save is already a guarded write; a refusal raises the changed-on-disk banner, which is what stops autosave until an explicit save. A guarded write now succeeds when disk changed but already holds exactly the text being saved (local/host compare is byte-exact; client-side fallbacks compare decoded text and refuse when it holds U+FFFD), so a restored draft that matches disk goes clean instead of showing a banner. The restore scan only raises the banner early for tabs that arrive dirty; a watch resync no longer re-checks dirty tabs. Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): skip guarded saves when disk is already identical Return a compatible optional no-op result from hosts and client fallbacks, clean the tab, and clear its provisional self-write stamp without rewriting identical bytes. Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): refuse lossy automatic saves, keep identical-skip on older hosts, flag dirty tabs on resync - Autosave and pre-restart saves refuse when disk text can't be decoded losslessly, so a baseline that decoded to U+FFFD can't authorize overwriting different bytes. - New files.write.identical-noop.v1 capability; for hosts with only the v1 guarded write the client compares first, skips identical saves, then delegates to the host's guarded write. - Watch resync compares dirty tabs against disk and shows the changed-on-disk banner. - Local guarded writes check for identical content before the write-only regular-file probe. Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): tell non-UTF-8 files apart from disk changes, and quiet false resync banners - Local guarded writes judge losslessness by bytes, so a valid UTF-8 file containing U+FFFD autosaves again. A file that really isn't UTF-8 is refused with its own reason, 'not-utf8' (older clients read it as 'changed'), which pauses autosave for that file with one notice until an explicit save converts it. - A watch resync whose disk read fails leaves dirty tabs alone; the guarded save still catches a real conflict. - Resync and restored-tab checks treat disk holding the tab's own just-written save as an echo. - On hosts with only the v1 guarded write, only automatic saves read the file first; explicit saves go straight to the host's guard. Co-Authored-By: Claude <noreply@anthropic.com> * fix(editor): lift the non-UTF-8 autosave pause when its edits end, and report disk changes first - The pause is released once no dirty tab of the file remains (close, reload from disk, discard), so a reopened or reloaded file's next autosave asks the host again and notifies. - Client-side precondition checks compare the signature before looking for U+FFFD, so an external rewrite shows the changed-on-disk banner rather than the non-UTF-8 notice. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
ed13ca1e6f |
Layout groundwork (switched off): main starts and restores every pane, and the window only attaches and paints the host's history (#31567)
* feat(terminal): the window's store shows main's pane start status (layout-owner build) A status-only frame changes one store entry and no pane tree, so the pane's view stays mounted. * refactor(terminal): keep the frame sync within its line budget * feat(terminal): every pane main starts shows 'starting' from before it is written (layout-owner build) * feat(terminal): a pane main is starting waits and attaches; a failed start shows why (layout-owner build) Fixes owner-visible row 15: a failed agent or setup start no longer opens a plain shell. * test(terminal): iterate store listeners directly * fix(terminal): an exit that reports no code keeps its pane, as lost contact (layout-owner build) * test(terminal): a pane main started attaches to main's terminal at its own grid * test(terminal): detach census tests assert main's move and frame with the switch on * fix(terminal): a restored pane paints history only from its terminal's host, never the window's copy (layout-owner build only) * fix(terminal): main releases a painted cold restore only for the pane's current terminal (layout-owner build only) * test(terminal): typed ack args in the painted cold-restore test * test(terminal): exited-pane tests assert main's close with the switch on These 8 have failed switch-on since #31130 moved the exit close to main. * feat(layout): main starts the panes a client's startPane or wake names, through its one restored-pane starter (layout-owner build only) The model's start and stop effects reach the runtime once the command is written, never the reply. startPane starts a pane whose binding has a start status, and a slept pane from its record. A wake keeps a pane's resume record until its start binds; a failed start keeps it and shows why. With the switch on, main owns a running agent's wake even with a window open. * fix(layout): a window's wake of a pane it resumed itself is record-only, so main does not start it again (layout-owner build only) * test(layout): a client's startPane starts the pane before any other trigger * Revert "fix(terminal): a restored pane paints history only from its terminal's host, never the window's copy (layout-owner build only)" This reverts commit |
||
|
|
bf0f7f58cc |
feat(connectors): add an off-by-default experimentalConnectors setting (no behaviour change) (#31757)
* feat(connectors): off-by-default experimentalConnectors flag and seam lifecycle (B2a) Adds the experimentalConnectors setting (no UI, telemetry whitelist) and a runtime-owned reconciler that builds the connector seam while the flag is on and disposes it with connectors_disabled when it is turned off. The seam is empty; later connector PRs land behind it. * fix(connectors): partial runtime stores read as connectors off * refactor(connectors): B2a is the setting only; the lifecycle lands with its first consumer |
||
|
|
ec546de75a |
fix(sidebar): remove redundant host badges in every grouping (#31744)
* fix(sidebar): omit host badges beneath host section headers * fix(mobile): keep host health without repeating section labels * test: align host section goldens and preserve chat translation exports * fix(i18n): retire obsolete Portuguese Codex version key |
||
|
|
9738dc6c08 |
Bring main back under the line limits (main lint is red) (#31729)
* fix(browser): bring the client-hosted page pane back under the 400-line limit Move the client-hosted guest's six event-listener add/remove calls into bindBrowserClientPageGuestEvents beside the guest load-failure handler, so ClientHostedBrowserPagePane.tsx drops from 404 to 395 counted lines. No behavior change. * test(browser): pin the client page guest event binder's bind and unbind contract * fix(native-chat): bring the question module back under the 300-line limit Move answer encoding (pasted answer text and the Claude and Codex selector keystrokes) into native-chat-ask-answer.ts and re-export it, so importers are unchanged. |
||
|
|
349e3d19b9 |
Agents need only a minimum version for chat; newer releases and prereleases keep working (#30393)
* fix(native-chat): agents need only a minimum version for chat; newer releases and prereleases run OpenCode chats accepted only the 1.x and 2.x lines and Pi only 0.x and 1.x, every prerelease was refused, and a slow or failed --version run counted as unsupported. A new major would open as a terminal and existing chats said "Orca can't run this agent in a chat here." Each agent now lists ascending minimum versions; a version must reach the latest one on or below its own major line, compared by semver. The check answers ready, too old, unknown (slow, failed or wordless run) or missing (did not start). Only too old refuses a launch, as Codex already did, with "<Agent> X is too old for chats. Update to Y or newer." carried in a new optional refusal fact agentInstallation; Codex keeps sending codexInstallation for older clients. Codex's reader and error fold into the same check. * refactor(native-chat): a launch check declares its minimum versions; create support and the agent health snapshot run the one shared check * fix(native-chat): read an agent's version from stderr too, so Pi 0.73 is known too old instead of unreadable |
||
|
|
03672738fd |
Fix terminal URLs split across padded output rows (#31713)
* fix(terminal): resolve URLs across padded hard-wrapped rows * Reject oversized wrapped URL prefixes and isolate reconstruction * Handle preceding links and uppercase schemes in wrapped URLs * Restore full lint by extracting props and ask dismissal identity * Keep wrapped URL clicks consistent and require padding evidence * Preserve soft-wrapped sibling URLs in cold click fallback |
||
|
|
50da78aa85 |
fix(mobile): detect New Workspace agents in the selected repo runtime
Pass the selected repository to New Workspace agent detection through the host-authoritative runtime resolver, including WSL paths and Windows project preferences. Preserve old-client request shape, SSH routing, and strict ownership/refusal behavior. This merge credits @welldoingk’s original WSL agent-detection investigation and community PR #20101, adapted to the current host-resolved contract. Co-authored-by: welldoingk <thkwon96@gmail.com> Fixes #20060 |
||
|
|
b0fcdb493c | fix(omp): show OMP's plan review as a plan card and answer it from chat (#31635) | ||
|
|
b17477614d | fix(agent-status): questions over 16 KB show their card with every option (#31632) | ||
|
|
eb9d2f9a06 |
fix(security): update Node runtimes for October security releases (#31687)
* fix(security): update Node runtimes for October security releases * fix(ci): compare normalized web file inventory without ordering artifacts |
||
|
|
d15677e334 | fix(native-chat): Codex async questions show an answer card on desktop and phone (#31652) | ||
|
|
e34b3709b3 | feat(browser): new tab page with a workspace card and suggested sites (#31656) | ||
|
|
c5e07bc3af | feat(browser): per-site appearance and zoom, from the page menu and Cmd/Ctrl +/-/0 (#31621) | ||
|
|
d085427628 |
Keep model choices coherent across Claude updates (#30107)
* Use one model catalog per execution scope * Accept a missing session record in host scope * Merge duplicate launch-resolution import * Fix catalog typecheck errors * Align catalog tests with the one-list design * Type the integration fixture's send without a cast * Give the discovery test complete runtime dependencies * Fix model catalog completion and scoped configured display * Preserve model catalog authority across released clients * Fix mobile first-frame catalog fixture narrowing * Keep startup catalog persistence with one completion owner * fix: preserve chat selections across CLI model updates A newer CLI can omit a model that an existing chat still runs. Keep that chat's selected model and effort instead of replacing them from the available list. Discover one model list per host, account, launch command and folder, refreshing after two minutes. Keep current values and the running model's exact effort choices with its chat. Show only the known effort when Claude supplies no matching menu. Preserve older paired-client delivery and configured launch arguments. Make Codex use independent discovery and retain the established ACP and Pi paths. Tracked in STA-10947. * fix: keep the Pi options read within its file limit after main's growth Tracked in STA-10947. * fix: import the option snapshot's shared module once Tracked in STA-10947. * fix: keep Grok and Pi model menus and fast controls across restarts Restore the established ACP and Pi catalog route: newer listed models and qualified startup defaults stay visible, and genuine retained effort menus survive later reads. Keep exact-child Fast and Speed controls. Update the phone option contracts and the remaining stale expectations to the selection rules. Tracked in STA-10947. * fix: share each workspace's model list and keep live Grok and Pi menus New chats read their workspace's own model list through the one shared request for that workspace, so a second chat in the same folder starts on the model and effort the agent actually runs there, and a slow first answer can no longer overwrite a newer list. A running Grok, OpenCode or Pi chat keeps its live model menu when an older shared list arrives later. Update the tests that still expected the replaced behavior. Tracked in STA-10947. * fix: keep separate agent and chat model lists for Grok, OpenCode and Pi A brand-new Claude chat now offers the selected model's effort levels before the first message, as it did before. Grok, OpenCode, omp and Pi again keep the list read from the installed agent apart from the list a running chat reports, and each newer list replaces only its own source. So a chat shows the model the agent is actually running with that model's own effort menu, and an effort change can no longer act on an older model's menu. Saved model lists on WSL are readable again without starting the agent. Tracked in STA-10947. * fix: keep desktop catalog storage out of the phone's type graph and show Grok's late model answer The phone app's type check no longer pulls in desktop-only catalog storage. The model-list code no longer reaches the saved-catalog file through a type import. When a Grok model change times out and Grok later confirms the model, the chat shows the model Grok actually runs. Tracked in STA-10947. * Remove unrelated merge formatter and package manager churn * Clarify independent catalog ownership and refresh contracts * Declare picker demand callback as an effect dependency * Complete mobile catalog surface and catalog merge types * Complete catalog contract fixtures for current host types * fix: preserve catalog source contracts and account fallback * test: inject independent Codex discovery transport * test: remove accidental client fixture assertion * test: qualify the saved account fallback read * fix(chat): preserve catalog evidence and current child controls * Fix catalog CI types and mobile option readiness * Reconcile session controls after inventory changes * Fix catalog import and deferred test resolver types * Keep model capability observations separate from picker views * Use installed model choices for chat options * Fix model catalog test fixture contracts * Restore model option compatibility and stable settlement * Return a catalog reply in provisional launch fixture * Compose unreported live model defaults in the host * Preserve explicit replacement model on recovery send * fix(chat): use stable scoped catalogs on local desktop * test(chat): preserve generic catalog runner type * fix: scope catalogs to configured environment and keep saved reads passive * fix: satisfy catalog regression and controller CI checks |
||
|
|
82512a43a3 |
fix(pairing): normalize base64 consistently across clients (#31465)
Normalize bounded Base64 input consistently across desktop, browser, and mobile pairing paths while preserving lossless legacy padding and trailing-bit spellings. Retain offer validation and authentication behavior.
Adapted from #12027. Compatibility verified across 378 spellings with no previously accepted inputs lost; full PR workflow and aggregate gate passed for
|
||
|
|
bd0f326218 |
feat(sidebar): one lifecycle line per workspace in main, with in-progress hints (switch-gated) (#31553)
* fix(sidebar): land flip-a's switch-on fixes on main, still dark (no flip) The fixes found while the sidebar ran from main's feed, without turning that on: ORCA_SIDEBAR_INPUTS_IS_MAIN stays false, and none of flip-a's stop-gaps come along. - Main stops counting a closed tab's terminal once it was asked to stop and no pane shows it; a failed or refused stop takes the request back, and a host out of contact stays unverifiable. - Main fetches a paired server's rows with the transport's normal bound, so a server slower than 5 s still lists. - A deferred unread raise flips the folder row it was decided for, and a read while the owner check is out cancels it. - Phone: no worktree.ps flash before the feed; a host's last installed feed stands in while a fresh read is out; it highlights its own last-opened workspace and a fold never scrolls; projects file under their project group with the desktop's indent; the collapse spinner shows only after 500 ms; "Reopen to update" keeps the rows on screen. - e2e helpers and journeys for the switch-on suite. * fix(sidebar): keep an owed relay stop marked, clear a thrown stop, and prune pending unread raises - A stop-and-wait that throws takes its stop request back, like one that fails. - A final stop the legacy relay still owes stays marked, since the relay retries it. - Pending unread raises are tracked only while one waits, so the map no longer grows. - The paired-server fallback poll test gives its third fetch a reply and asserts live. * feat(sidebar): main publishes cached snapshots and announces its own stores; detected, view and live-content domains (inert) * fix(sidebar): keep links confirmed only by a new git run, no rescan on metadata writes, no phone wait on detected checkouts * fix(sidebar): rescan the workspace rows when the Windows runtime default changes * feat(sidebar): one lifecycle queue per workspace in main, with in-progress hints (switch-gated) Create, delete, terminal.closeAll, terminal.sleep and worktree.sleep now run through one first-in, first-out queue per host-qualified workspace: strict order, no merging, delete cancels what has not started and waits for what has, an unconfirmed outcome pauses until the host's own answer. Hints publish in a new inProgress feed domain (no reader yet); the creations domain is its projection. A finished create or delete keeps its hint until a scan started after it applies, in the same revision. Adds the paired-server metadata serializer (saving domain, no caller yet). Replaces the creation registry. * fix(sidebar): a create never queues behind the previous occupant's delete * fix(sidebar): resume a paused workspace by re-observing, never replaying - A command issued while paused waits behind the pause; when the owner answers again main re-reads terminal liveness and the listing, then carries on. A forced delete runs past it. - Commands keep their arrival order across a workspace lookup; deletes by name key by the resolved id, so they wait for that workspace's running sleep. - A second delete with different options is refused as already in progress. - Close and delete read lost contact as sleep does. - A create always frees its own queue entry, even after a retry took over its id. - Drops the unused opId, and the paired-server write serializer and its feed section, which land with their first caller. Co-Authored-By: Claude <noreply@anthropic.com> * fix: restore main's final P2 test fixes a merge reverted --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
98007cb5f5 |
refactor(sidebar): one shared feed client for the desktop window and the phone (#31524)
* fix(sidebar): land flip-a's switch-on fixes on main, still dark (no flip) The fixes found while the sidebar ran from main's feed, without turning that on: ORCA_SIDEBAR_INPUTS_IS_MAIN stays false, and none of flip-a's stop-gaps come along. - Main stops counting a closed tab's terminal once it was asked to stop and no pane shows it; a failed or refused stop takes the request back, and a host out of contact stays unverifiable. - Main fetches a paired server's rows with the transport's normal bound, so a server slower than 5 s still lists. - A deferred unread raise flips the folder row it was decided for, and a read while the owner check is out cancels it. - Phone: no worktree.ps flash before the feed; a host's last installed feed stands in while a fresh read is out; it highlights its own last-opened workspace and a fold never scrolls; projects file under their project group with the desktop's indent; the collapse spinner shows only after 500 ms; "Reopen to update" keeps the rows on screen. - e2e helpers and journeys for the switch-on suite. * fix(sidebar): keep an owed relay stop marked, clear a thrown stop, and prune pending unread raises - A stop-and-wait that throws takes its stop request back, like one that fails. - A final stop the legacy relay still owes stays marked, since the relay retries it. - Pending unread raises are tracked only while one waits, so the map no longer grows. - The paired-server fallback poll test gives its third fetch a reply and asserts live. * refactor(sidebar): read the sidebar feed through one shared client library on desktop and phone The window and the phone each had their own feed reader. Both now use one reader under src/shared/sidebar-feed-client: paging, notices, retries and the snapshot it installs. A snapshot reuses each unchanged entity's parsed object, so one row's change re-parses one row instead of its whole domain. Adds the gesture and view-report pieces later cuts wire up. Lists are unchanged on both sides. Co-Authored-By: Claude <noreply@anthropic.com> * refactor(sidebar): drop the feed client's unused pieces until their callers land Co-Authored-By: Claude <noreply@anthropic.com> * test(sidebar): key the snapshot test's rows by host identity, as main's feed types now do Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
a57e027cb3 |
fix(orcad): one update decision for SSH and WSL, with connect, Update and Force intents (#31682)
* fix(wsl-host): apply the SSH update rules to a WSL connect A WSL connect deployed this app's orcad whenever the active build differed, so a distro another, newer Orca had activated ended in an unconnectable deferral, and a build the host had rolled back from was re-activated on every connect. It now runs the same planManagedOrcadAutoUpdate decision SSH uses and serves the active build when that plan skips. * fix(wsl-host): serve the skipped-update incumbent only if it is still active * fix(orcad): one update decision for SSH and WSL, applied again under the fence The connect's update plan moves to its own module, and the fenced admission every first deploy and WSL connect uses now applies it, so a transient readiness failure or a race cannot reactivate a rolled-back build. * refactor(wsl-host): adopt the serving build through the SSH first-deploy adoption * fix(wsl-host): do not retry a candidate rejected earlier this launch A rejected candidate is restored without recording rolledBackFrom, so WSL retried it on every connect. SSH's launch-scoped failure memory moves to a shared helper keyed per host, and WSL feeds it to the shared update decision. A null adoption now re-reads the record before the deploy, as SSH does. * fix(wsl-host): keep Force offered when a connect skips this app's build The WSL connect's update admission moves to its own module, which returns a forceable hint when it serves the incumbent over a rolled-back or failed build. * fix(orcad): connect, Update and Force are the three update intents on SSH and WSL Only a connect applies the skips; an explicit Update retries a skipped or failed build (clearing the failure memory) behind the terminal census; only Force passes the census. WSL's Update button now sends the update intent instead of a plain connect. A connect that records a rejection serves the restored incumbent at once. * fix(orcad): an explicit Update keeps the newer-host skip on SSH and WSL Update lifts only a host's own skips (rolled back, failed before); Force lifts all. SSH's explicit update now applies the same fenced admission, so stable cannot replace a host a newer Orca activated without Force. A rejection retries adoption only once the incumbent is back and no journal awaits recovery. * fix(wsl-host): keep Update and Force offered on a deferred cold connect A connect the host deferred with nothing serving now publishes its deferral, so a host stopped after a rollback can still be retried from the UI. SSH's explicit Update forgets a remembered failure only once it lands, and a restore that could not be read keeps the rejection as reported. * fix(wsl-host): offer only Force over a host a newer Orca runs, and keep failure memory until an Update lands A host-newer refusal gets its own deferral code so the WSL row hides Update, which can never pass it. An explicit Update no longer clears the launch failure memory up front; only a landed deploy does, as on SSH. * refactor(wsl-host): merge the intent type into the existing shared imports |
||
|
|
10d410455e |
Repair only the damaged parts of a profile instead of rolling back the whole profile (#30931)
* fix(profile-state): repair only the damaged sections instead of rolling back the whole profile One profile-state row whose checksum no longer matches made Orca refuse to open the whole profile, and the only recovery swapped in a whole backup, losing every newer change in every section. Startup now checks each section on its own. When only some sections are damaged, the dialog offers "Repair and Restart": Orca copies the damaged database aside, then replaces just those sections with the newest backup copy that passes its checks, keeping every intact section's current value, in one checked write. Headless starts name the damaged sections and `orca profile state rollback --repair`. Whole-file damage keeps the existing backup rollback. Also turns on checkpoint_fullfsync for the profile database: on macOS plain fsync leaves the drive cache unflushed, which can leave a long row's pages from two versions after a power loss or forced shutdown. Tracked in STA-10893. * test(profile-state): pin the repair dialog's text and buttons * fix(profile-state): list the repair module for the CLI typecheck; keep section labels out of the layout-writer count * fix: validate section repair admission before decoding payloads * fix(profile-state): share backup handles during section repair |
||
|
|
fcac5cf0f0 |
refactor(native-chat): one shared parser for the approval envelope (#30848)
The phone and the desktop each parsed the status row's
{ approval: { tool, summary } } envelope with identical validation.
Move that validation and the answer keys into
src/shared/native-chat-approval-envelope.ts; each caller still builds
its own card (phone English labels, desktop translated labels) and
keeps its own precedence and heuristics. No behaviour change.
Co-authored-by: E2E Test <e2e@test.local>
Co-authored-by: Claude <noreply@anthropic.com>
|
||
|
|
7df3ff76d5 |
fix(sidebar): keep each host's activity, PR lane and retention apart for a same-id workspace (dark) (#31517)
* fix(sidebar): land flip-a's switch-on fixes on main, still dark (no flip) The fixes found while the sidebar ran from main's feed, without turning that on: ORCA_SIDEBAR_INPUTS_IS_MAIN stays false, and none of flip-a's stop-gaps come along. - Main stops counting a closed tab's terminal once it was asked to stop and no pane shows it; a failed or refused stop takes the request back, and a host out of contact stays unverifiable. - Main fetches a paired server's rows with the transport's normal bound, so a server slower than 5 s still lists. - A deferred unread raise flips the folder row it was decided for, and a read while the owner check is out cancels it. - Phone: no worktree.ps flash before the feed; a host's last installed feed stands in while a fresh read is out; it highlights its own last-opened workspace and a fold never scrolls; projects file under their project group with the desktop's indent; the collapse spinner shows only after 500 ms; "Reopen to update" keeps the rows on screen. - e2e helpers and journeys for the switch-on suite. * fix(sidebar): keep an owed relay stop marked, clear a thrown stop, and prune pending unread raises - A stop-and-wait that throws takes its stop request back, like one that fails. - A final stop the legacy relay still owes stays marked, since the relay retries it. - Pending unread raises are tracked only while one waits, so the map no longer grows. - The paired-server fallback poll test gives its third fetch a reply and asserts live. * fix(sidebar): key activity, review, retention and repo lookups by host, not bare id The feed published activity and PR facts by bare workspace id, so a same-id workspace on two hosts (a paired server and this desktop, or two servers) shared one host's facts. Activity and review are now keyed by row identity, retention sweeps per listed row, and the builder resolves each row's repo by its own host's registration. Bumps the feed semantics version to 3. Claude-Session: e1fdb3d9-6985-4693-84aa-9a9fad732103 * test(e2e): read a review fact by its row key Claude-Session: e1fdb3d9-6985-4693-84aa-9a9fad732103 * test(mobile): key fixture rows by row identity Claude-Session: e1fdb3d9-6985-4693-84aa-9a9fad732103 * fix(sidebar): count and label rows by their own repo registration; keep activity keyed through a failed listing Host header counts and mixed-host labels read the row's own registration, as the host filter and row now do, so one render cannot file a row under one host and count it under another. A failed listing keys activity by the last rows. Claude-Session: e1fdb3d9-6985-4693-84aa-9a9fad732103 * fix(sidebar): a slower older listing never overwrites a newer one's rows Claude-Session: e1fdb3d9-6985-4693-84aa-9a9fad732103 * test(sidebar): read the quiet-desktop PR fact by its row key Claude-Session: e1fdb3d9-6985-4693-84aa-9a9fad732103 * refactor(repos): the renderer re-exports the shared getRepoHostIdentity Claude-Session: e1fdb3d9-6985-4693-84aa-9a9fad732103 |
||
|
|
2b716f601d |
fix(mobile): attach Codex images when agent identity is missing (#31370)
Use the shared desktop image-path formatter for unidentified mobile terminals and identified Codex, preserving owned agent identity, bracketed paste, upload routing and acknowledged-input ordering. Adapted from community PR #30310 by Wooseong Kim (@innocarpe). Fixes #30298. Validation includes exact-head CI and aggregate gate, native macOS and Windows consumer checks, actual paired Windows uploads with byte-integrity checks, and combined mobile/desktop tests, types, lint and bundle checks. Co-authored-by: Wooseong Kim <innocarpe@gmail.com> |
||
|
|
4a671db940 |
fix(native-chat): retire ghost queued continuation bubbles
Retire queued continuation echoes when transcript rows represent the sends. Preserve literal backslashes, occurrence boundaries, and image barriers on mobile and desktop. Closes #15288. Adapted from #15283. Co-authored-by: grboy6770 <2000grboy@gmail.com> |
||
|
|
524fa0039b |
Preview HTML files by default (#31575)
* Preview HTML files by default across file-opening flows * Centralize workspace file opening and HTML preview routing - Preserve source, diff, and host-safety behavior across all entry points - Reuse previews within the requested editor group and support branch HTML files * Respect working tree state when opening HTML previews * Route HTML links through owning workspaces and editors * Preserve HTML preview state and refresh changed local files * Resolve HTML preview hosts from workspace ownership * Update file-opening tests for HTML preview routing |
||
|
|
87ca5dad43 |
refactor(repo-host): one helper for the hosts registering a repo id (#31634)
Four twin checks (sort stamps, sidebar unread, sort-order notify, worktree-meta owner) each rebuilt new Set(repos.filter(id).map(getRepoExecutionHostId)). Name it once as getRepoRegistrationHostIds in shared/repo-host-identity. |
||
|
|
553a704403 |
refactor(execution-host): one resolver for the SSH target a repo row may dial (#31623)
getStoredRepoSshConnectionId and seven inline getSshTargetIdForExecutionHost(getRepoExecutionHostId(repo)) spellings answered the same question. Name it once in shared (getRepoDialableSshTargetId), build getRepoRoutingConnectionId on it, and drop the getRepoHostedReviewExecutionHostId re-export alias in favour of a direct import of getStoredRepoExecutionHostId. |
||
|
|
7d43ed9024 |
refactor(orcad): share one unverifiable terminal census (#31633)
Five modules each declared the same all-null census for a daemon that could not answer; they now use one frozen constant from the shared census module. |
||
|
+4 |
ae64a215a3 |
Add Brazilian Portuguese UI localization (#31627)
* feat(i18n): add Brazilian Portuguese * feat(i18n): migrate legacy Portuguese plugin preferences once Co-authored-by: Jackson Florencio <120382485+Jackson-Florencio@users.noreply.github.com> Co-authored-by: joaoguilhermesimon-collab <245094637+joaoguilhermesimon-collab@users.noreply.github.com> Co-authored-by: heslanx <167841364+heslanx@users.noreply.github.com> Co-authored-by: Janderson Fagner <135186779+janderson-fagner@users.noreply.github.com> Co-authored-by: Carlos <141033701+eusoucarlosmedeiros@users.noreply.github.com> Co-authored-by: João Messias Lima Pereira <41351492+joaorura@users.noreply.github.com> Co-authored-by: oliveiraleandro1981 <46854234+oliveiraleandro1981@users.noreply.github.com> Co-authored-by: hugolrf <12834009+hugolrf@users.noreply.github.com> Co-authored-by: Jonathan Oliveira <50607380+eojonathan@users.noreply.github.com> Co-authored-by: Antenor e Filhos <278213917+antenorefilhos@users.noreply.github.com> Co-authored-by: Daniel Dias <85655597+DeVFirmino@users.noreply.github.com> Co-authored-by: Sergio Alexandre de Carvalho <65230046+salexcarvalho@users.noreply.github.com> Co-authored-by: “Melostack” MeloX <229196278+Melostack@users.noreply.github.com> * rm design doc * fix(i18n): complete Brazilian Portuguese catalog --------- Co-authored-by: Jackson Florencio <120382485+Jackson-Florencio@users.noreply.github.com> Co-authored-by: joaoguilhermesimon-collab <245094637+joaoguilhermesimon-collab@users.noreply.github.com> Co-authored-by: heslanx <167841364+heslanx@users.noreply.github.com> Co-authored-by: Janderson Fagner <135186779+janderson-fagner@users.noreply.github.com> Co-authored-by: Carlos <141033701+eusoucarlosmedeiros@users.noreply.github.com> Co-authored-by: João Messias Lima Pereira <41351492+joaorura@users.noreply.github.com> Co-authored-by: oliveiraleandro1981 <46854234+oliveiraleandro1981@users.noreply.github.com> Co-authored-by: hugolrf <12834009+hugolrf@users.noreply.github.com> Co-authored-by: Jonathan Oliveira <50607380+eojonathan@users.noreply.github.com> Co-authored-by: Antenor e Filhos <278213917+antenorefilhos@users.noreply.github.com> Co-authored-by: Daniel Dias <85655597+DeVFirmino@users.noreply.github.com> Co-authored-by: Sergio Alexandre de Carvalho <65230046+salexcarvalho@users.noreply.github.com> Co-authored-by: “Melostack” MeloX <229196278+Melostack@users.noreply.github.com> |
||
|
|
b128cbbd6a |
fix(chat): route OMP question cards to terminal (#31440)
Route terminal-backed OMP question cards to the owning terminal and refuse automated ask answer/cancel writes. Preserve structured semantic answers and recognize OMP multi-select metadata. Verified against the real OMP selector source; automatic semantic card answering remains tracked in #26692. Co-authored-by: jairuspace <jairusbpace@gmail.com> Co-authored-by: Daniel Lopez <dafeloru@gmail.com> |
||
|
|
b3f1607c84 |
Remove directional tab-close actions and tracking (#31599)
* Remove directional tab-close menu actions * Remove retired directional-close translations * Remove retired directional-close PostHog tracking * Preserve legacy app-open schema compatibility without emitting samples |
||
|
|
2b1da76d70 |
fix(mobile): a windowless server warns about unwakeable agents only when the workspace really has slept agents (#31607)
* fix(mobile): warn about unwakeable agents on a windowless server only when the workspace really has slept agents
A running ('live') or quit agent's resume record made a windowless server tell the phone
'Open Orca on the host to wake sleeping agents.' Count only real sleep records, using the
shared isPaneSleepRecord predicate.
* refactor: move the headless wake check into a shared hasSleptAgentToWake predicate
* docs: say a live or quit record is resumed by its own pane
* test: build the headless wake report store from the shared partitioned fixture, without casts
* test: make a host-less session read miss the record, so the SSH partition test proves the named-host read
|
||
|
|
52f6960751 | fix(mobile): closing the tab a phone shows returns it to the tab it viewed before (#31365) | ||
|
|
22154de422 | feat(mobile): tab strip shows terminal and chat agent state, reveals the next tab, renames on double-tap (#31372) |