perf(threads): reuse derived state while loading activity - #9508
Open
extoci wants to merge 2 commits into
Open
Conversation
extoci
marked this pull request as ready for review
September 4, 2026 00:26
Contributor
ApprovabilityVerdict: Not approved Macroscope's review found this PR not approvable — This PR replaces existing activity and timeline derivation with stateful incremental projections across multiple production modules, including lifecycle folding, grouping, ordering, and shared summaries. The cross-cutting new state management and behavior changes make it broader than a low-risk isolated performance tweak. You can add or adjust custom eligibility rules. Learn more. |
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.
Summary
Long-running web threads repeatedly rebuilt work-log, timeline, and row projections when activity or messages changed. This change reuses immutable projection state across exact appends, keeps active timeline scan state with its owning timeline, and incrementally accumulates work-group presentation data.
The optimization is deliberately scoped to the web client. Mobile call sites are unchanged and can move to the shared incremental APIs in a follow-up PR.
Measured impact
Measured on a read-only snapshot of the current local state: 174 activity-bearing threads and 77,748 activities. Values are median projection times on the same machine; the average row is the real 441-activity thread nearest the corpus mean of 446.8 activities. The 2× and 10× cases duplicate the real maximum-thread activity shape with unique identities.
For 100 live updates using the maximum-thread shape, the full projection fanout went from 23.83 s to 22.88 s: 4.0% less time. The cold-load improvement is larger because it removes repeated full sorting, folding, and presentation work; the remaining live cost includes other projections that this PR does not change.
Validation
Model: GPT-5.6
Harness: Codex
Note
Medium Risk
Incremental projection logic is subtle (prefix checks, WeakMaps, lifecycle edge cases); bugs could show wrong tool groups, stale timeline rows, or incorrect changed-file chips without failing tests on typical threads.
Overview
Speeds up long web chat threads by reusing derived state when messages, plans, and activities only grow at the end, instead of rebuilding work-log folds, merged timeline rows, and message-timeline rows on every tick.
ChatViewnow keepsWorkLogEntriesProjectionandTimelineEntriesProjectionin refs and callsderiveWorkLogEntriesWithState/deriveTimelineEntriesWithState, which clone fold indexes only for the new activity suffix and merge timeline entries while preserving stable object identity where possible.MessagesTimelineowns anactiveTimelineScanRef(reset on thread change) so live “active tool” scanning and work-group presentation can append incrementally via WeakMap-anchored caches andToolGroupSummaryAccumulatorfrom client-runtime, with sliced snapshots for expanded groups so UI arrays stay immutable.session-logicalso tightens work-log metadata:changedFilesonly for mutating tool types (not dynamic reads), faster activity ordering/pending-derivation paths, and small command/detail parsing optimizations.Tests cover projection reuse, branch-safe snapshots, per-timeline scan isolation, and changed-file rules.
Reviewed by Cursor Bugbot for commit 71dbdae. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Reuse derived work-log and timeline state for incremental activity loading
WorkLogEntriesProjection,TimelineEntriesProjection) that cache derived entries and fold state. When the prior source arrays are an exact immutable prefix, only the suffix is derived; otherwise the full path rebuilds state.deriveMessagesTimelineRowsand theMessagesTimelinecomponent so active-turn scanning reuses prior scan state across renders.ToolGroupSummaryAccumulatorand switches activity ordering to a cachedorderedActivitieshelper.toDerivedWorkLogEntryto retain paths from MCP tool results and mutating dynamic tools while suppressing read-tool paths; prefersitem.commandinextractToolCommandand unifies the command preview inextractToolDetail.deriveTurnFoldsso unsettled-turn entries are skipped from the settled-turn fold map.toolGroupSummaryKindnow records an entry's action inallActionsbefore handlingtoolSourceentries, so source-bearing entries participate in single-action vs mixed classification. Branch-point projections inderiveWorkLogEntriesWithStateandderiveTimelineEntriesWithStatemust remain immutable after creation; mutating a returned projection's source arrays will break suffix reuse.Macroscope summarized 71dbdae.