You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Milestone: #9 TUI ShellApp Migration (TUI counterpart to #8 GTK ShellApp Event Dispatch; carved out of #7 Platform-Neutral to keep it bounded).
This is the single largest remaining architectural divergence between the two backends. tui_main::run() (src/tui_main/mod.rs:635) hand-rolls raw-mode/alt-screen bootstrap, ratatui::Terminal construction, and frame timing, then calls one event_loop() (:787, ~2,100 lines) with 32 dispatch sites fused into a single loop { }. None of it goes through quadraui::tui::run / run_with_shell. This epic migrates it onto quadraui::ShellApp + tui::shell_runner::run_with_shell, mirroring GTK's landed #493 migration, so quadraui owns the loop and App only implements setup/render_content/handle/tick. Per GOALS.md, cross-backend divergence is the direct cause of most GTK:/TUI: bug pairs — deleting event_loop() (Stage 6) is the payoff.
Scoping (Stage 0) found this is GTK-B.5-scale, not a quick pick — GTK's equivalent took 9 (B.5) + 13 (B.5b) stages. The three structural gaps and the full staged plan are recorded in PLAN.md ("Staged plan") and the src/tui_main/shell_app.rs module doc.
Migration status
Stage
Issue
Scope
Status
0
(this issue)
Dormant TuiShellApp scaffold — setup/tick fully ported, handle partial (accelerators + menu intercept), render_content stubbed; not wired to live entry point
Stages 2a/2b/2c were split out while scoping #601: render_content genuinely
cannot reach a raw ratatui::Frame/Buffer (confirmed via TuiBackend's
frame-scope internals — no public accessor exists), so #601 only wires the
subset already reachable through &mut dyn quadraui::Backend trait calls
(editor + tab/breadcrumb bars) and leaves sidebar content, quickfix/bottom
panel, and divider/drag/tooltip painting as explicit follow-ons. All three
block #605 — cutover can't delete event_loop() while those stay unpainted
without violating this epic's own "no change to what gets rendered" non-goal.
Supply-side (quadraui) dependencies
quadraui#466 — no consumer applies Backend::draw_editor's EditorPaintResult::cursor_position in the TUI ShellApp path. Hard-blocks Stage 5, and thus the Stage 6 cutover (live TUI would lose its cursor).
quadraui#467 — Backend trait has no DragState/ModalStack accessor; handle_mouse needs TuiBackend::drag_and_modal_mut(), which isn't on the trait. Preferred path for Stage 3 (a consumer-side rewrite onto dispatch_mouse_down/drag/up is the fallback).
Not blocked on quadraui#465 (macOS ShellApp) — TUI already runs everywhere via crossterm.
EPIC — parent/tracking issue
Milestone: #9 TUI ShellApp Migration (TUI counterpart to #8 GTK ShellApp Event Dispatch; carved out of #7 Platform-Neutral to keep it bounded).
This is the single largest remaining architectural divergence between the two backends.
tui_main::run()(src/tui_main/mod.rs:635) hand-rolls raw-mode/alt-screen bootstrap,ratatui::Terminalconstruction, and frame timing, then calls oneevent_loop()(:787, ~2,100 lines) with 32 dispatch sites fused into a singleloop { }. None of it goes throughquadraui::tui::run/run_with_shell. This epic migrates it ontoquadraui::ShellApp+tui::shell_runner::run_with_shell, mirroring GTK's landed #493 migration, so quadraui owns the loop andApponly implementssetup/render_content/handle/tick. Per GOALS.md, cross-backend divergence is the direct cause of mostGTK:/TUI:bug pairs — deletingevent_loop()(Stage 6) is the payoff.Scoping (Stage 0) found this is GTK-B.5-scale, not a quick pick — GTK's equivalent took 9 (B.5) + 13 (B.5b) stages. The three structural gaps and the full staged plan are recorded in
PLAN.md("Staged plan") and thesrc/tui_main/shell_app.rsmodule doc.Migration status
TuiShellAppscaffold —setup/tickfully ported,handlepartial (accelerators + menu intercept),render_contentstubbed; not wired to live entry pointissue-595-tui-migrate-to-quadraui-shellapp-run-wit)Backend::draw_*, collapseenter_frame_scoperender_contentpaints for real through&mut dyn Backend— editor windows + tab bars/breadcrumbs intomain_content_boundsrender_content: paint sidebar panel content (explorer/git/search/debug/settings/ext/AI panels) intosidebar_content_boundsrender_content: paint quickfix + bottom panel (terminal/debug output)render_content: window/group dividers, tab-drag overlay, tab-hover tooltiphandlemouse dispatch — consume quadraui#467 (DragState/ModalStack accessor)handlekey dispatch (dialog/palette/completion/context-menu + #318 Alt-reveal shim)main.rs/tui_bin.rstorun_with_shell; deleteevent_loop()Stages 2a/2b/2c were split out while scoping #601:
render_contentgenuinelycannot reach a raw
ratatui::Frame/Buffer(confirmed viaTuiBackend'sframe-scope internals — no public accessor exists), so #601 only wires the
subset already reachable through
&mut dyn quadraui::Backendtrait calls(editor + tab/breadcrumb bars) and leaves sidebar content, quickfix/bottom
panel, and divider/drag/tooltip painting as explicit follow-ons. All three
block #605 — cutover can't delete
event_loop()while those stay unpaintedwithout violating this epic's own "no change to what gets rendered" non-goal.
Supply-side (quadraui) dependencies
Backend::draw_editor'sEditorPaintResult::cursor_positionin the TUI ShellApp path. Hard-blocks Stage 5, and thus the Stage 6 cutover (live TUI would lose its cursor).Backendtrait has noDragState/ModalStackaccessor;handle_mouseneedsTuiBackend::drag_and_modal_mut(), which isn't on the trait. Preferred path for Stage 3 (a consumer-side rewrite ontodispatch_mouse_down/drag/upis the fallback).Non-goals
References
src/tui_main/mod.rs:635(run()),:787(event_loop());src/tui_main/shell_app.rs(Stage 0 scaffold + module-doc gap analysis)src/gtk/mod.rsimpl ShellApp for App(Full GTK run_with_shell migration: collapse 14 DAs to 1, strip Relm4 #493), Migrate GTK event dispatch to ShellApp::handle(UiEvent) #448 (GTK event-dispatch epic — the precedent this mirrors)PLAN.md"Staged plan for follow-up sessions"Dispatch note (2026-08-05)
coord drive/queue automation. Rationale: all six are simultaneously dispatchable per the Work-order DAG (each depends only on #595 Stage 2 — TuiShellApp::render_content paints for real through &mut dyn Backend #601), but vimcode has no automated gate that actually verifies TUI screen/behavior state today — the only Test-stage automation is a rerun of the existing unit suite (cargo test --no-default-features), which can't catch painting/mouse/cursor regressions. All six also touchsrc/tui_main/shell_app.rsconcurrently (the painting three likely alsorender_impl.rs/panels.rs), and that file isn't incoordinator.yml'sexclusive_files— real conflict risk if dispatched in parallel. See vimcode#622 (mini oracle-loop pilot, itself blocked on this epic) for the follow-up that would eventually make unattended driving of TUI work trustworthy.Work order
Sub-issues