Skip to content

fix(sidebar): a worktree card fetches its Linear issue again only when the issue or its source changes - #30904

Merged
brennanb2025 merged 1 commit into
mainfrom
brennanb2025/linear-card-refetch
Oct 21, 2026
Merged

brennanb2025 merged 1 commit into
mainfrom
brennanb2025/linear-card-refetch

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 1 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​31 0 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​31
Prod 1 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​8 $\color{#cf222e}{\Huge{\mathbf{−}}}$​5 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​3

ELI5

A sidebar card with a linked Linear issue is supposed to load that issue when the card appears and when you come back to the Orca window. Instead it reloaded the issue every time anything about the workspace changed: a comment edit, an agent status change, a new activity time. With a few busy Linear-linked workspaces, that is a steady stream of Linear requests, enough to use up the Linear rate limit. After this change the card loads the issue again only when the linked issue or the Linear source it is read from actually changes.

What Changed

  • Before: every workspace update made each Linear-linked card ask Linear for its issue again as soon as the 60-second cache had run out. A busy workspace re-read its issue about once a minute, all day, and each read is several Linear API requests (the issue plus its related fields).
  • After: a card reads its Linear issue when it appears, when the window regains focus or becomes visible, and when the issue or its source really changes (for example the workspace moves to another host or project). Workspace updates that don't touch the Linear link no longer trigger a read.

Mechanism: the card builds a "source context" (which host, project and account to read the issue through) from the workspace object. Every workspace update replaces that object, so the context was rebuilt as a new object each time, and both card effects that fetch the Linear issue listed the context as a dependency. use-worktree-card-review-details.ts now keeps the previous context object while the rebuilt one is equal to it (using the existing areTaskSourceContextsEqual), so the effects only see a change when there is one.

Why

The structural cause is that the fetch effects were triggered by an object's identity rather than by the identity of what they read. The common pattern for this is to keep a value's previous reference while its content is unchanged, so anything keyed on it only reacts to real changes. That is what this does, at the one place the context is produced, so every consumer of it gets a stable value.

Alternatives considered:

  • Keying the effects on the issue's cache key and reading the context through useEffectEvent. Rejected: WorktreeCard is a React.memo component, and in React 19.2.8 the commit step that refreshes an effect event skips memo components, so the effect read the previous render's context (verified in the test below before switching).
  • Dropping the context from the effect dependencies. Rejected: a real source change (another host or project) would then not refetch.

Credit: this is the same approach as community PR #30090 by calebcassel, who found the cause. This PR adds a test that a real source change still refetches through the new source.

Not in this PR (same class, smaller impact): the hover details card (use-workspace-reference-details.ts) also rebuilds its attachment requests from the workspace object, so while a hover card is open, workspace updates re-read the attachments. It is bounded to while the hover card is open and sits behind the same 60-second caches; a safe fix there needs a request key that also covers the branch and attachment title, so it is a separate change.

Linked Issue

Tracked in STA-10988.

Visual Proof

N/A: no visual change. Real-app evidence (fetch counts on main vs this branch while workspace updates run) is attached in a comment below.

Testing

  • WorktreeCard.hosted-review-refresh.test.tsx: a Linear-linked card re-rendered with only its comment and activity time changed fetches once (fails on main with two fetches, passes here); then a real source change (another host and project) fetches again with the new source.

  • Real Orca test copy: see the QA comment.

  • I manually tested these changes locally

  • Automated tests added/updated, or explained why not below

AI Disclosure

Review

Plan: keep the card's Linear source context value-stable at the one place it is built, so the two card effects that fetch the Linear issue re-run only when the issue, the Linear workspace or the source really changes. One production file, one test.

Light path classification:

  1. Small: 8 changed production lines in 1 production file (use-worktree-card-review-details.ts).
  2. Outside the risky areas: renderer-only hook state; no saved data, settings, IPC or wire change, no ordering, retries, processes, auth or orchestration, and no default change.
  3. Not a repeat: git log --since="30 days ago" on use-worktree-card-review-details.ts and use-worktree-card-lifecycle-effects.ts shows feat(sidebar): main produces per-workspace PR facts, checked against the window in dev and test #30026, fix(notifications): hidden workspaces stop notifying unless you opt in #28870, Fix linked reviews stuck loading on detached workspaces #28228, b1cd858 and Refresh visible reviews automatically and stop settled merged polling #25788; none fixes Linear issue refetching, and there is no revert or incident on these files.
  4. Local effect: one component's fetch effects (the sidebar worktree card).

Agent skill upstream boundary

  • Not applicable, or this change copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

Renderer only: no saved data, wire or visual change. SSH, WSL and runtime hosts: a host change still produces a different context and refetches. Folder workspaces: unaffected (same context derivation).

  • Author: Brennan Benson (X: @BrennanKB5)

Checklist

  • This PR is small and focused
  • I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred)

Branch: authenticated STA-10988 card after expired-cache focus refresh

…n the issue or its source changes

The card rebuilt its Linear source context on every workspace write, and both
card Linear effects listed that object as a dependency, so a comment, agent
status or activity update re-ran them and refetched the issue whenever the 60s
cache had expired. Hold the context while it is equal to the rebuilt one.

Tracked in STA-10988. Same approach as community PR #30090.
@brennanb2025
brennanb2025 marked this pull request as ready for review October 19, 2026 22:59
@coderabbitai

coderabbitai Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 3fbb54e4-730e-4d59-abf1-61a609ccafab
📥 Commits

Reviewing files that changed from the base of the PR and between ff70e9a and 1d650ee.

