agent pane: a steer that lands as the turn ends shows once

Merged
TE
16d ago
+181-0

When a steer reaches Claude Code just as its turn ends, acpmux records the steer row, gets STEER_NO_TURN, and runs the same prompt (same promptId) as the next turn, recording it again (hub/steer_end.rs โ†’ run_prompt). The agent got it once; the pane drew it twice, the first row marked read.

Fix: the pane's transcript model (direct.ts) keeps each steer's row by promptId; a non-steer prompt with that promptId replaces the steer's row. A rebuild or resync replays in order, so the dedupe holds there too. An older page folds in after the rows below it, and pages split before a turn-opening prompt, so the steer can arrive after the prompt it became: the pane remembers the promptIds it drew as prompts, and such a steer draws nothing.

Test

bun test test/agent-pane-steer-race.test.ts in webviews/:

  • red at 98799ea2f6: rows were [prompt, steer (landed), same text again];
  • green at 8a4f1e7f67: [prompt, the message once, not a steer]. A second case checks a read steer and a later prompt with its own id keep both rows.
  • paging (open at the next turn, scroll up to the steer): red in CI at c265b006af (rows: prompt, steer (landed), same text again), green in CI at fe33e0f4d9.

Observed / Not run

  • Ran: the new test (red, then green); 31 tests across the non-browser pane files (turn-opener, view-race, session-start, hold-acting-chat, compaction-rows, subagent-stopped-after-cancel, promptAccepted); scripts/web-lint.sh passed.
  • CI at fe33e0f4d9: the steer-race file passes. Other reds are base: the defaults snapshot (stale CmuxNextSettings exports), release-notary and Guard status; webviews files that also fail on merged #22831 (suggested-tasks, composer-history, composer-mention, composer-suggested-prompt, background-tasks, wheel-pass-through) or are new on the merge ref (agent-pane-adopted-tool-calls), plus math typesetting and quiet-access-chip colors, which have no prompt fixtures.
  • Since the hook blocks local bun test here, the paging test ran only in CI.
  • Not run: the Playwright browser files (agent-pane-steer*, queue*), left to CI. Not changed: the TUI/CLI transcript (acpmux/src/transcript.rs), which can show the same two rows.

Changelog

  • Fixed: a message sent while an agent's turn was ending no longer shows twice in the chat.

๐Ÿค– Generated with Claude Code

Agent session: cosmic-gray