Feature: TUI App Coverage Scenarios exercising previously uncovered code paths in cleveragents.tui.app module, including the Textual-based application class behind a mocked Textual import gate. Background: Given the TUI app module is imported with mocked Textual # --- Module-level import gate (lines 31-38) --- Scenario: Mocked Textual import makes _TEXTUAL_AVAILABLE True Then the reloaded app module should have _TEXTUAL_AVAILABLE True Scenario: Mocked Textual import assigns _TextualApp from textual.app Then the reloaded app module should expose _TextualCleverAgentsTuiApp # --- textual_available function (line 43-45) --- Scenario: textual_available returns True when Textual is mocked Then textual_available should return True on the reloaded module # --- SessionView dataclass (lines 48-54) --- Scenario: SessionView can be created with session_id and transcript When I create a SessionView with session_id "sess-1" and transcript entries Then the SessionView session_id should be "sess-1" And the SessionView transcript should contain 2 entries # --- _CommandRouter protocol (lines 56-61) --- Scenario: A class implementing _CommandRouter protocol can be used When I create a _CommandRouter implementation Then calling handle on the implementation should return a response # --- _TextualCleverAgentsTuiApp.__init__ (lines 91-100) --- Scenario: The Textual TUI app can be instantiated with mocked Textual Given a mock command router and persona state When I instantiate the Textual TUI app Then the app should have a _session with session_id "default" And the app should store the command router And the app should store the persona state # --- CSS_PATH and BINDINGS class variables (lines 84-89) --- Scenario: The Textual TUI app has correct class variables Given a mock command router and persona state When I instantiate the Textual TUI app Then the app class should have CSS_PATH set to "cleveragents.tcss" And the app class should have 3 key bindings # --- compose method (lines 102-112) --- Scenario: compose yields the expected widget tree Given a mock command router and persona state When I instantiate the Textual TUI app And I call compose on the app Then compose should yield at least 5 widgets # --- on_mount method (lines 114-121) --- Scenario: on_mount initialises persona bar and overlays Given a mock command router and persona state When I instantiate the Textual TUI app And I call on_mount on the app Then the persona bar should have content set And the help panel should be hidden on mount And the reference picker should have suggestions initialised And the slash overlay should have commands initialised # --- action_help method (lines 123-125) --- Scenario: action_help opens a main-screen help panel Given a mock command router and persona state When I instantiate the Textual TUI app And I call on_mount on the app And I call action_help on the app Then the help panel text should contain "Help: Main Screen" And the help panel text should contain "ctrl+q" Scenario: action_help reflects slash command context Given a mock command router and persona state When I instantiate the Textual TUI app And I call on_mount on the app And I set the prompt text to "/persona list" And I call action_help on the app Then the help panel text should contain "Help: Slash Commands" Scenario: action_help reflects shell mode context Given a mock command router and persona state When I instantiate the Textual TUI app And I call on_mount on the app And I set the prompt text to "!ls" And I call action_help on the app Then the help panel text should contain "Help: Shell Mode" Scenario: action_help toggles the visible help panel off Given a mock command router and persona state When I instantiate the Textual TUI app And I call on_mount on the app And I call action_help on the app And I call action_help on the app Then the help panel should be hidden on mount # --- action_cycle_preset method (lines 127-129) --- Scenario: action_cycle_preset cycles the preset and refreshes the bar Given a mock command router and persona state When I instantiate the Textual TUI app And I call on_mount on the app And I call action_cycle_preset on the app Then the persona bar content should be refreshed # --- _refresh_persona_bar method (lines 131-142) --- Scenario: _refresh_persona_bar builds scope text from active persona Given a mock command router and persona state When I instantiate the Textual TUI app And I call _refresh_persona_bar on the app Then the persona bar should display the persona name and scope # --- on_input_submitted with empty text (lines 144-150) --- Scenario: on_input_submitted with empty text returns early Given a mock command router and persona state When I instantiate the Textual TUI app And I call on_mount on the app And I submit empty text to the app Then the conversation widget should not be updated by input # --- on_input_submitted with command mode (lines 152-167) --- Scenario: on_input_submitted routes slash commands Given a mock command router and persona state When I instantiate the Textual TUI app And I call on_mount on the app And I submit "/help" to the app Then the conversation widget should contain "handled:help" # --- on_input_submitted with shell mode (lines 168-177) --- Scenario: on_input_submitted routes shell commands Given a mock command router and persona state When I instantiate the Textual TUI app And I call on_mount on the app And I submit "!echo tui_shell_test" to the app Then the conversation widget should contain "tui_shell_test" # --- on_input_submitted with shell returning None (lines 170-171) --- Scenario: on_input_submitted handles None shell result Given a mock command router and persona state When I instantiate the Textual TUI app And I call on_mount on the app And I submit shell text that produces a None shell result Then the conversation widget should contain "(no shell output)" # --- on_input_submitted normal mode with @ reference (lines 179-185) --- Scenario: on_input_submitted handles normal text with @ references Given a mock command router and persona state When I instantiate the Textual TUI app And I call on_mount on the app And I submit "check @README" to the app Then the conversation widget should contain "check" And the reference picker should have been updated # --- on_input_submitted normal mode without @ (line 179, 185) --- Scenario: on_input_submitted handles normal text without references Given a mock command router and persona state When I instantiate the Textual TUI app And I call on_mount on the app And I submit "plain message" to the app Then the conversation widget should contain "plain message" # --- CleverAgentsTuiApp alias (line 189) --- Scenario: CleverAgentsTuiApp resolves to the Textual app when available Then CleverAgentsTuiApp should be _TextualCleverAgentsTuiApp on the reloaded module # --- on_input_submitted shell with stdout output (lines 173-176) --- Scenario: on_input_submitted displays shell stdout and command Given a mock command router and persona state When I instantiate the Textual TUI app And I call on_mount on the app And I submit "!echo coverage_run" to the app Then the conversation widget should contain "$ echo coverage_run" # --- on_input_submitted shell with empty output (line 174) --- Scenario: on_input_submitted shows empty output for silent shell commands Given a mock command router and persona state When I instantiate the Textual TUI app And I call on_mount on the app And I submit "!true" to the app Then the conversation widget should contain "(empty output)" # --- THEME class variable (issue #4742) --- @tdd_issue @tdd_issue_4742 Scenario: The Textual TUI app has THEME set to dracula by default Given a mock command router and persona state When I instantiate the Textual TUI app Then the app class should have THEME set to "dracula"