📒 Files selected for processing: 2
  • src/renderer/src/components/sidebar/WorktreeCard.hosted-review-refresh.test.tsx
  • src/renderer/src/components/sidebar/use-worktree-card-review-details.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 0 remain after this review.

📝 Walkthrough

The hook now stores the Linear source context in state. It retains the stored context when the current context is equal and updates it when the context changes. A test checks issue fetch counts after initial render, metadata updates, and a context change. It also checks the arguments passed to the second fetch.

Priority: ⬇️ Low

Merge Risk: ⚪ Minimal · up to 1d650

Unrelated worktree updates should no longer refetch the Linear issue, while issue and source changes remain tracked. No merge-blocking issue was identified.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title clearly identifies the main change: limiting Linear issue refetches to issue or source-context changes.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Description check Passed The description is complete and detailed. It covers the user impact, implementation, rationale, alternatives, testing, visual proof, compatibility considerations, and checklist. It identifies STA-1098…
Full details: Description check

Explanation

The description is complete and detailed. It covers the user impact, implementation, rationale, alternatives, testing, visual proof, compatibility considerations, and checklist. It identifies STA-10988, but it does not provide an actual linked issue URL or Fixes # reference as required by the template. The full validation command checklist is also not marked complete, although CI coverage may explain this.

✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@brennanb2025

Copy link
Copy Markdown
Contributor Author

Real-app QA: main vs this branch (Windows, hidden dev builds)

Question tested: does a sidebar card with a linked Linear issue keep asking for that issue while the workspace gets updated, and does it still refresh when it should?

Setup: hidden dev test copies of Orca on Windows (throwaway home, no Linear account connected, so every read is answered locally and nothing reaches Linear). A scratch project, its card showing the "Linear issue" property, linked to ENG-1. Then 48 real workspace comment updates, one every 5 seconds for 4 minutes, on each build. Calls were counted at the store's fetchLinearIssue; reads were counted as new cache writes from the main process.

main (209e468) this branch (1d650ee)
Workspace updates 48 48
Times the card asked for the issue during the updates 48 0
Reads that reached the main process during the updates 4 (one per expired cache minute) 0
Reads the issue when the card first appears yes yes
Window focus after the 60s cache expired +1 read +1 read
Link changed to ENG-2 reads ENG-2 reads ENG-2
Source changed (another project scope) fresh read under the new source fresh read under the new source

Card rendering with a seeded issue is identical on both builds (title, identifier, status badge, hover details):

main:
main card hover

this branch:
branch card hover

Both with two linked items:
main two linked
branch two linked

Not covered here: a read through a real signed-in Linear account (this change doesn't touch the read itself, only when it is triggered), SSH and folder workspaces, and real OS focus changes (focus was simulated with a window focus event).

@brennanb2025

brennanb2025 commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor Author

A sidebar card rebuilt its Linear source context after unrelated workspace updates, so note and activity changes could repeatedly fetch the linked issue. This change retains the context while its values are equal. Those metadata writes stop triggering fetches; changing the issue or its source still refreshes it.

Review completed on 1d650eee3d2c8f8cd5e8d3517cabc3aa1471fc19: one fresh adversarial reviewer confirmed the light path and found no defects; an independent readiness and performance review found no proven issues. No review fixes were needed. The regression fails on main and passes on the branch, including a source change that supplies the new context. The full PR workflow and its aggregate gate passed on this exact head; there are no unresolved review threads.

Authenticated main-versus-branch QA completed in a hidden app through qa-gate. Both builds went from disconnected through the Settings connection form to displaying the real STA-10988 title and Triage status. The branch reused the profile created by main through an actual app restart, retaining the repo, linked issue, settings and prior note.

Measured behavior Main Branch
Persisted metadata writes 10 10
Fetch calls caused by those writes 10 0
Fresh issue-cache reads during those writes 1 0

After 75 seconds, the branch's focus event caused exactly one fetch and one fresh, non-null read of the same real issue. Counters and build identity were independently checked from saved per-write assertions. Earlier four-minute Windows QA separately measured 48 calls/four reads on main versus zero/zero on the branch; initial reads, relinking and source-change controls also passed. The authenticated supplement used one account and does not claim a second-account transition.

QA method limitations: two prohibited coordinate-based CDP mouse movements occurred. The first was found after that driver exited; the second driver was stopped by its verified PID. No OS input, desktop focus or window activation was reported. The branch driver exited 3 after saving the functional checks and disconnect action; this is acceptance of the saved assertions, not a successful driver completion or a claim of fully compliant methods. A redundant setup-install invocation was also discovered afterward; its lockfile churn was reversed. Disposable app/driver homes were removed, recorded processes exited, and real config hashes were unchanged.

Existing attachment-hover refetching and missing provider rate-limit backoff remain outside this change. Live SSH/folder-workspace variants and native OS focus transitions were not exercised. Preserving the existing cache, focus and routing behavior around value-based context retention is an intended difference from the common pattern's surrounding implementation.

For Brennan's review

Main, authenticated issue after metadata writes:
Main: authenticated STA-10988 card

Branch, the same authenticated issue after expired-cache focus refresh:
Branch: authenticated STA-10988 card after focus refresh

These demonstrate functional card content, not pixel equivalence: theme and capture scale changed within the main run itself, with the theme trigger unverified; notes and onboarding state also differ. Earlier Windows comparison and screenshots.

The main judgment point is retaining the source context while equal.

@brennanb2025
brennanb2025 merged commit 0985d6f into main Oct 21, 2026
60 checks passed
@brennanb2025
brennanb2025 deleted the brennanb2025/linear-card-refetch branch October 21, 2026 17:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant