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:
150
plans/tui-prd-v2-frankentui.feedback-6.md
Normal file
150
plans/tui-prd-v2-frankentui.feedback-6.md
Normal file
@@ -0,0 +1,150 @@
|
||||
Your plan is strong and unusually detailed. The biggest upgrades I’d 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.
|
||||
Reference in New Issue
Block a user