Skip to content

fix(desktop): unify observer feed scroll onto useAnchoredScroll#1825

Merged
wpfleger96 merged 3 commits into
mainfrom
duncan/observer-scroll-unify
Jul 13, 2026
Merged

fix(desktop): unify observer feed scroll onto useAnchoredScroll#1825
wpfleger96 merged 3 commits into
mainfrom
duncan/observer-scroll-unify

Conversation

@wpfleger96

Copy link
Copy Markdown
Collaborator

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 useAnchoredScroll hook already used by the inbox timeline, at the same container level (AuxiliaryPanelBody) the panel already scrolls:

  • messages sourced from combinedHeaderEvents (live + archived merged) so an idle agent's archived-only feed still snaps to latest, not just live-only scopedEvents
  • isLoading derived from connectionState === "connecting" so init waits for the first real paint instead of a fixed mount timing
  • bottom-tail only (pinTargetCentered: false, no targetMessageId) — this panel has no deep-link case
  • existing useLoadOlderOnScroll + top sentinel for archive paging left untouched
  • useStickToBottom.ts deleted (this panel was its only consumer)

Related: #1817

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>
@wpfleger96 wpfleger96 requested a review from a team as a code owner July 13, 2026 20:54
npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 and others added 2 commits July 13, 2026 17:09
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>
@wpfleger96 wpfleger96 merged commit d75c2e9 into main Jul 13, 2026
23 of 24 checks passed
@wpfleger96 wpfleger96 deleted the duncan/observer-scroll-unify branch July 13, 2026 21:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant