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,163 @@
I excluded everything already listed in `## Rejected Recommendations`.
These are the highest-impact net-new revisions Id make.
1. **Enforce Entity Identity Consistency End-to-End (P0)**
Analysis: The PRD defines `EntityKey`, but many code paths still pass bare `iid` (`IssueSelected(item.iid)`, timeline refs, search refs). In multi-project datasets this will cause wrong-entity navigation and subtle data corruption in cached state. Make `EntityKey` mandatory in every navigation message and add compile-time constructors.
```diff
@@ 4.3 Core Types
pub struct EntityKey {
pub project_id: i64,
pub iid: i64,
pub kind: EntityKind,
}
+impl EntityKey {
+ pub fn issue(project_id: i64, iid: i64) -> Self { Self { project_id, iid, kind: EntityKind::Issue } }
+ pub fn mr(project_id: i64, iid: i64) -> Self { Self { project_id, iid, kind: EntityKind::MergeRequest } }
+}
@@ 10.10 state/issue_list.rs
- .map(|item| Msg::IssueSelected(item.iid))
+ .map(|item| Msg::IssueSelected(EntityKey::issue(item.project_id, item.iid)))
@@ 10.10 state/mr_list.rs
- .map(|item| Msg::MrSelected(item.iid))
+ .map(|item| Msg::MrSelected(EntityKey::mr(item.project_id, item.iid)))
```
2. **Make TaskSupervisor Mandatory for All Background Work (P0)**
Analysis: The plan introduces `TaskSupervisor` but still dispatches many direct `Cmd::task` calls. That will reintroduce stale updates, duplicate queries, and priority inversion under rapid input. Centralize all background task creation through one spawn path that enforces dedupe, cancellation tokening, and generation checks.
```diff
@@ 4.5.1 Task Supervisor (Dedup + Cancellation + Priority)
-The supervisor is owned by `LoreApp` and consulted before dispatching any `Cmd::task`.
+The supervisor is owned by `LoreApp` and is the ONLY allowed path for background work.
+All task launches use `LoreApp::spawn_task(TaskKey, TaskPriority, closure)`.
@@ 4.4 App — Implementing the Model Trait
- Cmd::task(move || { ... })
+ self.spawn_task(TaskKey::LoadScreen(screen.clone()), TaskPriority::Navigation, move |token| { ... })
```
3. **Remove the Sync Streaming TODO and Make Real-Time Streaming a GA Gate (P0)**
Analysis: Current text admits sync progress is buffered with a TODO. That undercuts one of the main value props. Make streaming progress/log delivery non-optional, with bounded buffers and dropped-line accounting.
```diff
@@ 4.4 start_sync_task()
- // TODO: Register rx as subscription when FrankenTUI supports it.
- // For now, the task returns the final Msg and progress is buffered.
+ // Register rx as a live subscription (`Subscription::from_receiver` adapter).
+ // Progress and logs must render in real time (no batch-at-end fallback).
+ // Keep a bounded ring buffer (N=5000) and surface `dropped_log_lines` in UI.
@@ 9.3 Phase 0 — Toolchain Gate
+11. Real-time sync stream verified: progress updates visible during run, not only at completion.
```
4. **Upgrade List/Search Data Strategy to Windowed Keyset + Prefetch (P0)**
Analysis: “Virtualized list” alone does not solve query/transfer cost if full result sets are loaded. Move to fixed-size keyset windows with next-window prefetch and fast first paint; this keeps latency predictable on 100k+ records.
```diff
@@ 5.2 Issue List
- Pagination: Virtual scrolling for large result sets
+ Pagination: Windowed keyset pagination (window=200 rows) with background prefetch of next window.
+ First paint uses current window only; no full-result materialization.
@@ 5.4 MR List
+ Same windowed keyset pagination strategy as Issue List.
@@ 9.3 Success criteria
- 7. p95 list page fetch latency < 75ms using keyset pagination on synthetic fixture (10k issues, 5k MRs)
+ 7. p95 first-paint latency < 50ms and p95 next-window fetch < 75ms on synthetic fixture (100k issues, 50k MRs)
```
5. **Add Resumable Sync Checkpoints + Per-Project Fault Isolation (P1)**
Analysis: If sync is interrupted or one project fails, current design mostly falls back to cancel/fail. Add checkpoints so long runs can resume, and isolate failures to project/resource scope while continuing others.
```diff
@@ 3.1 Risk Matrix
+| Interrupted sync loses progress | High | Medium | Persist phase checkpoints and offer resume |
@@ 5.9 Sync
+Running mode: failed project/resource lanes are marked degraded while other lanes continue.
+Summary mode: offer `[R]esume interrupted sync` from last checkpoint.
@@ 11 Assumptions
-16. No new SQLite tables needed (but required indexes must be verified — see Performance SLOs).
+16. Add minimal internal tables for reliability: `sync_runs` and `sync_checkpoints` (append-only metadata).
```
6. **Add Capability-Adaptive Rendering Modes (P1)**
Analysis: Terminal compatibility is currently test-focused, but runtime adaptation is under-specified. Add explicit degradations for no-truecolor, no-unicode, slow SSH/tmux paths to reduce rendering artifacts and support incidents.
```diff
@@ 3.4 Terminal Compatibility Testing
+Add capability matrix validation: truecolor/256/16 color, unicode/ascii glyphs, alt-screen on/off.
@@ 10.19 CLI Integration
+Tui {
+ #[arg(long, default_value="auto")] render_mode: String, // auto|full|minimal
+ #[arg(long)] ascii: bool,
+ #[arg(long)] no_alt_screen: bool,
+}
```
7. **Harden Browser/Open and Log Privacy (P1)**
Analysis: `open_current_in_browser` currently trusts stored URLs; sync logs may expose tokens/emails from upstream messages. Add host allowlisting and redaction pipeline by default.
```diff
@@ 4.4 open_current_in_browser()
- if let Some(url) = url { ... open ... }
+ if let Some(url) = url {
+ if !self.state.security.is_allowed_gitlab_url(&url) {
+ self.state.set_error("Blocked non-GitLab URL".into());
+ return;
+ }
+ ... open ...
+ }
@@ 5.9 Sync
+Log stream passes through redaction (tokens, auth headers, email local-parts) before render/storage.
```
8. **Add “My Workbench” Screen for Daily Pull (P1, new feature)**
Analysis: The PRD is strong on exploration, weaker on “what should I do now?”. Add a focused operator screen aggregating assigned issues, requested reviews, unresolved threads mentioning me, and stale approvals. This makes the TUI habit-forming.
```diff
@@ 5. Screen Taxonomy
+### 5.12 My Workbench
+Single-screen triage cockpit:
+- Assigned-to-me open issues/MRs
+- Review requests awaiting action
+- Threads mentioning me and unresolved
+- Recently stale approvals / blocked MRs
@@ 8.1 Global
+| `gb` | Go to My Workbench |
@@ 9.2 Phases
+section Phase 3.5 — Daily Workflow
+My Workbench screen + queries :p35a, after p3d, 2d
```
9. **Add Rollout, SLO Telemetry, and Kill-Switch Plan (P0)**
Analysis: You have implementation phases but no production rollout control. Add explicit experiment flags, health telemetry, and rollback criteria so risk is operationally bounded.
```diff
@@ Table of Contents
-11. [Assumptions](#11-assumptions)
+11. [Assumptions](#11-assumptions)
+12. [Rollout & Telemetry](#12-rollout--telemetry)
@@ NEW SECTION 12
+## 12. Rollout & Telemetry
+- Feature flags: `tui_experimental`, `tui_sync_streaming`, `tui_workbench`
+- Metrics: startup_ms, frame_render_p95_ms, db_busy_rate, panic_free_sessions, sync_drop_events
+- Kill-switch: disable `tui` feature path at runtime if panic rate > 0.5% sessions over 24h
+- Canary rollout: internal only -> opt-in beta -> default-on
```
10. **Strengthen Reliability Pack with Event-Fuzz + Soak Tests (P0)**
Analysis: Current tests are good but still light on prolonged event pressure. Add deterministic fuzzed key/resize/paste streams and a long soak to catch rare deadlocks/leaks and state corruption.
```diff
@@ 9.2 Phase 5.5 — Reliability Test Pack
+Event fuzz tests (key/resize/paste interleavings) :p55g, after p55e, 1d
+30-minute soak test (no panic, bounded memory) :p55h, after p55g, 1d
@@ 9.3 Success criteria
+12. Event-fuzz suite passes with zero invariant violations across 10k randomized traces.
+13. 30-minute soak: no panic, no deadlock, memory growth < 5%.
```
If you want, I can produce a single consolidated unified diff of the full PRD text next (all edits merged, ready to apply as v3).