mirror of
https://github.com/stablyai/orca.git
synced 2026-11-02 01:57:57 +00:00
2c44830c68cd69ea97ff1eb7f70be0203aca14d4
14392
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
2c44830c68 |
fix(remote-terminal): a pane-restore snapshot moves the gap baseline so reveal skips a resync repaint (#29285)
Refs #22087 |
||
|
|
187c0b023a |
fix(runtime): suspend the socket idle timeout while a dispatch is in flight (#29262)
The runtime socket transport reaped connections after 30s of raw byte silence, and Node's idle timer counts bytes — so a slow dispatch like worktree.create on a large repo, which is not a long-poll and sends no keepalives, read as a dead peer: the server destroyed the socket mid- request, the handler kept running (the worktree got created), and the CLI reported runtime_unavailable and told the user to restart. Callers then retried, leaving orphaned worktrees or two agents on one task (#25830, the root behind #15663/#23911/#20108 symptoms). The reap timer now suspends while dispatches are pending and rearms when the last one cleans up. Quiet connections with nothing in flight still reap after exactly the same 30s, and a dead peer on a local socket is delivered by the kernel as close/error, which the existing cleanup already handles — so the reaping duty is unchanged where it mattered. Fixes #25830 Generated-by: GLM-5.3-Flash (ZCode) Co-authored-by: ggbdpq <ggbdpq@gmail.com> |
||
|
|
ebd8eff4ce |
fix(github): resolve SSH host aliases for account binding (#29018)
* fix(github): resolve SSH host aliases for account binding An origin like git@github-personal:owner/repo kept the alias as the required gh host, so the Settings account list matched nothing. * fix(github): keep github.com filter for resolved aliases and resolve in the gh runtime Real canonical keys carry github.com, so an alias resolving to github.com must filter to github.com like a direct remote. Resolve via the runtime-scoped resolveSshConfigHostname (WSL distro aware) and keep Enterprise hosts exact. * fix(github): expand SSH aliases only for SSH-transport remotes * fix(github): resolve the SSH alias with its original case --------- Co-authored-by: orchardprior <342342873+orchardprior@users.noreply.github.com> Co-authored-by: Neil <neil@stably.ai> |
||
|
|
0acb4933c0 |
test: observe keepalive suppression while short RPC is pending (#29475)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
82f9eef651 |
test: remove duplicate POSIX missing-artifact install probe (#29470)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
c3811b80d0 |
test: exercise a real mobile floor claim during preview paste (#29464)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
e82bdbe9da |
test(linear): reuse runtime import across project access cases (#29452)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
2004d0c7d1 |
perf: batch changed-code quality baseline reads (#29435)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
6ccb7d0a9c | perf: avoid pairing web rebuilds after editing existing tests (#29467) | ||
|
|
13084ba347 |
feat(mobile): long-press a workspace to see its linked PR, issues and notes (#29225)
* fix(mobile): phone server rows follow the desktop's other-client and sleeping filters A phone created through a desktop now records whom it acted for, so the desktop's Hide other-client workspaces filter keeps the user's own phone workspaces (locally and on servers) and hides only other people's. The desktop relay marks each server row its sidebar would hide, and the rows its own browser or chat tabs keep awake; the phone applies both. * test(e2e): dedupe sidebar row ids in the visibility spec * fix(mobile): address review: owner naming, old-server relayed phones, scope trim * refactor: move the sidebar's project section grouping into shared The project sections the desktop sidebar draws under Group by Project are built from the project/setup projection, the per-host catalog fold, the endpoint host stamp, and the section labelling and ordering rules. Move the pure parts of each into src/shared (no behaviour change) so the paired phone can call the same code instead of guessing the grouping. * fix(mobile): group by Project with the desktop sidebar's own sections The phone grouped Project sections by repo display name, so it merged checkouts the desktop keeps apart (several local stablyai/orca checkouts, or a server's copy) and split what the desktop merges. The phone now reads each host's repo.list, project.list and projectHostSetup.list (the desktop's own and each server's through the relay), folds them with the renderer's shared catalog fold and projection merge, and builds sections with the desktop's shared grouping, labelling and ordering code. Keys, labels and Recent order equal the sidebar's; a host that predates the project lists gets the repo-derived projection, as the desktop does. Header colour and icon come from the section's anchor repo and rows from their own repo by id, as on the desktop. The repo filter lists every catalog repo by id per host instead of merging same-named repos. Group-by labels read Project and None. project.list and projectHostSetup.list are routed for paired phones (read-only, workspace permission). * refactor(mobile): record a phone's owner as creator and fold desktop tab activity into the host flag A phone now records its owner as the creator (this host for a directly paired phone, the relaying desktop for a delegated one), so the shared rule is unchanged and onBehalfOf is gone. The relay ORs the desktop's saved browser/chat tabs into hasHostSidebarActivity, so the phone's status dot follows too, and local worktree.ps counts the same signals. The old-server fallback is removed. * test(e2e): poll the phone and the sidebar together in the visibility spec * fix(mobile): one Project-section builder for desktop and phone, with the desktop's repo order Review fixes. The sidebar's buildOrderedGroups now calls the shared buildProjectSections for Group by Project (notice and pending repos are optional inputs), so desktop and phone run one function. The phone ranks manual header order by its folded catalog order, which is each host's repo.list order with the desktop's own repos first, as the renderer loads them; only the desktop's cross-host manualRepoOrder (pairing-local) is unknown to it. The projection selector is now a memo over the shared resolver. A transient project-list failure keeps that host's last catalog; only forbidden or method_not_found falls back to the repo-derived projection. Catalog rows are checked on every member grouping reads, and the parity test answers the renderer's real catalog fetch, includes a server's own project rows, and fixes Manual and Recent orders that differ. * fix(mobile): use the repo-derived catalog until a host's project lists first answer * fix(mobile): the desktop serves its sidebar's Project catalog instead of the phone fetching it The phone fetched repo.list, project.list and projectHostSetup.list from the desktop and every relay-ready server each minute and folded them itself, so rows from offline or older servers fell back to repo sections and keys moved on cold start. The desktop renderer now publishes the inputs its own Project headers use (state.repos in sidebar order, the projection selector's projects and setups, projectOrderBy) on the runtime window graph it already sends to main, only when they change. Main keeps the last one and answers it on a new paired-desktop read, mobileRelay.projectSections. The phone reads it with its repo metadata and groups with the shared builder; a desktop that predates the read (forbidden or method_not_found) leaves the phone grouping rows by repo from the desktop's repo.list, and a transient failure keeps the last catalog. The payload carries only grouping and label fields, no hooks, credentials or uploaded icons. The phone's own catalog fetching and its project.list/projectHostSetup.list routes are removed. * fix(mobile): keep uploaded repo icons on the phone, and isolate the snapshot tests * test(e2e): the desktop window serves its sidebar's Project catalog to the phone * chore(i18n): regenerate the runtime English catalog (drift already on main) * fix(mobile): read the Project catalog as its own request, outside the recorded repo-metadata flow The extra read inside the repo-metadata refresh stalled its recorded RPC sequence. It now runs beside it with its own throttle. The repo-metadata goldens are re-recorded for the intended state change: the name-keyed colour, icon and id maps became desktopRepos. * refactor(sidebar): one shared Workspace options filter and sort evaluator The sidebar, the jump palette and the options badge each applied the Workspace options filters with their own copy of the rules. They now call one pure evaluator in src/shared/workspace-view, which reads each row through a small fact reader so the phone can call it next with the facts its host serves. The sort comparator moves there too, with each surface supplying its own Agent activity rank. No behaviour change: a parity test runs the old sidebar chain and the new evaluator over every toggle combination, and the old comparator against the new one for each sort mode. * wip: workspace view descriptors * refactor(sidebar): address review of the shared Workspace options evaluator One predicate builder instead of a per-row scope argument; one exemption-narrowing function taking the hide flag; consumers import the shared predicates directly; Agent activity ties fall to the label in the shared comparator. The activation filter lift reuses the shared predicates. The parity test now covers other-client rows, live agent attention classes and the sort-label map. * fix(mobile): fetch the Project catalog at once when the screen moves to another host The refresh window is now kept per client, so a host screen reused for another desktop doesn't wait out the previous host's 60s window before showing its Project headers. * wip: desktop option items from shared choices * refactor(sidebar): the Workspace options menu renders from one shared option list src/shared/workspace-view/workspace-view-options.ts lists every Workspace options control (Hosts, Projects, Group by, Sort by, Project order, Card layout, Show properties or Card display, and each filter) with its section, its English copy, its choices and when it shows. The desktop menu walks that list and renders each option through a table keyed on the option key, so a new option fails to compile until the desktop has a control for it; the phone sheet will do the same. The choice lists (sort modes, project order, card layout, agent activity layout, card properties) are derived from the shared ids, and a test checks the desktop's English copy matches the shared copy. The unused classic branch of the card property list is removed. No visible change. * wip: row facts * refactor(sidebar): address review of the shared Workspace options list The show rules get their own tests with fixed expectations (the cases the old filter-section test covered, plus the rest), and the menu test checks each option's own control rather than any matching text. Card display rows toggle one property each, with the folder-path copy in shared. The unused Status and Tasks copy left by the removed classic card list is deleted from the catalogs. Filter rows write through the store directly; files are named for what they hold. * feat(runtime): worktree.ps carries the Workspace options row facts Each worktree.ps row now says whether it is the project's default-branch workspace, created by an automation, created by the CLI, or on a detached HEAD, answered by the same shared predicates the desktop sidebar filters with. The phone has none of these facts today, so its copies of the filters either guess (default branch) or are missing. Additive and inert: optional fields that nothing reads yet. An older host omits them; readers must treat absence as 'not that kind', so the row stays visible. Server rows relayed through the desktop pass them through unchanged. * feat(mobile): the desktop's own phone reads and writes its other-client filter ui.get and ui.set strip the pairing-local UI fields for every paired client. That rule exists for clients with their own host catalog (a desktop paired to a server, a web client). A phone has none: it shows its desktop's view, so 'Hide other-client workspaces' must be one shared value. For the host's own phone (clientKind mobile, no relaying parent) ui.get now always answers the field and ui.set persists it; delegated phones, paired desktops and web clients keep the stripping rule. The phone's view-settings schema reads the rest of the Workspace options values it does not read yet (the automation, CLI and detached-HEAD filters, project order, card properties, agent activity layout), each salvaged to absent so an older desktop keeps the phone's local value. * feat(runtime): address review of the worktree.ps row facts Name the fact defaultBranch, and say what absence means for it: a reader keeps its own guess, because 'hide default branch' must not start hiding or showing rows an older host never described. Folder workspace rows get the facts too, so every row from a newer host carries them. The desktopOtherClient comment now says it is a verdict, not a fact. The test covers the rows where the host disagrees with the phone's current guess. * wip: phone uses the shared evaluator * feat(mobile): address review of the phone's other-client filter mirror One isHostOwnPhone predicate decides both who shares the filter value (ui.get/ui.set) and who gets the other-client row marks, so the two cannot drift. The pairing-local field list notes the exception. Tests cover a paired desktop still being stripped, and a phone write that leaves the field out not touching the host value. * feat(mobile): the phone filters and sorts with the desktop's shared Workspace options rules The phone's own filter chain and comparator are replaced by the shared evaluator, reading the facts the host stamps on each row. Phone filter state takes the desktop's setting names and carries every filter; the badge and Clear filters match the desktop's. The desktop's other-client marks become facts the phone filters with the shared value. A parity test runs the same workspaces through the desktop's reading and the phone's (facts stamped as the host stamps them) over every filter combination, folder projects included. * wip: phone view state carries project order and card props * fix(mobile): host scope in shared filters, patch-key writes, live view push Folds the phone's host filter into the shared filters so Clear and the badge agree, writes back only the touched filter keys, and pushes workspaceViewChanged so an open phone list re-reads desktop Workspace options. * fix(mobile): Clear sends only changed filters; skip a view re-read older than a local edit An older host's strict ui.set refuses a key it lacks, so Clear names only what differs. A ui.get that started before a local edit no longer overwrites it; the edit's own change event re-reads. The change publisher's field list now lives with it and derives the filter fields. * feat(mobile): the phone's Workspace options sheet, rendered from the desktop's shared option list The Filter drawer becomes the desktop's Workspace options: hosts, projects with search, group, sort, project order, card layout and properties, card display, and every filter. Each option renders through a table keyed on the shared option keys, so a new desktop option fails to compile until the phone has a control. Sort and group pickers use the desktop's words; Repo reads Project. * fix(mobile): Workspace options sheet review fixes Hosts read as on the desktop (none checked while all show; the last shown host is disabled). Project order falls back to the served value until the shared one is read. Card layout and card style changes now push to an open phone. Pick-one rows read as radio buttons. Simpler wiring: flat card state, the preset flag rides the patch, shared choices used directly. * fix(mobile): reset project order on host switch; simpler preset-flag handling * fix(workspace-options): all hosts and clear reach the desktop; one filter key list drives every surface Host visibility: the legacy host scope fallback moves to shared code; the phone reads it, and the host resets the scope whenever a client writes the host list, so All hosts and Clear stick. An older desktop that keeps the other-client filter to itself has its marks treated as hide. Badge counts, is-anything-filtered, Clear and reveal derive from the shared filter keys on the desktop sidebar and the kanban filter menu. The phone uses the desktop's group and sort values, holds its view in one state value, and reads its UI fields from one shared list. * feat(workspace-options): Status and PR grouping read the shared tables The phone groups by status with the desktop's status helpers and default catalog (its own copy had the defaults in reverse order) and by PR with a shared lane table, so its labels now read In review / In progress as the desktop's do. The desktop's PR lane decision ends in the same shared state-to-lane step. * feat(mobile): phone rows follow Card layout, Show properties, Card display and agent activity One shared helper (getWorktreeCardDetails) decides which card details show for the chosen properties and layout; the desktop card's flags and the phone row both read it. The phone row hides the PR badge, note/issue/Linear glyphs, host badge and agent rows the desktop turns off, and the Full list agent layout shows every agent row. * test(sidebar): folder rows survive restrictive filters; create grace ignores non-finite times * fix(mobile): write the host scope with the host list, and wait for the first read before forcing the other-client filter An older desktop narrows back to its legacy single-host scope when the phone writes only a null host list, so the phone now also writes the scope for a null or one-host list. The other-client fallback waits for the first ui.get so a new desktop's marks don't hide rows before its filter value arrives. Inline the clear-filters key list and note the PR state asymmetry. * test(mobile): re-record view-settings goldens for the unknown other-client state * fix(mobile): let a tall bottom drawer scroll on the page The drag wrapper around the drawer's ScrollView had no flex limit, so it grew to its content and the sheet clipped it instead of scrolling. The full Workspace options sheet is the first drawer tall enough to hit this. * fix(sidebar): reuse the palette's default host instead of reading the focus setting again * fix(sidebar): read the host options once in Workspace options and pass them to the Hosts item * fix: parse the ui.get reply into a named type, fix the row memo test's filters, prune the focus-read baseline * test(mobile): give the project catalog fixture its project order * feat(mobile): name the options chip Workspace options, as the desktop does The chip keeps the active-filter count and reads to screen readers with the desktop trigger's label. The pluralized filter count moves to shared code so both surfaces word it the same way. * fix(mobile): show the Workspace options count as a corner badge so the chip row fits "Workspace options (2)" squeezed the Sort and Group chips to ellipses at phone width. The count moves to a corner badge, as on the desktop trigger, and the chip drops its icon, which the desktop trigger does not show either. * refactor(sidebar): one switch-to-kind table, and fold the leftover helper files back - The four kind switches come from WORKSPACE_KIND_SWITCH in workspace-kinds; the shared evaluator and main's phone-push check both apply it, and the filter type derives its switch fields from it. - git-identity.ts folds back into git-identity-display.ts, as on main. - SidebarFilterState moves into sidebar-filter-actions.ts; visible-worktree-kinds.ts is gone. - buildWorkspaceRowPredicate is module-private. * feat(mobile): Workspace options sheet in the desktop menu's shape The sheet showed every choice of every option, so the filters sat screens down. It now follows the desktop menu: Hosts and Projects rows with their value, Group by as a segmented control, Sort by, Project order, Card layout and Show properties as rows that open a page of choices, and the filters as switches. Each option's control (an inline row, or a value plus a page) still comes from one table keyed by the shared option list. The segmented control is the voice settings one, extracted so both screens share it. * fix(mobile): Workspace options review fixes - A page whose option stops showing is forgotten, so it cannot reopen by itself. - Only the switch takes the tap on a filter row, so the web page writes once. - Sections split their rows in one pass; unused heading styles go. * fix(mobile): neutral filter switches on the page react-native-web paints an on-switch thumb teal unless given activeThumbColor, which React Native's types omit. MobileSwitch applies the app's switch colors, and its web sibling also sets that prop. * refactor(mobile): one MobileSwitch file, adding the web-only thumb color on web * fix(mobile): Show properties reads Hover under Compact, as the desktop does The row's value now comes from getWorkspaceCardPropertiesValue in the shared options, which the desktop trigger uses too: Hover under the compact layout, otherwise how many properties show. Card display shows no value, as on the desktop. * test(mobile): find the renamed Workspace options chip in the page drawer render check * feat(mobile): drop the Sort and Group chips; the Workspace options chip covers both The desktop has only its options button, and the sheet now holds Sort by and Group by. The chips' pickers, their screen state and the sort label go with them. * feat(mobile): option pages slide in from the right and keep the sheet's height The main sheet stays laid out under an open page, so the drawer keeps its height going in and out. The page slides in over 200 ms and back out on back (the row, or Android's back key), instantly under reduced motion. The reduced-motion hook moves to platform/ now that two screens use it. * feat(mobile): Compact rows fold into one title line like the desktop compact card The phone's Compact layout now moves repo identity into a title-row icon chip and drops the identity meta row (repo, host, branch or folder path, child badge), matching the desktop's compact card. The rule lives next to getWorktreeCardDetails as getWorktreeCardLayout, and the desktop presentation reads it too so both surfaces share one decision. * fix(mobile): keep a remote host glyph on compact rows; pass the card layout from the list Review follow-ups: compact rows show an icon-only host glyph for remote projects as the desktop compact card does, the list computes the layout once next to the card details, and a new-card-style row test. * fix(mobile): option pages fill the sheet and open at its top - The page layer grows to the pager's height, so no part of the main sheet shows below a short page. - The drawer takes a scrollResetKey; the sheet passes the open page, so a page opened from a row low on a scrolled sheet starts at the top. - The main sheet's height is measured under a page too, and the pager state lives in the sheet so it resets when the drawer closes. - A misplaced doc comment goes back to its function. * fix(mobile): phone rows show the Jira, automation and CLI glyphs; the options pager forgets a gone page in an effect * fix(mobile): Jira glyph sits before Linear as on the desktop; Jira reader tests beside it * feat(mobile): long-press a workspace to see its details The phone's long-press sheet now lists the workspace's linked PR and issues (tap to open), who created it, its notes and live ports (Copy), the phone's take on the desktop sidebar card's hover card. Folder workspaces get the sheet too, with details only. The desktop lets phones run workspacePorts.scanHost (read only). * fix(mobile): details read links the desktop's way and stay one-off Links come through the shared getWorkspaceAttachments, so references the desktop keeps apart stay apart, in the host's order with reviews first. The branch review read no longer takes the host's active-branch slot, each read re-runs only for its own inputs, a reopened sheet reads afresh, and Copy's confirmation never outlives the sheet. * fix(mobile): details clear on close without an effect; lint findings * fix(mobile): the phone leaves Ports out of Show properties and Card display * refactor(mobile): clearer names and tests for the phone's hidden card properties * feat(mobile): details sheet heading carries the origin; no ports As Jinwoo approved: the sheet heads with the workspace (primary text), its short branch, and a quiet origin line (automation name, or Orca CLI). The group below holds only linked reviews and tasks, then notes. Pin uses the pin icon. Ports are left out of the phone, so the desktop change that let phones scan them is reverted. * test(mobile): details section render helper matches its props * fix(mobile): details review read asks by branch; review merge by number; comments * fix(mobile): details rows share the action rows' text column * refactor(mobile): details sheet reads only the row The sheet no longer fetches. The host stamps two optional row fields: automationName beside automationCreated, and the branch PR's title, url and checks on linkedPR (from the GitHub cache it already reads). Older hosts omit them and the sheet shows what they send. Links match by provider, type and number; the reference label is one shared helper the desktop card uses too. Folder rows keep no long-press. One sheet file plus the pure model. * fix: review nits on the row-only details sheet * refactor(mobile): one view state and one settings read for the phone's Workspace options; tighter card glyph wiring - The phone's Card layout and card style now live in its view state; one parallel settings.get reads them with pinned placement beside ui.get. - The Card layout preset flag is a write option, no longer a view field or a change-event field. - getWorktreeCardDetails reads the raw desktop settings and resolves the layout once; the desktop card computes it once in its foundation. - The row computes its glyph presence in one place; Ports is hidden through one set. - Drops the vanished-page effect, the native-only a11y props and the web-only switch branch. * fix(mobile): the list settings read applies each half on its own, with tests; pinned placement changes announce themselves * fix(mobile): compact host glyph tests for older rows and the new card style; truer comments * fix(mobile): Card layout writes the setting before its preset; Card display names folder paths when the desktop has folder workspaces * fix(mobile): match the branch PR by repo and link, not number alone |
||
|
|
a8e3734e11 |
test: remove setup sequencing shell inspection seam (#29399)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
144aac00cc |
chore: update Vite, Tailwind, and build tooling (#29345)
* chore: update build and test toolchain * fix(build): isolate shared code from CLI entry overwrites * fix(build): preserve main startup asset paths * test(build): override resolved Vite 8 fixture inputs --------- Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
7f3677ec13 |
test(mobile): remove repeated presence and restore cases (#29457)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
955c7a95a6 |
perf(css): exclude renderer tests from Tailwind scanning (#29428)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
991e2dda26 |
feat(layout): move, reorder and split tab groups through main behind the layout-owner build switch (#29313)
* feat(layout): add the dark layout.apply channel and route pane splits through main behind ORCA_LAYOUT_OWNER A build made with ORCA_LAYOUT_OWNER=main registers layout.apply: main applies the window's layout command to the stored partition through the shared applyLayoutCommand, minting new ids. A user split then waits for main's answer and mounts the pane id main minted. Every other build substitutes 'window', so neither branch is compiled in. * fix(layout): write only the records a layout.apply command touched A load-then-save rewrite also normalizes records the command never touched. The command's effect is now the diff between the save before and after it, written onto the stored partition record by record. A split whose main reply says a paired server holds the tab splits as today. * fix(layout): write a load-supplied record whole and check that patched partitions reload to the command's result * feat(layout): close, rename and equalize panes through main behind ORCA_LAYOUT_OWNER In a layout-owner build the window's pane close, title change and equalize go through layout.apply and the window shows main's answer. A window pane close keeps the legacy close's rules: the tab's last pane is refused, a pane restarted since main read the close is left alone, every partition holding the tab closes it, and the tab's remote session id follows the remaining pane. The rules sit behind a command field only layout.apply sets. * fix(layout): close the tab when a racing pane close leaves the window one pane * fix(layout): leave an unmounted tab alone when main refuses its last pane * feat(layout): move panes and save divider ratios through main behind ORCA_LAYOUT_OWNER Claude-Session: 10569c9a-a0a1-4fc9-8469-0edfb7aed125 * test(layout): a taken pane drop whose pane closed does nothing Claude-Session: 10569c9a-a0a1-4fc9-8469-0edfb7aed125 * test(layout): pin the window's pane move to main's saved tree, and the drops main cannot take Claude-Session: 10569c9a-a0a1-4fc9-8469-0edfb7aed125 * fix(layout): close a user's pane even if its terminal restarted, as today Claude-Session: 10569c9a-a0a1-4fc9-8469-0edfb7aed125 * test(layout): pin the restarted-pane close directly, not through a made-up profile state Claude-Session: 10569c9a-a0a1-4fc9-8469-0edfb7aed125 * fix(layout): leave a split to today's path only when the workspace's row names a paired server The split switch point asked which host to route to with a helper that falls back to the focused server, so a focused server could claim a workspace whose row names no owner. Use the same owner test the tab mirror uses. * test(layout): type the split owner mock without a cast * test(layout): type the layout-owner command mocks with the real signature * test(layout): type the gesture command mock with the real signature * fix(layout): close the dark path's gaps: unmounted split panes, refused or failed splits and moves, ratios during a move, release guard - A pane main saved but the window could not mount (source pane or manager gone during the await) is closed again in main, so it does not come back on restart. - A split main refuses because its copy lacks the workspace, tab or pane, or a failed call, splits as today; a refused or failed move moves as today. - Divider ratios committed while a move is in flight wait for the window's move, then go to main. - The orcad bundle gets the ORCA_LAYOUT_OWNER define when the switch is on. - Packaging and the orcad template refuse ORCA_LAYOUT_OWNER=main and any output a dark build marked. - workspace-layout-record-patch.ts: no non-null assertions; plain comment for the map depth. * test(layout): count a split pane as mounted from the split mock's own results * fix(layout): act as today whenever main lacks the target or the call throws, not just for splits - sendPaneCommandToLayoutOwner runs asToday for workspace/tab/pane_not_found and a thrown call, so close, rename and equalize fall back like split and move; a handler that throws no longer runs the fallback too. - A close main refuses as its last pane, while this window still has others, closes as today. - A move whose local step throws still releases held divider ratios. - Drop the orcad output marker: nothing read it; the template build refuses the switch itself. * test(layout): plain names for the last-pane fallback test and the marker comment * docs(layout): say plainly what an indeterminate write can leave behind * fix(layout): finish the main merge with this branch's versions of the layout-owner files * test(build): copy the layout-owner build guard into the compiler-cache checkout fixture * fix(layout): write a folded legacy row in its loaded form when a layout.apply command touches its claim A legacy terminal row the load folds into a tab-bar tab stays stored as is. Closing the tab it repeats, or giving it a tab-bar entry by moving it, let the next load resolve the claim the other way: the row came back or took the other tab's terminal. Such a command now writes the row as the load had it; every other record still stays as stored. * feat(layout): accept tab moves, group splits and group sizes on layout.apply Group sizes have no tab, so they go to the workspace's routed partition. * refactor(layout): move the window's layout.apply sender out of the terminal pane folder Tab groups send through it too; it now also acts as today when main lacks the group. * feat(layout): reorder, move and split tab groups, and save group sizes, through main behind ORCA_LAYOUT_OWNER A tab drop and Move Tab to Split wait for main's answer and then show main's placement, with main's new group id; group divider sizes are drawn while dragging and saved by main when the drag ends. Closing an empty group needs no command: main never holds an empty group. * fix(layout): review fixes for tab moves through main - Read a folded row's terminals with the loader's own claim rule, so rows sharing only an SSH session are covered too, and drop the row's remote session entry with it. - The record-patch test allows a folded row only in its loaded form. - A tab drag ends at once; main's answer shows the move after. - A lone group main moved whole is placed so only when this window's group is lone too. * refactor(layout): adopt only a folded row's pane layout beside its row A row's remote session entry is carried through load and save unchanged, so adopting it from the load changed nothing (the earlier commit's message overstated it). |
||
|
|
29c825d72a |
test(runtime): observe fresh mail pointer receipt without fixed delay (#29447)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
e65a1dd553 |
Keep idle Claude sessions selected during nested Codex work (#29386)
* Preserve idle foreground Claude session ownership through nested hooks * Discard obsolete hook probes and cancel queued restarts |
||
|
|
a8f2c65df5 |
test: remove duplicate terminal query authority checks (#29422)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
4462001ba0 | fix(orcad): never launch the orca-ide bash shim as the headless browser (#29363) | ||
|
|
9c177fb944 |
test(runtime): remove duplicate completed-worker close sequence (#29411)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
ac0d8c4fd0 |
test: consolidate CLI regressions and simplify IPC lifecycle proof (#29298)
* test: batch lint fixtures and remove repeated runtime scan * test(cli): consolidate owner coverage and remove false decoding proof * test(renderer): retain IPC lifecycle behavior without copied inventories * test(git): keep checkout progress proof within file limit * fix(lint): classify the shared mobile chat harness as test support --------- Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
da099c3201 |
fix(worktrees): remote hosts honor the client's Nest Workspaces setting (#29404)
* fix(worktrees): remote hosts honor the client's Nest Workspaces setting The client now sends nestWorkspaces on worktree.create and the host uses it for the path layout, falling back to its own setting for older clients. * fix(worktrees): carry the chosen layout through name retirement and metadata |
||
|
|
90849ed0c6 |
Enable Claude plugin images and bounded terminal file transport (#28200)
* fix: render Kitty Unicode placeholder images with bounded ownership * Enable managed Claude plugin images and bounded host file transport * Preserve isolated Claude evidence and paired restart diagnostics * Resolve Windows workspace aliases before WSL image reads * Handle split remote terminal identities and improve WSL file-read diagnostics * Reuse native drive paths for WSL image files and preserve guest temporary roots * Apply native Windows path restrictions to mapped drive image sources * Preserve WSL participation evidence across image checks * Keep WSL drive directory containment case-sensitive after canonicalization * Negotiate managed Claude image support with the launching renderer * Make image repaint checks independent of display profile and shell output * Capture repaint diagnostics only after the pixel assertion fails * Allow floating terminal image reads from host temporary folders * Keep image stack independent of unrelated CI runner and mobile lint settings * Reuse worktree argument builder for terminal viewer context Remove duplicated mapping and keep the RPC method table within its existing line limit. |
||
|
|
802508c22f |
test(process-host): reuse compiled fixture for unchanged-output check (#29408)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
26278b32ce |
Render Kitty images at Unicode placeholder cells (#26031)
* fix: render Kitty Unicode placeholder images with bounded ownership * Make image repaint checks independent of display profile and shell output * Capture repaint diagnostics only after the pixel assertion fails |
||
|
|
9c863a6f83 | fix(ssh): read the macOS machine id from IOPlatformUUID and make the shared-home claim exclusive without hard links (#29259) (#29284) | ||
|
|
24b87a7a4d |
fix(remote): overlap a reveal's stream open with its create, and claim the viewport once (#29269)
* fix(ssh): a parked remote pane's reveal needs one snapshot and one fewer round trip (#24863) * fix(ssh): a different resize re-arms a claim of the earlier grid * fix(ssh): the host's echo of our own claim does not trigger a second claim * fix(ssh): build the subscribe image alongside viewport registration; a peer hold re-arms a claim * fix(ssh): a desktop-fit answer at the host's grid does not re-arm a second claim * fix(ssh): a served subscribe image no longer waits on the transcript read * fix(ssh): send the served subscribe image without waiting on viewport registration * revert(ssh): keep the requested reveal snapshot; the pushed one was slower on long history |
||
|
|
ec9a0af3e8 |
Show phone subagents and open the correct parent chat (#28686)
The phone's worktree list now shows the running subagents the desktop sidebar shows, under their parent agent with their own ages, read from the host's existing child records. Tapping one opens its parent's existing chat or terminal. The feature was reviewed in #26423 and merged into this branch. Links from the phone to native chats whose saved tab ID differs from the session-derived one (restored, reserved and headless chats) now resolve to the chat's real tab instead of missing it. |
||
|
|
7909e72d2d |
ci: move PR analysis and Linux unit tests to Blacksmith (#29362)
* ci: report final PR checks outside the shared runner queue * ci: fix inherited mobile test file size failure * ci: move PR analysis and ARM test shards to Blacksmith * Qualify x64 Blacksmith capacity and reject incompatible runner images early * Keep extracted mobile test adapters within the test-only lint scope * Identify the runner profile overriding shell fixture homes * Preserve fixture HOME through the Blacksmith login profile * Make cache invalidation fixtures observable within one filesystem clock tick * Scope Blacksmith system-profile preparation to Linux runners * Wait for observable ctime in daemon hash cache fixtures * Use the mobile test lint scope already merged on main * Stabilize metadata and timer fixtures on fast CI runners --------- Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
f152101010 |
ci: reuse prepared Windows security addon in PR packages (#29352)
* ci: reuse prepared Windows security addon in PR packages * ci: prepare bounded Windows security reuse qualification * ci: ignore owned Windows benchmark receipts during source checks * test: inject Windows security qualification dependencies * test(mobile): register chat view mocks in test roots |
||
|
|
c386cdd202 | fix: remove comments from typecheck JSON configs (#29398) | ||
|
|
24bec2d260 | fix(terminal): preserve wake records after hibernation exit (#29288) | ||
|
|
a3dda8af42 |
perf(typecheck): check shared tests only in the Node project (#29381)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
79d131d521 |
ci: move the final PR report off the busy runner pool (#29337)
* ci: report final PR checks outside the shared runner queue * ci: retain the mobile harness test mock allowance --------- Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
9b99928cb5 |
fix(layout): close the dark layout path's gaps, and refuse to package it (#29207)
* feat(layout): add the dark layout.apply channel and route pane splits through main behind ORCA_LAYOUT_OWNER A build made with ORCA_LAYOUT_OWNER=main registers layout.apply: main applies the window's layout command to the stored partition through the shared applyLayoutCommand, minting new ids. A user split then waits for main's answer and mounts the pane id main minted. Every other build substitutes 'window', so neither branch is compiled in. * fix(layout): write only the records a layout.apply command touched A load-then-save rewrite also normalizes records the command never touched. The command's effect is now the diff between the save before and after it, written onto the stored partition record by record. A split whose main reply says a paired server holds the tab splits as today. * fix(layout): write a load-supplied record whole and check that patched partitions reload to the command's result * feat(layout): close, rename and equalize panes through main behind ORCA_LAYOUT_OWNER In a layout-owner build the window's pane close, title change and equalize go through layout.apply and the window shows main's answer. A window pane close keeps the legacy close's rules: the tab's last pane is refused, a pane restarted since main read the close is left alone, every partition holding the tab closes it, and the tab's remote session id follows the remaining pane. The rules sit behind a command field only layout.apply sets. * fix(layout): close the tab when a racing pane close leaves the window one pane * fix(layout): leave an unmounted tab alone when main refuses its last pane * feat(layout): move panes and save divider ratios through main behind ORCA_LAYOUT_OWNER Claude-Session: 10569c9a-a0a1-4fc9-8469-0edfb7aed125 * test(layout): a taken pane drop whose pane closed does nothing Claude-Session: 10569c9a-a0a1-4fc9-8469-0edfb7aed125 * test(layout): pin the window's pane move to main's saved tree, and the drops main cannot take Claude-Session: 10569c9a-a0a1-4fc9-8469-0edfb7aed125 * fix(layout): close a user's pane even if its terminal restarted, as today Claude-Session: 10569c9a-a0a1-4fc9-8469-0edfb7aed125 * test(layout): pin the restarted-pane close directly, not through a made-up profile state Claude-Session: 10569c9a-a0a1-4fc9-8469-0edfb7aed125 * fix(layout): leave a split to today's path only when the workspace's row names a paired server The split switch point asked which host to route to with a helper that falls back to the focused server, so a focused server could claim a workspace whose row names no owner. Use the same owner test the tab mirror uses. * test(layout): type the split owner mock without a cast * test(layout): type the layout-owner command mocks with the real signature * test(layout): type the gesture command mock with the real signature * fix(layout): close the dark path's gaps: unmounted split panes, refused or failed splits and moves, ratios during a move, release guard - A pane main saved but the window could not mount (source pane or manager gone during the await) is closed again in main, so it does not come back on restart. - A split main refuses because its copy lacks the workspace, tab or pane, or a failed call, splits as today; a refused or failed move moves as today. - Divider ratios committed while a move is in flight wait for the window's move, then go to main. - The orcad bundle gets the ORCA_LAYOUT_OWNER define when the switch is on. - Packaging and the orcad template refuse ORCA_LAYOUT_OWNER=main and any output a dark build marked. - workspace-layout-record-patch.ts: no non-null assertions; plain comment for the map depth. * test(layout): count a split pane as mounted from the split mock's own results * fix(layout): act as today whenever main lacks the target or the call throws, not just for splits - sendPaneCommandToLayoutOwner runs asToday for workspace/tab/pane_not_found and a thrown call, so close, rename and equalize fall back like split and move; a handler that throws no longer runs the fallback too. - A close main refuses as its last pane, while this window still has others, closes as today. - A move whose local step throws still releases held divider ratios. - Drop the orcad output marker: nothing read it; the template build refuses the switch itself. * test(layout): plain names for the last-pane fallback test and the marker comment * docs(layout): say plainly what an indeterminate write can leave behind * fix(layout): finish the main merge with this branch's versions of the layout-owner files * test(build): copy the layout-owner build guard into the compiler-cache checkout fixture * fix: carry this branch's build-guard changes onto main's versions of three build files |
||
|
|
82a2414c53 |
ci: allow the shared MobileNativeChatView test harness to register module mocks (#29378)
#29368 moved these hoisted mocks from the test file into a shared fixture, which the anti-slop no-module-mocking rule only exempts for *.test files. Scope the same file-level exemption the RPC test fixture already uses. |
||
|
|
e554ef2a78 |
ci: cancel obsolete PR checks even when new checks are skipped (#29364)
* ci: cancel superseded PR checks even when replacement checks are filtered out * test(ci): verify cleanup keys against every automatic PR workflow |
||
|
|
a49295f024 |
fix(sidebar): Hide sleeping keeps a live workspace row through a transient PTY gap (#29325)
A pane that rebinds its PTY clears the tab's live binding one commit before re-registering it. Under Hide sleeping an open-but-idle remote workspace hung on that binding alone, so its row was swept out and back for one frame. The sweep now treats a still-open tab with no binding as unverifiable and keeps a row that was live for a short settle window; a deliberate sleep or a closed last tab still sweeps immediately. Fixes #15996 Co-authored-by: mmarabel <166927047+mmarabel@users.noreply.github.com> |
||
|
|
85121dd4d0 |
fix(ssh): no probe stall on the first remote action after a pause (#29240)
* fix(ssh): skip the managed-server probe while the control socket is answering A remote call after more than 5 s idle first ran a status.get probe on a new one-shot socket (SSH channel, WebSocket upgrade, hello, auth, request). A ready shared control socket that heard from the server in the last 20 s already proves it serves; a kill, reboot, rebind or stop closes that socket, so the probe still runs then. * fix(ssh): read control-socket answers through a leaf module orcad-managed-tunnel imported the request-connection cache, which (through the status owner) imports the serving gate back. Tests that mock that cache with an async factory deadlocked importing it. A leaf module now carries the answer source between them. |
||
|
|
330fd55376 |
test(mobile): split MobileNativeChatView.test.ts under the max-lines limit (#29368)
Pure move: the 36 test cases and their assertions are unchanged, now in six feature files. Shared mocks and render helpers live in MobileNativeChatView.harness.test-fixture.ts. The only non-move edits are typing and formatting: the harness adds getComposerEditGeneration to its default props (a required prop the fixture never passed), tests use hostType(node) for tag comparisons, and the typecheck baseline and reliability gate paths drop the removed file. |
||
|
|
bd56d8d096 |
perf(dev): skip unchanged process-host package rebuilds (#29317)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
fe08eb9a23 |
fix(agent-status): stop nested reviews from collapsing Claude children (#29264)
* fix(agent-status): preserve parent status through nested review hooks * fix(agent-status): preserve relay handoffs and verify session consumers * fix(agent-status): scope nested provider guards to terminal owner |
||
|
|
7306273d89 |
fix(ssh): switching back to a quiet remote terminal no longer refetches its snapshot (#29253)
* fix(ssh): switching back to a quiet remote terminal no longer refetches its snapshot Co-Authored-By: Claude <noreply@anthropic.com> * test(cross-version-wire): drop notice negotiates only between current peers Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
82029e6908 |
ci: stop warming unused Windows package archives (#29322)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
118cbd0481 |
feat(layout): move panes and save divider sizes through main behind ORCA_LAYOUT_OWNER (#29192)
* feat(layout): add the dark layout.apply channel and route pane splits through main behind ORCA_LAYOUT_OWNER A build made with ORCA_LAYOUT_OWNER=main registers layout.apply: main applies the window's layout command to the stored partition through the shared applyLayoutCommand, minting new ids. A user split then waits for main's answer and mounts the pane id main minted. Every other build substitutes 'window', so neither branch is compiled in. * fix(layout): write only the records a layout.apply command touched A load-then-save rewrite also normalizes records the command never touched. The command's effect is now the diff between the save before and after it, written onto the stored partition record by record. A split whose main reply says a paired server holds the tab splits as today. * fix(layout): write a load-supplied record whole and check that patched partitions reload to the command's result * feat(layout): close, rename and equalize panes through main behind ORCA_LAYOUT_OWNER In a layout-owner build the window's pane close, title change and equalize go through layout.apply and the window shows main's answer. A window pane close keeps the legacy close's rules: the tab's last pane is refused, a pane restarted since main read the close is left alone, every partition holding the tab closes it, and the tab's remote session id follows the remaining pane. The rules sit behind a command field only layout.apply sets. * fix(layout): close the tab when a racing pane close leaves the window one pane * fix(layout): leave an unmounted tab alone when main refuses its last pane * feat(layout): move panes and save divider ratios through main behind ORCA_LAYOUT_OWNER Claude-Session: 10569c9a-a0a1-4fc9-8469-0edfb7aed125 * test(layout): a taken pane drop whose pane closed does nothing Claude-Session: 10569c9a-a0a1-4fc9-8469-0edfb7aed125 * test(layout): pin the window's pane move to main's saved tree, and the drops main cannot take Claude-Session: 10569c9a-a0a1-4fc9-8469-0edfb7aed125 * fix(layout): close a user's pane even if its terminal restarted, as today Claude-Session: 10569c9a-a0a1-4fc9-8469-0edfb7aed125 * test(layout): pin the restarted-pane close directly, not through a made-up profile state Claude-Session: 10569c9a-a0a1-4fc9-8469-0edfb7aed125 * fix(layout): leave a split to today's path only when the workspace's row names a paired server The split switch point asked which host to route to with a helper that falls back to the focused server, so a focused server could claim a workspace whose row names no owner. Use the same owner test the tab mirror uses. * test(layout): type the split owner mock without a cast * test(layout): type the layout-owner command mocks with the real signature * test(layout): type the gesture command mock with the real signature * fix(layout): finish the main merge with this branch's versions of the layout-owner files * chore: keep main's exact bytes for files this branch does not change |
||
|
|
7a78dbd3c7 |
Native chat: one settlement transaction for everything an ended run left (4/5, rebuild of #26867) (#28111)
* feat(native-chat): record which agent run wrote each journal item Each journal item row, subagent roster entry and background-task entry now records ownerFence: the lease fence of the agent run whose output produced it. Optional, persisted, no row version bump and no migration. The journal's itemFence() returns it, so the turn-verdict rules and per-run provider activity read the producing run rather than the writer's fence. * feat(native-chat): one current-work projection for every host reader; record death first The host decides what work is current in one place (structured-agent-session-current-work.ts) from the lease, the exit this host saw, the runtimes it replaced, its live child and each item's provenance. Every host reader (queue, Stop, prompt answers, commands, status feed, idle sweep, teardown snapshot, history pages and frames, orchestration mailbox) reads it, so a dead agent's leftovers stop reading Working or holding the queue even when their cleanup write failed. The journal's activeTurnId()/liveTurnScope() become the raw runningTurn(). On exit the host records the child's end first and signals generationEnded, which republishes frames, the status feed and settlement waits and wakes the queue drain with no journal row. Pages and frames carry optional working and actionablePromptIds fields. * feat(native-chat): clients read the host's working answer; refuse answers to a stopped agent plainly Desktop and mobile prefer the host's working and actionablePromptIds fields when present (merged across batches like latestTurn) and fall back to today's row derivation against an older host. A prompt an ended agent raised stops looking active; answering it is refused before any provider sees it, with "<Agent> has stopped, so your answer was not sent. Send a message to continue." Cancelling it only dismisses it in the journal: it no longer triggers the chat's Stop, pauses the queue or withdraws queued cards. * feat(native-chat): one settlement transaction for everything an ended run left An exit now settles, in one lifecycle batch planned at its own turn in the write queue, everything its run left (turn, calls, prompts, reasoning, unanswered sends) plus leftovers of earlier ended runs, and only the subagent roster entries and background tasks those runs observed, by each entry's own provenance. Main's stale settle moves to stale-state-settlement.ts with fence scoping; dead-generation-settlement.ts becomes a planner; leftover-settlement.ts combines them. Resume eligibility widens in one case: this host saw the root exit at the lease's fence and the release write failed; the acquisition replaces the owner only once a probe proves it gone. * refactor(native-chat): keep structuredAgentSessionHandsOver file-local until a caller needs it Nothing outside the projection calls it in this part; Part 5 exports it for the start-failure row. * test(native-chat): fewer provenance tests: fold reopen and unstated-owner checks into the main case Drops the epoch-replacement case (Part 2 rewind test reads the same values through the same rebuild) and the corrupt-value case (no version writes one). * test(native-chat): drop current-work mirrors: the viewKey unit case and the still-live rewind case The flow cases keep every outcome: dead leftovers read as nothing, Stop has nothing to stop, a waiting card drains, a live owner publishes as before, and a rewind never promotes dead work. * test(native-chat): fewer client tests: one flow per client, one fallback each Keeps desktop and phone Working from the host (with the older-host fallback), the reducer merge contract, the ended question Cancel that only dismisses, the agent-named refusal and the resolution receipt. Drops per-helper prompt tests, the transcript-placement test, the stop-note client reduction, the Steer cards that match main, and per-reason refusal rows. * test(native-chat): fewer settlement tests: keep the exit-delivery flows and the per-entry scoping flow Drops the no-added-delay timing check, the frame-once check, two stamping unit cases and the Codex combined case (the roster flow test covers its outcome). * test(native-chat): drop the resume-eligibility predicate mirror; move the unstamped-entry case to Part 1 * test(native-chat): an unstamped roster entry from an older build reads as its row provenance Moved here from Part 4 so it sits beside stampJournalEntryProvenance. * test(native-chat): build the older-build roster row inline, after main removed its body helper Main #27947 writes one row per subagent and deleted journal-subagent-group-body; a roster row from an older build is still what this case reads. * refactor(native-chat): provenance is per item only; drop per-entry stamping Main's #27947 writes one saved row per subagent, and each background task already has its own row, so an item's own ownerFence names the run of every entry a producer still writes. Per-entry stamps inside a row mattered only for the shared roster rows saved before #27947, and no run writes into those any more, so the row's own provenance settles them correctly. Removes the entry stamping, the optional ownerFence on roster entries and background tasks, and their tests. * fix(native-chat): an item's provenance is set when it is created; revisions keep it A newer run's provider can revise an item an older run created: Pi's start and an ACP session/load both report context usage onto the newest saved turn. Restamping that turn with the newer run let the newer run's exit settle the older run's unverifiable turn as interrupted. Only creation states an owner now, as main's itemFences rule did. * test(native-chat): keep the provenance test below the production lines it covers * fix(native-chat): an ended agent's card Cancel commits with its receipt, through dismissPrompt The ended-generation dismissal wrote the cancelled resolution without the Cancel's operation receipt and without the dismissal's failure handling, so a receipt write failing after it would answer "outcome unknown" over a card already closed. It now goes through dismissPrompt, which carries the uncommitted receipt in the same append and answers dismissalNotSaved on failure; a null `answer` skips the adapter, since no live provider holds an ended generation's card (Pi's adapter refuses a fence with no live session outright). * Native chat: a resumed subagent or Claude background task belongs to the run executing it A subagent row that run 1 created and run 2 resumed kept run 1's creation fence, so settling run 1's death marked run 2's live subagent unverifiable. Claude background tasks reuse their rows the same way (a matching parent tool use, or a parentless row). Rows of reusable child execution now also name their execution owner: the fence of the child process whose report the write copies, captured when that report arrives, never the lease that is current when a queued write flushes. - Subagent rows: the host captures the live child's fence when its child-work report changes the records, and rewrites a running subagent another child now reports even when its text is unchanged. - Claude background-task rows: written through that child's own event sink, which stamps its bound fence. - Creation provenance (`ownerFence`) is unchanged. Writes that do not state an owner (settlement, Pi's start usage, ACP session/load replay, ACP tasks) keep it, and a row without one falls back to its creation fence. `journal.itemFence()` now answers whose execution an item is (`executionOwner ?? ownerFence`), so every settlement and liveness read, inside its write transaction, follows the run that resumed the work. Also drops the event sink's compatibility alias for the identity resolver (the Codex sink names the resolver itself), keeping the sink under its line limit. * Native chat: a subagent row is written through the child whose report it copies Review of |
||
|
|
a54236751e |
fix(serve): start Linux headless serve on X11 so an inherited Wayland session can't abort it (#29260)
* fix(serve): pin headless Linux serve to X11 so an inherited Wayland session can't abort startup Fixes #25400 * fix(serve): put --ozone-platform=x11 on the launch argv for Linux headless serve Chromium caches its Ozone platform in PreSandboxStartup, before main JS runs, so app.commandLine changes cannot move it off Wayland. Pin X11 on the CLI and orcad serve spawns, and re-exec in-process serve (same pid) when Electron already resolved Wayland. |
||
|
|
2e510c0cb2 |
perf(remote): send one changed tab instead of the whole worktree on session tab streams (#29319)
Fixes #22151 |
||
|
|
6578f0b3a9 |
test(git): move worktree cases out of the Git binary compatibility test (#29357)
Pure move to bring the file under the max-lines limit; same cases in the same order. |
||
|
|
7538fa9466 |
feat(mobile): the phone's Workspace options sheet, with every desktop option (#28997)
* fix(mobile): phone server rows follow the desktop's other-client and sleeping filters A phone created through a desktop now records whom it acted for, so the desktop's Hide other-client workspaces filter keeps the user's own phone workspaces (locally and on servers) and hides only other people's. The desktop relay marks each server row its sidebar would hide, and the rows its own browser or chat tabs keep awake; the phone applies both. * test(e2e): dedupe sidebar row ids in the visibility spec * fix(mobile): address review: owner naming, old-server relayed phones, scope trim * refactor: move the sidebar's project section grouping into shared The project sections the desktop sidebar draws under Group by Project are built from the project/setup projection, the per-host catalog fold, the endpoint host stamp, and the section labelling and ordering rules. Move the pure parts of each into src/shared (no behaviour change) so the paired phone can call the same code instead of guessing the grouping. * fix(mobile): group by Project with the desktop sidebar's own sections The phone grouped Project sections by repo display name, so it merged checkouts the desktop keeps apart (several local stablyai/orca checkouts, or a server's copy) and split what the desktop merges. The phone now reads each host's repo.list, project.list and projectHostSetup.list (the desktop's own and each server's through the relay), folds them with the renderer's shared catalog fold and projection merge, and builds sections with the desktop's shared grouping, labelling and ordering code. Keys, labels and Recent order equal the sidebar's; a host that predates the project lists gets the repo-derived projection, as the desktop does. Header colour and icon come from the section's anchor repo and rows from their own repo by id, as on the desktop. The repo filter lists every catalog repo by id per host instead of merging same-named repos. Group-by labels read Project and None. project.list and projectHostSetup.list are routed for paired phones (read-only, workspace permission). * refactor(mobile): record a phone's owner as creator and fold desktop tab activity into the host flag A phone now records its owner as the creator (this host for a directly paired phone, the relaying desktop for a delegated one), so the shared rule is unchanged and onBehalfOf is gone. The relay ORs the desktop's saved browser/chat tabs into hasHostSidebarActivity, so the phone's status dot follows too, and local worktree.ps counts the same signals. The old-server fallback is removed. * test(e2e): poll the phone and the sidebar together in the visibility spec * fix(mobile): one Project-section builder for desktop and phone, with the desktop's repo order Review fixes. The sidebar's buildOrderedGroups now calls the shared buildProjectSections for Group by Project (notice and pending repos are optional inputs), so desktop and phone run one function. The phone ranks manual header order by its folded catalog order, which is each host's repo.list order with the desktop's own repos first, as the renderer loads them; only the desktop's cross-host manualRepoOrder (pairing-local) is unknown to it. The projection selector is now a memo over the shared resolver. A transient project-list failure keeps that host's last catalog; only forbidden or method_not_found falls back to the repo-derived projection. Catalog rows are checked on every member grouping reads, and the parity test answers the renderer's real catalog fetch, includes a server's own project rows, and fixes Manual and Recent orders that differ. * fix(mobile): use the repo-derived catalog until a host's project lists first answer * fix(mobile): the desktop serves its sidebar's Project catalog instead of the phone fetching it The phone fetched repo.list, project.list and projectHostSetup.list from the desktop and every relay-ready server each minute and folded them itself, so rows from offline or older servers fell back to repo sections and keys moved on cold start. The desktop renderer now publishes the inputs its own Project headers use (state.repos in sidebar order, the projection selector's projects and setups, projectOrderBy) on the runtime window graph it already sends to main, only when they change. Main keeps the last one and answers it on a new paired-desktop read, mobileRelay.projectSections. The phone reads it with its repo metadata and groups with the shared builder; a desktop that predates the read (forbidden or method_not_found) leaves the phone grouping rows by repo from the desktop's repo.list, and a transient failure keeps the last catalog. The payload carries only grouping and label fields, no hooks, credentials or uploaded icons. The phone's own catalog fetching and its project.list/projectHostSetup.list routes are removed. * fix(mobile): keep uploaded repo icons on the phone, and isolate the snapshot tests * test(e2e): the desktop window serves its sidebar's Project catalog to the phone * chore(i18n): regenerate the runtime English catalog (drift already on main) * fix(mobile): read the Project catalog as its own request, outside the recorded repo-metadata flow The extra read inside the repo-metadata refresh stalled its recorded RPC sequence. It now runs beside it with its own throttle. The repo-metadata goldens are re-recorded for the intended state change: the name-keyed colour, icon and id maps became desktopRepos. * refactor(sidebar): one shared Workspace options filter and sort evaluator The sidebar, the jump palette and the options badge each applied the Workspace options filters with their own copy of the rules. They now call one pure evaluator in src/shared/workspace-view, which reads each row through a small fact reader so the phone can call it next with the facts its host serves. The sort comparator moves there too, with each surface supplying its own Agent activity rank. No behaviour change: a parity test runs the old sidebar chain and the new evaluator over every toggle combination, and the old comparator against the new one for each sort mode. * wip: workspace view descriptors * refactor(sidebar): address review of the shared Workspace options evaluator One predicate builder instead of a per-row scope argument; one exemption-narrowing function taking the hide flag; consumers import the shared predicates directly; Agent activity ties fall to the label in the shared comparator. The activation filter lift reuses the shared predicates. The parity test now covers other-client rows, live agent attention classes and the sort-label map. * fix(mobile): fetch the Project catalog at once when the screen moves to another host The refresh window is now kept per client, so a host screen reused for another desktop doesn't wait out the previous host's 60s window before showing its Project headers. * wip: desktop option items from shared choices * refactor(sidebar): the Workspace options menu renders from one shared option list src/shared/workspace-view/workspace-view-options.ts lists every Workspace options control (Hosts, Projects, Group by, Sort by, Project order, Card layout, Show properties or Card display, and each filter) with its section, its English copy, its choices and when it shows. The desktop menu walks that list and renders each option through a table keyed on the option key, so a new option fails to compile until the desktop has a control for it; the phone sheet will do the same. The choice lists (sort modes, project order, card layout, agent activity layout, card properties) are derived from the shared ids, and a test checks the desktop's English copy matches the shared copy. The unused classic branch of the card property list is removed. No visible change. * wip: row facts * refactor(sidebar): address review of the shared Workspace options list The show rules get their own tests with fixed expectations (the cases the old filter-section test covered, plus the rest), and the menu test checks each option's own control rather than any matching text. Card display rows toggle one property each, with the folder-path copy in shared. The unused Status and Tasks copy left by the removed classic card list is deleted from the catalogs. Filter rows write through the store directly; files are named for what they hold. * feat(runtime): worktree.ps carries the Workspace options row facts Each worktree.ps row now says whether it is the project's default-branch workspace, created by an automation, created by the CLI, or on a detached HEAD, answered by the same shared predicates the desktop sidebar filters with. The phone has none of these facts today, so its copies of the filters either guess (default branch) or are missing. Additive and inert: optional fields that nothing reads yet. An older host omits them; readers must treat absence as 'not that kind', so the row stays visible. Server rows relayed through the desktop pass them through unchanged. * feat(mobile): the desktop's own phone reads and writes its other-client filter ui.get and ui.set strip the pairing-local UI fields for every paired client. That rule exists for clients with their own host catalog (a desktop paired to a server, a web client). A phone has none: it shows its desktop's view, so 'Hide other-client workspaces' must be one shared value. For the host's own phone (clientKind mobile, no relaying parent) ui.get now always answers the field and ui.set persists it; delegated phones, paired desktops and web clients keep the stripping rule. The phone's view-settings schema reads the rest of the Workspace options values it does not read yet (the automation, CLI and detached-HEAD filters, project order, card properties, agent activity layout), each salvaged to absent so an older desktop keeps the phone's local value. * feat(runtime): address review of the worktree.ps row facts Name the fact defaultBranch, and say what absence means for it: a reader keeps its own guess, because 'hide default branch' must not start hiding or showing rows an older host never described. Folder workspace rows get the facts too, so every row from a newer host carries them. The desktopOtherClient comment now says it is a verdict, not a fact. The test covers the rows where the host disagrees with the phone's current guess. * wip: phone uses the shared evaluator * feat(mobile): address review of the phone's other-client filter mirror One isHostOwnPhone predicate decides both who shares the filter value (ui.get/ui.set) and who gets the other-client row marks, so the two cannot drift. The pairing-local field list notes the exception. Tests cover a paired desktop still being stripped, and a phone write that leaves the field out not touching the host value. * feat(mobile): the phone filters and sorts with the desktop's shared Workspace options rules The phone's own filter chain and comparator are replaced by the shared evaluator, reading the facts the host stamps on each row. Phone filter state takes the desktop's setting names and carries every filter; the badge and Clear filters match the desktop's. The desktop's other-client marks become facts the phone filters with the shared value. A parity test runs the same workspaces through the desktop's reading and the phone's (facts stamped as the host stamps them) over every filter combination, folder projects included. * wip: phone view state carries project order and card props * fix(mobile): host scope in shared filters, patch-key writes, live view push Folds the phone's host filter into the shared filters so Clear and the badge agree, writes back only the touched filter keys, and pushes workspaceViewChanged so an open phone list re-reads desktop Workspace options. * fix(mobile): Clear sends only changed filters; skip a view re-read older than a local edit An older host's strict ui.set refuses a key it lacks, so Clear names only what differs. A ui.get that started before a local edit no longer overwrites it; the edit's own change event re-reads. The change publisher's field list now lives with it and derives the filter fields. * feat(mobile): the phone's Workspace options sheet, rendered from the desktop's shared option list The Filter drawer becomes the desktop's Workspace options: hosts, projects with search, group, sort, project order, card layout and properties, card display, and every filter. Each option renders through a table keyed on the shared option keys, so a new desktop option fails to compile until the phone has a control. Sort and group pickers use the desktop's words; Repo reads Project. * fix(mobile): Workspace options sheet review fixes Hosts read as on the desktop (none checked while all show; the last shown host is disabled). Project order falls back to the served value until the shared one is read. Card layout and card style changes now push to an open phone. Pick-one rows read as radio buttons. Simpler wiring: flat card state, the preset flag rides the patch, shared choices used directly. * fix(mobile): reset project order on host switch; simpler preset-flag handling * fix(workspace-options): all hosts and clear reach the desktop; one filter key list drives every surface Host visibility: the legacy host scope fallback moves to shared code; the phone reads it, and the host resets the scope whenever a client writes the host list, so All hosts and Clear stick. An older desktop that keeps the other-client filter to itself has its marks treated as hide. Badge counts, is-anything-filtered, Clear and reveal derive from the shared filter keys on the desktop sidebar and the kanban filter menu. The phone uses the desktop's group and sort values, holds its view in one state value, and reads its UI fields from one shared list. * feat(workspace-options): Status and PR grouping read the shared tables The phone groups by status with the desktop's status helpers and default catalog (its own copy had the defaults in reverse order) and by PR with a shared lane table, so its labels now read In review / In progress as the desktop's do. The desktop's PR lane decision ends in the same shared state-to-lane step. * feat(mobile): phone rows follow Card layout, Show properties, Card display and agent activity One shared helper (getWorktreeCardDetails) decides which card details show for the chosen properties and layout; the desktop card's flags and the phone row both read it. The phone row hides the PR badge, note/issue/Linear glyphs, host badge and agent rows the desktop turns off, and the Full list agent layout shows every agent row. * test(sidebar): folder rows survive restrictive filters; create grace ignores non-finite times * fix(mobile): write the host scope with the host list, and wait for the first read before forcing the other-client filter An older desktop narrows back to its legacy single-host scope when the phone writes only a null host list, so the phone now also writes the scope for a null or one-host list. The other-client fallback waits for the first ui.get so a new desktop's marks don't hide rows before its filter value arrives. Inline the clear-filters key list and note the PR state asymmetry. * test(mobile): re-record view-settings goldens for the unknown other-client state * fix(mobile): let a tall bottom drawer scroll on the page The drag wrapper around the drawer's ScrollView had no flex limit, so it grew to its content and the sheet clipped it instead of scrolling. The full Workspace options sheet is the first drawer tall enough to hit this. * fix(sidebar): reuse the palette's default host instead of reading the focus setting again * fix(sidebar): read the host options once in Workspace options and pass them to the Hosts item * fix: parse the ui.get reply into a named type, fix the row memo test's filters, prune the focus-read baseline * test(mobile): give the project catalog fixture its project order * feat(mobile): name the options chip Workspace options, as the desktop does The chip keeps the active-filter count and reads to screen readers with the desktop trigger's label. The pluralized filter count moves to shared code so both surfaces word it the same way. * fix(mobile): show the Workspace options count as a corner badge so the chip row fits "Workspace options (2)" squeezed the Sort and Group chips to ellipses at phone width. The count moves to a corner badge, as on the desktop trigger, and the chip drops its icon, which the desktop trigger does not show either. * refactor(sidebar): one switch-to-kind table, and fold the leftover helper files back - The four kind switches come from WORKSPACE_KIND_SWITCH in workspace-kinds; the shared evaluator and main's phone-push check both apply it, and the filter type derives its switch fields from it. - git-identity.ts folds back into git-identity-display.ts, as on main. - SidebarFilterState moves into sidebar-filter-actions.ts; visible-worktree-kinds.ts is gone. - buildWorkspaceRowPredicate is module-private. * feat(mobile): Workspace options sheet in the desktop menu's shape The sheet showed every choice of every option, so the filters sat screens down. It now follows the desktop menu: Hosts and Projects rows with their value, Group by as a segmented control, Sort by, Project order, Card layout and Show properties as rows that open a page of choices, and the filters as switches. Each option's control (an inline row, or a value plus a page) still comes from one table keyed by the shared option list. The segmented control is the voice settings one, extracted so both screens share it. * fix(mobile): Workspace options review fixes - A page whose option stops showing is forgotten, so it cannot reopen by itself. - Only the switch takes the tap on a filter row, so the web page writes once. - Sections split their rows in one pass; unused heading styles go. * fix(mobile): neutral filter switches on the page react-native-web paints an on-switch thumb teal unless given activeThumbColor, which React Native's types omit. MobileSwitch applies the app's switch colors, and its web sibling also sets that prop. * refactor(mobile): one MobileSwitch file, adding the web-only thumb color on web * fix(mobile): Show properties reads Hover under Compact, as the desktop does The row's value now comes from getWorkspaceCardPropertiesValue in the shared options, which the desktop trigger uses too: Hover under the compact layout, otherwise how many properties show. Card display shows no value, as on the desktop. * test(mobile): find the renamed Workspace options chip in the page drawer render check * feat(mobile): drop the Sort and Group chips; the Workspace options chip covers both The desktop has only its options button, and the sheet now holds Sort by and Group by. The chips' pickers, their screen state and the sort label go with them. * feat(mobile): option pages slide in from the right and keep the sheet's height The main sheet stays laid out under an open page, so the drawer keeps its height going in and out. The page slides in over 200 ms and back out on back (the row, or Android's back key), instantly under reduced motion. The reduced-motion hook moves to platform/ now that two screens use it. * fix(mobile): option pages fill the sheet and open at its top - The page layer grows to the pager's height, so no part of the main sheet shows below a short page. - The drawer takes a scrollResetKey; the sheet passes the open page, so a page opened from a row low on a scrolled sheet starts at the top. - The main sheet's height is measured under a page too, and the pager state lives in the sheet so it resets when the drawer closes. - A misplaced doc comment goes back to its function. * fix(mobile): phone rows show the Jira, automation and CLI glyphs; the options pager forgets a gone page in an effect * fix(mobile): Jira glyph sits before Linear as on the desktop; Jira reader tests beside it * fix(mobile): the phone leaves Ports out of Show properties and Card display * refactor(mobile): clearer names and tests for the phone's hidden card properties * refactor(mobile): one view state and one settings read for the phone's Workspace options; tighter card glyph wiring - The phone's Card layout and card style now live in its view state; one parallel settings.get reads them with pinned placement beside ui.get. - The Card layout preset flag is a write option, no longer a view field or a change-event field. - getWorktreeCardDetails reads the raw desktop settings and resolves the layout once; the desktop card computes it once in its foundation. - The row computes its glyph presence in one place; Ports is hidden through one set. - Drops the vanished-page effect, the native-only a11y props and the web-only switch branch. * fix(mobile): the list settings read applies each half on its own, with tests; pinned placement changes announce themselves * fix(mobile): Card layout writes the setting before its preset; Card display names folder paths when the desktop has folder workspaces |