Bug
In the channel top-level message list, an edited message renders its newest content, but clicking reply to open the thread view shows the stale pre-edit content until (and unless) an async backfill lands.
a message edited from "two PRs" (2 list items) to "these PRs" (3 list items) shows correctly in the timeline but reverts to "two PRs" in the thread panel head. (see attached screenshots)
Root cause
desktop/src/features/messages/lib/independentThreadPanel.ts: buildIndependentThreadPanel extracts a single head content event by id from the channel window and builds events = [head, ...replyEvents], discarding the head's aux overlay events (edits kind:40003, deletions, reactions) that already sit beside it in that same window.
formatTimelineMessages only applies an edit when the edit event is in the same array as its target. The main timeline has both, so it renders correctly. The thread head relies solely on the async withThreadAux fetch to re-supply the edit — so it renders stale whenever that fetch lags, races, or misses.
Fix
Carry the head's non-content aux events (via !isTimelineContentEvent) from the channel window into the thread head's event array, deduped against replyEvents by id. The thread head becomes byte-identical to the main timeline the instant the thread opens, independent of the async aux fetch. Restricted to non-content kinds so reply content rows never leak in.
Tests
- Unit regression
independentThreadPanel.test.mjs: red pre-fix, green post-fix.
- e2e
thread-head-stale-edit.spec.ts: delays thread-replies aux to force the channel-window-vs-thread-aux divergence; asserts the thread panel head shows edited content. Red pre-fix (stale head), green post-fix.
- Full desktop unit suite: 5562 pass / 0 fail.

Bug
In the channel top-level message list, an edited message renders its newest content, but clicking reply to open the thread view shows the stale pre-edit content until (and unless) an async backfill lands.
a message edited from "two PRs" (2 list items) to "these PRs" (3 list items) shows correctly in the timeline but reverts to "two PRs" in the thread panel head. (see attached screenshots)
Root cause
desktop/src/features/messages/lib/independentThreadPanel.ts:buildIndependentThreadPanelextracts a single head content event by id from the channel window and buildsevents = [head, ...replyEvents], discarding the head's aux overlay events (editskind:40003, deletions, reactions) that already sit beside it in that same window.formatTimelineMessagesonly applies an edit when the edit event is in the same array as its target. The main timeline has both, so it renders correctly. The thread head relies solely on the asyncwithThreadAuxfetch to re-supply the edit — so it renders stale whenever that fetch lags, races, or misses.Fix
Carry the head's non-content aux events (via
!isTimelineContentEvent) from the channel window into the thread head's event array, deduped againstreplyEventsby id. The thread head becomes byte-identical to the main timeline the instant the thread opens, independent of the async aux fetch. Restricted to non-content kinds so reply content rows never leak in.Tests
independentThreadPanel.test.mjs: red pre-fix, green post-fix.thread-head-stale-edit.spec.ts: delays thread-replies aux to force the channel-window-vs-thread-aux divergence; asserts the thread panel head shows edited content. Red pre-fix (stale head), green post-fix.