perf(web): defer pull request line stats until visible - #6471

Merged
t3dotgg merged 6 commits into
pingdotgg:mainfrom
Adamulek123:t3code/pr-visible-line-stats
Sep 1, 2026
Merged

perf(web): defer pull request line stats until visible#6471
t3dotgg merged 6 commits into
pingdotgg:mainfrom
Adamulek123:t3code/pr-visible-line-stats

Conversation

@Adamulek123

@Adamulek123Adamulek123 commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Pull request line counts used to load for every row, including rows far outside the viewport. Large lists could send hundreds of expensive host stat reads before the user reached those rows.

This change uses one list-owned observer to request stats for rows near the viewport. It groups stable requests by environment, keeps received counts cached, and does not add active or cached rows to later batches.

Largest and smallest sorting still requests stats for every loaded row because those counts decide the row order. Manual refresh uses the same policy. Each environment batch stays within the 500-ref contract limit. If the filter or sort policy changes while a manual refresh waits for host invalidation, the stale stats refresh is ignored.

This modernizes @Adamulek123's original implementation on current main while preserving the new row layout, filters, facet refresh, scroll behavior, and sorting.

Validation

  • vp test run apps/web/src/components/pullRequest/pullRequestList.logic.test.ts (102 tests passed)
  • vp run --filter @t3tools/web typecheck
  • Targeted type-aware lint and format checks for the three policy source and test files
  • git diff --check origin/main...HEAD

No browser test was run for this logic and request-lifetime change.

Modernized by GPT-5.6 Sol in the Codex harness. Original implementation by @Adamulek123.


Note

Medium Risk
Touches request lifetime, refresh races, and sort-dependent data loading on a high-traffic list; logic is heavily unit-tested but browser behavior was not validated.

Overview
Pull request diff line counts are no longer fetched for every loaded row. The list now drives stats through a shared IntersectionObserver on the scroll container, with each PullRequestRow registering via statsRef and data-pull-request-stats-key.

New logic in pullRequestList.logic batches refs per environment (max 500 per batch), skips rows already in-flight or cached, prunes completed batches when rows scroll away, and chooses visible vs eager policy from sort mode (largest/smallest still loads all rows). Manual refresh re-requests only under the current filter/policy scope.

usePullRequestListStats / merged environment queries gain isPending and targeted refresh(override) so refresh does not blindly re-hit every prior batch. Pagination and header observers now share the parent scrollRef instead of the viewport.

Reviewed by Cursor Bugbot for commit 18e9cdf. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Defer pull request diff-stat fetches until rows are visible

  • Diff-stat requests for the pull-requests list are now batched by environment (max 500 refs per batch) and deferred until rows enter the viewport, driven by an IntersectionObserver on each row button.
  • Sorting by size uses an eager policy that requests stats for all loaded rows; other sorts use a visible policy that only requests stats for rows currently on screen.
  • Refresh triggers scoped re-fetches via pullRequestStatsRefreshBatches, ignoring late refreshes when the filter or policy has changed; completed batches whose rows have left the viewport are pruned with retainVisiblePullRequestStatsBatches.
  • PullRequestRow gains statsKey/statsRef props and a data-pull-request-stats-key attribute; PullRequestsColumn now receives a shared scrollRef so list paging and stats observers share one scroll root.
  • usePullRequestListStats now exposes isPending and accepts an explicit targets override on refresh.
  • Behavioral Change: size-based sorts now request stats for the full loaded list rather than only visible rows; the stats observer shares the scrollRef root with the list paging observer, so any consumer overriding PullRequestsColumn's scroll container must pass a valid ref.

Macroscope summarized 18e9cdf.

@coderabbitai

coderabbitaiBot commented Aug 13, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2578675f-6998-4024-88c9-10712ae67a9e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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

@github-actionsgithub-actionsBot added the size:M 30-99 changed lines (additions + deletions). label Aug 13, 2026
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
@macroscopeapp

macroscopeappBot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This changes the default pull-request list’s stats-loading behavior and adds substantial observer, batching, caching, refresh, and sort-dependent request lifecycle logic. The interaction between viewport visibility, pagination, sorting, and refresh warrants human review.

You can add or adjust custom eligibility rules. Learn more.

@github-actionsgithub-actionsBot added the vouch:unvouched PR author is not yet trusted in the VOUCHED list. label Aug 13, 2026
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
macroscopeapp[bot]
macroscopeappBot previously approved these changes Aug 13, 2026

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding on the new visibility-driven stats observer: the rootMargin lookahead is inert because the observer uses the implicit viewport root while the list scrolls inside the page's own overflow-y-auto container, so line counts land after rows are already on screen and reflow the row's right column in view.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
@macroscopeapp
macroscopeappBot dismissed their stale reviewAugust 23, 2026 18:59

Dismissing prior approval to re-evaluate 61e36cb

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). and removed size:M 30-99 changed lines (additions + deletions). labels Aug 23, 2026
@Adamulek123
Adamulek123force-pushed the t3code/pr-visible-line-stats branch from 61e36cb to 988f481CompareAugust 25, 2026 17:45
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
@Adamulek123
Adamulek123force-pushed the t3code/pr-visible-line-stats branch from e467145 to 2b197e3CompareAugust 27, 2026 22:19
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 27f2176. Configure here.

Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
@t3dotgg
t3dotggforce-pushed the t3code/pr-visible-line-stats branch from 71326c8 to bf29367CompareSeptember 1, 2026 10:48
@t3dotgg
t3dotgg merged commit 3c73fa7 into pingdotgg:mainSep 1, 2026
27 checks passed
henrychu04 pushed a commit to henrychu04/t3code-coder that referenced this pull request Sep 1, 2026
henrychu04 pushed a commit to henrychu04/t3code-coder that referenced this pull request Sep 1, 2026
github-actionsBot added a commit to omarcresp/t3code-flake that referenced this pull request Sep 1, 2026
## What's Changed
* perf(server): scan only appended transcript bytes for usage summaries by @StiensWout in pingdotgg/t3code#9024
* perf(server): cut chatty tool-update frames by 90% by @Adamulek123 in pingdotgg/t3code#8368
* fix(server): settle threads server-side by @t3dotgg in pingdotgg/t3code#8600
* fix(clients): dedupe skills in composer menus by @Adamulek123 in pingdotgg/t3code#8043
* fix(server): stop OpenCode child sessions by @t3dotgg in pingdotgg/t3code#9005
* perf(web): defer pull request line stats until visible by @Adamulek123 in pingdotgg/t3code#6471
* perf(server): skip full-message reads while streaming by @t3dotgg in pingdotgg/t3code#9032
* perf(client-runtime): halve server config bootstrap traffic by @Adamulek123 in pingdotgg/t3code#8367
**Full Changelog**: pingdotgg/t3code@v0.0.38-nightly.20260901.1245...v0.0.38-nightly.20260901.1246
Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.38-nightly.20260901.1246
github-actionsBot added a commit to omarcresp/t3code-flake that referenced this pull request Sep 1, 2026
## What's Changed
* Add mobile composer attachment menu with video support by @juliusmarminge in pingdotgg/t3code#8843
* fix(web): restore unified activity logs and composer banners by @t3dotgg in pingdotgg/t3code#8734
* fix(web): address composer banner review follow-ups by @juliusmarminge in pingdotgg/t3code#8850
* fix(web): widen sync banners and simplify the working timer by @juliusmarminge in pingdotgg/t3code#8855
* fix(preview): improve browser recording quality by @maria-rcks in pingdotgg/t3code#8839
* fix(web): mark pull request links as external by @juliusmarminge in pingdotgg/t3code#8856
* fix(mobile): replace Callstack glass with Expo glass by @juliusmarminge in pingdotgg/t3code#8862
* fix(server): skip IDE detection in Claude probes by @yashranaway in pingdotgg/t3code#8634
* chore(macroscope): review diagnostic overrides by @t3-code[bot] in pingdotgg/t3code#8917
* fix(contracts): accept CLI event origins by @nateEc in pingdotgg/t3code#8905
* fix(web): hide invalid slash skill completions by @nateEc in pingdotgg/t3code#8904
* fix(mobile): defer draft navigation until submission completes by @juliusmarminge in pingdotgg/t3code#8914
* chore: disable CodeRabbit review status by @juliusmarminge in pingdotgg/t3code#8933
* Delete app.json by @juliusmarminge in pingdotgg/t3code#8934
* fix(web): show scrollbar for wide markdown tables by @UtkarshUsername in pingdotgg/t3code#8868
* fix(mobile): shimmer active tool rows by @juliusmarminge in pingdotgg/t3code#8932
* chore(deps): bump Electron to 43.4.1 by @StiensWout in pingdotgg/t3code#8626
* fix(chat): smooth worktree setup status by @juliusmarminge in pingdotgg/t3code#8922
* feat(mobile): add video playback with native iOS controls by @juliusmarminge in pingdotgg/t3code#8919
* fix(web): prevent chat metadata overlap by @MatthewFeroz in pingdotgg/t3code#8851
* fix(server): preserve usage cache outside walked roots by @Lucenx9 in pingdotgg/t3code#8540
* feat(mobile): add native image and PDF previews by @juliusmarminge in pingdotgg/t3code#8959
* fix(server): allow long thread IDs in HTTP routes by @nateEc in pingdotgg/t3code#8898
* fix(shared): preserve Windows shell PATH priority by @UtkarshUsername in pingdotgg/t3code#8748
* fix(web): make WSL settings searchable by @UtkarshUsername in pingdotgg/t3code#8881
* feat(web): add expand/collapse all control to the files surface by @UtkarshUsername in pingdotgg/t3code#8889
* feat(mobile): upload attachments while composing by @juliusmarminge in pingdotgg/t3code#8978
* fix(chat): keep agent activity visible between actions by @maria-rcks in pingdotgg/t3code#8984
* fix(server): isolate remote web session cookies by @Bil0000 in pingdotgg/t3code#8085
* feat(pull-requests): link GitHub references in markdown by @maria-rcks in pingdotgg/t3code#8812
* perf(server): reduce frequency of full tool call output being loaded into memory from db by @t3dotgg in pingdotgg/t3code#8988
* feat(web): add pull request list filters by @maria-rcks in pingdotgg/t3code#8809
* feat(web): search individual settings by detail by @maria-rcks in pingdotgg/t3code#8831
* feat(client): render viewed images in work logs by @maria-rcks in pingdotgg/t3code#8936
* fix(client): use package import for markdown image helpers by @juliusmarminge in pingdotgg/t3code#9010
* test: remove static presentation snapshots by @t3-code[bot] in pingdotgg/t3code#9008
* perf(server): bound snapshot activity payload memory by @t3dotgg in pingdotgg/t3code#9000
* perf(server): cut idle CPU use and stop provider event leaks by @t3dotgg in pingdotgg/t3code#8187
* perf(server): scan only appended transcript bytes for usage summaries by @StiensWout in pingdotgg/t3code#9024
* perf(server): cut chatty tool-update frames by 90% by @Adamulek123 in pingdotgg/t3code#8368
* fix(server): settle threads server-side by @t3dotgg in pingdotgg/t3code#8600
* fix(clients): dedupe skills in composer menus by @Adamulek123 in pingdotgg/t3code#8043
* fix(server): stop OpenCode child sessions by @t3dotgg in pingdotgg/t3code#9005
* perf(web): defer pull request line stats until visible by @Adamulek123 in pingdotgg/t3code#6471
* perf(server): skip full-message reads while streaming by @t3dotgg in pingdotgg/t3code#9032
* perf(client-runtime): halve server config bootstrap traffic by @Adamulek123 in pingdotgg/t3code#8367
* fix(web): align un-settle banner action by @StiensWout in pingdotgg/t3code#9033
* fix(web): block type-to-focus behind open dialogs by @Lucenx9 in pingdotgg/t3code#8139
* feat(shortcuts): copy active thread reference by @maria-rcks in pingdotgg/t3code#8994
* fix(mobile): keep thread scroll bounds current after animations by @juliusmarminge in pingdotgg/t3code#9013
* fix(server): cache project favicon resolution by @willsheldon in pingdotgg/t3code#9080
* feat(claude): add Claude Fable 5.1 model by @q1 in pingdotgg/t3code#9078
* fix(preview): restore recording and macOS rendering after Electron 43 by @StiensWout in pingdotgg/t3code#9001
* feat(desktop): add configurable quit shortcut confirmation by @juliusmarminge in pingdotgg/t3code#9076
* feat(web): open project settings from thread menus by @SunkenInTime in pingdotgg/t3code#8925
* fix(chat): reuse one row for live activity by @maria-rcks in pingdotgg/t3code#9062
* feat(models): discover Claude models from remote manifest by @juliusmarminge in pingdotgg/t3code#9084
* Revert "fix(chat): reuse one row for live activity" by @maria-rcks in pingdotgg/t3code#9096
* fix(web): sync sidebar PR state from open panel by @t3-code[bot] in pingdotgg/t3code#9092
* fix(web): changing projects no longer creates a draft by @extoci in pingdotgg/t3code#9097
* fix(web): keep theme placeholder text dimmer than entered text by @flamboh in pingdotgg/t3code#9104
* fix(web): keep the selected environment when changing projects by @t3dotgg in pingdotgg/t3code#9102
## New Contributors
* @willsheldon made their first contribution in pingdotgg/t3code#9080
* @q1 made their first contribution in pingdotgg/t3code#9078
**Full Changelog**: pingdotgg/t3code@v0.0.37...v0.0.38
Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.38
henrychu04 pushed a commit to henrychu04/t3code-coder that referenced this pull request Sep 1, 2026
henrychu04 pushed a commit to henrychu04/t3code-coder that referenced this pull request Sep 1, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Adamulek123@t3dotgg
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

perf(web): defer pull request line stats until visible - #6471

Merged
t3dotgg merged 6 commits into
pingdotgg:mainfrom
Adamulek123:t3code/pr-visible-line-stats
Sep 1, 2026
Merged

perf(web): defer pull request line stats until visible#6471
t3dotgg merged 6 commits into
pingdotgg:mainfrom
Adamulek123:t3code/pr-visible-line-stats

Conversation

@Adamulek123

@Adamulek123Adamulek123 commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Pull request line counts used to load for every row, including rows far outside the viewport. Large lists could send hundreds of expensive host stat reads before the user reached those rows.

This change uses one list-owned observer to request stats for rows near the viewport. It groups stable requests by environment, keeps received counts cached, and does not add active or cached rows to later batches.

Largest and smallest sorting still requests stats for every loaded row because those counts decide the row order. Manual refresh uses the same policy. Each environment batch stays within the 500-ref contract limit. If the filter or sort policy changes while a manual refresh waits for host invalidation, the stale stats refresh is ignored.

This modernizes @Adamulek123's original implementation on current main while preserving the new row layout, filters, facet refresh, scroll behavior, and sorting.

Validation

  • vp test run apps/web/src/components/pullRequest/pullRequestList.logic.test.ts (102 tests passed)
  • vp run --filter @t3tools/web typecheck
  • Targeted type-aware lint and format checks for the three policy source and test files
  • git diff --check origin/main...HEAD

No browser test was run for this logic and request-lifetime change.

Modernized by GPT-5.6 Sol in the Codex harness. Original implementation by @Adamulek123.


Note

Medium Risk
Touches request lifetime, refresh races, and sort-dependent data loading on a high-traffic list; logic is heavily unit-tested but browser behavior was not validated.

Overview
Pull request diff line counts are no longer fetched for every loaded row. The list now drives stats through a shared IntersectionObserver on the scroll container, with each PullRequestRow registering via statsRef and data-pull-request-stats-key.

New logic in pullRequestList.logic batches refs per environment (max 500 per batch), skips rows already in-flight or cached, prunes completed batches when rows scroll away, and chooses visible vs eager policy from sort mode (largest/smallest still loads all rows). Manual refresh re-requests only under the current filter/policy scope.

usePullRequestListStats / merged environment queries gain isPending and targeted refresh(override) so refresh does not blindly re-hit every prior batch. Pagination and header observers now share the parent scrollRef instead of the viewport.

Reviewed by Cursor Bugbot for commit 18e9cdf. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Defer pull request diff-stat fetches until rows are visible

  • Diff-stat requests for the pull-requests list are now batched by environment (max 500 refs per batch) and deferred until rows enter the viewport, driven by an IntersectionObserver on each row button.
  • Sorting by size uses an eager policy that requests stats for all loaded rows; other sorts use a visible policy that only requests stats for rows currently on screen.
  • Refresh triggers scoped re-fetches via pullRequestStatsRefreshBatches, ignoring late refreshes when the filter or policy has changed; completed batches whose rows have left the viewport are pruned with retainVisiblePullRequestStatsBatches.
  • PullRequestRow gains statsKey/statsRef props and a data-pull-request-stats-key attribute; PullRequestsColumn now receives a shared scrollRef so list paging and stats observers share one scroll root.
  • usePullRequestListStats now exposes isPending and accepts an explicit targets override on refresh.
  • Behavioral Change: size-based sorts now request stats for the full loaded list rather than only visible rows; the stats observer shares the scrollRef root with the list paging observer, so any consumer overriding PullRequestsColumn's scroll container must pass a valid ref.

Macroscope summarized 18e9cdf.

@coderabbitai

coderabbitaiBot commented Aug 13, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2578675f-6998-4024-88c9-10712ae67a9e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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

@github-actionsgithub-actionsBot added the size:M 30-99 changed lines (additions + deletions). label Aug 13, 2026
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
@macroscopeapp

macroscopeappBot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This changes the default pull-request list’s stats-loading behavior and adds substantial observer, batching, caching, refresh, and sort-dependent request lifecycle logic. The interaction between viewport visibility, pagination, sorting, and refresh warrants human review.

You can add or adjust custom eligibility rules. Learn more.

@github-actionsgithub-actionsBot added the vouch:unvouched PR author is not yet trusted in the VOUCHED list. label Aug 13, 2026
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
macroscopeapp[bot]
macroscopeappBot previously approved these changes Aug 13, 2026

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding on the new visibility-driven stats observer: the rootMargin lookahead is inert because the observer uses the implicit viewport root while the list scrolls inside the page's own overflow-y-auto container, so line counts land after rows are already on screen and reflow the row's right column in view.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
@macroscopeapp
macroscopeappBot dismissed their stale reviewAugust 23, 2026 18:59

Dismissing prior approval to re-evaluate 61e36cb

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). and removed size:M 30-99 changed lines (additions + deletions). labels Aug 23, 2026
@Adamulek123
Adamulek123force-pushed the t3code/pr-visible-line-stats branch from 61e36cb to 988f481CompareAugust 25, 2026 17:45
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
@Adamulek123
Adamulek123force-pushed the t3code/pr-visible-line-stats branch from e467145 to 2b197e3CompareAugust 27, 2026 22:19
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 27f2176. Configure here.

Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
@t3dotgg
t3dotggforce-pushed the t3code/pr-visible-line-stats branch from 71326c8 to bf29367CompareSeptember 1, 2026 10:48
@t3dotgg
t3dotgg merged commit 3c73fa7 into pingdotgg:mainSep 1, 2026
27 checks passed
henrychu04 pushed a commit to henrychu04/t3code-coder that referenced this pull request Sep 1, 2026
henrychu04 pushed a commit to henrychu04/t3code-coder that referenced this pull request Sep 1, 2026
github-actionsBot added a commit to omarcresp/t3code-flake that referenced this pull request Sep 1, 2026
## What's Changed
* perf(server): scan only appended transcript bytes for usage summaries by @StiensWout in pingdotgg/t3code#9024
* perf(server): cut chatty tool-update frames by 90% by @Adamulek123 in pingdotgg/t3code#8368
* fix(server): settle threads server-side by @t3dotgg in pingdotgg/t3code#8600
* fix(clients): dedupe skills in composer menus by @Adamulek123 in pingdotgg/t3code#8043
* fix(server): stop OpenCode child sessions by @t3dotgg in pingdotgg/t3code#9005
* perf(web): defer pull request line stats until visible by @Adamulek123 in pingdotgg/t3code#6471
* perf(server): skip full-message reads while streaming by @t3dotgg in pingdotgg/t3code#9032
* perf(client-runtime): halve server config bootstrap traffic by @Adamulek123 in pingdotgg/t3code#8367
**Full Changelog**: pingdotgg/t3code@v0.0.38-nightly.20260901.1245...v0.0.38-nightly.20260901.1246
Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.38-nightly.20260901.1246
github-actionsBot added a commit to omarcresp/t3code-flake that referenced this pull request Sep 1, 2026
## What's Changed
* Add mobile composer attachment menu with video support by @juliusmarminge in pingdotgg/t3code#8843
* fix(web): restore unified activity logs and composer banners by @t3dotgg in pingdotgg/t3code#8734
* fix(web): address composer banner review follow-ups by @juliusmarminge in pingdotgg/t3code#8850
* fix(web): widen sync banners and simplify the working timer by @juliusmarminge in pingdotgg/t3code#8855
* fix(preview): improve browser recording quality by @maria-rcks in pingdotgg/t3code#8839
* fix(web): mark pull request links as external by @juliusmarminge in pingdotgg/t3code#8856
* fix(mobile): replace Callstack glass with Expo glass by @juliusmarminge in pingdotgg/t3code#8862
* fix(server): skip IDE detection in Claude probes by @yashranaway in pingdotgg/t3code#8634
* chore(macroscope): review diagnostic overrides by @t3-code[bot] in pingdotgg/t3code#8917
* fix(contracts): accept CLI event origins by @nateEc in pingdotgg/t3code#8905
* fix(web): hide invalid slash skill completions by @nateEc in pingdotgg/t3code#8904
* fix(mobile): defer draft navigation until submission completes by @juliusmarminge in pingdotgg/t3code#8914
* chore: disable CodeRabbit review status by @juliusmarminge in pingdotgg/t3code#8933
* Delete app.json by @juliusmarminge in pingdotgg/t3code#8934
* fix(web): show scrollbar for wide markdown tables by @UtkarshUsername in pingdotgg/t3code#8868
* fix(mobile): shimmer active tool rows by @juliusmarminge in pingdotgg/t3code#8932
* chore(deps): bump Electron to 43.4.1 by @StiensWout in pingdotgg/t3code#8626
* fix(chat): smooth worktree setup status by @juliusmarminge in pingdotgg/t3code#8922
* feat(mobile): add video playback with native iOS controls by @juliusmarminge in pingdotgg/t3code#8919
* fix(web): prevent chat metadata overlap by @MatthewFeroz in pingdotgg/t3code#8851
* fix(server): preserve usage cache outside walked roots by @Lucenx9 in pingdotgg/t3code#8540
* feat(mobile): add native image and PDF previews by @juliusmarminge in pingdotgg/t3code#8959
* fix(server): allow long thread IDs in HTTP routes by @nateEc in pingdotgg/t3code#8898
* fix(shared): preserve Windows shell PATH priority by @UtkarshUsername in pingdotgg/t3code#8748
* fix(web): make WSL settings searchable by @UtkarshUsername in pingdotgg/t3code#8881
* feat(web): add expand/collapse all control to the files surface by @UtkarshUsername in pingdotgg/t3code#8889
* feat(mobile): upload attachments while composing by @juliusmarminge in pingdotgg/t3code#8978
* fix(chat): keep agent activity visible between actions by @maria-rcks in pingdotgg/t3code#8984
* fix(server): isolate remote web session cookies by @Bil0000 in pingdotgg/t3code#8085
* feat(pull-requests): link GitHub references in markdown by @maria-rcks in pingdotgg/t3code#8812
* perf(server): reduce frequency of full tool call output being loaded into memory from db by @t3dotgg in pingdotgg/t3code#8988
* feat(web): add pull request list filters by @maria-rcks in pingdotgg/t3code#8809
* feat(web): search individual settings by detail by @maria-rcks in pingdotgg/t3code#8831
* feat(client): render viewed images in work logs by @maria-rcks in pingdotgg/t3code#8936
* fix(client): use package import for markdown image helpers by @juliusmarminge in pingdotgg/t3code#9010
* test: remove static presentation snapshots by @t3-code[bot] in pingdotgg/t3code#9008
* perf(server): bound snapshot activity payload memory by @t3dotgg in pingdotgg/t3code#9000
* perf(server): cut idle CPU use and stop provider event leaks by @t3dotgg in pingdotgg/t3code#8187
* perf(server): scan only appended transcript bytes for usage summaries by @StiensWout in pingdotgg/t3code#9024
* perf(server): cut chatty tool-update frames by 90% by @Adamulek123 in pingdotgg/t3code#8368
* fix(server): settle threads server-side by @t3dotgg in pingdotgg/t3code#8600
* fix(clients): dedupe skills in composer menus by @Adamulek123 in pingdotgg/t3code#8043
* fix(server): stop OpenCode child sessions by @t3dotgg in pingdotgg/t3code#9005
* perf(web): defer pull request line stats until visible by @Adamulek123 in pingdotgg/t3code#6471
* perf(server): skip full-message reads while streaming by @t3dotgg in pingdotgg/t3code#9032
* perf(client-runtime): halve server config bootstrap traffic by @Adamulek123 in pingdotgg/t3code#8367
* fix(web): align un-settle banner action by @StiensWout in pingdotgg/t3code#9033
* fix(web): block type-to-focus behind open dialogs by @Lucenx9 in pingdotgg/t3code#8139
* feat(shortcuts): copy active thread reference by @maria-rcks in pingdotgg/t3code#8994
* fix(mobile): keep thread scroll bounds current after animations by @juliusmarminge in pingdotgg/t3code#9013
* fix(server): cache project favicon resolution by @willsheldon in pingdotgg/t3code#9080
* feat(claude): add Claude Fable 5.1 model by @q1 in pingdotgg/t3code#9078
* fix(preview): restore recording and macOS rendering after Electron 43 by @StiensWout in pingdotgg/t3code#9001
* feat(desktop): add configurable quit shortcut confirmation by @juliusmarminge in pingdotgg/t3code#9076
* feat(web): open project settings from thread menus by @SunkenInTime in pingdotgg/t3code#8925
* fix(chat): reuse one row for live activity by @maria-rcks in pingdotgg/t3code#9062
* feat(models): discover Claude models from remote manifest by @juliusmarminge in pingdotgg/t3code#9084
* Revert "fix(chat): reuse one row for live activity" by @maria-rcks in pingdotgg/t3code#9096
* fix(web): sync sidebar PR state from open panel by @t3-code[bot] in pingdotgg/t3code#9092
* fix(web): changing projects no longer creates a draft by @extoci in pingdotgg/t3code#9097
* fix(web): keep theme placeholder text dimmer than entered text by @flamboh in pingdotgg/t3code#9104
* fix(web): keep the selected environment when changing projects by @t3dotgg in pingdotgg/t3code#9102
## New Contributors
* @willsheldon made their first contribution in pingdotgg/t3code#9080
* @q1 made their first contribution in pingdotgg/t3code#9078
**Full Changelog**: pingdotgg/t3code@v0.0.37...v0.0.38
Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.38
henrychu04 pushed a commit to henrychu04/t3code-coder that referenced this pull request Sep 1, 2026
henrychu04 pushed a commit to henrychu04/t3code-coder that referenced this pull request Sep 1, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Adamulek123@t3dotgg
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

perf(web): defer pull request line stats until visible - #6471

Merged
t3dotgg merged 6 commits into
pingdotgg:mainfrom
Adamulek123:t3code/pr-visible-line-stats
Sep 1, 2026
Merged

perf(web): defer pull request line stats until visible#6471
t3dotgg merged 6 commits into
pingdotgg:mainfrom
Adamulek123:t3code/pr-visible-line-stats

Conversation

@Adamulek123

@Adamulek123Adamulek123 commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Pull request line counts used to load for every row, including rows far outside the viewport. Large lists could send hundreds of expensive host stat reads before the user reached those rows.

This change uses one list-owned observer to request stats for rows near the viewport. It groups stable requests by environment, keeps received counts cached, and does not add active or cached rows to later batches.

Largest and smallest sorting still requests stats for every loaded row because those counts decide the row order. Manual refresh uses the same policy. Each environment batch stays within the 500-ref contract limit. If the filter or sort policy changes while a manual refresh waits for host invalidation, the stale stats refresh is ignored.

This modernizes @Adamulek123's original implementation on current main while preserving the new row layout, filters, facet refresh, scroll behavior, and sorting.

Validation

  • vp test run apps/web/src/components/pullRequest/pullRequestList.logic.test.ts (102 tests passed)
  • vp run --filter @t3tools/web typecheck
  • Targeted type-aware lint and format checks for the three policy source and test files
  • git diff --check origin/main...HEAD

No browser test was run for this logic and request-lifetime change.

Modernized by GPT-5.6 Sol in the Codex harness. Original implementation by @Adamulek123.


Note

Medium Risk
Touches request lifetime, refresh races, and sort-dependent data loading on a high-traffic list; logic is heavily unit-tested but browser behavior was not validated.

Overview
Pull request diff line counts are no longer fetched for every loaded row. The list now drives stats through a shared IntersectionObserver on the scroll container, with each PullRequestRow registering via statsRef and data-pull-request-stats-key.

New logic in pullRequestList.logic batches refs per environment (max 500 per batch), skips rows already in-flight or cached, prunes completed batches when rows scroll away, and chooses visible vs eager policy from sort mode (largest/smallest still loads all rows). Manual refresh re-requests only under the current filter/policy scope.

usePullRequestListStats / merged environment queries gain isPending and targeted refresh(override) so refresh does not blindly re-hit every prior batch. Pagination and header observers now share the parent scrollRef instead of the viewport.

Reviewed by Cursor Bugbot for commit 18e9cdf. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Defer pull request diff-stat fetches until rows are visible

  • Diff-stat requests for the pull-requests list are now batched by environment (max 500 refs per batch) and deferred until rows enter the viewport, driven by an IntersectionObserver on each row button.
  • Sorting by size uses an eager policy that requests stats for all loaded rows; other sorts use a visible policy that only requests stats for rows currently on screen.
  • Refresh triggers scoped re-fetches via pullRequestStatsRefreshBatches, ignoring late refreshes when the filter or policy has changed; completed batches whose rows have left the viewport are pruned with retainVisiblePullRequestStatsBatches.
  • PullRequestRow gains statsKey/statsRef props and a data-pull-request-stats-key attribute; PullRequestsColumn now receives a shared scrollRef so list paging and stats observers share one scroll root.
  • usePullRequestListStats now exposes isPending and accepts an explicit targets override on refresh.
  • Behavioral Change: size-based sorts now request stats for the full loaded list rather than only visible rows; the stats observer shares the scrollRef root with the list paging observer, so any consumer overriding PullRequestsColumn's scroll container must pass a valid ref.

Macroscope summarized 18e9cdf.

@coderabbitai

coderabbitaiBot commented Aug 13, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2578675f-6998-4024-88c9-10712ae67a9e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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

@github-actionsgithub-actionsBot added the size:M 30-99 changed lines (additions + deletions). label Aug 13, 2026
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
@macroscopeapp

macroscopeappBot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This changes the default pull-request list’s stats-loading behavior and adds substantial observer, batching, caching, refresh, and sort-dependent request lifecycle logic. The interaction between viewport visibility, pagination, sorting, and refresh warrants human review.

You can add or adjust custom eligibility rules. Learn more.

@github-actionsgithub-actionsBot added the vouch:unvouched PR author is not yet trusted in the VOUCHED list. label Aug 13, 2026
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
macroscopeapp[bot]
macroscopeappBot previously approved these changes Aug 13, 2026

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding on the new visibility-driven stats observer: the rootMargin lookahead is inert because the observer uses the implicit viewport root while the list scrolls inside the page's own overflow-y-auto container, so line counts land after rows are already on screen and reflow the row's right column in view.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
@macroscopeapp
macroscopeappBot dismissed their stale reviewAugust 23, 2026 18:59

Dismissing prior approval to re-evaluate 61e36cb

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). and removed size:M 30-99 changed lines (additions + deletions). labels Aug 23, 2026
@Adamulek123
Adamulek123force-pushed the t3code/pr-visible-line-stats branch from 61e36cb to 988f481CompareAugust 25, 2026 17:45
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
@Adamulek123
Adamulek123force-pushed the t3code/pr-visible-line-stats branch from e467145 to 2b197e3CompareAugust 27, 2026 22:19
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 27f2176. Configure here.

Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
@t3dotgg
t3dotggforce-pushed the t3code/pr-visible-line-stats branch from 71326c8 to bf29367CompareSeptember 1, 2026 10:48
@t3dotgg
t3dotgg merged commit 3c73fa7 into pingdotgg:mainSep 1, 2026
27 checks passed
henrychu04 pushed a commit to henrychu04/t3code-coder that referenced this pull request Sep 1, 2026
henrychu04 pushed a commit to henrychu04/t3code-coder that referenced this pull request Sep 1, 2026
github-actionsBot added a commit to omarcresp/t3code-flake that referenced this pull request Sep 1, 2026
## What's Changed
* perf(server): scan only appended transcript bytes for usage summaries by @StiensWout in pingdotgg/t3code#9024
* perf(server): cut chatty tool-update frames by 90% by @Adamulek123 in pingdotgg/t3code#8368
* fix(server): settle threads server-side by @t3dotgg in pingdotgg/t3code#8600
* fix(clients): dedupe skills in composer menus by @Adamulek123 in pingdotgg/t3code#8043
* fix(server): stop OpenCode child sessions by @t3dotgg in pingdotgg/t3code#9005
* perf(web): defer pull request line stats until visible by @Adamulek123 in pingdotgg/t3code#6471
* perf(server): skip full-message reads while streaming by @t3dotgg in pingdotgg/t3code#9032
* perf(client-runtime): halve server config bootstrap traffic by @Adamulek123 in pingdotgg/t3code#8367
**Full Changelog**: pingdotgg/t3code@v0.0.38-nightly.20260901.1245...v0.0.38-nightly.20260901.1246
Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.38-nightly.20260901.1246
github-actionsBot added a commit to omarcresp/t3code-flake that referenced this pull request Sep 1, 2026
## What's Changed
* Add mobile composer attachment menu with video support by @juliusmarminge in pingdotgg/t3code#8843
* fix(web): restore unified activity logs and composer banners by @t3dotgg in pingdotgg/t3code#8734
* fix(web): address composer banner review follow-ups by @juliusmarminge in pingdotgg/t3code#8850
* fix(web): widen sync banners and simplify the working timer by @juliusmarminge in pingdotgg/t3code#8855
* fix(preview): improve browser recording quality by @maria-rcks in pingdotgg/t3code#8839
* fix(web): mark pull request links as external by @juliusmarminge in pingdotgg/t3code#8856
* fix(mobile): replace Callstack glass with Expo glass by @juliusmarminge in pingdotgg/t3code#8862
* fix(server): skip IDE detection in Claude probes by @yashranaway in pingdotgg/t3code#8634
* chore(macroscope): review diagnostic overrides by @t3-code[bot] in pingdotgg/t3code#8917
* fix(contracts): accept CLI event origins by @nateEc in pingdotgg/t3code#8905
* fix(web): hide invalid slash skill completions by @nateEc in pingdotgg/t3code#8904
* fix(mobile): defer draft navigation until submission completes by @juliusmarminge in pingdotgg/t3code#8914
* chore: disable CodeRabbit review status by @juliusmarminge in pingdotgg/t3code#8933
* Delete app.json by @juliusmarminge in pingdotgg/t3code#8934
* fix(web): show scrollbar for wide markdown tables by @UtkarshUsername in pingdotgg/t3code#8868
* fix(mobile): shimmer active tool rows by @juliusmarminge in pingdotgg/t3code#8932
* chore(deps): bump Electron to 43.4.1 by @StiensWout in pingdotgg/t3code#8626
* fix(chat): smooth worktree setup status by @juliusmarminge in pingdotgg/t3code#8922
* feat(mobile): add video playback with native iOS controls by @juliusmarminge in pingdotgg/t3code#8919
* fix(web): prevent chat metadata overlap by @MatthewFeroz in pingdotgg/t3code#8851
* fix(server): preserve usage cache outside walked roots by @Lucenx9 in pingdotgg/t3code#8540
* feat(mobile): add native image and PDF previews by @juliusmarminge in pingdotgg/t3code#8959
* fix(server): allow long thread IDs in HTTP routes by @nateEc in pingdotgg/t3code#8898
* fix(shared): preserve Windows shell PATH priority by @UtkarshUsername in pingdotgg/t3code#8748
* fix(web): make WSL settings searchable by @UtkarshUsername in pingdotgg/t3code#8881
* feat(web): add expand/collapse all control to the files surface by @UtkarshUsername in pingdotgg/t3code#8889
* feat(mobile): upload attachments while composing by @juliusmarminge in pingdotgg/t3code#8978
* fix(chat): keep agent activity visible between actions by @maria-rcks in pingdotgg/t3code#8984
* fix(server): isolate remote web session cookies by @Bil0000 in pingdotgg/t3code#8085
* feat(pull-requests): link GitHub references in markdown by @maria-rcks in pingdotgg/t3code#8812
* perf(server): reduce frequency of full tool call output being loaded into memory from db by @t3dotgg in pingdotgg/t3code#8988
* feat(web): add pull request list filters by @maria-rcks in pingdotgg/t3code#8809
* feat(web): search individual settings by detail by @maria-rcks in pingdotgg/t3code#8831
* feat(client): render viewed images in work logs by @maria-rcks in pingdotgg/t3code#8936
* fix(client): use package import for markdown image helpers by @juliusmarminge in pingdotgg/t3code#9010
* test: remove static presentation snapshots by @t3-code[bot] in pingdotgg/t3code#9008
* perf(server): bound snapshot activity payload memory by @t3dotgg in pingdotgg/t3code#9000
* perf(server): cut idle CPU use and stop provider event leaks by @t3dotgg in pingdotgg/t3code#8187
* perf(server): scan only appended transcript bytes for usage summaries by @StiensWout in pingdotgg/t3code#9024
* perf(server): cut chatty tool-update frames by 90% by @Adamulek123 in pingdotgg/t3code#8368
* fix(server): settle threads server-side by @t3dotgg in pingdotgg/t3code#8600
* fix(clients): dedupe skills in composer menus by @Adamulek123 in pingdotgg/t3code#8043
* fix(server): stop OpenCode child sessions by @t3dotgg in pingdotgg/t3code#9005
* perf(web): defer pull request line stats until visible by @Adamulek123 in pingdotgg/t3code#6471
* perf(server): skip full-message reads while streaming by @t3dotgg in pingdotgg/t3code#9032
* perf(client-runtime): halve server config bootstrap traffic by @Adamulek123 in pingdotgg/t3code#8367
* fix(web): align un-settle banner action by @StiensWout in pingdotgg/t3code#9033
* fix(web): block type-to-focus behind open dialogs by @Lucenx9 in pingdotgg/t3code#8139
* feat(shortcuts): copy active thread reference by @maria-rcks in pingdotgg/t3code#8994
* fix(mobile): keep thread scroll bounds current after animations by @juliusmarminge in pingdotgg/t3code#9013
* fix(server): cache project favicon resolution by @willsheldon in pingdotgg/t3code#9080
* feat(claude): add Claude Fable 5.1 model by @q1 in pingdotgg/t3code#9078
* fix(preview): restore recording and macOS rendering after Electron 43 by @StiensWout in pingdotgg/t3code#9001
* feat(desktop): add configurable quit shortcut confirmation by @juliusmarminge in pingdotgg/t3code#9076
* feat(web): open project settings from thread menus by @SunkenInTime in pingdotgg/t3code#8925
* fix(chat): reuse one row for live activity by @maria-rcks in pingdotgg/t3code#9062
* feat(models): discover Claude models from remote manifest by @juliusmarminge in pingdotgg/t3code#9084
* Revert "fix(chat): reuse one row for live activity" by @maria-rcks in pingdotgg/t3code#9096
* fix(web): sync sidebar PR state from open panel by @t3-code[bot] in pingdotgg/t3code#9092
* fix(web): changing projects no longer creates a draft by @extoci in pingdotgg/t3code#9097
* fix(web): keep theme placeholder text dimmer than entered text by @flamboh in pingdotgg/t3code#9104
* fix(web): keep the selected environment when changing projects by @t3dotgg in pingdotgg/t3code#9102
## New Contributors
* @willsheldon made their first contribution in pingdotgg/t3code#9080
* @q1 made their first contribution in pingdotgg/t3code#9078
**Full Changelog**: pingdotgg/t3code@v0.0.37...v0.0.38
Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.38
henrychu04 pushed a commit to henrychu04/t3code-coder that referenced this pull request Sep 1, 2026
henrychu04 pushed a commit to henrychu04/t3code-coder that referenced this pull request Sep 1, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Adamulek123@t3dotgg
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

