fix(desktop): unify observer feed scroll onto useAnchoredScroll#1825
Merged
Conversation
The agent observer feed pinned to bottom via useStickToBottom, a mount-once effect with empty deps — a no-op when observer events hadn't rendered yet, causing nondeterministic auto-scroll on open. Replaces it with the shared useAnchoredScroll hook already used by the inbox timeline, gated on connectionState instead of a fixed mount timing. Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Raw ACP mode rendered each observer event as a bare <details> with no data-message-id, so useAnchoredScroll's mid-history anchor scan found no rows there — a scroll-up in raw mode would compute as at-bottom and get yanked back down on the next streamed frame or payload expansion. Keys the attribute off the same seq used to build anchoredScrollMessages. Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Observer seq is a per-agent-process monotonic counter (buzz-acp's ObserverHandle) that resets to 1 on every agent restart while timestamp keeps climbing, so a bare seq id collides across restarts within one channel's combined observer window. That broke two paths sharing the same seq-only id: the raw event rail's data-message-id (a later scroll-up anchor resolving to an older same-seq row) and the outer scroll list's prop-id delta classification (a post-restart append misclassified as unchanged, suppressing the auto-snap this feature exists to fix). Add a shared observerEventScrollId(seq, timestamp) helper and use it at both id sites instead of String(seq). Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
This was referenced Jul 13, 2026
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.
The agent observer feed panel pinned to bottom via
useStickToBottom, a mount-once effect with empty deps that no-ops when observer events haven't rendered yet — the source of the reported "sometimes it snaps to latest, sometimes it doesn't" behavior.Replaces it with the shared
useAnchoredScrollhook already used by the inbox timeline, at the same container level (AuxiliaryPanelBody) the panel already scrolls:messagessourced fromcombinedHeaderEvents(live + archived merged) so an idle agent's archived-only feed still snaps to latest, not just live-onlyscopedEventsisLoadingderived fromconnectionState === "connecting"so init waits for the first real paint instead of a fixed mount timingpinTargetCentered: false, notargetMessageId) — this panel has no deep-link caseuseLoadOlderOnScroll+ top sentinel for archive paging left untoucheduseStickToBottom.tsdeleted (this panel was its only consumer)Related: #1817