Skip to content

Commit 8a5ccb3

Browse files
committed
fix(vcs): harden panel review edge cases
Serialize source-control metadata updates and use globally monotonic snapshot generations. Use collision-proof file IDs, a themed commit-branch dialog, and pointer cursors for clickable rows. Generated by GPT-5 in Codex via T3 Code
1 parent 23b1a5e commit 8a5ccb3

15 files changed

Lines changed: 339 additions & 82 deletions

BRANCH_DETAILS.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@
22

33
The first-class Version Control panel includes a singleton right-panel surface, live VCS status watcher, Actionable and Remotes panel model, selected-file commit/stash flow, branch/commit/stash/remote actions, compare-base semantics, and Version Control panel RPC/contracts. On web, a logical project shared across environments renders one complete panel instance for each connected environment, with the active environment first and remote instances using the existing server-icon and environment-label treatment. Snapshots, status subscriptions, fetches, diffs, editor launches, and Git mutations stay routed through each instance's environment and cwd. Disconnected environments are omitted, failures remain isolated to their per-panel retry state, and only the active instance may update active-thread source-control metadata or open its standalone File surface. The shared `apps/web/src/rightPanelStore.ts`, `RightPanelTabs.tsx`, and `ChatView.sourceControl.ts` integration keeps singleton Source Control and multi-tab pull-request surfaces as peers: Source Control availability filtering removes only that surface, preserves pull-request tabs, and falls back to the first remaining visible surface when an unavailable Source Control tab was active. Version Control uses shortcut `V`, appears first in the empty-panel launcher, and remains last in the compact add-surface menu. Background preview mini-player lifecycle changes and right-panel browser-surface reconciliation must leave the Source Control surface open, visible, active, and present exactly once.
44

5-
Web source-control rows use the rich-tooltip presentation and timing shared with the default web sidebar in `apps/web/src/components/Sidebar.tsx`, including its `TooltipCardPopup` treatment. The opt-in legacy sidebar remains isolated in `apps/web/src/components/LegacySidebar.tsx` and does not define this convention. Working tree, file, branch, commit, stash, and remote cards expose their full paths or refs and relevant status, timestamp, identity, URL, and line-change details without covering the row. Federated environment headers expose their complete cwd through the shared styled tooltip primitive rather than the browser-native `title` attribute. File cards use trigger-scoped virtual anchors while retaining a common panel-aligned left edge. Nested action buttons keep their terse label tooltips and preserve the parent rich card only for the nested trigger in that same row, so unrelated tooltips elsewhere are unaffected.
5+
Web source-control rows use the rich-tooltip presentation and timing shared with the default web sidebar in `apps/web/src/components/Sidebar.tsx`, including its `TooltipCardPopup` treatment. The opt-in legacy sidebar remains isolated in `apps/web/src/components/LegacySidebar.tsx` and does not define this convention. Working tree, file, branch, commit, stash, and remote cards expose their full paths or refs and relevant status, timestamp, identity, URL, and line-change details without covering the row. Clickable tree and file rows use the pointer cursor alongside their keyboard button semantics. Federated environment headers expose their complete cwd through the shared styled tooltip primitive rather than the browser-native `title` attribute. File cards use trigger-scoped virtual anchors while retaining a common panel-aligned left edge. Nested action buttons keep their terse label tooltips and preserve the parent rich card only for the nested trigger in that same row, so unrelated tooltips elsewhere are unaffected.
66

77
VCS status ignores internal `.git/` watcher events before refreshing local status. Background activity keeps lightweight current-upstream status refreshes separate from the Version Control panel's broader fetch-all-remotes work. The normal Git interval retains the shared `performance`, `balanced`, and `battery-saver` values of 15 seconds, 30 seconds, and disabled, while the panel-specific all-remotes interval uses one minute, five minutes, and disabled respectively. Automatic panel fetches run only while a panel retains Git-ref demand and the owning environment's shared lock, low-power, battery, visibility, and activity policy allows the work. Opening the web panel and focusing the mobile route refresh their local snapshots immediately. On subsequent web focus, an enabled panel interval first makes the interval-aware, policy-gated fetch request and then refreshes the local snapshot once; a zero interval skips the network request and refreshes locally immediately. Explicit Fetch always remains available. The previous omitted custom default migrates through the new balanced default, with its conservative cadence preserved by the panel-specific value; an explicitly persisted five-minute upstream-status override remains an override instead of being reclassified by value. Settings search indexes the individual Source Control controls: stable writing controls anchor to their rows, while discovery-dependent Git intervals and provider-avatar controls route to the panel's stable Source Control section.
88

99
Provider-backed change-request and commit-avatar lookups remain best-effort in the panel service. Provider/auth/CLI failures must not fail the whole panel snapshot or hide git-derived actionable branch rows. These background reads share the provider-and-host cooldown used by pull-request services: the first classified rate-limit response records the provider reset time or fallback backoff, and later panel reads skip the provider until that pause expires while retaining Git-derived content and avatar fallbacks.
1010

11-
Version Control and source-control provider failures should preserve structured causes when normalized for panel RPC errors. GitLab, GitHub, Azure DevOps, and Bitbucket provider paths should keep provider-specific not-found/auth/missing-CLI details without collapsing structured process failures into generic strings. Web mutations reconcile VCS status and an authoritative panel snapshot after both success and failure before preserving a mutation error, so conflict-producing or partially applied operations remain visible. Web Source Control mutation confirmations use the shared themed `LocalApi` dialog with the destructive variant and never fall back to a native `window.confirm`. Azure DevOps commit-avatar lookups route through the organization encoded by the repository remote and use the stable Commits Get API version.
11+
Version Control and source-control provider failures should preserve structured causes when normalized for panel RPC errors. GitLab, GitHub, Azure DevOps, and Bitbucket provider paths should keep provider-specific not-found/auth/missing-CLI details without collapsing structured process failures into generic strings. Web mutations reconcile VCS status and an authoritative panel snapshot after both success and failure before preserving a mutation error, so conflict-producing or partially applied operations remain visible. Web Source Control mutation confirmations use the shared themed `LocalApi` dialog with the destructive variant and never fall back to a native `window.confirm`; commit branch-name entry likewise uses a themed `Dialog` and `Input` instead of native `window.prompt`. Azure DevOps commit-avatar lookups route through the organization encoded by the repository remote and use the stable Commits Get API version.
1212

1313
Panel mutations that can change refs invalidate both shared ref-cache layers in finalizers: `apps/server/src/sourceControl/SourceControlPanelActions.ts` and `SourceControlPanelService.ts` call the non-failing `GitVcsDriver.invalidateRefs` boundary for the shared server `listRefs` snapshot, while matching commands in `packages/client-runtime/src/state/vcs.ts` invalidate shared client ref state through `onSettled`. This applies after successful, failed, interrupted, or partially applied commit, branch, fetch, and remote mutations. Working-tree staging/unstaging/discard, stash operations, diffs, comparisons, and other read/display-only operations remain excluded. Cache invalidation supplements the existing authoritative panel/status reconciliation and never replaces or masks the original mutation result.
1414

15-
Thread source-control metadata update failures should surface on the thread without overwriting unrelated thread errors, and successful source-control updates should clear only the source-control metadata error for that thread. `apps/web/src/components/ChatView.sourceControl.ts` resolves the visible banner with local thread errors ahead of source-control metadata errors and persisted provider-session errors behind them. Dismissing a banner clears only its owning local or source-control error; persisted session errors are masked for the current UI session, so a lower-priority error remains available after the dismissed banner is gone. Metadata update sequencing stays monotonic for the hook lifetime so a reopened thread key cannot let an old in-flight failure overwrite a newer successful checkout. Server-thread updates carry the active branch as `expectedBranch`, allowing the server to reject a stale metadata write instead of overwriting a newer branch/worktree transition. Grouped-project navigation retargets an open singleton Source Control surface to the active draft/thread environment and effective repository cwd, while metadata errors remain scoped to the originating environment/thread key and are pruned when that context is no longer retained.
15+
Thread source-control metadata update failures should surface on the thread without overwriting unrelated thread errors, and successful source-control updates should clear only the source-control metadata error for that thread. `apps/web/src/components/ChatView.sourceControl.ts` resolves the visible banner with local thread errors ahead of source-control metadata errors and persisted provider-session errors behind them. Dismissing a banner clears only its owning local or source-control error; persisted session errors are masked for the current UI session, so a lower-priority error remains available after the dismissed banner is gone. Metadata updates are serialized per thread with monotonic hook-lifetime sequencing, and each successful update supplies its resulting branch as the next queued update's `expectedBranch`. Loading thread shells supply their recorded active branch as the initial guard. This prevents overlapping checkouts or a still-loading full thread from leaving server metadata behind the repository state. Grouped-project navigation retargets an open singleton Source Control surface to the active draft/thread environment and effective repository cwd, while metadata errors remain scoped to the originating environment/thread key and are pruned when that context is no longer retained.
1616

1717
Required edge cases: the current default branch remains a valid default compare ref and retains that stable base in its own branch details, status-derived default branch names such as `develop` are preferred over hardcoded `main`/`master` guesses, compare-history pagination queries the selected comparison range, branch pull/fetch parsing handles slashful remotes and remote-looking local branch names without treating slashless local upstreams as remote refs, fetch-before-sync refreshes the authoritative snapshot before choosing the same action's push/pull/diverged result and does not fetch an unchanged branch twice, non-Git projects disable the Source Control action and hide any retained surface after VCS status resolves, diverged normal merge sync is available only for the current branch, checked-out branch worktree paths fall back from porcelain worktree output to branch-format placeholders without failing on older Git versions, sibling worktree watcher refreshes keep root Actionable rows live while skipping stale/prunable worktree paths, working-tree refreshes that race an authoritative full snapshot cannot retain pre-mutation branch/remote/stash data, failed full snapshots release the in-flight full-refresh barrier so later working-tree refreshes can remain incremental, queued web refreshes still drain when the active refresh fails or is interrupted, duplicate web and mobile actions with the same key are synchronously suppressed while the first mutation remains in flight, branch sync and undo operations for checked-out branches target the owning worktree cwd, checkout and deletion remain rejected by both the client and server for branches already checked out in any worktree, cwd-scoped working-tree enrichment avoids cross-worktree file-detail reuse, a fallback File surface uses its own cwd and reveal metadata, stale background-stop failures cannot clear a newer thread's pending stop, selected-file commits omit pathspecs after staging, commit-hook output only enriches a failed Git result and never interrupts a still-running commit, merge refs are passed after `--`, tracked discard restore failures surface instead of being swallowed, fallback rename parsing preserves original paths, Review patches disable user-configured diff rendering, merged staged-plus-unstaged row stats are summed, collapsed mobile remotes hide their branch rows, mobile conflict-only rows open the working-tree diff side, sibling mobile working trees are not marked expansion-initialized until they become current, failed mobile branch/stash details replace loading placeholders with errors, invalid mobile branch and stash dates are omitted instead of appearing as recent activity, and late-month relative dates do not fall through to `0 years ago`.
1818

0 commit comments

Comments
 (0)