perf(web): defer pull request line stats until visible - #6471

Merged
t3dotgg merged 6 commits into
pingdotgg:mainfrom
Adamulek123:t3code/pr-visible-line-stats
Sep 1, 2026
Merged

perf(web): defer pull request line stats until visible#6471
t3dotgg merged 6 commits into
pingdotgg:mainfrom
Adamulek123:t3code/pr-visible-line-stats

Conversation

@Adamulek123

@Adamulek123Adamulek123 commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Pull request line counts used to load for every row, including rows far outside the viewport. Large lists could send hundreds of expensive host stat reads before the user reached those rows.

This change uses one list-owned observer to request stats for rows near the viewport. It groups stable requests by environment, keeps received counts cached, and does not add active or cached rows to later batches.

Largest and smallest sorting still requests stats for every loaded row because those counts decide the row order. Manual refresh uses the same policy. Each environment batch stays within the 500-ref contract limit. If the filter or sort policy changes while a manual refresh waits for host invalidation, the stale stats refresh is ignored.

This modernizes @Adamulek123's original implementation on current main while preserving the new row layout, filters, facet refresh, scroll behavior, and sorting.

Validation

  • vp test run apps/web/src/components/pullRequest/pullRequestList.logic.test.ts (102 tests passed)
  • vp run --filter @t3tools/web typecheck
  • Targeted type-aware lint and format checks for the three policy source and test files
  • git diff --check origin/main...HEAD

No browser test was run for this logic and request-lifetime change.

Modernized by GPT-5.6 Sol in the Codex harness. Original implementation by @Adamulek123.


Note

Medium Risk
Touches request lifetime, refresh races, and sort-dependent data loading on a high-traffic list; logic is heavily unit-tested but browser behavior was not validated.

Overview
Pull request diff line counts are no longer fetched for every loaded row. The list now drives stats through a shared IntersectionObserver on the scroll container, with each PullRequestRow registering via statsRef and data-pull-request-stats-key.

New logic in pullRequestList.logic batches refs per environment (max 500 per batch), skips rows already in-flight or cached, prunes completed batches when rows scroll away, and chooses visible vs eager policy from sort mode (largest/smallest still loads all rows). Manual refresh re-requests only under the current filter/policy scope.

usePullRequestListStats / merged environment queries gain isPending and targeted refresh(override) so refresh does not blindly re-hit every prior batch. Pagination and header observers now share the parent scrollRef instead of the viewport.

Reviewed by Cursor Bugbot for commit 18e9cdf. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Defer pull request diff-stat fetches until rows are visible

  • Diff-stat requests for the pull-requests list are now batched by environment (max 500 refs per batch) and deferred until rows enter the viewport, driven by an IntersectionObserver on each row button.
  • Sorting by size uses an eager policy that requests stats for all loaded rows; other sorts use a visible policy that only requests stats for rows currently on screen.
  • Refresh triggers scoped re-fetches via pullRequestStatsRefreshBatches, ignoring late refreshes when the filter or policy has changed; completed batches whose rows have left the viewport are pruned with retainVisiblePullRequestStatsBatches.
  • PullRequestRow gains statsKey/statsRef props and a data-pull-request-stats-key attribute; PullRequestsColumn now receives a shared scrollRef so list paging and stats observers share one scroll root.
  • usePullRequestListStats now exposes isPending and accepts an explicit targets override on refresh.
  • Behavioral Change: size-based sorts now request stats for the full loaded list rather than only visible rows; the stats observer shares the scrollRef root with the list paging observer, so any consumer overriding PullRequestsColumn's scroll container must pass a valid ref.

Macroscope summarized 18e9cdf.

@coderabbitai

coderabbitaiBot commented Aug 13, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2578675f-6998-4024-88c9-10712ae67a9e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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

@github-actionsgithub-actionsBot added the size:M 30-99 changed lines (additions + deletions). label Aug 13, 2026
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
@macroscopeapp

macroscopeappBot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This changes the default pull-request list’s stats-loading behavior and adds substantial observer, batching, caching, refresh, and sort-dependent request lifecycle logic. The interaction between viewport visibility, pagination, sorting, and refresh warrants human review.

You can add or adjust custom eligibility rules. Learn more.

@github-actionsgithub-actionsBot added the vouch:unvouched PR author is not yet trusted in the VOUCHED list. label Aug 13, 2026
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
macroscopeapp[bot]
macroscopeappBot previously approved these changes Aug 13, 2026

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding on the new visibility-driven stats observer: the rootMargin lookahead is inert because the observer uses the implicit viewport root while the list scrolls inside the page's own overflow-y-auto container, so line counts land after rows are already on screen and reflow the row's right column in view.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
@macroscopeapp
macroscopeappBot dismissed their stale reviewAugust 23, 2026 18:59

Dismissing prior approval to re-evaluate 61e36cb

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). and removed size:M 30-99 changed lines (additions + deletions). labels Aug 23, 2026
@Adamulek123
Adamulek123force-pushed the t3code/pr-visible-line-stats branch from 61e36cb to 988f481CompareAugust 25, 2026 17:45
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
@Adamulek123
Adamulek123force-pushed the t3code/pr-visible-line-stats branch from e467145 to 2b197e3CompareAugust 27, 2026 22:19
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 27f2176. Configure here.

Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
@t3dotgg
t3dotggforce-pushed the t3code/pr-visible-line-stats branch from 71326c8 to bf29367CompareSeptember 1, 2026 10:48
@t3dotgg
t3dotgg merged commit 3c73fa7 into pingdotgg:mainSep 1, 2026
27 checks passed
henrychu04 pushed a commit to henrychu04/t3code-coder that referenced this pull request Sep 1, 2026
henrychu04 pushed a commit to henrychu04/t3code-coder that referenced this pull request Sep 1, 2026
github-actionsBot added a commit to omarcresp/t3code-flake that referenced this pull request Sep 1, 2026
## What's Changed
* perf(server): scan only appended transcript bytes for usage summaries by @StiensWout in pingdotgg/t3code#9024
* perf(server): cut chatty tool-update frames by 90% by @Adamulek123 in pingdotgg/t3code#8368
* fix(server): settle threads server-side by @t3dotgg in pingdotgg/t3code#8600
* fix(clients): dedupe skills in composer menus by @Adamulek123 in pingdotgg/t3code#8043
* fix(server): stop OpenCode child sessions by @t3dotgg in pingdotgg/t3code#9005
* perf(web): defer pull request line stats until visible by @Adamulek123 in pingdotgg/t3code#6471
* perf(server): skip full-message reads while streaming by @t3dotgg in pingdotgg/t3code#9032
* perf(client-runtime): halve server config bootstrap traffic by @Adamulek123 in pingdotgg/t3code#8367
**Full Changelog**: pingdotgg/t3code@v0.0.38-nightly.20260901.1245...v0.0.38-nightly.20260901.1246
Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.38-nightly.20260901.1246
github-actionsBot added a commit to omarcresp/t3code-flake that referenced this pull request Sep 1, 2026
## What's Changed
* Add mobile composer attachment menu with video support by @juliusmarminge in pingdotgg/t3code#8843
* fix(web): restore unified activity logs and composer banners by @t3dotgg in pingdotgg/t3code#8734
* fix(web): address composer banner review follow-ups by @juliusmarminge in pingdotgg/t3code#8850
* fix(web): widen sync banners and simplify the working timer by @juliusmarminge in pingdotgg/t3code#8855
* fix(preview): improve browser recording quality by @maria-rcks in pingdotgg/t3code#8839
* fix(web): mark pull request links as external by @juliusmarminge in pingdotgg/t3code#8856
* fix(mobile): replace Callstack glass with Expo glass by @juliusmarminge in pingdotgg/t3code#8862
* fix(server): skip IDE detection in Claude probes by @yashranaway in pingdotgg/t3code#8634
* chore(macroscope): review diagnostic overrides by @t3-code[bot] in pingdotgg/t3code#8917
* fix(contracts): accept CLI event origins by @nateEc in pingdotgg/t3code#8905
* fix(web): hide invalid slash skill completions by @nateEc in pingdotgg/t3code#8904
* fix(mobile): defer draft navigation until submission completes by @juliusmarminge in pingdotgg/t3code#8914
* chore: disable CodeRabbit review status by @juliusmarminge in pingdotgg/t3code#8933
* Delete app.json by @juliusmarminge in pingdotgg/t3code#8934
* fix(web): show scrollbar for wide markdown tables by @UtkarshUsername in pingdotgg/t3code#8868
* fix(mobile): shimmer active tool rows by @juliusmarminge in pingdotgg/t3code#8932
* chore(deps): bump Electron to 43.4.1 by @StiensWout in pingdotgg/t3code#8626
* fix(chat): smooth worktree setup status by @juliusmarminge in pingdotgg/t3code#8922
* feat(mobile): add video playback with native iOS controls by @juliusmarminge in pingdotgg/t3code#8919
* fix(web): prevent chat metadata overlap by @MatthewFeroz in pingdotgg/t3code#8851
* fix(server): preserve usage cache outside walked roots by @Lucenx9 in pingdotgg/t3code#8540
* feat(mobile): add native image and PDF previews by @juliusmarminge in pingdotgg/t3code#8959
* fix(server): allow long thread IDs in HTTP routes by @nateEc in pingdotgg/t3code#8898
* fix(shared): preserve Windows shell PATH priority by @UtkarshUsername in pingdotgg/t3code#8748
* fix(web): make WSL settings searchable by @UtkarshUsername in pingdotgg/t3code#8881
* feat(web): add expand/collapse all control to the files surface by @UtkarshUsername in pingdotgg/t3code#8889
* feat(mobile): upload attachments while composing by @juliusmarminge in pingdotgg/t3code#8978
* fix(chat): keep agent activity visible between actions by @maria-rcks in pingdotgg/t3code#8984
* fix(server): isolate remote web session cookies by @Bil0000 in pingdotgg/t3code#8085
* feat(pull-requests): link GitHub references in markdown by @maria-rcks in pingdotgg/t3code#8812
* perf(server): reduce frequency of full tool call output being loaded into memory from db by @t3dotgg in pingdotgg/t3code#8988
* feat(web): add pull request list filters by @maria-rcks in pingdotgg/t3code#8809
* feat(web): search individual settings by detail by @maria-rcks in pingdotgg/t3code#8831
* feat(client): render viewed images in work logs by @maria-rcks in pingdotgg/t3code#8936
* fix(client): use package import for markdown image helpers by @juliusmarminge in pingdotgg/t3code#9010
* test: remove static presentation snapshots by @t3-code[bot] in pingdotgg/t3code#9008
* perf(server): bound snapshot activity payload memory by @t3dotgg in pingdotgg/t3code#9000
* perf(server): cut idle CPU use and stop provider event leaks by @t3dotgg in pingdotgg/t3code#8187
* perf(server): scan only appended transcript bytes for usage summaries by @StiensWout in pingdotgg/t3code#9024
* perf(server): cut chatty tool-update frames by 90% by @Adamulek123 in pingdotgg/t3code#8368
* fix(server): settle threads server-side by @t3dotgg in pingdotgg/t3code#8600
* fix(clients): dedupe skills in composer menus by @Adamulek123 in pingdotgg/t3code#8043
* fix(server): stop OpenCode child sessions by @t3dotgg in pingdotgg/t3code#9005
* perf(web): defer pull request line stats until visible by @Adamulek123 in pingdotgg/t3code#6471
* perf(server): skip full-message reads while streaming by @t3dotgg in pingdotgg/t3code#9032
* perf(client-runtime): halve server config bootstrap traffic by @Adamulek123 in pingdotgg/t3code#8367
* fix(web): align un-settle banner action by @StiensWout in pingdotgg/t3code#9033
* fix(web): block type-to-focus behind open dialogs by @Lucenx9 in pingdotgg/t3code#8139
* feat(shortcuts): copy active thread reference by @maria-rcks in pingdotgg/t3code#8994
* fix(mobile): keep thread scroll bounds current after animations by @juliusmarminge in pingdotgg/t3code#9013
* fix(server): cache project favicon resolution by @willsheldon in pingdotgg/t3code#9080
* feat(claude): add Claude Fable 5.1 model by @q1 in pingdotgg/t3code#9078
* fix(preview): restore recording and macOS rendering after Electron 43 by @StiensWout in pingdotgg/t3code#9001
* feat(desktop): add configurable quit shortcut confirmation by @juliusmarminge in pingdotgg/t3code#9076
* feat(web): open project settings from thread menus by @SunkenInTime in pingdotgg/t3code#8925
* fix(chat): reuse one row for live activity by @maria-rcks in pingdotgg/t3code#9062
* feat(models): discover Claude models from remote manifest by @juliusmarminge in pingdotgg/t3code#9084
* Revert "fix(chat): reuse one row for live activity" by @maria-rcks in pingdotgg/t3code#9096
* fix(web): sync sidebar PR state from open panel by @t3-code[bot] in pingdotgg/t3code#9092
* fix(web): changing projects no longer creates a draft by @extoci in pingdotgg/t3code#9097
* fix(web): keep theme placeholder text dimmer than entered text by @flamboh in pingdotgg/t3code#9104
* fix(web): keep the selected environment when changing projects by @t3dotgg in pingdotgg/t3code#9102
## New Contributors
* @willsheldon made their first contribution in pingdotgg/t3code#9080
* @q1 made their first contribution in pingdotgg/t3code#9078
**Full Changelog**: pingdotgg/t3code@v0.0.37...v0.0.38
Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.38
henrychu04 pushed a commit to henrychu04/t3code-coder that referenced this pull request Sep 1, 2026
henrychu04 pushed a commit to henrychu04/t3code-coder that referenced this pull request Sep 1, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Adamulek123@t3dotgg
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

perf(web): defer pull request line stats until visible - #6471

