Component: Terminal User Interface (TUI) Version: 2.0.0 Date: January 6, 2026 Status: Implementation-Ready (ink-based)
| ADR | Relationship |
|---|---|
| ADR-009: CLI-First Interface | Authorizes this spec |
This specification defines a comprehensive Terminal User Interface (TUI) for the Machine Dream system - a Cognitive Puzzle Solver using the GRASP loop and AgentDB memory. The TUI provides an intuitive, interactive menu-driven interface to all puzzle solving, memory management, dreaming/consolidation, and benchmarking functionality.
- Hierarchical Menu System: Navigate through organized command categories
- Interactive Forms: Fill out command options with validation and help
- Live Visualizations: Real-time displays of solving progress and performance metrics
- Keyboard & Mouse Support: Full navigation with both input methods
- Context-Sensitive Help: Inline documentation and examples
- Dashboard Views: At-a-glance system status and metrics
- Session Management: Save and restore work sessions
- Theme Support: Light/dark themes with customization
Primary Framework: ink (React-based TUI library)
- Modern React-based architecture using virtual DOM
- Used by Claude Code - proven in production
- Node.js v24 + WSL compatible - no stack overflow issues
- Component-based with React hooks for state management
- Declarative UI with JSX syntax
- Active maintenance with weekly updates
- Cross-platform (Linux, macOS, Windows, WSL)
Why ink over blessed:
- ❌ blessed/neo-blessed: Stack overflow on Node.js v24 + WSL (regex parsing bug)
- ✅ ink: Virtual DOM rendering, no regex issues
- ✅ ink: Modern React ecosystem and tooling
- ✅ ink: Better testing with React Testing Library
- ✅ ink: Same framework Claude Code uses successfully
Dependencies:
inkv5.x - Terminal rendering frameworkreactv18.x - Component model and virtual DOM- TypeScript with JSX support
React Component Hierarchy:
<App> // Main application component
<Box> // Root layout container
<Header /> // Title, subtitle
<Box horizontal> // Main content area
<Sidebar // Navigation menu
items={menuItems}
onSelect={handleNav}
/>
<ContentArea> // Dynamic screen content
{currentScreen === 'home' && <HomeScreen />}
{currentScreen === 'solve' && <SolveScreen />}
{/* ... other screens */}
</ContentArea>
</Box>
<StatusBar // Bottom status line
session={sessionId}
status={statusText}
/>
</Box>
</App>Layout Visual:
┌─────────────────────────────────────────────────────────────┐
│ Terminal Window │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌─────────────────────────────────────────┐ │
│ │ │ │ │ │
│ │ Main │ │ Content Area │ │
│ │ Menu │ │ │ │
│ │ (Left) │ │ - React Components │ │
│ │ │ │ - Hooks for State │ │
│ │ * Home │ │ - Dynamic Rendering │ │
│ │ # Solve │ │ - Real-time Updates │ │
│ │ @ Memory │ │ │ │
│ │ ~ Dream │ │ │ │
│ │ + Bench │ │ │ │
│ │ > Demo │ │ │ │
│ │ % Config │ │ │ │
│ │ ^ Export │ │ │ │
│ │ = System │ │ │ │
│ │ │ │ │ │
│ └─────────────┘ └─────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ Status Bar: [Session] [Memory] [Database] [Time] [Help: F1] │
└─────────────────────────────────────────────────────────────┘
Screen Dimensions: Minimum 80x24 (recommended 120x40)
Layout Zones:
- Header (2 lines): Title, version, current context
- Main Menu (left, 20% width): Hierarchical navigation
- Content Area (right, 78% width): Forms, displays, visualizations
- Status Bar (1 line): System status, shortcuts, time
- Modal Dialogs: Overlays for confirmations, help, errors
┌─────────────────────┐
│ Machine Dream │
├─────────────────────┤
│ ► 🧩 Solve Puzzle │
│ 🤖 AI Models │
│ 🧠 Memory │
│ 💭 Dream │
│ 📊 Benchmark │
│ 🎬 Demo │
│ ⚙️ Config │
│ 📤 Export │
│ 🔧 System │
│ > Console │
│ │
│ ─────────────────── │
│ ℹ️ Help │
│ 🚪 Exit │
└─────────────────────┘
Icons Legend:
- 🧩 Solve - Puzzle solving with GRASP loop
- 🤖 AI Models - AI model profile management (Spec 13)
- 🧠 Memory - AgentDB memory operations
- 💭 Dream - Night cycle consolidation
- 📊 Benchmark - Performance testing
- 🎬 Demo - Puzzle solving demonstrations
- ⚙️ Config - Configuration management
- 📤 Export - Data export utilities
- 🔧 System - System utilities
- > Console - CLI console with output capture (Spec 14)
Each top-level item expands to show subcommands:
🧩 Solve Puzzle
├── Quick Solve
├── Advanced Solve
├── Batch Solve
├── Solve with Visualization
├── 🤖 AI Model Play (Spec 11) # Pure AI model Sudoku player
└── 🎲 Puzzle Generator (Spec 12) # Randomized puzzle generation
🤖 AI Models (Spec 13)
├── Profile Manager # View, select, create profiles
├── Add Profile # Create new profile (interactive)
├── Edit Profile # Modify existing profile
├── Test Connection # Health check for profiles
├── Export Profiles # Export profiles to file
└── Import Profiles # Import profiles from file
🧠 Memory
├── Store Data
├── Retrieve Data
├── Search Memory
├── Consolidate
├── Optimize
├── Backup
└── Restore
💭 Dream
├── Run Dream Cycle
├── Schedule Dreams
└── Dream Status
📊 Benchmark
├── Run Benchmark
├── View Reports
└── Compare Results
🎬 Demo
├── Stakeholder Presentation
├── Quick Solve Demo
├── Transfer Learning Demo
├── Dreaming Visualization
├── Baseline Comparison
└── 🤖 AI Model Learning Demo # AI model memory ON vs OFF comparison
⚙️ Config
├── View Configuration
├── Edit Settings
├── Validate Config
└── Export Config
📤 Export
├── Export Metrics
├── Export Results
├── Export Memory
└── Export All
🔧 System
├── Dashboard
├── Initialize
├── System Status
├── Cleanup
├── Health Check
└── Migrate
┌──────────────────────────────────────────────────────────────────────────┐
│ Machine Dream v0.1.0 Session: main-20260105 │
├──────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─── System Status ────────────────────────────────────────────────┐ │
│ │ Memory System: ✓ AgentDB (RL: ON, Reflexion: ON) │ │
│ │ Sessions: 47 total, 3 today │ │
│ │ Database: ✓ Healthy (.agentdb/agent.db - 47.3 MB) │ │
│ │ Uptime: 2h 34m │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─── Recent Activity ──────────────────────────────────────────────┐ │
│ │ 10:34 | Solved hard-01.json (47 iterations, 12.4s) │ │
│ │ 10:28 | Dream cycle completed (47→5 patterns) │ │
│ │ 10:15 | Memory optimized (150 patterns → 47 skills) │ │
│ │ 10:05 | Benchmark completed (95% success rate) │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─── Quick Actions ────────────────────────────────────────────────┐ │
│ │ [1] Quick Solve [2] Memory Browser [3] Dream Cycle │ │
│ │ [4] Run Demo [5] Benchmark [6] System Health │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─── Performance Metrics ──────────────────────────────────────────┐ │
│ │ Avg Solve Time: ████████░░░░░░░░░░ 8.3s (target: 10s) │ │
│ │ Memory Usage: ███████░░░░░░░░░░░ 342 MB (limit: 2GB) │ │
│ │ Success Rate: ████████████████░░ 87% (target: 80%) │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────────────┘
[F1] Help [F2] Config [F10] Menu [Ctrl+C] Exit Memory: 342 MB
┌──────────────────────────────────────────────────────────────────────────┐
│ Solve Puzzle │
├──────────────────────────────────────────────────────────────────────────┤
│ │
│ Puzzle File: [puzzles/hard-01.json ] [📁 Browse] │
│ │
│ ┌─── Memory System ────────────────────────────────────────────────┐ │
│ │ ○ ReasoningBank (stable, baseline) │ │
│ │ ● AgentDB (enhanced, RL-enabled) │ │
│ │ │ │
│ │ ☑ Enable RL Learning │ │
│ │ ☑ Enable Reflexion (error correction) │ │
│ │ ☑ Enable Skill Library (auto-extract) │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─── Solving Parameters ───────────────────────────────────────────┐ │
│ │ Max Iterations: [100 ] ← → (10-1000) │ │
│ │ Max Time (ms): [300000] ← → (10000-600000) │ │
│ │ Reflection Interval: [5 ] ← → (1-50) │ │
│ │ Attention Window: [10 ] ← → (5-50) │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─── Strategy Configuration ───────────────────────────────────────┐ │
│ │ ☑ Naked Single ☑ Hidden Single │ │
│ │ ☑ Pointing Pairs ☑ Box-Line Reduction │ │
│ │ ☐ Naked Pairs ☐ X-Wing │ │
│ │ ☐ XY-Wing ☐ Swordfish │ │
│ │ │ │
│ │ ☑ Enable Backtracking │ │
│ │ Guess Threshold: [0.3] ← → (0.0-1.0) │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─── Output Options ───────────────────────────────────────────────┐ │
│ │ ☑ Live Visualization │ │
│ │ ☑ Export Trajectory │ │
│ │ ☑ Dream After Solving │ │
│ │ Save Results To: [results/solve-{timestamp}.json ] │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │
│ [ Start Solve ] [ Save Config ] [ Load Preset ] [ Cancel ] │
│ │
└──────────────────────────────────────────────────────────────────────────┘
[F1] Help [Tab] Next Field [↑↓] Navigate [Space] Toggle [Enter] Submit
┌──────────────────────────────────────────────────────────────────────────┐
│ Solving: hard-01.json Iteration: 23/100 (23%) │
├──────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─── Puzzle Grid ─────────────┐ ┌─── Progress ──────────────────┐ │
│ │ │ │ │ │
│ │ 5 3 · │ · 7 · │ · · · │ │ Cells Filled: 41/81 (51%) │ │
│ │ 6 · · │ 1 9 5 │ · · · │ │ Progress: ████████░░░░░░░ │ │
│ │ · 9 8 │ · · · │ · 6 · │ │ │ │
│ │ ───── ───── ───── │ │ Current Strategy: │ │
│ │ 8 · · │ · 6 · │ · · 3 │ │ Pointing Pairs │ │
│ │ 4 · · │ 8 · 3 │ · · 1 │ │ │ │
│ │ *7*· · │ · 2 · │ · · 6 │ │ Focus Cell: (4,0) │ │
│ │ ───── ───── ───── │ │ Candidates: {1, 7} │ │
│ │ · 6 · │ · · · │ 2 8 · │ │ │ │
│ │ · · · │ 4 1 9 │ · · 5 │ │ Insights: 3 │ │
│ │ · · · │ · 8 · │ · 7 9 │ │ - Strategy shift detected │ │
│ │ │ │ - Breakthrough at (3,5) │ │
│ │ *Focus ·Empty #Filled │ │ - Pattern: Naked Triple │ │
│ └──────────────────────────────┘ └──────────────────────────────┘ │
│ │
│ ┌─── Strategy Timeline ────────────────────────────────────────────┐ │
│ │ 1-10: Naked Single ████████ │ │
│ │ 11-15: Hidden Single ███ │ │
│ │ 16-20: Pointing Pairs ████ │ │
│ │ 21-23: Pointing Pairs ██ │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─── Recent Moves ──────────────────────────────────────────────────┐ │
│ │ #21 | (3,5) = 4 | Pointing Pairs | ✓ Valid │ │
│ │ #22 | (4,7) = 9 | Naked Single | ✓ Valid │ │
│ │ #23 | (4,0) = 7 | Pointing Pairs | ✓ Valid (current) │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │
│ [ Pause ] [ Step ] [ Skip to End ] [ Export ] [ Stop ] │
│ │
└──────────────────────────────────────────────────────────────────────────┘
[Space] Pause [S] Step [E] End [X] Stop Elapsed: 00:04.8s
┌──────────────────────────────────────────────────────────────────────────┐
│ Memory Browser Namespace: default │
├──────────────────────────────────────────────────────────────────────────┤
│ │
│ Search: [naked single ] [🔍] Type: [All ▼] │
│ │
│ ┌─── Results (47 items) ───────────────────────────────────────────┐ │
│ │ │ │
│ │ ► Pattern: naked-single-basic Success: 94% │ │
│ │ Type: Strategy | Created: 2h ago | Used: 127 times │ │
│ │ Description: Basic naked single detection in row/col/box │ │
│ │ Size: 2.3 KB | TTL: Persistent │ │
│ │ │ │
│ │ ► Skill: naked-single-advanced Success: 87% │ │
│ │ Type: Skill | Created: 1h ago | Used: 43 times │ │
│ │ Description: Advanced naked single with constraint chaining │ │
│ │ Size: 4.1 KB | TTL: 30 days │ │
│ │ │ │
│ │ ► Experience: solve-session-047 │ │
│ │ Type: Experience | Created: 15m ago | Moves: 47 │ │
│ │ Description: Solved hard-01.json using naked single strategy │ │
│ │ Size: 12.7 KB | TTL: 7 days │ │
│ │ │ │
│ │ ... │ │
│ │ │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─── Selected: Pattern: naked-single-basic ───────────────────────┐ │
│ │ │ │
│ │ { │ │
│ │ "id": "pattern-ns-001", │ │
│ │ "type": "strategy", │ │
│ │ "name": "naked-single-basic", │ │
│ │ "successRate": 0.94, │ │
│ │ "usageCount": 127, │ │
│ │ "conditions": ["cell has single candidate"], │ │
│ │ "actions": ["place value in cell"], │ │
│ │ "examples": [ ... ] │ │
│ │ } │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────────────┘ │
│ │
│ [Store] [Retrieve] [Delete] [Export] [Optimize] [Consolidate] [Backup] │
│ │
└──────────────────────────────────────────────────────────────────────────┘
[/] Search [Enter] View [Del] Delete [E] Export Page: 1/5
┌──────────────────────────────────────────────────────────────────────────┐
│ Benchmark Results Run: full-20260105 │
├──────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─── Overall Summary ──────────────────────────────────────────────┐ │
│ │ Total Tests: 200 (50 easy, 50 medium, 50 hard, 50 expert) │ │
│ │ Success Rate: 87% (174/200) │ │
│ │ Avg Solve Time: 8.3s (target: 10s) ✓ │ │
│ │ Total Duration: 27m 43s │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─── Baseline Comparison ──────────────────────────────────────────┐ │
│ │ │ │
│ │ │ Success │ Avg Time │ Iterations │ Memory │ │
│ │ ─────────────┼─────────┼──────────┼────────────┼────────── │ │
│ │ Single-Shot │ 42% │ 15.2s │ 1 │ 120 MB │ │
│ │ Naive Cont. │ 68% │ 11.7s │ 35 │ 180 MB │ │
│ │ GRASP │ 87% ✓ │ 8.3s ✓ │ 28 ✓ │ 240 MB │ │
│ │ GRASP+AgentDB│ 92% ✓✓ │ 7.1s ✓✓ │ 23 ✓✓ │ 310 MB │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─── Performance by Difficulty ────────────────────────────────────┐ │
│ │ │ │
│ │ Easy: ████████████████████ 98% (49/50) Avg: 2.1s │ │
│ │ Medium: ████████████████░░░░ 94% (47/50) Avg: 5.8s │ │
│ │ Hard: ████████████░░░░░░░░ 82% (41/50) Avg: 12.4s │ │
│ │ Expert: ██████░░░░░░░░░░░░░░ 74% (37/50) Avg: 23.7s │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─── Strategy Effectiveness ───────────────────────────────────────┐ │
│ │ │ │
│ │ Naked Single: ████████████████████ 96% (1,247 uses) │ │
│ │ Hidden Single: ███████████████░░░░░ 89% (843 uses) │ │
│ │ Pointing Pairs: ███████████░░░░░░░░░ 71% (412 uses) │ │
│ │ Box-Line Reduct.: ████████░░░░░░░░░░░░ 65% (287 uses) │ │
│ │ Guess: ████░░░░░░░░░░░░░░░░ 42% (93 uses) │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────────────┘ │
│ │
│ [View Details] [Export Report] [Compare] [Re-run] [Back] │
│ │
└──────────────────────────────────────────────────────────────────────────┘
[D] Details [E] Export [C] Compare [R] Re-run [Q] Back
Purpose: Generate randomized Sudoku puzzles with seed-based reproducibility and variable grid sizes.
Configuration Form:
┌──────────────────────────────────────────────────────────────────────────┐
│ 🎲 Puzzle Generator Spec 12 Integration │
├──────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─── Generation Configuration ─────────────────────────────────────┐ │
│ │ │ │
│ │ Seed Number: [Random ▼] or [12345 ] │ │
│ │ ○ Random (auto-generate) │ │
│ │ ● Specific (enter seed below) │ │
│ │ │ │
│ │ Grid Size: [9×9 ▼] │ │
│ │ Options: 4×4, 9×9, 16×16, 25×25 │ │
│ │ │ │
│ │ Difficulty: [Medium ▼] │ │
│ │ Easy, Medium, Hard, Expert, Diabolical │ │
│ │ │ │
│ │ Symmetry: [None ▼] │ │
│ │ None, Rotational, Reflectional, Diagonal │ │
│ │ │ │
│ │ ☑ Validate uniqueness (ensure single solution) │ │
│ │ ☑ Show preview after generation │ │
│ │ │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─── Batch Generation (Optional) ──────────────────────────────────┐ │
│ │ │ │
│ │ ☐ Generate multiple puzzles │ │
│ │ Count: [10 ] ← → (1-1000) │ │
│ │ Seed Mode: ○ Sequential ● Random │ │
│ │ Seed Start: [1000 ] (if sequential) │ │
│ │ Output Dir: [puzzles/batch/ ] │ │
│ │ │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │
│ [ Generate ] [ Load from Seed ] [ Validate Puzzle ] [ Cancel ]│
│ │
└──────────────────────────────────────────────────────────────────────────┘
[Tab] Next Field [↑↓] Navigate [Space] Toggle [Enter] Generate [Esc] Cancel
Live Preview (After Generation):
┌──────────────────────────────────────────────────────────────────────────┐
│ 🎲 Puzzle Generated Successfully Seed: 12345 │
├──────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─── Generated Puzzle (9×9) ──────┐ ┌─── Metadata ──────────────┐ │
│ │ │ │ │ │
│ │ 5 3 · │ · 7 · │ · · · │ │ Seed: 12345 │ │
│ │ 6 · · │ 1 9 5 │ · · · │ │ Size: 9×9 │ │
│ │ · 9 8 │ · · · │ · 6 · │ │ Difficulty: Medium │ │
│ │ ───── ───── ───── │ │ Clues: 32/81 (40%) │ │
│ │ 8 · · │ · 6 · │ · · 3 │ │ Symmetry: None │ │
│ │ 4 · · │ 8 · 3 │ · · 1 │ │ │ │
│ │ 7 · · │ · 2 · │ · · 6 │ │ Validation: ✓ Unique │ │
│ │ ───── ───── ───── │ │ Gen Time: 147ms │ │
│ │ · 6 · │ · · · │ 2 8 · │ │ Retries: 0 │ │
│ │ · · · │ 4 1 9 │ · · 5 │ │ │ │
│ │ · · · │ · 8 · │ · 7 9 │ │ Solvable: ✓ Yes │ │
│ │ │ │ Solution: ✓ Verified │ │
│ │ ·Empty #Given *Focus │ │ │ │
│ └──────────────────────────────────┘ └────────────────────────────┘ │
│ │
│ ┌─── Quick Actions ────────────────────────────────────────────────┐ │
│ │ │ │
│ │ [1] Save to File [4] Regenerate from Seed │ │
│ │ [2] Use for LLM Play [5] Generate Batch (same config) │ │
│ │ [3] Export Metadata [6] Copy Seed Number │ │
│ │ │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─── Output Path ──────────────────────────────────────────────────┐ │
│ │ Save As: [puzzles/seed-12345-medium-9x9.json ] [📁 Browse] │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │
│ [ Save ] [ Solve Now ] [ LLM Play ] [ New Puzzle ] [ Back ]│
│ │
└──────────────────────────────────────────────────────────────────────────┘
[1-6] Quick Actions [S] Save [L] LLM Play [N] New [Q] Back
Batch Generation Progress:
┌──────────────────────────────────────────────────────────────────────────┐
│ 🎲 Batch Generation Progress: 7/10 (70%) │
├──────────────────────────────────────────────────────────────────────────┤
│ │
│ Overall Progress: ██████████████░░░░░░ 70% (7/10 complete) │
│ Elapsed: 00:01.2s | Estimated: 00:00.5s remaining │
│ │
│ ┌─── Generation Log ────────────────────────────────────────────────┐ │
│ │ │ │
│ │ ✓ Puzzle 1 | Seed: 1000 | 147ms | ✓ Valid | puzzles/batch/001.json│ │
│ │ ✓ Puzzle 2 | Seed: 1001 | 142ms | ✓ Valid | puzzles/batch/002.json│ │
│ │ ✓ Puzzle 3 | Seed: 1002 | 158ms | ✓ Valid | puzzles/batch/003.json│ │
│ │ ✓ Puzzle 4 | Seed: 1003 | 139ms | ✓ Valid | puzzles/batch/004.json│ │
│ │ ✓ Puzzle 5 | Seed: 1004 | 151ms | ✓ Valid | puzzles/batch/005.json│ │
│ │ ✓ Puzzle 6 | Seed: 1005 | 144ms | ✓ Valid | puzzles/batch/006.json│ │
│ │ ▶ Puzzle 7 | Seed: 1006 | Generating... (attempt 1) │ │
│ │ ○ Puzzle 8 | Seed: 1007 | Pending... │ │
│ │ ○ Puzzle 9 | Seed: 1008 | Pending... │ │
│ │ ○ Puzzle 10| Seed: 1009 | Pending... │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─── Statistics ────────────────────────────────────────────────────┐ │
│ │ Success: 6/7 (100%) | Failed: 0 | Avg Time: 145ms/puzzle │ │
│ │ Output: puzzles/batch/ | Total Size: 47.3 KB │ │
│ └───────────────────────────────────────────────────────────────────┘ │
│ │
│ [ Pause ] [ Skip Current ] [ Cancel All ] │
│ │
└──────────────────────────────────────────────────────────────────────────┘
[Space] Pause [K] Skip [C] Cancel All
Key Features:
- Seed input field: Random or specific seed number
- Grid size selector: 4×4, 9×9, 16×16, 25×25 via dropdown
- Difficulty selector: Easy through Diabolical
- Symmetry options: None, Rotational, Reflectional, Diagonal
- Live preview: Shows generated puzzle with metadata
- Validation status: Uniqueness and solvability verification
- Quick actions: Save, Use for LLM Play, Regenerate, Batch
- Batch generation: Sequential or random seed modes with progress tracking
- CLI integration: All operations drive CLI commands via CLIExecutor
CLI Command Mapping:
// Single puzzle generation
CLIExecutor.executePuzzleGenerate({
seed: 12345,
size: 9,
difficulty: 'medium',
symmetry: 'none',
output: 'puzzles/seed-12345-medium-9x9.json'
});
// Executes: machine-dream puzzle generate --seed 12345 --size 9 --difficulty medium --output puzzles/seed-12345-medium-9x9.json
// Batch generation
CLIExecutor.executePuzzleBatch({
count: 10,
seedStart: 1000,
seedMode: 'sequential',
difficulty: 'medium',
size: 9,
outputDir: 'puzzles/batch/'
});
// Executes: machine-dream puzzle batch --count 10 --seed-start 1000 --seed-mode sequential --difficulty medium --size 9 --output-dir puzzles/batch/Navigation Flow:
- Main Menu → Solve Puzzle → Puzzle Generator
- Fill configuration form
- Click "Generate" or press Enter
- View live preview with metadata
- Choose quick action: Save, LLM Play, Batch, or New
- Return to form or exit to main menu
Input Fields:
Label: [value ]
↑ Cursor position
Numeric Sliders:
Max Iterations: [100 ] ← → (10-1000)
████████░░░░░░░░░░ 10%
Checkboxes:
☑ Enabled (checked)
☐ Disabled (unchecked)
Radio Buttons:
○ Option 1 (unselected)
● Option 2 (selected)
○ Option 3 (unselected)
Dropdown Menus:
Memory System: [AgentDB ▼]
Expanded:
┌─────────────────────────┐
│ ● AgentDB (enhanced) │
│ ○ ReasoningBank (basic) │
└─────────────────────────┘
File Browsers:
[📁 Browse Files]
Modal:
┌─── Select Puzzle File ──────────────────┐
│ Path: /home/vscode/machine-dream_AG/ │
│ │
│ 📁 puzzles/ │
│ ├── 📄 easy-01.json │
│ ├── 📄 medium-01.json │
│ ├── 📄 hard-01.json [Select]│
│ └── 📄 expert-01.json │
│ │
│ [ OK ] [ Cancel ] │
└──────────────────────────────────────────┘
Sortable Columns:
┌─── Strategy Performance ───────────────────────────────┐
│ Strategy ↑ │ Uses │ Success │ Avg Time │ Last │
├────────────────────┼───────┼─────────┼──────────┼──────┤
│ naked-single │ 247 │ 98.4% │ 12ms │ 2m │
│ hidden-single │ 189 │ 94.7% │ 18ms │ 5m │
│ pointing-pairs │ 76 │ 87.2% │ 24ms │ 8m │
│ box-line-reduction │ 43 │ 91.1% │ 31ms │ 12m │
└────────────────────┴───────┴─────────┴──────────┴──────┘
Click column header to sort. [↑↓] Navigate rows.
Pagination:
┌─────────────────────────────────────────────────────┐
│ ...table content... │
└─────────────────────────────────────────────────────┘
Page: [1] 2 3 4 5 ... 12 [<] [>] [<<First] [Last>>]
Progress Bars:
Solving: ████████████░░░░░░░░ 60% (30/50 iterations)
[Estimated: 8s remaining]
Spinners:
Loading... ⠋
Loading... ⠙
Loading... ⠹
Loading... ⠸
Multi-Step Progress:
┌─── Dream Cycle Progress ─────────────────────────┐
│ ✓ Capture (47 experiences) │
│ ✓ Triage (23 significant) │
│ ▶ Compress ████████░░░░░░░░ 45% (11/23) │
│ ○ Abstract (pending) │
│ ○ Integrate (pending) │
│ ○ Verify (pending) │
└──────────────────────────────────────────────────┘
Confirmation Dialog:
┌─── Confirm Action ──────────────────────────────┐
│ │
│ ⚠️ Are you sure you want to clear all memory │
│ and reset the learning database? │
│ │
│ This will delete 1,247 learned patterns and │
│ cannot be undone. │
│ │
│ [ Yes, Clear ] [ Cancel ] │
│ │
└──────────────────────────────────────────────────┘
Alert Dialog:
┌─── Success ─────────────────────────────────────┐
│ │
│ ✓ Puzzle solved successfully! │
│ │
│ Iterations: 47 │
│ Time: 12.4 seconds │
│ Strategy: Pointing Pairs │
│ │
│ [ View Details ] [ OK ] │
│ │
└──────────────────────────────────────────────────┘
Error Dialog:
┌─── Error ───────────────────────────────────────┐
│ │
│ ✗ Solving failed: Maximum iterations exceeded │
│ │
│ Details: │
│ - Iterations: 100/100 │
│ - Progress: 73% complete │
│ - Stuck at iteration 87 │
│ │
│ Suggestions: │
│ • Increase max iterations │
│ • Enable backtracking │
│ • Try different strategies │
│ │
│ [ View Log ] [ Retry ] [ Cancel ] │
│ │
└──────────────────────────────────────────────────┘
Context-Sensitive Help:
┌─── Help: Solve Puzzle ──────────────────────────┐
│ │
│ OVERVIEW │
│ Execute puzzle solving with GRASP loop and │
│ AgentDB memory integration. │
│ │
│ PARAMETERS │
│ • Puzzle File: Path to puzzle (JSON format) │
│ • Memory System: AgentDB or ReasoningBank │
│ • Max Iterations: Safety limit (default: 100) │
│ • Strategies: Solving techniques to use │
│ │
│ EXAMPLES │
│ Quick solve: │
│ Use preset "Quick Solve" with defaults │
│ │
│ Advanced: │
│ Enable RL + Reflexion for best results │
│ │
│ KEYBOARD SHORTCUTS │
│ Tab - Next field │
│ Shift+Tab - Previous field │
│ Space - Toggle checkbox │
│ Enter - Submit form │
│ Esc - Cancel │
│ │
│ [ Close ] │
│ │
└──────────────────────────────────────────────────┘
? - Help overlay (context-sensitive) - Spec 14
` - Toggle console overlay - Spec 14
Ctrl+C - Exit application
Esc - Close overlay (if open)
q - Quit application
↑ ↓ - Navigate menu items
Note: F1-F12 function keys are not supported by the Ink library. Use ? for help instead.
↑ ↓ - Navigate menu items / table rows
← → - Navigate menu hierarchy / table columns
Tab - Next field / Next section
Shift+Tab - Previous field / Previous section
Enter - Select / Submit / Execute
Esc - Cancel / Go back / Close modal
Home - First item / Top of list
End - Last item / Bottom of list
PgUp/PgDn - Scroll page up/down
Main Menu:
H - Home
S - Solve Puzzle
G - Generate Puzzle
L - LLM Play
A - AI Models (Profiles)
M - Memory Browser
D - Dream Cycle
B - Benchmark
E - Demo
C - Config
X - Export
Y - System Utilities
T - Console
Q - Quit
Form Shortcuts:
Space - Toggle checkbox / Radio button
↑ ↓ - Adjust slider / dropdown selection
← → - Adjust numeric values
Ctrl+Enter - Submit form
Ctrl+W - Close without saving
/ - Search / Filter
N - Next result
P - Previous result
R - Refresh data
E - Export current view
V - View details
D - Delete selected
Ctrl+A - Select all
Ctrl+D - Deselect all
Single Click - Select item / Focus field
Double Click - Execute / Open details
Right Click - Context menu
Scroll Wheel - Scroll content
Click+Drag - Resize panels (where applicable)
Right-click on menu item:
┌─────────────────────┐
│ Execute │
│ View Details │
│ ─────────────────── │
│ Add to Favorites │
│ Create Shortcut │
│ ─────────────────── │
│ Help │
└─────────────────────┘
Right-click on table row:
┌─────────────────────┐
│ View Details │
│ Edit │
│ Delete │
│ ─────────────────── │
│ Copy ID │
│ Export Row │
└─────────────────────┘
const darkTheme = {
// Background colors
bg: {
primary: '#1e1e1e', // Main background
secondary: '#252525', // Panels, dialogs
highlight: '#2d2d30', // Hover states
active: '#094771' // Active selection
},
// Foreground colors
fg: {
primary: '#cccccc', // Main text
secondary: '#858585', // Secondary text
dim: '#555555', // Disabled/dim text
bright: '#ffffff' // Emphasized text
},
// Semantic colors
status: {
success: '#4ec9b0', // Green
error: '#f48771', // Red
warning: '#dcdcaa', // Yellow
info: '#4fc1ff' // Blue
},
// UI elements
ui: {
border: '#3e3e42', // Borders
scrollbar: '#424242', // Scrollbars
shadow: '#00000050', // Shadows
focus: '#007acc' // Focus outline
},
// Syntax highlighting
syntax: {
keyword: '#569cd6', // Keywords
string: '#ce9178', // Strings
number: '#b5cea8', // Numbers
comment: '#6a9955', // Comments
function: '#dcdcaa' // Functions
}
};const lightTheme = {
bg: {
primary: '#ffffff',
secondary: '#f3f3f3',
highlight: '#e8e8e8',
active: '#0078d4'
},
fg: {
primary: '#000000',
secondary: '#616161',
dim: '#a0a0a0',
bright: '#000000'
},
status: {
success: '#0e8a16',
error: '#d73a49',
warning: '#f9c513',
info: '#0366d6'
},
ui: {
border: '#d0d0d0',
scrollbar: '#c0c0c0',
shadow: '#00000020',
focus: '#0078d4'
}
};Config > Theme > [Dark | Light | Auto | Custom]
Auto Mode: Matches system preference or time of day
- Day (6am-6pm): Light theme
- Night (6pm-6am): Dark theme
.machine-dream-tui.json:
{
"theme": "dark",
"layout": {
"menuWidth": 20,
"showStatusBar": true,
"fontSize": "normal",
"animations": true
},
"behavior": {
"confirmDestructive": true,
"autoRefresh": true,
"refreshInterval": 5000,
"mouseEnabled": true,
"soundEnabled": false
},
"shortcuts": {
"custom": {
"Ctrl+Q": "quickSolve",
"Ctrl+B": "benchmark"
}
},
"favorites": [
"solve",
"memory.search",
"dream.run",
"system.dashboard"
],
"history": {
"maxSize": 100,
"persistAcrossSessions": true
}
}Auto-save state:
- Current menu position
- Form field values
- Active tabs/views
- Scroll positions
- Filter/search terms
Restore on launch:
┌─── Welcome Back ───────────────────────────────┐
│ │
│ Previous session found (5 minutes ago) │
│ │
│ • Location: Memory Browser │
│ • Unsaved form: Advanced Solve │
│ • Active solve sessions: 2 running │
│ │
│ [ Restore Session ] [ Start Fresh ] │
│ │
└─────────────────────────────────────────────────┘
Activate: Ctrl+P
┌─── Command Palette ─────────────────────────────────────────┐
│ │
│ Type command or search... │
│ > solve │
│ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ 🧩 Solve Puzzle │ │
│ │ 🧩 Quick Solve │ │
│ │ 🧩 Advanced Solve │ │
│ │ 🧩 Batch Solve │ │
│ │ ⚙️ Solve: Configuration Presets │ │
│ │ 📊 Benchmark: Solve Performance │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
│ [↑↓] Navigate [Enter] Execute [Esc] Cancel │
│ │
└──────────────────────────────────────────────────────────────┘
Features:
- Fuzzy search across all commands
- Recent commands history
- Keyboard-driven navigation
- Shows shortcuts for each command
Layout Manager: Ctrl+\
┌──────────────────────────────────────────────────────────────┐
│ Layout: Split View [=] [□] [×] │
├─────────────────────────┬────────────────────────────────────┤
│ │ │
│ Solve Puzzle (Form) │ Live Visualization │
│ │ │
│ [Puzzle File] │ ┌─── Puzzle Grid ──────────┐ │
│ [Memory System] │ │ 5 3 · │ · 7 · │ · · · │ │
│ [Parameters] │ │ 6 · · │ 1 9 5 │ · · · │ │
│ │ │ ... │ │
│ [Start Solve] │ └──────────────────────────┘ │
│ │ │
│ │ Progress: 23% (Iteration 23/100) │
│ │ │
├─────────────────────────┴────────────────────────────────────┤
│ Status Bar │
└──────────────────────────────────────────────────────────────┘
Layouts:
- Single panel (default)
- Split horizontal (2 panels)
- Split vertical (2 panels)
- Quad view (4 panels)
- Custom layouts (save/load)
Auto-refresh for live data:
┌─── System Status (Watch Mode: ON) ──────────────────────────┐
│ Auto-refresh: 5s [⏸ Pause] [⏵ Resume] [↻ Refresh Now] │
├─────────────────────────────────────────────────────────────┤
│ │
│ Last Update: 2 seconds ago │
│ │
│ Active Sessions: 3 ● (↑ 1 from last refresh) │
│ CPU Usage: 31% ███████░░░░░░░░░░ │
│ Memory: 342 MB ████████████████░░░░ │
│ Puzzles Solved: 147 total (+3), 3 in progress (-1) │
│ │
│ Changes since last refresh: │
│ • Session solve-047 completed successfully │
│ • Dream cycle started (session consolidation) │
│ • Memory usage decreased 15 MB │
│ │
└──────────────────────────────────────────────────────────────┘
System Notifications:
┌─────────────────────────────────────────────────────┐
│ 🔔 Notification │
├─────────────────────────────────────────────────────┤
│ Puzzle solved successfully! │
│ hard-01.json completed in 12.4s (47 iterations) │
│ │
│ [View Details] [Dismiss] (3s) │
└─────────────────────────────────────────────────────┘
Notification Center: Access recent notifications
┌─── Notifications (5 unread) ────────────────────────┐
│ │
│ ✓ 10:34 | Puzzle solved: hard-01.json │
│ ℹ 10:28 | Dream cycle completed │
│ ⚠ 10:15 | Memory usage high (450 MB) │
│ ✓ 10:05 | Benchmark completed │
│ ℹ 09:47 | Database optimized │
│ │
│ [Clear All] [Settings] │
└──────────────────────────────────────────────────────┘
Customizable toolbar: Common actions for quick access
┌────────────────────────────────────────────────────────────┐
│ Quick Actions: │
│ [🧩 Solve] [🧠 Memory] [💭 Dream] [📊 Bench] [🔧 Status] │
└────────────────────────────────────────────────────────────┘
Configure: Drag and drop to customize
Behind the scenes:
// Form submission → CLI command generation → Execution
// User fills form:
{
puzzleFile: 'puzzles/hard-01.json',
memorySystem: 'agentdb',
enableRL: true,
maxIterations: 100
}
// Generates CLI command:
'machine-dream solve puzzles/hard-01.json --memory-system agentdb --enable-rl --max-iterations 100'
// Executes via child_process
const result = await executeCLICommand(command);
// Parses output and updates UI
updateUI(result);// Stream CLI output to TUI
const process = spawn('machine-dream', ['solve', 'puzzles/hard-01.json']);
process.stdout.on('data', (data) => {
// Parse output (JSON lines)
const event = JSON.parse(data);
// Update live visualization
if (event.type === 'ITERATION_COMPLETE') {
updatePuzzleGrid(event.data.state);
updateProgress(event.data.iteration);
}
});┌─── Command History ─────────────────────────────────┐
│ │
│ 1. solve puzzles/hard-01.json --enable-rl │
│ ✓ Success (12.4s, 47 iterations) │
│ │
│ 2. memory optimize --prune-redundancy │
│ ✓ Success (150→47 patterns) │
│ │
│ 3. benchmark run quick │
│ ✓ Success (95% success rate) │
│ │
│ 4. dream run --sessions session-001,session-002 │
│ ✓ Success (47→5 patterns) │
│ │
│ [Re-run] [Edit] [Export] [Clear] │
│ │
└──────────────────────────────────────────────────────┘
Real-time validation:
Max Iterations: [abc ] ✗ Must be a number
↑ Invalid input highlighted in red
Max Iterations: [1000000] ⚠ Value exceeds maximum (1000)
↑ Warning in yellow
Max Iterations: [100 ] ✓ Valid
↑ Confirmed in green
┌─── Initializing System ─────────────────────────┐
│ │
│ ⠋ Loading configuration... │
│ ✓ Configuration loaded │
│ ⠙ Initializing AgentDB... │
│ ✓ AgentDB initialized │
│ ⠹ Loading GRASP strategies... │
│ ✓ GRASP strategies loaded │
│ ... │
│ │
│ Progress: ██████████░░░░░░░░░░ 75% │
│ Estimated: 2s remaining │
│ │
└──────────────────────────────────────────────────┘
┌─── Connection Error ────────────────────────────┐
│ │
│ ✗ Failed to connect to AgentDB │
│ │
│ Details: │
│ Database file locked by another process │
│ │
│ Suggested Actions: │
│ 1. Close other instances of Machine Dream │
│ 2. Run system cleanup │
│ 3. Use ReasoningBank instead │
│ │
│ [1. Auto-fix] [2. Cleanup] [3. Switch] [Cancel]│
│ │
└──────────────────────────────────────────────────┘
- Semantic markup for all UI elements
- ARIA labels for interactive components
- Announcement of state changes
- Keyboard-only navigation
Activate: Config > Accessibility > High Contrast
Enhanced contrast ratios (WCAG AAA compliant)
- Text: 7:1 minimum contrast
- UI elements: 4.5:1 minimum
- Borders: Bold, high-contrast
Config > Display > Font Size
○ Small
● Normal
○ Large
○ Extra Large
Config > Accessibility > Reduce Motion
☑ Disable animations
☑ Disable transitions
☑ Static progress indicators
For large datasets (e.g., memory browser with 10,000+ items):
- Only render visible rows
- Recycle DOM elements
- Smooth scrolling experience
┌─── Memory Patterns (1,247 total) ───────────┐
│ Showing: 1-50 │
│ │
│ [Pattern data...] │
│ │
│ Loading more... ⠋ │
│ │
└──────────────────────────────────────────────┘
Search input: Debounce 300ms to avoid excessive queries
let searchTimeout;
searchInput.on('change', (value) => {
clearTimeout(searchTimeout);
searchTimeout = setTimeout(() => {
performSearch(value);
}, 300);
});describe('MenuNavigation', () => {
it('should navigate to submenu on arrow right', () => {
const menu = new MainMenu();
menu.selectItem('Memory');
menu.pressKey('right');
expect(menu.currentSubmenu).toBe('memory');
});
});
describe('FormValidation', () => {
it('should validate numeric input', () => {
const form = new SolveForm();
form.setField('maxIterations', 'abc');
expect(form.isValid()).toBe(false);
expect(form.errors).toContain('Must be a number');
});
});describe('Solve Workflow', () => {
it('should complete solve workflow', async () => {
const tui = new MachineDreamTUI();
await tui.start();
tui.navigateTo('Solve Puzzle');
tui.fillForm({
puzzleFile: 'test/easy-01.json',
memorySystem: 'agentdb'
});
await tui.submit();
await tui.waitForCompletion();
const result = tui.getResult();
expect(result.solved).toBe(true);
});
});describe('Visual Regression', () => {
it('should match dashboard screenshot', async () => {
const tui = new MachineDreamTUI();
await tui.navigateTo('Dashboard');
const screenshot = await tui.screenshot();
expect(screenshot).toMatchSnapshot();
});
});- ✓ Set up blessed/ink framework
- ✓ Implement basic menu navigation
- ✓ Create layout system (header, menu, content, status)
- ✓ Basic keyboard navigation
- ✓ Simple form components (input, checkbox, button)
- ✓ Dashboard / Home screen
- ✓ Solve puzzle form and visualization
- ✓ System status screen
- ✓ Configuration viewer/editor
- ✓ CLI command integration
- ✓ Memory browser and search
- ✓ Benchmark results viewer
- ✓ Dream cycle visualization
- ✓ Real-time solving visualization
- ✓ Real-time updates and watch mode
- ✓ Themes and customization
- ✓ Command palette
- ✓ Help system
- ✓ Error handling and recovery
- ✓ Session persistence
- ✓ Performance optimization
- ✓ Unit and integration tests
- ✓ User documentation
- ✓ Video tutorials
- ✓ Performance benchmarks
- ✓ Accessibility audit
- ✅ All CLI commands accessible via TUI
- ✅ Forms validate input with helpful error messages
- ✅ Real-time visualizations update smoothly
- ✅ Keyboard navigation works for all screens
- ✅ Mouse support for all interactive elements
- ✅ Session state persists across restarts
- ✅ Configuration changes apply immediately
- ✅ Help available for all screens and commands
- ✅ TUI startup: <2s
- ✅ Screen transitions: <100ms
- ✅ Form submission: <50ms (before CLI execution)
- ✅ Real-time updates: <50ms latency
- ✅ Memory usage: <100MB for TUI
- ✅ Handle 1000+ items in lists/tables smoothly
- ✅ Intuitive navigation (learnable in <5 minutes)
- ✅ Consistent UI patterns throughout
- ✅ Clear visual hierarchy
- ✅ Helpful error messages with recovery suggestions
- ✅ Responsive feedback for all actions
- ✅ Works in terminals 80x24 and larger
- ✅ Screen reader compatible
- ✅ Keyboard-only navigation
- ✅ High contrast mode
- ✅ Adjustable font sizes
- ✅ Reduced motion option
- Graph visualizations: Strategy dependency graphs, knowledge graph
- Charts: Performance trends, solve time metrics over time
- Heatmaps: Strategy usage, puzzle difficulty patterns
- Timeline view: Session history with replay capability
- Multi-user sessions: Share solving sessions with team
- Live updates: See real-time solving progress from other users
- Chat/annotations: Communicate about strategies within TUI
- Session sharing: Export/import solving sessions and configurations
- Macro recording: Record and replay actions
- Scheduled tasks: Cron-like task scheduling
- Webhooks: Trigger actions on events
- Custom plugins: Extend TUI with plugins
- Web UI: Browser-based version of TUI
- Mobile app: iOS/Android companion app
- Progressive Web App: Installable web version
- API server: Expose TUI functionality via REST API
// Box (container)
const box = blessed.box({
top: 'center',
left: 'center',
width: '50%',
height: '50%',
border: { type: 'line' },
style: {
border: { fg: 'blue' }
}
});
// List (menu)
const list = blessed.list({
items: ['Item 1', 'Item 2'],
mouse: true,
keys: true,
vi: true,
style: {
selected: { bg: 'blue' }
}
});
// Form
const form = blessed.form({
mouse: true,
keys: true
});
// Textbox (input)
const textbox = blessed.textbox({
label: 'Name:',
height: 3,
inputOnFocus: true
});
// Progress bar
const progress = blessed.progressbar({
filled: 0,
style: {
bar: { bg: 'blue' }
}
});
// Table
const table = blessed.table({
headers: ['Name', 'Value'],
data: [['foo', 'bar']],
columnWidth: [20, 20]
});See Section 9.1 for .machine-dream-tui.json
Tested Terminals:
- ✅ iTerm2 (macOS)
- ✅ Terminal.app (macOS)
- ✅ GNOME Terminal (Linux)
- ✅ Konsole (Linux)
- ✅ Windows Terminal (Windows 10/11)
- ✅ ConEmu (Windows)
⚠️ CMD.exe (limited features)⚠️ PowerShell (requires UTF-8 encoding)
Requirements:
- UTF-8 encoding support
- 256 colors minimum (truecolor recommended)
- Mouse support (optional)
- Minimum 80x24 characters
Purpose: Enable complete testability by making all TUI actions observable and machine-readable.
Core Interface:
interface TUIOutputEvent {
timestamp: number;
eventType: 'render' | 'input' | 'navigation' | 'command' | 'state' | 'error';
component: string;
data: Record<string, unknown>;
}| Event Type | Description | Example Data |
|---|---|---|
render |
Component rendered to screen | { screen: 'solve', component: 'form', content: {...} } |
input |
User input received | { key: 'enter', component: 'form-field' } |
navigation |
Menu/screen navigation | { from: 'home', to: 'solve' } |
command |
CLI command execution | { command: 'solve', args: [...], status: 'started' } |
state |
Application state change | { field: 'sessionState.currentScreen', value: 'solve' } |
error |
Error occurred | { code: 'INVALID_INPUT', message: '...' } |
Environment Variable:
TUI_DEBUG_OUTPUT=/tmp/tui-events.jsonl machine-dream tuiCLI Flag:
machine-dream tui --debug-output /tmp/tui-events.jsonlOutput Targets:
stdout- Write to standard output (interleaved with TUI)<file>- Write to file (one JSON event per line)/dev/null- Disable output (production mode)
// Example: E2E test using event stream
const driver = new TestDriver({ debugOutput: '/tmp/test.jsonl' });
await driver.start();
await driver.pressKey('s'); // Navigate to Solve
const navEvent = await driver.waitForEvent('navigation', 5000);
expect(navEvent.data.to).toBe('solve');Dependency: string-width npm package
Purpose: Accurate character width calculation for terminals, accounting for:
- Emoji (usually 2 cells wide)
- Wide characters (CJK characters)
- Zero-width joiners
- ANSI escape codes
Usage:
import stringWidth from 'string-width';
// Emoji takes 2 cells
stringWidth('🧩'); // Returns: 2
stringWidth('A'); // Returns: 1
// Proper padding
function padMenuItem(icon: string, label: string): string {
const iconWidth = stringWidth(icon);
const iconPadding = 4 - iconWidth;
const labelPadded = label.padEnd(14);
return `${icon}${' '.repeat(iconPadding)}${labelPadded}`;
}Menu Item Layout:
┌────┬──────────────┬─────┐
│Icon│ Label │Short│
├────┼──────────────┼─────┤
│ 4 │ 14 │ 5 │
└────┴──────────────┴─────┘
🧩 Solve Puzzle [S]
🧠 Memory [M]
Width Specifications:
- Icon column: 4 characters (emoji + trailing space)
- Label column: 14 characters (padded with spaces)
- Shortcut column: 5 characters (e.g., "[S]" + space)
Unicode Box Drawing (default, when supported):
┌─────────┐
│ Content │
└─────────┘
ASCII Fallback (for limited terminals):
+---------+
| Content |
+---------+
Detection Logic:
function getBoxChars(): BoxCharacters {
if (terminalInfo.supportsUnicode && !terminalInfo.isCI) {
return {
topLeft: '┌', topRight: '┐',
bottomLeft: '└', bottomRight: '┘',
horizontal: '─', vertical: '│'
};
}
return {
topLeft: '+', topRight: '+',
bottomLeft: '+', bottomRight: '+',
horizontal: '-', vertical: '|'
};
}| Environment | Detection Method | Capabilities |
|---|---|---|
| VS Code Terminal | TERM_PROGRAM=vscode |
Full features (mouse, colors, unicode) |
| iTerm2 | TERM_PROGRAM=iTerm.app |
Full features |
| Windows Terminal | WT_SESSION env var defined |
Full features |
| Docker | /.dockerenv file exists |
Headless mode (no mouse, limited colors) |
| GitHub Actions | GITHUB_ACTIONS=true |
Headless mode, CI mode |
| Generic CI | CI=true |
Headless mode, CI mode |
| WSL | WSL_DISTRO_NAME defined |
Full features |
| cmd.exe | Windows + no WT_SESSION |
ASCII borders, no mouse, 16 colors |
| SSH | SSH_TTY or SSH_CONNECTION |
Full features (remote terminal) |
interface TerminalCapabilities {
supportsUnicode: boolean;
supportsColor: boolean;
colorDepth: 16 | 256 | 16777216; // 16, 256, or truecolor
supportsMouse: boolean;
supportsKeyboard: boolean;
isHeadless: boolean; // CI/Docker
columns: number;
rows: number;
}
function detectCapabilities(): TerminalCapabilities {
const isCI = Boolean(process.env.CI || process.env.GITHUB_ACTIONS);
const isDocker = fs.existsSync('/.dockerenv');
const isTTY = process.stdout.isTTY;
return {
supportsUnicode: !isCI && !isDocker && hasUTF8Locale(),
supportsColor: isTTY && !isCI,
colorDepth: process.stdout.getColorDepth?.() || 16,
supportsMouse: isTTY && !isCI && !isDocker,
supportsKeyboard: isTTY,
isHeadless: isCI || isDocker || !isTTY,
columns: process.stdout.columns || 80,
rows: process.stdout.rows || 24
};
}When running in CI/Docker/non-TTY environments:
- Disable interactive features
- Use simple output mode
- Skip mouse/keyboard setup
- Use ASCII-only characters
- Provide clear error messages
PuzzleGrid Component (src/tui-ink/components/PuzzleGrid.tsx):
- React/Ink component for interactive visual grid display in TUI
- Uses Box and Text components for colored, interactive rendering
- Supports highlighting cells with colors (yellow for active, green for filled)
- Use Case: TUI screens requiring interactive board visualization
BoardFormatter Utility (src/llm/BoardFormatter.ts):
- Shared utility for text-based grid formatting (DRY principle)
- Static class with no dependencies on React/Ink
- Use Cases:
- CLI commands requiring terminal output
- LLM prompts requiring plain text grids
- Text-based board exports
- Methods:
formatForPrompt()- Plain text for LLM (no colors)formatForCLI()- ANSI-colored for terminal with highlightingcountEmptyCells()- Utility method
Design Decision: Keep separate implementations for TUI (React-based) and CLI/prompt (text-based) to maintain appropriate separation of concerns.
src/tui/
├── index.ts # Public API exports
├── TUIApplication.ts # Main application orchestrator
├── types.ts # TypeScript interfaces
│
├── components/
│ ├── base/
│ │ ├── Component.ts # Base component class
│ │ └── FocusManager.ts # Focus and navigation
│ │
│ ├── layout/
│ │ ├── Screen.ts # blessed.screen wrapper
│ │ ├── Header.ts # Title bar component
│ │ ├── Sidebar.ts # Menu sidebar
│ │ ├── ContentArea.ts # Main content area
│ │ └── StatusBar.ts # Bottom status bar
│ │
│ ├── widgets/
│ │ ├── Menu.ts # Navigation menu
│ │ ├── Form.ts # Form container
│ │ ├── TextField.ts # Text input field
│ │ ├── Select.ts # Dropdown select
│ │ ├── Checkbox.ts # Boolean checkbox
│ │ ├── Button.ts # Action button
│ │ ├── Table.ts # Data table
│ │ ├── ProgressBar.ts # Progress indicator
│ │ └── LogViewer.ts # Scrolling log viewer
│ │
│ └── modals/
│ ├── Modal.ts # Base modal dialog
│ ├── Alert.ts # Alert dialog
│ ├── Confirm.ts # Confirmation dialog
│ └── HelpModal.ts # Help overlay
│
├── screens/ # Full screen implementations
│ ├── HomeScreen.ts # Dashboard/home
│ ├── SolveScreen.ts # Puzzle solving
│ ├── MemoryScreen.ts # Memory browser
│ ├── DreamScreen.ts # Dream cycle viewer
│ ├── BenchmarkScreen.ts # Benchmark runner
│ ├── DemoScreen.ts # Demo launcher
│ ├── ConfigScreen.ts # Configuration editor
│ ├── ExportScreen.ts # Export wizard
│ └── SystemScreen.ts # System utilities
│
├── services/
│ ├── CLIExecutor.ts # CLI command execution
│ ├── OutputManager.ts # JSON event stream
│ ├── StateManager.ts # Application state
│ └── ThemeManager.ts # Theme management
│
└── utils/
├── textAlign.ts # string-width alignment
├── boxDrawing.ts # Box character utilities
└── terminalDetect.ts # Environment detection
// components/base/Component.ts
export abstract class Component {
protected element: Widgets.Node;
protected outputManager: OutputManager;
abstract render(): void;
protected emit(eventType: string, data: unknown): void {
this.outputManager.emit({
timestamp: Date.now(),
eventType,
component: this.constructor.name,
data
});
}
}// screens/SolveScreen.ts
export class SolveScreen extends Component {
private form: Form;
private submitButton: Button;
render(): void {
this.form = new Form({ /* config */ });
this.submitButton = new Button({
label: 'Start Solve',
onClick: () => this.handleSubmit()
});
this.emit('render', { screen: 'solve' });
}
private async handleSubmit(): Promise<void> {
const formData = this.form.getData();
this.emit('command', {
command: 'solve',
args: [formData.puzzleFile],
options: formData
});
await this.cliExecutor.execute('solve', [formData.puzzleFile], formData);
}
}Purpose: Manage AI model connection profiles for easy switching between providers.
┌──────────────────────────────────────────────────────────────────────────┐
│ 🤖 AI Model Profile Manager Spec 13 Integration │
├──────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─── Available Profiles (5) ──────────────────────────────────────┐ │
│ │ │ │
│ │ ► lm-studio-local (Active) │ │
│ │ Provider: LM Studio | Model: qwen3-30b | Last Used: 5m ago│ │
│ │ http://localhost:1234/v1 | Tags: local, default │ │
│ │ │ │
│ │ openai-gpt4 │ │
│ │ Provider: OpenAI | Model: gpt-4 | Last Used: 2h ago │ │
│ │ https://api.openai.com/v1 | Tags: cloud, production │ │
│ │ │ │
│ │ anthropic-claude │ │
│ │ Provider: Anthropic | Model: claude-3-opus | Never used │ │
│ │ https://api.anthropic.com/v1 | Tags: cloud, testing │ │
│ │ │ │
│ │ ollama-local │ │
│ │ Provider: Ollama | Model: llama3 | Last Used: 1d ago │ │
│ │ http://localhost:11434/v1 | Tags: local, experimental │ │
│ │ │ │
│ │ openrouter-mixed │ │
│ │ Provider: OpenRouter | Model: auto | Never used │ │
│ │ https://openrouter.ai/api/v1 | Tags: cloud, fallback │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─── Selected Profile: lm-studio-local ───────────────────────────┐ │
│ │ │ │
│ │ Name: lm-studio-local │ │
│ │ Description: Local LM Studio with Qwen3 30B │ │
│ │ Provider: LM Studio (local server) │ │
│ │ Base URL: http://localhost:1234/v1 │ │
│ │ Model: qwen3-30b │ │
│ │ API Key: (none required for local) │ │
│ │ │ │
│ │ Parameters: │ │
│ │ Temperature: 0.7 │ │
│ │ Max Tokens: 2048 │ │
│ │ Timeout: 60000ms │ │
│ │ Top P: 0.9 │ │
│ │ │ │
│ │ Metadata: │ │
│ │ Created: 2 weeks ago │ │
│ │ Last Used: 5 minutes ago │ │
│ │ Usage Count: 127 times │ │
│ │ Tags: local, default │ │
│ │ Status: ✓ Healthy (last checked: 1m ago) │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────────────┘ │
│ │
│ [Set Active] [Add New] [Edit] [Test] [Delete] [Export] [Import] [Back] │
│ │
└──────────────────────────────────────────────────────────────────────────┘
[Enter] Set Active [A] Add [E] Edit [T] Test [D] Delete [Q] Back
Add Profile Form:
┌──────────────────────────────────────────────────────────────────────────┐
│ 🤖 Add AI Model Profile │
├──────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─── Basic Information ─────────────────────────────────────────────┐ │
│ │ │ │
│ │ Profile Name: [lm-studio-qwen3 ] │ │
│ │ Description: [Local LM Studio with Qwen3 30B ] │ │
│ │ │ │
│ │ Provider: [LM Studio ▼] │ │
│ │ Options: LM Studio, OpenAI, Anthropic, Ollama, │ │
│ │ OpenRouter, Custom │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─── Connection Settings ────────────────────────────────────────────┐ │
│ │ │ │
│ │ Base URL: [http://localhost:1234/v1 ] │ │
│ │ Model: [qwen3-30b ] │ │
│ │ API Key: [${LM_STUDIO_KEY} ] │ │
│ │ (Use ${ENV_VAR} for environment variables) │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─── Model Parameters ───────────────────────────────────────────────┐ │
│ │ │ │
│ │ Temperature: [0.7 ] ← → (0.0-2.0) │ │
│ │ Max Tokens: [2048 ] ← → (1-32768) │ │
│ │ Timeout: [60000] ms ← → (1000-300000) │ │
│ │ Top P: [0.9 ] ← → (0.0-1.0) │ │
│ │ Frequency Pen: [0.0 ] ← → (-2.0-2.0) │ │
│ │ Presence Pen: [0.0 ] ← → (-2.0-2.0) │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─── Organization ───────────────────────────────────────────────────┐ │
│ │ │ │
│ │ Tags: [local, default ] │ │
│ │ (Comma-separated) │ │
│ │ Display Color: [cyan ▼] │ │
│ │ ☑ Set as active profile after creation │ │
│ │ ☑ Test connection before saving │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ [ Save & Test ] [ Save ] [ Test Only ] [ Cancel ] │
│ │
└──────────────────────────────────────────────────────────────────────────┘
[Tab] Next Field [↑↓] Navigate [Space] Toggle [Enter] Save [Esc] Cancel
Key Features:
- Profile list: Scrollable list with active profile indicator
- Profile details: Full configuration display for selected profile
- Quick actions: Set active, add, edit, test, delete operations
- Connection testing: Health check before saving
- Import/export: Share profiles across machines
- Environment variables: Secure API key storage using ${ENV_VAR} syntax
- Color coding: Visual distinction for profiles in TUI
- Usage tracking: Show last used time and usage count
Purpose: Visualize AI model Sudoku solving with live reasoning display.
┌──────────────────────────────────────────────────────────────────────────┐
│ 🤖 AI Model Sudoku Player Move: 15 | Memory: ON │
├──────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─── Puzzle Grid ─────────────┐ ┌─── AI Model Reasoning ───────────┐ │
│ │ │ │ │ │
│ │ 5 3 · │ · 7 · │ · · · │ │ Analyzing row 2, column 2... │ │
│ │ 6 · · │ 1 9 5 │ · · · │ │ │ │
│ │ · 9 8 │ · · · │ · 6 · │ │ Row 2 has: 6, 1, 9, 5 │ │
│ │ ───── ───── ───── │ │ Column 2 has: 3, 9, 6 │ │
│ │ 8 · · │ · 6 · │ · · 3 │ │ Box 1 has: 5, 3, 6, 9, 8 │ │
│ │ 4 · · │ 8 · 3 │ · · 1 │ │ │ │
│ │ 7 · · │ · 2 · │ · · 6 │ │ Missing from intersection: │ │
│ │ ───── ───── ───── │ │ {2, 4, 7} │ │
│ │ · 6 · │ · · · │ 2 8 · │ │ │ │
│ │ · · · │ 4 1 9 │ · · 5 │ │ Trying value 7 at (2,2) │ │
│ │ · · · │ · 8 · │ · 7 9 │ │ │ │
│ │ │ └───────────────────────────────────┘ │
│ │ *Current ·Empty #Correct │ │
│ └──────────────────────────────┘ │
│ │
│ ┌─── Move History ───────────────────────────────────────────────────┐ │
│ │ #13 | (1,3)=4 | CORRECT ✓ | "Only candidate in row 1" │ │
│ │ #14 | (2,2)=7 | INVALID ✗ | "7 already in column 2" │ │
│ │ #15 | (2,2)=4 | CORRECT ✓ | "Only remaining candidate" ← now │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─── Statistics ─────────────────────────────────────────────────────┐ │
│ │ Correct: 12/15 (80%) | Invalid: 2 | Wrong: 1 | Time: 01:23 │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │
│ [ Pause ] [ Memory Toggle ] [ Export Session ] [ Stop ] │
│ │
└──────────────────────────────────────────────────────────────────────────┘
[Space] Pause [M] Toggle Memory [E] Export [Q] Stop
Key Features:
- Live AI model reasoning display: Shows the AI model's step-by-step analysis
- Move validation feedback: CORRECT (green), INVALID (red), WRONG (yellow)
- Memory toggle button: Switch between memory ON/OFF for A/B testing
- Statistics panel: Real-time accuracy tracking
- Move history: Scrollable history with reasoning excerpts
- Profile selection: Choose from saved profiles (Spec 13)
Configuration Options:
┌─── AI Model Configuration ────────────────────────────────────────────┐
│ │
│ Active Profile: [lm-studio-local ▼] [Edit Profile] │
│ Base URL: [http://localhost:1234/v1 ] │
│ Model: [qwen3-30b ] │
│ Temperature: [0.7 ] ← → (0.0-1.0) │
│ │
│ ┌─── Memory Settings ────────────────────────────────────────────┐ │
│ │ ● Memory Enabled (include past experiences in prompts) │ │
│ │ ○ Memory Disabled (baseline mode for A/B testing) │ │
│ │ │ │
│ │ Max History Moves: [20 ] ← → (0-50) │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ [ Start AI Play ] [ Manage Profiles ] [ Cancel ] │
│ │
└─────────────────────────────────────────────────────────────────────────┘
interface TUITestDriver {
// Lifecycle
start(options?: TUITestOptions): Promise<void>;
stop(): Promise<void>;
// Input simulation
pressKey(key: string): Promise<void>;
pressKeys(keys: string[]): Promise<void>;
typeText(text: string): Promise<void>;
// State inspection (from JSON event stream)
waitForEvent(type: string, timeout?: number): Promise<TUIOutputEvent>;
getEvents(filter?: Partial<TUIOutputEvent>): TUIOutputEvent[];
getLastEvent(type?: string): TUIOutputEvent | undefined;
clearEvents(): void;
// Assertions
assertScreen(screenName: string): void;
assertFocus(componentId: string): void;
assertText(pattern: string | RegExp): void;
assertEventEmitted(type: string, data?: Partial<unknown>): void;
}
interface TUITestOptions {
debugOutput?: string; // Path to event log file
headless?: boolean; // Run in headless mode
dimensions?: { cols: number; rows: number };
theme?: 'dark' | 'light';
}import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import { TestDriver } from '../helpers/TestDriver';
describe('Solve Workflow E2E', () => {
let driver: TestDriver;
beforeAll(async () => {
driver = new TestDriver({
debugOutput: '/tmp/test-solve.jsonl',
headless: true
});
await driver.start();
});
afterAll(async () => {
await driver.stop();
});
it('should complete solve workflow', async () => {
// Navigate to Solve screen
await driver.pressKey('s');
const navEvent = await driver.waitForEvent('navigation', 5000);
expect(navEvent.data.to).toBe('solve');
// Fill form
await driver.typeText('puzzles/easy-01.json');
await driver.pressKey('tab');
await driver.typeText('test-session');
// Submit form
await driver.pressKeys(['ctrl', 'enter']);
// Wait for command execution
const cmdEvent = await driver.waitForEvent('command', 5000);
expect(cmdEvent.data.command).toBe('solve');
expect(cmdEvent.data.args).toContain('puzzles/easy-01.json');
// Wait for completion
const completeEvent = await driver.waitForEvent('command-complete', 30000);
expect(completeEvent.data.success).toBe(true);
});
});// tests/tui/helpers/MockScreen.ts
export class MockScreen {
private events: TUIOutputEvent[] = [];
emit(event: TUIOutputEvent): void {
this.events.push(event);
}
getEvents(): TUIOutputEvent[] {
return [...this.events];
}
render(): void {
// No-op in test mode
}
}Document Status: ✅ Complete and Ready for Implementation
Next Steps:
- Review with UX team
- Create wireframe mockups
- Begin Phase 1 implementation
- User testing with prototypes
- Iterate based on feedback