- Add bare Left arrow key as alias for navigate_back (same as Backspace)
- Add bare Right arrow key as alias for navigate_forward (same as Alt+Right)
- Update handle_key doc comment to list new Left/Right bindings
- Add description field to DirEntry struct in vault.rs
- Add extract_frontmatter_description() to parse YAML frontmatter
- Populate description from frontmatter in list_vault_files()
- Show descriptions in DarkGray beside file entries in build_directory_lines()
- Truncate descriptions to keep total line width within 78 chars
- Link span_len covers only [name] portion, not the description
- Create FileWatcher watching index.md's parent directory before App::new()
- Pass file_watcher Option to App::new() as seventh argument
- Watcher failure is non-fatal: prints warning and passes None to App
- Add FileWatcher struct with RecommendedWatcher, mpsc channel, and rewatch() method
- Add file_watcher and pending_reload_at fields to App struct
- Update App::new() to accept Option<FileWatcher> parameter
- Add reload_current_document() preserving scroll and link selection
- Add rewatch_for_current_page() to re-point watcher on navigation
- Integrate try_recv() drain loop in event loop (non-blocking)
- Add 300ms debounce timer that fires reload after last relevant event
- Call rewatch_for_current_page() in navigate_to/back/forward/to_directory
- 04-02-SUMMARY.md created with full deviations, decisions, and dependency graph
- STATE.md updated: position to plan 2/3, decisions, session continuity, metrics
- ROADMAP.md updated: phase 4 progress 2/3 plans complete
- REQUIREMENTS.md: LIVE-02 marked complete
- Add PageMeta struct and read_page_meta() to app.rs with Gregorian date math
- App::new() computes initial page_meta from vault path + current_path
- navigate_to/back/forward all prepend splash lines and offset link_records for index.md
- handle_resize re-prepends splash for index.md after re-render
- Initial index.md load in main.rs prepends splash and adjusts link_records
- Status bar right side now shows 'Last modified: Mon DD, YYYY | X.X KB'
- Graceful truncation loop drops metadata fields when status bar is too narrow
- Add notify = "6.1", ansi-to-tui = "8.0", walkdir = "2.5" to Cargo.toml
- Create src/splash.rs with load_splash() using IntoText trait
- Add mod splash to main.rs module declarations
- Verified single ratatui-core v0.1.0 in dependency tree
- Add HistoryEntry struct with path, scroll_offset, selected_link fields
- Add Phase 3 navigation fields to App: history, history_index, link_records, selected_link, current_path
- Update App::new() to accept link_records and current_path parameters
- Implement navigate_to() with browser-style forward history truncation
- Implement navigate_back() and navigate_forward() with state restoration
- Implement follow_selected_link() for wiki-link and standard link resolution
- Implement select_next_link() and select_prev_link() with wrap-around
- Implement scroll_to_selected_link() for auto-scroll centering
- Add Tab, Shift-Tab, Enter, Backspace, Alt+Left, Alt+Right key bindings
- Update handle_resize() to capture and validate link_records after re-render
- Update main.rs to destructure link_records and pass to App::new()
- Remove #[allow(dead_code)] on config field (now actively used)
- Add is_within_vault() with canonicalize + starts_with path traversal guard
- Add resolve_wiki_link() with case-insensitive multi-strategy matching
(hyphens first, then underscores, then literal spaces per locked decision)
- Support subpath wiki-links: [[guides/Getting Started]] -> guides/getting-started.md
- Add resolve_standard_link() for inline [text](path.md) link resolution
relative to the current document's directory within the vault
- All resolution functions guarded by is_within_vault() to prevent traversal
- Add 02-01-SUMMARY.md with full execution record and deviation documentation
- Update STATE.md: Phase 2 Plan 1 complete, resume at 02-02-PLAN.md
- Update REQUIREMENTS.md: mark REND-03, REND-10, NAV-06, NAV-07 complete
- SignalFlags struct wraps Arc<AtomicBool> for SIGHUP/SIGTERM
- register_signals() registers SIGHUP and SIGTERM only (not SIGINT)
- SIGINT deliberately excluded — handled via crossterm key events for double-press Ctrl+C
- should_terminate() polls flag with Ordering::Relaxed for event loop use
- init_logging() is a Phase 1 no-op stub with LIFE-03 documentation
- init_terminal() enables raw mode and clears main screen via Viewport::Fullscreen
- No alternate screen buffer used (deliberate BBS immersive approach)
- restore_terminal() disables raw mode and shows cursor using let _ for all calls
- install_panic_hook() restores terminal, prints BBS-themed message, delegates to original hook
- Use ratatui::crossterm re-export (crossterm is transitive dep only)
- All panic hook operations use let _ or eprintln! — no unwrap() or ? inside hook