What happens. The index announces a repository read newest first. reread applies the listing in that order (crates/vibescrobble-index/src/relay.rs:463-478), and so does a relist after a gap (backfill.rs:238-252). It runs when the stream first draws an account (worker.rs:539), when an account comes back from inactive, and after every gap. The index sorts what it holds (#111). The canvas does not: addScrobble sets agent.text and agent.emoji from each live event as it arrives (web/graph/feed.js:544), pushes a callout for each one (feed.js:591), and the detail panel appends in arrival order (web/detail.js:1431). The canvas ends on the oldest line read and shows it as what the agent is doing now. It stays that way until the page reloads or the agent posts again. /lanes sorts by time (web/model.js:110) and is right, so the two pages disagree.
How to reproduce. A throwaway node --test built on web/dev/test/canvas.test.mjs's harness applies a session, then line 9 live, then line 8, 7, 6, 5 live, the order a reread announces. state.agents.get(session).text is "line 5". state.floats holds all five callouts in that order.
Why it matters. An agent that returns after being let go for room, or that wrote several lines during a stream gap, is shown with stale intent. Each of those reads also replays its history as a burst of callouts.
Fixed by https://tangled.org/permadeath.com/vibescrobble.com/pulls/375, now on main.