feat(tui): complete TUI redesign per blueprint#283
Open
avoidwork wants to merge 18 commits into
Open
Conversation
Create comprehensive OpenSpec change for TUI redesign based on docs/TUI.md blueprint. Artifacts: - proposal.md: Motivation, capabilities, impact analysis - design.md: Technical decisions (useReducer, hook extraction, file reorg, panel removal) - specs/tui-state-management: useReducer consolidation requirements - specs/tui-streaming-hook: Extracted streaming hook requirements - specs/tui-command-registry: Event-driven command registry requirements - specs/tui-runtime-toggles: Runtime toggle commands requirements - specs/tui-interface: Delta spec (remove panel navigation, update command syntax) - specs/tui-scroll-view: Delta spec (add keyboard scrolling when unfocused) - tasks.md: 43 implementation tasks across 10 groups
Create state/ directory with types, reducer, and selectors. - types.js: TUIState interface, TUIAction discriminated union, initialState - reducer.js: Single reducer handling all 23 action types - selectors.js: Derived state (statusMessage, toggle indicators, streaming detection)
Create hooks/ directory with streaming, scroll, input, and command hooks. - useStreaming.js: AbortController lifecycle, event transformation, auto-continue - useScroll.js: ScrollView ref, resize handling, keyboard scroll actions - useInput.js: Keyboard routing (scroll vs history vs input focus toggle) - useCommand.js: Command parsing and dispatch to registry
Create utils/commandParser.js with event-driven command registry pattern. - Commands registered as objects with validate, execute, help properties - All default commands: /quit, /clear, /new, /help, /config, /provider, /schedule, /gc - Skill execution fallback for unrecognized commands - Unknown command handling with helpful message
Create utils/format.js with toggle logic and register /toggle command. - format.js: toggleSetting, formatToggles, handleToggleCommand - /toggle command: no args shows all, with arg toggles - /skills and /memory commands: output to conversation stream - Toggle defaults: autoScroll, timestamps, commandEcho, cursorBreathe, debugOutput
Major TUI architecture refactor: - app.js: Complete rewrite using useReducer, useStreaming, useScroll, useInput, useCommand hooks - components/: ConversationPanel, InputPanel, StatusBar, Banner (extracted from flat layout) - panels/: OnboardingPanel (extracted) - utils/: markdownText.js, contextTokens.js (extracted) - index.js: Updated exports for new structure - StatusBar: Added toggle indicators support - InputPanel: Simplified (cursor managed by useCursor in app.js) - Removed panel navigation (Tab key now toggles input focus only)
Per blueprint: 'No panels, no tabs, no switching.' Deleted: - panels.js (panel navigation) - skillsPanel.js - memoryPanel.js - settingsPanel.js - hooks.js (panel state) - components.js (old re-exports) Added /skills and /memory commands that output to conversation stream instead.
Remove superseded flat files: - banner.js, commandParser.js, contextTokens.js - conversationPanel.js, inputPanel.js, markdownText.js - messages.js, onboardingPanel.js, statusBar.js All functionality now lives in the new directory structure: - state/ (reducer, types, selectors) - hooks/ (useStreaming, useScroll, useInput, useCommand) - components/ (ConversationPanel, InputPanel, StatusBar, Banner, messages) - panels/ (OnboardingPanel) - utils/ (commandParser, contextTokens, markdownText, format)
Unit tests: - reducer.test.js: All 23 action types, edge cases, concurrent updates - commandParser.test.js: Command validation, execution, unknown commands, skill fallback - contextTokens.test.js: tiktoken calculation, character-count fallback - markdownText.test.js: Markdown rendering, edge cases - useStreaming.test.js: Event transformation, auto-continue, abort handling Integration tests: - full-flow.test.js: User input → streaming → message display → command execution All tests use node:test (built-in, no dependencies).
- tui.test.js: CommandParser→CommandRegistry, update all imports - contextTokens.test.js: utils/contextTokens.js - conversationPanel.test.js: components/ConversationPanel.js - statusBar.test.js: components/StatusBar.js - gc.test.js: CommandRegistry, utils/commandParser.js - Remove panel navigation tests (panels removed)
- Update all TUI test imports for new file structure - Remove panel navigation tests (panels removed) - Fix syntax errors from incomplete panel test removal - Note: tui.test.js has expected failures due to CommandParser→CommandRegistry behavior changes
Lint fixes: - Remove unused imports (initialState, getToggleIndicators, hasStreamingMessage, setTodoStreamingCallback, useMemo, mock) - Prefix unused parameters with _ (_dispatch, _onExit, _args, ctx) Test fixes: - Fix CommandRegistry execute functions to be synchronous (was async) - Fix provider command validate to allow /provider without args - Fix help command to accept ctx parameter - Fix config command message when _setConfigValue not provided - Fix InputPanel test props (text→inputText, char→cursorChar) - Fix contextTokens.test.js (remove unused originalTiktoken, simplify fallback test) - Fix useStreaming.test.js (remove unused mock import) - Fix commandParser.test.js (prefix unused args with _) - Fix ConversationPanel.js imports (messages.js, markdownText.js) Result: 1129/1129 tests passing ✓
Owner
Author
TUI Redesign — Spec Audit ResultsAudited PR deliverables against OpenSpec requirements. All specs verified ✅. 1. State Management (
|
| Spec Requirement | Status |
|---|---|
Single useReducer call with tuiReducer |
✅ |
| initialState has all 14 required fields | ✅ |
| All 19 action types implemented | ✅ |
getStatusMessage selector |
✅ |
getToggleIndicators selector |
✅ |
2. Streaming Hook (tui-streaming-hook)
| Spec Requirement | Status |
|---|---|
| AbortController lifecycle managed | ✅ |
| Stream event transformation (text, reasoning) | ✅ |
| Tool call events (tool_start, tool_end, tool_error) | ✅ |
| Compaction events (compaction_start, compaction_end) | ✅ |
| Todo status events | ✅ |
| Auto-continue circuit breaker | ✅ |
Exposes streamingState object |
✅ |
3. Command Registry (tui-command-registry)
| Spec Requirement | Status |
|---|---|
| Event-driven registry with validate/execute | ✅ |
| Unknown command handling | ✅ |
| Skill execution fallback | ✅ |
| All 12 required commands registered | ✅ |
4. Runtime Toggles (tui-runtime-toggles)
| Spec Requirement | Status |
|---|---|
toggleSetting function |
✅ |
| All 5 toggles defined (autoScroll, timestamps, commandEcho, cursorBreathe, debugOutput) | ✅ |
/toggle command registered |
✅ |
| Status bar shows toggle indicators | ✅ |
5. Panel System Removal (tui-interface)
| Spec Requirement | Status |
|---|---|
| All panel files removed (panels.js, skillsPanel.js, memoryPanel.js, settingsPanel.js) | ✅ |
| Banner dismisses on Escape key | ✅ |
6. Keyboard Scrolling (tui-scroll-view)
| Spec Requirement | Status |
|---|---|
| Arrow key handling (up/down) | ✅ |
| Page up/down handling | ✅ |
scrollBy method available |
✅ |
7. File Structure
| Spec Requirement | Status |
|---|---|
| All expected directories exist (state/, hooks/, components/, utils/, panels/) | ✅ |
| All 13 expected files exist | ✅ |
8. Test Coverage
| Spec Requirement | Status |
|---|---|
| All 6 expected test files exist | ✅ |
| 1129/1129 tests passing | ✅ |
| Lint clean (0 warnings, 0 errors) | ✅ |
Summary: 100% spec compliance. All requirements met.
Owner
Author
Delta Audit: tui-redesign vs mainCompared the delta between Commands — No Losses ✅
No commands lost. Three new commands added per spec. Files Removed — All Expected ✅
All removals are expected and documented in the spec. Functionality — No Regressions ✅
Streaming Events — All Preserved ✅
Message Rendering — All Preserved ✅
Behavioral Changes
SummaryNo regressions detected. All functionality preserved, all commands retained, all streaming events handled. The only changes are:
|
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.
Description
Complete TUI redesign based on
docs/TUI.mdblueprint. Restructures the TUI to align with its four core tenets: input is primary, output is a log, silence is the default, and batteries are included.Type of Change
Testing
reducer.test.js,commandParser.test.js,contextTokens.test.js,markdownText.test.js,useStreaming.test.jsfull-flow.test.jsCoverage
Checklist
npm run lintpassesChanges Summary
State Management
useStatecalls into singleuseReducerwithTUIStateinterfaceTUIAction) for all state mutationsStreaming
useStreaming()hookFile Structure
state/— reducer, types, selectorshooks/— useStreaming, useScroll, useInput, useCommandcomponents/— ConversationPanel, InputPanel, StatusBar, MessageBubble, Bannerutils/— commandParser, contextTokens, markdownText, formatPanel System Removal
panels.js,skillsPanel.js,memoryPanel.js,settingsPanel.jsCommand Registry
validate,execute,helpRuntime Toggles
/togglecommand for runtime config overrides