fix(server): stop routine events from rescanning thread history - #7356

Closed
dain wants to merge 1 commit into
pingdotgg:mainfrom
dain:user/dain/skip-routine-summary-refresh
Closed

fix(server): stop routine events from rescanning thread history#7356
dain wants to merge 1 commit into
pingdotgg:mainfrom
dain:user/dain/skip-routine-summary-refresh

Conversation

@dain

@daindain commented Aug 18, 2026

Copy link
Copy Markdown

Fixes#5719.

What Changed

The threads projector no longer calls refreshThreadShellSummary for assistant messages or routine activities. Those events still update their normal projections and advance the thread's updatedAt, but they skip the second operation that reloads the thread's complete message, proposed-plan, activity, and approval histories.

The existing full refresh remains in place for events that can change the current shell summary:

  • user messages
  • approval and user-input lifecycle activities
  • proposed plans and explicit approval/user-input responses
  • session and latest-turn changes
  • thread reverts

A focused projection-pipeline regression test verifies that an assistant message and a routine tool.updated activity each produce only the expected thread timestamp update, rather than that update followed by a summary rewrite.

Why

refreshThreadShellSummary derives four fields: the latest user-message time, pending approval count, pending user-input count, and actionable-plan state. Assistant messages and ordinary tool/context activities cannot change any of them, but every such event currently reloads all four backing collections.

On a high-activity thread with 27,303 activities and 23,778 messages, activity projection averaged 734 ms per event. A burst of 526 routine activity and assistant-message events therefore accounted for approximately 386 seconds of serialized projection work, delaying unrelated threads behind the same global ingestion worker.

This change removes that measured hot path without changing summary derivation or introducing incremental counters.

Related: #5855 and #6608 address the same projection cost with broader changes. This PR intentionally keeps the existing summary implementation and only avoids invoking it for events that cannot affect its result.

Verification

  • vp test run apps/server/src/orchestration/Layers/ProjectionPipeline.test.ts — 22 passed
  • server typecheck passed
  • targeted lint and formatting passed
  • server bundle build passed
  • git diff --check passed

No schema, projector cursor, transaction, replay, queue, client, or UI changes.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • No UI changes; screenshots are not applicable
  • No animation or interaction changes; video is not applicable

Model and harness: GPT-5.6 Sol using the Codex harness in T3 Code.

Note

Stop assistant messages and routine activities from rescanning thread history

  • Adds eventCanChangeThreadShellSummary in ProjectionPipeline.ts to gate calls to refreshThreadShellSummary. Only user messages and specific activity kinds (approval.requested, approval.resolved, user-input.requested, etc.) qualify.
  • Assistant messages and routine activities (e.g. tool.updated) now only update the thread shell updatedAt timestamp instead of triggering a full summary refresh.
  • Behavioral Change: previously every thread.message-sent and thread.activity-appended event caused a summary rescan; now only a subset does.

Macroscope summarized 77b586e.


Note

Medium Risk
Changes which events recompute thread list/shell summary fields; incorrect gating could leave stale pending counts or user-message timestamps, though existing tests cover approval/user-input paths and the new assistant/tool cases.

Overview
Skips expensive thread shell summary rescans for assistant messages and routine activities (e.g. tool.updated) during orchestration projection, while still bumping the thread shell updatedAt.

Adds eventCanChangeThreadShellSummary in ProjectionPipeline.ts so refreshThreadShellSummary runs only when an event can change derived fields (latest user message time, pending approvals/user input, actionable plans). User messages and approval/user-input lifecycle activities still trigger a full refresh; proposed plans and explicit response events behave as before.

A regression test uses a SQLite trigger on projection_threads to assert assistant messages and routine activities cause a single row update (timestamp only), not a second update from summary refresh.

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

Assistant messages and routine activities cannot change the current thread shell summary, but each previously reloaded all messages, plans, activities, and approvals.
Keep the existing refresh for user messages and approval or user-input lifecycle events, and cover the bypass with the projection pipeline test.
@coderabbitai

coderabbitaiBot commented Aug 18, 2026

Copy link
Copy Markdown

Important

Review skipped

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

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: aa0c1725-906e-4497-beb0-7514139b989d

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

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

❤️ Share

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

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Aug 18, 2026
@dain
dain marked this pull request as ready for review August 18, 2026 02:52
@macroscopeapp

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR changes when the thread shell summary refresh occurs, gating a database read/write operation based on event type. While the optimization logic appears correct, changes that determine whether significant processing work happens warrant human review to verify the gating conditions are complete.

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

@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing in favor of merged #8150, which skips full thread-history scans for assistant messages and routine activity. Your work is credited in #8150.

@t3dotggt3dotgg closed this Aug 25, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Assistant streaming causes full-thread projection scans for every text delta

2 participants

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

