fix(tui): bound inbox delivery verification loop and stop duplicate pastes#204
Merged
Merged
Conversation
…astes Claude Code now runs in the tmux alternate screen, so capture-pane verification only sees the visible viewport; long bracketed pastes also collapse in the composer, so the [msg:from:seq] snippet may never be visible. The inbox poll had no terminal state for verification failure: the head seq was re-pasted up to 3 times per cycle, every cycle, forever, duplicating deliveries and blocking all later seqs. - Track consecutive verification-failure cycles per (target, head seq), carried across cycles like stuck_skip_counts and reset on head-seq change or successful delivery. After 3 failed cycles, log a loud WARN and force-advance the cursor via inbox::mark_delivered; the inbox.jsonl row remains the durable record. Only cycles where the message actually reached the pane count — pure inject failures never force-advance. - Within one delivery cycle, once inject_message_to succeeds (or the snippet is observed in the pane), later attempts only send Enter and re-verify; the full message is never pasted twice in a cycle. - Add -J to the verification capture-pane call and match snippets via a newline-stripping snippet_in_capture helper so pane-wrapped delivery tags still match. Verified with a scratch tmux smoke (alt-screen, echo-suppressed pane emulating the collapsed-paste failure): a 5.4KB/30-line message pasted exactly once per cycle, force-advanced after 3 cycles with a WARN, and the next seq was unblocked; a short message in an echoing pane still verified normally with a single paste. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- snippet_in_capture now strips all whitespace (not just newlines): Claude's renderer hard-wraps long lines at its layout width with an indented continuation margin, which tmux -J cannot join. Delivery tags contain no meaningful whitespace, so false-positive risk is negligible. Adds a Claude-style wrapped-capture test case. - Skip the generic "delivery failed after N attempts" error on the cycle where force-advance fires — the force-advance WARN already tells the whole story and the generic error was being logged after it. Review: researcher agman-improvements--pm-inbox-delivery-verification-loop approved ef2ac98; these are their two optional non-blocking findings. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Gives inbox delivery verification a terminal state and stops duplicate message pastes.
inbox.jsonlrow remains the durable record. Only cycles where the message actually reached the pane count — a pure tmux/inject failure can never skip an undelivered message.capture-pane -Jand a whitespace-insensitive snippet match, so delivery tags split by pane or composer line-wrapping still match.Why
Claude Code now runs in the tmux alternate screen, so capture-pane verification only sees the visible viewport, and long bracketed pastes collapse in the composer — the
[msg:from:seq]delivery tag can be permanently invisible to verification even though the message arrived. With no terminal state, the poll loop re-pasted the same head message up to 3× per cycle forever: real duplicate deliveries to the PM, and every later message blocked behind the unverifiable head. This reproduced live (a PM stuck redelivering a 5.6KB reviewer message) and required manual cursor surgery to clear.🤖 Generated with Claude Code