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

150 lines
6.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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.