fix(server): stop routine events from rescanning thread history - #7356

Closed
dain wants to merge 1 commit into
pingdotgg:mainfrom
dain:user/dain/skip-routine-summary-refresh
Closed

fix(server): stop routine events from rescanning thread history#7356
dain wants to merge 1 commit into
pingdotgg:mainfrom
dain:user/dain/skip-routine-summary-refresh

Conversation

@dain

@daindain commented Aug 18, 2026

Copy link
Copy Markdown

Fixes#5719.

What Changed

The threads projector no longer calls refreshThreadShellSummary for assistant messages or routine activities. Those events still update their normal projections and advance the thread's updatedAt, but they skip the second operation that reloads the thread's complete message, proposed-plan, activity, and approval histories.

The existing full refresh remains in place for events that can change the current shell summary:

  • user messages
  • approval and user-input lifecycle activities
  • proposed plans and explicit approval/user-input responses
  • session and latest-turn changes
  • thread reverts

A focused projection-pipeline regression test verifies that an assistant message and a routine tool.updated activity each produce only the expected thread timestamp update, rather than that update followed by a summary rewrite.

Why

refreshThreadShellSummary derives four fields: the latest user-message time, pending approval count, pending user-input count, and actionable-plan state. Assistant messages and ordinary tool/context activities cannot change any of them, but every such event currently reloads all four backing collections.

On a high-activity thread with 27,303 activities and 23,778 messages, activity projection averaged 734 ms per event. A burst of 526 routine activity and assistant-message events therefore accounted for approximately 386 seconds of serialized projection work, delaying unrelated threads behind the same global ingestion worker.

This change removes that measured hot path without changing summary derivation or introducing incremental counters.

Related: #5855 and #6608 address the same projection cost with broader changes. This PR intentionally keeps the existing summary implementation and only avoids invoking it for events that cannot affect its result.

Verification

  • vp test run apps/server/src/orchestration/Layers/ProjectionPipeline.test.ts — 22 passed
  • server typecheck passed
  • targeted lint and formatting passed
  • server bundle build passed
  • git diff --check passed

No schema, projector cursor, transaction, replay, queue, client, or UI changes.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • No UI changes; screenshots are not applicable
  • No animation or interaction changes; video is not applicable

Model and harness: GPT-5.6 Sol using the Codex harness in T3 Code.

Note

Stop assistant messages and routine activities from rescanning thread history

  • Adds eventCanChangeThreadShellSummary in ProjectionPipeline.ts to gate calls to refreshThreadShellSummary. Only user messages and specific activity kinds (approval.requested, approval.resolved, user-input.requested, etc.) qualify.
  • Assistant messages and routine activities (e.g. tool.updated) now only update the thread shell updatedAt timestamp instead of triggering a full summary refresh.
  • Behavioral Change: previously every thread.message-sent and thread.activity-appended event caused a summary rescan; now only a subset does.

Macroscope summarized 77b586e.


Note

Medium Risk
Changes which events recompute thread list/shell summary fields; incorrect gating could leave stale pending counts or user-message timestamps, though existing tests cover approval/user-input paths and the new assistant/tool cases.

Overview
Skips expensive thread shell summary rescans for assistant messages and routine activities (e.g. tool.updated) during orchestration projection, while still bumping the thread shell updatedAt.

Adds eventCanChangeThreadShellSummary in ProjectionPipeline.ts so refreshThreadShellSummary runs only when an event can change derived fields (latest user message time, pending approvals/user input, actionable plans). User messages and approval/user-input lifecycle activities still trigger a full refresh; proposed plans and explicit response events behave as before.

A regression test uses a SQLite trigger on projection_threads to assert assistant messages and routine activities cause a single row update (timestamp only), not a second update from summary refresh.

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

Assistant messages and routine activities cannot change the current thread shell summary, but each previously reloaded all messages, plans, activities, and approvals.
Keep the existing refresh for user messages and approval or user-input lifecycle events, and cover the bypass with the projection pipeline test.
@coderabbitai

coderabbitaiBot commented Aug 18, 2026

Copy link
Copy Markdown

Important

Review skipped

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

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: aa0c1725-906e-4497-beb0-7514139b989d

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

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

❤️ Share

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

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Aug 18, 2026
@dain
dain marked this pull request as ready for review August 18, 2026 02:52
@macroscopeapp

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR changes when the thread shell summary refresh occurs, gating a database read/write operation based on event type. While the optimization logic appears correct, changes that determine whether significant processing work happens warrant human review to verify the gating conditions are complete.

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

@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing in favor of merged #8150, which skips full thread-history scans for assistant messages and routine activity. Your work is credited in #8150.

@t3dotggt3dotgg closed this Aug 25, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Assistant streaming causes full-thread projection scans for every text delta

2 participants

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

