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>
This commit is contained in:
Taylor Eernisse
2026-02-11 08:11:26 -05:00
parent 5ea976583e
commit 1161edb212
11 changed files with 11638 additions and 0 deletions

View File

@@ -0,0 +1,150 @@
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.
```diff
@@ 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.
```diff
@@ 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.
```diff
@@ 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.
```diff
@@ 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.
```diff
@@ 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.
```diff
@@ 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.
```diff
@@ 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.
```diff
@@ 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.
```diff
@@ 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.
```diff
@@ 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.