Warm sidebar thread detail subscriptions - #2001

Merged
juliusmarminge merged 2 commits into
mainfrom
t3code/thread-subscription-cache-policy
Apr 13, 2026
Merged

Warm sidebar thread detail subscriptions#2001
juliusmarminge merged 2 commits into
mainfrom
t3code/thread-subscription-cache-policy

Conversation

@juliusmarminge

@juliusmarmingejuliusmarminge commented Apr 13, 2026

Copy link
Copy Markdown
Member

Summary

  • Prewarm thread detail subscriptions for the first visible sidebar threads so nearby navigation can reuse hot data.
  • Extend the thread-detail cache policy to keep non-idle threads sticky and only evict idle subscriptions.
  • Increase the idle TTL and cache capacity to reduce churn while navigating and working in active threads.
  • Add tests for sidebar prewarm selection and the updated subscription eviction behavior.

Testing

  • bun fmt
  • bun lint
  • bun typecheck
  • bun run test apps/web/src/components/Sidebar.logic.test.ts
  • bun run test apps/web/src/environments/runtime/service.threadSubscriptions.test.ts

Note

Medium Risk
Changes thread-detail subscription caching/eviction and adds background prewarming from the sidebar, which can affect memory/network usage and when subscriptions are released. Logic now depends on thread activity state to prevent eviction, so regressions could keep subscriptions alive longer than intended.

Overview
Prewarms thread-detail data for the first visible sidebar threads by retaining their detail subscriptions (default 10) while they remain visible, releasing them when the visible set changes.

Updates the runtime thread-detail subscription cache policy to be stickier for non-idle threads (pending approvals/input/plan, running turns, or non-idle orchestration), and to evict only idle unretained entries; idle TTL increases to 15 minutes and cache capacity to 32.

Adds unit tests covering getSidebarThreadIdsToPrewarm and the new eviction behavior (longer warm period, non-idle stickiness, and increased capacity before eviction).

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

Note

Warm thread detail subscriptions for visible sidebar threads

  • The sidebar now retains thread detail subscriptions for up to 10 visible threads (SIDEBAR_THREAD_PREWARM_LIMIT) using retainThreadDetailSubscription, releasing them when threads leave the prewarmed set.
  • The thread detail subscription cache is expanded from 8 to 32 entries and the idle eviction timeout is increased from 2 to 15 minutes.
  • Non-idle threads (pending approvals, running turns, etc.) are exempt from eviction via a new isNonIdleThreadDetailSubscription helper in service.ts; eviction is deferred until the thread becomes idle.
  • Eviction schedules are reconciled after shell snapshot syncs, recovered event batches, and shell upserts to keep cache state consistent.
  • Behavioral Change: releasing a subscription no longer always schedules eviction — non-idle threads remain cached until idle, and capacity eviction only removes the least-recently-accessed idle entries.

Macroscope summarized a4afe8c.

- Prewarm visible sidebar threads
- Keep active thread subscriptions sticky until idle
- Expand cache capacity and add coverage
@coderabbitai

coderabbitaiBot commented Apr 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

Run ID: 65d2f790-b9a8-4a72-937c-a2601d27dbcc

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
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch t3code/thread-subscription-cache-policy

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

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels Apr 13, 2026

@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 and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Prewarm effect re-runs on every sidebar thread change
    • Replaced the prewarmedSidebarThreads memo (which depended on the frequently-changing sidebarThreadByKey map) with prewarmedSidebarThreadRefs that uses parseScopedThreadKey to extract stable identity pairs directly from prewarmedSidebarThreadKeys, breaking the dependency chain that caused unnecessary effect re-runs on every thread summary update.

Create PR

Or push these changes by commenting:

@cursor push 1017cc1156
Preview (1017cc1156)
diff --git a/apps/web/src/components/Sidebar.tsx b/apps/web/src/components/Sidebar.tsx--- a/apps/web/src/components/Sidebar.tsx+++ b/apps/web/src/components/Sidebar.tsx@@ -43,6 +43,7 @@
type GitStatusResult,
} from "@t3tools/contracts";
import {
+ parseScopedThreadKey,
scopedProjectKey,
scopedThreadKey,
scopeProjectRef,
@@ -2884,18 +2885,18 @@
() => getSidebarThreadIdsToPrewarm(visibleSidebarThreadKeys),
[visibleSidebarThreadKeys],
);
- const prewarmedSidebarThreads = useMemo(+ const prewarmedSidebarThreadRefs = useMemo(
() =>
prewarmedSidebarThreadKeys.flatMap((threadKey) => {
- const thread = sidebarThreadByKey.get(threadKey);- return thread ? [thread] : [];+ const ref = parseScopedThreadKey(threadKey);+ return ref ? [ref] : [];
}),
- [prewarmedSidebarThreadKeys, sidebarThreadByKey],+ [prewarmedSidebarThreadKeys],
);
useEffect(() => {
- const releases = prewarmedSidebarThreads.map((thread) =>- retainThreadDetailSubscription(thread.environmentId, thread.id),+ const releases = prewarmedSidebarThreadRefs.map((ref) =>+ retainThreadDetailSubscription(ref.environmentId, ref.threadId),
);
return () => {
@@ -2903,7 +2904,7 @@
release();
}
};
- }, [prewarmedSidebarThreads]);+ }, [prewarmedSidebarThreadRefs]);
useEffect(() => {
const clearThreadJumpHints = () => {

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit 9284b86. Configure here.

Comment threadapps/web/src/components/Sidebar.tsx Outdated
@macroscopeapp

macroscopeappBot commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new feature that proactively warms thread subscriptions for visible sidebar items and significantly changes the subscription cache policy (longer TTL, larger cache, sticky non-idle threads). While the author owns this code and changes are well-tested, this is a new capability with runtime behavior implications around network subscriptions and resource management that warrants human review.

You can customize Macroscope's approvability policy. Learn more.

@juliusmarminge

Copy link
Copy Markdown
MemberAuthor

@cursor push 1017cc1

…s on thread summary changes
The prewarmedSidebarThreads memo depended on sidebarThreadByKey, which is
recreated whenever any sidebar thread summary changes. Since the useEffect
only needs environmentId and threadId (stable identities), this caused
unnecessary cleanup/re-setup cycles for all prewarm subscriptions on every
thread status update.
Replace the thread-object lookup with parseScopedThreadKey to extract
identity pairs directly from the already-stable prewarmedSidebarThreadKeys,
breaking the dependency on the frequently-changing sidebarThreadByKey map.
Applied via @cursor push command
@juliusmarminge
juliusmarminge merged commit 569fea8 into mainApr 13, 2026
12 checks passed
@juliusmarminge
juliusmarminge deleted the t3code/thread-subscription-cache-policy branch April 13, 2026 20:55
juliusmarminge added a commit that referenced this pull request Apr 13, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
aaditagrawal added a commit to aaditagrawal/t3code that referenced this pull request Apr 16, 2026
Integrates upstream/main (d22c6f5) into the fork while preserving all
multi-provider support (codex, claudeAgent, copilot, cursor, opencode,
geminiCli, amp, kilo) and fork UI/UX additions.
Highlights adopted from upstream:
- Nightly release channel + update channel selector (pingdotgg#2012, pingdotgg#2049, pingdotgg#1969)
- Filesystem browse API + command palette project picker (pingdotgg#2024)
- Launch Args setting for Claude provider (pingdotgg#1971)
- Kiro editor support in open picker (pingdotgg#1974)
- Claude plan events for TodoWrite during input streaming (pingdotgg#1541)
- Lost provider session recovery (pingdotgg#1938)
- Cache provider status and gate desktop startup (pingdotgg#1962)
- LegendList migration for chat scrolling and branch lists (pingdotgg#1953)
- Shell snapshot queries + backfill migration (pingdotgg#1973, pingdotgg#2004)
- PATH hydration + fallback detection (pingdotgg#1799)
- Warm sidebar thread subscriptions (pingdotgg#2001)
- Full thread title tooltip (pingdotgg#1994)
- Markdown file link UX (pingdotgg#1956), composer polish (pingdotgg#1944, pingdotgg#1992, pingdotgg#1985)
- Worktree/branch state + draft reuse fixes (pingdotgg#2005, pingdotgg#2003, pingdotgg#1995, pingdotgg#1936)
- Window controls overlay for Windows/Linux (pingdotgg#1969)
- Backend readiness timeout 10s→30s (pingdotgg#1979)
- Clear tracked RPCs on reconnect, live stream subscriptions (pingdotgg#2000, pingdotgg#1972)
- Various misc fixes (pingdotgg#2051, pingdotgg#2052, pingdotgg#2025, pingdotgg#2027, pingdotgg#2049, pingdotgg#1997, pingdotgg#1975)
Fork features preserved and reconciled:
- All 8 provider adapters + conformance tests
- Extended ProviderKind union across contracts/model/settings/provider
- appearance/accentColor/themeConfig/ProviderLogo UI system
- customModels + gitTextGeneration + providerModelOptions
- Migration IDs 23 (NormalizeLegacyProviderKinds) and 24
(RepairProjectionThreadProposedPlanImplementationColumns) kept; new
upstream migrations registered at IDs 25-26 to avoid breaking deployed
fork databases
- DesktopBridge: log directory channels (LOG_DIR/LIST/READ/OPEN_DIR)
retained; getWsUrl replaced by upstream's getAppBranding
- PROVIDER_CACHE_IDS extended to all 8 providers
znoraka pushed a commit to znoraka/t3code that referenced this pull request Apr 17, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
NeilTheFisher pushed a commit to NeilTheFisher/t3code that referenced this pull request Aug 18, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
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:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@juliusmarminge@cursoragent
, '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

Warm sidebar thread detail subscriptions - #2001

Merged
juliusmarminge merged 2 commits into
mainfrom
t3code/thread-subscription-cache-policy
Apr 13, 2026
Merged

Warm sidebar thread detail subscriptions#2001
juliusmarminge merged 2 commits into
mainfrom
t3code/thread-subscription-cache-policy

Conversation

@juliusmarminge

@juliusmarmingejuliusmarminge commented Apr 13, 2026

Copy link
Copy Markdown
Member

Summary

  • Prewarm thread detail subscriptions for the first visible sidebar threads so nearby navigation can reuse hot data.
  • Extend the thread-detail cache policy to keep non-idle threads sticky and only evict idle subscriptions.
  • Increase the idle TTL and cache capacity to reduce churn while navigating and working in active threads.
  • Add tests for sidebar prewarm selection and the updated subscription eviction behavior.

Testing

  • bun fmt
  • bun lint
  • bun typecheck
  • bun run test apps/web/src/components/Sidebar.logic.test.ts
  • bun run test apps/web/src/environments/runtime/service.threadSubscriptions.test.ts

Note

Medium Risk
Changes thread-detail subscription caching/eviction and adds background prewarming from the sidebar, which can affect memory/network usage and when subscriptions are released. Logic now depends on thread activity state to prevent eviction, so regressions could keep subscriptions alive longer than intended.

Overview
Prewarms thread-detail data for the first visible sidebar threads by retaining their detail subscriptions (default 10) while they remain visible, releasing them when the visible set changes.

Updates the runtime thread-detail subscription cache policy to be stickier for non-idle threads (pending approvals/input/plan, running turns, or non-idle orchestration), and to evict only idle unretained entries; idle TTL increases to 15 minutes and cache capacity to 32.

Adds unit tests covering getSidebarThreadIdsToPrewarm and the new eviction behavior (longer warm period, non-idle stickiness, and increased capacity before eviction).

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

Note

Warm thread detail subscriptions for visible sidebar threads

  • The sidebar now retains thread detail subscriptions for up to 10 visible threads (SIDEBAR_THREAD_PREWARM_LIMIT) using retainThreadDetailSubscription, releasing them when threads leave the prewarmed set.
  • The thread detail subscription cache is expanded from 8 to 32 entries and the idle eviction timeout is increased from 2 to 15 minutes.
  • Non-idle threads (pending approvals, running turns, etc.) are exempt from eviction via a new isNonIdleThreadDetailSubscription helper in service.ts; eviction is deferred until the thread becomes idle.
  • Eviction schedules are reconciled after shell snapshot syncs, recovered event batches, and shell upserts to keep cache state consistent.
  • Behavioral Change: releasing a subscription no longer always schedules eviction — non-idle threads remain cached until idle, and capacity eviction only removes the least-recently-accessed idle entries.

Macroscope summarized a4afe8c.

- Prewarm visible sidebar threads
- Keep active thread subscriptions sticky until idle
- Expand cache capacity and add coverage
@coderabbitai

coderabbitaiBot commented Apr 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

Run ID: 65d2f790-b9a8-4a72-937c-a2601d27dbcc

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
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch t3code/thread-subscription-cache-policy

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

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels Apr 13, 2026

@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 and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Prewarm effect re-runs on every sidebar thread change
    • Replaced the prewarmedSidebarThreads memo (which depended on the frequently-changing sidebarThreadByKey map) with prewarmedSidebarThreadRefs that uses parseScopedThreadKey to extract stable identity pairs directly from prewarmedSidebarThreadKeys, breaking the dependency chain that caused unnecessary effect re-runs on every thread summary update.

Create PR

Or push these changes by commenting:

@cursor push 1017cc1156
Preview (1017cc1156)
diff --git a/apps/web/src/components/Sidebar.tsx b/apps/web/src/components/Sidebar.tsx--- a/apps/web/src/components/Sidebar.tsx+++ b/apps/web/src/components/Sidebar.tsx@@ -43,6 +43,7 @@
type GitStatusResult,
} from "@t3tools/contracts";
import {
+ parseScopedThreadKey,
scopedProjectKey,
scopedThreadKey,
scopeProjectRef,
@@ -2884,18 +2885,18 @@
() => getSidebarThreadIdsToPrewarm(visibleSidebarThreadKeys),
[visibleSidebarThreadKeys],
);
- const prewarmedSidebarThreads = useMemo(+ const prewarmedSidebarThreadRefs = useMemo(
() =>
prewarmedSidebarThreadKeys.flatMap((threadKey) => {
- const thread = sidebarThreadByKey.get(threadKey);- return thread ? [thread] : [];+ const ref = parseScopedThreadKey(threadKey);+ return ref ? [ref] : [];
}),
- [prewarmedSidebarThreadKeys, sidebarThreadByKey],+ [prewarmedSidebarThreadKeys],
);
useEffect(() => {
- const releases = prewarmedSidebarThreads.map((thread) =>- retainThreadDetailSubscription(thread.environmentId, thread.id),+ const releases = prewarmedSidebarThreadRefs.map((ref) =>+ retainThreadDetailSubscription(ref.environmentId, ref.threadId),
);
return () => {
@@ -2903,7 +2904,7 @@
release();
}
};
- }, [prewarmedSidebarThreads]);+ }, [prewarmedSidebarThreadRefs]);
useEffect(() => {
const clearThreadJumpHints = () => {

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit 9284b86. Configure here.

Comment threadapps/web/src/components/Sidebar.tsx Outdated
@macroscopeapp

macroscopeappBot commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new feature that proactively warms thread subscriptions for visible sidebar items and significantly changes the subscription cache policy (longer TTL, larger cache, sticky non-idle threads). While the author owns this code and changes are well-tested, this is a new capability with runtime behavior implications around network subscriptions and resource management that warrants human review.

You can customize Macroscope's approvability policy. Learn more.

@juliusmarminge

Copy link
Copy Markdown
MemberAuthor

@cursor push 1017cc1

…s on thread summary changes
The prewarmedSidebarThreads memo depended on sidebarThreadByKey, which is
recreated whenever any sidebar thread summary changes. Since the useEffect
only needs environmentId and threadId (stable identities), this caused
unnecessary cleanup/re-setup cycles for all prewarm subscriptions on every
thread status update.
Replace the thread-object lookup with parseScopedThreadKey to extract
identity pairs directly from the already-stable prewarmedSidebarThreadKeys,
breaking the dependency on the frequently-changing sidebarThreadByKey map.
Applied via @cursor push command
@juliusmarminge
juliusmarminge merged commit 569fea8 into mainApr 13, 2026
12 checks passed
@juliusmarminge
juliusmarminge deleted the t3code/thread-subscription-cache-policy branch April 13, 2026 20:55
juliusmarminge added a commit that referenced this pull request Apr 13, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
aaditagrawal added a commit to aaditagrawal/t3code that referenced this pull request Apr 16, 2026
Integrates upstream/main (d22c6f5) into the fork while preserving all
multi-provider support (codex, claudeAgent, copilot, cursor, opencode,
geminiCli, amp, kilo) and fork UI/UX additions.
Highlights adopted from upstream:
- Nightly release channel + update channel selector (pingdotgg#2012, pingdotgg#2049, pingdotgg#1969)
- Filesystem browse API + command palette project picker (pingdotgg#2024)
- Launch Args setting for Claude provider (pingdotgg#1971)
- Kiro editor support in open picker (pingdotgg#1974)
- Claude plan events for TodoWrite during input streaming (pingdotgg#1541)
- Lost provider session recovery (pingdotgg#1938)
- Cache provider status and gate desktop startup (pingdotgg#1962)
- LegendList migration for chat scrolling and branch lists (pingdotgg#1953)
- Shell snapshot queries + backfill migration (pingdotgg#1973, pingdotgg#2004)
- PATH hydration + fallback detection (pingdotgg#1799)
- Warm sidebar thread subscriptions (pingdotgg#2001)
- Full thread title tooltip (pingdotgg#1994)
- Markdown file link UX (pingdotgg#1956), composer polish (pingdotgg#1944, pingdotgg#1992, pingdotgg#1985)
- Worktree/branch state + draft reuse fixes (pingdotgg#2005, pingdotgg#2003, pingdotgg#1995, pingdotgg#1936)
- Window controls overlay for Windows/Linux (pingdotgg#1969)
- Backend readiness timeout 10s→30s (pingdotgg#1979)
- Clear tracked RPCs on reconnect, live stream subscriptions (pingdotgg#2000, pingdotgg#1972)
- Various misc fixes (pingdotgg#2051, pingdotgg#2052, pingdotgg#2025, pingdotgg#2027, pingdotgg#2049, pingdotgg#1997, pingdotgg#1975)
Fork features preserved and reconciled:
- All 8 provider adapters + conformance tests
- Extended ProviderKind union across contracts/model/settings/provider
- appearance/accentColor/themeConfig/ProviderLogo UI system
- customModels + gitTextGeneration + providerModelOptions
- Migration IDs 23 (NormalizeLegacyProviderKinds) and 24
(RepairProjectionThreadProposedPlanImplementationColumns) kept; new
upstream migrations registered at IDs 25-26 to avoid breaking deployed
fork databases
- DesktopBridge: log directory channels (LOG_DIR/LIST/READ/OPEN_DIR)
retained; getWsUrl replaced by upstream's getAppBranding
- PROVIDER_CACHE_IDS extended to all 8 providers
znoraka pushed a commit to znoraka/t3code that referenced this pull request Apr 17, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
NeilTheFisher pushed a commit to NeilTheFisher/t3code that referenced this pull request Aug 18, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
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:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@juliusmarminge@cursoragent
, '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

Warm sidebar thread detail subscriptions - #2001

Merged
juliusmarminge merged 2 commits into
mainfrom
t3code/thread-subscription-cache-policy
Apr 13, 2026
Merged

Warm sidebar thread detail subscriptions#2001
juliusmarminge merged 2 commits into
mainfrom
t3code/thread-subscription-cache-policy

Conversation

@juliusmarminge

@juliusmarmingejuliusmarminge commented Apr 13, 2026

Copy link
Copy Markdown
Member

Summary

  • Prewarm thread detail subscriptions for the first visible sidebar threads so nearby navigation can reuse hot data.
  • Extend the thread-detail cache policy to keep non-idle threads sticky and only evict idle subscriptions.
  • Increase the idle TTL and cache capacity to reduce churn while navigating and working in active threads.
  • Add tests for sidebar prewarm selection and the updated subscription eviction behavior.

Testing

  • bun fmt
  • bun lint
  • bun typecheck
  • bun run test apps/web/src/components/Sidebar.logic.test.ts
  • bun run test apps/web/src/environments/runtime/service.threadSubscriptions.test.ts

Note

Medium Risk
Changes thread-detail subscription caching/eviction and adds background prewarming from the sidebar, which can affect memory/network usage and when subscriptions are released. Logic now depends on thread activity state to prevent eviction, so regressions could keep subscriptions alive longer than intended.

Overview
Prewarms thread-detail data for the first visible sidebar threads by retaining their detail subscriptions (default 10) while they remain visible, releasing them when the visible set changes.

Updates the runtime thread-detail subscription cache policy to be stickier for non-idle threads (pending approvals/input/plan, running turns, or non-idle orchestration), and to evict only idle unretained entries; idle TTL increases to 15 minutes and cache capacity to 32.

Adds unit tests covering getSidebarThreadIdsToPrewarm and the new eviction behavior (longer warm period, non-idle stickiness, and increased capacity before eviction).

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

Note

Warm thread detail subscriptions for visible sidebar threads

  • The sidebar now retains thread detail subscriptions for up to 10 visible threads (SIDEBAR_THREAD_PREWARM_LIMIT) using retainThreadDetailSubscription, releasing them when threads leave the prewarmed set.
  • The thread detail subscription cache is expanded from 8 to 32 entries and the idle eviction timeout is increased from 2 to 15 minutes.
  • Non-idle threads (pending approvals, running turns, etc.) are exempt from eviction via a new isNonIdleThreadDetailSubscription helper in service.ts; eviction is deferred until the thread becomes idle.
  • Eviction schedules are reconciled after shell snapshot syncs, recovered event batches, and shell upserts to keep cache state consistent.
  • Behavioral Change: releasing a subscription no longer always schedules eviction — non-idle threads remain cached until idle, and capacity eviction only removes the least-recently-accessed idle entries.

Macroscope summarized a4afe8c.

- Prewarm visible sidebar threads
- Keep active thread subscriptions sticky until idle
- Expand cache capacity and add coverage
@coderabbitai

coderabbitaiBot commented Apr 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

Run ID: 65d2f790-b9a8-4a72-937c-a2601d27dbcc

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
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch t3code/thread-subscription-cache-policy

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

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels Apr 13, 2026

@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 and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Prewarm effect re-runs on every sidebar thread change
    • Replaced the prewarmedSidebarThreads memo (which depended on the frequently-changing sidebarThreadByKey map) with prewarmedSidebarThreadRefs that uses parseScopedThreadKey to extract stable identity pairs directly from prewarmedSidebarThreadKeys, breaking the dependency chain that caused unnecessary effect re-runs on every thread summary update.

Create PR

Or push these changes by commenting:

@cursor push 1017cc1156
Preview (1017cc1156)
diff --git a/apps/web/src/components/Sidebar.tsx b/apps/web/src/components/Sidebar.tsx--- a/apps/web/src/components/Sidebar.tsx+++ b/apps/web/src/components/Sidebar.tsx@@ -43,6 +43,7 @@
type GitStatusResult,
} from "@t3tools/contracts";
import {
+ parseScopedThreadKey,
scopedProjectKey,
scopedThreadKey,
scopeProjectRef,
@@ -2884,18 +2885,18 @@
() => getSidebarThreadIdsToPrewarm(visibleSidebarThreadKeys),
[visibleSidebarThreadKeys],
);
- const prewarmedSidebarThreads = useMemo(+ const prewarmedSidebarThreadRefs = useMemo(
() =>
prewarmedSidebarThreadKeys.flatMap((threadKey) => {
- const thread = sidebarThreadByKey.get(threadKey);- return thread ? [thread] : [];+ const ref = parseScopedThreadKey(threadKey);+ return ref ? [ref] : [];
}),
- [prewarmedSidebarThreadKeys, sidebarThreadByKey],+ [prewarmedSidebarThreadKeys],
);
useEffect(() => {
- const releases = prewarmedSidebarThreads.map((thread) =>- retainThreadDetailSubscription(thread.environmentId, thread.id),+ const releases = prewarmedSidebarThreadRefs.map((ref) =>+ retainThreadDetailSubscription(ref.environmentId, ref.threadId),
);
return () => {
@@ -2903,7 +2904,7 @@
release();
}
};
- }, [prewarmedSidebarThreads]);+ }, [prewarmedSidebarThreadRefs]);
useEffect(() => {
const clearThreadJumpHints = () => {

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit 9284b86. Configure here.

Comment threadapps/web/src/components/Sidebar.tsx Outdated
@macroscopeapp

macroscopeappBot commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new feature that proactively warms thread subscriptions for visible sidebar items and significantly changes the subscription cache policy (longer TTL, larger cache, sticky non-idle threads). While the author owns this code and changes are well-tested, this is a new capability with runtime behavior implications around network subscriptions and resource management that warrants human review.

You can customize Macroscope's approvability policy. Learn more.

@juliusmarminge

Copy link
Copy Markdown
MemberAuthor

@cursor push 1017cc1

…s on thread summary changes
The prewarmedSidebarThreads memo depended on sidebarThreadByKey, which is
recreated whenever any sidebar thread summary changes. Since the useEffect
only needs environmentId and threadId (stable identities), this caused
unnecessary cleanup/re-setup cycles for all prewarm subscriptions on every
thread status update.
Replace the thread-object lookup with parseScopedThreadKey to extract
identity pairs directly from the already-stable prewarmedSidebarThreadKeys,
breaking the dependency on the frequently-changing sidebarThreadByKey map.
Applied via @cursor push command
@juliusmarminge
juliusmarminge merged commit 569fea8 into mainApr 13, 2026
12 checks passed
@juliusmarminge
juliusmarminge deleted the t3code/thread-subscription-cache-policy branch April 13, 2026 20:55
juliusmarminge added a commit that referenced this pull request Apr 13, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
aaditagrawal added a commit to aaditagrawal/t3code that referenced this pull request Apr 16, 2026
Integrates upstream/main (d22c6f5) into the fork while preserving all
multi-provider support (codex, claudeAgent, copilot, cursor, opencode,
geminiCli, amp, kilo) and fork UI/UX additions.
Highlights adopted from upstream:
- Nightly release channel + update channel selector (pingdotgg#2012, pingdotgg#2049, pingdotgg#1969)
- Filesystem browse API + command palette project picker (pingdotgg#2024)
- Launch Args setting for Claude provider (pingdotgg#1971)
- Kiro editor support in open picker (pingdotgg#1974)
- Claude plan events for TodoWrite during input streaming (pingdotgg#1541)
- Lost provider session recovery (pingdotgg#1938)
- Cache provider status and gate desktop startup (pingdotgg#1962)
- LegendList migration for chat scrolling and branch lists (pingdotgg#1953)
- Shell snapshot queries + backfill migration (pingdotgg#1973, pingdotgg#2004)
- PATH hydration + fallback detection (pingdotgg#1799)
- Warm sidebar thread subscriptions (pingdotgg#2001)
- Full thread title tooltip (pingdotgg#1994)
- Markdown file link UX (pingdotgg#1956), composer polish (pingdotgg#1944, pingdotgg#1992, pingdotgg#1985)
- Worktree/branch state + draft reuse fixes (pingdotgg#2005, pingdotgg#2003, pingdotgg#1995, pingdotgg#1936)
- Window controls overlay for Windows/Linux (pingdotgg#1969)
- Backend readiness timeout 10s→30s (pingdotgg#1979)
- Clear tracked RPCs on reconnect, live stream subscriptions (pingdotgg#2000, pingdotgg#1972)
- Various misc fixes (pingdotgg#2051, pingdotgg#2052, pingdotgg#2025, pingdotgg#2027, pingdotgg#2049, pingdotgg#1997, pingdotgg#1975)
Fork features preserved and reconciled:
- All 8 provider adapters + conformance tests
- Extended ProviderKind union across contracts/model/settings/provider
- appearance/accentColor/themeConfig/ProviderLogo UI system
- customModels + gitTextGeneration + providerModelOptions
- Migration IDs 23 (NormalizeLegacyProviderKinds) and 24
(RepairProjectionThreadProposedPlanImplementationColumns) kept; new
upstream migrations registered at IDs 25-26 to avoid breaking deployed
fork databases
- DesktopBridge: log directory channels (LOG_DIR/LIST/READ/OPEN_DIR)
retained; getWsUrl replaced by upstream's getAppBranding
- PROVIDER_CACHE_IDS extended to all 8 providers
znoraka pushed a commit to znoraka/t3code that referenced this pull request Apr 17, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
NeilTheFisher pushed a commit to NeilTheFisher/t3code that referenced this pull request Aug 18, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
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:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@juliusmarminge@cursoragent
, '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

Warm sidebar thread detail subscriptions - #2001

Merged
juliusmarminge merged 2 commits into
mainfrom
t3code/thread-subscription-cache-policy
Apr 13, 2026
Merged

Warm sidebar thread detail subscriptions#2001
juliusmarminge merged 2 commits into
mainfrom
t3code/thread-subscription-cache-policy

Conversation

@juliusmarminge

@juliusmarmingejuliusmarminge commented Apr 13, 2026

Copy link
Copy Markdown
Member

Summary

  • Prewarm thread detail subscriptions for the first visible sidebar threads so nearby navigation can reuse hot data.
  • Extend the thread-detail cache policy to keep non-idle threads sticky and only evict idle subscriptions.
  • Increase the idle TTL and cache capacity to reduce churn while navigating and working in active threads.
  • Add tests for sidebar prewarm selection and the updated subscription eviction behavior.

Testing

  • bun fmt
  • bun lint
  • bun typecheck
  • bun run test apps/web/src/components/Sidebar.logic.test.ts
  • bun run test apps/web/src/environments/runtime/service.threadSubscriptions.test.ts

Note

Medium Risk
Changes thread-detail subscription caching/eviction and adds background prewarming from the sidebar, which can affect memory/network usage and when subscriptions are released. Logic now depends on thread activity state to prevent eviction, so regressions could keep subscriptions alive longer than intended.

Overview
Prewarms thread-detail data for the first visible sidebar threads by retaining their detail subscriptions (default 10) while they remain visible, releasing them when the visible set changes.

Updates the runtime thread-detail subscription cache policy to be stickier for non-idle threads (pending approvals/input/plan, running turns, or non-idle orchestration), and to evict only idle unretained entries; idle TTL increases to 15 minutes and cache capacity to 32.

Adds unit tests covering getSidebarThreadIdsToPrewarm and the new eviction behavior (longer warm period, non-idle stickiness, and increased capacity before eviction).

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

Note

Warm thread detail subscriptions for visible sidebar threads

  • The sidebar now retains thread detail subscriptions for up to 10 visible threads (SIDEBAR_THREAD_PREWARM_LIMIT) using retainThreadDetailSubscription, releasing them when threads leave the prewarmed set.
  • The thread detail subscription cache is expanded from 8 to 32 entries and the idle eviction timeout is increased from 2 to 15 minutes.
  • Non-idle threads (pending approvals, running turns, etc.) are exempt from eviction via a new isNonIdleThreadDetailSubscription helper in service.ts; eviction is deferred until the thread becomes idle.
  • Eviction schedules are reconciled after shell snapshot syncs, recovered event batches, and shell upserts to keep cache state consistent.
  • Behavioral Change: releasing a subscription no longer always schedules eviction — non-idle threads remain cached until idle, and capacity eviction only removes the least-recently-accessed idle entries.

Macroscope summarized a4afe8c.

- Prewarm visible sidebar threads
- Keep active thread subscriptions sticky until idle
- Expand cache capacity and add coverage
@coderabbitai

coderabbitaiBot commented Apr 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

Run ID: 65d2f790-b9a8-4a72-937c-a2601d27dbcc

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
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch t3code/thread-subscription-cache-policy

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

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels Apr 13, 2026

@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 and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Prewarm effect re-runs on every sidebar thread change
    • Replaced the prewarmedSidebarThreads memo (which depended on the frequently-changing sidebarThreadByKey map) with prewarmedSidebarThreadRefs that uses parseScopedThreadKey to extract stable identity pairs directly from prewarmedSidebarThreadKeys, breaking the dependency chain that caused unnecessary effect re-runs on every thread summary update.

Create PR

Or push these changes by commenting:

@cursor push 1017cc1156
Preview (1017cc1156)
diff --git a/apps/web/src/components/Sidebar.tsx b/apps/web/src/components/Sidebar.tsx--- a/apps/web/src/components/Sidebar.tsx+++ b/apps/web/src/components/Sidebar.tsx@@ -43,6 +43,7 @@
type GitStatusResult,
} from "@t3tools/contracts";
import {
+ parseScopedThreadKey,
scopedProjectKey,
scopedThreadKey,
scopeProjectRef,
@@ -2884,18 +2885,18 @@
() => getSidebarThreadIdsToPrewarm(visibleSidebarThreadKeys),
[visibleSidebarThreadKeys],
);
- const prewarmedSidebarThreads = useMemo(+ const prewarmedSidebarThreadRefs = useMemo(
() =>
prewarmedSidebarThreadKeys.flatMap((threadKey) => {
- const thread = sidebarThreadByKey.get(threadKey);- return thread ? [thread] : [];+ const ref = parseScopedThreadKey(threadKey);+ return ref ? [ref] : [];
}),
- [prewarmedSidebarThreadKeys, sidebarThreadByKey],+ [prewarmedSidebarThreadKeys],
);
useEffect(() => {
- const releases = prewarmedSidebarThreads.map((thread) =>- retainThreadDetailSubscription(thread.environmentId, thread.id),+ const releases = prewarmedSidebarThreadRefs.map((ref) =>+ retainThreadDetailSubscription(ref.environmentId, ref.threadId),
);
return () => {
@@ -2903,7 +2904,7 @@
release();
}
};
- }, [prewarmedSidebarThreads]);+ }, [prewarmedSidebarThreadRefs]);
useEffect(() => {
const clearThreadJumpHints = () => {

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit 9284b86. Configure here.

Comment threadapps/web/src/components/Sidebar.tsx Outdated
@macroscopeapp

macroscopeappBot commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new feature that proactively warms thread subscriptions for visible sidebar items and significantly changes the subscription cache policy (longer TTL, larger cache, sticky non-idle threads). While the author owns this code and changes are well-tested, this is a new capability with runtime behavior implications around network subscriptions and resource management that warrants human review.

You can customize Macroscope's approvability policy. Learn more.

@juliusmarminge

Copy link
Copy Markdown
MemberAuthor

@cursor push 1017cc1

…s on thread summary changes
The prewarmedSidebarThreads memo depended on sidebarThreadByKey, which is
recreated whenever any sidebar thread summary changes. Since the useEffect
only needs environmentId and threadId (stable identities), this caused
unnecessary cleanup/re-setup cycles for all prewarm subscriptions on every
thread status update.
Replace the thread-object lookup with parseScopedThreadKey to extract
identity pairs directly from the already-stable prewarmedSidebarThreadKeys,
breaking the dependency on the frequently-changing sidebarThreadByKey map.
Applied via @cursor push command
@juliusmarminge
juliusmarminge merged commit 569fea8 into mainApr 13, 2026
12 checks passed
@juliusmarminge
juliusmarminge deleted the t3code/thread-subscription-cache-policy branch April 13, 2026 20:55
juliusmarminge added a commit that referenced this pull request Apr 13, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
aaditagrawal added a commit to aaditagrawal/t3code that referenced this pull request Apr 16, 2026
Integrates upstream/main (d22c6f5) into the fork while preserving all
multi-provider support (codex, claudeAgent, copilot, cursor, opencode,
geminiCli, amp, kilo) and fork UI/UX additions.
Highlights adopted from upstream:
- Nightly release channel + update channel selector (pingdotgg#2012, pingdotgg#2049, pingdotgg#1969)
- Filesystem browse API + command palette project picker (pingdotgg#2024)
- Launch Args setting for Claude provider (pingdotgg#1971)
- Kiro editor support in open picker (pingdotgg#1974)
- Claude plan events for TodoWrite during input streaming (pingdotgg#1541)
- Lost provider session recovery (pingdotgg#1938)
- Cache provider status and gate desktop startup (pingdotgg#1962)
- LegendList migration for chat scrolling and branch lists (pingdotgg#1953)
- Shell snapshot queries + backfill migration (pingdotgg#1973, pingdotgg#2004)
- PATH hydration + fallback detection (pingdotgg#1799)
- Warm sidebar thread subscriptions (pingdotgg#2001)
- Full thread title tooltip (pingdotgg#1994)
- Markdown file link UX (pingdotgg#1956), composer polish (pingdotgg#1944, pingdotgg#1992, pingdotgg#1985)
- Worktree/branch state + draft reuse fixes (pingdotgg#2005, pingdotgg#2003, pingdotgg#1995, pingdotgg#1936)
- Window controls overlay for Windows/Linux (pingdotgg#1969)
- Backend readiness timeout 10s→30s (pingdotgg#1979)
- Clear tracked RPCs on reconnect, live stream subscriptions (pingdotgg#2000, pingdotgg#1972)
- Various misc fixes (pingdotgg#2051, pingdotgg#2052, pingdotgg#2025, pingdotgg#2027, pingdotgg#2049, pingdotgg#1997, pingdotgg#1975)
Fork features preserved and reconciled:
- All 8 provider adapters + conformance tests
- Extended ProviderKind union across contracts/model/settings/provider
- appearance/accentColor/themeConfig/ProviderLogo UI system
- customModels + gitTextGeneration + providerModelOptions
- Migration IDs 23 (NormalizeLegacyProviderKinds) and 24
(RepairProjectionThreadProposedPlanImplementationColumns) kept; new
upstream migrations registered at IDs 25-26 to avoid breaking deployed
fork databases
- DesktopBridge: log directory channels (LOG_DIR/LIST/READ/OPEN_DIR)
retained; getWsUrl replaced by upstream's getAppBranding
- PROVIDER_CACHE_IDS extended to all 8 providers
znoraka pushed a commit to znoraka/t3code that referenced this pull request Apr 17, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
NeilTheFisher pushed a commit to NeilTheFisher/t3code that referenced this pull request Aug 18, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
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:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@juliusmarminge@cursoragent
, '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

Warm sidebar thread detail subscriptions - #2001

Merged
juliusmarminge merged 2 commits into
mainfrom
t3code/thread-subscription-cache-policy
Apr 13, 2026
Merged

Warm sidebar thread detail subscriptions#2001
juliusmarminge merged 2 commits into
mainfrom
t3code/thread-subscription-cache-policy

Conversation

@juliusmarminge

@juliusmarmingejuliusmarminge commented Apr 13, 2026

Copy link
Copy Markdown
Member

Summary

  • Prewarm thread detail subscriptions for the first visible sidebar threads so nearby navigation can reuse hot data.
  • Extend the thread-detail cache policy to keep non-idle threads sticky and only evict idle subscriptions.
  • Increase the idle TTL and cache capacity to reduce churn while navigating and working in active threads.
  • Add tests for sidebar prewarm selection and the updated subscription eviction behavior.

Testing

  • bun fmt
  • bun lint
  • bun typecheck
  • bun run test apps/web/src/components/Sidebar.logic.test.ts
  • bun run test apps/web/src/environments/runtime/service.threadSubscriptions.test.ts

Note

Medium Risk
Changes thread-detail subscription caching/eviction and adds background prewarming from the sidebar, which can affect memory/network usage and when subscriptions are released. Logic now depends on thread activity state to prevent eviction, so regressions could keep subscriptions alive longer than intended.

Overview
Prewarms thread-detail data for the first visible sidebar threads by retaining their detail subscriptions (default 10) while they remain visible, releasing them when the visible set changes.

Updates the runtime thread-detail subscription cache policy to be stickier for non-idle threads (pending approvals/input/plan, running turns, or non-idle orchestration), and to evict only idle unretained entries; idle TTL increases to 15 minutes and cache capacity to 32.

Adds unit tests covering getSidebarThreadIdsToPrewarm and the new eviction behavior (longer warm period, non-idle stickiness, and increased capacity before eviction).

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

Note

Warm thread detail subscriptions for visible sidebar threads

  • The sidebar now retains thread detail subscriptions for up to 10 visible threads (SIDEBAR_THREAD_PREWARM_LIMIT) using retainThreadDetailSubscription, releasing them when threads leave the prewarmed set.
  • The thread detail subscription cache is expanded from 8 to 32 entries and the idle eviction timeout is increased from 2 to 15 minutes.
  • Non-idle threads (pending approvals, running turns, etc.) are exempt from eviction via a new isNonIdleThreadDetailSubscription helper in service.ts; eviction is deferred until the thread becomes idle.
  • Eviction schedules are reconciled after shell snapshot syncs, recovered event batches, and shell upserts to keep cache state consistent.
  • Behavioral Change: releasing a subscription no longer always schedules eviction — non-idle threads remain cached until idle, and capacity eviction only removes the least-recently-accessed idle entries.

Macroscope summarized a4afe8c.

- Prewarm visible sidebar threads
- Keep active thread subscriptions sticky until idle
- Expand cache capacity and add coverage
@coderabbitai

coderabbitaiBot commented Apr 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

Run ID: 65d2f790-b9a8-4a72-937c-a2601d27dbcc

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
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch t3code/thread-subscription-cache-policy

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

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels Apr 13, 2026

@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 and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Prewarm effect re-runs on every sidebar thread change
    • Replaced the prewarmedSidebarThreads memo (which depended on the frequently-changing sidebarThreadByKey map) with prewarmedSidebarThreadRefs that uses parseScopedThreadKey to extract stable identity pairs directly from prewarmedSidebarThreadKeys, breaking the dependency chain that caused unnecessary effect re-runs on every thread summary update.

Create PR

Or push these changes by commenting:

@cursor push 1017cc1156
Preview (1017cc1156)
diff --git a/apps/web/src/components/Sidebar.tsx b/apps/web/src/components/Sidebar.tsx--- a/apps/web/src/components/Sidebar.tsx+++ b/apps/web/src/components/Sidebar.tsx@@ -43,6 +43,7 @@
type GitStatusResult,
} from "@t3tools/contracts";
import {
+ parseScopedThreadKey,
scopedProjectKey,
scopedThreadKey,
scopeProjectRef,
@@ -2884,18 +2885,18 @@
() => getSidebarThreadIdsToPrewarm(visibleSidebarThreadKeys),
[visibleSidebarThreadKeys],
);
- const prewarmedSidebarThreads = useMemo(+ const prewarmedSidebarThreadRefs = useMemo(
() =>
prewarmedSidebarThreadKeys.flatMap((threadKey) => {
- const thread = sidebarThreadByKey.get(threadKey);- return thread ? [thread] : [];+ const ref = parseScopedThreadKey(threadKey);+ return ref ? [ref] : [];
}),
- [prewarmedSidebarThreadKeys, sidebarThreadByKey],+ [prewarmedSidebarThreadKeys],
);
useEffect(() => {
- const releases = prewarmedSidebarThreads.map((thread) =>- retainThreadDetailSubscription(thread.environmentId, thread.id),+ const releases = prewarmedSidebarThreadRefs.map((ref) =>+ retainThreadDetailSubscription(ref.environmentId, ref.threadId),
);
return () => {
@@ -2903,7 +2904,7 @@
release();
}
};
- }, [prewarmedSidebarThreads]);+ }, [prewarmedSidebarThreadRefs]);
useEffect(() => {
const clearThreadJumpHints = () => {

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit 9284b86. Configure here.

Comment threadapps/web/src/components/Sidebar.tsx Outdated
@macroscopeapp

macroscopeappBot commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new feature that proactively warms thread subscriptions for visible sidebar items and significantly changes the subscription cache policy (longer TTL, larger cache, sticky non-idle threads). While the author owns this code and changes are well-tested, this is a new capability with runtime behavior implications around network subscriptions and resource management that warrants human review.

You can customize Macroscope's approvability policy. Learn more.

@juliusmarminge

Copy link
Copy Markdown
MemberAuthor

@cursor push 1017cc1

…s on thread summary changes
The prewarmedSidebarThreads memo depended on sidebarThreadByKey, which is
recreated whenever any sidebar thread summary changes. Since the useEffect
only needs environmentId and threadId (stable identities), this caused
unnecessary cleanup/re-setup cycles for all prewarm subscriptions on every
thread status update.
Replace the thread-object lookup with parseScopedThreadKey to extract
identity pairs directly from the already-stable prewarmedSidebarThreadKeys,
breaking the dependency on the frequently-changing sidebarThreadByKey map.
Applied via @cursor push command
@juliusmarminge
juliusmarminge merged commit 569fea8 into mainApr 13, 2026
12 checks passed
@juliusmarminge
juliusmarminge deleted the t3code/thread-subscription-cache-policy branch April 13, 2026 20:55
juliusmarminge added a commit that referenced this pull request Apr 13, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
aaditagrawal added a commit to aaditagrawal/t3code that referenced this pull request Apr 16, 2026
Integrates upstream/main (d22c6f5) into the fork while preserving all
multi-provider support (codex, claudeAgent, copilot, cursor, opencode,
geminiCli, amp, kilo) and fork UI/UX additions.
Highlights adopted from upstream:
- Nightly release channel + update channel selector (pingdotgg#2012, pingdotgg#2049, pingdotgg#1969)
- Filesystem browse API + command palette project picker (pingdotgg#2024)
- Launch Args setting for Claude provider (pingdotgg#1971)
- Kiro editor support in open picker (pingdotgg#1974)
- Claude plan events for TodoWrite during input streaming (pingdotgg#1541)
- Lost provider session recovery (pingdotgg#1938)
- Cache provider status and gate desktop startup (pingdotgg#1962)
- LegendList migration for chat scrolling and branch lists (pingdotgg#1953)
- Shell snapshot queries + backfill migration (pingdotgg#1973, pingdotgg#2004)
- PATH hydration + fallback detection (pingdotgg#1799)
- Warm sidebar thread subscriptions (pingdotgg#2001)
- Full thread title tooltip (pingdotgg#1994)
- Markdown file link UX (pingdotgg#1956), composer polish (pingdotgg#1944, pingdotgg#1992, pingdotgg#1985)
- Worktree/branch state + draft reuse fixes (pingdotgg#2005, pingdotgg#2003, pingdotgg#1995, pingdotgg#1936)
- Window controls overlay for Windows/Linux (pingdotgg#1969)
- Backend readiness timeout 10s→30s (pingdotgg#1979)
- Clear tracked RPCs on reconnect, live stream subscriptions (pingdotgg#2000, pingdotgg#1972)
- Various misc fixes (pingdotgg#2051, pingdotgg#2052, pingdotgg#2025, pingdotgg#2027, pingdotgg#2049, pingdotgg#1997, pingdotgg#1975)
Fork features preserved and reconciled:
- All 8 provider adapters + conformance tests
- Extended ProviderKind union across contracts/model/settings/provider
- appearance/accentColor/themeConfig/ProviderLogo UI system
- customModels + gitTextGeneration + providerModelOptions
- Migration IDs 23 (NormalizeLegacyProviderKinds) and 24
(RepairProjectionThreadProposedPlanImplementationColumns) kept; new
upstream migrations registered at IDs 25-26 to avoid breaking deployed
fork databases
- DesktopBridge: log directory channels (LOG_DIR/LIST/READ/OPEN_DIR)
retained; getWsUrl replaced by upstream's getAppBranding
- PROVIDER_CACHE_IDS extended to all 8 providers
znoraka pushed a commit to znoraka/t3code that referenced this pull request Apr 17, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
NeilTheFisher pushed a commit to NeilTheFisher/t3code that referenced this pull request Aug 18, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
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:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@juliusmarminge@cursoragent
, '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

Warm sidebar thread detail subscriptions - #2001

Merged
juliusmarminge merged 2 commits into
mainfrom
t3code/thread-subscription-cache-policy
Apr 13, 2026
Merged

Warm sidebar thread detail subscriptions#2001
juliusmarminge merged 2 commits into
mainfrom
t3code/thread-subscription-cache-policy

Conversation

@juliusmarminge

@juliusmarmingejuliusmarminge commented Apr 13, 2026

Copy link
Copy Markdown
Member

Summary

  • Prewarm thread detail subscriptions for the first visible sidebar threads so nearby navigation can reuse hot data.
  • Extend the thread-detail cache policy to keep non-idle threads sticky and only evict idle subscriptions.
  • Increase the idle TTL and cache capacity to reduce churn while navigating and working in active threads.
  • Add tests for sidebar prewarm selection and the updated subscription eviction behavior.

Testing

  • bun fmt
  • bun lint
  • bun typecheck
  • bun run test apps/web/src/components/Sidebar.logic.test.ts
  • bun run test apps/web/src/environments/runtime/service.threadSubscriptions.test.ts

Note

Medium Risk
Changes thread-detail subscription caching/eviction and adds background prewarming from the sidebar, which can affect memory/network usage and when subscriptions are released. Logic now depends on thread activity state to prevent eviction, so regressions could keep subscriptions alive longer than intended.

Overview
Prewarms thread-detail data for the first visible sidebar threads by retaining their detail subscriptions (default 10) while they remain visible, releasing them when the visible set changes.

Updates the runtime thread-detail subscription cache policy to be stickier for non-idle threads (pending approvals/input/plan, running turns, or non-idle orchestration), and to evict only idle unretained entries; idle TTL increases to 15 minutes and cache capacity to 32.

Adds unit tests covering getSidebarThreadIdsToPrewarm and the new eviction behavior (longer warm period, non-idle stickiness, and increased capacity before eviction).

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

Note

Warm thread detail subscriptions for visible sidebar threads

  • The sidebar now retains thread detail subscriptions for up to 10 visible threads (SIDEBAR_THREAD_PREWARM_LIMIT) using retainThreadDetailSubscription, releasing them when threads leave the prewarmed set.
  • The thread detail subscription cache is expanded from 8 to 32 entries and the idle eviction timeout is increased from 2 to 15 minutes.
  • Non-idle threads (pending approvals, running turns, etc.) are exempt from eviction via a new isNonIdleThreadDetailSubscription helper in service.ts; eviction is deferred until the thread becomes idle.
  • Eviction schedules are reconciled after shell snapshot syncs, recovered event batches, and shell upserts to keep cache state consistent.
  • Behavioral Change: releasing a subscription no longer always schedules eviction — non-idle threads remain cached until idle, and capacity eviction only removes the least-recently-accessed idle entries.

Macroscope summarized a4afe8c.

- Prewarm visible sidebar threads
- Keep active thread subscriptions sticky until idle
- Expand cache capacity and add coverage
@coderabbitai

coderabbitaiBot commented Apr 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

Run ID: 65d2f790-b9a8-4a72-937c-a2601d27dbcc

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
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch t3code/thread-subscription-cache-policy

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

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels Apr 13, 2026

@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 and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Prewarm effect re-runs on every sidebar thread change
    • Replaced the prewarmedSidebarThreads memo (which depended on the frequently-changing sidebarThreadByKey map) with prewarmedSidebarThreadRefs that uses parseScopedThreadKey to extract stable identity pairs directly from prewarmedSidebarThreadKeys, breaking the dependency chain that caused unnecessary effect re-runs on every thread summary update.

Create PR

Or push these changes by commenting:

@cursor push 1017cc1156
Preview (1017cc1156)
diff --git a/apps/web/src/components/Sidebar.tsx b/apps/web/src/components/Sidebar.tsx--- a/apps/web/src/components/Sidebar.tsx+++ b/apps/web/src/components/Sidebar.tsx@@ -43,6 +43,7 @@
type GitStatusResult,
} from "@t3tools/contracts";
import {
+ parseScopedThreadKey,
scopedProjectKey,
scopedThreadKey,
scopeProjectRef,
@@ -2884,18 +2885,18 @@
() => getSidebarThreadIdsToPrewarm(visibleSidebarThreadKeys),
[visibleSidebarThreadKeys],
);
- const prewarmedSidebarThreads = useMemo(+ const prewarmedSidebarThreadRefs = useMemo(
() =>
prewarmedSidebarThreadKeys.flatMap((threadKey) => {
- const thread = sidebarThreadByKey.get(threadKey);- return thread ? [thread] : [];+ const ref = parseScopedThreadKey(threadKey);+ return ref ? [ref] : [];
}),
- [prewarmedSidebarThreadKeys, sidebarThreadByKey],+ [prewarmedSidebarThreadKeys],
);
useEffect(() => {
- const releases = prewarmedSidebarThreads.map((thread) =>- retainThreadDetailSubscription(thread.environmentId, thread.id),+ const releases = prewarmedSidebarThreadRefs.map((ref) =>+ retainThreadDetailSubscription(ref.environmentId, ref.threadId),
);
return () => {
@@ -2903,7 +2904,7 @@
release();
}
};
- }, [prewarmedSidebarThreads]);+ }, [prewarmedSidebarThreadRefs]);
useEffect(() => {
const clearThreadJumpHints = () => {

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit 9284b86. Configure here.

Comment threadapps/web/src/components/Sidebar.tsx Outdated
@macroscopeapp

macroscopeappBot commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new feature that proactively warms thread subscriptions for visible sidebar items and significantly changes the subscription cache policy (longer TTL, larger cache, sticky non-idle threads). While the author owns this code and changes are well-tested, this is a new capability with runtime behavior implications around network subscriptions and resource management that warrants human review.

You can customize Macroscope's approvability policy. Learn more.

@juliusmarminge

Copy link
Copy Markdown
MemberAuthor

@cursor push 1017cc1

…s on thread summary changes
The prewarmedSidebarThreads memo depended on sidebarThreadByKey, which is
recreated whenever any sidebar thread summary changes. Since the useEffect
only needs environmentId and threadId (stable identities), this caused
unnecessary cleanup/re-setup cycles for all prewarm subscriptions on every
thread status update.
Replace the thread-object lookup with parseScopedThreadKey to extract
identity pairs directly from the already-stable prewarmedSidebarThreadKeys,
breaking the dependency on the frequently-changing sidebarThreadByKey map.
Applied via @cursor push command
@juliusmarminge
juliusmarminge merged commit 569fea8 into mainApr 13, 2026
12 checks passed
@juliusmarminge
juliusmarminge deleted the t3code/thread-subscription-cache-policy branch April 13, 2026 20:55
juliusmarminge added a commit that referenced this pull request Apr 13, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
aaditagrawal added a commit to aaditagrawal/t3code that referenced this pull request Apr 16, 2026
Integrates upstream/main (d22c6f5) into the fork while preserving all
multi-provider support (codex, claudeAgent, copilot, cursor, opencode,
geminiCli, amp, kilo) and fork UI/UX additions.
Highlights adopted from upstream:
- Nightly release channel + update channel selector (pingdotgg#2012, pingdotgg#2049, pingdotgg#1969)
- Filesystem browse API + command palette project picker (pingdotgg#2024)
- Launch Args setting for Claude provider (pingdotgg#1971)
- Kiro editor support in open picker (pingdotgg#1974)
- Claude plan events for TodoWrite during input streaming (pingdotgg#1541)
- Lost provider session recovery (pingdotgg#1938)
- Cache provider status and gate desktop startup (pingdotgg#1962)
- LegendList migration for chat scrolling and branch lists (pingdotgg#1953)
- Shell snapshot queries + backfill migration (pingdotgg#1973, pingdotgg#2004)
- PATH hydration + fallback detection (pingdotgg#1799)
- Warm sidebar thread subscriptions (pingdotgg#2001)
- Full thread title tooltip (pingdotgg#1994)
- Markdown file link UX (pingdotgg#1956), composer polish (pingdotgg#1944, pingdotgg#1992, pingdotgg#1985)
- Worktree/branch state + draft reuse fixes (pingdotgg#2005, pingdotgg#2003, pingdotgg#1995, pingdotgg#1936)
- Window controls overlay for Windows/Linux (pingdotgg#1969)
- Backend readiness timeout 10s→30s (pingdotgg#1979)
- Clear tracked RPCs on reconnect, live stream subscriptions (pingdotgg#2000, pingdotgg#1972)
- Various misc fixes (pingdotgg#2051, pingdotgg#2052, pingdotgg#2025, pingdotgg#2027, pingdotgg#2049, pingdotgg#1997, pingdotgg#1975)
Fork features preserved and reconciled:
- All 8 provider adapters + conformance tests
- Extended ProviderKind union across contracts/model/settings/provider
- appearance/accentColor/themeConfig/ProviderLogo UI system
- customModels + gitTextGeneration + providerModelOptions
- Migration IDs 23 (NormalizeLegacyProviderKinds) and 24
(RepairProjectionThreadProposedPlanImplementationColumns) kept; new
upstream migrations registered at IDs 25-26 to avoid breaking deployed
fork databases
- DesktopBridge: log directory channels (LOG_DIR/LIST/READ/OPEN_DIR)
retained; getWsUrl replaced by upstream's getAppBranding
- PROVIDER_CACHE_IDS extended to all 8 providers
znoraka pushed a commit to znoraka/t3code that referenced this pull request Apr 17, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
NeilTheFisher pushed a commit to NeilTheFisher/t3code that referenced this pull request Aug 18, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
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:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@juliusmarminge@cursoragent
, '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

Warm sidebar thread detail subscriptions - #2001

Merged
juliusmarminge merged 2 commits into
mainfrom
t3code/thread-subscription-cache-policy
Apr 13, 2026
Merged

Warm sidebar thread detail subscriptions#2001
juliusmarminge merged 2 commits into
mainfrom
t3code/thread-subscription-cache-policy

Conversation

@juliusmarminge

@juliusmarmingejuliusmarminge commented Apr 13, 2026

Copy link
Copy Markdown
Member

Summary

  • Prewarm thread detail subscriptions for the first visible sidebar threads so nearby navigation can reuse hot data.
  • Extend the thread-detail cache policy to keep non-idle threads sticky and only evict idle subscriptions.
  • Increase the idle TTL and cache capacity to reduce churn while navigating and working in active threads.
  • Add tests for sidebar prewarm selection and the updated subscription eviction behavior.

Testing

  • bun fmt
  • bun lint
  • bun typecheck
  • bun run test apps/web/src/components/Sidebar.logic.test.ts
  • bun run test apps/web/src/environments/runtime/service.threadSubscriptions.test.ts

Note

Medium Risk
Changes thread-detail subscription caching/eviction and adds background prewarming from the sidebar, which can affect memory/network usage and when subscriptions are released. Logic now depends on thread activity state to prevent eviction, so regressions could keep subscriptions alive longer than intended.

Overview
Prewarms thread-detail data for the first visible sidebar threads by retaining their detail subscriptions (default 10) while they remain visible, releasing them when the visible set changes.

Updates the runtime thread-detail subscription cache policy to be stickier for non-idle threads (pending approvals/input/plan, running turns, or non-idle orchestration), and to evict only idle unretained entries; idle TTL increases to 15 minutes and cache capacity to 32.

Adds unit tests covering getSidebarThreadIdsToPrewarm and the new eviction behavior (longer warm period, non-idle stickiness, and increased capacity before eviction).

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

Note

Warm thread detail subscriptions for visible sidebar threads

  • The sidebar now retains thread detail subscriptions for up to 10 visible threads (SIDEBAR_THREAD_PREWARM_LIMIT) using retainThreadDetailSubscription, releasing them when threads leave the prewarmed set.
  • The thread detail subscription cache is expanded from 8 to 32 entries and the idle eviction timeout is increased from 2 to 15 minutes.
  • Non-idle threads (pending approvals, running turns, etc.) are exempt from eviction via a new isNonIdleThreadDetailSubscription helper in service.ts; eviction is deferred until the thread becomes idle.
  • Eviction schedules are reconciled after shell snapshot syncs, recovered event batches, and shell upserts to keep cache state consistent.
  • Behavioral Change: releasing a subscription no longer always schedules eviction — non-idle threads remain cached until idle, and capacity eviction only removes the least-recently-accessed idle entries.

Macroscope summarized a4afe8c.

- Prewarm visible sidebar threads
- Keep active thread subscriptions sticky until idle
- Expand cache capacity and add coverage
@coderabbitai

coderabbitaiBot commented Apr 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

Run ID: 65d2f790-b9a8-4a72-937c-a2601d27dbcc

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
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch t3code/thread-subscription-cache-policy

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

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels Apr 13, 2026

@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 and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Prewarm effect re-runs on every sidebar thread change
    • Replaced the prewarmedSidebarThreads memo (which depended on the frequently-changing sidebarThreadByKey map) with prewarmedSidebarThreadRefs that uses parseScopedThreadKey to extract stable identity pairs directly from prewarmedSidebarThreadKeys, breaking the dependency chain that caused unnecessary effect re-runs on every thread summary update.

Create PR

Or push these changes by commenting:

@cursor push 1017cc1156
Preview (1017cc1156)
diff --git a/apps/web/src/components/Sidebar.tsx b/apps/web/src/components/Sidebar.tsx--- a/apps/web/src/components/Sidebar.tsx+++ b/apps/web/src/components/Sidebar.tsx@@ -43,6 +43,7 @@
type GitStatusResult,
} from "@t3tools/contracts";
import {
+ parseScopedThreadKey,
scopedProjectKey,
scopedThreadKey,
scopeProjectRef,
@@ -2884,18 +2885,18 @@
() => getSidebarThreadIdsToPrewarm(visibleSidebarThreadKeys),
[visibleSidebarThreadKeys],
);
- const prewarmedSidebarThreads = useMemo(+ const prewarmedSidebarThreadRefs = useMemo(
() =>
prewarmedSidebarThreadKeys.flatMap((threadKey) => {
- const thread = sidebarThreadByKey.get(threadKey);- return thread ? [thread] : [];+ const ref = parseScopedThreadKey(threadKey);+ return ref ? [ref] : [];
}),
- [prewarmedSidebarThreadKeys, sidebarThreadByKey],+ [prewarmedSidebarThreadKeys],
);
useEffect(() => {
- const releases = prewarmedSidebarThreads.map((thread) =>- retainThreadDetailSubscription(thread.environmentId, thread.id),+ const releases = prewarmedSidebarThreadRefs.map((ref) =>+ retainThreadDetailSubscription(ref.environmentId, ref.threadId),
);
return () => {
@@ -2903,7 +2904,7 @@
release();
}
};
- }, [prewarmedSidebarThreads]);+ }, [prewarmedSidebarThreadRefs]);
useEffect(() => {
const clearThreadJumpHints = () => {

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit 9284b86. Configure here.

Comment threadapps/web/src/components/Sidebar.tsx Outdated
@macroscopeapp

macroscopeappBot commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new feature that proactively warms thread subscriptions for visible sidebar items and significantly changes the subscription cache policy (longer TTL, larger cache, sticky non-idle threads). While the author owns this code and changes are well-tested, this is a new capability with runtime behavior implications around network subscriptions and resource management that warrants human review.

You can customize Macroscope's approvability policy. Learn more.

@juliusmarminge

Copy link
Copy Markdown
MemberAuthor

@cursor push 1017cc1

…s on thread summary changes
The prewarmedSidebarThreads memo depended on sidebarThreadByKey, which is
recreated whenever any sidebar thread summary changes. Since the useEffect
only needs environmentId and threadId (stable identities), this caused
unnecessary cleanup/re-setup cycles for all prewarm subscriptions on every
thread status update.
Replace the thread-object lookup with parseScopedThreadKey to extract
identity pairs directly from the already-stable prewarmedSidebarThreadKeys,
breaking the dependency on the frequently-changing sidebarThreadByKey map.
Applied via @cursor push command
@juliusmarminge
juliusmarminge merged commit 569fea8 into mainApr 13, 2026
12 checks passed
@juliusmarminge
juliusmarminge deleted the t3code/thread-subscription-cache-policy branch April 13, 2026 20:55
juliusmarminge added a commit that referenced this pull request Apr 13, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
aaditagrawal added a commit to aaditagrawal/t3code that referenced this pull request Apr 16, 2026
Integrates upstream/main (d22c6f5) into the fork while preserving all
multi-provider support (codex, claudeAgent, copilot, cursor, opencode,
geminiCli, amp, kilo) and fork UI/UX additions.
Highlights adopted from upstream:
- Nightly release channel + update channel selector (pingdotgg#2012, pingdotgg#2049, pingdotgg#1969)
- Filesystem browse API + command palette project picker (pingdotgg#2024)
- Launch Args setting for Claude provider (pingdotgg#1971)
- Kiro editor support in open picker (pingdotgg#1974)
- Claude plan events for TodoWrite during input streaming (pingdotgg#1541)
- Lost provider session recovery (pingdotgg#1938)
- Cache provider status and gate desktop startup (pingdotgg#1962)
- LegendList migration for chat scrolling and branch lists (pingdotgg#1953)
- Shell snapshot queries + backfill migration (pingdotgg#1973, pingdotgg#2004)
- PATH hydration + fallback detection (pingdotgg#1799)
- Warm sidebar thread subscriptions (pingdotgg#2001)
- Full thread title tooltip (pingdotgg#1994)
- Markdown file link UX (pingdotgg#1956), composer polish (pingdotgg#1944, pingdotgg#1992, pingdotgg#1985)
- Worktree/branch state + draft reuse fixes (pingdotgg#2005, pingdotgg#2003, pingdotgg#1995, pingdotgg#1936)
- Window controls overlay for Windows/Linux (pingdotgg#1969)
- Backend readiness timeout 10s→30s (pingdotgg#1979)
- Clear tracked RPCs on reconnect, live stream subscriptions (pingdotgg#2000, pingdotgg#1972)
- Various misc fixes (pingdotgg#2051, pingdotgg#2052, pingdotgg#2025, pingdotgg#2027, pingdotgg#2049, pingdotgg#1997, pingdotgg#1975)
Fork features preserved and reconciled:
- All 8 provider adapters + conformance tests
- Extended ProviderKind union across contracts/model/settings/provider
- appearance/accentColor/themeConfig/ProviderLogo UI system
- customModels + gitTextGeneration + providerModelOptions
- Migration IDs 23 (NormalizeLegacyProviderKinds) and 24
(RepairProjectionThreadProposedPlanImplementationColumns) kept; new
upstream migrations registered at IDs 25-26 to avoid breaking deployed
fork databases
- DesktopBridge: log directory channels (LOG_DIR/LIST/READ/OPEN_DIR)
retained; getWsUrl replaced by upstream's getAppBranding
- PROVIDER_CACHE_IDS extended to all 8 providers
znoraka pushed a commit to znoraka/t3code that referenced this pull request Apr 17, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
NeilTheFisher pushed a commit to NeilTheFisher/t3code that referenced this pull request Aug 18, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
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:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@juliusmarminge@cursoragent
, '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

Warm sidebar thread detail subscriptions - #2001

Merged
juliusmarminge merged 2 commits into
mainfrom
t3code/thread-subscription-cache-policy
Apr 13, 2026
Merged

Warm sidebar thread detail subscriptions#2001
juliusmarminge merged 2 commits into
mainfrom
t3code/thread-subscription-cache-policy

Conversation

@juliusmarminge

@juliusmarmingejuliusmarminge commented Apr 13, 2026

Copy link
Copy Markdown
Member

Summary

  • Prewarm thread detail subscriptions for the first visible sidebar threads so nearby navigation can reuse hot data.
  • Extend the thread-detail cache policy to keep non-idle threads sticky and only evict idle subscriptions.
  • Increase the idle TTL and cache capacity to reduce churn while navigating and working in active threads.
  • Add tests for sidebar prewarm selection and the updated subscription eviction behavior.

Testing

  • bun fmt
  • bun lint
  • bun typecheck
  • bun run test apps/web/src/components/Sidebar.logic.test.ts
  • bun run test apps/web/src/environments/runtime/service.threadSubscriptions.test.ts

Note

Medium Risk
Changes thread-detail subscription caching/eviction and adds background prewarming from the sidebar, which can affect memory/network usage and when subscriptions are released. Logic now depends on thread activity state to prevent eviction, so regressions could keep subscriptions alive longer than intended.

Overview
Prewarms thread-detail data for the first visible sidebar threads by retaining their detail subscriptions (default 10) while they remain visible, releasing them when the visible set changes.

Updates the runtime thread-detail subscription cache policy to be stickier for non-idle threads (pending approvals/input/plan, running turns, or non-idle orchestration), and to evict only idle unretained entries; idle TTL increases to 15 minutes and cache capacity to 32.

Adds unit tests covering getSidebarThreadIdsToPrewarm and the new eviction behavior (longer warm period, non-idle stickiness, and increased capacity before eviction).

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

Note

Warm thread detail subscriptions for visible sidebar threads

  • The sidebar now retains thread detail subscriptions for up to 10 visible threads (SIDEBAR_THREAD_PREWARM_LIMIT) using retainThreadDetailSubscription, releasing them when threads leave the prewarmed set.
  • The thread detail subscription cache is expanded from 8 to 32 entries and the idle eviction timeout is increased from 2 to 15 minutes.
  • Non-idle threads (pending approvals, running turns, etc.) are exempt from eviction via a new isNonIdleThreadDetailSubscription helper in service.ts; eviction is deferred until the thread becomes idle.
  • Eviction schedules are reconciled after shell snapshot syncs, recovered event batches, and shell upserts to keep cache state consistent.
  • Behavioral Change: releasing a subscription no longer always schedules eviction — non-idle threads remain cached until idle, and capacity eviction only removes the least-recently-accessed idle entries.

Macroscope summarized a4afe8c.

- Prewarm visible sidebar threads
- Keep active thread subscriptions sticky until idle
- Expand cache capacity and add coverage
@coderabbitai

coderabbitaiBot commented Apr 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

Run ID: 65d2f790-b9a8-4a72-937c-a2601d27dbcc

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
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch t3code/thread-subscription-cache-policy

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

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels Apr 13, 2026

@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 and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Prewarm effect re-runs on every sidebar thread change
    • Replaced the prewarmedSidebarThreads memo (which depended on the frequently-changing sidebarThreadByKey map) with prewarmedSidebarThreadRefs that uses parseScopedThreadKey to extract stable identity pairs directly from prewarmedSidebarThreadKeys, breaking the dependency chain that caused unnecessary effect re-runs on every thread summary update.

Create PR

Or push these changes by commenting:

@cursor push 1017cc1156
Preview (1017cc1156)
diff --git a/apps/web/src/components/Sidebar.tsx b/apps/web/src/components/Sidebar.tsx--- a/apps/web/src/components/Sidebar.tsx+++ b/apps/web/src/components/Sidebar.tsx@@ -43,6 +43,7 @@
type GitStatusResult,
} from "@t3tools/contracts";
import {
+ parseScopedThreadKey,
scopedProjectKey,
scopedThreadKey,
scopeProjectRef,
@@ -2884,18 +2885,18 @@
() => getSidebarThreadIdsToPrewarm(visibleSidebarThreadKeys),
[visibleSidebarThreadKeys],
);
- const prewarmedSidebarThreads = useMemo(+ const prewarmedSidebarThreadRefs = useMemo(
() =>
prewarmedSidebarThreadKeys.flatMap((threadKey) => {
- const thread = sidebarThreadByKey.get(threadKey);- return thread ? [thread] : [];+ const ref = parseScopedThreadKey(threadKey);+ return ref ? [ref] : [];
}),
- [prewarmedSidebarThreadKeys, sidebarThreadByKey],+ [prewarmedSidebarThreadKeys],
);
useEffect(() => {
- const releases = prewarmedSidebarThreads.map((thread) =>- retainThreadDetailSubscription(thread.environmentId, thread.id),+ const releases = prewarmedSidebarThreadRefs.map((ref) =>+ retainThreadDetailSubscription(ref.environmentId, ref.threadId),
);
return () => {
@@ -2903,7 +2904,7 @@
release();
}
};
- }, [prewarmedSidebarThreads]);+ }, [prewarmedSidebarThreadRefs]);
useEffect(() => {
const clearThreadJumpHints = () => {

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit 9284b86. Configure here.

Comment threadapps/web/src/components/Sidebar.tsx Outdated
@macroscopeapp

macroscopeappBot commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new feature that proactively warms thread subscriptions for visible sidebar items and significantly changes the subscription cache policy (longer TTL, larger cache, sticky non-idle threads). While the author owns this code and changes are well-tested, this is a new capability with runtime behavior implications around network subscriptions and resource management that warrants human review.

You can customize Macroscope's approvability policy. Learn more.

@juliusmarminge

Copy link
Copy Markdown
MemberAuthor

@cursor push 1017cc1

…s on thread summary changes
The prewarmedSidebarThreads memo depended on sidebarThreadByKey, which is
recreated whenever any sidebar thread summary changes. Since the useEffect
only needs environmentId and threadId (stable identities), this caused
unnecessary cleanup/re-setup cycles for all prewarm subscriptions on every
thread status update.
Replace the thread-object lookup with parseScopedThreadKey to extract
identity pairs directly from the already-stable prewarmedSidebarThreadKeys,
breaking the dependency on the frequently-changing sidebarThreadByKey map.
Applied via @cursor push command
@juliusmarminge
juliusmarminge merged commit 569fea8 into mainApr 13, 2026
12 checks passed
@juliusmarminge
juliusmarminge deleted the t3code/thread-subscription-cache-policy branch April 13, 2026 20:55
juliusmarminge added a commit that referenced this pull request Apr 13, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
aaditagrawal added a commit to aaditagrawal/t3code that referenced this pull request Apr 16, 2026
Integrates upstream/main (d22c6f5) into the fork while preserving all
multi-provider support (codex, claudeAgent, copilot, cursor, opencode,
geminiCli, amp, kilo) and fork UI/UX additions.
Highlights adopted from upstream:
- Nightly release channel + update channel selector (pingdotgg#2012, pingdotgg#2049, pingdotgg#1969)
- Filesystem browse API + command palette project picker (pingdotgg#2024)
- Launch Args setting for Claude provider (pingdotgg#1971)
- Kiro editor support in open picker (pingdotgg#1974)
- Claude plan events for TodoWrite during input streaming (pingdotgg#1541)
- Lost provider session recovery (pingdotgg#1938)
- Cache provider status and gate desktop startup (pingdotgg#1962)
- LegendList migration for chat scrolling and branch lists (pingdotgg#1953)
- Shell snapshot queries + backfill migration (pingdotgg#1973, pingdotgg#2004)
- PATH hydration + fallback detection (pingdotgg#1799)
- Warm sidebar thread subscriptions (pingdotgg#2001)
- Full thread title tooltip (pingdotgg#1994)
- Markdown file link UX (pingdotgg#1956), composer polish (pingdotgg#1944, pingdotgg#1992, pingdotgg#1985)
- Worktree/branch state + draft reuse fixes (pingdotgg#2005, pingdotgg#2003, pingdotgg#1995, pingdotgg#1936)
- Window controls overlay for Windows/Linux (pingdotgg#1969)
- Backend readiness timeout 10s→30s (pingdotgg#1979)
- Clear tracked RPCs on reconnect, live stream subscriptions (pingdotgg#2000, pingdotgg#1972)
- Various misc fixes (pingdotgg#2051, pingdotgg#2052, pingdotgg#2025, pingdotgg#2027, pingdotgg#2049, pingdotgg#1997, pingdotgg#1975)
Fork features preserved and reconciled:
- All 8 provider adapters + conformance tests
- Extended ProviderKind union across contracts/model/settings/provider
- appearance/accentColor/themeConfig/ProviderLogo UI system
- customModels + gitTextGeneration + providerModelOptions
- Migration IDs 23 (NormalizeLegacyProviderKinds) and 24
(RepairProjectionThreadProposedPlanImplementationColumns) kept; new
upstream migrations registered at IDs 25-26 to avoid breaking deployed
fork databases
- DesktopBridge: log directory channels (LOG_DIR/LIST/READ/OPEN_DIR)
retained; getWsUrl replaced by upstream's getAppBranding
- PROVIDER_CACHE_IDS extended to all 8 providers
znoraka pushed a commit to znoraka/t3code that referenced this pull request Apr 17, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
NeilTheFisher pushed a commit to NeilTheFisher/t3code that referenced this pull request Aug 18, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
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:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@juliusmarminge@cursoragent