Files
gitlore/plans/tui-prd-v2-frankentui.feedback-6.md
Taylor Eernisse 1161edb212 docs: add TUI PRD v2 (FrankenTUI) with 9 plan-refine iterations
Comprehensive product requirements document for the gitlore TUI built on
FrankenTUI's Elm architecture (Msg -> update -> view). The PRD (7800+
lines) covers:

Architecture: Separate binary crate (lore-tui) with runtime delegation,
Elm-style Model/Cmd/Msg, DbManager with closure-based read pool + WAL,
TaskSupervisor for dedup/cancellation, EntityKey system for type-safe
entity references, CommandRegistry as single source of truth for
keybindings/palette/help.

Screens: Dashboard, IssueList, IssueDetail, MrList, MrDetail, Search
(lexical/hybrid/semantic with facets), Timeline (5-stage pipeline),
Who (expert/workload/reviews/active/overlap), Sync (live progress),
CommandPalette, Help overlay.

Infrastructure: InputMode state machine, Clock trait for deterministic
rendering, crash_context ring buffer with redaction, instance lock,
progressive hydration, session restore, grapheme-safe text truncation
(unicode-width + unicode-segmentation), terminal sanitization (ANSI/bidi/
C1 controls), entity LRU cache.

Testing: Snapshot tests via insta, event-fuzz, CLI/TUI parity, tiered
benchmark fixtures (S/M/L), query-plan CI enforcement, Phase 2.5
vertical slice gate.

9 plan-refine iterations (ChatGPT review -> Claude integration):
  Iter 1-3: Connection pool, debounce, EntityKey, TaskSupervisor,
    keyset pagination, capability-adaptive rendering
  Iter 4-6: Separate binary crate, ANSI hardening, session restore,
    read tx isolation, progressive hydration, unicode-width
  Iter 7-9: Per-screen LoadState, CommandRegistry, InputMode, Clock,
    log redaction, entity cache, search cancel SLO, crash diagnostics

Also includes the original tui-prd.md (ratatui-based, superseded by v2).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 08:11:26 -05:00

6.8 KiB
Raw Blame History

Your plan is strong and unusually detailed. The biggest upgrades Id make are around build isolation, async correctness, terminal correctness, and turning existing data into sharper triage workflows.

1) Fix toolchain isolation so stable builds cannot accidentally pull nightly

Rationale: a rust-toolchain.toml inside crates/lore-tui is not a complete guard when running workspace commands from repo root. You should structurally prevent stable workflows from touching nightly-only code.

@@ 3.2 Nightly Rust Strategy
-[workspace]
-members = [".", "crates/lore-tui"]
+[workspace]
+members = ["."]
+exclude = ["crates/lore-tui"]

+`crates/lore-tui` is built as an isolated workspace/package with explicit toolchain invocation:
+  cargo +nightly-2026-02-08 check --manifest-path crates/lore-tui/Cargo.toml
+Core repo remains:
+  cargo +stable check --workspace

2) Add an explicit lore <-> lore-tui compatibility contract

Rationale: runtime delegation is correct, but version drift between binaries will become the #1 support failure mode. Add a handshake before launch.

@@ 10.19 CLI Integration — Adding `lore tui`
+Before spawning `lore-tui`, `lore` runs:
+  lore-tui --print-contract-json
+and validates:
+  - minimum_core_version
+  - supported_db_schema_range
+  - contract_version
+On mismatch, print actionable remediation:
+  cargo install --path crates/lore-tui

3) Make TaskSupervisor truly authoritative (remove split async paths)

Rationale: the document says supervisor is the only path, but examples still use direct Cmd::task and search_request_id. Close that contradiction now to avoid stale-data races.

@@ 4.4 App — Implementing the Model Trait
-    search_request_id: u64,
+    task_supervisor: TaskSupervisor,

@@ 4.5.1 Task Supervisor
-The `search_request_id` field in `LoreApp` is superseded...
+`search_request_id` is removed. All async work uses TaskSupervisor generations.
+No direct `Cmd::task` from screen handlers or ad-hoc helpers.

4) Resolve keybinding conflicts and implement real go-prefix timeout

Rationale: Ctrl+I collides with Tab in terminals. Also your 500ms go-prefix timeout is described but not enforced in code.

@@ 8.1 Global (Available Everywhere)
-| `Ctrl+I` | Jump forward in jump list (entity hops) |
+| `Alt+o` | Jump forward in jump list (entity hops) |

