feat(tui): Phase 4 completion + Phase 5 session/lock/text-width

Phase 4 (bd-1df9) — all 5 acceptance criteria met:
- Sync screen with delta ledger (bd-2x2h, bd-y095)
- Doctor screen with health checks (bd-2iqk)
- Stats screen with document counts (bd-2iqk)
- CLI integration: lore tui subcommand (bd-26lp)
- CLI integration: lore sync --tui flag (bd-3l56)

Phase 5 (bd-3h00) — session persistence + instance lock + text width:
- text_width.rs: Unicode-aware measurement, truncation, padding (16 tests)
- instance_lock.rs: Advisory PID lock with stale recovery (6 tests)
- session.rs: Atomic write + CRC32 checksum + quarantine (9 tests)

Closes: bd-26lp, bd-3h00, bd-3l56, bd-1df9, bd-y095
This commit is contained in:
teernisse
2026-02-18 23:40:30 -05:00
parent 418417b0f4
commit 146eb61623
45 changed files with 5216 additions and 207 deletions

View File

@@ -22,6 +22,7 @@ use ftui::render::drawing::Draw;
use ftui::render::frame::Frame;
use crate::state::file_history::{FileHistoryResult, FileHistoryState};
use super::common::truncate_str;
// ---------------------------------------------------------------------------
// Colors (Flexoki palette)
@@ -136,7 +137,8 @@ fn render_path_input(frame: &mut Frame<'_>, state: &FileHistoryState, x: u16, y:
// Cursor indicator.
if state.path_focused {
let cursor_x = after_label + state.path_cursor as u16;
let cursor_col = state.path_input[..state.path_cursor].chars().count() as u16;
let cursor_x = after_label + cursor_col;
if cursor_x < max_x {
let cursor_cell = Cell {
fg: PackedRgba::rgb(0x10, 0x0F, 0x0F), // dark bg
@@ -446,16 +448,6 @@ fn render_hint_bar(frame: &mut Frame<'_>, x: u16, y: u16, max_x: u16) {
frame.print_text_clipped(x + 1, y, hints, style, max_x);
}
/// Truncate a string to at most `max_chars` display characters.
fn truncate_str(s: &str, max_chars: usize) -> String {
if s.chars().count() <= max_chars {
s.to_string()
} else {
let truncated: String = s.chars().take(max_chars.saturating_sub(1)).collect();
format!("{truncated}")
}
}
// ---------------------------------------------------------------------------
// Tests
// ---------------------------------------------------------------------------