fix(server): bound thread shell-summary reads - #7486

Closed
t3-code[bot] wants to merge 2 commits into
mainfrom
fix/bound-thread-shell-summary
Closed

fix(server): bound thread shell-summary reads#7486
t3-code[bot] wants to merge 2 commits into
mainfrom
fix/bound-thread-shell-summary

Conversation

@t3-code

@t3-codet3-codeBot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

what changed

  • normalize user-input request ids and state transitions when projecting activities
  • maintain a one-row pending-input summary per thread through indexed old/new request lookups
  • read latest user-message timestamps through a partial covering index
  • repair old and new thread owners after destructive activity-id and message-id upserts
  • reconcile existing shell rows in migration 42 and self-heal a missing lifecycle summary on replay

why

fixes#5719.

common assistant messages and routine activities previously rebuilt thread shell fields by loading and decoding full message and activity history. the first fix replaced that with a scalar aggregate, but review found the aggregate still scanned and decoded every lifecycle row.

this revision moves normal runtime work to indexed point lookups plus one summary row. migration 42 safely upgrades databases that already recorded migration 41, ignores malformed json and non-string failure details, and repairs stale shell fields. live updates, owner-changing upserts, cursor replay, and revert reconstruction now use the same sqlite ordering and normalized state.

testing

  • vp test run apps/server/src/orchestration apps/server/src/persistence (302 passed)
  • vp run --filter t3 typecheck
  • vp check <changed server files>
  • git diff --check

regressions cover 10,000 matching lifecycle rows with large payloads, malformed lifecycle json, non-string failure details, activity-id and message-id replacement within and across threads, missing-summary replay, equal timestamps, stale/unknown response failures, migration 41-to-42 upgrades, shell-row reconciliation, and exact production query plans.

checklist

  • i have performed a self-review of my changes
  • i have added tests that prove my fix is effective
  • new and existing tests pass locally

Note

Medium Risk
Touches projection correctness for thread list badges and pending-input counts across migrations, transactional upserts, and revert rebuild paths; wrong deltas would show stale UI state but is well-covered by tests.

Overview
Thread list shell summary fields (latest_user_message_at, pending_user_input_count, etc.) no longer rebuild by loading full message/activity history on every routine event.

Persistence: Activities now store normalized user_input_request_id / user_input_state and maintain a per-thread projection_thread_user_input_summaries row via transactional upserts (including cross-thread activity-id moves). Messages upsert refreshes latest_user_message_at on affected threads through an indexed “latest user message” query.

Projection pipeline: In-memory derivePendingUserInputCountFromActivities and the old refreshThreadShellSummary full-scan path are removed. Common events update shell fields incrementally; thread.reverted still calls rebuildThreadShellSummary, which uses scalar/count queries instead of hydrating payloads.

Migrations 41–42: Add lifecycle indexing, then upgrade to the summary table + covering indexes and backfill/reconcile existing projection_threads rows (including safe handling of malformed JSON).

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

Note

Bound thread shell-summary reads using pre-aggregated counts instead of full activity hydration

  • Thread shell summary fields (pending_user_input_count, latest_user_message_at) are now maintained incrementally in projection_thread_user_input_summaries and directly on projection_threads, rather than being recomputed by scanning all activities/messages.
  • Activity upserts and deletes in ProjectionThreadActivities.ts maintain per-thread pending counts via delta updates to the summary table, including correct handling of cross-thread activity moves.
  • Message upserts and deletes in ProjectionThreadMessages.ts synchronize latest_user_message_at on projection_threads, including correcting the previous thread when a message moves.
  • ProjectionPipeline.ts projection handlers now call targeted repository aggregates per event type; thread.reverted triggers a full rebuildThreadShellSummary using persisted aggregates.
  • Migration 042 backfills user_input_request_id/user_input_state columns on activities, creates the summary table, and reconciles existing thread-level counts and timestamps.
  • Risk: upserts for activities and messages now run in transactions with additional reads and writes, increasing per-event DB load.

Macroscope summarized 6dba7cc.

Co-authored-by: maria <254055478+maria-rcks@users.noreply.github.com>
@github-actionsgithub-actionsBot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Aug 19, 2026
@github-actions

github-actionsBot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ℹ️ The exact PR base did not have a successful artifact. Baseline uses the latest successful main measurement shown below.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wire11.3 KiB12.4 KiB+1.1 KiB (+9.9%)15.1 KiB
CodexThread snapshot wire5.5 KiB6.3 KiB+837 B (+15.0%)7.3 KiB
CodexLive turn WebSocket wire5.9 KiB6.2 KiB+310 B (+5.2%)7.8 KiB
CodexLive turn WebSocket decoded49.7 KiB52.4 KiB+2.7 KiB (+5.3%)66.4 KiB
CodexLive turn messages1610−6 (−37.5%)21
ClaudeTotal thread wire11.3 KiB12.4 KiB+1.1 KiB (+9.6%)15.1 KiB
ClaudeThread snapshot wire5.5 KiB6.3 KiB+817 B (+14.6%)7.3 KiB
ClaudeLive turn WebSocket wire5.9 KiB6.1 KiB+301 B (+5.0%)7.8 KiB
ClaudeLive turn WebSocket decoded50.6 KiB53.2 KiB+2.7 KiB (+5.3%)66.4 KiB
ClaudeLive turn messages1610−6 (−37.5%)21

Baseline: 83d769f · PR result: 6dba7cc · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 99.9 KiB
  • Claude decoded thread snapshot: 100.6 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

@macroscopeapp

macroscopeappBot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR introduces database schema changes (new columns, tables, indexes) and refactors shell summary tracking from in-memory full-collection scans to transactional incremental updates with delta tracking. The PR's own description labels it 'Medium Risk' affecting projection correctness, warranting human review.

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

Co-authored-by: maria <254055478+maria-rcks@users.noreply.github.com>
@github-actionsgithub-actionsBot added size:XL 500-999 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Aug 19, 2026
@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing in favor of merged #8150, which removes repeated full-history reads from assistant messages and routine activities. The additional summary-state migration and lifecycle changes were not needed for that fix. 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:XL500-999 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.

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

1 participant

@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): bound thread shell-summary reads - #7486

Closed
t3-code[bot] wants to merge 2 commits into
mainfrom
fix/bound-thread-shell-summary
Closed

fix(server): bound thread shell-summary reads#7486
t3-code[bot] wants to merge 2 commits into
mainfrom
fix/bound-thread-shell-summary

Conversation

@t3-code

@t3-codet3-codeBot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

what changed

  • normalize user-input request ids and state transitions when projecting activities
  • maintain a one-row pending-input summary per thread through indexed old/new request lookups
  • read latest user-message timestamps through a partial covering index
  • repair old and new thread owners after destructive activity-id and message-id upserts
  • reconcile existing shell rows in migration 42 and self-heal a missing lifecycle summary on replay

why

fixes#5719.

common assistant messages and routine activities previously rebuilt thread shell fields by loading and decoding full message and activity history. the first fix replaced that with a scalar aggregate, but review found the aggregate still scanned and decoded every lifecycle row.

this revision moves normal runtime work to indexed point lookups plus one summary row. migration 42 safely upgrades databases that already recorded migration 41, ignores malformed json and non-string failure details, and repairs stale shell fields. live updates, owner-changing upserts, cursor replay, and revert reconstruction now use the same sqlite ordering and normalized state.

testing

  • vp test run apps/server/src/orchestration apps/server/src/persistence (302 passed)
  • vp run --filter t3 typecheck
  • vp check <changed server files>
  • git diff --check

regressions cover 10,000 matching lifecycle rows with large payloads, malformed lifecycle json, non-string failure details, activity-id and message-id replacement within and across threads, missing-summary replay, equal timestamps, stale/unknown response failures, migration 41-to-42 upgrades, shell-row reconciliation, and exact production query plans.

checklist

  • i have performed a self-review of my changes
  • i have added tests that prove my fix is effective
  • new and existing tests pass locally

Note

Medium Risk
Touches projection correctness for thread list badges and pending-input counts across migrations, transactional upserts, and revert rebuild paths; wrong deltas would show stale UI state but is well-covered by tests.

Overview
Thread list shell summary fields (latest_user_message_at, pending_user_input_count, etc.) no longer rebuild by loading full message/activity history on every routine event.

Persistence: Activities now store normalized user_input_request_id / user_input_state and maintain a per-thread projection_thread_user_input_summaries row via transactional upserts (including cross-thread activity-id moves). Messages upsert refreshes latest_user_message_at on affected threads through an indexed “latest user message” query.

Projection pipeline: In-memory derivePendingUserInputCountFromActivities and the old refreshThreadShellSummary full-scan path are removed. Common events update shell fields incrementally; thread.reverted still calls rebuildThreadShellSummary, which uses scalar/count queries instead of hydrating payloads.

Migrations 41–42: Add lifecycle indexing, then upgrade to the summary table + covering indexes and backfill/reconcile existing projection_threads rows (including safe handling of malformed JSON).

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

Note

Bound thread shell-summary reads using pre-aggregated counts instead of full activity hydration

  • Thread shell summary fields (pending_user_input_count, latest_user_message_at) are now maintained incrementally in projection_thread_user_input_summaries and directly on projection_threads, rather than being recomputed by scanning all activities/messages.
  • Activity upserts and deletes in ProjectionThreadActivities.ts maintain per-thread pending counts via delta updates to the summary table, including correct handling of cross-thread activity moves.
  • Message upserts and deletes in ProjectionThreadMessages.ts synchronize latest_user_message_at on projection_threads, including correcting the previous thread when a message moves.
  • ProjectionPipeline.ts projection handlers now call targeted repository aggregates per event type; thread.reverted triggers a full rebuildThreadShellSummary using persisted aggregates.
  • Migration 042 backfills user_input_request_id/user_input_state columns on activities, creates the summary table, and reconciles existing thread-level counts and timestamps.
  • Risk: upserts for activities and messages now run in transactions with additional reads and writes, increasing per-event DB load.

Macroscope summarized 6dba7cc.

Co-authored-by: maria <254055478+maria-rcks@users.noreply.github.com>
@github-actionsgithub-actionsBot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Aug 19, 2026
@github-actions

github-actionsBot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ℹ️ The exact PR base did not have a successful artifact. Baseline uses the latest successful main measurement shown below.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wire11.3 KiB12.4 KiB+1.1 KiB (+9.9%)15.1 KiB
CodexThread snapshot wire5.5 KiB6.3 KiB+837 B (+15.0%)7.3 KiB
CodexLive turn WebSocket wire5.9 KiB6.2 KiB+310 B (+5.2%)7.8 KiB
CodexLive turn WebSocket decoded49.7 KiB52.4 KiB+2.7 KiB (+5.3%)66.4 KiB
CodexLive turn messages1610−6 (−37.5%)21
ClaudeTotal thread wire11.3 KiB12.4 KiB+1.1 KiB (+9.6%)15.1 KiB
ClaudeThread snapshot wire5.5 KiB6.3 KiB+817 B (+14.6%)7.3 KiB
ClaudeLive turn WebSocket wire5.9 KiB6.1 KiB+301 B (+5.0%)7.8 KiB
ClaudeLive turn WebSocket decoded50.6 KiB53.2 KiB+2.7 KiB (+5.3%)66.4 KiB
ClaudeLive turn messages1610−6 (−37.5%)21

Baseline: 83d769f · PR result: 6dba7cc · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 99.9 KiB
  • Claude decoded thread snapshot: 100.6 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

@macroscopeapp

macroscopeappBot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR introduces database schema changes (new columns, tables, indexes) and refactors shell summary tracking from in-memory full-collection scans to transactional incremental updates with delta tracking. The PR's own description labels it 'Medium Risk' affecting projection correctness, warranting human review.

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

Co-authored-by: maria <254055478+maria-rcks@users.noreply.github.com>
@github-actionsgithub-actionsBot added size:XL 500-999 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Aug 19, 2026
@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing in favor of merged #8150, which removes repeated full-history reads from assistant messages and routine activities. The additional summary-state migration and lifecycle changes were not needed for that fix. 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:XL500-999 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.

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

1 participant

@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): bound thread shell-summary reads - #7486

Closed
t3-code[bot] wants to merge 2 commits into
mainfrom
fix/bound-thread-shell-summary
Closed

fix(server): bound thread shell-summary reads#7486
t3-code[bot] wants to merge 2 commits into
mainfrom
fix/bound-thread-shell-summary

Conversation

@t3-code

@t3-codet3-codeBot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

what changed

  • normalize user-input request ids and state transitions when projecting activities
  • maintain a one-row pending-input summary per thread through indexed old/new request lookups
  • read latest user-message timestamps through a partial covering index
  • repair old and new thread owners after destructive activity-id and message-id upserts
  • reconcile existing shell rows in migration 42 and self-heal a missing lifecycle summary on replay

why

fixes#5719.

common assistant messages and routine activities previously rebuilt thread shell fields by loading and decoding full message and activity history. the first fix replaced that with a scalar aggregate, but review found the aggregate still scanned and decoded every lifecycle row.

this revision moves normal runtime work to indexed point lookups plus one summary row. migration 42 safely upgrades databases that already recorded migration 41, ignores malformed json and non-string failure details, and repairs stale shell fields. live updates, owner-changing upserts, cursor replay, and revert reconstruction now use the same sqlite ordering and normalized state.

testing

  • vp test run apps/server/src/orchestration apps/server/src/persistence (302 passed)
  • vp run --filter t3 typecheck
  • vp check <changed server files>
  • git diff --check

regressions cover 10,000 matching lifecycle rows with large payloads, malformed lifecycle json, non-string failure details, activity-id and message-id replacement within and across threads, missing-summary replay, equal timestamps, stale/unknown response failures, migration 41-to-42 upgrades, shell-row reconciliation, and exact production query plans.

checklist

  • i have performed a self-review of my changes
  • i have added tests that prove my fix is effective
  • new and existing tests pass locally

Note

Medium Risk
Touches projection correctness for thread list badges and pending-input counts across migrations, transactional upserts, and revert rebuild paths; wrong deltas would show stale UI state but is well-covered by tests.

Overview
Thread list shell summary fields (latest_user_message_at, pending_user_input_count, etc.) no longer rebuild by loading full message/activity history on every routine event.

Persistence: Activities now store normalized user_input_request_id / user_input_state and maintain a per-thread projection_thread_user_input_summaries row via transactional upserts (including cross-thread activity-id moves). Messages upsert refreshes latest_user_message_at on affected threads through an indexed “latest user message” query.

Projection pipeline: In-memory derivePendingUserInputCountFromActivities and the old refreshThreadShellSummary full-scan path are removed. Common events update shell fields incrementally; thread.reverted still calls rebuildThreadShellSummary, which uses scalar/count queries instead of hydrating payloads.

Migrations 41–42: Add lifecycle indexing, then upgrade to the summary table + covering indexes and backfill/reconcile existing projection_threads rows (including safe handling of malformed JSON).

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

Note

Bound thread shell-summary reads using pre-aggregated counts instead of full activity hydration

  • Thread shell summary fields (pending_user_input_count, latest_user_message_at) are now maintained incrementally in projection_thread_user_input_summaries and directly on projection_threads, rather than being recomputed by scanning all activities/messages.
  • Activity upserts and deletes in ProjectionThreadActivities.ts maintain per-thread pending counts via delta updates to the summary table, including correct handling of cross-thread activity moves.
  • Message upserts and deletes in ProjectionThreadMessages.ts synchronize latest_user_message_at on projection_threads, including correcting the previous thread when a message moves.
  • ProjectionPipeline.ts projection handlers now call targeted repository aggregates per event type; thread.reverted triggers a full rebuildThreadShellSummary using persisted aggregates.
  • Migration 042 backfills user_input_request_id/user_input_state columns on activities, creates the summary table, and reconciles existing thread-level counts and timestamps.
  • Risk: upserts for activities and messages now run in transactions with additional reads and writes, increasing per-event DB load.

Macroscope summarized 6dba7cc.

Co-authored-by: maria <254055478+maria-rcks@users.noreply.github.com>
@github-actionsgithub-actionsBot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Aug 19, 2026
@github-actions

github-actionsBot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ℹ️ The exact PR base did not have a successful artifact. Baseline uses the latest successful main measurement shown below.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wire11.3 KiB12.4 KiB+1.1 KiB (+9.9%)15.1 KiB
CodexThread snapshot wire5.5 KiB6.3 KiB+837 B (+15.0%)7.3 KiB
CodexLive turn WebSocket wire5.9 KiB6.2 KiB+310 B (+5.2%)7.8 KiB
CodexLive turn WebSocket decoded49.7 KiB52.4 KiB+2.7 KiB (+5.3%)66.4 KiB
CodexLive turn messages1610−6 (−37.5%)21
ClaudeTotal thread wire11.3 KiB12.4 KiB+1.1 KiB (+9.6%)15.1 KiB
ClaudeThread snapshot wire5.5 KiB6.3 KiB+817 B (+14.6%)7.3 KiB
ClaudeLive turn WebSocket wire5.9 KiB6.1 KiB+301 B (+5.0%)7.8 KiB
ClaudeLive turn WebSocket decoded50.6 KiB53.2 KiB+2.7 KiB (+5.3%)66.4 KiB
ClaudeLive turn messages1610−6 (−37.5%)21

Baseline: 83d769f · PR result: 6dba7cc · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 99.9 KiB
  • Claude decoded thread snapshot: 100.6 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

@macroscopeapp

macroscopeappBot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR introduces database schema changes (new columns, tables, indexes) and refactors shell summary tracking from in-memory full-collection scans to transactional incremental updates with delta tracking. The PR's own description labels it 'Medium Risk' affecting projection correctness, warranting human review.

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

Co-authored-by: maria <254055478+maria-rcks@users.noreply.github.com>
@github-actionsgithub-actionsBot added size:XL 500-999 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Aug 19, 2026
@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing in favor of merged #8150, which removes repeated full-history reads from assistant messages and routine activities. The additional summary-state migration and lifecycle changes were not needed for that fix. 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:XL500-999 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.

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

1 participant

@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): bound thread shell-summary reads - #7486

Closed
t3-code[bot] wants to merge 2 commits into
mainfrom
fix/bound-thread-shell-summary
Closed

fix(server): bound thread shell-summary reads#7486
t3-code[bot] wants to merge 2 commits into
mainfrom
fix/bound-thread-shell-summary

Conversation

@t3-code

@t3-codet3-codeBot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

what changed

  • normalize user-input request ids and state transitions when projecting activities
  • maintain a one-row pending-input summary per thread through indexed old/new request lookups
  • read latest user-message timestamps through a partial covering index
  • repair old and new thread owners after destructive activity-id and message-id upserts
  • reconcile existing shell rows in migration 42 and self-heal a missing lifecycle summary on replay

why

fixes#5719.

common assistant messages and routine activities previously rebuilt thread shell fields by loading and decoding full message and activity history. the first fix replaced that with a scalar aggregate, but review found the aggregate still scanned and decoded every lifecycle row.

this revision moves normal runtime work to indexed point lookups plus one summary row. migration 42 safely upgrades databases that already recorded migration 41, ignores malformed json and non-string failure details, and repairs stale shell fields. live updates, owner-changing upserts, cursor replay, and revert reconstruction now use the same sqlite ordering and normalized state.

testing

  • vp test run apps/server/src/orchestration apps/server/src/persistence (302 passed)
  • vp run --filter t3 typecheck
  • vp check <changed server files>
  • git diff --check

regressions cover 10,000 matching lifecycle rows with large payloads, malformed lifecycle json, non-string failure details, activity-id and message-id replacement within and across threads, missing-summary replay, equal timestamps, stale/unknown response failures, migration 41-to-42 upgrades, shell-row reconciliation, and exact production query plans.

checklist

  • i have performed a self-review of my changes
  • i have added tests that prove my fix is effective
  • new and existing tests pass locally

Note

Medium Risk
Touches projection correctness for thread list badges and pending-input counts across migrations, transactional upserts, and revert rebuild paths; wrong deltas would show stale UI state but is well-covered by tests.

Overview
Thread list shell summary fields (latest_user_message_at, pending_user_input_count, etc.) no longer rebuild by loading full message/activity history on every routine event.

Persistence: Activities now store normalized user_input_request_id / user_input_state and maintain a per-thread projection_thread_user_input_summaries row via transactional upserts (including cross-thread activity-id moves). Messages upsert refreshes latest_user_message_at on affected threads through an indexed “latest user message” query.

Projection pipeline: In-memory derivePendingUserInputCountFromActivities and the old refreshThreadShellSummary full-scan path are removed. Common events update shell fields incrementally; thread.reverted still calls rebuildThreadShellSummary, which uses scalar/count queries instead of hydrating payloads.

Migrations 41–42: Add lifecycle indexing, then upgrade to the summary table + covering indexes and backfill/reconcile existing projection_threads rows (including safe handling of malformed JSON).

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

Note

Bound thread shell-summary reads using pre-aggregated counts instead of full activity hydration

  • Thread shell summary fields (pending_user_input_count, latest_user_message_at) are now maintained incrementally in projection_thread_user_input_summaries and directly on projection_threads, rather than being recomputed by scanning all activities/messages.
  • Activity upserts and deletes in ProjectionThreadActivities.ts maintain per-thread pending counts via delta updates to the summary table, including correct handling of cross-thread activity moves.
  • Message upserts and deletes in ProjectionThreadMessages.ts synchronize latest_user_message_at on projection_threads, including correcting the previous thread when a message moves.
  • ProjectionPipeline.ts projection handlers now call targeted repository aggregates per event type; thread.reverted triggers a full rebuildThreadShellSummary using persisted aggregates.
  • Migration 042 backfills user_input_request_id/user_input_state columns on activities, creates the summary table, and reconciles existing thread-level counts and timestamps.
  • Risk: upserts for activities and messages now run in transactions with additional reads and writes, increasing per-event DB load.

Macroscope summarized 6dba7cc.

Co-authored-by: maria <254055478+maria-rcks@users.noreply.github.com>
@github-actionsgithub-actionsBot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Aug 19, 2026
@github-actions

github-actionsBot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ℹ️ The exact PR base did not have a successful artifact. Baseline uses the latest successful main measurement shown below.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wire11.3 KiB12.4 KiB+1.1 KiB (+9.9%)15.1 KiB
CodexThread snapshot wire5.5 KiB6.3 KiB+837 B (+15.0%)7.3 KiB
CodexLive turn WebSocket wire5.9 KiB6.2 KiB+310 B (+5.2%)7.8 KiB
CodexLive turn WebSocket decoded49.7 KiB52.4 KiB+2.7 KiB (+5.3%)66.4 KiB
CodexLive turn messages1610−6 (−37.5%)21
ClaudeTotal thread wire11.3 KiB12.4 KiB+1.1 KiB (+9.6%)15.1 KiB
ClaudeThread snapshot wire5.5 KiB6.3 KiB+817 B (+14.6%)7.3 KiB
ClaudeLive turn WebSocket wire5.9 KiB6.1 KiB+301 B (+5.0%)7.8 KiB
ClaudeLive turn WebSocket decoded50.6 KiB53.2 KiB+2.7 KiB (+5.3%)66.4 KiB
ClaudeLive turn messages1610−6 (−37.5%)21

Baseline: 83d769f · PR result: 6dba7cc · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 99.9 KiB
  • Claude decoded thread snapshot: 100.6 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

@macroscopeapp

macroscopeappBot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR introduces database schema changes (new columns, tables, indexes) and refactors shell summary tracking from in-memory full-collection scans to transactional incremental updates with delta tracking. The PR's own description labels it 'Medium Risk' affecting projection correctness, warranting human review.

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

Co-authored-by: maria <254055478+maria-rcks@users.noreply.github.com>
@github-actionsgithub-actionsBot added size:XL 500-999 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Aug 19, 2026
@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing in favor of merged #8150, which removes repeated full-history reads from assistant messages and routine activities. The additional summary-state migration and lifecycle changes were not needed for that fix. 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:XL500-999 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.

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

1 participant

@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): bound thread shell-summary reads - #7486

Closed
t3-code[bot] wants to merge 2 commits into
mainfrom
fix/bound-thread-shell-summary
Closed

fix(server): bound thread shell-summary reads#7486
t3-code[bot] wants to merge 2 commits into
mainfrom
fix/bound-thread-shell-summary

Conversation

@t3-code

@t3-codet3-codeBot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

what changed

  • normalize user-input request ids and state transitions when projecting activities
  • maintain a one-row pending-input summary per thread through indexed old/new request lookups
  • read latest user-message timestamps through a partial covering index
  • repair old and new thread owners after destructive activity-id and message-id upserts
  • reconcile existing shell rows in migration 42 and self-heal a missing lifecycle summary on replay

why

fixes#5719.

common assistant messages and routine activities previously rebuilt thread shell fields by loading and decoding full message and activity history. the first fix replaced that with a scalar aggregate, but review found the aggregate still scanned and decoded every lifecycle row.

this revision moves normal runtime work to indexed point lookups plus one summary row. migration 42 safely upgrades databases that already recorded migration 41, ignores malformed json and non-string failure details, and repairs stale shell fields. live updates, owner-changing upserts, cursor replay, and revert reconstruction now use the same sqlite ordering and normalized state.

testing

  • vp test run apps/server/src/orchestration apps/server/src/persistence (302 passed)
  • vp run --filter t3 typecheck
  • vp check <changed server files>
  • git diff --check

regressions cover 10,000 matching lifecycle rows with large payloads, malformed lifecycle json, non-string failure details, activity-id and message-id replacement within and across threads, missing-summary replay, equal timestamps, stale/unknown response failures, migration 41-to-42 upgrades, shell-row reconciliation, and exact production query plans.

checklist

  • i have performed a self-review of my changes
  • i have added tests that prove my fix is effective
  • new and existing tests pass locally

Note

Medium Risk
Touches projection correctness for thread list badges and pending-input counts across migrations, transactional upserts, and revert rebuild paths; wrong deltas would show stale UI state but is well-covered by tests.

Overview
Thread list shell summary fields (latest_user_message_at, pending_user_input_count, etc.) no longer rebuild by loading full message/activity history on every routine event.

Persistence: Activities now store normalized user_input_request_id / user_input_state and maintain a per-thread projection_thread_user_input_summaries row via transactional upserts (including cross-thread activity-id moves). Messages upsert refreshes latest_user_message_at on affected threads through an indexed “latest user message” query.

Projection pipeline: In-memory derivePendingUserInputCountFromActivities and the old refreshThreadShellSummary full-scan path are removed. Common events update shell fields incrementally; thread.reverted still calls rebuildThreadShellSummary, which uses scalar/count queries instead of hydrating payloads.

Migrations 41–42: Add lifecycle indexing, then upgrade to the summary table + covering indexes and backfill/reconcile existing projection_threads rows (including safe handling of malformed JSON).

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

Note

Bound thread shell-summary reads using pre-aggregated counts instead of full activity hydration

  • Thread shell summary fields (pending_user_input_count, latest_user_message_at) are now maintained incrementally in projection_thread_user_input_summaries and directly on projection_threads, rather than being recomputed by scanning all activities/messages.
  • Activity upserts and deletes in ProjectionThreadActivities.ts maintain per-thread pending counts via delta updates to the summary table, including correct handling of cross-thread activity moves.
  • Message upserts and deletes in ProjectionThreadMessages.ts synchronize latest_user_message_at on projection_threads, including correcting the previous thread when a message moves.
  • ProjectionPipeline.ts projection handlers now call targeted repository aggregates per event type; thread.reverted triggers a full rebuildThreadShellSummary using persisted aggregates.
  • Migration 042 backfills user_input_request_id/user_input_state columns on activities, creates the summary table, and reconciles existing thread-level counts and timestamps.
  • Risk: upserts for activities and messages now run in transactions with additional reads and writes, increasing per-event DB load.

Macroscope summarized 6dba7cc.

Co-authored-by: maria <254055478+maria-rcks@users.noreply.github.com>
@github-actionsgithub-actionsBot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Aug 19, 2026
@github-actions

github-actionsBot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ℹ️ The exact PR base did not have a successful artifact. Baseline uses the latest successful main measurement shown below.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wire11.3 KiB12.4 KiB+1.1 KiB (+9.9%)15.1 KiB
CodexThread snapshot wire5.5 KiB6.3 KiB+837 B (+15.0%)7.3 KiB
CodexLive turn WebSocket wire5.9 KiB6.2 KiB+310 B (+5.2%)7.8 KiB
CodexLive turn WebSocket decoded49.7 KiB52.4 KiB+2.7 KiB (+5.3%)66.4 KiB
CodexLive turn messages1610−6 (−37.5%)21
ClaudeTotal thread wire11.3 KiB12.4 KiB+1.1 KiB (+9.6%)15.1 KiB
ClaudeThread snapshot wire5.5 KiB6.3 KiB+817 B (+14.6%)7.3 KiB
ClaudeLive turn WebSocket wire5.9 KiB6.1 KiB+301 B (+5.0%)7.8 KiB
ClaudeLive turn WebSocket decoded50.6 KiB53.2 KiB+2.7 KiB (+5.3%)66.4 KiB
ClaudeLive turn messages1610−6 (−37.5%)21

Baseline: 83d769f · PR result: 6dba7cc · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 99.9 KiB
  • Claude decoded thread snapshot: 100.6 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

@macroscopeapp

macroscopeappBot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR introduces database schema changes (new columns, tables, indexes) and refactors shell summary tracking from in-memory full-collection scans to transactional incremental updates with delta tracking. The PR's own description labels it 'Medium Risk' affecting projection correctness, warranting human review.

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

Co-authored-by: maria <254055478+maria-rcks@users.noreply.github.com>
@github-actionsgithub-actionsBot added size:XL 500-999 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Aug 19, 2026
@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing in favor of merged #8150, which removes repeated full-history reads from assistant messages and routine activities. The additional summary-state migration and lifecycle changes were not needed for that fix. 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:XL500-999 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.

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

1 participant

@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): bound thread shell-summary reads - #7486

Closed
t3-code[bot] wants to merge 2 commits into
mainfrom
fix/bound-thread-shell-summary
Closed

fix(server): bound thread shell-summary reads#7486
t3-code[bot] wants to merge 2 commits into
mainfrom
fix/bound-thread-shell-summary

Conversation

@t3-code

@t3-codet3-codeBot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

what changed

  • normalize user-input request ids and state transitions when projecting activities
  • maintain a one-row pending-input summary per thread through indexed old/new request lookups
  • read latest user-message timestamps through a partial covering index
  • repair old and new thread owners after destructive activity-id and message-id upserts
  • reconcile existing shell rows in migration 42 and self-heal a missing lifecycle summary on replay

why

fixes#5719.

common assistant messages and routine activities previously rebuilt thread shell fields by loading and decoding full message and activity history. the first fix replaced that with a scalar aggregate, but review found the aggregate still scanned and decoded every lifecycle row.

this revision moves normal runtime work to indexed point lookups plus one summary row. migration 42 safely upgrades databases that already recorded migration 41, ignores malformed json and non-string failure details, and repairs stale shell fields. live updates, owner-changing upserts, cursor replay, and revert reconstruction now use the same sqlite ordering and normalized state.

testing

  • vp test run apps/server/src/orchestration apps/server/src/persistence (302 passed)
  • vp run --filter t3 typecheck
  • vp check <changed server files>
  • git diff --check

regressions cover 10,000 matching lifecycle rows with large payloads, malformed lifecycle json, non-string failure details, activity-id and message-id replacement within and across threads, missing-summary replay, equal timestamps, stale/unknown response failures, migration 41-to-42 upgrades, shell-row reconciliation, and exact production query plans.

checklist

  • i have performed a self-review of my changes
  • i have added tests that prove my fix is effective
  • new and existing tests pass locally

Note

Medium Risk
Touches projection correctness for thread list badges and pending-input counts across migrations, transactional upserts, and revert rebuild paths; wrong deltas would show stale UI state but is well-covered by tests.

Overview
Thread list shell summary fields (latest_user_message_at, pending_user_input_count, etc.) no longer rebuild by loading full message/activity history on every routine event.

Persistence: Activities now store normalized user_input_request_id / user_input_state and maintain a per-thread projection_thread_user_input_summaries row via transactional upserts (including cross-thread activity-id moves). Messages upsert refreshes latest_user_message_at on affected threads through an indexed “latest user message” query.

Projection pipeline: In-memory derivePendingUserInputCountFromActivities and the old refreshThreadShellSummary full-scan path are removed. Common events update shell fields incrementally; thread.reverted still calls rebuildThreadShellSummary, which uses scalar/count queries instead of hydrating payloads.

Migrations 41–42: Add lifecycle indexing, then upgrade to the summary table + covering indexes and backfill/reconcile existing projection_threads rows (including safe handling of malformed JSON).

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

Note

Bound thread shell-summary reads using pre-aggregated counts instead of full activity hydration

  • Thread shell summary fields (pending_user_input_count, latest_user_message_at) are now maintained incrementally in projection_thread_user_input_summaries and directly on projection_threads, rather than being recomputed by scanning all activities/messages.
  • Activity upserts and deletes in ProjectionThreadActivities.ts maintain per-thread pending counts via delta updates to the summary table, including correct handling of cross-thread activity moves.
  • Message upserts and deletes in ProjectionThreadMessages.ts synchronize latest_user_message_at on projection_threads, including correcting the previous thread when a message moves.
  • ProjectionPipeline.ts projection handlers now call targeted repository aggregates per event type; thread.reverted triggers a full rebuildThreadShellSummary using persisted aggregates.
  • Migration 042 backfills user_input_request_id/user_input_state columns on activities, creates the summary table, and reconciles existing thread-level counts and timestamps.
  • Risk: upserts for activities and messages now run in transactions with additional reads and writes, increasing per-event DB load.

Macroscope summarized 6dba7cc.

Co-authored-by: maria <254055478+maria-rcks@users.noreply.github.com>
@github-actionsgithub-actionsBot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Aug 19, 2026
@github-actions

github-actionsBot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ℹ️ The exact PR base did not have a successful artifact. Baseline uses the latest successful main measurement shown below.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wire11.3 KiB12.4 KiB+1.1 KiB (+9.9%)15.1 KiB
CodexThread snapshot wire5.5 KiB6.3 KiB+837 B (+15.0%)7.3 KiB
CodexLive turn WebSocket wire5.9 KiB6.2 KiB+310 B (+5.2%)7.8 KiB
CodexLive turn WebSocket decoded49.7 KiB52.4 KiB+2.7 KiB (+5.3%)66.4 KiB
CodexLive turn messages1610−6 (−37.5%)21
ClaudeTotal thread wire11.3 KiB12.4 KiB+1.1 KiB (+9.6%)15.1 KiB
ClaudeThread snapshot wire5.5 KiB6.3 KiB+817 B (+14.6%)7.3 KiB
ClaudeLive turn WebSocket wire5.9 KiB6.1 KiB+301 B (+5.0%)7.8 KiB
ClaudeLive turn WebSocket decoded50.6 KiB53.2 KiB+2.7 KiB (+5.3%)66.4 KiB
ClaudeLive turn messages1610−6 (−37.5%)21

Baseline: 83d769f · PR result: 6dba7cc · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 99.9 KiB
  • Claude decoded thread snapshot: 100.6 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

@macroscopeapp

macroscopeappBot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR introduces database schema changes (new columns, tables, indexes) and refactors shell summary tracking from in-memory full-collection scans to transactional incremental updates with delta tracking. The PR's own description labels it 'Medium Risk' affecting projection correctness, warranting human review.

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

Co-authored-by: maria <254055478+maria-rcks@users.noreply.github.com>
@github-actionsgithub-actionsBot added size:XL 500-999 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Aug 19, 2026
@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing in favor of merged #8150, which removes repeated full-history reads from assistant messages and routine activities. The additional summary-state migration and lifecycle changes were not needed for that fix. 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:XL500-999 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.

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

1 participant

@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): bound thread shell-summary reads - #7486

Closed
t3-code[bot] wants to merge 2 commits into
mainfrom
fix/bound-thread-shell-summary
Closed

fix(server): bound thread shell-summary reads#7486
t3-code[bot] wants to merge 2 commits into
mainfrom
fix/bound-thread-shell-summary

Conversation

@t3-code

@t3-codet3-codeBot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

what changed

  • normalize user-input request ids and state transitions when projecting activities
  • maintain a one-row pending-input summary per thread through indexed old/new request lookups
  • read latest user-message timestamps through a partial covering index
  • repair old and new thread owners after destructive activity-id and message-id upserts
  • reconcile existing shell rows in migration 42 and self-heal a missing lifecycle summary on replay

why

fixes#5719.

common assistant messages and routine activities previously rebuilt thread shell fields by loading and decoding full message and activity history. the first fix replaced that with a scalar aggregate, but review found the aggregate still scanned and decoded every lifecycle row.

this revision moves normal runtime work to indexed point lookups plus one summary row. migration 42 safely upgrades databases that already recorded migration 41, ignores malformed json and non-string failure details, and repairs stale shell fields. live updates, owner-changing upserts, cursor replay, and revert reconstruction now use the same sqlite ordering and normalized state.

testing

  • vp test run apps/server/src/orchestration apps/server/src/persistence (302 passed)
  • vp run --filter t3 typecheck
  • vp check <changed server files>
  • git diff --check

regressions cover 10,000 matching lifecycle rows with large payloads, malformed lifecycle json, non-string failure details, activity-id and message-id replacement within and across threads, missing-summary replay, equal timestamps, stale/unknown response failures, migration 41-to-42 upgrades, shell-row reconciliation, and exact production query plans.

checklist

  • i have performed a self-review of my changes
  • i have added tests that prove my fix is effective
  • new and existing tests pass locally

Note

Medium Risk
Touches projection correctness for thread list badges and pending-input counts across migrations, transactional upserts, and revert rebuild paths; wrong deltas would show stale UI state but is well-covered by tests.

Overview
Thread list shell summary fields (latest_user_message_at, pending_user_input_count, etc.) no longer rebuild by loading full message/activity history on every routine event.

Persistence: Activities now store normalized user_input_request_id / user_input_state and maintain a per-thread projection_thread_user_input_summaries row via transactional upserts (including cross-thread activity-id moves). Messages upsert refreshes latest_user_message_at on affected threads through an indexed “latest user message” query.

Projection pipeline: In-memory derivePendingUserInputCountFromActivities and the old refreshThreadShellSummary full-scan path are removed. Common events update shell fields incrementally; thread.reverted still calls rebuildThreadShellSummary, which uses scalar/count queries instead of hydrating payloads.

Migrations 41–42: Add lifecycle indexing, then upgrade to the summary table + covering indexes and backfill/reconcile existing projection_threads rows (including safe handling of malformed JSON).

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

Note

Bound thread shell-summary reads using pre-aggregated counts instead of full activity hydration

  • Thread shell summary fields (pending_user_input_count, latest_user_message_at) are now maintained incrementally in projection_thread_user_input_summaries and directly on projection_threads, rather than being recomputed by scanning all activities/messages.
  • Activity upserts and deletes in ProjectionThreadActivities.ts maintain per-thread pending counts via delta updates to the summary table, including correct handling of cross-thread activity moves.
  • Message upserts and deletes in ProjectionThreadMessages.ts synchronize latest_user_message_at on projection_threads, including correcting the previous thread when a message moves.
  • ProjectionPipeline.ts projection handlers now call targeted repository aggregates per event type; thread.reverted triggers a full rebuildThreadShellSummary using persisted aggregates.
  • Migration 042 backfills user_input_request_id/user_input_state columns on activities, creates the summary table, and reconciles existing thread-level counts and timestamps.
  • Risk: upserts for activities and messages now run in transactions with additional reads and writes, increasing per-event DB load.

Macroscope summarized 6dba7cc.

Co-authored-by: maria <254055478+maria-rcks@users.noreply.github.com>
@github-actionsgithub-actionsBot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Aug 19, 2026
@github-actions

github-actionsBot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ℹ️ The exact PR base did not have a successful artifact. Baseline uses the latest successful main measurement shown below.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wire11.3 KiB12.4 KiB+1.1 KiB (+9.9%)15.1 KiB
CodexThread snapshot wire5.5 KiB6.3 KiB+837 B (+15.0%)7.3 KiB
CodexLive turn WebSocket wire5.9 KiB6.2 KiB+310 B (+5.2%)7.8 KiB
CodexLive turn WebSocket decoded49.7 KiB52.4 KiB+2.7 KiB (+5.3%)66.4 KiB
CodexLive turn messages1610−6 (−37.5%)21
ClaudeTotal thread wire11.3 KiB12.4 KiB+1.1 KiB (+9.6%)15.1 KiB
ClaudeThread snapshot wire5.5 KiB6.3 KiB+817 B (+14.6%)7.3 KiB
ClaudeLive turn WebSocket wire5.9 KiB6.1 KiB+301 B (+5.0%)7.8 KiB
ClaudeLive turn WebSocket decoded50.6 KiB53.2 KiB+2.7 KiB (+5.3%)66.4 KiB
ClaudeLive turn messages1610−6 (−37.5%)21

Baseline: 83d769f · PR result: 6dba7cc · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 99.9 KiB
  • Claude decoded thread snapshot: 100.6 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

@macroscopeapp

macroscopeappBot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR introduces database schema changes (new columns, tables, indexes) and refactors shell summary tracking from in-memory full-collection scans to transactional incremental updates with delta tracking. The PR's own description labels it 'Medium Risk' affecting projection correctness, warranting human review.

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

Co-authored-by: maria <254055478+maria-rcks@users.noreply.github.com>
@github-actionsgithub-actionsBot added size:XL 500-999 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Aug 19, 2026
@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing in favor of merged #8150, which removes repeated full-history reads from assistant messages and routine activities. The additional summary-state migration and lifecycle changes were not needed for that fix. 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:XL500-999 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.

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

1 participant

@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): bound thread shell-summary reads - #7486

Closed
t3-code[bot] wants to merge 2 commits into
mainfrom
fix/bound-thread-shell-summary
Closed

fix(server): bound thread shell-summary reads#7486
t3-code[bot] wants to merge 2 commits into
mainfrom
fix/bound-thread-shell-summary

Conversation

@t3-code

@t3-codet3-codeBot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

what changed

  • normalize user-input request ids and state transitions when projecting activities
  • maintain a one-row pending-input summary per thread through indexed old/new request lookups
  • read latest user-message timestamps through a partial covering index
  • repair old and new thread owners after destructive activity-id and message-id upserts
  • reconcile existing shell rows in migration 42 and self-heal a missing lifecycle summary on replay

why

fixes#5719.

common assistant messages and routine activities previously rebuilt thread shell fields by loading and decoding full message and activity history. the first fix replaced that with a scalar aggregate, but review found the aggregate still scanned and decoded every lifecycle row.

this revision moves normal runtime work to indexed point lookups plus one summary row. migration 42 safely upgrades databases that already recorded migration 41, ignores malformed json and non-string failure details, and repairs stale shell fields. live updates, owner-changing upserts, cursor replay, and revert reconstruction now use the same sqlite ordering and normalized state.

testing

  • vp test run apps/server/src/orchestration apps/server/src/persistence (302 passed)
  • vp run --filter t3 typecheck
  • vp check <changed server files>
  • git diff --check

regressions cover 10,000 matching lifecycle rows with large payloads, malformed lifecycle json, non-string failure details, activity-id and message-id replacement within and across threads, missing-summary replay, equal timestamps, stale/unknown response failures, migration 41-to-42 upgrades, shell-row reconciliation, and exact production query plans.

checklist

  • i have performed a self-review of my changes
  • i have added tests that prove my fix is effective
  • new and existing tests pass locally

Note

Medium Risk
Touches projection correctness for thread list badges and pending-input counts across migrations, transactional upserts, and revert rebuild paths; wrong deltas would show stale UI state but is well-covered by tests.

Overview
Thread list shell summary fields (latest_user_message_at, pending_user_input_count, etc.) no longer rebuild by loading full message/activity history on every routine event.

Persistence: Activities now store normalized user_input_request_id / user_input_state and maintain a per-thread projection_thread_user_input_summaries row via transactional upserts (including cross-thread activity-id moves). Messages upsert refreshes latest_user_message_at on affected threads through an indexed “latest user message” query.

Projection pipeline: In-memory derivePendingUserInputCountFromActivities and the old refreshThreadShellSummary full-scan path are removed. Common events update shell fields incrementally; thread.reverted still calls rebuildThreadShellSummary, which uses scalar/count queries instead of hydrating payloads.

Migrations 41–42: Add lifecycle indexing, then upgrade to the summary table + covering indexes and backfill/reconcile existing projection_threads rows (including safe handling of malformed JSON).

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

Note

Bound thread shell-summary reads using pre-aggregated counts instead of full activity hydration

  • Thread shell summary fields (pending_user_input_count, latest_user_message_at) are now maintained incrementally in projection_thread_user_input_summaries and directly on projection_threads, rather than being recomputed by scanning all activities/messages.
  • Activity upserts and deletes in ProjectionThreadActivities.ts maintain per-thread pending counts via delta updates to the summary table, including correct handling of cross-thread activity moves.
  • Message upserts and deletes in ProjectionThreadMessages.ts synchronize latest_user_message_at on projection_threads, including correcting the previous thread when a message moves.
  • ProjectionPipeline.ts projection handlers now call targeted repository aggregates per event type; thread.reverted triggers a full rebuildThreadShellSummary using persisted aggregates.
  • Migration 042 backfills user_input_request_id/user_input_state columns on activities, creates the summary table, and reconciles existing thread-level counts and timestamps.
  • Risk: upserts for activities and messages now run in transactions with additional reads and writes, increasing per-event DB load.

Macroscope summarized 6dba7cc.

Co-authored-by: maria <254055478+maria-rcks@users.noreply.github.com>
@github-actionsgithub-actionsBot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Aug 19, 2026
@github-actions

github-actionsBot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ℹ️ The exact PR base did not have a successful artifact. Baseline uses the latest successful main measurement shown below.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wire11.3 KiB12.4 KiB+1.1 KiB (+9.9%)15.1 KiB
CodexThread snapshot wire5.5 KiB6.3 KiB+837 B (+15.0%)7.3 KiB
CodexLive turn WebSocket wire5.9 KiB6.2 KiB+310 B (+5.2%)7.8 KiB
CodexLive turn WebSocket decoded49.7 KiB52.4 KiB+2.7 KiB (+5.3%)66.4 KiB
CodexLive turn messages1610−6 (−37.5%)21
ClaudeTotal thread wire11.3 KiB12.4 KiB+1.1 KiB (+9.6%)15.1 KiB
ClaudeThread snapshot wire5.5 KiB6.3 KiB+817 B (+14.6%)7.3 KiB
ClaudeLive turn WebSocket wire5.9 KiB6.1 KiB+301 B (+5.0%)7.8 KiB
ClaudeLive turn WebSocket decoded50.6 KiB53.2 KiB+2.7 KiB (+5.3%)66.4 KiB
ClaudeLive turn messages1610−6 (−37.5%)21

Baseline: 83d769f · PR result: 6dba7cc · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 99.9 KiB
  • Claude decoded thread snapshot: 100.6 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

@macroscopeapp

macroscopeappBot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR introduces database schema changes (new columns, tables, indexes) and refactors shell summary tracking from in-memory full-collection scans to transactional incremental updates with delta tracking. The PR's own description labels it 'Medium Risk' affecting projection correctness, warranting human review.

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

Co-authored-by: maria <254055478+maria-rcks@users.noreply.github.com>
@github-actionsgithub-actionsBot added size:XL 500-999 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Aug 19, 2026
@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing in favor of merged #8150, which removes repeated full-history reads from assistant messages and routine activities. The additional summary-state migration and lifecycle changes were not needed for that fix. 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:XL500-999 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.

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

1 participant

@t3dotgg