Conversation
A latest timeline page reports olderRowsSourceSeqEnd for rows it omits. When a row on an older page keeps receiving events (a running background subagent under a later message), that value passes the client's loaded tip on every event. The client then drops its loaded history, reloads the older pages, and repeats, so the transcript flickers. The latest page now sends omitted rows that reach its window start as timelinePage.olderRowUpdates, cut to the children that reach it. The client joins them into its loaded rows by id, and those rows no longer count toward olderRowsSourceSeqEnd. The latest build also backfills delegation progress and completion state, so a pulled-in delegation keeps its status and output. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
hemaaanth
force-pushed
the
fix/timeline-omitted-row-rebuild-loop
branch
from
September 26, 2026 05:59
be6695e to
f53a197
Compare
This branch has not been deployed
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.
Human comments
What was wrong
A latest timeline page reports
timelinePage.olderRowsSourceSeqEnd, the highestsourceSeqEndof the rows it omits.mergeAdvancedSnapshotTimelineRowsrebuilds from the latest page when that value is past the client's loaded tip. #3686 documented this as a known limitation.A long-running background subagent (a
delegationrow) under a later message trips this on every event. The delegation's turn sits on an older page but keeps getting child rows. Each new event pushesolderRowsSourceSeqEndpast the tip. The client drops its loaded history,useAutoLoadOlderRowsloads the older pages again, and the next event repeats this. The transcript flips several times a second between full history and "Loading older messages…". See #4388 for the live trace.Also, the latest page did not include the thread-scoped
item/delegation/progressanditem/delegation/completedevents for a delegation whose turn it pulled in. That delegation projected as pending with no output.What changed
paginateTimelineRows: on a latest page, omitted rows whosesourceSeqEndreaches the window start go to a newtimelinePage.olderRowUpdatesarray, not intoolderRowsSourceSeqEnd.children/childRowssuffix that reaches the window start, applied recursively.timelineWindowsAreContiguous), so this suffix holds every child that changed after the tip.olderRowsSourceSeqEndas before. Leaves cut by a content page still always count, so that limitation remains.mergeAdvancedSnapshotTimelineRowsjoins each update into the loaded row with the same id, usingprependOlderTimelineRows, the same join used for partial latest rows. It ignores updates for rows it has not loaded.listLatestBackgroundTaskStateRowsByItemIdsalso returns the latest delegation progress/completed row, and the timeline window backfill applies it to delegation items. Without this, an update replaces a completed delegation with a pending one.olderRowUpdatesontimelinePageMetadataSchema, with allowlist entries.docs/timeline-pagination.mddescribes the updates.HOST_DAEMON_PROTOCOL_VERSION, CLI or SDK changes.How you verified
timeline-event-budget.test.tscase: a running subagent under a later message streams child messages. The test reads each latest page, walks the older pages, and merges like the client. Onmainat2726ab1ee, the merge takes the rebuild path after the first event. With the fix, loaded history stays equal to a fresh full walk. It also fails if the delegation state backfill is removed.paginateTimelineRowsupdate cutting and the byte-budget fallback; the client merge joining updates; the delegation state backfill query.pnpm exec turbo run test --filter=@bb/db --filter=@bb/server-contract --filter=@bb/client-core --filter=@bb/server --continue --force:@bb/db,@bb/server-contractand@bb/client-corepassed.@bb/server: 3241 passed, 1 skipped, and 3 timed out ininstall-machine-script.test.ts, which this change does not touch. That file passes on its own, together withtimeline-event-budget.test.ts(74/74).pnpm exec turbo run typecheck lintfor those packages passed.oxfmt --checkpasses on the changed files.Fixes #4388
🤖 Generated with Claude Code