@@ 8.2 Keybinding precedence
+Go-prefix timeout is enforced by timestamped state + tick check.
+Backspace global-back behavior is implemented (currently documented but not wired).

5) Add a shared display-width text utility (Unicode-safe truncation and alignment)

Rationale: current truncate() implementations use byte/char length and will misalign CJK/emoji/full-width text in tables and trees.

@@ 10.1 New Files
+crates/lore-tui/src/text_width.rs      # grapheme-safe truncation + display width helpers

@@ 10.5 Dashboard View / 10.13 Issue List / 10.16 Who View
-fn truncate(s: &str, max: usize) -> String { ... }
+use crate::text_width::truncate_display_width;
+// all column fitting/truncation uses terminal display width, not bytes/chars

6) Upgrade sync streaming to a QoS event bus with sequence IDs

Rationale: today progress/log events can be dropped under load with weak observability. Keep UI responsive while guaranteeing completion semantics and visible gap accounting.

@@ 4.4 start_sync_task()
-let (tx, rx) = std::sync::mpsc::sync_channel::<SyncUiEvent>(2048);
+let (ctrl_tx, ctrl_rx) = std::sync::mpsc::sync_channel::<SyncCtrlEvent>(256);   // never-drop
+let (data_tx, data_rx) = std::sync::mpsc::sync_channel::<SyncDataEvent>(4096);   // coalescible

+Every streamed event carries seq_no.
+UI detects gaps and renders: "Dropped N log/progress events due to backpressure."
+Terminal events (started/completed/failed/cancelled) remain lossless.

7) Make list pagination truly keyset-driven in state, not just in prose

Rationale: plan text promises windowed keyset paging, but state examples still keep a single list without cursor model. Encode pagination state explicitly.

@@ 10.10 state/issue_list.rs
-pub items: Vec<IssueListRow>,
+pub window: Vec<IssueListRow>,
+pub next_cursor: Option<IssueCursor>,
+pub prev_cursor: Option<IssueCursor>,
+pub prefetch: Option<Vec<IssueListRow>>,
+pub window_size: usize, // default 200

@@ 5.2 Issue List
-Pagination: Windowed keyset pagination...
+Pagination: Keyset cursor model is first-class state with forward/back cursors and prefetch buffer.

8) Harden session restore with atomic persistence + integrity checksum

Rationale: versioning/quarantine is good, but you still need crash-safe write semantics and tamper/corruption detection to avoid random boot failures.

@@ 10.1 New Files
-crates/lore-tui/src/session.rs         # Versioned session state persistence + validation + corruption quarantine
+crates/lore-tui/src/session.rs         # + atomic write (tmp->fsync->rename), checksum, max-size guard

@@ 11. Assumptions
+Session writes are atomic and checksummed.
+Invalid checksum or oversized file triggers quarantine and fresh boot.

9) Evolve Doctor from read-only text into actionable remediation

Rationale: your CLI already returns machine-actionable actions. TUI should surface those as one-key fixes; this materially increases usefulness.

@@ 5.11 Doctor / Stats (Info Screens)
-Simple read-only views rendering the output...
+Doctor is interactive:
+  - shows health checks + severity
+  - exposes suggested `actions` from robot-mode errors
+  - Enter runs selected action command (with confirmation modal)
+Stats remains read-only.

10) Add a Dependency Lens to Issue/MR detail (high-value triage feature)

Rationale: you already have cross-refs + discussions + timeline. A compact dependency panel (blocked-by / blocks / unresolved threads) makes this data operational for prioritization.

@@ 5.3 Issue Detail
-│ ┌─ Cross-References ─────────────────────────────────────────┐ │
+│ ┌─ Dependency Lens ──────────────────────────────────────────┐ │
+│ │ Blocked by: #1198 (open, stale 9d)                        │ │
+│ │ Blocks: !458 (opened, 2 unresolved threads)               │ │
+│ │ Risk: High (P1 + stale blocker + open MR discussion)      │ │
+│ └────────────────────────────────────────────────────────────┘ │

@@ 9.2 Phases
+Dependency Lens (issue/mr detail, computed risk score) :p3e, after p2e, 1d

If you want, I can next produce a consolidated “v2.1 patch” of the PRD with all these edits merged into one coherent updated document structure.