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.
2 files changedLine totals unavailable