Fix flicker of pushed-off sticky project header in threads sidebar (#57529)

The threads sidebar rebuilds its `Vec<ListEntry>` from scratch on events
that touch thread/sidebar state (status changes, title generation, new
live info, sending a message, etc.). It previously called
`ListState::reset` after every rebuild, which rewrote every list item to
`Unmeasured`. On the next render frame, the sticky project header had no
measured bounds for the next project header.

The sticky project header uses `ListState::bounds_for_item` for the next
project header to compute how far it should be pushed off screen. When
those measurements were missing, it temporarily fell back to `top_offset
= 0`, snapped fully into view for one frame, then popped back once the
list was remeasured.

Fix: preserve list measurements for entries whose identity and layout
shape did not change. `EntryShape` captures each entry's identity plus
height-affecting project-header flags. `update_entries` snapshots the
old shapes, rebuilds contents, then splices only the changed shape range
into `ListState`. Unchanged items keep their measured bounds, so the
sticky header remains in its pushed-off position across same-shape
updates.

This also adds a regression test that renders a two-project sidebar,
scrolls into the sticky-header push-off state, performs a same-shape
thread metadata update, and verifies the next header's measured bounds
are preserved.

Closes AI-196

Release Notes:

- Fixed the project section header flickering in the agent threads
sidebar when sending a message while the header was partially scrolled
off screen.
a8966695eeMartinYe1234 committed on 5/26/2026, 2:41:26 PM· committed by GitHubparenteb944cf
2 files changedLine totals unavailable