Severity: Critical (TUI advertised but largely non-functional)
Source: PR #16 review (C5, M6, M7)
rune/review/tui.py has 14 keybinds declared but most are advertised in BINDINGS without backing action_* methods. Pressing r (rescan), p (preview), a (apply), d (dismiss), o (open_editor), / (filter), ? (help), gg/G (goto) all raise in Textual.
The stale_banner_visible flag is set by _check_staleness but never rendered — compose() doesn't yield a banner widget. The "≤1s mid-session staleness banner" promise (commit 4871683) is satisfied only for tests inspecting the bool, not for users.
_label shows "[ ] finding N" with no path or kind — users can't tell what they're selecting. _detail widget is yielded but never updated.
Fix scope (likely splits into sub-tasks)
- Render banner widget bound to a
reactive flag.
- Implement
action_rescan (re-load chunks, clear selected, reset _initial_mtimes).
- Implement
action_preview (populate _detail with chunk text + line range).
- Implement
action_apply (route through applier.apply_operations with confirmation modal).
- Implement
action_dismiss, action_filter, action_goto_first, action_goto_last, action_help, action_open_editor.
- Update
_label to show f"{mark} {f['kind']} {Path(f['path']).name}:{f.get('start_line')}".
- Cancel
set_interval on on_unmount.
- Add TUI tests asserting banner widget visibility (not just bool) and that each binding has a working handler.
Severity: Critical (TUI advertised but largely non-functional)
Source: PR #16 review (C5, M6, M7)
rune/review/tui.pyhas 14 keybinds declared but most are advertised inBINDINGSwithout backingaction_*methods. Pressingr(rescan),p(preview),a(apply),d(dismiss),o(open_editor),/(filter),?(help),gg/G(goto) all raise in Textual.The
stale_banner_visibleflag is set by_check_stalenessbut never rendered —compose()doesn't yield a banner widget. The "≤1s mid-session staleness banner" promise (commit 4871683) is satisfied only for tests inspecting the bool, not for users._labelshows"[ ] finding N"with no path or kind — users can't tell what they're selecting._detailwidget is yielded but never updated.Fix scope (likely splits into sub-tasks)
reactiveflag.action_rescan(re-load chunks, clearselected, reset_initial_mtimes).action_preview(populate_detailwith chunk text + line range).action_apply(route throughapplier.apply_operationswith confirmation modal).action_dismiss,action_filter,action_goto_first,action_goto_last,action_help,action_open_editor._labelto showf"{mark} {f['kind']} {Path(f['path']).name}:{f.get('start_line')}".set_intervalonon_unmount.