Merged
t3dotgg merged 6 commits into
pingdotgg:mainfrom
Adamulek123:t3code/pr-visible-line-stats
Sep 1, 2026
Merged

perf(web): defer pull request line stats until visible#6471
t3dotgg merged 6 commits into
pingdotgg:mainfrom
Adamulek123:t3code/pr-visible-line-stats

Conversation

@Adamulek123

@Adamulek123Adamulek123 commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Pull request line counts used to load for every row, including rows far outside the viewport. Large lists could send hundreds of expensive host stat reads before the user reached those rows.

This change uses one list-owned observer to request stats for rows near the viewport. It groups stable requests by environment, keeps received counts cached, and does not add active or cached rows to later batches.

Largest and smallest sorting still requests stats for every loaded row because those counts decide the row order. Manual refresh uses the same policy. Each environment batch stays within the 500-ref contract limit. If the filter or sort policy changes while a manual refresh waits for host invalidation, the stale stats refresh is ignored.

This modernizes @Adamulek123's original implementation on current main while preserving the new row layout, filters, facet refresh, scroll behavior, and sorting.

Validation

  • vp test run apps/web/src/components/pullRequest/pullRequestList.logic.test.ts (102 tests passed)
  • vp run --filter @t3tools/web typecheck
  • Targeted type-aware lint and format checks for the three policy source and test files
  • git diff --check origin/main...HEAD

No browser test was run for this logic and request-lifetime change.

Modernized by GPT-5.6 Sol in the Codex harness. Original implementation by @Adamulek123.


Note

Medium Risk
Touches request lifetime, refresh races, and sort-dependent data loading on a high-traffic list; logic is heavily unit-tested but browser behavior was not validated.

Overview
Pull request diff line counts are no longer fetched for every loaded row. The list now drives stats through a shared IntersectionObserver on the scroll container, with each PullRequestRow registering via statsRef and data-pull-request-stats-key.

New logic in pullRequestList.logic batches refs per environment (max 500 per batch), skips rows already in-flight or cached, prunes completed batches when rows scroll away, and chooses visible vs eager policy from sort mode (largest/smallest still loads all rows). Manual refresh re-requests only under the current filter/policy scope.

usePullRequestListStats / merged environment queries gain isPending and targeted refresh(override) so refresh does not blindly re-hit every prior batch. Pagination and header observers now share the parent scrollRef instead of the viewport.

Reviewed by Cursor Bugbot for commit 18e9cdf. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Defer pull request diff-stat fetches until rows are visible

  • Diff-stat requests for the pull-requests list are now batched by environment (max 500 refs per batch) and deferred until rows enter the viewport, driven by an IntersectionObserver on each row button.
  • Sorting by size uses an eager policy that requests stats for all loaded rows; other sorts use a visible policy that only requests stats for rows currently on screen.
  • Refresh triggers scoped re-fetches via pullRequestStatsRefreshBatches, ignoring late refreshes when the filter or policy has changed; completed batches whose rows have left the viewport are pruned with retainVisiblePullRequestStatsBatches.
  • PullRequestRow gains statsKey/statsRef props and a data-pull-request-stats-key attribute; PullRequestsColumn now receives a shared scrollRef so list paging and stats observers share one scroll root.
  • usePullRequestListStats now exposes isPending and accepts an explicit targets override on refresh.
  • Behavioral Change: size-based sorts now request stats for the full loaded list rather than only visible rows; the stats observer shares the scrollRef root with the list paging observer, so any consumer overriding PullRequestsColumn's scroll container must pass a valid ref.

Macroscope summarized 18e9cdf.

@coderabbitai

coderabbitaiBot commented Aug 13, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2578675f-6998-4024-88c9-10712ae67a9e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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

@github-actionsgithub-actionsBot added the size:M 30-99 changed lines (additions + deletions). label Aug 13, 2026
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
@macroscopeapp

macroscopeappBot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This changes the default pull-request list’s stats-loading behavior and adds substantial observer, batching, caching, refresh, and sort-dependent request lifecycle logic. The interaction between viewport visibility, pagination, sorting, and refresh warrants human review.

You can add or adjust custom eligibility rules. Learn more.

@github-actionsgithub-actionsBot added the vouch:unvouched PR author is not yet trusted in the VOUCHED list. label Aug 13, 2026
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
macroscopeapp[bot]
macroscopeappBot previously approved these changes Aug 13, 2026

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding on the new visibility-driven stats observer: the rootMargin lookahead is inert because the observer uses the implicit viewport root while the list scrolls inside the page's own overflow-y-auto container, so line counts land after rows are already on screen and reflow the row's right column in view.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
@macroscopeapp
macroscopeappBot dismissed their stale reviewAugust 23, 2026 18:59

Dismissing prior approval to re-evaluate 61e36cb

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). and removed size:M 30-99 changed lines (additions + deletions). labels Aug 23, 2026
@Adamulek123
Adamulek123force-pushed the t3code/pr-visible-line-stats branch from 61e36cb to 988f481CompareAugust 25, 2026 17:45
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
@Adamulek123
Adamulek123force-pushed the t3code/pr-visible-line-stats branch from e467145 to 2b197e3CompareAugust 27, 2026 22:19
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 27f2176. Configure here.

Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
@t3dotgg
t3dotggforce-pushed the t3code/pr-visible-line-stats branch from 71326c8 to bf29367CompareSeptember 1, 2026 10:48
@t3dotgg
t3dotgg merged commit 3c73fa7 into pingdotgg:mainSep 1, 2026
27 checks passed
henrychu04 pushed a commit to henrychu04/t3code-coder that referenced this pull request Sep 1, 2026
henrychu04 pushed a commit to henrychu04/t3code-coder that referenced this pull request Sep 1, 2026
github-actionsBot added a commit to omarcresp/t3code-flake that referenced this pull request Sep 1, 2026
## What's Changed
* perf(server): scan only appended transcript bytes for usage summaries by @StiensWout in pingdotgg/t3code#9024
* perf(server): cut chatty tool-update frames by 90% by @Adamulek123 in pingdotgg/t3code#8368
* fix(server): settle threads server-side by @t3dotgg in pingdotgg/t3code#8600
* fix(clients): dedupe skills in composer menus by @Adamulek123 in pingdotgg/t3code#8043
* fix(server): stop OpenCode child sessions by @t3dotgg in pingdotgg/t3code#9005
* perf(web): defer pull request line stats until visible by @Adamulek123 in pingdotgg/t3code#6471
* perf(server): skip full-message reads while streaming by @t3dotgg in pingdotgg/t3code#9032
* perf(client-runtime): halve server config bootstrap traffic by @Adamulek123 in pingdotgg/t3code#8367
**Full Changelog**: pingdotgg/t3code@v0.0.38-nightly.20260901.1245...v0.0.38-nightly.20260901.1246
Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.38-nightly.20260901.1246
github-actionsBot added a commit to omarcresp/t3code-flake that referenced this pull request Sep 1, 2026
## What's Changed
* Add mobile composer attachment menu with video support by @juliusmarminge in pingdotgg/t3code#8843
* fix(web): restore unified activity logs and composer banners by @t3dotgg in pingdotgg/t3code#8734
* fix(web): address composer banner review follow-ups by @juliusmarminge in pingdotgg/t3code#8850
* fix(web): widen sync banners and simplify the working timer by @juliusmarminge in pingdotgg/t3code#8855
* fix(preview): improve browser recording quality by @maria-rcks in pingdotgg/t3code#8839
* fix(web): mark pull request links as external by @juliusmarminge in pingdotgg/t3code#8856
* fix(mobile): replace Callstack glass with Expo glass by @juliusmarminge in pingdotgg/t3code#8862
* fix(server): skip IDE detection in Claude probes by @yashranaway in pingdotgg/t3code#8634
* chore(macroscope): review diagnostic overrides by @t3-code[bot] in pingdotgg/t3code#8917
* fix(contracts): accept CLI event origins by @nateEc in pingdotgg/t3code#8905
* fix(web): hide invalid slash skill completions by @nateEc in pingdotgg/t3code#8904
* fix(mobile): defer draft navigation until submission completes by @juliusmarminge in pingdotgg/t3code#8914
* chore: disable CodeRabbit review status by @juliusmarminge in pingdotgg/t3code#8933
* Delete app.json by @juliusmarminge in pingdotgg/t3code#8934
* fix(web): show scrollbar for wide markdown tables by @UtkarshUsername in pingdotgg/t3code#8868
* fix(mobile): shimmer active tool rows by @juliusmarminge in pingdotgg/t3code#8932
* chore(deps): bump Electron to 43.4.1 by @StiensWout in pingdotgg/t3code#8626
* fix(chat): smooth worktree setup status by @juliusmarminge in pingdotgg/t3code#8922
* feat(mobile): add video playback with native iOS controls by @juliusmarminge in pingdotgg/t3code#8919
* fix(web): prevent chat metadata overlap by @MatthewFeroz in pingdotgg/t3code#8851
* fix(server): preserve usage cache outside walked roots by @Lucenx9 in pingdotgg/t3code#8540
* feat(mobile): add native image and PDF previews by @juliusmarminge in pingdotgg/t3code#8959
* fix(server): allow long thread IDs in HTTP routes by @nateEc in pingdotgg/t3code#8898
* fix(shared): preserve Windows shell PATH priority by @UtkarshUsername in pingdotgg/t3code#8748
* fix(web): make WSL settings searchable by @UtkarshUsername in pingdotgg/t3code#8881
* feat(web): add expand/collapse all control to the files surface by @UtkarshUsername in pingdotgg/t3code#8889
* feat(mobile): upload attachments while composing by @juliusmarminge in pingdotgg/t3code#8978
* fix(chat): keep agent activity visible between actions by @maria-rcks in pingdotgg/t3code#8984
* fix(server): isolate remote web session cookies by @Bil0000 in pingdotgg/t3code#8085
* feat(pull-requests): link GitHub references in markdown by @maria-rcks in pingdotgg/t3code#8812
* perf(server): reduce frequency of full tool call output being loaded into memory from db by @t3dotgg in pingdotgg/t3code#8988
* feat(web): add pull request list filters by @maria-rcks in pingdotgg/t3code#8809
* feat(web): search individual settings by detail by @maria-rcks in pingdotgg/t3code#8831
* feat(client): render viewed images in work logs by @maria-rcks in pingdotgg/t3code#8936
* fix(client): use package import for markdown image helpers by @juliusmarminge in pingdotgg/t3code#9010
* test: remove static presentation snapshots by @t3-code[bot] in pingdotgg/t3code#9008
* perf(server): bound snapshot activity payload memory by @t3dotgg in pingdotgg/t3code#9000
* perf(server): cut idle CPU use and stop provider event leaks by @t3dotgg in pingdotgg/t3code#8187
* perf(server): scan only appended transcript bytes for usage summaries by @StiensWout in pingdotgg/t3code#9024
* perf(server): cut chatty tool-update frames by 90% by @Adamulek123 in pingdotgg/t3code#8368
* fix(server): settle threads server-side by @t3dotgg in pingdotgg/t3code#8600
* fix(clients): dedupe skills in composer menus by @Adamulek123 in pingdotgg/t3code#8043
* fix(server): stop OpenCode child sessions by @t3dotgg in pingdotgg/t3code#9005
* perf(web): defer pull request line stats until visible by @Adamulek123 in pingdotgg/t3code#6471
* perf(server): skip full-message reads while streaming by @t3dotgg in pingdotgg/t3code#9032
* perf(client-runtime): halve server config bootstrap traffic by @Adamulek123 in pingdotgg/t3code#8367
* fix(web): align un-settle banner action by @StiensWout in pingdotgg/t3code#9033
* fix(web): block type-to-focus behind open dialogs by @Lucenx9 in pingdotgg/t3code#8139
* feat(shortcuts): copy active thread reference by @maria-rcks in pingdotgg/t3code#8994
* fix(mobile): keep thread scroll bounds current after animations by @juliusmarminge in pingdotgg/t3code#9013
* fix(server): cache project favicon resolution by @willsheldon in pingdotgg/t3code#9080
* feat(claude): add Claude Fable 5.1 model by @q1 in pingdotgg/t3code#9078
* fix(preview): restore recording and macOS rendering after Electron 43 by @StiensWout in pingdotgg/t3code#9001
* feat(desktop): add configurable quit shortcut confirmation by @juliusmarminge in pingdotgg/t3code#9076
* feat(web): open project settings from thread menus by @SunkenInTime in pingdotgg/t3code#8925
* fix(chat): reuse one row for live activity by @maria-rcks in pingdotgg/t3code#9062
* feat(models): discover Claude models from remote manifest by @juliusmarminge in pingdotgg/t3code#9084
* Revert "fix(chat): reuse one row for live activity" by @maria-rcks in pingdotgg/t3code#9096
* fix(web): sync sidebar PR state from open panel by @t3-code[bot] in pingdotgg/t3code#9092
* fix(web): changing projects no longer creates a draft by @extoci in pingdotgg/t3code#9097
* fix(web): keep theme placeholder text dimmer than entered text by @flamboh in pingdotgg/t3code#9104
* fix(web): keep the selected environment when changing projects by @t3dotgg in pingdotgg/t3code#9102
## New Contributors
* @willsheldon made their first contribution in pingdotgg/t3code#9080
* @q1 made their first contribution in pingdotgg/t3code#9078
**Full Changelog**: pingdotgg/t3code@v0.0.37...v0.0.38
Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.38
henrychu04 pushed a commit to henrychu04/t3code-coder that referenced this pull request Sep 1, 2026
henrychu04 pushed a commit to henrychu04/t3code-coder that referenced this pull request Sep 1, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Adamulek123@t3dotgg
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

perf(web): defer pull request line stats until visible - #6471

