fix(tui): unify keyboard input into a single reader thread - #817
Open
judyks wants to merge 1 commit into
Open
Conversation
Two threads previously read the same crossterm event queue: a nav-only poller thread (alive through the confirm prompt) and the prompts' own blocking readers. Whichever reader won the race got the key, so at the project-confirm prompt 'y' could scroll the log instead of accepting and Enter could be silently dropped. The language/framework re-pick prompts and the file picker (when tailoring was skipped) raced the same way. Replace both poller variants with one input hub thread that owns event::read() for the whole run and routes by a shared flag: - Execution route: nav keys become NavCmds, quit keys (q/Q/Esc/Ctrl+C) set a watch-channel cancel signal, resizes request a redraw. - Prompt route: every key and resize is forwarded verbatim to the active prompt over a channel; the renderer flips the route flag on prompt entry/exit and drains stale events on entry. This also fixes two adjacent defects: - Cancellation now works outside tailoring: quit keys abort the 503 backoff and API fetch immediately (the cancel future now wraps attempts and backoff sleeps alike), and take effect at stage boundaries after the synchronous analysis/signals phases. Previously the nav-only poller deliberately ignored quit keys and raw mode ate Ctrl+C, so nothing before tailoring could be cancelled. - Resize events are no longer discarded: prompt loops and review mode redraw immediately on resize, and the 503 backoff now sleeps in 1s slices with a live countdown so the frame stays current during waits. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V9Rz9BcK1xb1jiGNER1FeU
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.
Two threads previously read the same crossterm event queue: a nav-only
poller thread (alive through the confirm prompt) and the prompts' own
blocking readers. Whichever reader won the race got the key, so at the
project-confirm prompt 'y' could scroll the log instead of accepting and
Enter could be silently dropped. The language/framework re-pick prompts
and the file picker (when tailoring was skipped) raced the same way.
Replace both poller variants with one input hub thread that owns
event::read() for the whole run and routes by a shared flag:
set a watch-channel cancel signal, resizes request a redraw.
prompt over a channel; the renderer flips the route flag on prompt
entry/exit and drains stale events on entry.
This also fixes two adjacent defects:
backoff and API fetch immediately (the cancel future now wraps
attempts and backoff sleeps alike), and take effect at stage
boundaries after the synchronous analysis/signals phases. Previously
the nav-only poller deliberately ignored quit keys and raw mode ate
Ctrl+C, so nothing before tailoring could be cancelled.
redraw immediately on resize, and the 503 backoff now sleeps in 1s
slices with a live countdown so the frame stays current during waits.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01V9Rz9BcK1xb1jiGNER1FeU