fix(server): stop routine events from rescanning thread history - #7356

Closed
dain wants to merge 1 commit into
pingdotgg:mainfrom
dain:user/dain/skip-routine-summary-refresh
Closed

fix(server): stop routine events from rescanning thread history#7356
dain wants to merge 1 commit into
pingdotgg:mainfrom
dain:user/dain/skip-routine-summary-refresh

Conversation

@dain

@daindain commented Aug 18, 2026

Copy link
Copy Markdown

Fixes#5719.

What Changed

The threads projector no longer calls refreshThreadShellSummary for assistant messages or routine activities. Those events still update their normal projections and advance the thread's updatedAt, but they skip the second operation that reloads the thread's complete message, proposed-plan, activity, and approval histories.

The existing full refresh remains in place for events that can change the current shell summary:

  • user messages
  • approval and user-input lifecycle activities
  • proposed plans and explicit approval/user-input responses
  • session and latest-turn changes
  • thread reverts

A focused projection-pipeline regression test verifies that an assistant message and a routine tool.updated activity each produce only the expected thread timestamp update, rather than that update followed by a summary rewrite.

Why

refreshThreadShellSummary derives four fields: the latest user-message time, pending approval count, pending user-input count, and actionable-plan state. Assistant messages and ordinary tool/context activities cannot change any of them, but every such event currently reloads all four backing collections.

On a high-activity thread with 27,303 activities and 23,778 messages, activity projection averaged 734 ms per event. A burst of 526 routine activity and assistant-message events therefore accounted for approximately 386 seconds of serialized projection work, delaying unrelated threads behind the same global ingestion worker.

This change removes that measured hot path without changing summary derivation or introducing incremental counters.

Related: #5855 and #6608 address the same projection cost with broader changes. This PR intentionally keeps the existing summary implementation and only avoids invoking it for events that cannot affect its result.

Verification

  • vp test run apps/server/src/orchestration/Layers/ProjectionPipeline.test.ts — 22 passed
  • server typecheck passed
  • targeted lint and formatting passed
  • server bundle build passed
  • git diff --check passed

No schema, projector cursor, transaction, replay, queue, client, or UI changes.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • No UI changes; screenshots are not applicable
  • No animation or interaction changes; video is not applicable

Model and harness: GPT-5.6 Sol using the Codex harness in T3 Code.

Note

Stop assistant messages and routine activities from rescanning thread history

  • Adds eventCanChangeThreadShellSummary in ProjectionPipeline.ts to gate calls to refreshThreadShellSummary. Only user messages and specific activity kinds (approval.requested, approval.resolved, user-input.requested, etc.) qualify.
  • Assistant messages and routine activities (e.g. tool.updated) now only update the thread shell updatedAt timestamp instead of triggering a full summary refresh.
  • Behavioral Change: previously every thread.message-sent and thread.activity-appended event caused a summary rescan; now only a subset does.

Macroscope summarized 77b586e.


Note

Medium Risk
Changes which events recompute thread list/shell summary fields; incorrect gating could leave stale pending counts or user-message timestamps, though existing tests cover approval/user-input paths and the new assistant/tool cases.

Overview
Skips expensive thread shell summary rescans for assistant messages and routine activities (e.g. tool.updated) during orchestration projection, while still bumping the thread shell updatedAt.

Adds eventCanChangeThreadShellSummary in ProjectionPipeline.ts so refreshThreadShellSummary runs only when an event can change derived fields (latest user message time, pending approvals/user input, actionable plans). User messages and approval/user-input lifecycle activities still trigger a full refresh; proposed plans and explicit response events behave as before.

A regression test uses a SQLite trigger on projection_threads to assert assistant messages and routine activities cause a single row update (timestamp only), not a second update from summary refresh.

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

Assistant messages and routine activities cannot change the current thread shell summary, but each previously reloaded all messages, plans, activities, and approvals.
Keep the existing refresh for user messages and approval or user-input lifecycle events, and cover the bypass with the projection pipeline test.
@coderabbitai

coderabbitaiBot commented Aug 18, 2026

Copy link
Copy Markdown

Important

Review skipped

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

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: aa0c1725-906e-4497-beb0-7514139b989d

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

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

❤️ Share

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

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Aug 18, 2026
@dain
dain marked this pull request as ready for review August 18, 2026 02:52
@macroscopeapp

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR changes when the thread shell summary refresh occurs, gating a database read/write operation based on event type. While the optimization logic appears correct, changes that determine whether significant processing work happens warrant human review to verify the gating conditions are complete.

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

@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing in favor of merged #8150, which skips full thread-history scans for assistant messages and routine activity. Your work is credited in #8150.

@t3dotggt3dotgg closed this Aug 25, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Assistant streaming causes full-thread projection scans for every text delta

2 participants

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

fix(server): stop routine events from rescanning thread history - #7356

Closed
dain wants to merge 1 commit into
pingdotgg:mainfrom
dain:user/dain/skip-routine-summary-refresh
Closed

fix(server): stop routine events from rescanning thread history#7356
dain wants to merge 1 commit into
pingdotgg:mainfrom
dain:user/dain/skip-routine-summary-refresh

Conversation

@dain

@daindain commented Aug 18, 2026

Copy link
Copy Markdown

Fixes#5719.

What Changed

The threads projector no longer calls refreshThreadShellSummary for assistant messages or routine activities. Those events still update their normal projections and advance the thread's updatedAt, but they skip the second operation that reloads the thread's complete message, proposed-plan, activity, and approval histories.

The existing full refresh remains in place for events that can change the current shell summary:

  • user messages
  • approval and user-input lifecycle activities
  • proposed plans and explicit approval/user-input responses
  • session and latest-turn changes
  • thread reverts

A focused projection-pipeline regression test verifies that an assistant message and a routine tool.updated activity each produce only the expected thread timestamp update, rather than that update followed by a summary rewrite.

Why

refreshThreadShellSummary derives four fields: the latest user-message time, pending approval count, pending user-input count, and actionable-plan state. Assistant messages and ordinary tool/context activities cannot change any of them, but every such event currently reloads all four backing collections.

On a high-activity thread with 27,303 activities and 23,778 messages, activity projection averaged 734 ms per event. A burst of 526 routine activity and assistant-message events therefore accounted for approximately 386 seconds of serialized projection work, delaying unrelated threads behind the same global ingestion worker.

This change removes that measured hot path without changing summary derivation or introducing incremental counters.

Related: #5855 and #6608 address the same projection cost with broader changes. This PR intentionally keeps the existing summary implementation and only avoids invoking it for events that cannot affect its result.

Verification

  • vp test run apps/server/src/orchestration/Layers/ProjectionPipeline.test.ts — 22 passed
  • server typecheck passed
  • targeted lint and formatting passed
  • server bundle build passed
  • git diff --check passed

No schema, projector cursor, transaction, replay, queue, client, or UI changes.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • No UI changes; screenshots are not applicable
  • No animation or interaction changes; video is not applicable

Model and harness: GPT-5.6 Sol using the Codex harness in T3 Code.

Note

Stop assistant messages and routine activities from rescanning thread history

  • Adds eventCanChangeThreadShellSummary in ProjectionPipeline.ts to gate calls to refreshThreadShellSummary. Only user messages and specific activity kinds (approval.requested, approval.resolved, user-input.requested, etc.) qualify.
  • Assistant messages and routine activities (e.g. tool.updated) now only update the thread shell updatedAt timestamp instead of triggering a full summary refresh.
  • Behavioral Change: previously every thread.message-sent and thread.activity-appended event caused a summary rescan; now only a subset does.

Macroscope summarized 77b586e.


Note

Medium Risk
Changes which events recompute thread list/shell summary fields; incorrect gating could leave stale pending counts or user-message timestamps, though existing tests cover approval/user-input paths and the new assistant/tool cases.

Overview
Skips expensive thread shell summary rescans for assistant messages and routine activities (e.g. tool.updated) during orchestration projection, while still bumping the thread shell updatedAt.

Adds eventCanChangeThreadShellSummary in ProjectionPipeline.ts so refreshThreadShellSummary runs only when an event can change derived fields (latest user message time, pending approvals/user input, actionable plans). User messages and approval/user-input lifecycle activities still trigger a full refresh; proposed plans and explicit response events behave as before.

A regression test uses a SQLite trigger on projection_threads to assert assistant messages and routine activities cause a single row update (timestamp only), not a second update from summary refresh.

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

Assistant messages and routine activities cannot change the current thread shell summary, but each previously reloaded all messages, plans, activities, and approvals.
Keep the existing refresh for user messages and approval or user-input lifecycle events, and cover the bypass with the projection pipeline test.
@coderabbitai

coderabbitaiBot commented Aug 18, 2026

Copy link
Copy Markdown

Important

Review skipped

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

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: aa0c1725-906e-4497-beb0-7514139b989d

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

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

❤️ Share

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

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Aug 18, 2026
@dain
dain marked this pull request as ready for review August 18, 2026 02:52
@macroscopeapp

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR changes when the thread shell summary refresh occurs, gating a database read/write operation based on event type. While the optimization logic appears correct, changes that determine whether significant processing work happens warrant human review to verify the gating conditions are complete.

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

@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing in favor of merged #8150, which skips full thread-history scans for assistant messages and routine activity. Your work is credited in #8150.

@t3dotggt3dotgg closed this Aug 25, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Assistant streaming causes full-thread projection scans for every text delta

2 participants

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

fix(server): stop routine events from rescanning thread history - #7356

Closed
dain wants to merge 1 commit into
pingdotgg:mainfrom
dain:user/dain/skip-routine-summary-refresh
Closed

fix(server): stop routine events from rescanning thread history#7356
dain wants to merge 1 commit into
pingdotgg:mainfrom
dain:user/dain/skip-routine-summary-refresh

Conversation

@dain

@daindain commented Aug 18, 2026

Copy link
Copy Markdown

Fixes#5719.

What Changed

The threads projector no longer calls refreshThreadShellSummary for assistant messages or routine activities. Those events still update their normal projections and advance the thread's updatedAt, but they skip the second operation that reloads the thread's complete message, proposed-plan, activity, and approval histories.

The existing full refresh remains in place for events that can change the current shell summary:

  • user messages
  • approval and user-input lifecycle activities
  • proposed plans and explicit approval/user-input responses
  • session and latest-turn changes
  • thread reverts

A focused projection-pipeline regression test verifies that an assistant message and a routine tool.updated activity each produce only the expected thread timestamp update, rather than that update followed by a summary rewrite.

Why

refreshThreadShellSummary derives four fields: the latest user-message time, pending approval count, pending user-input count, and actionable-plan state. Assistant messages and ordinary tool/context activities cannot change any of them, but every such event currently reloads all four backing collections.

On a high-activity thread with 27,303 activities and 23,778 messages, activity projection averaged 734 ms per event. A burst of 526 routine activity and assistant-message events therefore accounted for approximately 386 seconds of serialized projection work, delaying unrelated threads behind the same global ingestion worker.

This change removes that measured hot path without changing summary derivation or introducing incremental counters.

Related: #5855 and #6608 address the same projection cost with broader changes. This PR intentionally keeps the existing summary implementation and only avoids invoking it for events that cannot affect its result.

Verification

  • vp test run apps/server/src/orchestration/Layers/ProjectionPipeline.test.ts — 22 passed
  • server typecheck passed
  • targeted lint and formatting passed
  • server bundle build passed
  • git diff --check passed

No schema, projector cursor, transaction, replay, queue, client, or UI changes.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • No UI changes; screenshots are not applicable
  • No animation or interaction changes; video is not applicable

Model and harness: GPT-5.6 Sol using the Codex harness in T3 Code.

Note

Stop assistant messages and routine activities from rescanning thread history

  • Adds eventCanChangeThreadShellSummary in ProjectionPipeline.ts to gate calls to refreshThreadShellSummary. Only user messages and specific activity kinds (approval.requested, approval.resolved, user-input.requested, etc.) qualify.
  • Assistant messages and routine activities (e.g. tool.updated) now only update the thread shell updatedAt timestamp instead of triggering a full summary refresh.
  • Behavioral Change: previously every thread.message-sent and thread.activity-appended event caused a summary rescan; now only a subset does.

Macroscope summarized 77b586e.


Note

Medium Risk
Changes which events recompute thread list/shell summary fields; incorrect gating could leave stale pending counts or user-message timestamps, though existing tests cover approval/user-input paths and the new assistant/tool cases.

Overview
Skips expensive thread shell summary rescans for assistant messages and routine activities (e.g. tool.updated) during orchestration projection, while still bumping the thread shell updatedAt.

Adds eventCanChangeThreadShellSummary in ProjectionPipeline.ts so refreshThreadShellSummary runs only when an event can change derived fields (latest user message time, pending approvals/user input, actionable plans). User messages and approval/user-input lifecycle activities still trigger a full refresh; proposed plans and explicit response events behave as before.

A regression test uses a SQLite trigger on projection_threads to assert assistant messages and routine activities cause a single row update (timestamp only), not a second update from summary refresh.

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

Assistant messages and routine activities cannot change the current thread shell summary, but each previously reloaded all messages, plans, activities, and approvals.
Keep the existing refresh for user messages and approval or user-input lifecycle events, and cover the bypass with the projection pipeline test.
@coderabbitai

coderabbitaiBot commented Aug 18, 2026

Copy link
Copy Markdown

Important

Review skipped

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

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: aa0c1725-906e-4497-beb0-7514139b989d

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

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

❤️ Share

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

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Aug 18, 2026
@dain
dain marked this pull request as ready for review August 18, 2026 02:52
@macroscopeapp

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR changes when the thread shell summary refresh occurs, gating a database read/write operation based on event type. While the optimization logic appears correct, changes that determine whether significant processing work happens warrant human review to verify the gating conditions are complete.

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

@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing in favor of merged #8150, which skips full thread-history scans for assistant messages and routine activity. Your work is credited in #8150.

@t3dotggt3dotgg closed this Aug 25, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Assistant streaming causes full-thread projection scans for every text delta

2 participants

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

fix(server): stop routine events from rescanning thread history - #7356

Closed
dain wants to merge 1 commit into
pingdotgg:mainfrom
dain:user/dain/skip-routine-summary-refresh
Closed

fix(server): stop routine events from rescanning thread history#7356
dain wants to merge 1 commit into
pingdotgg:mainfrom
dain:user/dain/skip-routine-summary-refresh

Conversation

@dain

@daindain commented Aug 18, 2026

Copy link
Copy Markdown

Fixes#5719.

What Changed

The threads projector no longer calls refreshThreadShellSummary for assistant messages or routine activities. Those events still update their normal projections and advance the thread's updatedAt, but they skip the second operation that reloads the thread's complete message, proposed-plan, activity, and approval histories.

The existing full refresh remains in place for events that can change the current shell summary:

  • user messages
  • approval and user-input lifecycle activities
  • proposed plans and explicit approval/user-input responses
  • session and latest-turn changes
  • thread reverts

A focused projection-pipeline regression test verifies that an assistant message and a routine tool.updated activity each produce only the expected thread timestamp update, rather than that update followed by a summary rewrite.

Why

refreshThreadShellSummary derives four fields: the latest user-message time, pending approval count, pending user-input count, and actionable-plan state. Assistant messages and ordinary tool/context activities cannot change any of them, but every such event currently reloads all four backing collections.

On a high-activity thread with 27,303 activities and 23,778 messages, activity projection averaged 734 ms per event. A burst of 526 routine activity and assistant-message events therefore accounted for approximately 386 seconds of serialized projection work, delaying unrelated threads behind the same global ingestion worker.

This change removes that measured hot path without changing summary derivation or introducing incremental counters.

Related: #5855 and #6608 address the same projection cost with broader changes. This PR intentionally keeps the existing summary implementation and only avoids invoking it for events that cannot affect its result.

Verification

  • vp test run apps/server/src/orchestration/Layers/ProjectionPipeline.test.ts — 22 passed
  • server typecheck passed
  • targeted lint and formatting passed
  • server bundle build passed
  • git diff --check passed

No schema, projector cursor, transaction, replay, queue, client, or UI changes.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • No UI changes; screenshots are not applicable
  • No animation or interaction changes; video is not applicable

Model and harness: GPT-5.6 Sol using the Codex harness in T3 Code.

Note

Stop assistant messages and routine activities from rescanning thread history

  • Adds eventCanChangeThreadShellSummary in ProjectionPipeline.ts to gate calls to refreshThreadShellSummary. Only user messages and specific activity kinds (approval.requested, approval.resolved, user-input.requested, etc.) qualify.
  • Assistant messages and routine activities (e.g. tool.updated) now only update the thread shell updatedAt timestamp instead of triggering a full summary refresh.
  • Behavioral Change: previously every thread.message-sent and thread.activity-appended event caused a summary rescan; now only a subset does.

Macroscope summarized 77b586e.


Note

Medium Risk
Changes which events recompute thread list/shell summary fields; incorrect gating could leave stale pending counts or user-message timestamps, though existing tests cover approval/user-input paths and the new assistant/tool cases.

Overview
Skips expensive thread shell summary rescans for assistant messages and routine activities (e.g. tool.updated) during orchestration projection, while still bumping the thread shell updatedAt.

Adds eventCanChangeThreadShellSummary in ProjectionPipeline.ts so refreshThreadShellSummary runs only when an event can change derived fields (latest user message time, pending approvals/user input, actionable plans). User messages and approval/user-input lifecycle activities still trigger a full refresh; proposed plans and explicit response events behave as before.

A regression test uses a SQLite trigger on projection_threads to assert assistant messages and routine activities cause a single row update (timestamp only), not a second update from summary refresh.

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

Assistant messages and routine activities cannot change the current thread shell summary, but each previously reloaded all messages, plans, activities, and approvals.
Keep the existing refresh for user messages and approval or user-input lifecycle events, and cover the bypass with the projection pipeline test.
@coderabbitai

coderabbitaiBot commented Aug 18, 2026

Copy link
Copy Markdown

Important

Review skipped

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

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: aa0c1725-906e-4497-beb0-7514139b989d

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

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

❤️ Share

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

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Aug 18, 2026
@dain
dain marked this pull request as ready for review August 18, 2026 02:52
@macroscopeapp

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR changes when the thread shell summary refresh occurs, gating a database read/write operation based on event type. While the optimization logic appears correct, changes that determine whether significant processing work happens warrant human review to verify the gating conditions are complete.

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

@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing in favor of merged #8150, which skips full thread-history scans for assistant messages and routine activity. Your work is credited in #8150.

@t3dotggt3dotgg closed this Aug 25, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Assistant streaming causes full-thread projection scans for every text delta

2 participants

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

fix(server): stop routine events from rescanning thread history - #7356

Closed
dain wants to merge 1 commit into
pingdotgg:mainfrom
dain:user/dain/skip-routine-summary-refresh
Closed

fix(server): stop routine events from rescanning thread history#7356
dain wants to merge 1 commit into
pingdotgg:mainfrom
dain:user/dain/skip-routine-summary-refresh

Conversation

@dain

@daindain commented Aug 18, 2026

Copy link
Copy Markdown

Fixes#5719.

What Changed

The threads projector no longer calls refreshThreadShellSummary for assistant messages or routine activities. Those events still update their normal projections and advance the thread's updatedAt, but they skip the second operation that reloads the thread's complete message, proposed-plan, activity, and approval histories.

The existing full refresh remains in place for events that can change the current shell summary:

  • user messages
  • approval and user-input lifecycle activities
  • proposed plans and explicit approval/user-input responses
  • session and latest-turn changes
  • thread reverts

A focused projection-pipeline regression test verifies that an assistant message and a routine tool.updated activity each produce only the expected thread timestamp update, rather than that update followed by a summary rewrite.

Why

refreshThreadShellSummary derives four fields: the latest user-message time, pending approval count, pending user-input count, and actionable-plan state. Assistant messages and ordinary tool/context activities cannot change any of them, but every such event currently reloads all four backing collections.

On a high-activity thread with 27,303 activities and 23,778 messages, activity projection averaged 734 ms per event. A burst of 526 routine activity and assistant-message events therefore accounted for approximately 386 seconds of serialized projection work, delaying unrelated threads behind the same global ingestion worker.

This change removes that measured hot path without changing summary derivation or introducing incremental counters.

Related: #5855 and #6608 address the same projection cost with broader changes. This PR intentionally keeps the existing summary implementation and only avoids invoking it for events that cannot affect its result.

Verification

  • vp test run apps/server/src/orchestration/Layers/ProjectionPipeline.test.ts — 22 passed
  • server typecheck passed
  • targeted lint and formatting passed
  • server bundle build passed
  • git diff --check passed

No schema, projector cursor, transaction, replay, queue, client, or UI changes.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • No UI changes; screenshots are not applicable
  • No animation or interaction changes; video is not applicable

Model and harness: GPT-5.6 Sol using the Codex harness in T3 Code.

Note

Stop assistant messages and routine activities from rescanning thread history

  • Adds eventCanChangeThreadShellSummary in ProjectionPipeline.ts to gate calls to refreshThreadShellSummary. Only user messages and specific activity kinds (approval.requested, approval.resolved, user-input.requested, etc.) qualify.
  • Assistant messages and routine activities (e.g. tool.updated) now only update the thread shell updatedAt timestamp instead of triggering a full summary refresh.
  • Behavioral Change: previously every thread.message-sent and thread.activity-appended event caused a summary rescan; now only a subset does.

Macroscope summarized 77b586e.


Note

Medium Risk
Changes which events recompute thread list/shell summary fields; incorrect gating could leave stale pending counts or user-message timestamps, though existing tests cover approval/user-input paths and the new assistant/tool cases.

Overview
Skips expensive thread shell summary rescans for assistant messages and routine activities (e.g. tool.updated) during orchestration projection, while still bumping the thread shell updatedAt.

Adds eventCanChangeThreadShellSummary in ProjectionPipeline.ts so refreshThreadShellSummary runs only when an event can change derived fields (latest user message time, pending approvals/user input, actionable plans). User messages and approval/user-input lifecycle activities still trigger a full refresh; proposed plans and explicit response events behave as before.

A regression test uses a SQLite trigger on projection_threads to assert assistant messages and routine activities cause a single row update (timestamp only), not a second update from summary refresh.

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

Assistant messages and routine activities cannot change the current thread shell summary, but each previously reloaded all messages, plans, activities, and approvals.
Keep the existing refresh for user messages and approval or user-input lifecycle events, and cover the bypass with the projection pipeline test.
@coderabbitai

coderabbitaiBot commented Aug 18, 2026

Copy link
Copy Markdown

Important

Review skipped

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

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: aa0c1725-906e-4497-beb0-7514139b989d

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

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

❤️ Share

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

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Aug 18, 2026
@dain
dain marked this pull request as ready for review August 18, 2026 02:52
@macroscopeapp

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR changes when the thread shell summary refresh occurs, gating a database read/write operation based on event type. While the optimization logic appears correct, changes that determine whether significant processing work happens warrant human review to verify the gating conditions are complete.

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

@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing in favor of merged #8150, which skips full thread-history scans for assistant messages and routine activity. Your work is credited in #8150.

@t3dotggt3dotgg closed this Aug 25, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Assistant streaming causes full-thread projection scans for every text delta

2 participants

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

fix(server): stop routine events from rescanning thread history - #7356

Closed
dain wants to merge 1 commit into
pingdotgg:mainfrom
dain:user/dain/skip-routine-summary-refresh
Closed

fix(server): stop routine events from rescanning thread history#7356
dain wants to merge 1 commit into
pingdotgg:mainfrom
dain:user/dain/skip-routine-summary-refresh

Conversation

@dain

@daindain commented Aug 18, 2026

Copy link
Copy Markdown

Fixes#5719.

What Changed

The threads projector no longer calls refreshThreadShellSummary for assistant messages or routine activities. Those events still update their normal projections and advance the thread's updatedAt, but they skip the second operation that reloads the thread's complete message, proposed-plan, activity, and approval histories.

The existing full refresh remains in place for events that can change the current shell summary:

  • user messages
  • approval and user-input lifecycle activities
  • proposed plans and explicit approval/user-input responses
  • session and latest-turn changes
  • thread reverts

A focused projection-pipeline regression test verifies that an assistant message and a routine tool.updated activity each produce only the expected thread timestamp update, rather than that update followed by a summary rewrite.

Why

refreshThreadShellSummary derives four fields: the latest user-message time, pending approval count, pending user-input count, and actionable-plan state. Assistant messages and ordinary tool/context activities cannot change any of them, but every such event currently reloads all four backing collections.

On a high-activity thread with 27,303 activities and 23,778 messages, activity projection averaged 734 ms per event. A burst of 526 routine activity and assistant-message events therefore accounted for approximately 386 seconds of serialized projection work, delaying unrelated threads behind the same global ingestion worker.

This change removes that measured hot path without changing summary derivation or introducing incremental counters.

Related: #5855 and #6608 address the same projection cost with broader changes. This PR intentionally keeps the existing summary implementation and only avoids invoking it for events that cannot affect its result.

Verification

  • vp test run apps/server/src/orchestration/Layers/ProjectionPipeline.test.ts — 22 passed
  • server typecheck passed
  • targeted lint and formatting passed
  • server bundle build passed
  • git diff --check passed

No schema, projector cursor, transaction, replay, queue, client, or UI changes.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • No UI changes; screenshots are not applicable
  • No animation or interaction changes; video is not applicable

Model and harness: GPT-5.6 Sol using the Codex harness in T3 Code.

Note

Stop assistant messages and routine activities from rescanning thread history

  • Adds eventCanChangeThreadShellSummary in ProjectionPipeline.ts to gate calls to refreshThreadShellSummary. Only user messages and specific activity kinds (approval.requested, approval.resolved, user-input.requested, etc.) qualify.
  • Assistant messages and routine activities (e.g. tool.updated) now only update the thread shell updatedAt timestamp instead of triggering a full summary refresh.
  • Behavioral Change: previously every thread.message-sent and thread.activity-appended event caused a summary rescan; now only a subset does.

Macroscope summarized 77b586e.


Note

Medium Risk
Changes which events recompute thread list/shell summary fields; incorrect gating could leave stale pending counts or user-message timestamps, though existing tests cover approval/user-input paths and the new assistant/tool cases.

Overview
Skips expensive thread shell summary rescans for assistant messages and routine activities (e.g. tool.updated) during orchestration projection, while still bumping the thread shell updatedAt.

Adds eventCanChangeThreadShellSummary in ProjectionPipeline.ts so refreshThreadShellSummary runs only when an event can change derived fields (latest user message time, pending approvals/user input, actionable plans). User messages and approval/user-input lifecycle activities still trigger a full refresh; proposed plans and explicit response events behave as before.

A regression test uses a SQLite trigger on projection_threads to assert assistant messages and routine activities cause a single row update (timestamp only), not a second update from summary refresh.

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

Assistant messages and routine activities cannot change the current thread shell summary, but each previously reloaded all messages, plans, activities, and approvals.
Keep the existing refresh for user messages and approval or user-input lifecycle events, and cover the bypass with the projection pipeline test.
@coderabbitai

coderabbitaiBot commented Aug 18, 2026

Copy link
Copy Markdown

Important

Review skipped

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

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: aa0c1725-906e-4497-beb0-7514139b989d

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

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

❤️ Share

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

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Aug 18, 2026
@dain
dain marked this pull request as ready for review August 18, 2026 02:52
@macroscopeapp

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR changes when the thread shell summary refresh occurs, gating a database read/write operation based on event type. While the optimization logic appears correct, changes that determine whether significant processing work happens warrant human review to verify the gating conditions are complete.

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

@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing in favor of merged #8150, which skips full thread-history scans for assistant messages and routine activity. Your work is credited in #8150.

@t3dotggt3dotgg closed this Aug 25, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Assistant streaming causes full-thread projection scans for every text delta

2 participants

@dain@t3dotgg