* Hide projects from the sidebar without stopping them
Adds Repo.hiddenAt, a per-host, view-only flag. A hidden project's
workspaces, empty header and project-filter entry leave the desktop
sidebar, the paired phone's list, the new-workspace picker and the
palette's project filter. Its terminals, agents and automations keep
running, and repo.list / worktree.ps still list it.
- Hide Project in the project menu (toast with Undo), a collapsed
"N hidden projects" list under the workspace list with Show buttons,
and a Hide from sidebar switch in Settings > Projects.
- repo.setHidden RPC ({repo, repoHostId?, hidden} -> {repo, hostId,
hidden}) and `orca repo hide|unhide [--host]`; `repo list` marks
hidden rows.
- Opening a hidden project's workspace (notification, CLI, deep link)
focuses it without unhiding it, lifting sidebar filters, or leaving a
pending sidebar reveal.
- repo.update echo check: a host that drops hiddenAt reports failure
instead of reading as hidden.
* Address hidden-projects review: multi-host hide, picker scope, mute, stale filters, shared predicate, restore list styling
* Hidden projects re-review: keep saved filters, Agents filter, composer seed, per-toast Undo, shared default host
* Hidden projects: address review threads (pre-feed, palette search, notices, dialog default, seed remap, row keys, a11y)
* Hidden projects: no implicit dialog default when every project is hidden
* fix(sidebar): keep the session name first on a monitoring agent row
Leading with "Monitoring background tasks" made every monitoring row in a
narrow sidebar truncate to the same text. The row's dot already draws the
monitoring glyph, so the status can trail the name like every other state.
* fix(agents): keep a monitoring child row's name first too
Sub-agent rows (desktop sidebar, chat strip and mobile) share one lead/trail
rule that also put "Monitoring background tasks" before the name.
* feat(mobile): show only the open tab, with a tab count and a sheet of every tab
The session bar shows the open tab at full width, then a tab count cell and a + cell. The count opens a sheet of every tab grouped Needs you / Working / Everything else; tapping the tab opens its actions; swiping it steps between tabs; + opens a new tab sheet with agents as tiles. The header subtitle shows the branch. Brings back #40592 on current main.
* fix(mobile): don't switch tabs when a bar swipe is interrupted
* build(mobile): upgrade to Expo SDK 58 and React Native 0.88
Expo 58 drops Zod from @expo/cli, which clears the last Zod 3 advisory
(GHSA-mrhx-c7xc-m3w5) in mobile along with its local patch and override.
- Expo 55 -> 58, React Native 0.83 -> 0.88, React 19.3, gesture-handler 3,
webview 14, reanimated 4.7, worklets 0.13 (SDK 58 bundled versions,
pinned below today's batch to respect minimumReleaseAge).
- Port the react-native and react-native-webview patches unchanged; drop
expo-constants, expo-notifications, @expo/cli, expo-router, zod and
query-string patches plus the zod/query-string/xcode>uuid overrides,
which upstream fixed or no longer need.
- iOS minimum rises to 16.4 (Expo 58 / RN 0.88 requirement).
- Migrate to RN 0.88 strict types: instance ref types, NamedStyles,
AppState.currentState, list header/footer nulls.
- Replace removed runtime APIs: InteractionManager -> idle callback with a
macrotask fallback; StyleSheet.absoluteFillObject -> absoluteFill;
FileHandle.readBytes -> readBytesSync (it became async).
- Resolve react-native/asset-registry for shared assets in Metro and alias
the old registry path for react-native-svg in the desktop mobile-web bundle.
- Reduce the iOS scene plugin to the reconnect override; Expo 58's template
now ships the scene delegate itself.
* fix(mobile): bridge react-native-svg web imports and libsodium runtime for RN 0.88
- Share react-native-svg web shims between the mobile-web build and its render
checks: map the old asset-registry path to react-native-web's registry and stub
the Android-only touch-sound TurboModule.
- Patch react-native-libsodium 1.7.0 to read the JSI runtime from the bridge proxy;
RN 0.88 removed RCTCxxBridge.runtime.
* fix(mobile): use Expo 58's legacy promise resolver for audio permissions
* fix(mobile): skip null handles in the RPC recording timer shims for RN 0.88 types
* style(mobile): format MobilePRSidebar after rebase
* fix(mobile): name RN 0.88 text input refs for declarations; allow queued back in stack render check
- Type text input refs with an exported interface so declaration emit can name hook results
(RN 0.88 aliases TextInputInstance to an unexported class).
- Expo Router 58 drains back() after a commit; check the interrupted push's exit from the
frame it starts, bounded to three frames of lag.
* chore(mobile): justify the text input handle interface for React Doctor
* chore(mobile): use a nameable intersection alias for text input refs
* fix(mobile): use sync expo-file-system writes, copies and moves on Expo 58
Expo 58 made File.write/copy/move and FileHandle.writeBytes return promises.
Our callers never awaited them, so failures escaped their try/catch and the
store's tmp-then-move and PDF writes could race their close or rename.
* build(mobile): raise the page bundle budget to 10 MiB for Expo 58
Expo 58 adds about 310 KB to the page: expo-router (+258 KB, now carrying
React Navigation, net about +110 KB) and Reanimated 4.7 (+152 KB). Main had
85 KB of headroom left. 10 MiB still stays within the 10 MiB per-asset contract.
* fix(mobile): drop the window-metrics seed RN 0.88 removed from Android
RN 0.88 no longer holds window metrics: DeviceInfoModule reads the activity's
WindowMetrics on demand and setWindowDisplayMetrics is gone, so MainActivity
no longer compiled. Layout scale still comes from the screen metrics we reseed.
---------
Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com>
Reverts #40592 (12e809c755). The session bar goes back to the scrolling strip of tab cells, the + menu goes back to the action sheet, and the header subtitle shows the tab count again.
* feat(mobile): show the open tab as one pill with a tabs sheet
The phone copied desktop's tab strip, which fits about three tabs cut to
~95 pt and hides a tab that needs you behind an edge dot. The bar now shows
only the tab you're in, at full width, with the tab count. Tapping it opens
a sheet of every tab grouped by what needs you, with each tab's state and
last activity; swiping it steps to the next tab. The + sheet shows agents as
a grid above Terminal, Browser and Markdown note, and the header names the
branch instead of the tab count.
* feat(mobile): pair the tab count with + and open tab actions from the pill
The count and its chevron inside the pill read like a menu and hid the
"another tab needs you" dot. The count now shares a capsule with +, the
way phone browsers put the tab-count button beside new tab, and tapping
the pill opens the tab's own actions.
* feat(mobile): give the tab count its own button beside +
The shared capsule made each half a small target. The count is now a
round nav button like +, lined up under the header's buttons.
* feat(mobile): draw the tab bar as the strip's square cells
The rounded pill and round buttons read as a different control from the
strip people know. The open tab is now the strip's raised, underlined cell
from the screen edge, with the count and + as square cells in the same
row, which also gives them 46x44 pt targets.
* fix(mobile): keep a hairline after the tab bar's last cell in the top bar
* perf(mobile): open Home with last-known workspaces and counts
* fix(mobile): keep disconnected desktops on Home and judge agents by the client's connect time
* fix(mobile): store the seeded Home counts before removing the old snapshot
* fix(mobile): floor router reads after failures, catch up reads that span a stream reopen, seed the wide host list from Home
* fix(mobile): keep the old Home snapshot until the store can take it, and never re-date stored totals
* perf(mobile): key Home's counts in the host list module so the page boot never loads Home's code
* test(mobile): type the Home catalog adapter's modules with type imports
* perf(mobile): read Home's stored rows in one batch beside the host list, and keep mark-read a delta read
* perf(mobile): paint Home's desktop rows without waiting for the stored counts
* perf(mobile): restore Home's stored rows after the desktop list paints, from its host ids
* perf(mobile): read Home's counts on the connected edge itself, not a render later
* feat(runtime): tell phones when relay hosts change
* fix(runtime): keep the relay host backstop live and watch every list input
* fix(mobile): hold the relay host feed only for desktops that announce changes
* perf(runtime): watch relay host inputs only while phones read the list
* feat(mobile): show folder workspace Source Control on the phone
A folder workspace now has Source Control on the phone: one row per attached
worktree (repo, name, branch, ahead/behind, change count), read from the host
list's own lineage projection and each worktree's git.status. Tapping a row
opens that worktree's existing Source Control in place; Back returns to the list.
* fix(mobile): folder Source Control routing, back, hidden reads and failure states
- A desktop worktree under a server's folder is listed and opens with desktop routing and gates.
- A child opened in the dock gets Back to the folder list beside Close.
- Rows and the catalog stop reading while the screen is covered, as the single-worktree screen does.
- Offline, failed and missing-folder states; rows whose status can't be read say Unavailable.
- Server rows poll like the host list; branch shown without refs/heads/.
- Perf contract: git.status reads per signal at N and 10N rows.
* perf(mobile): folder Source Control reads summaries and rebuilds only on lineage changes
- Rows read a status summary without per-file line stats; relayed servers' rows open no desktop event stream.
- Membership resolves over a projection of lineage and label fields, so agent and terminal churn rebuilds nothing.
- A row whose re-read failed or whose host reported readError shows Unavailable.
- A connection still coming up shows loading, not offline.
- Perf contracts at N/10N rows and H/10H catalog rows.
* perf(mobile): folder membership keys on lineage only; child status reads update the folder list
Membership resolves again only when a row's lineage fields change, keying
only rows the catalog replaced; labels come from the current rows. A child
Source Control's newer status read is handed to the folder list's summary,
so Back shows what an action did without another read.
* fix(mobile): folder summary takes child reads as they land and ignores server health
Membership depends only on each relayed server's installation, so health
and relay flips no longer resolve the folder again. A child Source
Control hands each status read to the folder summary as it is accepted,
so a summary read answering just after can't hide it, and an older read
never replaces a newer summary failure.
* fix(mobile): folder summary skips restored and cached reads that could undo newer ones
Persisted status is marked restored before anyone hears of it, so a
child screen never hands an earlier launch's status to the folder list.
A cached read caught up on opening writes only an idle summary and never
cancels one in flight. Perf contracts count real lineage serializations,
committed row renders and summary publications.
* fix(mobile): clear the restored mark on any answer but the restore's own
A live answer timed before the stored record, as after a clock
correction, is still this launch's, so its reads and the folder summary
treat it as confirmed.
* fix(mobile): the restore's own write skips clearing its mark only once
A listener replacing restored data as it hears of it writes this
launch's answer, so the mark clears for it too.
* test(mobile): type folder Source Control test fixtures without assertions
* test(mobile): name mocked modules with type-only namespace imports
* feat(mobile): show folder worktrees as cards on the sheet surface
Each attached worktree is its own grouped card on the grey sheet
surface, the look the phone's option sheets use, so rows read apart
from the page.
* fix(mobile): keep folder Source Control's states on the card surface
Loading, empty, error and the list now share the sheet surface, so the
screen no longer changes background between states.
Unread rows show the desktop's bell, swipe right toggles read, swipe
left clears a finished agent, and the long-press and options menus get
Mark read/unread, Unread only, Mark all read and Clear finished. Writes
go through agentActivity.setRead/clear and show optimistically until the
desktop's list confirms them.
* feat(agents): send paired phones the desktop Agents list's verdict per agent
While a phone is paired, the desktop window publishes its own Agents-list
classification for each pane (listed, status, unread, clearable, title,
worker parent) and worktree.ps attaches it to each agent row, so the phone
lists agents exactly as the sidebar does. agentActivity.setRead/clear apply
through the sidebar's own Activity actions and resolve once the new
verdicts are stored.
* feat(mobile): add an Agents tab to Home
One row per agent across every paired desktop, grouped by status, with
a desktop filter, search, group-by, nested workers and a long-press
menu. Feed's per-workspace Agents section becomes a short Needs you
list, and the needs-you badge moves to the Agents tab.
* refactor(mobile): give relay and encryption concrete owners
* refactor(mobile): organize session and review feature owners
* refactor(mobile): organize RPC and host ownership
* test(mobile): point render fixtures at concrete owners
* refactor(mobile): use explicit type-only owner imports
* refactor: import journal queue state from defining owners
* refactor(shared): organize execution and automation owners
* fix: retain type imports used by surviving test cases
* refactor: finish work item owners and refresh validation metadata
* test: infer reconnect status fixture type
* test(claude): resolve source files beside same-named directories
* test(runtime): group repository creation mock registrations
* perf(runtime): push worktree row changes; host list poll becomes a 10 s backstop
* fix(runtime): announce title-only agent status changes and gate the rows capability with the switch
* fix(mobile): keep event reads a floor apart while a read is out; announce a retired title clear
* test(runtime): assert the rows notice without counting events
* feat(mobile): keep screen data on the phone between launches
* feat(mobile): keep the repo list snapshot id across launches
* fix(mobile): don't read a key again that the boot read just found empty
* fix(mobile): late-restored strips, revocation fence and reads never built on stored data
* test(mobile): give the session startup recording the late strip watch
* fix(mobile): remember Workspace options, keep the revocation fence until reauth, store no terminal output
* test(mobile): give the view settings recording its remember hook
* docs(mobile): say what a restored key means to a fetch
* style(mobile): format host-query after rebase onto Q11
* fix(mobile): re-subscribe Home and the follow-up preference after the client event stream ends
* fix(mobile): try a refused client event wire once per connected edge
* refactor(mobile): mark replayed client event readies in the shared stream
* test(e2e): give the phone feed socket client a state listener
* perf(mobile): show the workspace list from memory and refresh it on desktop changes
* fix(mobile): import the host list queries type without an import() annotation
* fix(mobile): keep host labels on a not-connected read and update the phone feed e2e helper
* fix(mobile): keep the event router listening when its stream ends while opening
* fix(mobile): reuse the shared read-view base and remount for the cache-return recording
* perf(mobile): stop a hidden host list refetching on every change
The host list's change-event path fetched worktree.ps (and the server rows read) on every worktreesChanged or reposChanged with no throttle, even while the page was buried under a session or the app was backgrounded. Hidden pages now note what they owe and the foreground refresh catches up once; visible pages read at most once per 3 s.
* perf(mobile): count poll reads in the change throttle and queue the catch-up read
* perf(mobile): leave the poll out of the change throttle and queue the catch-up only after skipped notices
* test(mobile): drop the throttle timing test
* refactor(mobile): one owed flag and one full catch-up read for a hidden host list
* perf(mobile): trim the page bundle back under its old budget
* build(mobile): simplify the route entry anchors and zod table guard
* fix(mobile): import zod as a type in the RPC result reader
Multi-repo folder workspaces can parent workspaces on this machine and on paired servers, and their children nest under them in the sidebar and on the phone. Task parents are inferred at creation instead of on every lineage refresh.
* perf(mobile): share one clientEvents stream per host connection
* perf(mobile): keep the shared clientEvents stream across a same-tick rejoin
* fix(mobile): let a later subscriber retry after the shared clientEvents open throws
* fix(mobile): guard the shared clientEvents cleanup after a throwing open
* test(e2e): give the phone list's socket client the shared clientEvents shape
Inert refactor: move the same-store parent rule and merged resolver into src/shared/worktree/workspace-lineage-graph.ts and add one row identity rule. No behaviour change.
* feat(lineage): store cross-store parent links beside same-store lineage (inert)
A workspace's parent can live in another Orca store. Save that link in the
child's store under a new top-level key, crossStoreLineageByChildKey, so older
builds' same-store cleanup never reads it. Nothing writes records yet.
- Types, load normalization (malformed entries dropped one by one), section label.
- Store get/set/remove by child; a child keeps at most one parent record.
- Every maintenance path acts by the child only: deletion and missing-worktree
pruning, repo removal and deregistered-repo residue, identity migration,
profile project transfer, WSL move projection and UNC drive conversion, and
the orcad migration dormant payload (export, validation, import, subtraction).
* fix(lineage): gate cross-store links on host capability; one parent per child
- Migration stage/commit carrying crossStoreLineage requires the new
orcad.migration-cross-store-lineage.v1 capability; older hosts are refused
before staging instead of silently dropping the links. Empty arrays are omitted.
- Payload validation and destination prepare reject a child that has both a
cross-store and a same-store parent, through one shared conflict check.
- Saved entries stay on disk as written; the map is Record<string, unknown> and
readers go through validCrossStoreLineage. Re-keying moves unreadable entries unchanged.
- Tests: literal expectations; drop touched mock-call and work-count assertions.
* test(lineage): drop clone and save work-count assertions from project group removal test
* feat(lineage): resolve cross-store parents into the sidebar parent map (inert)
- One resolver: a saved record nests its child under the single visible
row whose store reports the parent's installationId and whose instance
matches; copied installs, unknown stores and stale instances stay standalone.
- getSidebarLineageParentsByIdentity merges resolved cross-store parents with
same-store edges before cycle breaking; a valid same-store edge wins.
- Workspace delete collects descendants only from the parent's own store.
- Store identity: paired stores from their verified status hostDescriptor;
this store from the published descriptor, else host-installation.json.
- Nothing passes a view or writes records yet, so the sidebar is unchanged.
* fix(lineage): import WorkspaceKey from workspace-scope after main move
* fix(lineage): resolve sidebar parents once over complete rows; keep unowned rows' delete rule
- resolveSidebarLineageParentIdentities resolves same-store edges and cross-store
records once over every visible store's unfiltered rows, then drops cycles.
Ancestor injection and nesting reuse that map, so a filtered-out twin still
makes a parent ambiguous.
- Removed, retired or refusing paired servers leave the view: their records stay
saved and their children standalone. Offline servers keep their last-known id.
- A row with no owner is unknown, not ours: it never resolves, and delete only
excludes descendants whose store is known and differs from the parent's.
* fix(lineage): refuse UNC rekey collisions and transfers giving a child two parents
The UNC drive conversion rekeys cross-store child keys through the shared
collision merge, so a UNC key and its drive key with different records throw
instead of one silently overwriting the other. Profile project transfer runs the
shared child-key conflict check before writing the target.
* feat(lineage): write, carry and nest cross-machine parents
- Capability worktree.lineage.crossMachine on the child's store; the CLI
refuses before any request when the server lacks it.
- worktree.set / worktree.create accept crossStoreParent
{ installationId, workspaceKey, instanceId } and write only
crossStoreLineageByChildKey (refused when it names this store, or the
child has no identity). Remove Parent clears both.
- worktree.crossStoreParentRef: the parent's own store names it with its
installationId; reparent refuses a parent whose chain already reaches
another store. Same-store Set Parent refuses the same.
- worktree.ps rows and lineage lists carry the records; same-store lineage
fields stay null so older readers show the child standalone.
- The desktop sidebar resolves parents over its own and paired stores'
records (PR 2's resolver) at the visible-worktree and row-plan call sites.
- CLI: active/current or an inferred terminal parent against a server is
sent as a cross-store parent.
* fix(lineage): read worktree rows through the record selector; mark the test runtime cast
* fix(lineage): hydrate every store, fence refreshes, honest CLI fallback
- Each host's catalog hydration fetches its lineage snapshot, so this
desktop's identity and records load whichever store is focused.
- Cross-store records join the per-child request-start fence: a stale
lineage list can't restore a removed record or override a newer one.
- A failed inferred cross-store parent sends noParent instead of
forwarding the selector a server could match to a same-store twin.
- Inferred cross-store creates record env-workspace/inferred capture.
- The writer states its trust contract; the chain rule runs at the mint.
* feat(lineage): cross-machine parents on the phone, pickers, chat resume and labels
- Phone: the list nests a child under a parent on another machine, from the
records rows already carry and the store identities its host verified
(status.get descriptor; relayed servers' installationId on the host list).
- Set Parent popover, context menu and the composer's parent picker offer
parents in other visible stores. The parent's own store names it
(worktree.crossStoreParentRef); the window checks it against that store's
verified installationId and the child store's capability before any write.
Remove Parent and Open parent cover cross-machine links.
- Native chat resume ancestors follow resolved cross-machine parents.
- Host sections keep a nested child under its parent and keep its own
machine label.
- Main sidebar feed resolves cross-store parents (rows carry records; desktop
facts and paired-host facts carry identities); paired web windows read
their host's installationId; reveal without an occurrence plan resolves
them; `worktree create --agent` names a parent on another machine.
* test(lineage): type the mint test's parent row through unknown
* test(lineage): give the cross-machine tests' partial-row casts their SAFETY reasons
* fix(cli): worktree set names a parent on another machine
* feat(lineage): name the machine of parent candidates on another machine
* fix(lineage): Set Parent and Remove Parent act on the clicked row's own host
* fix(lineage): phone resolves parents over every row before the repo filter
* fix(lineage): chat resume nests by host-qualified identity across machines
* fix(lineage): local create refuses a same-install parent before checkout and shares the RPC recorder
* fix(lineage): name parent machines without a focus read; keep create's probes synchronous
* fix(lineage): chat resume keys offers by their own machine; only cross-machine parents leave a section
* fix(lineage): name an older parent server before asking it for a cross-machine ref
* fix(lineage): an app-picked parent on another machine records as manual
* fix(lineage): chat resume keeps base grouping; only resolved cross-store parents move a chat
* revert(lineage): drop chat resume from cross-machine parents; it groups by machine as before
* refactor(lineage): CLI builds cross-machine parents; explicit only
- Drop worktree.crossStoreParentRef and its reparent chain walk: the CLI
builds the ref from this desktop's installationId (worktree.lineageList
now reports it) and the parent row it reads. Cross-machine chains are
allowed; same-store cycle validation and same-install refusal stay.
- No inferred cross-machine parent: remove crossStoreParentInferred and
the fallback states. Against a server, this machine's terminal, cwd and
env context is never sent; the CLI prints how to nest explicitly.
* refactor(lineage): build cross-machine parent refs from verified ids; pickers hide only loops; one desktop install id source
* refactor(lineage): refuse moving a linked workspace instead of carrying the link
Orcad migration and profile project transfer now refuse, before any staging or
write, when a workspace in the move has a cross-store parent record (raw entries,
readable or not). Remove the carry machinery: the dormant crossStoreLineage
field, its runtime capability and destination gate, import/subtract/claim code,
transfer carry and the two-parent conflict checker. Also drop the unused
removeCrossStoreWorkspaceLineage.
* docs(lineage): describe cross-store parent refs without the removed mint RPC
* test(lineage): drop the RPC call-list assertion from the cross-store ref test
* fix(lineage): refuse linked moves before any write and for shared-repo children
- Migration refusal passes the child's own host stamp to the scope matcher and
refuses an unstamped key whose shared repo id the move includes, so such a
child can't move while its link stays behind.
- Profile transfer checks the read-only source snapshot before pending-move
recovery or storage migration; the payload check stays as the final guard.
* fix(lineage): refuse a linked profile move before the profile lookup can restore the index
* fix(lineage): startup hydration of other stores loads only cross-machine links
* fix(lineage): list the child's own machine first in the parent picker
* fix(lineage): keep profile argument errors ahead of the linked-move preflight
* fix(worktrees): let the first listing replace a restored server workspace stub
A restored active server workspace starts as a session stub with no head.
If git status fills in its branch before the first listing lands, the
listing merge took that as a concurrent branch switch and kept the stub,
dropping the catalog row (instance id, lineage, provenance). The workspace
then showed standalone until the next listing.
* fix(worktrees): accept a headless row's listing only when it confirms git status
A stale listing could otherwise roll back a branch switch git status saw on
an empty-head row (e.g. an SSH fallback row) during the first connected listing.
* feat(lineage): CLI nests a create on another machine under the caller workspace
- No parent flag and no --no-parent against a server: the caller's workspace
on this machine (env, else cwd) is sent as an inferred cross-store parent,
the way --parent-worktree active builds it. The host records it as
inferred from environment or cwd.
- A server without worktree.lineage.crossMachine, or a caller workspace that
can't be linked, still creates unnested and prints one note.
- An inferred parent falls away for folder targets, as same-machine folder
creates record none.
* fix(lineage): CLI cross-machine inference reads the caller terminal and suppresses fallbacks
- The caller terminal's workspace joins env and cwd as an inferred parent,
with same-machine precedence: env and terminal must agree, cwd only alone.
- A fallback (old server, unlinkable or unresolved caller, ambiguous cwd)
prints one note and sends noParent, so the server's own create-time
inference can't nest what the CLI reported as not nested.
* feat(sidebar): drag a workspace onto one on another machine to nest it
Dropping a workspace on a workspace from another machine now sets the
parent through the same cross-machine path as Set Parent: same eligibility
(loops, older servers), same refusal messages. Drop targets carry host
identity so the child's own copy is the one written.
* refactor(lineage): this machine's Orca resolves the caller parent for a create on another machine
- New read-only worktree.resolveCallerParent runs the same-machine create
resolver over the caller's env, terminal and cwd context, so stale
contexts are skipped and only validated parents can conflict, and returns
the cross-store ref or a reason.
- The CLI's own precedence and terminal lookup are removed; it keeps the
capability gate, one note with noParent on any fallback, and silence with
no Orca context.
* feat(orchestration): remote worker-start --worktree new-child nests under the coordinator's workspace
worker-start --on <server> --worktree new-child creates the server's worktree
under the coordinator's workspace on this machine, using the same verified
cross-machine parent ref as the CLI's caller auto-nest. A server without
cross-machine parents still starts the worker, top-level, with a warning in
the receipt. Guide, CLI help and docs describe it.
* fix(lineage): resolveCallerParent reads this store's identity without creating it
- Uses the published host descriptor's installationId, else the existing
host-installation.json; never creates or repairs it. Missing identity
returns a reason, so the CLI creates unnested with its note.
- Drops the read-only wording: parent resolution does the same catalog
upkeep a same-machine create does.
* fix(sidebar): validate every cross-machine parent before a multi-select drop writes
A drop of several workspaces builds every cross-machine parent ref first, so an
older server's refusal leaves the whole selection unchanged. Drops the touched
preview-timing test cases.
* refactor(orchestration): build the remote new-child parent ref with the shared caller resolver
Orchestration still picks the caller workspace; resolveCallerParentForAnotherStore
verifies it and builds the ref, and both read the installationId the same way.
Drops the copy and mock-call tests.
* fix(lineage): narrow the inferred source with a guard instead of casts
* fix(lineage): a composer parent picked on another machine nests normally once the destination is that machine
The retained host-qualified pick is classified against the current destination:
same host gives the ordinary parent fields, another store the cross-machine ref.
Also corrects two stale comments.
* perf(lineage): read only the requested child's cross-store entry
* perf(lineage): request each store's lineage list once at startup
* perf(lineage): cap optional caller-parent inference at 3 s and skip a timed-out local Orca
* perf(lineage): return cached sidebar parents when selector inputs are unchanged
* fix(lineage): snapshot selector inputs without a type assertion
* Route startup lineage and the sidebar lineage memo through their owners
* feat(mobile): offer Sign in on a signed-out chat via a host terminal login
* feat(mobile): say which host is out in the chat composer, with Reconnect for the desktop link
* refactor(mobile): fit the host outage line beside main's chat changes
* test: remove 98 low-value mobile tests
* test: drop stale typecheck allowance for removed browser budget test
---------
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* revert(mobile): drop the details card on session tab taps
Reverts 852391da0f (#36395). The card popped up on every tab switch.
Tapping a tab switches tabs again, and the session title card goes back
to its own owner from #30389. Keeps later changes to these files: tab
press feedback, the compact top bar's + button, and #36866's keyboard
keep-focus for title taps.
* fix(mobile): hide branch and folder when the setting is off
The phone's workspace row always printed the branch or folder path, so the
Branch name / Branch / folder path toggle under Card display did nothing.
The shared card details now carry that rule, and the row reads it.
* fix(mobile): centre the chevron on Home list rows
* fix(mobile): scroll sheets taller than the screen
Content-sized sheets ride the keyboard by translation, but their height cap ignored that lift, so a tall sheet pushed its top off screen with no way to scroll back to it. The cap now gives back the keyboard lift. Sheets that scroll their own list can now shrink to the cap instead of clipping it, and the GitHub Pages picker no longer nests its list inside the drawer's ScrollView.
* feat(mobile): show each desktop's machine kind and model
The desktop now reports whether it is a laptop, desktop or server, and its
model, on status.get. The phone stores it with the other last-known host
fields and turns it into a line like "MacBook Pro · macOS".
* feat(mobile): edit a host from its screen and align the Automations bar
The host screen's menu gains Edit host and Network diagnostics. Edit host moves
onto the standard bar and gains Remove host. Automations uses the standard bar
with its switcher pinned under it, as Source Control does.
* feat(mobile): arrange Home and bring back stats and account usage
Home drops the Jump back in times, names the repo on every Jump back in row
(#37642), shows each desktop's machine kind, and adds stats and account usage
at the bottom. A new Arrange button reorders and hides sections, saved on the
phone.
* fix(mobile): keep the page bundle within budget and show the machine on the host screen
The edit route gets a web stub so its native-only removal flow stays out of
the page's chunks, and Automations keeps its own segment style. The host
screen header shows the machine line like Home does.
* fix(mobile): give the edit route's page stub its own module
A bare re-export of the catch-all route compiled to the same asset as
[...page], so the page manifest listed it twice and the desktop template's
inventory check refused the build.
* feat(mobile): turn Home into Feed, Usage, Automations and Settings tabs
Feed keeps agents (needs-you first, five then Show all), desktops with a
needs-you count, and Tasks; New workspace moves to a floating button.
Usage shows stats and per-desktop account usage, Automations a per-desktop
summary with on/off switches that opens the page for editing (new=1 opens
its editor). Settings becomes a tab. Arrange Home is removed: tabs replace
the long scrolling Home it was for.
* style(mobile): darken the accent blue slightly
* style(mobile): give the Home Tasks row the desktop tile icon
* style(mobile): condense the Home Feed
Smaller tiles, type and gaps; a desktop is two lines with its needs-you
count as an amber pill; the Tasks row drops its duplicate heading.
* style(mobile): drop the Last known prefix on Home desktop rows
* chore(mobile): bump to 0.0.63 and Android versionCode 27
* test(mobile): re-record Linear task recordings for the darker accent blue
* test(mobile): check the page Back stack on Tasks now that Edit host is native
* fix(mobile): pass the Usage tab's limit window to the shared usage helpers
* fix(mobile): type the Usage tab test to the account-slot limits and keep the tab under 400 lines
Rows named only the workspace, so with several agents in one workspace they didn't say which conversation needed you. The newest live top-level agent in the row's dot state now gives the title, the workspace moves to the subtitle, and tapping the row opens that conversation's tab. Older desktops send no names and keep the workspace title.
* fix: respect manual workspace order around primary checkouts
* test: consolidate manual primary-order coverage
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test: name twin-reorder cases after the dragged linked worktree
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test: read worktree ID from mobile workspace row
* test: exercise primary checkout drops in reorder cases
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>