Merged
t3dotgg merged 6 commits into
pingdotgg:mainfrom
Adamulek123:t3code/pr-visible-line-stats
Sep 1, 2026
Merged

perf(web): defer pull request line stats until visible#6471
t3dotgg merged 6 commits into
pingdotgg:mainfrom
Adamulek123:t3code/pr-visible-line-stats

Conversation

@Adamulek123

@Adamulek123Adamulek123 commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Pull request line counts used to load for every row, including rows far outside the viewport. Large lists could send hundreds of expensive host stat reads before the user reached those rows.

This change uses one list-owned observer to request stats for rows near the viewport. It groups stable requests by environment, keeps received counts cached, and does not add active or cached rows to later batches.

Largest and smallest sorting still requests stats for every loaded row because those counts decide the row order. Manual refresh uses the same policy. Each environment batch stays within the 500-ref contract limit. If the filter or sort policy changes while a manual refresh waits for host invalidation, the stale stats refresh is ignored.

This modernizes @Adamulek123's original implementation on current main while preserving the new row layout, filters, facet refresh, scroll behavior, and sorting.

Validation

  • vp test run apps/web/src/components/pullRequest/pullRequestList.logic.test.ts (102 tests passed)
  • vp run --filter @t3tools/web typecheck
  • Targeted type-aware lint and format checks for the three policy source and test files
  • git diff --check origin/main...HEAD

No browser test was run for this logic and request-lifetime change.

Modernized by GPT-5.6 Sol in the Codex harness. Original implementation by @Adamulek123.


Note

Medium Risk
Touches request lifetime, refresh races, and sort-dependent data loading on a high-traffic list; logic is heavily unit-tested but browser behavior was not validated.

Overview
Pull request diff line counts are no longer fetched for every loaded row. The list now drives stats through a shared IntersectionObserver on the scroll container, with each PullRequestRow registering via statsRef and data-pull-request-stats-key.

New logic in pullRequestList.logic batches refs per environment (max 500 per batch), skips rows already in-flight or cached, prunes completed batches when rows scroll away, and chooses visible vs eager policy from sort mode (largest/smallest still loads all rows). Manual refresh re-requests only under the current filter/policy scope.

usePullRequestListStats / merged environment queries gain isPending and targeted refresh(override) so refresh does not blindly re-hit every prior batch. Pagination and header observers now share the parent scrollRef instead of the viewport.

Reviewed by Cursor Bugbot for commit 18e9cdf. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Defer pull request diff-stat fetches until rows are visible

  • Diff-stat requests for the pull-requests list are now batched by environment (max 500 refs per batch) and deferred until rows enter the viewport, driven by an IntersectionObserver on each row button.
  • Sorting by size uses an eager policy that requests stats for all loaded rows; other sorts use a visible policy that only requests stats for rows currently on screen.
  • Refresh triggers scoped re-fetches via pullRequestStatsRefreshBatches, ignoring late refreshes when the filter or policy has changed; completed batches whose rows have left the viewport are pruned with retainVisiblePullRequestStatsBatches.
  • PullRequestRow gains statsKey/statsRef props and a data-pull-request-stats-key attribute; PullRequestsColumn now receives a shared scrollRef so list paging and stats observers share one scroll root.
  • usePullRequestListStats now exposes isPending and accepts an explicit targets override on refresh.
  • Behavioral Change: size-based sorts now request stats for the full loaded list rather than only visible rows; the stats observer shares the scrollRef root with the list paging observer, so any consumer overriding PullRequestsColumn's scroll container must pass a valid ref.

Macroscope summarized 18e9cdf.

@coderabbitai

coderabbitaiBot commented Aug 13, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2578675f-6998-4024-88c9-10712ae67a9e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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

@github-actionsgithub-actionsBot added the size:M 30-99 changed lines (additions + deletions). label Aug 13, 2026
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
@macroscopeapp

macroscopeappBot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This changes the default pull-request list’s stats-loading behavior and adds substantial observer, batching, caching, refresh, and sort-dependent request lifecycle logic. The interaction between viewport visibility, pagination, sorting, and refresh warrants human review.

You can add or adjust custom eligibility rules. Learn more.

@github-actionsgithub-actionsBot added the vouch:unvouched PR author is not yet trusted in the VOUCHED list. label Aug 13, 2026
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
macroscopeapp[bot]
macroscopeappBot previously approved these changes Aug 13, 2026

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding on the new visibility-driven stats observer: the rootMargin lookahead is inert because the observer uses the implicit viewport root while the list scrolls inside the page's own overflow-y-auto container, so line counts land after rows are already on screen and reflow the row's right column in view.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
@macroscopeapp
macroscopeappBot dismissed their stale reviewAugust 23, 2026 18:59

Dismissing prior approval to re-evaluate 61e36cb

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). and removed size:M 30-99 changed lines (additions + deletions). labels Aug 23, 2026
@Adamulek123
Adamulek123force-pushed the t3code/pr-visible-line-stats branch from 61e36cb to 988f481CompareAugust 25, 2026 17:45
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
@Adamulek123
Adamulek123force-pushed the t3code/pr-visible-line-stats branch from e467145 to 2b197e3CompareAugust 27, 2026 22:19
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 27f2176. Configure here.

Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
@t3dotgg
t3dotggforce-pushed the t3code/pr-visible-line-stats branch from 71326c8 to bf29367CompareSeptember 1, 2026 10:48
@t3dotgg
t3dotgg merged commit 3c73fa7 into pingdotgg:mainSep 1, 2026
27 checks passed
henrychu04 pushed a commit to henrychu04/t3code-coder that referenced this pull request Sep 1, 2026
henrychu04 pushed a commit to henrychu04/t3code-coder that referenced this pull request Sep 1, 2026
github-actionsBot added a commit to omarcresp/t3code-flake that referenced this pull request Sep 1, 2026
## What's Changed
* perf(server): scan only appended transcript bytes for usage summaries by @StiensWout in pingdotgg/t3code#9024
* perf(server): cut chatty tool-update frames by 90% by @Adamulek123 in pingdotgg/t3code#8368
* fix(server): settle threads server-side by @t3dotgg in pingdotgg/t3code#8600
* fix(clients): dedupe skills in composer menus by @Adamulek123 in pingdotgg/t3code#8043
* fix(server): stop OpenCode child sessions by @t3dotgg in pingdotgg/t3code#9005
* perf(web): defer pull request line stats until visible by @Adamulek123 in pingdotgg/t3code#6471
* perf(server): skip full-message reads while streaming by @t3dotgg in pingdotgg/t3code#9032
* perf(client-runtime): halve server config bootstrap traffic by @Adamulek123 in pingdotgg/t3code#8367
**Full Changelog**: pingdotgg/t3code@v0.0.38-nightly.20260901.1245...v0.0.38-nightly.20260901.1246
Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.38-nightly.20260901.1246
github-actionsBot added a commit to omarcresp/t3code-flake that referenced this pull request Sep 1, 2026
## What's Changed
* Add mobile composer attachment menu with video support by @juliusmarminge in pingdotgg/t3code#8843
* fix(web): restore unified activity logs and composer banners by @t3dotgg in pingdotgg/t3code#8734
* fix(web): address composer banner review follow-ups by @juliusmarminge in pingdotgg/t3code#8850
* fix(web): widen sync banners and simplify the working timer by @juliusmarminge in pingdotgg/t3code#8855
* fix(preview): improve browser recording quality by @maria-rcks in pingdotgg/t3code#8839
* fix(web): mark pull request links as external by @juliusmarminge in pingdotgg/t3code#8856
* fix(mobile): replace Callstack glass with Expo glass by @juliusmarminge in pingdotgg/t3code#8862
* fix(server): skip IDE detection in Claude probes by @yashranaway in pingdotgg/t3code#8634
* chore(macroscope): review diagnostic overrides by @t3-code[bot] in pingdotgg/t3code#8917
* fix(contracts): accept CLI event origins by @nateEc in pingdotgg/t3code#8905
* fix(web): hide invalid slash skill completions by @nateEc in pingdotgg/t3code#8904
* fix(mobile): defer draft navigation until submission completes by @juliusmarminge in pingdotgg/t3code#8914
* chore: disable CodeRabbit review status by @juliusmarminge in pingdotgg/t3code#8933
* Delete app.json by @juliusmarminge in pingdotgg/t3code#8934
* fix(web): show scrollbar for wide markdown tables by @UtkarshUsername in pingdotgg/t3code#8868
* fix(mobile): shimmer active tool rows by @juliusmarminge in pingdotgg/t3code#8932
* chore(deps): bump Electron to 43.4.1 by @StiensWout in pingdotgg/t3code#8626
* fix(chat): smooth worktree setup status by @juliusmarminge in pingdotgg/t3code#8922
* feat(mobile): add video playback with native iOS controls by @juliusmarminge in pingdotgg/t3code#8919
* fix(web): prevent chat metadata overlap by @MatthewFeroz in pingdotgg/t3code#8851
* fix(server): preserve usage cache outside walked roots by @Lucenx9 in pingdotgg/t3code#8540
* feat(mobile): add native image and PDF previews by @juliusmarminge in pingdotgg/t3code#8959
* fix(server): allow long thread IDs in HTTP routes by @nateEc in pingdotgg/t3code#8898
* fix(shared): preserve Windows shell PATH priority by @UtkarshUsername in pingdotgg/t3code#8748
* fix(web): make WSL settings searchable by @UtkarshUsername in pingdotgg/t3code#8881
* feat(web): add expand/collapse all control to the files surface by @UtkarshUsername in pingdotgg/t3code#8889
* feat(mobile): upload attachments while composing by @juliusmarminge in pingdotgg/t3code#8978
* fix(chat): keep agent activity visible between actions by @maria-rcks in pingdotgg/t3code#8984
* fix(server): isolate remote web session cookies by @Bil0000 in pingdotgg/t3code#8085
* feat(pull-requests): link GitHub references in markdown by @maria-rcks in pingdotgg/t3code#8812
* perf(server): reduce frequency of full tool call output being loaded into memory from db by @t3dotgg in pingdotgg/t3code#8988
* feat(web): add pull request list filters by @maria-rcks in pingdotgg/t3code#8809
* feat(web): search individual settings by detail by @maria-rcks in pingdotgg/t3code#8831
* feat(client): render viewed images in work logs by @maria-rcks in pingdotgg/t3code#8936
* fix(client): use package import for markdown image helpers by @juliusmarminge in pingdotgg/t3code#9010
* test: remove static presentation snapshots by @t3-code[bot] in pingdotgg/t3code#9008
* perf(server): bound snapshot activity payload memory by @t3dotgg in pingdotgg/t3code#9000
* perf(server): cut idle CPU use and stop provider event leaks by @t3dotgg in pingdotgg/t3code#8187
* perf(server): scan only appended transcript bytes for usage summaries by @StiensWout in pingdotgg/t3code#9024
* perf(server): cut chatty tool-update frames by 90% by @Adamulek123 in pingdotgg/t3code#8368
* fix(server): settle threads server-side by @t3dotgg in pingdotgg/t3code#8600
* fix(clients): dedupe skills in composer menus by @Adamulek123 in pingdotgg/t3code#8043
* fix(server): stop OpenCode child sessions by @t3dotgg in pingdotgg/t3code#9005
* perf(web): defer pull request line stats until visible by @Adamulek123 in pingdotgg/t3code#6471
* perf(server): skip full-message reads while streaming by @t3dotgg in pingdotgg/t3code#9032
* perf(client-runtime): halve server config bootstrap traffic by @Adamulek123 in pingdotgg/t3code#8367
* fix(web): align un-settle banner action by @StiensWout in pingdotgg/t3code#9033
* fix(web): block type-to-focus behind open dialogs by @Lucenx9 in pingdotgg/t3code#8139
* feat(shortcuts): copy active thread reference by @maria-rcks in pingdotgg/t3code#8994
* fix(mobile): keep thread scroll bounds current after animations by @juliusmarminge in pingdotgg/t3code#9013
* fix(server): cache project favicon resolution by @willsheldon in pingdotgg/t3code#9080
* feat(claude): add Claude Fable 5.1 model by @q1 in pingdotgg/t3code#9078
* fix(preview): restore recording and macOS rendering after Electron 43 by @StiensWout in pingdotgg/t3code#9001
* feat(desktop): add configurable quit shortcut confirmation by @juliusmarminge in pingdotgg/t3code#9076
* feat(web): open project settings from thread menus by @SunkenInTime in pingdotgg/t3code#8925
* fix(chat): reuse one row for live activity by @maria-rcks in pingdotgg/t3code#9062
* feat(models): discover Claude models from remote manifest by @juliusmarminge in pingdotgg/t3code#9084
* Revert "fix(chat): reuse one row for live activity" by @maria-rcks in pingdotgg/t3code#9096
* fix(web): sync sidebar PR state from open panel by @t3-code[bot] in pingdotgg/t3code#9092
* fix(web): changing projects no longer creates a draft by @extoci in pingdotgg/t3code#9097
* fix(web): keep theme placeholder text dimmer than entered text by @flamboh in pingdotgg/t3code#9104
* fix(web): keep the selected environment when changing projects by @t3dotgg in pingdotgg/t3code#9102
## New Contributors
* @willsheldon made their first contribution in pingdotgg/t3code#9080
* @q1 made their first contribution in pingdotgg/t3code#9078
**Full Changelog**: pingdotgg/t3code@v0.0.37...v0.0.38
Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.38
henrychu04 pushed a commit to henrychu04/t3code-coder that referenced this pull request Sep 1, 2026
henrychu04 pushed a commit to henrychu04/t3code-coder that referenced this pull request Sep 1, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Adamulek123@t3dotgg
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

perf(web): defer pull request line stats until visible - #6471

