* fix(repos): remove a paired computer's deleted projects from every connected device
A project deleted on a paired Orca host stayed in every connected client's
sidebar and could not be removed there.
Two independent defects:
1. Host-local repo IPC mutations only sent `repos:changed` to the host's own
renderer (src/main/ipc/repos.ts:2711). The runtime client-event stream was
fed only by mutations arriving over runtime RPC, and clients refetch a remote
catalog only on a `reposChanged` event -- there is no polling on desktop -- so
the deleted rows persisted indefinitely. The shared `notifyReposChanged`
helper now also calls the new
`OrcaRuntimeService.notifyReposChangedForRemoteClients()`
(src/main/runtime/orca-runtime.ts:5175), mirroring the existing
`notifyWorktreesChangedForRemoteClients` precedent. This covers every repo,
project-group and folder-workspace IPC mutation, so renames, colors, reorders
and adds propagate too.
2. Deleting the ghost row on the client routed `repo.rm` to the owner, which
answered `repo_not_found`. `removeProject` wrapped its whole body in one
try/catch, so the rejection aborted the local purge before the `set()`
(src/renderer/src/store/slices/repos.ts:3466) and the delete button appeared
to do nothing. Only `repo_not_found` is now tolerated; any other failure still
keeps the row, and an opt-in `errorFeedback: 'toast'` makes it visible at the
three single-project user-initiated entry points. Bulk and background callers
keep today's silence plus their own aggregate reporting.
Closes#11994
Co-authored-by: Orca <help@stably.ai>
* fix(repos): revert inert RepositoryPane removeProject arg
The settings pane's only render site drops the argument; the toast is
already delivered by removeSettingsProjectFromAllHosts.
Co-authored-by: Orca <help@stably.ai>
* fix(repos): scope duplicate-repo-id deletes to the owning execution host
Cover the cross-host collisions #11994's broadcast now fans out to every paired
device. Same-name projects on different hosts were already isolated (per-host
UUIDs, host-scoped catalog merge and purge) and are pinned by regression tests.
Two same-repo-id paths were not: `repo.rm` with a `path:`/`name:` selector and
`deleteProjectHostSetup` both resolved one row and then deleted by bare id,
taking the sibling host's registration with it.
Co-authored-by: Orca <help@stably.ai>
* test(mobile): align the poll-interval rationale with the new reposChanged emission
Co-authored-by: Orca <help@stably.ai>
* fix(repos): resolve deleteProjectHostSetup's repo row only on the setup's own host
The sibling-host fallback could only ever pick a row on a host the caller
did not name; with no exact match the setup is stale and the existing path
already drops just the setup.
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Orca <help@stably.ai>
* perf(mobile): gate host polling on foreground
The mobile host screen ran two 3s polls (routed + embedded), each firing worktree.ps
AND repo.list, with no foreground/background gate — so a connected phone kept pinging
every 3s (worktree.ps is a full multi-repo process scan) plus a radio wakeup, including
brief background windows while the socket stays parked.
Consolidate both into one startHostWorktreeRefresh lifecycle and AppState-gate the
interval so BOTH polls stop while backgrounded and refresh immediately on foreground
return. worktree.ps keeps its 3s cadence while foregrounded (it carries live agent
status/preview/unread that no push event replaces). repo.list stays on the interval as
an AppState-gated, self-throttling (REPO_METADATA_REFRESH_MS=60s) convergence safety-net
— desktop Settings repo edits notify only the renderer, not the runtime clientEvents
stream, so it can't be made purely event-driven without going stale — and additionally
gets a reposChanged/worktreesChanged fast-path and reconnect-replay refetch.
Verified in a deps-installed mobile checkout: full mobile suite 2232 pass, typecheck,
oxlint (within the frozen max-lines budget), and oxfmt --check all clean.
Co-authored-by: Orca <help@stably.ai>
* chore(mobile): drop stale fetchRepoMetadata dep from the reconnect effect
Address CodeRabbit nitpick: the reconnect effect no longer calls fetchRepoMetadata
(that refetch moved into startHostWorktreeRefresh), so it shouldn't remain in the
effect's dependency array.
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Orca <help@stably.ai>