# Changelog Archive (Legacy Crates v0.8.x and Earlier)

This file contains changelog entries for legacy crates (`lib/core`, `lib/sys`, plugins).
For new architecture changes (v0.9.0-dev), see [CHANGELOG.md](../CHANGELOG.md).

## [0.8.1] - Unreleased

### Changed

- **Screen module reorganization** - Better separation of concerns
  - Created `render/` submodule: chrome (status/tab/cmd line), line, pipeline, separator
  - Created `layout/` submodule: split tree, tab management
  - Created `WindowStore` as single source of truth for windows
  - Simplified `Window` struct from 14 fields to 8 fields:
    - `bounds: WindowRect` (combines x, y, width, height)
    - `viewport: Viewport` (combines scroll, cursor, desired_col)
    - `config: WindowConfig` (groups line_number, scrollbar, sign_column, border)
    - `id: WindowId` (type-safe wrapper instead of raw usize)

### Added

- **Enhanced Markdown Decorations** (Epic #89) - Complete markdown rendering overhaul
  - **Phase 1: Heading Decorations** (#90)
    - Heading indentation by level (H1=0, H2=1 space, H3=2 spaces, etc.)
    - Inline code span background styling with backtick concealment
    - Link background styling for distinct link appearance
    - Strikethrough styling with `~~` marker concealment
  - **Phase 2: Horizontal Rules and Blockquotes** (#91)
    - Horizontal rules: `---`/`***`/`___` → full-width `────────` line
    - Blockquotes: `>` → `│ ` vertical bar with background color
  - **Phase 3: Table Border Decorations** (#92)
    - Visual unicode borders (─│┌┐└┘├┤┬┴┼) around markdown tables
    - Cells expand to uniform width with proper padding
    - New `MarkdownTableBorderStage` render stage
    - `virtual_lines` system in RenderData for rendering lines above/below content

- **% motion for matching bracket navigation** (Issue #123) - Jump between matching brackets
  - Supports `()`, `[]`, `{}` bracket pairs
  - Vim-compatible behavior: cursor on bracket jumps to match, otherwise searches forward on line
  - Inclusive motion for operator support (`d%`, `y%`, `c%`)
  - Added `Motion::MatchingBracket` variant to core motion system
  - Added `CursorMatchingBracketCommand` with `%` keybinding

- **Backtick auto-pair completion** (Issue #124) - Auto-close backticks when typing
  - Typing `` ` `` now auto-completes to ``` `` ``` with cursor between
  - Useful for markdown inline code, JavaScript template literals, shell command substitution
  - Added to pair plugin rainbow bracket highlighting

- **Explorer backspace and dot navigation** (Issue #128) - Navigate directories with Backspace and dot
  - `<Backspace>` in explorer navigates up to parent directory (changes root)
  - `.` sets current selection as new root directory
  - Matches nvim-tree behavior (navigate up with backspace, set root with dot)
  - Backspace still works for text deletion in input mode (create/rename/filter)

- **Sticky context headers** (Issue #88) - Overlay at viewport top showing enclosing scopes
  - Displays 1-3 parent scope headers as user scrolls through files
  - Works with both markdown headings and code scopes (functions, classes, impl blocks)
  - Uses same ContextProvider infrastructure as statusline breadcrumbs (#130, #131, #132)
  - Buffer content passed via EditorContext (same pattern as #133) for markdown support
  - Settings: `sticky_headers_enabled`, `sticky_headers_max_count`, `sticky_headers_show_separator`
  - z-order 125 overlay window using PluginWindow trait
  - Auto-queries context at top visible line

- **TreesitterContextProvider** - AST-based scope detection for breadcrumb navigation (#132)
  - Detects code hierarchy (functions, classes, impl blocks, methods) by analyzing treesitter parse tree
  - Multi-language support: Rust, Python, JavaScript, C, C++, Go, Java
  - Provides context at cursor position: e.g., `> mod.rs > impl Screen > fn render_windows`
  - Phase 3 of context provider system, enables statusline breadcrumb integration

- **Core ContextProvider trait and registry** (Issue #130) - Foundation for plugin-based context/scope detection
  - `ContextProvider` trait with `get_context()`, `name()`, `supports_buffer()` methods
  - `ContextItem` struct for representing individual context levels (text, line range, kind, level)
  - `ContextHierarchy` struct with helper methods (`to_breadcrumb()`, `current_scope()`, `at_level()`)
  - Multi-provider registry in `PluginStateRegistry` with priority-based resolution
  - Enables future implementations: markdown headings, treesitter AST nodes, LSP symbols

- **Markdown Context Provider** (Issue #131) - Detect heading hierarchy in markdown files
  - `MarkdownContextProvider` implementation with tree-sitter parsing
  - Supports H1-H6 ATX-style headings (`#`, `##`, `###`, etc.)
  - Smart caching with content hash for performance (>95% cache hit rate)
  - Stack-based hierarchy algorithm for nested headings
  - Returns breadcrumb format: `> CLAUDE.md > Architecture > Workspace Structure`
  - Extended `ContextProvider` trait API to pass `content: &str` parameter
  - 7 comprehensive unit tests covering edge cases

- **Context breadcrumb in statusline** (Issue #133) - Shows current scope hierarchy in statusline
  - Displays breadcrumb like: ` > CLAUDE.md > Section > Subsection > `
  - Works with markdown headings via `MarkdownContextProvider`
  - Works with code scopes via `TreesitterContextProvider` (Rust, Python, JS, C, etc.)
  - Smart truncation for long names and deep nesting
  - Settings: `context_breadcrumb_enabled`, `context_separator`, `context_max_items`
  - Extended `StatuslineRenderContext` to include active buffer content, ID, and cursor position
  - Completes Epic #129 (Context Provider Trait System)

- **Scope navigation commands** (Issue #133) - Jump between scope headers with keyboard shortcuts
  - `gu` - Jump to parent scope (go up)
  - `[s` - Jump to previous scope header (placeholder - TODO)
  - `]s` - Jump to next scope header (placeholder - TODO)
  - Works across all languages with context providers
  - Commands registered in treesitter plugin with keybindings

- **File explorer visual enhancements** (Issue #127) - nvim-tree style coloring and tree structure
  - **Dedicated FileExplorerStyles** in theme system with distinct colors for each file category:
    - Directories: blue (bold)
    - Source files: orange (for .rs, .py, .js, etc.)
    - Config files: gray/dimmed (for .toml, .yaml, .json)
    - Documentation: cyan (for README, .md)
    - Data files: magenta (for .csv, .sql, .db)
    - Media files: pink (for images, audio, video)
    - Special files: yellow (for LICENSE, .gitignore)
    - Lock files: dimmed yellow (for Cargo.lock, package-lock.json)
    - Executable files: green (for shell scripts, binaries)
    - Hidden files: dimmed gray
  - Box-drawing characters (│, ├, └) for visual tree hierarchy
  - Three tree styles: None (indent only), Simple (ASCII ">"), BoxDrawing (Unicode)
  - Hidden items count display at bottom: "(N hidden)" when hidden files are not shown
  - Explorer settings section with options:
    - `explorer.enable_colors` - Toggle file type coloring (default: true)
    - `explorer.tree_style` - Choose tree drawing style (default: "box_drawing")
    - `explorer.show_hidden` - Toggle hidden files visibility (default: false)
    - `explorer.show_sizes` - Toggle file size display (default: false)

### Enhanced

- **Bidirectional multi-char search** (Issue #125) - `s` key now searches both directions simultaneously
  - Added `Direction::Both` variant to support bidirectional search
  - Labels prioritize by distance (Manhattan distance from cursor)
  - Closest matches get simpler labels (s, f, n, j, k...)
  - Works with operators: `dsab` deletes to closest match in either direction

- **Viewport-limited jump labels** (Issue #126) - Range-finder labels now only appear within visible viewport
  - Added `active_window_height` field to EditorContext
  - Jump labels filtered by viewport boundaries in render
  - Dramatically reduces visual clutter in large files (100+ matches → ~50 visible labels)
  - Labels update automatically when scrolling

### Fixed

- **Cursor no longer moves into padding areas in decorated tables** (#89)
  - Added `col_mapping` to `DecorationKind::Conceal` for buffer→visual column translation
  - Position-based mapping algorithm that skips padding areas
  - Cursor stays on content characters, jumps directly to trailing space/pipe

- **Visual mode now disables decorations on selected lines** (#89)
  - Replaced single-line `is_insert_mode` with `skip_decoration_lines: HashSet<usize>`
  - In visual mode, all selected lines show raw markdown (like insert mode)
  - Works with visual (`v`), visual line (`V`), and visual block (`Ctrl-V`) modes

- **Multiple Conceal decorations per line now render correctly** (Issue #143)
  - Changed from single-index iterator to multi-decoration lookup
  - Now finds ALL decorations covering each character position
  - Conceal decorations can now apply background styles when both are present
  - Enables proper rendering of markdown table pipes and other multi-conceal scenarios

### Changed

- **reo-cli**: Changed default output format for `keys` command from `plain_text` to `raw_ansi` for better visual feedback (Issue #134)
- **reo-cli**: Added `--format` flag to `keys` command to allow choosing output format (raw_ansi, plain_text, cell_grid)

## [0.8.0] - 2026-01-09

### Fixed

- **tokio::spawn panics in EventBus handlers** (Issue #120) - Fix plugins using `tokio::spawn()` after PR #85 moved EventBus to std::thread
  - Capture `tokio::runtime::Handle::current()` at `subscribe()` start (runs in tokio context)
  - Use `handle.spawn()` instead of `tokio::spawn()` in EventBus handlers
  - Affected: completion (BufferModified), LSP (GotoDefinition, GotoReferences, ShowHover)

### Performance

- **Priority channels for user input events** (Issue #95, #86) - Dual-channel architecture for responsive user experience
  - Separates high-priority user input from low-priority background events
  - `hi_tx/hi_rx` (64 capacity): user input, mode changes, text insertion
  - `lo_tx/lo_rx` (255 capacity): render signals, plugins, background tasks
  - Biased `select!` ensures high-priority events processed first
  - `MAX_LO_DRAIN=16` provides fairness for background events
  - Auto-pair latency reduced from ~100ms to ~92us (1000x improvement, closes #86)

### Added

- **GitHub Actions CI pipeline** (Issue #121) - Automated code quality checks on PRs and pushes to develop
  - Format check with `cargo fmt --all --check`
  - Clippy with zero-warning enforcement (`-D warnings`)
  - Build verification for entire workspace
  - Unit tests and doc tests
  - Rust cache for faster subsequent builds

- **Dynamic content in DisplayRegistry** (Issue #57) - Allow plugins to show contextual status line info
  - `DisplayContext` struct for render context with `PluginStateRegistry` access
  - `DynamicDisplayFn` type alias for dynamic display callbacks
  - `DisplayInfo::with_dynamic()` method for fluent configuration
  - `DisplayInfoBuilder::dynamic()` builder method
  - `DisplayRegistry::display_string()` now takes `PluginStateRegistry` and invokes dynamic callbacks
  - Enables dynamic status like "Explorer (3 files)" or "Telescope (42 results)"

- **Window resize operations** (Issue #54) - Implement direction-specific window resizing
  - `SplitNode::adjust_ratio_in_direction()` - Find innermost split matching direction and adjust ratio
  - `Screen::resize_window(direction, delta)` - Public API for resizing active window
  - `WindowAction::Resize` handler now functional (5% ratio change per unit delta)
  - Vertical direction adjusts width, Horizontal direction adjusts height

- **Mouse click and scroll support** (Issue #59) - Basic mouse interaction for cursor positioning and scrolling
  - Left click: Move cursor to clicked position and focus window if different
  - Scroll wheel: Move viewport up/down by 3 lines, cursor adjusts to stay visible
  - Coordinate translation: Screen position to buffer position with gutter and scrollbar awareness
  - Server mode support: Mouse events forwarded in dual-output mode

- **Theme customization/override system** (Issue #55) - Allow users to override individual colors/styles in TOML config
  - `ThemeOverrides` struct for storing style path -> override mappings
  - `StyleOverride` struct with fg, bg, underline_color, and attribute options
  - `parse_color()` function supporting hex, rgb(), ansi:N, and named color formats
  - `Theme::from_name_with_overrides()` and `Theme::apply_overrides()` methods
  - `editor.theme_overrides` field in profile config schema
  - Example config:
    ```toml
    [editor.theme_overrides]
    "statusline.background" = { bg = "#1a1b26" }
    "gutter.line_number" = { fg = "#565f89" }
    "statusline.mode.normal" = { fg = "#1a1b26", bg = "#7aa2f7", bold = true }
    ```

- **Consolidated mode display logic into DisplayRegistry** (Issue #53) - Centralize all mode display logic in one place
  - New `display/icons.rs` module for icon constants
  - `DisplayRegistry::mode_icon()` - Get icon for current mode state
  - `DisplayRegistry::mode_style()` - Get style for current mode from theme
  - `DisplayRegistry::mode_name()` - Get display name ("Normal", "Insert", etc.)
  - `DisplayRegistry::short_mode_name()` - Get short name ("NORMAL", "INSERT", etc.)
  - `DisplayRegistry::hierarchical_display()` - Build "Kind | Mode | SubMode" string
  - Removed duplicate logic from `Screen` (was `get_mode_style()`, `get_mode_name()`)
  - Removed `ModeState::hierarchical_display()` - use `DisplayRegistry` instead
  - `ModeSnapshot::from_mode()` added for RPC serialization with display registry

- **Metadata-driven interactor input behavior** (Issue #46) - Refactored `accepts_char_input()` to use registry instead of hardcoded checks
  - `InteractorConfig` struct for configuring input behavior per interactor
  - `InteractorRegistry` for storing and querying interactor configurations
  - `accepts_char_input_with(registry)` method on `ModeState` for registry-based lookup
  - `PluginContext::register_interactor()` for plugins to register their input behavior
  - Window mode registered via `InteractorConfig::using_keymap()` instead of hardcoded exclusion
  - Default behavior: unregistered interactors accept character input (safe default)

- **HandlerContext mode change helpers** (Issue #44) - Reduce mode change boilerplate
  - `enter_interactor_mode(component_id)` - Enter interactor sub-mode for text input
  - `exit_to_normal()` - Return to normal editor mode
  - `set_mode(mode)` - Set arbitrary mode state for edge cases
  - Updated Range-Finder plugin: 5 mode changes simplified
  - Updated Microscope plugin: 1 mode change simplified

- **Subscription helper macros** (Issue #41) - Reduce plugin boilerplate with three new macros
  - `subscribe_state!` - Simple state mutation + render pattern (4 variants)
  - `subscribe_state_mode!` - State mutation + mode change + render (2 variants)
  - `subscribe_state_conditional!` - Conditional render based on return value (4 variants)
  - Migrated Explorer plugin: 23 subscription blocks (~180 lines saved)
  - Migrated Range-Finder plugin: 5 subscription blocks (~30 lines saved)
  - Total: ~210 lines of boilerplate removed across 28 subscription blocks

- **`subscribe_targeted()` API for EventBus** (Issue #45) - New method to automatically filter events by component ID
  - `TargetedEvent` trait for events with a `target: ComponentId` field
  - Implemented for `PluginTextInput`, `PluginBackspace`, and `RequestFocusChange`
  - Eliminates boilerplate target-checking code in plugin event handlers
  - Migrated 7 subscriptions across 4 plugins (Explorer, Microscope, Range-finder, Which-key)

### Changed

- **Remove dead status line code** (Issue #50) - Delete unused `StatusLineComponent` and consolidate duplicates
  - Deleted `lib/core/src/component/status_line.rs` (303 lines) - `StatusLineComponent` was never instantiated
  - Deleted `lib/core/src/screen/status_line.rs` (256 lines) - `StatusLineRenderer` trait was never called
  - Removed `impl StatusLineRenderer for Screen` (31 lines) - Only consumer of deleted functions
  - Active rendering uses `Screen::render_status_line_to_buffer()` which remains unchanged
  - Fixes OperatorPending style bug (was in dead code path using wrong style)

- **Remove unused cursor and animation theme features** (Issue #49) - Dead code cleanup
  - Removed `CursorStyles` struct (line, column, glow, pulse fields never accessed)
  - Removed `EffectConfig` struct (never instantiated)
  - Removed `AnimationConfig` struct (actual animation system uses hardcoded frame rate)
  - Removed `HighlightGroup::CursorEffect` enum variant (never applied)
  - Updated docs/animation-system.md to remove future config section

- **RAII-based cursor synchronization** (Issue #48) - Centralize cursor sync between windows and buffers
  - Added `Screen::save_cursor_to_active_window()` for pre-split cursor save
  - Added `Screen::switch_active_window()` for full cursor handoff during navigation
  - Refactored `handle_window_split()` to use centralized API (15 lines → 1 call)
  - Refactored `handle_window_navigate()` to use centralized API (50 lines → direction lookup + 1 call)
  - Eliminates manual cursor sync scattered across handlers, reducing error risk

- **Split large subscribe() methods** (Issue #52) - Improve plugin maintainability by splitting monolithic subscribe() methods
  - Explorer plugin: Split 426-line method into 9 focused sub-methods (raw_input, navigation, tree_operations, clipboard, file_operations, input_handling, visual_mode, focus_visibility, popup)
  - Range-Finder plugin: Split 191-line method into 5 focused sub-methods (jump_mode_handlers, jump_input_handler, fold_handlers, cleanup)
  - Removed `#[allow(clippy::too_many_lines)]` pragmas from both plugins

- **Decomposed window render_to_buffer() method** (Issue #51) - Extract focused helper methods for better testability
  - `compute_line_number_width()` - Calculate line number column width
  - `render_fold_marker_to_buffer()` - Render collapsed fold indicators
  - `render_empty_lines_to_buffer()` - Fill viewport with tilde markers
  - Main method reduced from ~106 to ~82 lines with clearer separation of concerns

- **Declarative mode metadata** (Issue #42) - Replace hardcoded `mode_for_command()` with `resulting_mode()` trait method
  - Added `resulting_mode()` method to `CommandTrait` with default `None` return
  - Implemented for 32 mode-changing commands (mode, window, operator, command-line)
  - Replaced 60-line string matching function with 6-line trait-based lookup
  - Provides compile-time safety: no more missing match arms causing flaky tests
  - Fixed bug: `enter_visual_line_mode` was missing from old implementation

- **Unified active buffer tracking** (Issue #47) - Removed redundant `active_buffer_id` field from Runtime
  - Screen is now the single source of truth for active buffer ID
  - `Runtime::active_buffer_id()` method derives value from `Screen::active_buffer_id()`
  - Eliminates dual tracking and manual synchronization between Runtime and Screen
  - Simplifies buffer switching, file opening, and window navigation code

- **Window move commands use SwapDirection** (Issue #54) - 8 move commands now use `SwapDirection` instead of `MoveDirection`
  - `WindowMoveLeft/Down/Up/Right` commands and their window-mode variants now perform actual swaps
  - Consistent behavior between move and swap operations

### Removed

- **`WindowAction::MoveDirection`** (Issue #54) - Removed redundant enum variant
  - Was identical in purpose to existing `SwapDirection` but never implemented
  - 8 commands updated to use `SwapDirection` directly

### Fixed

- **Light theme syntax highlighting** (Issue #43) - Light theme now uses proper One Light colors
  - Added `light_palette` module with Atom One Light colors (red, blue, purple, green, cyan, orange, yellow)
  - Created `TreesitterTheme::light()` with comprehensive capture mappings
  - Fixed `from_theme_name()` to correctly return light theme instead of dark
  - 3 new tests for light theme functionality

- **RegisterOption events not processed** (Issue #39) - Options registered via `bus.emit(RegisterOption)` are now properly added to the option registry
  - `:set` commands now work for all core options (signcolumn, number, tabwidth, etc.)
  - Fix: Create OptionRegistry before plugins subscribe and add event handler

---

## [0.7.10] - 2026-01-06

### Fixed

- **reo-cli REPL help text** (Issue #36) - Help text now auto-generated from clap definitions
  - Fixed incorrect `screen` command description (said "dimensions" but returned content)
  - Removed non-existent `screen-content` command from help
  - Added `screen-size` command for getting dimensions
  - Added `capture` as visible alias for `screen` command
  - Help text now always matches implementation (single source of truth)
  - Added 10 unit tests for command parsing and help generation

### Added

- **Sign column and virtual text configuration** (Issue #29) - Phase 3 of diagnostics system (#21)
  - Sign column modes: `auto`, `yes`, `no`, `number`
    - `auto`: Show sign column only when signs are present (width 2)
    - `yes`: Always show sign column (default, width 2)
    - `no`: Never show sign column
    - `number`: Display signs as background color on line numbers
  - Virtual text options: `:set virtual_text`, `virtual_text_prefix`, `virtual_text_max_length`, `virtual_text_show`
    - `virtual_text` (bool): Enable/disable virtual text display
    - `virtual_text_prefix` (string): Custom prefix (empty = use severity icons)
    - `virtual_text_max_length` (number): Maximum length before truncation (default: 80)
    - `virtual_text_show` (string): "first", "highest", or "all" mode
  - Settings menu integration for all new options under "Diagnostics" section
  - 14 new tests for sign column modes and virtual text configuration

- **Virtual text system for inline diagnostics** (Issue #28) - Display diagnostic messages after line content
  - `VirtualTextEntry` type with text, style, and priority fields
  - `VirtualTextStyles` in theme for severity-based styling (error, warn, info, hint)
  - Rendering with automatic truncation and ellipsis when exceeding viewport
  - LSP integration: severity icons (● error, ◐ warning, ⓘ info, · hint) + message
  - Priority-based resolution (ERROR 404 > WARNING 403 > INFO 402 > HINT 401)
  - 44 new tests covering all virtual text functionality

- **Multi-instance server support** (Issue #19) - Multiple reovim servers can now run concurrently
  - Port fallback: When default port (12521) is in use, server automatically tries 12522, 12523, etc.
  - Port files: Each server writes `~/.local/share/reovim/servers/<pid>.port` for discovery
  - `reo-cli list` command: Lists all running reovim server instances with PID and port
  - Auto-discovery: `reo-cli` auto-connects to single server, prompts when multiple servers running
  - Clean shutdown: Port files automatically removed when server exits

- **Ex-command registry system** - Plugins can now register custom ex-commands dynamically
  - `ExCommandRegistry` for thread-safe command registration and dispatch
  - `RegisterExCommand` event for plugin-based command registration
  - Support for three command patterns: zero-arg, single-arg, and subcommand
  - All handlers include descriptions for help/completion systems
- **Profile trait system** - Framework for extensible configuration profiles
  - `Configurable` trait for components that participate in profile save/load
  - `ProfileRegistry` for coordinating serialization across all registered components
  - `RegisterConfigurable` event for plugin components to register for profile management
  - Profile events: `ProfileLoadEvent`, `ProfileSaveEvent`, `ProfileListEvent`
- **ProfilesPlugin** - New plugin for profile command handling
  - `:profile list` - Open profile picker
  - `:profile load <name>` - Load a profile by name
  - `:profile save <name>` - Save current settings as a profile
- **Health check system** - Diagnostic system for verifying core and plugin status
  - `:health` and `:checkhealth` commands to open health check modal
  - Modal UI (z-order 700) with category grouping and navigation (j/k, r, q/Esc)
  - Expandable details view - press Space/Enter to toggle full details for selected check
  - `RegisterHealthCheck` event for plugins to register custom health checks
  - Built-in checks for runtime, plugin system, event bus, terminal, and keybindings
  - Plugin-decoupled architecture - zero core modifications using v0.7.9+ ex-command registry
- **Plugin-specific status line styling** - Plugins can now provide custom colors for status line
  - Each plugin defines its own `Style` with custom fg/bg colors
  - Visual identity: Explorer (orange), Microscope (blue), Settings (gray), Leap (green), Health (teal), Jump (gold)
  - Status line shows `[INTERACTOR][MODE]` as separate colored sections
  - `Color` type exported from `reovim_core::highlight` for plugin use
- **LSP debugging tools** (Issue #26) - Tools for debugging LSP communication
  - LSP health check: Shows server status, document count, diagnostic stats, and timestamps in `:health` modal
  - `:LspLog` command to open the latest LSP log file directly in the editor
  - Dedicated LSP log: `--lsp-log` flag for capturing JSON-RPC messages to separate file
    - `--lsp-log=default` creates timestamped `lsp-<timestamp>.log` in data directory
    - `--lsp-log=/path/to/file.log` for custom path
    - `--lsp-log=default:LEVEL` or `--lsp-log=/path:LEVEL` for configurable verbosity
    - Supported levels: error, warn, info, debug, trace (default: trace)
    - Logs show `->` for outgoing and `<-` for incoming messages
- **Request-driven cursor movement with operator support** - Plugin-to-runtime communication for cursor positioning
  - `RequestCursorMove` event allows plugins to request cursor movement
  - `Motion::JumpTo { line, column }` variant for absolute positioning
  - `InnerEvent::MoveCursor` for runtime event loop handling
  - Automatic operator integration: `d`/`y`/`c` + jump creates `OperatorMotionAction`
  - Runtime detects `OperatorPending` mode and applies operators to jump targets
  - Enables jump navigation, LSP goto-definition, and other plugin-driven navigation with full vim operator semantics

### Fixed

- **LSP diagnostics not received after opening files** (Issue #26)
  - rust-analyzer uses LSP 3.17 "pull diagnostics" instead of push notifications
  - Now request diagnostics immediately after `textDocument/didOpen`
  - Handle `workspace/diagnostic/refresh` requests from server

### Changed

- **DisplayInfo API (BREAKING)** - Simplified and made styling mandatory
  - `DisplayInfo::new()` now requires `style: Style` parameter
  - Removed `EditModeKey`, `SubModeKey` enums (mode-specific displays removed)
  - Removed `DisplayInfoBuilder::when_mode()` and `when_sub_mode()` methods
  - `DisplayRegistry` simplified to single HashMap lookup
  - `register_builtins()` now requires `theme` parameter
  - Plugins must update to provide styles when registering display info

- **Ex-command architecture refactored** - Full decoupling of core from plugin-specific commands (Issue #13)
  - Removed `Settings`, `ProfileLoad`, `ProfileSave`, `ProfileList` variants from `ExCommand` enum
  - Added generic `Plugin { command: String }` variant for all plugin-registered commands
  - Settings menu now registers `:settings` command via `RegisterExCommand` event
  - Profile commands now handled by dedicated ProfilesPlugin
  - Core handlers dispatch to registry instead of hardcoded match arms
- **Paste animation** - Visual pulse animation feedback for paste operations
  - Cyan pulsing glow (600ms, 2 cycles) when pasting with `p` or `P`
  - Distinct from yank's gold fade animation
  - Works with both characterwise and linewise paste
  - Helps locate pasted content in large files
- **Performance logging reduced** - [RTT] performance logs lowered from debug to trace level
  - Render timing, event loop, pipeline execution now require TRACE log level
  - Reduces noise in DEBUG logs while still available for performance analysis
  - Affects 10+ log statements across runtime, screen, and render modules

### Fixed

- **Yank animation for linewise motions** - `yj` and `yk` now correctly highlight entire lines
  - Previously only highlighted partial lines (current line for `yj`, upper line for `yk`)
  - Now properly animates all yanked lines from start to end
  - Affects all linewise motions: `j`, `k`, `gg`, `G`
- **Markdown decorations update immediately on insert/change** - Fixed stale cache bug in saturator
  - Saturator now calls `decorator.refresh()` before `decoration_range()` to update cached parse tree
  - Mirrors the pattern from syntax highlighting (`update_highlights()`)
  - Heading icons, bullets, checkboxes, and emphasis concealment now update in real-time
- **Decorations disabled on cursor line in insert mode** - Show raw markdown syntax while typing
  - When in insert mode, decorations are filtered out on the current line
  - Allows seeing raw markers (`# Heading`, `**bold**`, etc.) while editing
  - Decorations reappear when returning to normal mode

### Changed

- **Code cleanup in markdown plugin** - Removed dead code and streamlined query loading
  - Deleted `markdown/mod.rs` (685 lines of dead code, obsolete LanguageRenderer implementation)
  - Converted embedded query constants to `.scm` files via `include_str!()` (57 lines → 2 lines)
  - Queries now editable in `.scm` files with syntax highlighting support
  - Total reduction: ~740 lines

- **Range-Finder plugin** - Merged Leap and Fold plugins into unified navigation system
  - Combined jump navigation and code folding into single `reovim-plugin-range-finder` plugin
  - New architecture: `src/jump/` (navigation subsystem) + `src/fold/` (visibility subsystem)
  - Multi-char search: `s` + 2 chars + label to jump (leap-style navigation)
  - Enhanced f/t motions: `f`/`F`/`t`/`T` now use label selection for multiple matches
  - Smart auto-jump: 1 match → instant, 2-676 matches → show labels, >676 → cancel
  - Code folding: `za`/`zo`/`zc`/`zR`/`zM` (unchanged functionality)
  - Home row priority labels: `sfnjklhodweimbuyvrgtaqpcxz`
  - Single-char labels for <=26 matches, two-char labels for >26 matches (up to 676)
  - Two-char label input: first character validates, second completes the jump
  - Label overlay rendering with z-order 200 (above editor, below popups)
  - **BREAKING**: `f`/`F`/`t`/`T` keys now trigger leap-style label selection (replaces default vim single-char find/till)
  - Removed separate `reovim-plugin-leap` and `reovim-plugin-fold` plugins
  - Total plugin size: ~2,000 lines (vs 2,295 lines for separate plugins)

## [0.7.9]

### Added

- **Microscope syntax highlighting** - Preview panels now show syntax-highlighted code
  - File picker (`Space f f`) previews display full syntax highlighting
  - Grep picker (`Space f g`) shows highlighted matches with context
  - Recent files picker (`Space f r`) includes syntax highlighting
  - Language injection support (markdown code blocks, etc.)
  - On-demand highlighting via `SyntaxFactory` integration (no background tasks)
  - Graceful degradation when treesitter unavailable (plain text fallback)
  - New `syntax_helper` module in pickers crate for highlight computation
  - Updated `Picker::preview()` trait to accept `PickerContext` with factories

- **Landing page animation (WIP)** - Animated ASCII lion on startup dashboard
  - Three size variants: Large (roar), Medium (sleep), Small (breathing)
  - Responsive size selection based on terminal dimensions
  - Animation controller with Loop, PingPong, Once modes
  - This is the initial implementation; more dashboard enhancements planned

- **Reo color system** - 45-color HSL-organized palette (Tokyo Night + Catppuccin + One Dark)
- **Extended Rust highlighting** - Pattern types, operator expressions, async/unsafe, type syntax captures
- **Documentation** - `docs/color-system.md`, `docs/syntax-highlighting.md`

### Fixed

- **Characterwise paste positioning** - Fixed `p` command to paste AFTER cursor for characterwise yanks
  - `Y` (yank to end of line) followed by `p` now correctly pastes after cursor position
  - Previously pasted at cursor position instead of after it (breaking Vim compatibility)
  - Added cursor movement logic (`buf.cur.x += 1`) before characterwise paste when `before=false`
  - All yank operations now properly track yank type (linewise vs characterwise)

- **Linewise paste behavior** - Fixed `dd`/`yy` paste to use proper linewise semantics
  - `p` now pastes BELOW current line (Vim behavior)
  - `P` now pastes ABOVE current line (Vim behavior)
  - Previously pasted at cursor position, corrupting text for linewise operations
  - Added `insert_linewise()` method to buffer for proper linewise paste handling

- **Yank type tracking** - Extended yank/delete operators to track linewise vs characterwise
  - Added `YankType` enum and `RegisterContent` struct to register system
  - Updated `Delete` operator to detect linewise motions (`dj`, `dk`, `dd`)
  - Updated `Change` operator to detect linewise motions (`cj`, `ck`, `cc`)
  - Extended `CommandResult::ClipboardWrite` with `yank_type` field
  - All 26 operator tests pass with correct yank/paste behavior

- **Yank animations** - Added visual feedback for `Y` and `yy` commands

- **Terminal cleanup on exit** - Fixed afterimage and "%" marker issues when closing reovim
  - Implemented RAII `TerminalGuard` to guarantee cleanup even on panic
  - Now uses alternate screen mode to isolate editor UI from shell
  - Cursor is properly restored and final newline printed on exit
  - Terminal state is always restored, preventing broken terminal after crashes
  - Added `lib/core/src/command/terminal/terminal_guard.rs` with Drop trait implementation
  - `Y` (yank to end) now highlights from cursor to end of line
  - `yy` (yank line) now highlights entire current line
  - Extended `CommandResult::ClipboardWrite` with `yank_range` field for animation support
  - Animation start position adjusted (`x+1`) to avoid highlighting extra character on left
  - Visual feedback matches Vim's yank highlight feature

- **Jump list navigation (Ctrl+O/Ctrl+I)** - Fixed non-functional jump navigation (#4)
  - Added Tab as fallback keybinding for jump-newer (works in all terminals)
  - Enabled Kitty keyboard enhancement protocol for modern terminals (kitty, WezTerm, foot)
  - Added Ctrl+O/Ctrl+I/Tab bindings to insert mode (jump navigation works during editing)
  - Jump points recorded when **leaving** insert mode (records where editing finished, not started)
  - Fixed `current_index` calculation bug where first Ctrl+O did nothing
  - Fixed duplicate detection causing `current_index` to become invalid
  - Fixed duplicate detection truncating jump history (entries were lost on subsequent pushes)
  - Fixed INSERT LEAVE truncating all previous jump entries (now preserves full history)
  - Fixed Ctrl+O requiring double press (now automatically skips current position)
  - Marked LSP goto definition/references commands as jumps (gd, gr)
  - Marked leap and buffer navigation commands as jump-recording actions (s/S, H/L)
  - Root cause: Ctrl+I was indistinguishable from Tab in traditional terminals
  - UX improvement: Jump back to where you **finished** editing, not where you started

- **Landing page animation alignment** - All frame lines now have consistent widths to prevent horizontal shifting during animation

- **Landing page size thresholds** - Adjusted thresholds so "Large" requires actually large terminals (50×24+), "Medium" for normal windows (35×16+)

- **Notification tests failing locally** - LSP plugin now skips auto-start when `REOVIM_TEST` env var is set, preventing progress notifications from polluting test state

- **Tree-sitter Rust query errors** - Fixed invalid node types (`rest_pattern`, `type_bound_list`, etc.)

## [0.7.8] - 2025-12-27

### Fixed

- **Settings menu border rendering** - Now uses the plugin window system's border utilities
  - Replaced manual box-drawing character rendering with `render_border_to_buffer()`
  - Uses `BorderConfig::new(BorderStyle::Rounded).with_title("Settings")`
  - Consistent with other plugin windows (explorer, telescope)

- **Settings menu changes not applying** - Settings now apply immediately to the editor
  - Added decoupled event flow: `OptionChanged` → `Request*` events → runtime capabilities
  - CorePlugin maps option names ("number", "theme", etc.) to capability requests
  - Runtime subscribes to `RequestSetLineNumbers`, `RequestSetTheme`, etc.
  - Avoids tight coupling between runtime and option names

- **LSP hover popup not dismissing on cursor movement** - Core runtime now emits `CursorMoved` events when commands change cursor position, enabling hover dismissal and cursor-aware plugin features

- **LSP commands (gd/gr/K) not working** - Fixed saturator deadlock by spawning tokio tasks instead of blocking await in select! loop

### Added

- **Settings capability request events** - New core events for runtime capabilities
  - `RequestSetLineNumbers` / `RequestSetRelativeLineNumbers`
  - `RequestSetTheme` / `RequestSetScrollbar` / `RequestSetIndentGuide`
  - Corresponding `InnerEvent` variants for runtime handling
  - Enables plugins to change settings without knowing runtime internals

- **LSP progress notifications** - Display rust-analyzer indexing progress in notification popup and statusline

- **LSP hover with markdown rendering** - Hover popups render formatted markdown (bold, italic, code blocks)

- **LSP multiple definition picker** - When `gd` returns multiple locations, show picker for user selection

- **Statusline Plugin** (`reovim-plugin-statusline`) - Section-based API for statusline extensions
  - `StatuslineSection` type with id, priority, alignment, and render callback
  - `SharedStatuslineManager` with thread-safe section registration
  - Implements core's generic `StatuslineSectionProvider` trait
  - Events: `StatuslineSectionRegister`, `StatuslineSectionUnregister`, `StatuslineRefresh`
  - Other plugins can register dynamic sections (e.g., LSP status, diagnostics count)

- **Notification Plugin** (`reovim-plugin-notification`) - Toast notifications and progress bars
  - `NotificationLevel` variants: Info, Success, Warning, Error with colored icons
  - `ProgressNotification` with percentage bar or indeterminate spinner
  - `SharedNotificationManager` for state management
  - Plugin-local `NotificationStyles` (not in core Theme)
  - Events: `NotificationShow`, `NotificationDismiss`, `ProgressUpdate`, `ProgressComplete`
  - `NotificationPluginWindow` with z-order 500 (above most UI)
  - Configurable position: TopRight, TopLeft, BottomRight, BottomLeft, TopCenter, BottomCenter

- **`StatuslineSectionProvider` trait** - Generic core API for statusline extensions
  - Added to `lib/core/src/plugin/statusline.rs`
  - `StatuslineRenderContext` with plugin state and screen dimensions
  - `RenderedSection` output type with text, style, alignment, priority
  - Provider hook in `render_status_line_to_buffer()` for generic section rendering
  - Follows same pattern as `SyntaxFactory` - core is plugin-agnostic

## [0.7.7] - 2025-12-27

### Changed

- **Which-key decoupled from core** - Complete removal of plugin-specific code from reovim-core
  - Deleted `lib/core/src/which_key.rs` - event now defined in plugin
  - Removed hard-coded `?` key dispatch from command handler
  - Removed `ComposableId::WhichKey` enum variant (use `Custom("which_key")`)
  - Removed `disable_which_key` behavior modifier
  - Removed `STATE_WHICHKEY` RPC constant
  - Plugin now registers all keybindings via `build()` method

- **Renamed `hint`/`group` to `description`/`category`** - General-purpose keybinding metadata
  - `KeyBinding.hint` → `KeyBinding.description`
  - `KeyBinding.group` → `KeyBinding.category`
  - `KeyMapInner::with_hint()` → `KeyMapInner::with_description()`
  - `KeyMapInner::group()` → `KeyMapInner::with_category()`

### Added

- **Plugin Decoupling Policy** - Documented architectural principle
  - Added policy to CLAUDE.md: "Never add plugin-specific code to core"
  - Added "Plugin Decoupling Principles" section to docs/plugin-system.md
  - Added decoupling note to docs/DEVELOPMENT.md
  - If API is insufficient, propose extension rather than adding coupling

- **`WhichKeyTrigger` inline command** - Plugin-owned keybinding trigger
  - Carries prefix for context-specific bindings (e.g., `g?`, `<Space>?`)
  - Uses `CommandRef::Inline(Arc<dyn CommandTrait>)` pattern
  - Emits `WhichKeyOpen` event via `CommandResult::EmitEvent`

## [0.7.6] - 2025-12-27

### Added

- **Completion fuzzy filtering** - Nucleo-based fuzzy matching with score threshold
  - Filters items based on typed prefix using `nucleo` crate
  - Minimum score threshold (`prefix.len() * 10`) prevents irrelevant matches
  - Sets `CompletionItem::score` and `match_indices` for highlighting

- **Completion match highlighting** - Per-character styling for matched characters
  - Added `match_indices: Vec<u32>` field to `CompletionItem`
  - Added `match_fg` style to `PopupStyles` (yellow/bold)
  - Matched characters rendered with highlight color

- **Completion UI columns** - Kind and source indicators in popup
  - Kind column (left): Colored abbreviation (`fn`, `mod`, `st`, `var`, etc.)
  - Source column (right): Dimmed source name (`buffer_words`, `lsp`, etc.)
  - Format: `[kind] [label] [source]`

- **RequestInsertText prefix deletion** - Replace typed prefix on completion confirm
  - Added `delete_prefix_len: usize` field to `RequestInsertText` event
  - Runtime deletes prefix before inserting completion text
  - Fixes `pkg` → `CARGO_PKG` instead of `pkgCARGO_PKG`

- **Completion auto-popup** - Automatic completion after 300ms debounce
  - Triggers on text insertion in insert mode
  - Uses generation counter for proper debounce cancellation
  - Sends `CommandEvent` to trigger completion with buffer context

- **EditorContext active window fields** - Window context for popup positioning
  - `active_window_anchor_x/y`, `active_window_gutter_width`, `active_window_scroll_y`
  - `cursor_screen_x()` and `cursor_screen_y()` helper methods
  - Enables accurate screen coordinate calculation for plugin windows

### Fixed

- **Completion popup position** - Now correctly positioned relative to cursor
  - Uses EditorContext to transform buffer coordinates to screen coordinates
  - Accounts for window anchor, line number gutter, and scroll offset

- **Completion ghost text position** - Inline preview now at correct cursor location
  - Uses `cursor_screen_x/y()` helpers for accurate positioning

- **Completion prefix extraction** - Proper word boundary detection
  - Added `is_word_boundary()` function with programming delimiters
  - Correctly extracts prefix for cases like `foo.bar.hel` -> `hel`

- **Completion live update** - Popup updates as user types
  - Re-triggers completion immediately when active (no debounce delay)
  - Dismisses on whitespace, mode change, or empty prefix

- **Completion dismiss behavior** - Proper cleanup on various events
  - Dismisses when leaving insert mode (via `ModeChanged`)
  - Dismisses when typing whitespace (space/enter)
  - Validates cursor position when completion re-triggers

- **Microscope backspace** - Backspace now works in microscope interactor mode
  - Added `PluginBackspace` subscription to microscope plugin
  - Previously, backspace events were silently dropped in microscope query input

### Changed

- **reo-cli keys response** - Enhanced feedback with parsed keys list
  - Response now includes `"keys": ["i", "H", "e", "l", "l", "o", "<Esc>"]`
  - Helps debugging key parsing issues

## [0.7.5] - 2025-12-27

### Added

- **LSP hover popup** - Floating documentation window on `K` keypress
  - Lock-free `HoverCache` using `ArcSwap` for non-blocking render
  - `HoverPluginWindow` with bordered popup (z-order 300)
  - Auto-dismiss on cursor move or mode change

- **LSP references picker** - Show references in microscope picker on `gr`
  - `LspReferencesPicker` implementing `Picker` trait
  - File preview with context around reference location
  - Navigation via `MicroscopeAction::GotoLocation`

## [0.7.4] - 2025-12-27

### Added

- **Which-key plugin** - Shows available keybindings in a popup panel
  - Press `?` after any prefix key (e.g., `g?`, `<Space>?`, `<C-w>?`) to see available bindings
  - Displays key sequences with descriptions from command registry
  - Type additional characters to filter the binding list
  - Backspace to remove filter, Escape to close
  - Background saturator for non-blocking UI updates
  - Integrated with `PluginStateRegistry` for keymap/command access

### Fixed

- **Plugin loader extraction bug** - All plugins now boot correctly
  - Fixed algorithm that caused only 1 plugin to have `boot()` called
  - Plugins with background saturators (completion, which-key) now work properly

- **Flaky test timing** - Fixed intermittent test failure
  - `test_vsplit_cursor_movement_after_navigate` now waits for cursor movement

## [0.7.2] - 2025-12-26

### Added

- **Extensible option system** - Plugin-extensible settings with full validation
  - Plugins can register their own options via `PluginContext::option()` builder API
  - Type-safe `OptionValue` variants: `Bool`, `Integer`, `String`, `Choice`
  - Constraint validation: min/max ranges, string length limits
  - Dynamic `:set` commands: `:set plugin.treesitter.timeout=200`
  - Query options: `:set optionname?`, reset to default: `:set optionname&`
  - TOML persistence in profiles under `[plugin.{plugin_name}]` sections
  - `RegisterOption` and `OptionChanged` events for plugin communication
  - Thread-safe `OptionRegistry` with alias support (short names)

- **`--log` CLI option** - Configurable log output destination
  - Custom file path: `--log=/path/to/file.log`
  - Stderr output: `--log=-` or `--log=stderr` (with ANSI colors)
  - Disable logging: `--log=none` or `--log=off`
  - Default behavior unchanged when not specified

- **Animation system** - Visual effects framework for UI feedback
  - Status line flash on mode change (smooth color transition)
  - Idle shimmer effect on status line after 3 seconds of inactivity
  - Yank blink effect - brief flash on yanked text (both operator motions and visual mode)
  - `AnimatedColor` types: pulse, shimmer, transition with easing functions
  - `SweepConfig` for position-based glow effects (glowing reflection)
  - Background animation controller at 30 FPS (only ticks when effects active)
  - `AnimationRenderStage` for applying effects in render pipeline

- **Microscope RPC support** - JSON-RPC endpoint for fuzzy finder state
  - `state/microscope` RPC method returns picker state (active, query, items, selection)
  - Integration test infrastructure for microscope plugin
  - Test port range changed to 17000-17099 for parallel test execution

### Fixed

- **Microscope preview** - Preview panel now displays file content
  - Preview loads on picker open and updates on navigation (j/k)
  - Files picker shows file content preview for selected item

- **Microscope event handlers** - Add missing command handlers
  - Confirm (Enter), ClearQuery, DeleteWord, cursor movement, page navigation
  - MicroscopeConfirm opens selected file and closes picker

- **Microscope UI cleanup** - Cleaner status display
  - Remove [N]/[I] mode indicator from title bar
  - Status line shows "Editor | Normal" instead of "microscope"

- **Preview highlighting infrastructure** - Prepare for syntax highlighting
  - Add StyledSpan type and styled_lines field to PreviewContent
  - render_preview_panel supports highlight_line and per-character styles

## [0.7.0] - 2025-12-25

### Added

- **Window mode (Ctrl-W)** - Hierarchical status line display for window navigation
  - `<C-w>h/j/k/l` for directional window navigation
  - `<C-w>v` for vertical split, `<C-w>s` for horizontal split
  - `<C-w>c` to close window, `<C-w>o` for only window
  - Status line shows current mode context

- **Pair plugin** - Comprehensive bracket matching and highlighting
  - Rainbow bracket coloring based on nesting depth (6-color cycle)
  - Matched pair highlighting when cursor is inside brackets
  - **Bold + underline** when cursor is directly ON a bracket
  - Unmatched bracket warning with red underline
  - Auto-pair insertion: typing `(`, `[`, or `{` automatically inserts closing bracket
  - Cursor positioned between brackets after auto-insertion

- **Language injection highlighting** - Embedded code blocks now have proper syntax highlighting
  - Markdown fenced code blocks (` ```rust `, ` ```python `, etc.) display with language-specific colors
  - Rust doc comments (`///`, `//!`, `/** */`) inject markdown for rich rendering
  - Added `saturate_injections()` to `SyntaxProvider` trait for eager injection computation
  - Injection highlights merge with decoration backgrounds (code blocks have both syntax colors AND grey tint)

- **Per-buffer saturator** - Non-blocking syntax highlighting architecture
  - Each buffer has its own saturator for independent highlighting
  - Prevents blocking on large files

- **Icon system** - Improved file and UI icons

### Architecture

- **Buffer-centric syntax highlighting** - Syntax highlighting is now buffer-centric
  - Highlights computed per-buffer, not per-window
  - Better separation of concerns

- **Plugin system decoupling** - Complete separation of plugins from core
  - Plugins communicate via events only
  - No direct core dependencies in plugin code

- **Render system refactor** - Improved rendering pipeline
  - Cleaner separation of rendering stages
  - Better performance characteristics

- **Remove UIComponent and Overlay systems** - Simplified component architecture
  - Replaced with more focused abstractions

### Fixed

- **Visual selection yank/delete** - Fixed yank and delete operations in visual mode

- **Scroll issues** - Fixed various scrolling edge cases

- **Explorer file operations** - Fixed character input not working in explorer file operations
  - Character input (create file, rename, etc.) now correctly captures typed characters
  - Backspace works correctly in input mode

- **Render issues** - Fixed various rendering edge cases

### Improved

- **reo-cli capture** - Simplified screen capture command
  - `capture` command prints raw screen content directly
  - Removed JSON wrapper for better usability and piping

## [0.6.22] - 2025-12-20

### Markdown Rendering (Phase 4)

- **Dual-grammar support for inline elements** - Added `MarkdownInline` language for tree-sitter-md's `INLINE_LANGUAGE`
  - Registered `LanguageId::MarkdownInline` in grammar system
  - Created inline parser for emphasis, strong emphasis, and links
  - Added `queries/markdown_inline/highlights.scm` and `decorations.scm`

- **Inline formatting concealment** - Hide markdown markers in normal mode
  - `*italic*` → `italic` (single asterisks hidden)
  - `**bold**` → `bold` (double asterisks hidden)
  - `[text](url)` → `text` (brackets and URL hidden)

- **Table rendering** - Header and delimiter row styling
  - Header row background highlighting
  - Delimiter row dimmed styling via `pipe_table*` node captures

- **Style system enhancements** - Added new text attributes
  - Added `BLINK` and `DIM` attribute constants
  - Added `blink()` and `dim()` builder methods to `Style`

- **Conceal style merging** - Fixed replacement character styling
  - Conceal replacement chars now use conceal's style merged with syntax highlights
  - Heading icons display with proper bold + color styling

- **Insert mode raw display** - Show raw markdown when editing
  - Decorations disabled in insert mode for accurate cursor positioning
  - Raw `#`, `*`, `**`, `[]()` markers visible during editing
  - Returns to concealed view on mode exit

## [0.6.21] - 2025-12-20

### Architecture

- **Explicit Keystroke and KeySequence types** - Replace implicit string-based key definitions
  - New `keystroke` module with `Key`, `Modifiers`, `Keystroke`, `KeySequence` types
  - Type-safe key definitions instead of strings like `"gg"`, `" ff"`, `"<C-d>"`
  - `key!` macro for single keystrokes: `key!('a')`, `key!(Ctrl 'd')`, `key!(Space)`
  - `keys!` macro for sequences: `keys!['g' 'g']`, `keys![Space 'f' 'f']`, `keys![(Ctrl 'd')]`

- **Multiple render formats for key display**
  - Vim notation: `<C-d>`, `<Space>ff`, `<Esc>`
  - Human-readable: `Ctrl+D`, `Space → F → F`, `Escape`
  - StatusLine: `C-d`, `SPC f f`, `ESC`

- **KeySequence integration throughout codebase**
  - `CommandHandler.pending_keys` now uses `KeySequence` instead of `String`
  - `KeyMap` uses `KeySequence` as HashMap key type
  - `KeyBinding.keys` field changed from `&'static str` to `KeySequence`
  - Status line displays pending keys using StatusLine render format

### Files Changed

- `lib/core/src/keystroke/mod.rs` - Core types (Key, Modifiers, Keystroke, KeySequence)
- `lib/core/src/keystroke/notation.rs` - Render methods for multiple formats
- `lib/core/src/keystroke/macros.rs` - key! and keys! macros
- `lib/core/src/bind/mod.rs` - Updated KeyBinding and KeyMap to use KeySequence
- `lib/core/src/event/handler/command/mod.rs` - pending_keys as KeySequence
- `lib/core/src/plugin/context.rs` - bind_key_scoped takes KeySequence
- `lib/core/src/telescope/picker/keymaps.rs` - Renders KeySequence for display

## [0.6.20] - 2025-12-20

### Refactoring

- **Clap-based CLI argument parsing** - Replaced manual argument parsing with clap v4
  - Added `clap` to workspace dependencies with derive feature
  - Defined `Cli` struct with clap derive macros in `main/src/main.rs`
  - Removed manual `print_help()` and `print_version()` functions (clap auto-generates)
  - Reduced argument parsing code from ~80 lines to ~30 lines
  - Consistent with `reo-cli` which already uses clap

## [0.6.17] - 2025-12-20

### Architecture

- **RenderState for Bundled Render Parameters**
  - Created `RenderState<'a>` struct to bundle all runtime state needed for rendering
  - Reduces 16-parameter render function signatures to single state struct
  - Fields: buffers, highlight_store, mode, command_line, pending_keys, last_command,
    color_mode, theme, explorer, which_key, completion, telescope, leap, fold_manager,
    indent_analyzer, settings_menu

- **Enhanced RenderContext**
  - Added optional `state: Option<&'a RenderState<'a>>` field to `RenderContext`
  - Added `RenderContext::with_state()` constructor for creating context with state
  - Added `RenderContext::state()` getter method
  - Backward compatible - existing code using `RenderContext::new()` still works

- **New Screen::render_with_state() Method**
  - Added `Screen::render_with_state(&mut self, state: &RenderState)` method
  - Preferred rendering entry point with cleaner API
  - Runtime::render() now creates RenderState and calls this method
  - Legacy `Screen::render()` with 16 parameters kept for compatibility

- **WhichKeyPanel Debug Derive**
  - Added `Debug` derive to `WhichKeyPanel` for RenderState compatibility

### Files Changed

- `lib/core/src/component/display.rs` - Added RenderState struct, updated RenderContext
- `lib/core/src/component/mod.rs` - Export RenderState
- `lib/core/src/screen/mod.rs` - Added render_with_state() method
- `lib/core/src/screen/which_key.rs` - Added Debug derive to WhichKeyPanel
- `lib/core/src/runtime/core.rs` - Use RenderState in render()

### Testing

- All unit tests passing (324 tests)
- All integration tests passing
- Zero warnings (build + clippy)

## [0.6.16] - 2025-12-20

### Architecture

- **Removed Layer Trait**
  - Deleted `Layer` trait from `screen/layer.rs` - unused dead code
  - Deleted `screen/layers/` directory with all Layer implementations
  - Layer wrappers (CompletionLayer, LeapLayer, etc.) were never instantiated
  - Buffered rendering path already had all logic directly in Screen

- **Consolidated z_order and LayerBounds**
  - Moved `z_order` module constants to `screen/mod.rs`
  - Moved `LayerBounds` struct to `screen/mod.rs`
  - These are now directly available via `screen::z_order::*` and `screen::LayerBounds`

### Files Changed

- `lib/core/src/screen/mod.rs` - Added z_order module and LayerBounds struct
- `lib/core/src/screen/layer.rs` - **DELETED** (Layer trait, z_order, LayerBounds moved)
- `lib/core/src/screen/layers/` - **DELETED** (8 unused Layer implementations)

### Deleted Files

- `lib/core/src/screen/layer.rs`
- `lib/core/src/screen/layers/mod.rs`
- `lib/core/src/screen/layers/base.rs`
- `lib/core/src/screen/layers/completion.rs`
- `lib/core/src/screen/layers/editor.rs`
- `lib/core/src/screen/layers/explorer.rs`
- `lib/core/src/screen/layers/leap.rs`
- `lib/core/src/screen/layers/settings_menu.rs`
- `lib/core/src/screen/layers/telescope.rs`
- `lib/core/src/screen/layers/which_key.rs`

### Testing

- All unit tests passing (324 tests)
- All integration tests passing
- Zero warnings (build + clippy)

## [0.6.15] - 2025-12-20

### Architecture

- **Plugin-Based Component Registration**
  - Created `UIComponentsPlugin` to register built-in UI components via plugin system
  - Editor, Explorer, Telescope, Settings, `CommandLine` now registered through plugins
  - Focus input handlers registered via `PluginContext.register_focus_handler()`
  - `Runtime::new()` now delegates to `Runtime::with_plugins(screen, DefaultPlugins)`

- **Removed Hardcoded Defaults**
  - Removed `InteractorRegistry::with_defaults()` - components come from plugins
  - Removed hardcoded telescope pickers - registered by `TelescopePlugin`
  - Removed `enlist_default_handlers()` - handlers registered by `UIComponentsPlugin`

- **New ComponentId Constants**
  - Added `ComponentId::COMPLETION` for completion popup overlay
  - Added `ComponentId::LEAP` for leap motion overlay
  - Added `ComponentId::WHICH_KEY` for which-key hint panel

### Files Changed

- `lib/core/src/plugin/builtin/ui_components.rs` - **NEW** `UIComponentsPlugin`
- `lib/core/src/plugin/builtin/mod.rs` - Added UIComponentsPlugin to DefaultPlugins
- `lib/core/src/runtime/core.rs` - `new()` delegates to `with_plugins()`
- `lib/core/src/runtime/enlist.rs` - Made handler functions public for plugin use
- `lib/core/src/runtime/mod.rs` - Export handler functions
- `lib/core/src/interactor/mod.rs` - Removed `with_defaults()` method
- `lib/core/src/ui_component/component.rs` - Added COMPLETION, LEAP, WHICH_KEY constants

### Testing

- All unit tests passing
- All integration tests passing
- Zero warnings (build + clippy)

## [0.6.14] - 2025-12-20

### Breaking Changes

- **Removed `DisplayComponent` trait** - Use `UIComponent` exclusively for all components
- **Removed `Interactor` trait** - Input handling now integrated into `UIComponent`
- **`InteractorId` is now an alias** - Use `ComponentId` directly (InteractorId re-exported for backward compatibility)

### Architecture

- **Unified UIComponent-Only Architecture**
  - All UI components now implement the single `UIComponent` trait
  - `StatusLineComponent` and `TabLineComponent` render logic inlined into `UIComponent` impl
  - `InteractorRegistry` now stores `Box<dyn UIComponent>` instead of `Box<dyn Interactor>`
  - Input handling methods (`handle_insert_char`, `handle_delete_backward`) integrated into `UIComponent`

- **Plugin Component Registration**
  - Added `ComponentRegistry` to `PluginContext` for plugin-registered components
  - `register_component()` method for plugins to register custom UI components
  - `component_registry()` / `component_registry_mut()` accessors
  - Runtime receives and stores `ComponentRegistry` from plugin context

- **ComponentId Unification**
  - `InteractorId` replaced with `ComponentId` across entire codebase
  - `ModeState.interactor_id` now uses `ComponentId`
  - Focus handlers use `ComponentId` as HashMap key
  - All interactor comparisons use `ComponentId` constants

### Files Changed

- `lib/core/src/component/display.rs` - Removed `DisplayComponent` trait, kept `RenderContext`
- `lib/core/src/component/mod.rs` - Removed `DisplayComponent` export
- `lib/core/src/component/status_line.rs` - Inlined DisplayComponent logic into UIComponent
- `lib/core/src/component/tab_line.rs` - Inlined DisplayComponent logic into UIComponent
- `lib/core/src/interactor/mod.rs` - Removed Interactor trait, updated registry to use UIComponent
- `lib/core/src/plugin/context.rs` - Added ComponentRegistry support
- `lib/core/src/runtime/core.rs` - Added component_registry field
- `lib/core/src/modd/mod.rs` - Re-export ComponentId instead of InteractorId
- `lib/core/src/screen/layers/base.rs` - Use UIComponent trait for rendering
- `lib/core/src/event/handler/command/dispatcher.rs` - Removed deprecated allow block
- `lib/core/src/runtime/handlers.rs` - Removed deprecated allow block

### Migration Guide

```rust
// Before (DisplayComponent):
impl DisplayComponent for MyComponent {
    fn render_to_frame(&self, buffer: &mut FrameBuffer, ctx: &RenderContext<'_>) { ... }
}

// After (UIComponent only):
impl UIComponent for MyComponent {
    fn render_to_frame(&self, buffer: &mut FrameBuffer, ctx: &RenderContext<'_>) { ... }
    fn is_focusable(&self) -> bool { false }
}

// Before (InteractorId):
use crate::interactor::InteractorId;
if mode.interactor_id == InteractorId::EDITOR { ... }

// After (ComponentId):
use crate::ui_component::ComponentId;
if mode.interactor_id == ComponentId::EDITOR { ... }
```

### Testing

- All unit tests passing
- All integration tests passing
- Zero warnings (build + clippy)

## [0.6.13] - 2025-12-20

### Architecture

- **Unified UIComponent Trait** (`lib/core/src/ui_component/`)
  - `UIComponent` trait combining `Interactor`, `DisplayComponent`, and `Layer` functionality
  - `ComponentId` for unique component identification (STATUS_LINE, TAB_LINE, EDITOR, EXPLORER, TELESCOPE, SETTINGS, COMMAND_LINE)
  - `ComponentRegistry` for managing registered components and tracking active focus
  - Unified interface for identity, rendering, and input handling

- **UIComponent Implementations**
  - `StatusLineComponent` - Display-only, not focusable
  - `TabLineComponent` - Display-only, not focusable
  - `Editor` - Focusable, handles insert/delete input
  - `Explorer` - Focusable, handles input when `input_active`
  - `Telescope` - Focusable, captures all input when active
  - `Settings` - Focusable, captures all input when active
  - `CommandLineInt` - Focusable, captures all input when active

### Files Added

- `lib/core/src/ui_component/mod.rs` - Module root with documentation
- `lib/core/src/ui_component/component.rs` - `UIComponent` trait and `ComponentId`
- `lib/core/src/ui_component/registry.rs` - `ComponentRegistry` for component management

### Files Changed

- `lib/core/src/lib.rs` - Added `pub mod ui_component`
- `lib/core/src/component/status_line.rs` - Added `UIComponent` impl
- `lib/core/src/component/tab_line.rs` - Added `UIComponent` impl
- `lib/core/src/interactor/mod.rs` - Added `UIComponent` impl for all interactors

### Testing

- 324 unit tests passing
- 100 integration tests passing
- Zero warnings (build + clippy)

### Notes

- Rendering for interactors is currently delegated to existing Layer implementations
- Full rendering unification will be completed in Stream C (v0.6.14) with plugin registration

## [0.6.12] - 2025-12-20

### Breaking Changes

- **Removed `Focus` enum** - Use `InteractorId` exclusively for focus tracking
  - `ModeState.focus` field removed
  - `ModeState::with_focus_and_mode()` removed
  - `ModeState::with_sub_mode()` (Focus-based) removed
  - `ModeState::with_focus()` removed

### Architecture

- **InteractorId-based Focus System** - Complete migration from closed enum to extensible IDs
  - `ModeState` now contains only `interactor_id`, `edit_mode`, `sub_mode`
  - Pattern matching replaced with `InteractorId` equality checks
  - Enables plugins to define custom focus targets without core changes

### Changed

- **modd/mod.rs** - Simplified `ModeState` struct
  - Removed `focus: Focus` field
  - `display_string()` now matches on `interactor_id`
  - All convenience constructors updated

- **Status Line Rendering** - Updated for `InteractorId`
  - `mode_icon()` uses `InteractorId` comparison
  - New `get_mode_style()` helper method
  - Both `component/status_line.rs` and `screen/status_line.rs` updated

- **Keymap Selection** - `bind/mod.rs`
  - `get_keymap_for_mode()` matches on `interactor_id` instead of `focus`
  - Changed from `const fn` to `fn` (InteractorId comparison not const)

- **Runtime Handlers** - `runtime/handlers.rs`
  - `sync_mode_with_screen_focus()` uses `InteractorId::EXPLORER`
  - Telescope handlers use convenience constructors

- **Command Dispatcher** - `dispatcher.rs`
  - `telescope_enter_normal` uses `ModeState::telescope_normal()`

### Migration Guide

```rust
// Before:
match (&mode.focus, &mode.edit_mode) {
    (Focus::Editor, EditMode::Normal) => ...
}

// After:
if mode.interactor_id == InteractorId::EDITOR {
    match &mode.edit_mode {
        EditMode::Normal => ...
    }
}

// Before:
ModeState::with_focus_and_mode(Focus::Telescope, EditMode::Normal)

// After:
ModeState::telescope_normal()
```

### Testing

- 318 unit tests passing
- All integration tests passing
- Zero clippy warnings

## [0.6.11] - 2025-12-20

### Architecture

- **DisplayComponent Trait** (`lib/core/src/component/`)
  - `DisplayComponent` trait for display-only UI components (no input handling)
  - `RenderContext` struct passed to components during rendering
  - Clean separation: Interactor for input, DisplayComponent for display

- **StatusLineComponent** - Renders mode indicator, pending keys, filename, cursor position
  - Uses `DisplayComponent` trait
  - Mode-specific icons and styling

- **TabLineComponent** - Renders tab bar when multiple tabs are open
  - Uses `DisplayComponent` trait
  - Visibility conditional on tab count

- **CommandLine Interactor** - Input handling for `:` command mode
  - `InteractorId::COMMAND_LINE` for identifying command line focus
  - `CommandLineInt` struct implementing `Interactor` trait
  - `handle_command_line_input()` enlist handler

### Changed

- **BaseLayer uses DisplayComponents** - Rendering delegated to components
  - `TabLineComponent` replaces inline tab line rendering
  - `StatusLineComponent` replaces inline status line rendering
  - Removed unused `render_tab_line()` and `render_status_line()` methods

- **Screen layer module made public** - `pub mod layer` for component access

### Files Added

- `lib/core/src/component/mod.rs` - Component module exports
- `lib/core/src/component/display.rs` - DisplayComponent trait + RenderContext
- `lib/core/src/component/status_line.rs` - StatusLineComponent
- `lib/core/src/component/tab_line.rs` - TabLineComponent

### Testing

- 318 unit tests passing
- All integration tests passing

## [0.6.10] - 2025-12-20

### Architecture

- **Enlist-Based Handler Registration** (Bevy/Zed Pattern)
  - Fully removes hardcoding from runtime dispatch - only enlist (initialization) knows about specific interactors
  - Function pointer registry: `HashMap<InteractorId, FocusInputHandler>`
  - Handlers registered at initialization via `enlist_focus_input_handler()`
  - Runtime dispatch is fully generic via handler lookup

- **Interactor System** (`lib/core/src/interactor/`) - Renamed from Focus System
  - `InteractorId` for identifying input targets (Editor, Telescope, Explorer, etc.)
  - `Interactor` trait for input-receiving components
  - `InteractorRegistry` for managing interactors and active focus
  - `InputResult` enum: `NotHandled`, `Handled`, `SendEvent(InnerEvent)`

### Changed

- **Generic Event Dispatch** - Runtime no longer matches on interactor types
  - Before: `match InteractorId::TELESCOPE => ...`
  - After: `handlers.get(&interactor_id)` - fully generic lookup
  - Adding new interactors only requires calling `enlist_*` at initialization

- **FocusInput Event** - Generic focus input event for all interactors
  - `InnerEvent::FocusInput { char, delete, clear_landing }`
  - Dispatched to registered handler based on active `InteractorId`

### Files Added

- `lib/core/src/interactor/mod.rs` - Interactor trait and registry
- `lib/core/src/runtime/enlist.rs` - Handler implementations (enlist pattern)

### Files Removed

- `lib/core/src/focus/mod.rs` - Replaced by interactor module

### Testing

- 318 unit tests passing
- 132 integration tests passing

## [0.6.9] - 2025-12-20

### Architecture

- **Compositor System** (`lib/core/src/compositor/`)
  - `ZOrder` and `ZGroup` for layered rendering priority (Base, Editor, Popup, Overlay, Modal)
  - `Bounds` for component layout bounds with collision detection
  - `ComposableId` for unique component identification

- **Modifier System** (`lib/core/src/modifier/`)
  - `Modifier` trait for context-aware styling and behavior
  - `ModifierRegistry` with caching for efficient evaluation
  - `ModifierContext` for passing window/buffer/mode context
  - `StyleModifiers` for visual style overrides (borders, decorations, colors)
  - `BehaviorModifiers` for keybinding overrides and feature flags

- **Border System** (`lib/core/src/screen/border.rs`)
  - `BorderStyle` variants (None, Single, Double, Rounded, Heavy, Custom)
  - `BorderSides` for selective borders (top, bottom, left, right)
  - `BorderConfig` builder pattern with fluent API
  - `BorderMode::Collide` and `BorderMode::Float` for multi-window layouts

- **Filetype Detection** (`lib/core/src/filetype/`)
  - Extension-based and filename-based detection
  - `FiletypeInfo` with icon and color
  - Global `FiletypeRegistry` for language detection

### Changed

- **Text Input Routing** - Input events now routed via `TextInputEvent`
  - `TextInputEvent::InsertChar(char)` for character insertion
  - `TextInputEvent::DeleteCharBackward` for backspace handling
  - CommandHandler emits `TextInputEvent` for insert/command modes
  - Runtime routes events via two-tier system: fast path for built-ins, UIComponent trait for plugins

### Files Added

- `lib/core/src/compositor/mod.rs` - Compositor types and ZOrder
- `lib/core/src/compositor/types.rs` - Bounds, ComposableId
- `lib/core/src/modifier/mod.rs` - Modifier module root
- `lib/core/src/modifier/traits.rs` - Modifier trait definition
- `lib/core/src/modifier/registry.rs` - ModifierRegistry
- `lib/core/src/modifier/context.rs` - ModifierContext
- `lib/core/src/modifier/style.rs` - StyleModifiers
- `lib/core/src/modifier/behavior.rs` - BehaviorModifiers
- `lib/core/src/focus/mod.rs` - Focus system
- `lib/core/src/filetype/mod.rs` - Filetype detection
- `lib/core/src/screen/border.rs` - Border system

### Testing

- 320 unit tests passing
- 154 integration tests passing

## [0.6.8] - 2025-12-19

### Fixed

- **Transparent Background Support** - Editor now uses terminal's native background
  - Removed explicit background from `base.default` and `command_line` styles
  - Fixed visual artifacts by emitting ANSI code `49` (background reset) when `bg: None`
  - Added `flush()` after `clear()` in screen `initialize()` and `finalize()`

### Changed

- `Style::to_ansi_start()` now emits `49` reset code when background is `None`
- All themes (Dark, Light, TokyoNight) use terminal default background for text areas

## [0.6.7] - 2025-12-19

### Fixed

- **Independent Scroll Per Window** - Each window maintains its own scroll position
  - Fixed bug where scrolling in one window would sync across all windows sharing the same buffer
  - Root cause: All windows called `update_scroll()` with buffer's live cursor
  - Fix: Active window uses `buf.cur.y`, inactive windows use saved `win.cursor.y`

### Added

- **`state/windows` RPC Endpoint** - Query per-window scroll and cursor state
  - `WindowSnapshot` struct with `buffer_anchor`, `cursor`, `is_active` fields
  - Useful for testing and debugging window state

### Tests

- `test_shared_buffer_scroll_independence` - Verifies scroll isolation between splits
- `test_shared_buffer_scroll_preserved_after_navigation` - Verifies scroll preserved on window switch
- `test_three_windows_scroll_isolation` - Verifies 3-window scroll independence

## [0.6.6] - 2025-12-19

### Architecture

- **Double-Buffer Rendering Refactor** - Simplified and unified rendering architecture
  - `FrameRenderer` uses front/back buffer swap pattern for flicker-free updates
  - `front` buffer: Latest complete frame (external readers access this)
  - `back` buffer: Currently being rendered to
  - Cell-by-cell diff computed between buffers, only changed cells sent to terminal
  - After flush: `std::mem::swap(&mut front, &mut back)` for efficient buffer rotation

- **Unified Capture System** - Consolidated all RPC capture formats into `FrameBufferHandle`
  - Single capture handle provides: `RawAnsi`, `PlainText`, `CellGrid` formats
  - Added `to_ansi()` and `to_plain_text()` methods to `FrameBuffer`
  - Removed `CaptureHandle` and `DualOutput` (redundant with unified system)
  - Capture buffer updated after each flush for RPC clients

- **Rendering Pipeline Cleanup**
  - Removed unused render strategies (`cell_delta`, `dirty_region`, `virtual_buffer`)
  - Removed unused `screen/compositor.rs` - rendering now via `Screen::render_buffered()`
  - Streamlined frame module: just `buffer.rs`, `cell.rs`, `renderer.rs`
  - Direct layer rendering in z-order without intermediate compositor

### Documentation

- Updated `docs/architecture.md`:
  - Rendering flow diagram now reflects actual `Screen::render_buffered()` implementation
  - Removed stale `LayerCompositor` references
  - Documented double-buffer swap pattern
- Updated `CLAUDE.md` - Simplified RPC capture documentation

### Removed

- `lib/core/src/frame/dirty.rs` - Unused dirty tracking
- `lib/core/src/frame/strategy/` - Entire unused strategy module (4 files)
- `lib/core/src/screen/compositor.rs` - Unused z-layer compositor
- `lib/core/src/io/output.rs` - `CaptureHandle`, `DualOutput` types

### Performance

- Window render (10 lines): 10.14 µs
- Full screen render: 62.80 µs
- Char insert RTT: 108 µs
- Throughput: ~18.1k renders/sec
- Double-buffer swap: O(1) pointer swap, no data copy

## [0.6.5] - 2025-12-19

### Features

- **Smart Window Focus/Split** - `<leader>wh/j/k/l` focuses existing window OR creates split
  - Unified window operations under `<leader>w*` prefix
  - Smart behavior: navigate if adjacent window exists, split if not
  - Removed `<C-hjkl>` from normal mode (use `<leader>w*` instead)

- **Buffer Navigation** - LazyVim-style buffer switching
  - `H` / `L` - Previous/next buffer
  - `<leader>bd` - Delete current buffer
  - `<leader>b` prefix group in which-key

- **Change Line Command** - `cc` deletes line content and enters insert mode
  - Consistent with `dd` (delete line) and `yy` (yank line)

### Documentation

- **Window-Buffer Architecture** - New `docs/window-buffer.md`
  - Explains N:1 window-to-buffer relationship
  - Dual cursor state (buffer cursor vs window cursor)
  - Cursor handoff protocol on window switch

### Fixed

- **Smart Focus Cursor Bug** - `handle_focus_or_split` now uses proper cursor save/restore
  - Was calling `screen.navigate_window()` directly, bypassing cursor handoff
  - Now calls `handle_window_navigate()` for correct behavior

- **Cursor Rendering in Multi-Window** - Fixed cursor highlight appearing in wrong window
  - `render_buffered()` was calculating cursor position for ALL windows
  - Last window in loop always overwrote `cursor_pos`, ignoring active window
  - Fix: Added `win.is_active &&` check before cursor position calculation
  - Line numbers updated correctly but cursor highlight didn't follow

### New Keymaps

| Key | Action |
|-----|--------|
| `H` | Previous buffer |
| `L` | Next buffer |
| `cc` | Change line |
| `<leader>b` | +buffer (prefix) |
| `<leader>bd` | Delete buffer |
| `<leader>wh` | Smart focus left (or vsplit) |
| `<leader>wj` | Smart focus down (or hsplit) |
| `<leader>wk` | Smart focus up (or hsplit) |
| `<leader>wl` | Smart focus right (or vsplit) |
| `<leader>wv` | Vertical split |
| `<leader>ws` | Horizontal split |
| `<leader>wc` | Close window |
| `<leader>wo` | Close other windows |
| `<leader>w=` | Equalize windows |

### Removed Keymaps

- `<C-h/j/k/l>` - Window focus (now use `<leader>wh/j/k/l`)
- `<C-S-H/J/K/L>` - Window move (all window ops under `<leader>w`)

### Testing

- Add 13 window split integration tests (`window_splits.rs`)
  - 11 window split/focus tests
  - 2 shared buffer cursor preservation tests
- Update visual_snapshot tests to use `<leader>w*` instead of `<C-h/l>`
- Total: 311 tests passing

## [0.6.4] - 2025-12-19

### Features

- **Per-Window Cursor** - Each window maintains its own cursor position (Vim-like behavior)
  - `cursor` and `desired_col` fields added to Window struct
  - Cursor syncs between window and buffer on navigation
  - `effective_cursor_y()` method for rendering (active uses buffer cursor, inactive uses window cursor)

- **Inactive Line Number Styling** - Dimmed line numbers for inactive windows
  - `inactive_line_number` style in theme's gutter configuration
  - `fg_gutter` (#3b4261) and `fg_inactive` (#292e42) colors for TokyoNightOrange
  - `is_active` field on Window to track focus state

### Fixed

- **Split Window Cursor Movement** - j/k now works immediately after Ctrl-h/l window navigation
  - `active_buffer_id` now syncs when navigating between windows
  - Buffer cursor properly loads from window's saved cursor on switch

### Testing

- Add 6 split window visual tests
  - `test_vsplit_creates_two_windows` - Verify split shows content in both windows
  - `test_vsplit_navigate_right/left` - Test Ctrl-l/h navigation
  - `test_vsplit_cursor_movement_after_navigate` - Verify j/k works after switch
  - `test_vsplit_independent_cursors` - Windows maintain separate cursor positions
  - `test_vsplit_cursor_preserved_on_switch` - Cursor restored when returning to window

## [0.6.3] - 2025-12-19

### Features

- **Visual Testing Infrastructure** - Comprehensive TUI debugging for tests and AI assistants
  - ASCII art snapshots: Plain and annotated views with borders/line numbers
  - Structured visual snapshots: Cell grid, cursor info, layer visibility (JSON)
  - `with_size(width, height)` builder method for explicit screen dimensions
  - `VisualAssertions` trait: `assert_cell_char`, `assert_row_content`, `assert_contains`, etc.

### New Modules

- `lib/core/src/visual/` - Visual snapshot types and ASCII rendering
  - `VisualSnapshot`, `CursorInfo`, `LayerInfo`, `BoundsInfo`
  - `AsciiRenderConfig` for customized ASCII output
- `lib/core/src/testing/visual.rs` - Visual assertions trait

### RPC Methods

- `state/visual_snapshot` - Full visual snapshot with cells, cursor, layers
- `state/ascii_art` - ASCII art representation (plain or annotated)
- `state/layer_info` - Layer visibility and bounds information

### Testing

- Add 17 visual snapshot integration tests
- Add `visual_snapshot()`, `ascii_art()`, `layer_info()` to `ServerTestResult`
- Update `docs/TESTING.md` with visual testing examples

## [0.6.2] - 2025-12-19

### Fixed

- **Buffer Switching Not Updating Screen** - Fix 6 locations where screen state wasn't synchronized
  - Telescope buffer picker now properly switches displayed buffer
  - Telescope file picker and grep match now sync screen after open
  - `:e` command now updates screen after opening file
  - `BufferEvent::Switch` now syncs screen
  - `:split`/`:vsplit` and `:tabnew` use correct buffer ID after file open

### Testing

- Add buffer switching integration tests (10 tests)
- Add `screen()`, `buffer_list()`, `open_file()` to testing framework
- Add `assert_active_buffer_id()` and `active_buffer_id()` assertions

## [0.6.1] - 2025-12-19

### Fixed

- **Cursor Blinking During Movement** - Hide cursor during render operations
  - Wrap render with Hide/Show escape sequences to prevent visual artifacts
  - Fixes flickering cursor when navigating with hjkl

### Testing

- Add cursor visibility integration tests
- Add `screen_content_raw()` to testing framework
- Add `assert_cursor_visibility_managed()` assertion

### Chores

- Add `cargo +nightly fmt --all` step to `scripts/check.sh` for consistent formatting

## [0.6.0] - 2025-12-18

### Features

- **Diff-Based Rendering System** - Eliminates terminal flickering
  - FrameBuffer: 2D cell grid for double-buffering
  - Three render strategies: VirtualBuffer (full diff), DirtyRegion, CellDelta
  - Only changed cells sent to terminal - massive reduction in I/O

- **Overlay System** - Composable UI overlays
  - Overlay trait with z-order compositing
  - OverlayCompositor for managing overlay stack
  - OverlayGeometry for positioning and bounds

- **Layer-Based Compositor** - Structured rendering pipeline
  - Layer trait with z-order constants (BASE=0, EDITOR=2, COMPLETION=4, etc.)
  - Implementations: BaseLayer, EditorLayer, ExplorerLayer, CompletionLayer, WhichKeyLayer, TelescopeLayer, LeapLayer, SettingsMenuLayer

- **Theme Background Colors** - All UI styles now have fg AND bg for proper diff-based rendering

### Architecture

- `FrameBuffer` - 2D cell storage with dirty tracking
- `Cell` - Individual screen cell (char, fg, bg, modifiers)
- `FrameRenderer` - Coordinates render strategies
- `RenderStrategy` trait - Pluggable diff algorithms
- `LayerCompositor` - Coordinates layer rendering to FrameBuffer
- `OverlayCompositor` - Manages overlay z-order

### Files Added

- `lib/core/src/frame/` - Frame buffer module
  - `mod.rs`, `buffer.rs`, `cell.rs`, `dirty.rs`, `renderer.rs`
  - `strategy/` - VirtualBuffer, DirtyRegion, CellDelta strategies
- `lib/core/src/overlay/` - Overlay system
  - `mod.rs`, `compositor.rs`, `geometry.rs`, `render.rs`, `selectable.rs`
- `lib/core/src/screen/layer.rs` - Layer trait and z-order constants
- `lib/core/src/screen/compositor.rs` - LayerCompositor
- `lib/core/src/screen/layers/` - Layer implementations
  - `base.rs`, `editor.rs`, `explorer.rs`, `completion.rs`
  - `which_key.rs`, `telescope.rs`, `leap.rs`, `settings_menu.rs`

### Files Changed

- `lib/core/src/screen/mod.rs` - Integration with layer compositor
- `lib/core/src/screen/window.rs` - render_to_buffer method
- `lib/core/src/runtime/core.rs` - FrameRenderer initialization
- `lib/core/src/runtime/event_loop.rs` - RenderSignal handling
- `lib/core/src/highlight/theme.rs` - Background colors for all styles

### Technical Changes

- Screen rendering now goes through LayerCompositor → FrameBuffer → FrameRenderer → Terminal
- Eliminated full-screen clear on every render
- Added `*_to_buffer` methods to all renderable components

### Testing

- 256 unit tests passing (includes frame/overlay tests)
- 95 integration tests passing
- Zero warnings (build + clippy)

---

## [0.5.3] - 2025-12-18

### Features

- **Which-Key Enhancements**
  - RPC endpoint `state/whichkey` for querying which-key popup state
  - Keybinding grouping - bindings now categorized (motion, operator, mode, edit, jump, fold, telescope, window, misc)
  - Grouped rendering with section headers in which-key popup

- **Explorer File Operations**
  - Copy/Cut/Paste: `yy` (yank), `dd` (cut), `p` (paste), `D` (delete)
  - Multi-file selection: `v` (visual mode), `V` (select all)
  - Selection marker (`*`) displayed for selected items
  - Visual selection updates as cursor moves with j/k

- **Explorer Display Enhancements**
  - Human-readable file sizes: `S` toggles size column (1.2K, 3.4M, etc.)
  - Broken symlink detection: shows `! ` icon for broken links

- **Telescope Enhancements**
  - RPC endpoint `state/telescope` for querying telescope state
  - Fixed escape race condition in telescope close handling
  - Fixed buffer picker returning empty items

### Bug Fixes

- **`cw` operator enters insert mode** - Fixed race condition where change operator stayed in normal mode instead of entering insert mode after deletion
- **Explorer cursor position with tabs** - Cursor now correctly positioned when tab line is visible
- **Explorer root protection** - Prevents accidental delete/rename of root directory
- **Explorer cursor bounds** - Cursor now validated after tree modifications
- **Telescope escape handling** - Fixed race condition causing stuck mode

### Tests

- New `lib/core/tests/which_key.rs` - Which-key visibility and binding tests
- New `lib/core/tests/telescope.rs` - Telescope picker integration tests

### Technical Changes

- Added `group` field to `WhichKeyBinding` and `KeyMapInner` structs
- Added `ExplorerClipboard` and `ExplorerSelection` structures
- Added `format_size()` for human-readable byte formatting
- Added `WhichKeySnapshot` and `TelescopeSnapshot` RPC types

## [0.5.2] - 2025-12-18

### Bug Fixes

- **`e` motion implemented** - Word end motion now works (`e` moves to end of current/next word)
- **Count prefix for w/b/e motions** - `2w`, `3b`, `2e` now work correctly
- **Cross-line word motions** - `w` and `b` now cross line boundaries
- **dw/cw off-by-one fixed** - Motion inclusivity corrected; `dw` no longer deletes first char of next word
- **dd+p register populated** - Linewise delete now stores text in register for paste
- **V (visual line mode) implemented** - `V` enters visual line mode
- **Visual selection initialization** - Visual mode now properly initializes selection
- **Undo batching per session** - Insert mode edits are undone as a single unit
- **`:` bound in visual mode** - Can now enter command mode from visual mode
- **Leap auto-jump** - Single match automatically jumps to target

### Technical Changes

- Add `Motion::WordEnd` variant and `is_inclusive()` method to Motion enum
- Add `begin_batch()`/`flush_batch()` methods for undo grouping in Buffer
- Implement cross-line calculations in `word_forward_calc()` and `word_backward_calc()`
- Add `ModExtension::Line` variant for visual line mode
- Fix `cw` to use `WordEnd` motion (vim behavior: `cw` acts like `ce`)

### Tests

- Updated test suite from documenting bugs to expecting correct behavior
- All 332 tests passing

## [0.5.1] - 2025-12-18

### Features

- **Comprehensive Integration Test Suite** - 95 new server-based E2E tests
  - `word_motions.rs` (20 tests) - w, b motion tests
  - `operators.rs` (21 tests) - dd, x, yy, p, dw, cw, dj, dk, d$ tests
  - `undo_redo.rs` (11 tests) - u and Ctrl-R tests
  - `visual_mode.rs` (10 tests) - v, V, Ctrl-V mode tests
  - `command_mode.rs` (10 tests) - : command and :set tests
  - `cursor_advanced.rs` (14 tests) - gg, G, 0, $, count prefix tests
  - `leap.rs` (9 tests) - s, S leap navigation tests

### Documentation

- Tests document actual behavior vs expected vim behavior for gaps:
  - `e` motion not implemented
  - Count prefix not supported for w/b motions
  - w/b motions don't cross lines
  - dw/cw off-by-one bug (deletes first char of next word)
  - Undo is per-character, not per-insert-session
  - V (visual line mode) not implemented
  - Leap jump doesn't move cursor to match position

### Files Added

- `lib/core/tests/word_motions.rs`
- `lib/core/tests/operators.rs`
- `lib/core/tests/undo_redo.rs`
- `lib/core/tests/visual_mode.rs`
- `lib/core/tests/command_mode.rs`
- `lib/core/tests/cursor_advanced.rs`
- `lib/core/tests/leap.rs`

## [0.5.0] - 2025-12-18

### Features

- **Server Mode with JSON-RPC 2.0 Protocol** - Headless server for programmatic editor control
  - `--server` flag starts persistent server (runs until killed)
  - `--server --test` starts test server (exits when all clients disconnect)
  - Headless operation: no terminal required, captures output for RPC responses

- **Multiple Transport Options** - Flexible connectivity
  - `--stdio` - Stdio transport (stdin/stdout)
  - `--listen-tcp <port>` - TCP transport on specified port
  - `--listen-socket <path>` - Unix socket transport
  - Default TCP port: 12521 ('r'×100 + 'e'×10 + 'o')

- **RPC API Methods** - Full editor control via JSON-RPC 2.0
  - `input/keys` - Send key sequences (e.g., `{"keys": "iHello<Esc>"}`)
  - `state/mode` - Get current mode state
  - `state/cursor` - Get cursor position (x, y)
  - `state/buffer` - Get buffer content
  - `state/screen` - Get full screen state (cells, cursor, mode, dimensions)
  - `editor/quit` - Request editor quit

- **reo-cli Client Tool** - Command-line client for server interaction
  - `reo-cli mode` - Query current mode
  - `reo-cli cursor` - Query cursor position
  - `reo-cli buffer` - Query buffer content
  - `reo-cli screen` - Query screen state
  - `reo-cli keys '<keys>'` - Send key sequence
  - `reo-cli quit` - Request server quit
  - `reo-cli repl` - Interactive REPL mode
  - Configurable host/port: `--host`, `--port`

- **Hybrid Line Numbers by Default** - Line numbers now show hybrid mode (absolute for current line, relative for others) on startup

- **Server-Based Integration Testing** - E2E test infrastructure using real server
  - `ServerTestHarness` - Spawns test server with auto port allocation (ports 12600-12699)
  - `TestClient` - Async JSON-RPC client for test communication
  - `ServerTest` - Fluent builder API: `.with_content()`, `.with_keys()`, `.run()`
  - `ServerTestResult` - Assertion methods: `assert_normal_mode()`, `assert_cursor()`, `assert_buffer_contains()`
  - 1ms delay between key injections for reliable mode propagation
  - Replaces mock-based `TestRuntime` with real end-to-end testing

### Architecture

- `RpcServer` - Coordinates JSON-RPC request handling
- `TransportConfig` - Transport selection: Stdio, UnixSocket, Tcp
- `TransportReader`/`TransportWriter` - Async I/O abstraction
- `TransportListener` - Accepts connections for socket/TCP
- `ChannelKeySource` - Injects keys from RPC into runtime
- `DualOutput` - Captures screen output for headless mode
- `ServerConfig` - Server behavior configuration (headless, test mode)

### Files Added

- `lib/core/src/rpc/mod.rs` - RPC module root
- `lib/core/src/rpc/server.rs` - RpcServer implementation
- `lib/core/src/rpc/state.rs` - Screen state serialization
- `lib/core/src/rpc/transport.rs` - Transport abstractions
- `lib/core/src/rpc/types.rs` - JSON-RPC message types
- `lib/core/src/testing/client.rs` - TestClient for JSON-RPC communication
- `lib/core/src/testing/server.rs` - ServerTestHarness for spawning test servers
- `lib/core/src/testing/assertions.rs` - ServerTest builder and ServerTestResult assertions
- `main/src/server.rs` - Server mode entry point
- `tools/reo-cli/` - CLI client tool (Cargo.toml, src/main.rs, client.rs, commands.rs, repl.rs)

### Files Changed

- `Cargo.toml` - Added reo-cli workspace member, serde_json dependency
- `lib/core/Cargo.toml` - Added serde_json dependency
- `lib/core/src/lib.rs` - Added rpc, testing module exports
- `lib/core/src/io/output.rs` - Added DualOutput for screen capture
- `lib/core/src/event/inner/mod.rs` - Added RpcRequestEvent
- `lib/core/src/runtime/core.rs` - Added RPC request handling
- `lib/core/src/runtime/event_loop.rs` - Added RPC event handling
- `lib/core/src/runtime/mod.rs` - Removed TestRuntime exports
- `lib/core/src/testing/mod.rs` - Added exports for server-based testing
- `lib/core/tests/common/mod.rs` - Switched to ServerTest
- `lib/core/tests/basic_editing.rs` - Rewritten to use ServerTest
- `lib/core/tests/mode_switching.rs` - Rewritten to use ServerTest
- `main/src/main.rs` - Added server mode CLI flags
- `docs/TESTING.md` - Updated for server-based testing architecture

### Files Removed

- `lib/core/src/runtime/test.rs` - Old mock-based TestRuntime (replaced by server-based testing)

### Testing

- 213 unit tests passing
- 23 integration tests passing (basic_editing: 10, mode_switching: 8, resize: 5)
- Zero warnings (build + clippy)
- Performance: No regression in core benchmarks

---

## [0.4.18] - 2025-12-18

### Features

- **TOML-based configuration profile system** - Save, load, and switch editor configurations at runtime
  - Profiles stored at `~/.config/reovim/profiles/` (XDG Base Directory compliant)
  - Ex-commands: `:profile load <name>`, `:profile save <name>`, `:profile list`
  - Telescope picker for profile selection (via `:profile list`)
  - CLI flag: `--profile/-p <name>` to start with a specific profile
  - First-run auto-creates default profile
  - Profiles control: theme, colormode, line numbers, relative numbers, indent guides, scrollbar, tab width

- **TUI Settings Menu** - Interactive settings editor with live preview
  - Open with `Space s` or `:settings` command
  - Vim-style navigation: `j/k` to navigate, `Space` to toggle, `h/l` to cycle choices
  - Quick select choices with number keys `1-9`
  - Number settings adjustable with `+/-`
  - Immediate apply: changes take effect instantly
  - Settings organized in sections: Editor, Cursor, Window, Profile
  - Checkbox-style booleans, dropdown-style choices, number inputs

### Files Added

- `lib/core/src/config/mod.rs` - Config module root
- `lib/core/src/config/schema.rs` - TOML structs with serde
- `lib/core/src/config/loader.rs` - XDG paths, load/save utilities
- `lib/core/src/config/profile.rs` - ProfileManager struct
- `lib/core/src/telescope/picker/profiles.rs` - Profiles picker
- `lib/core/src/settings_menu/mod.rs` - Settings menu module root
- `lib/core/src/settings_menu/item.rs` - SettingItem, SettingValue, SettingSection types
- `lib/core/src/settings_menu/state.rs` - SettingsMenuState with navigation/manipulation
- `lib/core/src/settings_menu/render.rs` - TUI rendering with box drawing
- `lib/core/src/command/builtin/settings_menu.rs` - Settings menu commands

### Files Changed

- `lib/core/Cargo.toml` - Added toml, serde dependencies
- `lib/core/src/lib.rs` - Added config and settings_menu module exports
- `lib/core/src/command_line/ex_command.rs` - Added ProfileLoad/Save/List/Settings commands
- `lib/core/src/runtime/core.rs` - Added ProfileManager, settings_menu field
- `lib/core/src/runtime/event_loop.rs` - Added profile and settings menu event handling
- `lib/core/src/runtime/handlers.rs` - Added profile and settings menu handlers
- `lib/core/src/telescope/item.rs` - Added TelescopeData::Profile variant
- `lib/core/src/telescope/picker/mod.rs` - Added TelescopeAction::SwitchProfile, ProfilesPicker
- `lib/core/src/event/inner/mod.rs` - Added SettingsMenuEvent enum
- `lib/core/src/event/mod.rs` - Export SettingsMenuEvent
- `lib/core/src/modd/mod.rs` - Added Focus::SettingsMenu variant
- `lib/core/src/bind/mod.rs` - Added settings_menu keymap and Space-s binding
- `lib/core/src/command/id.rs` - Added settings menu command IDs
- `lib/core/src/command/traits.rs` - Added SettingsMenuAction, DeferredAction::SettingsMenu
- `lib/core/src/command/builtin/mod.rs` - Export settings_menu commands
- `lib/core/src/command/registry.rs` - Register settings menu commands
- `lib/core/src/screen/mod.rs` - Render settings menu overlay
- `lib/core/src/screen/status_line.rs` - Added SETTINGS icon
- `main/src/main.rs` - Added --profile/-p CLI flag

### Testing

- Zero warnings (build + clippy)
- All tests passing

### Deferred

- Runtime keybinding modification from profiles (Phase 5) - keybindings stored in TOML but not applied at runtime

---

## [0.4.17] - 2025-12-18

### Bug Fixes

- **Fixed integration test timing issues** - All 19 integration tests now pass reliably
  - Added `grace_period` to `InputEventBroker` for async event propagation
  - Added delay between keys in `MockKeySource` for mode state synchronization
  - Fixed Visual mode Escape handling to use keymap lookup instead of `is_esc_clearable_mode`

### Documentation

- **Added Integration Testing section to docs/TESTING.md** - Comprehensive guide for writing and running integration tests
  - Test architecture overview
  - `keys_from_str()` notation reference
  - `TestResult` assertion methods
  - Best practices and examples

### Testing

- All 19 integration tests now pass (was 9 passing, 10 ignored)
  - 10 basic editing tests (cursor movement, insert mode, open line)
  - 9 mode switching tests (enter/exit modes with Escape)

### Files Changed

- `lib/core/src/event/input.rs` - Added `grace_period` field and `with_grace_period()` builder method
- `lib/core/src/event/handler/command/mod.rs` - Fixed `is_esc_clearable_mode` to exclude Visual mode
- `lib/core/src/runtime/test.rs` - Use 10ms delay between keys and 50ms grace period
- `lib/core/tests/basic_editing.rs` - Removed `#[ignore]` from 6 tests, fixed `test_insert_at_beginning`
- `lib/core/tests/mode_switching.rs` - Removed `#[ignore]` from 4 tests
- `docs/TESTING.md` - Added Integration Testing section

---

## [0.4.16] - 2025-12-18

### Bug Fixes

- **Fixed telescope display jitter** - Eliminated screen flickering during telescope navigation and typing by adding a dedicated `render_telescope_only()` path that skips full screen clear

### Files Changed

- `lib/core/src/screen/mod.rs` - Added `render_telescope_only()` method
- `lib/core/src/runtime/core.rs` - Added `render_telescope_only()` wrapper method
- `lib/core/src/runtime/event_loop.rs` - Use `render_telescope_only()` for telescope internal updates
- `lib/core/src/runtime/handlers.rs` - Use `render_telescope_only()` for telescope actions

### Testing

- Zero warnings (build + clippy)
- All 186 tests passing

---

## [0.4.15] - 2025-12-18

### Features

- **Terminal resize event handling** - Editor now properly responds to terminal resize events:
  - Screen dimensions update correctly when terminal is resized
  - Window layouts recalculate to fit new dimensions
  - Explorer sidebar width clamps correctly on small screens
  - Explorer rendering uses layout width instead of hardcoded width

### Bug Fixes

- **Fixed editor content bleeding into explorer column** - All explorer lines now padded to full width to prevent editor text from showing through gaps

### Files Changed

- `lib/core/src/event/inner/mod.rs` - Added `ScreenResizeEvent` variant
- `lib/core/src/event/input.rs` - Added `with_event_sender()` to InputEventBroker
- `lib/core/src/io/input.rs` - Added `with_event_sender()` to EventStreamKeySource for resize events
- `lib/core/src/screen/mod.rs` - Added `resize()` method and unit tests
- `lib/core/src/screen/layout.rs` - Added resize behavior tests
- `lib/core/src/explorer/render.rs` - Pass layout width, pad all lines to full width
- `lib/core/src/runtime/event_loop.rs` - Handle resize events

### Testing

- Zero warnings (build + clippy)
- All tests passing
- Added 5 new integration tests for resize behavior (`lib/core/tests/resize.rs`)

### Known Issues

- **Panel background bleeding** - The content bleeding through on resize. (Ex, Editor content to Explorer)
  - Each UI component (explorer, which-key, telescope, etc.) has its own rendering system
  - Require the common-unified method for managing window and buffer.

---

## [0.4.14] - 2025-12-18

### Features

- **Integration test system with mock I/O layer** - End-to-end testing capability that verifies key input → expected output without requiring a real terminal
  - `KeySource` trait abstraction for terminal input (MockKeySource, ChannelKeySource, EventStreamKeySource)
  - `MockOutput` for capturing screen render output
  - `TestRuntime` with builder pattern for integration tests
  - `keys_from_str()` helper for readable key sequences (e.g., "ihello<Esc>")
  - Generic `InputEventBroker<K: KeySource>` to support mock input injection

### Testing

- Added integration tests for cursor movement (j, jj, l, hjkl)
- Added integration tests for mode transitions (i, a, v, :, :q<CR>)
- 9 integration tests passing, 10 ignored (timing issues documented for future work)

### Files Added

- `lib/core/src/io/mod.rs` - I/O abstraction module
- `lib/core/src/io/input.rs` - KeySource trait and implementations
- `lib/core/src/io/output.rs` - MockOutput for capturing display
- `lib/core/src/testing/mod.rs` - Testing utilities module
- `lib/core/src/testing/keys.rs` - Key event helpers
- `lib/core/src/runtime/test.rs` - TestRuntime and TestResult
- `lib/core/tests/basic_editing.rs` - Cursor movement tests
- `lib/core/tests/mode_switching.rs` - Mode transition tests
- `lib/core/tests/common/mod.rs` - Shared test utilities

### Files Changed

- `lib/core/Cargo.toml` - Added async-trait dependency
- `lib/core/src/lib.rs` - Added io, testing module exports
- `lib/core/src/runtime/event_loop.rs` - Made handle_event pub(crate)
- `lib/core/src/event/input.rs` - Made InputEventBroker generic over KeySource
- `lib/core/src/runtime/mod.rs` - Added test module export

---

## [0.4.13] - 2025-12-18

### Bug Fixes

- **Fixed treesitter theme not syncing with UI theme** - TreesitterTheme was hardcoded to default, ignoring `:colorscheme` changes. Now syncs with UI theme.
- **Fixed telescope keymaps picker showing empty results** - KeymapsPicker now populates from KeyMap::with_defaults()

### Features

- **Added telescope theme picker** - New `telescope_themes` command to select colorschemes visually with preview
- **Theme changes now rehighlight all buffers** - Switching themes immediately updates syntax highlighting

### Files Changed

- `lib/core/src/treesitter/theme.rs` - Added `from_theme_name()` method
- `lib/core/src/treesitter/highlighter.rs` - Added `set_theme()` method
- `lib/core/src/treesitter/mod.rs` - Added `set_theme()` method
- `lib/core/src/runtime/handlers.rs` - Updated `:colorscheme` to sync treesitter theme
- `lib/core/src/runtime/core.rs` - Added `rehighlight_all_buffers()`, registered ThemesPicker
- `lib/core/src/runtime/event_loop.rs` - Handle theme selection from telescope
- `lib/core/src/telescope/item.rs` - Added `Theme(ThemeName)` variant
- `lib/core/src/telescope/picker/mod.rs` - Added `ApplyTheme` action, themes module
- `lib/core/src/telescope/picker/themes.rs` - New ThemesPicker implementation
- `lib/core/src/command/builtin/telescope.rs` - Added `TelescopeThemesCommand`
- `lib/core/src/command/registry.rs` - Registered `TelescopeThemesCommand`
- `lib/core/src/telescope/picker/keymaps.rs` - Populate keymaps from `KeyMap::with_defaults()`

---

## [0.4.12] - 2025-12-18

### Bug Fixes

- **Fixed window navigation commands not working** - Window and tab commands were defined but never registered in CommandRegistry
- **Fixed C-hjkl not working in explorer mode** - Added window navigation keybindings to explorer mode
- **Fixed mode not syncing when navigating between explorer and editor** - Screen is now source of truth for focus, mode syncs after window actions

### Features

- **Added Space e toggle to explorer mode** - Can now toggle explorer from within explorer
- **Explorer included in window navigation** - C-l from explorer moves to editor, C-h from editor moves to explorer

### Removed

- Removed `q` binding from explorer (use C-l or Escape instead)

### Files Changed

- `lib/core/src/command/registry.rs` - Register window/tab commands
- `lib/core/src/bind/mod.rs` - Add explorer keybindings (C-hjkl, Space e)
- `lib/core/src/runtime/handlers.rs` - Add sync_mode_with_screen_focus()
- `lib/core/src/screen/mod.rs` - navigate_window() includes explorer as virtual window
- `lib/core/src/screen/split.rs` - Add EXPLORER_WINDOW_ID constant

---

## [0.4.11] - 2025-12-18

### Refactoring

- **Fixed all clippy cognitive complexity warnings** - Refactored 3 functions to meet complexity threshold (25):
  - `run()` in command handler: 63→<25 (extracted 8 helper methods)
  - `handle_explorer_action()` in runtime handlers: 31→<25 (extracted 5 helper methods)
  - `render()` in window: 30→<25 (extracted 5 helper methods)

### Files Changed

- `lib/core/src/event/handler/command/mod.rs` - Cognitive complexity refactoring
- `lib/core/src/runtime/handlers.rs` - Cognitive complexity refactoring
- `lib/core/src/screen/window.rs` - Cognitive complexity refactoring

### Testing

- Zero warnings (build + clippy)
- All tests passing

---

## [0.4.10] - 2025-12-18

### Bug Fixes

- **Fixed dd/yy/cc operators not working on real files**:
  - Race condition fix: Prevent `local_mode` from being overwritten when already in operator-pending mode
  - Explicit dereference in match pattern for operator type
  - Count=0 handling: `dd` now correctly deletes only the current line (was deleting 2 lines)
  - Buffer ID fix: Operators now use active buffer instead of hardcoded buffer 0
  - Paste fix: `p` command now uses active buffer instead of hardcoded buffer 0

- **Fixed which-key showing "E" instead of proper hints in operator-pending mode**:
  - Added `hint` field to `KeyMapInner` for hint-only entries
  - Operator-pending keymap now shows proper descriptions (e.g., "delete line (dd)")

### Files Changed

- `lib/core/src/bind/mod.rs` - Hint system for operator-pending mode
- `lib/core/src/buffer/mod.rs` - Count=0 fix for dd/yy
- `lib/core/src/event/handler/command/mod.rs` - Race condition fix
- `lib/core/src/runtime/handlers.rs` - Buffer ID and paste fixes

### Testing

- **159 tests passing**
- Zero warnings

---

## [0.4.9] - 2025-12-18

### Bug Fixes

- **Fixed Rust treesitter syntax highlighting** - Query syntax updated to match tree-sitter-rust v0.24:
  - Keywords `crate`, `self`, `super` now use named node syntax instead of string literals
  - Field-based patterns (`function:`, `body:`, `macro:`) properly aligned with grammar
  - Added error logging for query compilation failures
  - Added unit tests for query validation (4 new tests)

### Files Changed

- `lib/core/src/treesitter/queries.rs` - Error logging and tests
- `lib/core/src/treesitter/queries/rust/highlights.scm` - Rewritten for v0.24
- `lib/core/src/treesitter/queries/rust/textobjects.scm` - Fixed field syntax
- `lib/core/src/treesitter/queries/rust/folds.scm` - Fixed field syntax

### Testing

- **159 tests passing** (4 new treesitter query tests)
- Zero warnings

---

## [0.4.8] - 2025-12-18

### New Features

#### Unified Theme System with Sub-Structs
- **Restructured Theme with logical sub-structs** for better maintainability:
  - `base`: Default and cursor line styles
  - `gutter`: Line numbers, sign column
  - `selection`: Visual selection styles
  - `statusline`: Status line with mode-specific styles
  - `popup`: Completion popup styles
  - `telescope`: Fuzzy finder styles
  - `whichkey`: Which-key panel styles
  - `leap`: Jump navigation styles
  - `fold`: Code folding styles
  - `indent`: Indentation guide styles
  - `scrollbar`: Scrollbar with diagnostic marks
  - `search`: Search highlight styles
  - `tab`: Tab line styles
  - `window`: Window separator styles

- **ThemeName enum** with three built-in themes:
  - `Dark` - OneDark-inspired dark theme (default)
  - `Light` - Light theme for bright environments
  - `TokyoNightOrange` - Tokyo Night with orange accents

- **`:colorscheme` command** for runtime theme switching:
  - `:colorscheme dark` / `:colo dark`
  - `:colorscheme light` / `:colo light`
  - `:colorscheme tokyonight` / `:colo tokyonight`

- **TreesitterTheme::tokyo_night_orange()** - Coordinated syntax highlighting:
  - Comments: Light gray, italic
  - Keywords: Purple, bold, italic
  - Functions: Blue
  - Strings: Green
  - Types: Cyan

#### UI Enhancements
- **Enhanced statusline** with more information:
  - Mode icons: `` (normal), `` (insert), `` (visual), `` (command)
  - Position display: `line:col`
  - Filetype indicator with icon
  - Modified indicator `[+]`

- **Indent guides integration** - Visual vertical lines at indent levels:
  - `:set indentguide` / `:set ig` - Enable
  - `:set noindentguide` / `:set noig` - Disable
  - Uses `theme.indent.guide` and `theme.indent.active` styles

- **Scrollbar rendering** - Visual scroll position indicator:
  - `:set scrollbar` / `:set sb` - Enable
  - `:set noscrollbar` / `:set nosb` - Disable
  - Track character: `▕`, Thumb character: `█`
  - Uses `theme.scrollbar.track` and `theme.scrollbar.thumb` styles

#### Textobject Improvements
- **Word textobjects** for operators (delete, yank, change):
  - `iw` - Inner word (alphanumeric + underscore)
  - `aw` - Around word (includes trailing/leading whitespace)
  - `iW` - Inner WORD (non-whitespace)
  - `aW` - Around WORD (includes trailing/leading whitespace)
  - Examples: `diw`, `yaw`, `ciW`, `daW`

- **Visual mode textobject selection**:
  - `viw`, `vaw`, `viW`, `vaW` - Select word textobjects
  - `vi(`, `va{`, `vi"` - Select delimiter textobjects
  - `vif`, `vac` - Select semantic textobjects (treesitter)

- **VisualTextObjectAction event** for visual mode integration

### New Commands

| Command | Description |
|---------|-------------|
| `:colorscheme <name>` | Switch theme (dark, light, tokyonight) |
| `:colo <name>` | Short form of colorscheme |
| `:set indentguide` | Enable indent guides |
| `:set noindentguide` | Disable indent guides |
| `:set scrollbar` | Enable scrollbar |
| `:set noscrollbar` | Disable scrollbar |

### New Textobjects

| Textobject | Description |
|------------|-------------|
| `iw` / `aw` | Inner/around word |
| `iW` / `aW` | Inner/around WORD |

### Architecture

- `ThemeName` enum for theme identification
- `Theme::from_name()` for runtime theme creation
- Sub-struct organization: `BaseStyles`, `GutterStyles`, `SelectionStyles`, `StatusLineStyles`, `PopupStyles`, `TelescopeStyles`, `WhichKeyStyles`, `LeapStyles`, `FoldStyles`, `IndentStyles`, `ScrollbarStyles`, `SearchStyles`, `TabStyles`, `WindowStyles`
- `ScrollbarState` for scrollbar position calculation
- `VisualTextObjectAction` event type
- `WordTextObject` enum (Word, BigWord)

### Files Modified

- `lib/core/src/highlight/theme.rs` - Complete restructure with sub-structs
- `lib/core/src/highlight/mod.rs` - Export ThemeName
- `lib/core/src/treesitter/theme.rs` - Tokyo Night Orange syntax theme
- `lib/core/src/command_line/ex_command.rs` - New SetOption variants
- `lib/core/src/screen/window.rs` - Indent guides, scrollbar rendering
- `lib/core/src/screen/mod.rs` - Theme sub-struct access
- `lib/core/src/screen/status_line.rs` - Enhanced statusline
- `lib/core/src/textobject.rs` - Word textobject types
- `lib/core/src/buffer/mod.rs` - Word textobject methods
- `lib/core/src/event/inner/mod.rs` - VisualTextObjectAction
- `lib/core/src/runtime/handlers.rs` - New command handlers

---

## [0.4.7] - 2025-12-18

### New Features

#### Window Splits and Tab Pages
- **Vim-style window splits** - Split editor into multiple panes
  - `:sp [file]` / `:split [file]` - Horizontal split (one above the other)
  - `:vs [file]` / `:vsplit [file]` - Vertical split (side by side)
  - `:close` / `:clo` - Close current window
  - `:only` / `:on` - Close all windows except current

- **Window navigation** - Move focus between splits
  - `Ctrl-h` - Focus window to the left
  - `Ctrl-j` - Focus window below
  - `Ctrl-k` - Focus window above
  - `Ctrl-l` - Focus window to the right

- **Window movement** - Reposition windows in layout
  - `Ctrl-Shift-H` - Move window left
  - `Ctrl-Shift-J` - Move window down
  - `Ctrl-Shift-K` - Move window up
  - `Ctrl-Shift-L` - Move window right

- **Tab pages** - Multiple editor layouts
  - `:tabnew [file]` / `:tabe [file]` - Create new tab
  - `:tabclose` / `:tabc` - Close current tab
  - `:tabnext` / `:tabn` - Switch to next tab
  - `:tabprev` / `:tabp` - Switch to previous tab
  - `gt` - Next tab
  - `gT` - Previous tab

- **Tab line rendering** - Visual tab indicator when multiple tabs exist
- **Window separators** - Visual borders between split windows

### Architecture

- `SplitNode` - Binary tree for recursive window layouts
- `TabPage` / `TabManager` - Tab page management
- `WindowAction` / `TabAction` - Deferred action enums

### New Files

- `lib/core/src/screen/split.rs` - Split tree and layout calculation
- `lib/core/src/screen/tab.rs` - Tab page and manager
- `lib/core/src/command/builtin/window.rs` - Window commands
- `lib/core/src/command/builtin/tab.rs` - Tab commands

### Testing

- **152 tests passing**
- Zero warnings

---

## [0.4.6] - 2025-12-18

### Features

#### Unified Fast Benchmarking
- **New `bench` subcommand for perf-report** - Single command workflow:
  - Clears old benchmark data (`target/criterion/`)
  - Runs all benchmarks (`cargo bench -p reovim-core`)
  - Generates performance report (`perf/PERF-{version}.md`)

- **Faster benchmark execution** - Reduced from ~8 minutes to ~2 minutes:
  - measurement_time: 5s → 1s
  - warm_up_time: 3s → 200ms
  - sample_size: 100 → 30

- **`cargo run` defaults to reovim** - Added `default-members = ["main/"]` to workspace

### Usage

```bash
# Run benchmarks + generate report (unified)
cargo run -p perf-report -- bench -v X.Y.Z

# Run reovim directly
cargo run
```

---

## [0.4.5] - 2025-12-18

### Bug Fixes

#### Viewport Scrolling
- **Fixed cursor going off-screen when moving beyond viewport**
  - Root cause: `buffer_anchor` (scroll offset) was never updated when cursor moved
  - Added `Window::update_scroll()` method to keep cursor visible within viewport
  - Fixed cursor position calculation to account for scroll offset

### Technical Details

**Files modified:**
- `lib/core/src/screen/window.rs` - Added `update_scroll()` method
- `lib/core/src/screen/mod.rs` - Call `update_scroll()` before render, fix cursor_y calculation

**Implementation:**
```rust
// New method in Window
pub const fn update_scroll(&mut self, cursor_y: u16) {
    // Scroll up if cursor is above visible area
    if cursor_y < self.buffer_anchor.y {
        self.buffer_anchor.y = cursor_y;
    }
    // Scroll down if cursor is below visible area
    else if cursor_y >= self.buffer_anchor.y + self.height {
        self.buffer_anchor.y = cursor_y.saturating_sub(self.height) + 1;
    }
}

// Fixed cursor position calculation
let cursor_y = win.anchor.y + buf.cur.y.saturating_sub(win.buffer_anchor.y);
```

---

## [0.4.4] - 2025-12-17

### Performance Optimization

#### Zero-Copy Render Path
- **Eliminated buffer cloning in render loop** - Major optimization
  - Changed `Screen::render()` to accept `&BTreeMap<usize, Buffer>` instead of `&[Buffer]`
  - Removed costly `buffers.values().cloned().collect()` from every render call
  - Previous cost: 364µs (10K lines) to 1.96ms (50K lines) per render
  - Now: Zero allocation - only a reference is passed

### Technical Details

**Files modified:**
- `lib/core/src/screen/mod.rs` - Changed render signature to accept BTreeMap reference
- `lib/core/src/runtime/core.rs` - Removed buffer cloning, pass reference directly

**API Change:**
```rust
// Before:
pub fn render(&mut self, buffers: &[Buffer], ...);
let buffers: Vec<Buffer> = self.buffers.values().cloned().collect();
screen.render(&buffers, ...);

// After:
pub fn render(&mut self, buffers: &BTreeMap<usize, Buffer>, ...);
screen.render(&self.buffers, ...);
```

### Performance Results (v0.4.2 → v0.4.4)

| Benchmark | v0.4.2 | v0.4.4 | Change |
|-----------|--------|--------|--------|
| window_render/10 | 639 ns | 473 ns | **26% faster** |
| rtt/char_insert | - | 28 µs | baseline |
| rtt/move_down | 397 µs | 383 µs | **4% faster** |
| rtt/half_page_down | 410 µs | 390 µs | **5% faster** |
| rtt/goto_top | 397 µs | 390 µs | **2% faster** |
| input_mode_switch | - | 18 µs | baseline |
| stress_editing/50k | 38.99 ms | 37.60 ms | **4% faster** |

### Key Metrics (v0.4.4)

- **Window render**: 473ns (10 lines) - 2.6µs (10K lines)
- **Input RTT**: 28µs (char insert), 45µs (word motion)
- **Movement RTT**: 383-390µs (vertical), 45µs (horizontal)
- **Mode switch**: 18µs (Normal→Insert→Normal cycle)
- **Throughput**: ~400k renders/sec

---

## [0.4.3] - 2025-12-17

### New Features

#### Treesitter Integration
- **Syntax highlighting** powered by tree-sitter for accurate parsing
  - Supported languages: Rust, C, JavaScript, Python, JSON, TOML, Markdown
  - Incremental parsing with 50ms debounce for efficient re-highlighting
  - Theme-aware capture mapping (keyword, function, type, string, comment, etc.)

- **Code folding** with treesitter queries
  - `za` - Toggle fold at cursor
  - `zo` - Open fold at cursor
  - `zc` - Close fold at cursor
  - `zR` - Open all folds in buffer
  - `zM` - Close all folds in buffer
  - Fold markers show line count and preview text

- **Semantic text objects** (treesitter-based)
  - `af` / `if` - Around/inner function
  - `ac` / `ic` - Around/inner class/struct
  - Works with operators: `daf`, `yif`, `cic`, etc.

- **Indentation guides** (theme support added)
  - `indent_guide` and `indent_guide_active` theme styles

### Technical Details

**New modules:**
- `lib/core/src/treesitter/` - TreesitterManager, BufferParser, Highlighter
- `lib/core/src/folding.rs` - FoldManager, FoldState, FoldRange

**Dependencies added:**
- tree-sitter = "0.24"
- tree-sitter-rust, tree-sitter-c, tree-sitter-javascript, tree-sitter-python
- tree-sitter-json, tree-sitter-toml-ng, tree-sitter-md

### Testing

- **133 tests passing** (up from 118)
- New tests for folding operations

---

## [0.4.2] - 2025-12-17

### New Features

#### Performance Benchmarking Infrastructure
- **Criterion benchmark suite** - Comprehensive performance testing
  - Window render benchmarks (various buffer sizes)
  - Screen I/O benchmarks (buffered vs unbuffered)
  - Input simulation benchmarks (typing, scrolling, mode switching)
  - RTT (Round-Trip Time) benchmarks for latency measurement
  - Stress tests for worst-case scenarios
  - Location: `lib/core/benches/`

- **perf-report CLI tool** - Performance data management
  - `update --version X.Y.Z` - Generate versioned performance reports
  - `list` - Show current benchmark results
  - `check` - CI regression detection
  - `compare` - Diff between versions
  - Location: `tools/perf-report/`

- **Versioned performance reports** - Git-tracked benchmark data
  - Markdown + TOML format for human and machine readability
  - Full statistics: mean, median, std_dev, confidence intervals
  - Metadata: commit, date, Rust version, OS
  - Location: `perf/PERF-{version}.md`

### Benchmark Categories

| Category | Description |
|----------|-------------|
| window_render | Window::render() performance |
| screen_io | Full screen I/O with real files |
| input_* | Typing, scrolling, mode switching |
| rtt_* | Input lag, movement lag, explorer toggle |
| stress_* | Combined editing, rapid scroll, worst case |
| buffer_clone | Buffer clone overhead (bottleneck identified) |

### Performance Results (v0.3.0 → v0.4.2)

| Benchmark | v0.3.0 | v0.4.2 | Improvement |
|-----------|--------|--------|-------------|
| window_render/10 | 1.67 µs | 639 ns | **62% faster** |
| window_render/10000 | 6.60 µs | 2.48 µs | **62% faster** |
| viewport_size/24 | 3.76 µs | 1.20 µs | **68% faster** |
| viewport_size/200 | 33.41 µs | 9.73 µs | **71% faster** |
| screen_io/full_render | 27.68 µs | 5.91 µs | **79% faster** |
| file_io/buffered | 61.56 µs | 12.68 µs | **79% faster** |
| rtt/move_down | 1.35 ms | 397 µs | **71% faster** |
| rtt/half_page_down | 4.32 ms | 410 µs | **91% faster** |
| rtt/goto_top | 3.61 ms | 397 µs | **89% faster** |
| stress_editing/50k | 111.77 ms | 38.99 ms | **65% faster** |
| buffer_clone/50k | 3.90 ms | 1.96 ms | **50% faster** |
| throughput | 8.61 µs | 2.49 µs | **71% faster** |

### Key Findings

- **Average 50-80% improvement** across all benchmarks
- **Movement RTT improved 60-90%** - dramatically better responsiveness
- Window render: ~639ns-3µs (viewport-limited)
- Buffer clone: Reduced from 3.9ms to 1.96ms for 50K lines
- Buffered I/O: 10x faster than unbuffered

---

## [0.4.1] - 2025-12-17

### New Features

#### Leap Motion
- **Two-character jump navigation** - Quick cursor movement by typing 2 characters
  - `s` - Leap forward
  - `S` - Leap backward
- LeapState tracking and LeapEvent system
- Integrates with operator-pending mode (e.g., `ds{char}{char}` to delete to target)
- Location: `lib/core/src/leap/`

### Documentation

- **Full documentation rewrite** - Updated all docs to reflect actual codebase state
- Updated architecture.md with Runtime fields and feature modules
- Updated event-system.md with all InnerEvent variants
- Complete rewrite of commands.md with trait-based architecture

---

## Features Present Since v0.3.0

The following features were implemented but not documented in earlier changelogs:

### CommandTrait System
- Trait-based command architecture replacing simple enum
- `CommandTrait` interface with `execute()`, `name()`, `description()`
- `CommandRegistry` - Thread-safe command lookup with `Arc<dyn CommandTrait>`
- `ExecutionContext` - Execution parameters (buffer, count, ids)
- `DeferredAction` - Actions requiring Runtime access
- 129 registered CommandIds, ~79 implementations
- Location: `lib/core/src/command/`

### Telescope Fuzzy Finder
- Fuzzy file/buffer/grep search powered by nucleo
- 7 built-in pickers: files, buffers, live_grep, recent, commands, help, keymaps
- Normal and Insert modes for navigation/typing
- `Space f` prefix keybindings
- Location: `lib/core/src/telescope/`

### Explorer File Browser
- Tree-view file browser with expand/collapse
- 25 commands for navigation, file operations, filtering
- Create/rename/delete files and directories
- Hidden file toggle, filter mode
- `Space e` to toggle
- Location: `lib/core/src/explorer/`

### Completion Engine
- Async word completion
- Triggered with Ctrl-Space
- Ctrl-n/p for navigation, Tab to confirm
- Location: `lib/core/src/completion/`

### Which-Key Panel
- Popup showing available keybindings
- Appears after prefix keys (e.g., `g`, `Space`)
- Location: `lib/core/src/screen/which_key.rs`

### Jump List
- Ctrl-O/Ctrl-I navigation between jump locations
- Tracks cursor positions for jump commands
- Location: `lib/core/src/jump_list/`

### Operators with Motions
- `d` + motion = delete
- `y` + motion = yank
- `c` + motion = change
- Operator-pending mode with count support
- Location: `lib/core/src/command/builtin/operator.rs`

### Registers System
- Multi-register copy/paste storage
- Default register and named registers
- Location: `lib/core/src/registers/`

### Theme System
- Color mode detection (ANSI, 256, TrueColor)
- Themed styling for UI components
- Location: `lib/core/src/theme/`

### Undo/Redo
- `u` to undo, `Ctrl-r` to redo
- Per-buffer history

---

## [0.4.0] - 2025-12-17

### New Features

#### Multi-Dimensional Mode State System
- **Refactored flat `Mod` enum into structured `ModeState` system**
  - `Focus`: Where you are (Editor, Explorer, Telescope)
  - `EditMode`: How you're interacting (Normal, Insert, Visual)
  - `SubMode`: Special overlay states (Command, OperatorPending)
  - Location: `lib/core/src/modd/mod.rs`

- **Convenience constructors for common modes**
  - `ModeState::normal()` - Editor + Normal mode
  - `ModeState::insert()` - Editor + Insert mode
  - `ModeState::visual()` - Editor + Visual mode
  - `ModeState::visual_block()` - Editor + Visual Block mode
  - `ModeState::command()` - Editor + Command sub-mode
  - `ModeState::explorer()` - Explorer + Normal mode
  - `ModeState::explorer_input()` - Explorer + Insert mode
  - `ModeState::telescope()` - Telescope + Insert mode (for typing)
  - `ModeState::telescope_normal()` - Telescope + Normal mode (for navigation)
  - `ModeState::operator_pending(operator, count)` - Operator-pending sub-mode

- **State check methods**
  - `is_normal()`, `is_insert()`, `is_visual()` - Edit mode checks
  - `is_command()`, `is_operator_pending()` - Sub-mode checks
  - `is_editor_focus()`, `is_explorer_focus()`, `is_telescope_focus()` - Focus checks

- **Status line display**
  - `display_string()` method for human-readable mode indicator

#### Telescope Mode Switching
- **Telescope now supports both Normal and Insert modes**
  - Insert mode (default): For typing search query
  - Normal mode: For j/k navigation
  - ESC switches from Insert to Normal mode in Telescope
  - New keymaps: `telescope_normal` and `telescope_insert`

### Breaking Changes

- **Removed legacy `Mod` enum** - All code must use `ModeState` struct
- **Updated `CommandResult::ModeChange`** - Now takes `ModeState` instead of `Mod`
- **Updated `ModeChangeEvent`** - Now broadcasts `ModeState`

### Mode Mapping (Old -> New)

| Old Mode | New ModeState |
|----------|---------------|
| `Mod::Normal` | `ModeState::normal()` |
| `Mod::Insert(_)` | `ModeState::insert()` |
| `Mod::Visual(_)` | `ModeState::visual()` |
| `Mod::Command` | `ModeState::command()` |
| `Mod::Explorer` | `ModeState::explorer()` |
| `Mod::ExplorerInput` | `ModeState::explorer_input()` |
| `Mod::OperatorPending { .. }` | `ModeState::operator_pending(..)` |
| `Mod::Telescope` | `ModeState::telescope()` |

### Testing

- **All 115 tests passing**
- Zero warnings from `cargo build` and `cargo clippy`

### Key Files Modified

- `lib/core/src/modd/mod.rs` - New type definitions (Focus, EditMode, SubMode, ModeState)
- `lib/core/src/runtime/core.rs` - Runtime state management
- `lib/core/src/runtime/event_loop.rs` - Event handling
- `lib/core/src/runtime/handlers.rs` - Command handlers
- `lib/core/src/event/inner/mod.rs` - Event types
- `lib/core/src/event/handler/command/mod.rs` - Command handler
- `lib/core/src/event/handler/command/dispatcher.rs` - Dispatcher
- `lib/core/src/event/handler/command/count_parser.rs` - Count parsing
- `lib/core/src/event/handler/completion.rs` - Completion handler
- `lib/core/src/bind/mod.rs` - Keymap system
- `lib/core/src/screen/status_line.rs` - Status display
- `lib/core/src/screen/mod.rs` - Screen rendering
- `lib/core/src/settings/mod.rs` - Settings
- `lib/core/src/command/builtin/mode.rs` - Mode commands
- `lib/core/src/command/traits.rs` - Command traits

### Usage Example

```rust
use reovim_core::modd::{ModeState, Focus, EditMode, SubMode};

// Create common modes
let normal = ModeState::normal();
let insert = ModeState::insert();
let visual = ModeState::visual();

// Check mode state
if mode.is_insert() {
    // Handle insert mode
}

if mode.is_telescope_focus() && mode.is_normal() {
    // Telescope in navigation mode
}

// Create custom mode
let telescope_insert = ModeState::with_focus_and_mode(
    Focus::Telescope,
    EditMode::Insert(ModExtension::Normal),
);
```

## [0.3.0] - Previous Release

See git history for earlier changes.
