Skip to content

Post-1.0 review backlog: 28 verified findings from the pre-release adversarial review #2

Description

@antonarnaudov

The pre-1.0 adversarial review (10 angles, 41 candidates, 1-vote verify) surfaced 42 confirmed findings. 13 release-gating ones were fixed pre-merge (see PR #1); this issue tracks the rest, grouped. Full details incl. verified failure scenarios live in the review transcript.

Correctness

  • packages/webview-ui/src/graph/commit-graph.ts:1972 — CommitGraph.reveal() silently no-ops when the sha isn't in the loaded pages, so promoting a deep commit from the sidebar rail opens the graph panel without selecting or scrolling to that commit.

Correctness (sweep)

  • apps/extension/src/changes/commitView.ts:988 — doPushState's instant first post carries this.lastBranches/lastAiEnabled without any repo-scope check, so right after switching the active repo the branch menu is populated with the PREVIOUS repo's branch list until the slow for-each-ref probe re-posts.
  • packages/webview-ui/src/graph/commit-rail.ts:1164 — reveal() queues an unresolvable sha into pendingReveal forever (no loadMore paging toward it), so the header's "Jump to HEAD" silently no-ops when HEAD isn't in the loaded window, and updated() then takes the pendingReveal branch and skips renderRows() on every reactive update while it pends.

Cross-file correctness

  • apps/desktop/src/main/gitBridge.ts:561 — compareRefs reports ahead as commits.length, but the commits stream is capped at maxCount 400, so 'ahead' silently saturates at 400 while 'behind' (revCount, uncapped) is exact — the extension's refCompare counts ahead exactly via rev-list --count.

Stale-cache / race hygiene

  • apps/desktop/src/renderer/cache.ts:82 — gget's resolution handler stores its result with a fresh timestamp unconditionally, so bust() cannot invalidate an in-flight request and pre-mutation data is resurrected into the cache as fresh (no generation stamp on entries).
  • apps/desktop/src/renderer/bridge.ts:43 — GraphHostAdapter.reset() clears the loading flag without cancelling or generation-guarding the in-flight page request, so after loadInitial() a stale loadMore response clobbers skip/exhausted and appends pre-reload rows to the freshly initialized graph.
  • apps/desktop/src/main/gitBridge.ts:118 — graphLoad is a stateful accumulator (this.loaded/this.records keyed only by repo root and skip===0) with no request serialization or generation, so concurrent or out-of-order graph:load calls build a gapped, out-of-order commit list whose layout and nextSkip are wrong.
  • apps/desktop/src/renderer/renderer.ts:692 — The keep-alive viewCache is never invalidated by git mutations (only repo switch clears it, and force-refresh deletes only the current view), so a restored Branches view shows a stale branch list with no refetch, and its reloadBranchRows closure is permanently dead from routeGen mismatch.
  • apps/desktop/src/renderer/renderer.ts:3102 — refreshRefs() assigns this.refs and repaints the top-bar branch label after its awaits with no routeGen/scope check, so a slow resolve from the previous repo overwrites the new repo's refs after a repo switch.
  • apps/extension/src/changes/commitView.ts:685 — listRefsCached stores its result into refsCache unconditionally after the await, so a listRefs() call that was in flight when invalidateRefs() ran re-caches pre-mutation refs with a fresh 1.5s TTL, defeating the invalidation the branch ops rely on.

Efficiency

  • apps/extension/src/graph/graphPanel.ts:739 — pushRowStats fires up to 60 concurrent per-sha stat jobs (the 'Bounded concurrency' comment is false — Promise.all over the whole queue), and each sha costs TWO git spawns (getCommitFiles runs both diff --numstat and diff --name-status), when one batched git log --no-walk -z --numstat --format=%H <shas> spawn per visible window yields the same files/adds/dels.
  • apps/desktop/src/main/gitBridge.ts:277 — Desktop twin of the rowStats waste, one worse: for each sha not in the records cache it additionally runs a full streamCommits spawn just to learn parents[0], so an uncached visible sha costs THREE git spawns (log -1 + diff --numstat + diff --name-status) where one batched --no-walk --numstat call per window would serve all 60.
  • apps/extension/src/changes/commitView.ts:1007 — Every doPushState re-runs the uncached AI-availability probe: gitBrain.isEnabled() -> getProvider(), which in auto mode calls vscode.lm.selectChatModels() plus a SecretStorage/OS-keychain read (anthropic key), and in cli mode spawns a which/where process — per state push, for a value that only changes on config/secret edits.
  • apps/desktop/src/main/gitBridge.ts:635 — headCommit always runs git rev-list --count HEAD — a full history walk — even for the amend-prefill call site (renderer.ts:2172) that only needs the HEAD subject from the preceding log -1, and uncached for the Code-view root bar (renderer.ts:1978) on every visit.
  • apps/extension/src/changes/commitView.ts:1016 — doPushState unconditionally posts the ENTIRE state payload a second time (spread of base = full merge/staged/unstaged file lists) after the slow probe resolves, even when aiEnabled and branches are identical to the lastAiEnabled/lastBranches already sent in the first post — a cheap equality check (or a slim {aiEnabled, branches} delta message) would skip it.

Duplication to consolidate

  • packages/webview-ui/src/graph/commit-rail.ts:1600 — rowMatches() and the identical search-scope union are duplicated between commit-rail.ts (1587/68) and commit-graph.ts (2030/106) instead of living in one shared graph module, and the copies have already drifted: the rail's "all" case omits the authorEmail check the graph's has.
  • packages/webview-ui/src/graph/commit-rail.ts:1624 — avatarHtml() is byte-for-byte duplicated in commit-rail.ts:1624 and commit-graph.ts:2501 even though both files already import gravatarUrl/avatarHue/authorInitials from the existing shared home packages/webview-ui/src/graph/avatar.ts, where this function belongs.
  • apps/extension/src/changes/commitView.ts:762 — The no-checkout fast-forward pull (for-each-ref %(upstream:short) -> split on first '/' -> git fetch remote remoteBranch:localBranch) is re-implemented in commitView.ts:762-784 and gitBridge.branchPullFf (apps/desktop/src/main/gitBridge.ts:828-846) instead of living in git-service's SyncOps, which both call sites already hold as ctx.sync.
  • apps/desktop/src/main/gitBridge.ts:1332 — git status porcelain parsing exists three times — gitBridge.ts:1332 parsePorcelainStatus (v1) and packages/git-service/src/GitToolHost.ts:324 parsePorcelain (v1) — even though this PR ships the canonical StatusProvider (packages/git-service/src/StatusProvider.ts, wired as ctx.status at GitContext.ts:68 and already consumed by the extension at commitView.ts:925), and gitBridge already holds that same GitContext.
  • packages/webview-ui/src/graph/commit-rail.ts:1645 — The esc/relTime/absTime helper trio is re-implemented per file inside the same package: esc+relTime+absTime identical in commit-rail.ts (1645/1660/1671) and commit-graph.ts (2528/2543/2587), with absTime tripled again in commit-details.ts:731 — no shared home exists, but one is trivially creatable next to avatar.ts (e.g. packages/webview-ui/src/graph/format.ts).

Dead code / simplification

  • apps/extension/src/changes/commitView.ts:716 — handleBranchAction's case "checkout" and case "checkoutRemote" (plus their noteRecentBranch calls) are unreachable dead code: the webview never posts branchAction with those actions — every checkout goes through the branchRefCommand path (subAct → gitstudio.branch.checkout / gitstudio.remoteBranch.checkout), and the FromWebview doc comment at lines 115-116 still advertises them.
  • apps/extension/src/graph/graphPanel.ts:449 — Private method openCommit (lines 449-468) is never called — the "openCommit" webview message was rewired to pushCommitDetails (line 167-168), leaving this pre-details-panel showInformationMessage flow (its own comment says "A full commit-details panel is M5; for now…") as 20 lines of dead code.
  • packages/host-bridge/src/graphProtocol.ts:84 — GraphConfigMessage ("graphConfig" / lanePalette override) is a dead protocol member: no host ever posts it (neither apps/extension/src/graph/graphPanel.ts nor the desktop graphMount/main.ts), and both webview receivers (packages/webview-ui/src/graph/main.ts:222 and sidebar-main.ts:108) handle it with an empty break that never applies the palette.
  • apps/extension/src/changes/commitView.ts:2435 — branchAct's action !== "fetch" keep-menu-open exception (and its two-line comment about fetch running in place) is dead after the quick-actions rewiring — fetch is posted directly by the live menu-action handler (lines 2699-2703) and never flows through branchAct, whose only remaining callers pass "favorite", "new", or "checkoutRef"; plainAct (line 2490) is then an exact duplicate of branchAct.
  • apps/extension/src/changes/commitView.ts:109 — FromWebview's status?: string field is dead: its doc comment describes a fileMenu message that no longer exists in the type union, the webview script never sends status, and the host never reads msg.status.

Right-depth refactors

  • apps/desktop/src/main/autoUpdate.ts:13 — macOS auto-update is disabled by a hard process.platform === 'darwin' early-return in app code coupled (by comments only) to a feed-omission special case in release-desktop.yml's mac matrix entries, instead of the general mechanism: a post-build publish step that merges the two per-arch latest-mac.yml feeds' files entries into one feed — after which the existing 404-swallowing error handler already covers 'no feed yet' on every platform with no special case.
  • apps/desktop/src/renderer/renderer.ts:1113 — fetchLiveInMenu keeps the open branch menu's 'Pull …' label fresh by DOM-spelunking (closest('.dropdown') → querySelector('.dropdown-item .codicon-arrow-down') → parentElement → '.dropdown-label') — a per-item patch layered on ui.ts's keepOpen mechanism — instead of the data-driven repaint the extension already implements for the identical problem (commitView.ts refreshOpenBranchUi rebuilds the dialog stack from fresh branchData and re-opens the submenu).
  • packages/webview-ui/src/graph/gutter.ts:34 — curveSpan is an opt-in caller-supplied magic number (commit-rail.ts:920 passes 26 for its 40px rows; commit-graph's 30px rows rely on the implicit full-height default) rather than a rowHeight-derived default inside the renderer — e.g. bend span = min(rowHeight, ~30), which reproduces both existing geometries exactly (30 ≥ rowHeight is a no-op for the editor graph) with zero parameters.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions