Fix long-thread database and event-loop stalls - #2025
Merged
Merged
Conversation
ymichael
added a commit
that referenced
this pull request
Aug 20, 2026
## What was wrong The active thread timeline and the full-history conversation outline shared the same realtime invalidation group, so every events-appended streaming batch sent another /conversation-outline request. The server cache hardening now on main from #2025 avoids rebuilding for outline-irrelevant events, but the client still performs redundant HTTP reads at streaming cadence, and assistant text deltas can still invalidate the full projection. The outline does not need sub-second route refreshes because the incremental timeline already carries the live conversation rows. ## What changed - Split realtime timeline-window invalidation from conversation-outline invalidation. - Refresh the full outline at the terminal turn boundary instead of for every streaming delta; unknown lifecycle notifications still invalidate it conservatively, and history rewrites retain the existing full invalidation path. - Overlay live timeline conversation rows onto the cached full outline so current user and assistant messages remain fresh while a turn streams. - Reconciled the server cache documentation with the outline-aware cache added by #2025 and the new client refresh policy. - Added regressions proving streaming deltas do not refetch the outline, turn completion does, and live timeline labels replace or extend a cached outline. This implements the client-side pacing direction from #1972 using a turn boundary plus live-row overlay instead of a timed debounce. It does not change the API contract or the server/daemon wire format, so HOST_DAEMON_PROTOCOL_VERSION is unchanged. ## How you verified The new realtime invalidation test fails before the change because an assistant delta refetches the active outline query. The TOC merge test also fails before the change because a loaded outline always wins over newer timeline rows. After rebasing onto origin/main at 0b2723a: - pnpm exec turbo run test --filter=@bb/app -- src/hooks/cache-owners/cache-owner-registry.test.ts src/hooks/realtime-cache-effects.test.ts src/components/thread/toc/ThreadTableOfContents.test.tsx — 80 tests passed - pnpm exec turbo run typecheck --filter=@bb/app — passed - git diff --check origin/main...HEAD — passed Fixes #1972 > AGENT GENERATED: by GPT-5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What was wrong
Long-lived threads repeatedly scanned JSON payloads for todo tool names, rebuilt the full conversation outline for unrelated command and reasoning events, and pruned arbitrarily large sets of resolved deltas in one synchronous SQLite write. Those paths blocked the server event loop and delayed otherwise small event inserts. Separately, stall diagnostics attributed awaited RPC wall time as event-loop work, treated laptop suspension as a runtime stall, and warned on fresh 512-event bursts before there was evidence that delivery was stuck.
What changed
The timeline byte limit and default event budget are intentionally unchanged. There are no server/host wire changes, so HOST_DAEMON_PROTOCOL_VERSION is unchanged.
How you verified
The full server suite was also attempted, but existing npm-artifact packaging tests do not produce a clean signal in this sandbox; all suites covering changed server paths passed.
Fixes: N/A — log-driven performance investigation.