Why this matters
pending_user_inputs is the engine→user question surface that runtime clients render (the GPUI app turns it into a question sheet and hides the pet). An entry whose turn dies through a path that skips settle_user_inputs_for_terminal_turn never settles: it renders forever, and repeated prompts accumulate — the user sees "stuck pending inputs" they cannot clear except by answering a question the turn is no longer waiting for.
Current behavior
crates/tui/src/runtime_threads.rs:11684 — EngineEvent::UserInputRequired registers the entry.
- Settlement paths: user answers (
submit_user_input route) or settle_user_inputs_for_terminal_turn at runtime_threads.rs:6510, :8705, :12004.
- Turns that end through interrupt/cancel/failure paths which skip those three call sites leak their entries. The map is in-memory, so a leaked entry also survives until process restart.
Repro (live)
This session (GPUI client): plugin-install prompts fired by the overactive matcher (#6274) parked as pending user inputs; after the underlying turns ended the prompts remained rendered and further inputs kept arriving. Session record: ~/.codewhale/sessions/6453856f-10b5-4a9b-947c-dcac902071d3.json.
Desired behavior
- Every turn-death path (complete, interrupt, cancel, failure) settles that turn's pending user inputs with
user_input.canceled events — no path may leave an entry.
claim_pending_user_inputs_for_turn bailing on indeterminate entries should stay loud, but indeterminate entries must also be resolvable, not permanent.
Acceptance criteria
Related
Why this matters
pending_user_inputsis the engine→user question surface that runtime clients render (the GPUI app turns it into a question sheet and hides the pet). An entry whose turn dies through a path that skipssettle_user_inputs_for_terminal_turnnever settles: it renders forever, and repeated prompts accumulate — the user sees "stuck pending inputs" they cannot clear except by answering a question the turn is no longer waiting for.Current behavior
crates/tui/src/runtime_threads.rs:11684—EngineEvent::UserInputRequiredregisters the entry.submit_user_inputroute) orsettle_user_inputs_for_terminal_turnatruntime_threads.rs:6510,:8705,:12004.Repro (live)
This session (GPUI client): plugin-install prompts fired by the overactive matcher (#6274) parked as pending user inputs; after the underlying turns ended the prompts remained rendered and further inputs kept arriving. Session record:
~/.codewhale/sessions/6453856f-10b5-4a9b-947c-dcac902071d3.json.Desired behavior
user_input.canceledevents — no path may leave an entry.claim_pending_user_inputs_for_turnbailing onindeterminateentries should stay loud, but indeterminate entries must also be resolvable, not permanent.Acceptance criteria
user_input.canceledand leavespending_user_inputsempty for that threadEngineEvent::TurnComplete/interrupt handling to a terminal state can skip the settle (assertion or exhaustive audit note in the PR)cargo test -p codewhale-tui --lib --lockedgreen for runtime_threads/runtime_api testsRelated