- 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
- 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