Merged
t3dotgg merged 6 commits into
pingdotgg:mainfrom
Adamulek123:t3code/pr-visible-line-stats
Sep 1, 2026
Merged

perf(web): defer pull request line stats until visible#6471
t3dotgg merged 6 commits into
pingdotgg:mainfrom
Adamulek123:t3code/pr-visible-line-stats

Conversation

@Adamulek123

@Adamulek123Adamulek123 commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Pull request line counts used to load for every row, including rows far outside the viewport. Large lists could send hundreds of expensive host stat reads before the user reached those rows.

This change uses one list-owned observer to request stats for rows near the viewport. It groups stable requests by environment, keeps received counts cached, and does not add active or cached rows to later batches.

Largest and smallest sorting still requests stats for every loaded row because those counts decide the row order. Manual refresh uses the same policy. Each environment batch stays within the 500-ref contract limit. If the filter or sort policy changes while a manual refresh waits for host invalidation, the stale stats refresh is ignored.

This modernizes @Adamulek123's original implementation on current main while preserving the new row layout, filters, facet refresh, scroll behavior, and sorting.

Validation

  • vp test run apps/web/src/components/pullRequest/pullRequestList.logic.test.ts (102 tests passed)
  • vp run --filter @t3tools/web typecheck
  • Targeted type-aware lint and format checks for the three policy source and test files
  • git diff --check origin/main...HEAD

No browser test was run for this logic and request-lifetime change.

Modernized by GPT-5.6 Sol in the Codex harness. Original implementation by @Adamulek123.


Note

Medium Risk
Touches request lifetime, refresh races, and sort-dependent data loading on a high-traffic list; logic is heavily unit-tested but browser behavior was not validated.

Overview
Pull request diff line counts are no longer fetched for every loaded row. The list now drives stats through a shared IntersectionObserver on the scroll container, with each PullRequestRow registering via statsRef and data-pull-request-stats-key.

New logic in pullRequestList.logic batches refs per environment (max 500 per batch), skips rows already in-flight or cached, prunes completed batches when rows scroll away, and chooses visible vs eager policy from sort mode (largest/smallest still loads all rows). Manual refresh re-requests only under the current filter/policy scope.

usePullRequestListStats / merged environment queries gain isPending and targeted refresh(override) so refresh does not blindly re-hit every prior batch. Pagination and header observers now share the parent scrollRef instead of the viewport.

Reviewed by Cursor Bugbot for commit 18e9cdf. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Defer pull request diff-stat fetches until rows are visible

  • Diff-stat requests for the pull-requests list are now batched by environment (max 500 refs per batch) and deferred until rows enter the viewport, driven by an IntersectionObserver on each row button.
  • Sorting by size uses an eager policy that requests stats for all loaded rows; other sorts use a visible policy that only requests stats for rows currently on screen.
  • Refresh triggers scoped re-fetches via pullRequestStatsRefreshBatches, ignoring late refreshes when the filter or policy has changed; completed batches whose rows have left the viewport are pruned with retainVisiblePullRequestStatsBatches.
  • PullRequestRow gains statsKey/statsRef props and a data-pull-request-stats-key attribute; PullRequestsColumn now receives a shared scrollRef so list paging and stats observers share one scroll root.
  • usePullRequestListStats now exposes isPending and accepts an explicit targets override on refresh.
  • Behavioral Change: size-based sorts now request stats for the full loaded list rather than only visible rows; the stats observer shares the scrollRef root with the list paging observer, so any consumer overriding PullRequestsColumn's scroll container must pass a valid ref.

Macroscope summarized 18e9cdf.

@coderabbitai

coderabbitaiBot commented Aug 13, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2578675f-6998-4024-88c9-10712ae67a9e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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

@github-actionsgithub-actionsBot added the size:M 30-99 changed lines (additions + deletions). label Aug 13, 2026
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
@macroscopeapp

macroscopeappBot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This changes the default pull-request list’s stats-loading behavior and adds substantial observer, batching, caching, refresh, and sort-dependent request lifecycle logic. The interaction between viewport visibility, pagination, sorting, and refresh warrants human review.

You can add or adjust custom eligibility rules. Learn more.

@github-actionsgithub-actionsBot added the vouch:unvouched PR author is not yet trusted in the VOUCHED list. label Aug 13, 2026
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
macroscopeapp[bot]
macroscopeappBot previously approved these changes Aug 13, 2026

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding on the new visibility-driven stats observer: the rootMargin lookahead is inert because the observer uses the implicit viewport root while the list scrolls inside the page's own overflow-y-auto container, so line counts land after rows are already on screen and reflow the row's right column in view.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
@macroscopeapp
macroscopeappBot dismissed their stale reviewAugust 23, 2026 18:59

Dismissing prior approval to re-evaluate 61e36cb

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). and removed size:M 30-99 changed lines (additions + deletions). labels Aug 23, 2026
@Adamulek123
Adamulek123force-pushed the t3code/pr-visible-line-stats branch from 61e36cb to 988f481CompareAugust 25, 2026 17:45
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
@Adamulek123
Adamulek123force-pushed the t3code/pr-visible-line-stats branch from e467145 to 2b197e3CompareAugust 27, 2026 22:19
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 27f2176. Configure here.

Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
@t3dotgg
t3dotggforce-pushed the t3code/pr-visible-line-stats branch from 71326c8 to bf29367CompareSeptember 1, 2026 10:48
@t3dotgg
t3dotgg merged commit 3c73fa7 into pingdotgg:mainSep 1, 2026
27 checks passed
henrychu04 pushed a commit to henrychu04/t3code-coder that referenced this pull request Sep 1, 2026
henrychu04 pushed a commit to henrychu04/t3code-coder that referenced this pull request Sep 1, 2026
github-actionsBot added a commit to omarcresp/t3code-flake that referenced this pull request Sep 1, 2026
## What's Changed
* perf(server): scan only appended transcript bytes for usage summaries by @StiensWout in pingdotgg/t3code#9024
* perf(server): cut chatty tool-update frames by 90% by @Adamulek123 in pingdotgg/t3code#8368
* fix(server): settle threads server-side by @t3dotgg in pingdotgg/t3code#8600
* fix(clients): dedupe skills in composer menus by @Adamulek123 in pingdotgg/t3code#8043
* fix(server): stop OpenCode child sessions by @t3dotgg in pingdotgg/t3code#9005
* perf(web): defer pull request line stats until visible by @Adamulek123 in pingdotgg/t3code#6471
* perf(server): skip full-message reads while streaming by @t3dotgg in pingdotgg/t3code#9032
* perf(client-runtime): halve server config bootstrap traffic by @Adamulek123 in pingdotgg/t3code#8367
**Full Changelog**: pingdotgg/t3code@v0.0.38-nightly.20260901.1245...v0.0.38-nightly.20260901.1246
Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.38-nightly.20260901.1246
github-actionsBot added a commit to omarcresp/t3code-flake that referenced this pull request Sep 1, 2026
## What's Changed
* Add mobile composer attachment menu with video support by @juliusmarminge in pingdotgg/t3code#8843
* fix(web): restore unified activity logs and composer banners by @t3dotgg in pingdotgg/t3code#8734
* fix(web): address composer banner review follow-ups by @juliusmarminge in pingdotgg/t3code#8850
* fix(web): widen sync banners and simplify the working timer by @juliusmarminge in pingdotgg/t3code#8855
* fix(preview): improve browser recording quality by @maria-rcks in pingdotgg/t3code#8839
* fix(web): mark pull request links as external by @juliusmarminge in pingdotgg/t3code#8856
* fix(mobile): replace Callstack glass with Expo glass by @juliusmarminge in pingdotgg/t3code#8862
* fix(server): skip IDE detection in Claude probes by @yashranaway in pingdotgg/t3code#8634
* chore(macroscope): review diagnostic overrides by @t3-code[bot] in pingdotgg/t3code#8917
* fix(contracts): accept CLI event origins by @nateEc in pingdotgg/t3code#8905
* fix(web): hide invalid slash skill completions by @nateEc in pingdotgg/t3code#8904
* fix(mobile): defer draft navigation until submission completes by @juliusmarminge in pingdotgg/t3code#8914
* chore: disable CodeRabbit review status by @juliusmarminge in pingdotgg/t3code#8933
* Delete app.json by @juliusmarminge in pingdotgg/t3code#8934
* fix(web): show scrollbar for wide markdown tables by @UtkarshUsername in pingdotgg/t3code#8868
* fix(mobile): shimmer active tool rows by @juliusmarminge in pingdotgg/t3code#8932
* chore(deps): bump Electron to 43.4.1 by @StiensWout in pingdotgg/t3code#8626
* fix(chat): smooth worktree setup status by @juliusmarminge in pingdotgg/t3code#8922
* feat(mobile): add video playback with native iOS controls by @juliusmarminge in pingdotgg/t3code#8919
* fix(web): prevent chat metadata overlap by @MatthewFeroz in pingdotgg/t3code#8851
* fix(server): preserve usage cache outside walked roots by @Lucenx9 in pingdotgg/t3code#8540
* feat(mobile): add native image and PDF previews by @juliusmarminge in pingdotgg/t3code#8959
* fix(server): allow long thread IDs in HTTP routes by @nateEc in pingdotgg/t3code#8898
* fix(shared): preserve Windows shell PATH priority by @UtkarshUsername in pingdotgg/t3code#8748
* fix(web): make WSL settings searchable by @UtkarshUsername in pingdotgg/t3code#8881
* feat(web): add expand/collapse all control to the files surface by @UtkarshUsername in pingdotgg/t3code#8889
* feat(mobile): upload attachments while composing by @juliusmarminge in pingdotgg/t3code#8978
* fix(chat): keep agent activity visible between actions by @maria-rcks in pingdotgg/t3code#8984
* fix(server): isolate remote web session cookies by @Bil0000 in pingdotgg/t3code#8085
* feat(pull-requests): link GitHub references in markdown by @maria-rcks in pingdotgg/t3code#8812
* perf(server): reduce frequency of full tool call output being loaded into memory from db by @t3dotgg in pingdotgg/t3code#8988
* feat(web): add pull request list filters by @maria-rcks in pingdotgg/t3code#8809
* feat(web): search individual settings by detail by @maria-rcks in pingdotgg/t3code#8831
* feat(client): render viewed images in work logs by @maria-rcks in pingdotgg/t3code#8936
* fix(client): use package import for markdown image helpers by @juliusmarminge in pingdotgg/t3code#9010
* test: remove static presentation snapshots by @t3-code[bot] in pingdotgg/t3code#9008
* perf(server): bound snapshot activity payload memory by @t3dotgg in pingdotgg/t3code#9000
* perf(server): cut idle CPU use and stop provider event leaks by @t3dotgg in pingdotgg/t3code#8187
* perf(server): scan only appended transcript bytes for usage summaries by @StiensWout in pingdotgg/t3code#9024
* perf(server): cut chatty tool-update frames by 90% by @Adamulek123 in pingdotgg/t3code#8368
* fix(server): settle threads server-side by @t3dotgg in pingdotgg/t3code#8600
* fix(clients): dedupe skills in composer menus by @Adamulek123 in pingdotgg/t3code#8043
* fix(server): stop OpenCode child sessions by @t3dotgg in pingdotgg/t3code#9005
* perf(web): defer pull request line stats until visible by @Adamulek123 in pingdotgg/t3code#6471
* perf(server): skip full-message reads while streaming by @t3dotgg in pingdotgg/t3code#9032
* perf(client-runtime): halve server config bootstrap traffic by @Adamulek123 in pingdotgg/t3code#8367
* fix(web): align un-settle banner action by @StiensWout in pingdotgg/t3code#9033
* fix(web): block type-to-focus behind open dialogs by @Lucenx9 in pingdotgg/t3code#8139
* feat(shortcuts): copy active thread reference by @maria-rcks in pingdotgg/t3code#8994
* fix(mobile): keep thread scroll bounds current after animations by @juliusmarminge in pingdotgg/t3code#9013
* fix(server): cache project favicon resolution by @willsheldon in pingdotgg/t3code#9080
* feat(claude): add Claude Fable 5.1 model by @q1 in pingdotgg/t3code#9078
* fix(preview): restore recording and macOS rendering after Electron 43 by @StiensWout in pingdotgg/t3code#9001
* feat(desktop): add configurable quit shortcut confirmation by @juliusmarminge in pingdotgg/t3code#9076
* feat(web): open project settings from thread menus by @SunkenInTime in pingdotgg/t3code#8925
* fix(chat): reuse one row for live activity by @maria-rcks in pingdotgg/t3code#9062
* feat(models): discover Claude models from remote manifest by @juliusmarminge in pingdotgg/t3code#9084
* Revert "fix(chat): reuse one row for live activity" by @maria-rcks in pingdotgg/t3code#9096
* fix(web): sync sidebar PR state from open panel by @t3-code[bot] in pingdotgg/t3code#9092
* fix(web): changing projects no longer creates a draft by @extoci in pingdotgg/t3code#9097
* fix(web): keep theme placeholder text dimmer than entered text by @flamboh in pingdotgg/t3code#9104
* fix(web): keep the selected environment when changing projects by @t3dotgg in pingdotgg/t3code#9102
## New Contributors
* @willsheldon made their first contribution in pingdotgg/t3code#9080
* @q1 made their first contribution in pingdotgg/t3code#9078
**Full Changelog**: pingdotgg/t3code@v0.0.37...v0.0.38
Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.38
henrychu04 pushed a commit to henrychu04/t3code-coder that referenced this pull request Sep 1, 2026
henrychu04 pushed a commit to henrychu04/t3code-coder that referenced this pull request Sep 1, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Adamulek123@t3dotgg
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

perf(web): defer pull request line stats until visible - #6471

Merged
t3dotgg merged 6 commits into
pingdotgg:mainfrom
Adamulek123:t3code/pr-visible-line-stats
Sep 1, 2026
Merged

perf(web): defer pull request line stats until visible#6471
t3dotgg merged 6 commits into
pingdotgg:mainfrom
Adamulek123:t3code/pr-visible-line-stats

Conversation

@Adamulek123

@Adamulek123Adamulek123 commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Pull request line counts used to load for every row, including rows far outside the viewport. Large lists could send hundreds of expensive host stat reads before the user reached those rows.

This change uses one list-owned observer to request stats for rows near the viewport. It groups stable requests by environment, keeps received counts cached, and does not add active or cached rows to later batches.

Largest and smallest sorting still requests stats for every loaded row because those counts decide the row order. Manual refresh uses the same policy. Each environment batch stays within the 500-ref contract limit. If the filter or sort policy changes while a manual refresh waits for host invalidation, the stale stats refresh is ignored.

This modernizes @Adamulek123's original implementation on current main while preserving the new row layout, filters, facet refresh, scroll behavior, and sorting.

Validation

  • vp test run apps/web/src/components/pullRequest/pullRequestList.logic.test.ts (102 tests passed)
  • vp run --filter @t3tools/web typecheck
  • Targeted type-aware lint and format checks for the three policy source and test files
  • git diff --check origin/main...HEAD

No browser test was run for this logic and request-lifetime change.

Modernized by GPT-5.6 Sol in the Codex harness. Original implementation by @Adamulek123.


Note

Medium Risk
Touches request lifetime, refresh races, and sort-dependent data loading on a high-traffic list; logic is heavily unit-tested but browser behavior was not validated.

Overview
Pull request diff line counts are no longer fetched for every loaded row. The list now drives stats through a shared IntersectionObserver on the scroll container, with each PullRequestRow registering via statsRef and data-pull-request-stats-key.

New logic in pullRequestList.logic batches refs per environment (max 500 per batch), skips rows already in-flight or cached, prunes completed batches when rows scroll away, and chooses visible vs eager policy from sort mode (largest/smallest still loads all rows). Manual refresh re-requests only under the current filter/policy scope.

usePullRequestListStats / merged environment queries gain isPending and targeted refresh(override) so refresh does not blindly re-hit every prior batch. Pagination and header observers now share the parent scrollRef instead of the viewport.

Reviewed by Cursor Bugbot for commit 18e9cdf. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Defer pull request diff-stat fetches until rows are visible

  • Diff-stat requests for the pull-requests list are now batched by environment (max 500 refs per batch) and deferred until rows enter the viewport, driven by an IntersectionObserver on each row button.
  • Sorting by size uses an eager policy that requests stats for all loaded rows; other sorts use a visible policy that only requests stats for rows currently on screen.
  • Refresh triggers scoped re-fetches via pullRequestStatsRefreshBatches, ignoring late refreshes when the filter or policy has changed; completed batches whose rows have left the viewport are pruned with retainVisiblePullRequestStatsBatches.
  • PullRequestRow gains statsKey/statsRef props and a data-pull-request-stats-key attribute; PullRequestsColumn now receives a shared scrollRef so list paging and stats observers share one scroll root.
  • usePullRequestListStats now exposes isPending and accepts an explicit targets override on refresh.
  • Behavioral Change: size-based sorts now request stats for the full loaded list rather than only visible rows; the stats observer shares the scrollRef root with the list paging observer, so any consumer overriding PullRequestsColumn's scroll container must pass a valid ref.

Macroscope summarized 18e9cdf.

@coderabbitai

coderabbitaiBot commented Aug 13, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2578675f-6998-4024-88c9-10712ae67a9e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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

@github-actionsgithub-actionsBot added the size:M 30-99 changed lines (additions + deletions). label Aug 13, 2026
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
@macroscopeapp

macroscopeappBot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This changes the default pull-request list’s stats-loading behavior and adds substantial observer, batching, caching, refresh, and sort-dependent request lifecycle logic. The interaction between viewport visibility, pagination, sorting, and refresh warrants human review.

You can add or adjust custom eligibility rules. Learn more.

@github-actionsgithub-actionsBot added the vouch:unvouched PR author is not yet trusted in the VOUCHED list. label Aug 13, 2026
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
macroscopeapp[bot]
macroscopeappBot previously approved these changes Aug 13, 2026

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding on the new visibility-driven stats observer: the rootMargin lookahead is inert because the observer uses the implicit viewport root while the list scrolls inside the page's own overflow-y-auto container, so line counts land after rows are already on screen and reflow the row's right column in view.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
@macroscopeapp
macroscopeappBot dismissed their stale reviewAugust 23, 2026 18:59

Dismissing prior approval to re-evaluate 61e36cb

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). and removed size:M 30-99 changed lines (additions + deletions). labels Aug 23, 2026
@Adamulek123
Adamulek123force-pushed the t3code/pr-visible-line-stats branch from 61e36cb to 988f481CompareAugust 25, 2026 17:45
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
@Adamulek123
Adamulek123force-pushed the t3code/pr-visible-line-stats branch from e467145 to 2b197e3CompareAugust 27, 2026 22:19
Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 27f2176. Configure here.

Comment threadapps/web/src/routes/_chat.pull-requests.tsx Outdated
@t3dotgg
t3dotggforce-pushed the t3code/pr-visible-line-stats branch from 71326c8 to bf29367CompareSeptember 1, 2026 10:48
@t3dotgg
t3dotgg merged commit 3c73fa7 into pingdotgg:mainSep 1, 2026
27 checks passed
henrychu04 pushed a commit to henrychu04/t3code-coder that referenced this pull request Sep 1, 2026
henrychu04 pushed a commit to henrychu04/t3code-coder that referenced this pull request Sep 1, 2026
github-actionsBot added a commit to omarcresp/t3code-flake that referenced this pull request Sep 1, 2026
## What's Changed
* perf(server): scan only appended transcript bytes for usage summaries by @StiensWout in pingdotgg/t3code#9024
* perf(server): cut chatty tool-update frames by 90% by @Adamulek123 in pingdotgg/t3code#8368
* fix(server): settle threads server-side by @t3dotgg in pingdotgg/t3code#8600
* fix(clients): dedupe skills in composer menus by @Adamulek123 in pingdotgg/t3code#8043
* fix(server): stop OpenCode child sessions by @t3dotgg in pingdotgg/t3code#9005
* perf(web): defer pull request line stats until visible by @Adamulek123 in pingdotgg/t3code#6471
* perf(server): skip full-message reads while streaming by @t3dotgg in pingdotgg/t3code#9032
* perf(client-runtime): halve server config bootstrap traffic by @Adamulek123 in pingdotgg/t3code#8367
**Full Changelog**: pingdotgg/t3code@v0.0.38-nightly.20260901.1245...v0.0.38-nightly.20260901.1246
Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.38-nightly.20260901.1246
github-actionsBot added a commit to omarcresp/t3code-flake that referenced this pull request Sep 1, 2026
## What's Changed
* Add mobile composer attachment menu with video support by @juliusmarminge in pingdotgg/t3code#8843
* fix(web): restore unified activity logs and composer banners by @t3dotgg in pingdotgg/t3code#8734
* fix(web): address composer banner review follow-ups by @juliusmarminge in pingdotgg/t3code#8850
* fix(web): widen sync banners and simplify the working timer by @juliusmarminge in pingdotgg/t3code#8855
* fix(preview): improve browser recording quality by @maria-rcks in pingdotgg/t3code#8839
* fix(web): mark pull request links as external by @juliusmarminge in pingdotgg/t3code#8856
* fix(mobile): replace Callstack glass with Expo glass by @juliusmarminge in pingdotgg/t3code#8862
* fix(server): skip IDE detection in Claude probes by @yashranaway in pingdotgg/t3code#8634
* chore(macroscope): review diagnostic overrides by @t3-code[bot] in pingdotgg/t3code#8917
* fix(contracts): accept CLI event origins by @nateEc in pingdotgg/t3code#8905
* fix(web): hide invalid slash skill completions by @nateEc in pingdotgg/t3code#8904
* fix(mobile): defer draft navigation until submission completes by @juliusmarminge in pingdotgg/t3code#8914
* chore: disable CodeRabbit review status by @juliusmarminge in pingdotgg/t3code#8933
* Delete app.json by @juliusmarminge in pingdotgg/t3code#8934
* fix(web): show scrollbar for wide markdown tables by @UtkarshUsername in pingdotgg/t3code#8868
* fix(mobile): shimmer active tool rows by @juliusmarminge in pingdotgg/t3code#8932
* chore(deps): bump Electron to 43.4.1 by @StiensWout in pingdotgg/t3code#8626
* fix(chat): smooth worktree setup status by @juliusmarminge in pingdotgg/t3code#8922
* feat(mobile): add video playback with native iOS controls by @juliusmarminge in pingdotgg/t3code#8919
* fix(web): prevent chat metadata overlap by @MatthewFeroz in pingdotgg/t3code#8851
* fix(server): preserve usage cache outside walked roots by @Lucenx9 in pingdotgg/t3code#8540
* feat(mobile): add native image and PDF previews by @juliusmarminge in pingdotgg/t3code#8959
* fix(server): allow long thread IDs in HTTP routes by @nateEc in pingdotgg/t3code#8898
* fix(shared): preserve Windows shell PATH priority by @UtkarshUsername in pingdotgg/t3code#8748
* fix(web): make WSL settings searchable by @UtkarshUsername in pingdotgg/t3code#8881
* feat(web): add expand/collapse all control to the files surface by @UtkarshUsername in pingdotgg/t3code#8889
* feat(mobile): upload attachments while composing by @juliusmarminge in pingdotgg/t3code#8978
* fix(chat): keep agent activity visible between actions by @maria-rcks in pingdotgg/t3code#8984
* fix(server): isolate remote web session cookies by @Bil0000 in pingdotgg/t3code#8085
* feat(pull-requests): link GitHub references in markdown by @maria-rcks in pingdotgg/t3code#8812
* perf(server): reduce frequency of full tool call output being loaded into memory from db by @t3dotgg in pingdotgg/t3code#8988
* feat(web): add pull request list filters by @maria-rcks in pingdotgg/t3code#8809
* feat(web): search individual settings by detail by @maria-rcks in pingdotgg/t3code#8831
* feat(client): render viewed images in work logs by @maria-rcks in pingdotgg/t3code#8936
* fix(client): use package import for markdown image helpers by @juliusmarminge in pingdotgg/t3code#9010
* test: remove static presentation snapshots by @t3-code[bot] in pingdotgg/t3code#9008
* perf(server): bound snapshot activity payload memory by @t3dotgg in pingdotgg/t3code#9000
* perf(server): cut idle CPU use and stop provider event leaks by @t3dotgg in pingdotgg/t3code#8187
* perf(server): scan only appended transcript bytes for usage summaries by @StiensWout in pingdotgg/t3code#9024
* perf(server): cut chatty tool-update frames by 90% by @Adamulek123 in pingdotgg/t3code#8368
* fix(server): settle threads server-side by @t3dotgg in pingdotgg/t3code#8600
* fix(clients): dedupe skills in composer menus by @Adamulek123 in pingdotgg/t3code#8043
* fix(server): stop OpenCode child sessions by @t3dotgg in pingdotgg/t3code#9005
* perf(web): defer pull request line stats until visible by @Adamulek123 in pingdotgg/t3code#6471
* perf(server): skip full-message reads while streaming by @t3dotgg in pingdotgg/t3code#9032
* perf(client-runtime): halve server config bootstrap traffic by @Adamulek123 in pingdotgg/t3code#8367
* fix(web): align un-settle banner action by @StiensWout in pingdotgg/t3code#9033
* fix(web): block type-to-focus behind open dialogs by @Lucenx9 in pingdotgg/t3code#8139
* feat(shortcuts): copy active thread reference by @maria-rcks in pingdotgg/t3code#8994
* fix(mobile): keep thread scroll bounds current after animations by @juliusmarminge in pingdotgg/t3code#9013
* fix(server): cache project favicon resolution by @willsheldon in pingdotgg/t3code#9080
* feat(claude): add Claude Fable 5.1 model by @q1 in pingdotgg/t3code#9078
* fix(preview): restore recording and macOS rendering after Electron 43 by @StiensWout in pingdotgg/t3code#9001
* feat(desktop): add configurable quit shortcut confirmation by @juliusmarminge in pingdotgg/t3code#9076
* feat(web): open project settings from thread menus by @SunkenInTime in pingdotgg/t3code#8925
* fix(chat): reuse one row for live activity by @maria-rcks in pingdotgg/t3code#9062
* feat(models): discover Claude models from remote manifest by @juliusmarminge in pingdotgg/t3code#9084
* Revert "fix(chat): reuse one row for live activity" by @maria-rcks in pingdotgg/t3code#9096
* fix(web): sync sidebar PR state from open panel by @t3-code[bot] in pingdotgg/t3code#9092
* fix(web): changing projects no longer creates a draft by @extoci in pingdotgg/t3code#9097
* fix(web): keep theme placeholder text dimmer than entered text by @flamboh in pingdotgg/t3code#9104
* fix(web): keep the selected environment when changing projects by @t3dotgg in pingdotgg/t3code#9102
## New Contributors
* @willsheldon made their first contribution in pingdotgg/t3code#9080
* @q1 made their first contribution in pingdotgg/t3code#9078
**Full Changelog**: pingdotgg/t3code@v0.0.37...v0.0.38
Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.38
henrychu04 pushed a commit to henrychu04/t3code-coder that referenced this pull request Sep 1, 2026
henrychu04 pushed a commit to henrychu04/t3code-coder that referenced this pull request Sep 1, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Adamulek123@t3dotgg