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>
209 lines
7.7 KiB
Markdown
209 lines
7.7 KiB
Markdown
No `## Rejected Recommendations` section was present, so these are all net-new improvements.
|
||
|
||
1. Keep core `lore` stable; isolate nightly to a TUI crate
|
||
Rationale: the current plan says “whole project nightly” but later assumes TUI is feature-gated. Isolating nightly removes unnecessary risk from non-TUI users, CI, and release cadence.
|
||
|
||
```diff
|
||
@@ 3.2 Nightly Rust Strategy
|
||
-- The entire gitlore project moves to pinned nightly, not just the TUI feature.
|
||
+- Keep core `lore` on stable Rust.
|
||
+- Add workspace member `lore-tui` pinned to nightly for FrankenTUI.
|
||
+- Ship `lore tui` only when `--features tui` (or separate `lore-tui` binary) is enabled.
|
||
|
||
@@ 10.1 New Files
|
||
+- crates/lore-tui/Cargo.toml
|
||
+- crates/lore-tui/src/main.rs
|
||
|
||
@@ 11. Assumptions
|
||
-17. TUI module is feature-gated.
|
||
+17. TUI is isolated in a workspace crate and feature-gated in root CLI integration.
|
||
```
|
||
|
||
2. Add a framework adapter boundary from day 1
|
||
Rationale: the “3-day ratatui escape hatch” is optimistic without a strict interface. A tiny `UiRuntime` + screen renderer trait makes fallback real, not aspirational.
|
||
|
||
```diff
|
||
@@ 4. Architecture
|
||
+### 4.9 UI Runtime Abstraction
|
||
+Introduce `UiRuntime` trait (`run`, `send`, `subscribe`) and `ScreenRenderer` trait.
|
||
+FrankenTUI implementation is default; ratatui adapter can be dropped in with no state/action rewrite.
|
||
|
||
@@ 3.5 Escape Hatch
|
||
-- The migration cost to ratatui is ~3 days
|
||
+- Migration cost target is ~3-5 days, validated by one ratatui spike screen in Phase 1.
|
||
```
|
||
|
||
3. Stop using CLI command modules as the TUI query API
|
||
Rationale: coupling TUI to CLI output-era structs creates long-term friction and accidental regressions. Create a shared domain query layer used by both CLI and TUI.
|
||
|
||
```diff
|
||
@@ 10.20 Refactor: Extract Query Functions
|
||
-- extract query_* from cli/commands/*
|
||
+- introduce `src/domain/query/*` as the canonical read model API.
|
||
+- CLI and TUI both depend on domain query layer.
|
||
+- CLI modules retain formatting/output only.
|
||
|
||
@@ 10.2 Modified Files
|
||
+- src/domain/query/mod.rs
|
||
+- src/domain/query/issues.rs
|
||
+- src/domain/query/mrs.rs
|
||
+- src/domain/query/search.rs
|
||
+- src/domain/query/who.rs
|
||
```
|
||
|
||
4. Replace single `Arc<Mutex<Connection>>` with connection manager
|
||
Rationale: one locked connection serializes everything and hurts responsiveness, especially during sync. Use separate read pool + writer connection with WAL and busy timeout.
|
||
|
||
```diff
|
||
@@ 4.4 App — Implementing the Model Trait
|
||
- pub db: Arc<Mutex<Connection>>,
|
||
+ pub db: Arc<DbManager>, // read pool + single writer coordination
|
||
|
||
@@ 4.5 Async Action System
|
||
- Each Cmd::task closure locks the mutex, runs the query, and returns a Msg
|
||
+ Reads use pooled read-only connections.
|
||
+ Sync/write path uses dedicated writer connection.
|
||
+ Enforce WAL, busy_timeout, and retry policy for SQLITE_BUSY.
|
||
```
|
||
|
||
5. Make debouncing/cancellation explicit and correct
|
||
Rationale: “runtime coalesces rapid keypresses” is not a safe correctness guarantee. Add request IDs and stale-response dropping to prevent flicker and wrong data.
|
||
|
||
```diff
|
||
@@ 4.3 Core Types (Msg)
|
||
+ SearchRequestStarted { request_id: u64, query: String }
|
||
- SearchExecuted(SearchResults),
|
||
+ SearchExecuted { request_id: u64, results: SearchResults },
|
||
|
||
@@ 4.4 maybe_debounced_query()
|
||
- runtime coalesces rapid keypresses
|
||
+ use explicit 200ms debounce timer + monotonic request_id
|
||
+ ignore results whose request_id != current_search_request_id
|
||
```
|
||
|
||
6. Implement true streaming sync, not batch-at-end pseudo-streaming
|
||
Rationale: the plan promises real-time logs/progress but code currently returns one completion message. This gap will disappoint users and complicate cancellation.
|
||
|
||
```diff
|
||
@@ 4.4 start_sync_task()
|
||
- Pragmatic approach: run sync synchronously, collect all progress events, return summary.
|
||
+ Use event channel subscription for `SyncProgress`/`SyncLogLine` streaming.
|
||
+ Keep `SyncCompleted` only as terminal event.
|
||
+ Add cooperative cancel token mapped to `Esc` while running.
|
||
|
||
@@ 5.9 Sync
|
||
+ Add "Resume from checkpoint" option for interrupted syncs.
|
||
```
|
||
|
||
7. Fix entity identity ambiguity across projects
|
||
Rationale: using `iid` alone is unsafe in multi-project datasets. Navigation and cross-refs should key by `(project_id, iid)` or global ID.
|
||
|
||
```diff
|
||
@@ 4.3 Core Types
|
||
- IssueDetail(i64)
|
||
- MrDetail(i64)
|
||
+ IssueDetail(EntityKey)
|
||
+ MrDetail(EntityKey)
|
||
|
||
+ pub struct EntityKey { pub project_id: i64, pub iid: i64, pub kind: EntityKind }
|
||
|
||
@@ 10.12.4 Cross-Reference Widget
|
||
- parse "group/project#123" -> iid only
|
||
+ parse into `{project_path, iid, kind}` then resolve to `project_id` before navigation
|
||
```
|
||
|
||
8. Resolve keybinding conflicts and formalize keymap precedence
|
||
Rationale: current spec conflicts (`Tab` sort vs focus filter; `gg` vs go-prefix). A deterministic keymap contract prevents UX bugs.
|
||
|
||
```diff
|
||
@@ 8.2 List Screens
|
||
- Tab | Cycle sort column
|
||
- f | Focus filter bar
|
||
+ Tab | Focus filter bar
|
||
+ S | Cycle sort column
|
||
+ / | Focus filter bar (alias)
|
||
|
||
@@ 4.4 interpret_key()
|
||
+ Add explicit precedence table:
|
||
+ 1) modal/palette
|
||
+ 2) focused input
|
||
+ 3) global
|
||
+ 4) screen-local
|
||
+ Add configurable go-prefix timeout (default 500ms) with cancel feedback.
|
||
```
|
||
|
||
9. Add performance SLOs and DB/index plan
|
||
Rationale: “fast enough” is vague. Add measurable budgets, required indexes, and query-plan gates in CI for predictable performance.
|
||
|
||
```diff
|
||
@@ 3.1 Risk Matrix
|
||
+ Add risk: "Query latency regressions on large datasets"
|
||
|
||
@@ 9.3 Phase 0 — Toolchain Gate
|
||
+7. p95 list query latency < 75ms on 100k issues synthetic fixture
|
||
+8. p95 search latency < 200ms on 1M docs (lexical mode)
|
||
|
||
@@ 11. Assumptions
|
||
-5. SQLite queries are fast enough for interactive use (<50ms for filtered results).
|
||
+5. Performance budgets are enforced by benchmark fixtures and query-plan checks.
|
||
+6. Required indexes documented and migration-backed before TUI GA.
|
||
```
|
||
|
||
10. Add reliability/observability model (error classes, retries, tracing)
|
||
Rationale: one string toast is not enough for production debugging. Add typed errors, retry policy, and an in-TUI diagnostics pane.
|
||
|
||
```diff
|
||
@@ 4.3 Core Types (Msg)
|
||
- Error(String),
|
||
+ Error(AppError),
|
||
|
||
+ pub enum AppError {
|
||
+ DbBusy, DbCorruption, NetworkRateLimited, NetworkUnavailable,
|
||
+ AuthFailed, ParseError, Internal(String)
|
||
+ }
|
||
|
||
@@ 5.11 Doctor / Stats
|
||
+ Add "Diagnostics" tab:
|
||
+ - last 100 errors
|
||
+ - retry counts
|
||
+ - current sync/backoff state
|
||
+ - DB contention metrics
|
||
```
|
||
|
||
11. Add “Saved Views + Watchlist” as high-value product features
|
||
Rationale: this makes the TUI compelling daily, not just navigable. Users can persist filters and monitor critical slices (e.g., “P1 auth issues updated in last 24h”).
|
||
|
||
```diff
|
||
@@ 1. Executive Summary
|
||
+ - Saved Views (named filters and layouts)
|
||
+ - Watchlist panel (tracked queries with delta badges)
|
||
|
||
@@ 5. Screen Taxonomy
|
||
+### 5.12 Saved Views / Watchlist
|
||
+Persistent named filters for Issues/MRs/Search.
|
||
+Dashboard shows per-watchlist deltas since last session.
|
||
|
||
@@ 6. User Flows
|
||
+### 6.9 Flow: "Run morning watchlist triage"
|
||
+Dashboard -> Watchlist -> filtered IssueList/MRList -> detail drilldown
|
||
```
|
||
|
||
12. Strengthen testing plan with deterministic behavior and chaos cases
|
||
Rationale: snapshot tests alone won’t catch race/staleness/cancellation issues. Add concurrency, cancellation, and flaky terminal behavior tests.
|
||
|
||
```diff
|
||
@@ 9.2 Phases
|
||
+Phase 5.5 Reliability Test Pack (2d)
|
||
+ - stale response drop tests
|
||
+ - sync cancel/resume tests
|
||
+ - SQLITE_BUSY retry tests
|
||
+ - resize storm and rapid key-chord tests
|
||
|
||
@@ 10.9 Snapshot Test Example
|
||
+ Add non-snapshot tests:
|
||
+ - property tests for navigation invariants
|
||
+ - integration tests for request ordering correctness
|
||
+ - benchmark tests for query budgets
|
||
```
|
||
|
||
If you want, I can produce a consolidated “PRD v2.1 patch” with all of the above merged into one coherent updated document structure. |