Files
orca/src
Brennan Benson 5e1a5bf664 fix(sidebar): stop collapsing two hosts into one workspace row (STA-4343)
Routing a removal to the confirmed host is useless if that host's row can
never be confirmed. `worktreeId` is `repoId::path` with no host component,
and every id-keyed projection folded the second host away.

Store index: dedup by (host, id) instead of id. The duplicate this dedup
was built for — the createWorktree-appends / fetchWorktrees-replaces race —
is the SAME workspace twice and still collapses; two hosts are two
workspaces and now both survive. Adds getIndexedWorktreesById for callers
that need every owner.

Sidebar: rowKey, host-context labels, and the lineage emit/child sets are
keyed by host-qualified identity. The lineage set mattered most — keyed by
bare id, the second host's row was never emitted at all. Repo grouping
falls back to per-row host labels when one repo id spans two hosts, since
the per-repo label cannot tell those rows apart.

Delete lineage: a colliding child id resolves to the parent's host, so
"delete all" cannot route a descendant at the other machine's checkout.

Reconciles the two id indices, which disagreed (first-wins in
worktree-by-id-index, last-wins in worktree-repo-index) and so resolved the
same colliding id to different rows. Both are first-wins now, matching the
`.find()` they replaced; same-host duplicates are already collapsed by
freshness before that point, so first-vs-last only decides genuine
two-host collisions, which no bare-id lookup can resolve. Documented on
both, and both are marked as not-evidence-of-ownership.

The index keeps its one-read-per-row budget (retained selectors assert it)
by recovering the id from the identity key instead of re-reading it.
2026-08-16 21:59:42 -07:00
..