Last updated: September 5, 2026 (issue #827 correction pass — the #47/44-call-site claims below were stale within hours of being written; see the corrected section); prior revisions September 4 (#801) and September 3 (the platform-neutrality chain drained, and the audit it mandated is now run). Milestone #7 is 0 open: everything the 2026-09-01 audit filed landed, including 16 slices it never named (#751–#766). The post-#735 sizing audit — which the previous revision explicitly warned not to skip — is below, and it missed its projection by roughly 60% (though most of that miss is #731/#732 dead-code removal, not convergence — see GOALS.md §2/§3 for the corrected attribution). Nothing is in flight and nothing is queued for vimcode. #47 is reopened, in milestone #5 — its blocker (quadraui#699/#704) was filed and closed 2026-09-03, and #811 already ported the TUI side onto the new API. See GOALS.md for the full correction.
The north star is GOALS.md: eliminate all platform-specific code from
vimcode and lift it into quadraui. Milestone #7 Platform-Neutral is the consume
side (vimcode adopts a shipped quadraui API and deletes its bespoke per-backend code);
milestone #5 Cross-Platform UI Crate is the supply side (building quadraui itself).
Don't conflate them.
The 2026-09-01 audit filed ten issues and queued them in two parallel chains. All ten closed, along with the slice chains that #733/#734/#735 turned out to need:
| Convergence | Parent | Slices that did the work |
|---|---|---|
| Mouse routing — one precedence ladder, was written twice | #733 | #751 → #756 |
Keyboard dispatch — incl. the 19 stale mirrors mod.rs:NNNN pointers |
#734 | #757 → #762 |
Frame composition — FrameOp / compose_frame, one walk per backend |
#735 | #763 → #766 |
Also closed: #730 (ai_panel paint, closing epic #592), #593 (GTK Ctrl+V),
#731 (22 permanently-None Relm4 handles + ~103 unreachable arms), #732 (the GTK
Msg bus — 124 variants, 301 sites, a 684-line dispatch), #658 (preview tier),
#480, #550, #551. #146 moved out to #4 Editor Features as
recommended — it is an addition, not a deletion, and it was making the burndown mean two
things.
Two structural landmarks fell with them:
- #657 shipped
[lib] vimcode_core(eb745e2).render,tui_mainandgtkare promoted out of thevimcode/vcdbinaries into the library, andtests/acceptance/is sealed. The oracle loop is available to this repo for the first time — seetests/acceptance.rsanddocs/ARCHITECTURE.md. - #766 deleted
draw_frame(eedebf8), the last raw-ratatui::Framepath. The #735 staging question ("enumerate the raw-Bufferresidue first") resolved exactly as the previous revision predicted: it was#[cfg(test)]-gated and dead in production, and the three test-only helpers went with it.
Still true from earlier in the arc: fn event_loop does not exist in src/;
src/gtk/draw.rs is deleted; both ShellApp migrations (#448, #595) are closed.
Production lines, #[cfg(test)] excluded. All columns measured with the same
script (scripts/prod_lines.py, added for this audit) so they are comparable:
| 2026-05-01 | 2026-07-01 | pre-chain 2026-08-31 | pre-#785 2026-09-03 | post-#785, now @ ee26268 |
|
|---|---|---|---|---|---|
src/gtk/ |
18,969 | 13,675 | 12,526 | 9,650 | 2,607 |
src/tui_main/ |
14,649 | 10,358 | 11,125 | 10,345 | 10,366 |
src/app.rs (hoisted out of src/gtk/ by #785) |
— | — | — | — | 7,131 |
| all three files | 33,618 | 24,033 | 23,651 | 19,995 (2 files) | 20,104 |
src/render.rs (shared) |
10,574 | 12,807 | 15,009 | 21,405 | 21,405 |
(#785, "stage 1 of #47," hoisted struct App verbatim out of src/gtk/mod.rs into
a new src/app.rs — see GOALS.md's post-#735 audit for the full account. The
src/gtk/ = 9,650 figure this file previously carried as "now" predates that move;
regenerated at ee26268 per #827.)
Projected vs. actual over the chain (08-31 → 09-03):
| projected | actual | |
|---|---|---|
| Backends | −8,700 … −9,500, landing near 14,000–15,000 | −3,656, landing at 19,995 |
render.rs |
+4,000 … +5,000 | +6,396 |
| Net across the three files | ≈ −4,000 | +2,740 |
Where the reduction came from:
| File | pre-chain | now | Δ |
|---|---|---|---|
src/gtk/mod.rs |
10,518 | 7,684 | −2,834 |
src/tui_main/panels.rs |
1,554 | 1,208 | −346 |
src/tui_main/mouse.rs |
3,211 | 2,895 | −316 |
src/tui_main/shell_app.rs |
4,109 | 3,989 | −120 |
src/gtk/click.rs |
751 | 696 | −55 |
src/gtk/util.rs |
303 | 250 | −53 |
src/gtk/css.rs |
507 | 507 | 0 |
gtk/mod.rs is 78% of the entire cut. tui_main/mouse.rs — the file #733 was sized
against at −3,000…−3,500 — lost 316 lines.
Correcting the record. The
src/gtk/figure this file previously carried as "12,588 at 2026-09-01" was measured before #727/#728/#730 landed; it matches the pre-chain 08-31 column, not the 09-01 tree. The 05-01 and 07-01 figures also differ from the previously recorded ones (by 10–290 lines) for the same reason. That is the whole argument forscripts/prod_lines.py: regenerate, don't re-type.
Every decision — which surface was hit, which handler owns a key, what order a frame is
composed in — is now stated once in render.rs, and both backends walk it. Delegation
density is high: src/gtk/mod.rs makes 424 render:: calls. That is a durable
correctness win, and it is also why the net line count went up — the shared
op-sequence machinery (FrameOp/compose_frame, the routers) costs more lines than the
duplicate pair it replaced.
It is not "thin event-to-engine wiring." 19,995 production lines across two backends is a long way from the north star, and the remaining gap should not be planned as small.
The irreducible surface is recorded but never aggregated.✅ Done 2026-09-03, corrected 2026-09-05:docs/IRREDUCIBLE_SURFACE.md. The nine verdicts reduce to three facts (the folder-picker verdict was wrong and has been struck —quadraui::compose::FolderPickerControllerhas existed since 2026-05-25), two genuinely irreducible. And the sizing answer: only 246 of 19,429 production lines (1.3%) name a native toolkit type, so platform-specificity is not what keeps the backends large —src/gtk/mod.rsandsrc/tui_main/shell_app.rsare two implementations of the same fourShellAppentry points. Plan the remainder as duplication, not porting. One verdict (tui_main/mouse.rs:1620, command-line selection) turned out to be a mislabelled supply gap:CommandLineLayout::hit_testdoes not exist in quadraui and was never filed; #194 is the open consumer-side symptom.- The "duplication moved down into quadraui" claim is largely refuted (#827).
quadraui#481/#482 remain open and un-milestoned, but most of the headline numbers
don't hold up at the pinned rev:
EventOutcomeis declared once, not twice (quadraui#496); the 1,671-line byte-identical claim was withdrawn by quadraui#481's own correction comment as "idiom coincidence" (real duplication ~85 lines); the UTF-8 fix has been public since 2026-08-15 (quadraui#503); the tree-layout "twins" are both 1-line wrappers over one shared function (quadraui#499); and quadraui#482's eight children (#503–#510) are all closed. SeeGOALS.md§2 for the full table. What's still real: macOS dispatchesWindowResizedundebounced while TUI/GTK share aResizeDebouncer. - #47's blocker was filed and cleared 2026-09-03 — see below (this used to say "filed nowhere"; it wasn't, within hours of that claim being written).
- The divergence bug class is still ~44 issues deep (#206, #420, #264, #194, #233
and friends), plus milestone #5's cross-backend residue (#149, #167, #168, #233,
#294).
GOALS.md's thesis is that each is a symptom of a duplicated surface; if the convergence had reached far enough this list would be shrinking. It is the only outcome measure this goal has that isn't a line count — watch it.
Corrected 2026-09-05. #47 (native macOS GUI) was closed 2026-09-02 with commit
44882e9 — "re-audit at pickup, no code — Backend-trait Rc-handle gap blocks Stage
1" — recording the real blocker: App called GtkBackend::modal_stack_handle() /
drag_state_handle() at 19 call sites (modal_stack_handle ×12,
drag_state_handle ×7 — not the "44" this file previously said, which counted every
use of the backend field via grep -n 'self\.backend\.' src/gtk/mod.rs, not just
the two Rc-handle methods) in the drag and modal dispatch paths. Those were
inherent methods on the concrete struct, not on the generic quadraui::Backend
trait, and MacBackend's trait equivalents (modal_stack_mut, drag_and_modal_mut)
returned short-lived &mut borrows that couldn't be stashed and reused the way App
does. Full findings are in PLAN.md.
That blocker was filed — this file just never caught up. quadraui#699 was
filed 2026-09-03 16:38Z (into quadraui milestone #9) and closed 17:11Z
(PR#700/88345fb); follow-up #704 closed 21:41Z. vimcode#47 was reopened
16:38Z and is open now, in milestone #5. quadraui#699/#704 gave every backend a
symmetric Rc-handle API, and vimcode has already started consuming it: #811
bumped the quadraui pin to 4ff2a64 and ported the TUI-side call sites off the
now-removed drag_and_modal_mut. The actual next actionable item is vimcode#47
Stage 1 (the GTK-side App move), not a re-filing task — see PLAN.md and
GOALS.md for the full correction.
- #7 is 0 open. #146 moved to #4 Editor Features; #47 sits in #5 Cross-Platform UI
Crate, which
GOALS.mddefines as covering the macOS/Windows backends, and is open (reopened 2026-09-03). - quadraui milestone #9 ("vimcode Platform-Neutral blockers") is open (0 open / 7 closed issues) — it held quadraui#699 and does not need re-opening.
- Stale Win-GUI issues. Roughly a dozen open
Win-GUI:issues (#160–#178, #61, #172, #176) describe a backend deleted from this repo on 2026-05-11 (3e4bcff). Their live counterparts are quadraui#19–#31 / quadraui#580. They should be migrated or closed rather than left to implysrc/win_gui/still exists.
There are none, deliberately. Locate code by symbol, not coordinate:
grep -n "impl quadraui::ShellApp for App" src/gtk/mod.rs and friends. Where a count
appears it is evidence measured on a named revision — regenerate it
(python3 scripts/prod_lines.py src/gtk src/tui_main src/render.rs) rather than trusting
it. #734 existed in the first place because src/tui_main/ carried 19
mirrors mod.rs:NNNN comments whose targets had all drifted.
Feature documentation lives in README.md. Sessions 389 and earlier in SESSION_HISTORY.md. No multi-stage wave is in flight — PLAN.md holds the #47 re-audit findings and is otherwise history.
Every new Vim feature and every bug fix MUST have comprehensive integration tests before the work is considered done. Subtle bugs (register content, cursor position, newline handling, linewise vs. char-mode paste) are only reliably caught by tests. The process is:
- Write failing tests that document the expected Vim behavior
- Implement/fix the feature until all tests pass
- Run the full suite (
cargo test) — no regressions allowed
When implementing a new key/command, add tests covering:
- Basic happy path
- Edge cases: start/middle/end of line, start/end of file, empty buffer, count prefix
- Register content (text and
is_linewiseflag) - Cursor position after the operation
- Interaction with paste (
p/P) to verify the yanked/deleted content behaves correctly
Snapshot of where each surface stands on its quadraui primitive. TUI was the reference implementation through Phase C; GTK caught up. Numbers update with each Path-A landing — read this to find the next slice.
Status (2026-09-03): Paint duplication is done for every
surface in the table below — all ✅ on both backends. The
GTK-side regression that #540 introduced (surfaces painted only
by the since-deleted draw.rs) was swept by #669–#672, and the
last holdout, ai_panel, was painted on GTK by #730.
No bespoke section-walk paint code remains (debug sidebar moved to
MultiSectionView in #296 — both paint and click consume one cached
layout per frame). The mouse-routing, keyboard-dispatch and
frame-composition duplication that this note used to point at as
"untracked residual" was converged by #751–#766: both backends now
walk one FrameOp sequence built by render::compose_frame, and
draw_frame — the last raw-ratatui::Frame path — is deleted (#766).
What remains cross-backend is the set of rungs the slices
deliberately declined to converge, each with its verdict recorded
at the call site (grep -rn -iE "do not converge|one-sided|intrinsic difference" src/),
plus intrinsic-to-surface divergences (Cairo painter order vs ratatui
cell coalescence, px vs cell units). See "What remains" above — that
set has never been aggregated into one statement, and doing so is the
next piece of the north star's own work.
| Surface | Primitive | TUI | GTK | Notes |
|---|---|---|---|---|
| Status bar (per-window + global) | StatusBar |
✅ | ✅ | layout via StatusBarLayout |
| Tab bar | TabBar |
✅ | ✅ | |
| Activity bar | ActivityBar |
✅ | ✅ | |
| Tree view (explorer + SC) | TreeView |
✅ | ✅ | layout via TreeViewLayout |
| List view (quickfix + tab switcher) | ListView |
✅ | ✅ | layout via ListViewLayout |
| Form (settings) | Form |
✅ | ✅ | hint field exists but unrendered (#202) |
| Palette (all pickers: file/symbol/cmd/branch) | Palette |
✅ | ✅ | #402: all pickers route through picker_panel_to_palette() → quadraui::Palette. Preview panes + tree items. PaletteLayout for hit-test. PickerGeometry for popup bounds. |
| Find/replace overlay | shared hit-regions | ✅ | ✅ | engine-side compute_find_replace_hit_regions |
| Terminal cells + scrollbar + split | Terminal + TerminalSplitLayout |
✅ | ✅ | #353. build_terminal_draw_data() shared; both call Backend::draw_terminal. Themed scrollbar via TerminalScrollbar { inverted: true }. |
| LSP hover popup (simple) | Tooltip |
✅ | ✅ | slice 1, e1e76cd |
| Signature help popup | Tooltip{styled_lines} |
✅ | ✅ | slice 2, aaa9a3c |
| Diff peek popup | Tooltip{styled_lines} |
✅ | ✅ | slice 3, e6650fa |
| Dialog (quit/close confirm) | Dialog |
✅ | ✅ | slice 5, 7768a25 |
| Context menu (right-click) | ContextMenu |
✅ | ✅ | slice 6, 7ce0f5d |
| Menu dropdown (top menu bar) | MenuSystem |
✅ | ✅ | #319. Owned by MenuSystem::render() + MenuOverlay. |
| Debug toolbar | StatusBar |
✅ | ✅ | slice 8, caf62a8 |
| Breadcrumb bar | StatusBar |
✅ | ✅ | slice 8 |
| Editor hover popup (markdown + code-hl + selection + scroll + links) | RichTextPopup |
✅ | ✅ | #214 shipped (c8a23e9); rasterisers lifted via #266 (779f6e8); paint migrated to Surface::RichTextPopup via frame.draw() in #469 / PR #487 (1912cd3). Both backends consume quadraui::{tui,gtk}::draw_rich_text_popup through the trait. |
| Completion popup | Completions |
✅ | ✅ | #285 — GTK lifted to quadraui::gtk::draw_completions |
| Editor scrollbar (v + h paint) | Scrollbar |
✅ | ✅ | #277, fbbc85f+ |
| Settings panel chrome (header + search row) | draw_settings_chrome |
✅ | ✅ | #278, fd08db0 |
| AI sidebar message history | MessageList |
✅ | ✅ | #279, 8e55720 |
| Editor viewport (text + gutter + cursor + selection + diagnostics) | Editor |
✅ | ✅ | #276, 5b23718+ (Phase C Stage 1) |
| Extension panel | TreeView (with Decoration::Header) |
✅ | ✅ | #280, d29d1b4. Adapter render::ext_sidebar_to_multi_section_view (paint goes through render::populate_ext_sidebar_system; the original ext_sidebar_to_tree_view adapter lost its last caller and was deleted in #812). Click via TreeViewLayout::hit_test() on both backends. |
| Debug sidebar (variables tree, breakpoints, watch) | MultiSectionView (4 × TreeView) |
✅ | ✅ | #296, 285916b. Adapter render::debug_sidebar_to_multi_section_view. Paint caches layout; click reads verbatim. |
| Source control panel | SidebarSystem (4 sections) |
✅ | ✅ | #321/#339/#340. populate_sc_sidebar_system + SidebarSystem.render(). Unified dispatch via dispatch_sc_sidebar_key_unified. Section badges + visibility (quadraui#103). |
| Bottom panel tabs (Terminal / Debug Output) | TabBar |
✅ | ✅ | #304, 5d7fa09. Adapter render::build_bottom_panel_tab_bar. Click via Engine::handle_bottom_tab_bar_click. show_tab_close: false, compact: true. |
| Terminal toolbar (find bar + tab strip) | StatusBar / TabBar |
✅ | ✅ | #305, 08dd916. Adapter render::build_terminal_toolbar. Click via Engine::resolve_terminal_toolbar_click. Tab strip uses compact: true. |
| Menu bar labels | MenuSystem |
✅ | ✅ | #319. quadraui::MenuSystem owns all state + rendering. MenuOverlay helper for GTK overlay DA. |
| Command center (nav arrows + search box) | CommandCenter |
✅ | ✅ | #310, b5fdd7d. Adapter render::build_command_center_view. Click via CommandCenterLayout::hit_test. |
| Search panel (chrome + results) | SidebarSystem (Form + Tree) |
✅ | ✅ | #323/#333/#334. populate_search_sidebar_system + SidebarSystem.render(). Unified dispatch via dispatch_search_sidebar_key_unified. Form: query/replace TextInput + ToggleGroup + ButtonRow. Tree: file-grouped results with collapse. |
Cross-backend logic-sharing (where one implementation drives both backends):
- All primitive
Layoutalgorithms (StatusBarLayout,PaletteLayout, etc.) — single implementation, both backends consume. quadraui::dispatch_scroll/click/mouse_down/drag/up+ModalStack+DragState— drives all scroll wheel routing, scrollbar thumb-drag + track-page, palette drag, picker drag. All scrollable surfaces registered asScrollSurfaceat paint time (#307, completed Session 353).- Engine-side hit-region builders (
compute_find_replace_hit_regions) and cell-unit fit algorithms (StatusBar::fit_right_start,TabBar::fit_active_scroll_offset) — parameterised over a measurement closure so each backend supplies its native unit. core::settings::SAVE_REVISION— one source of truth both file watchers consult (#201).- All
*_to_form/*_to_tree_view/lsp_status_for_bufferadapters inrender.rsandcore/engine/. quadraui::MenuSystem— menu bar + dropdown lifecycle (open/close, keyboard nav, hover-to-switch, modal stack). Both backends callrender()andhandle()with zero per-backend menu logic. GTK usesMenuOverlayhelper for the titlebar DA overlay wiring.quadraui::TreeController— explorer file tree: selection, scroll, keyboard nav, inline editing (rename + new-file/folder), scrollbar rendering + interaction (#415, quadraui#193). Both backends callrender()for drawing (including built-in 8px/1-cell scrollbar) and route mouse events throughhandle()for scrollbar thumb drag, track click, and row selection._viamethods for keyboard editing. All domain logic inengine/explorer_ops.rs.quadraui::SidebarSystem— extensions sidebar (#336/#337/#338), source control panel (#321/#339/#340), and search panel (#323/#333/#334): section selection, scroll, keyboard nav, mouse handling, collapse, badges, visibility. Search panel usesSectionKind::Formfor the chrome section (quadraui#105). Both backends callpopulate_*()+render()anddispatch_*_key_unified(). Zero per-backend nav/click code.quadraui::StatusBarInteraction— debug toolbar hover/press state. TUI uses it via UiEvent intercept; GTK manual wiring produces identical results (#331 verified and closed).render::build_terminal_draw_data()+Backend::draw_terminal— terminal cell grid + themed scrollbar + split-pane layout. Both backends call one shared builder, thendraw_terminal. Zero per-backend terminal rendering code (#353).render::build_tab_drop_groups()+compute_tab_drop_zone()+compute_tab_drop_overlay()— tab drag-and-drop drop-zone computation (delegates toquadraui::compute_drop_zone()) and overlay geometry (highlight rect, insertion bar, ghost position). Both backends build atab_slots_map(backend-specific measurement) andDropGroupBounds, then call shared functions. Zero per-backend drop-zone algorithm code (#345).render::screen_zone_hit_test()+window_zone_hit_test()+resolve_gutter_action()— screen-level click zone detection (tab bar, window, breadcrumb, divider), window sub-zone detection (gutter, status bar, scrollbar, text area), and gutter action resolution. GTK cachesScreenLayoutfrom paint; both backends call shared functions for zone detection. Tab bar inner slot resolution (Pango vs char-cell) stays per-backend (#344).render::build_tab_bar_primitive()+breadcrumbs_to_quadraui_status_bar()— tab bar and breadcrumb bar primitives pre-built inScreenLayout(#347). Both backends draw directly fromGroupTabBar.bar/BreadcrumbBar.bar/ScreenLayout.tab_bar_primitive. Zero per-backend adapter construction orshow_splitlogic.render::picker_panel_to_palette()+PickerGeometry— ALL picker types (file/symbol/command/branch, with/without preview, flat/tree) route through one adapter toquadraui::Palette.PickerGeometry::compute()+PickerSizingconstants give a single source of truth for popup bounds. Zero per-backend picker rendering code (#402).Engine::needs_clipboard_for_paste()+prepare_paste_clipboard()— paste-key detection and clipboard register loading (#381). Both backends call the same two engine methods beforehandle_key(). Zero per-backend paste detection logic.Engine::clipboard_read+clipboard_writecallbacks — clipboard access routed through engine-owned closures (#417). GTKsetup_gtk_clipboard()wiresgdk4::Displayclipboard once at startup; TUI wirescopypastaprovider. Six GTK call sites (yank sync, paste prep, hover-popup copy, terminal copy/paste, AI panel Ctrl-V) consolidated. Zero per-backend clipboard logic beyond the one-time provider setup.Engine::handle_explorer_mouse_event()— single-click row dispatch (toggle dir / preview file) for explorer TreeController events (#415). Both backends route mouse events throughTreeController.handle()→handle_explorer_mouse_event().render::compute_editor_layout(engine, total_height, line_height, menu_in_viewport) -> EditorLayout— one-shot layout computation for all chrome heights (#386). GTK passes pixel units, TUI passesline_height=1.0for row units. Replacesgtk_editor_bottom,gtk_terminal_target_maximize_rows, TUIterminal_target_maximize_rows_tui, and the unusededitor_bottom_px.Engine::handle_completion_click(CompletionsHit) -> bool— click-to-pick on completion popup (#288). Both backends cacheCompletionsLayoutfrom render, callhit_test()at click time.Item(idx)→ apply + dismiss,Inert→ dismiss,Empty→ dismiss + fall through.Engine::context_menu_hit_to_idx()+ cachedContextMenuLayout— context menu click/hover viahit_test()(#210). Both backends cache layout from render. GTK motion handler + click handler + TUI click + motion handlers all replaced with sharedhit_test().resolve_context_menu_click()gated to#[cfg(test)].Engine::resolve_bottom_panel_zone()+BottomPanelGeometry— cached vertical geometry for bottom panel zone detection (#418). Explicittoolbar_y/content_y/content_row_hoffsets (not uniformrow_h) so GTK's taller tab bar gets correct zones. Both backends cache at paint time.Engine::handle_terminal_split_click(TerminalSplitHit) -> bool+ cachedTerminalSplitLayout— terminal split divider detection, pane focus, and selection via quadrauihit_test()(#430, quadraui#196). Both backends cache split layout frombuild_terminal_draw_data(). Zero per-backend divider math.quadraui::AppShell+engine::sidebar— sidebar visibility and active panel owned by the engine (#385). TUI reads all state fromengine.app_shell; panel switching, focus flags, and session persistence handled by engine methods (toggle_sidebar_panel,focus_sidebar_panel,handle_nav_overflow). GTKsync_sidebar_from_engine()reads engine state;sync_sidebar_widgets()updates GTK widget visibility viaactive_panel_id: String+ lookup-table arrays (#408/#409 removedSidebarPanelenum). ExtPanel panels bypass AppShell —sync_sidebar_from_engine()checksext_panel_active(#413).
North-star ("developer doesn't need to know the backend") status after B.5:
- ✅ True for picker / status-bar / tree / dialog / context-menu / tooltip-shaped surfaces — adding a new instance means writing data + handlers, never touching Pango/cells.
- ✅ True for rich-document popups since #214 shipped + #266 lifted both rasterisers — adding new rich popups means writing a
RichTextDocumentand handlers, never touching Pango/cells. ⚠️ Hit-test glue partially shared (#210/#344) — screen-level zone detection (tab bar, window, divider, breadcrumb) and window sub-zone detection (gutter, status bar, scrollbar, text area) now shared viarender::screen_zone_hit_test+window_zone_hit_test. GTK caches ScreenLayout from paint (#344). Remaining per-backend: motion-handler →selected_idxwiring for primitive surfaces (#210), tab bar inner slot resolution (Pango vs char-cell).- ❌ No
Backend::watch_file(path) -> Stream<FileEvent>trait method — every backend rolls its own watcher (TUI poll, GTK GIO). Suppress decision is shared (#201) but not the watcher invocation. - ✅ Editor viewport lifted (Phase C Stage 1 / #276). Both backends paint through
quadraui::{tui,gtk}::draw_editor. The vim-motion-suite vision (PLAN.md) is now unblocked at the paint layer; engine-slice extraction (Phase 2 —editor_corecrate carving outkeys.rs+ buffer + LSP) remains as a separate multi-month wave. - ⏭️ Win-GUI removed from this repo on 2026-05-11 (
3e4bcff). Will be re-added as a thin wrapper when quadraui ships its Win backend (quadraui#19–#31, quadraui#580). TheWin-GUI:issues still open on this tracker describe that deleted backend — migrate or close them (see Milestone hygiene above).
Sessions 389 and earlier in SESSION_HISTORY.md.
2026-09-04 — #801: / and :s got a real regex engine. New
src/core/vim_regex.rs translates Vim patterns (all four magic levels, \</\>,
\{n,m}/\{-}, \zs/\ze, \c/\C, the character classes, ~) into Rust
regex, and rejects what it cannot express instead of falling back to literal
matching. run_search and :s both use it; search offsets (/pat/e, /e+1, /b+2,
/+1), ; chaining, // reuse and 3/pat all work; */# now set a real
\<word\> pattern. parse_ex_address/parse_ex_range implement the full ex address
grammar, which :s, :g/:v, :d, :y, :j, :>, :<, :t, :m and :normal
now all accept. :s gained replacement expansion (& \0 \1 \u \U \L \E \r \t),
the g c e i I n & flags (c errors rather than being silently dropped), :&/:&&,
counts and | chaining. KNOWN_DEVIATIONS 638 → 465 (−173): the search, sub
and g conformance categories are clean apart from operator-pending d/pat (the next
issue in the #801 chain), gd/gn, and \1 back-references.
2026-09-03 — the chain drained; #7 closed out; the audit run. #751–#756 converged
mouse routing, #757–#762 keyboard dispatch, #763–#766 frame composition (FrameOp /
compose_frame, then the deletion of draw_frame). #657 promoted render/tui_main/
gtk into [lib] vimcode_core and sealed tests/acceptance/. #730/#593/#731/#732/#658/
#480/#550/#551 all closed; #146 moved to #4. Milestone #7 reached 0 open. Ran the
post-#735 sizing audit the previous revision mandated and added scripts/prod_lines.py
so it is reproducible: backends −3,656 against a −8,700…−9,500 projection, render.rs
+6,396, net +2,740. #47 closed having shipped no code (44882e9) with its
Backend-trait Rc-handle blocker filed nowhere — the top open action. (Corrected
2026-09-05, issue #827: that blocker — quadraui#699, at 19 not 44 call sites — was
filed and closed the same day, 16:38Z–17:11Z, and #47 was reopened 16:38Z. This
entry's "filed nowhere" was already wrong by the time the revision carrying it was
written; see the corrected section above.)
2026-09-05 — GOALS.md/PLAN.md/PROJECT_STATE.md/IRREDUCIBLE_SURFACE.md corrected
(#827). A four-agent audit of develop @ ee26268 found the planning docs
materially stale: the #47-blocker-unfiled claim (quadraui#699 had already closed),
the 44-call-site figure (real count 19), the quadraui#481/#482 "duplication moved
down a level" claims (mostly refuted at the pinned rev), the src/gtk/ size-table
column (predated #785's move), and the IRREDUCIBLE_SURFACE.md folder-picker
verdict (wrong — FolderPickerController has existed in quadraui since 05-25).
Corrected all four docs; no code changed.
2026-09-01 — platform-neutrality audit, and everything it found is now queued.
Filed #730 (ai_panel), #731 (orphan handles), #732 (Msg bus), #733 (mouse routers),
#734 (keyboard), #735 (frame composition). Re-scoped #593 (unblocked, GtkDriver
supersedes its smoke plan), #657 (audit run and recorded, fixture list corrected, freeze
contradiction flagged) and #47 (macOS: thin wrapper, not Core Graphics). Moved #146 out
of #7. Queued all of it plus quadraui#596/#597 — 16 entries, two parallel chains. #592
given an audit comment and deliberately left open on ai_panel. Docs: PRs #729
(PROJECT_STATE + PLAN) and #736 (GOALS).
2026-08-26 → 09-01 — the #592 epic and the dedup sweep cleared. #669/#670/#671/#672
(GTK live-path paint + draw.rs deletion), #676 (Command Center), #673/#674/#677 (tab
MRU, jump-list pane identity, vacuous-test rewrites), #621/#659/#660/#536 (dedup),
#691 (quadraui pinned as a git rev instead of a sibling path dep), #693/#694/#695
(menu-bar paint + hamburger), #699–#705 (VS Code chrome-metrics parity), #35 (minimap
primitive, both backends), #710/#712 (omnibar + dropdown fonts), #715/#716/#719/#720
(WM identity, titlebar glyphs, app icon), #722/#723 (per-pane minimap, scroll thumb).
2026-08-26 — both ShellApp migrations closed. #448 (GTK) and #595 (TUI).
fn event_loop deleted from src/ (#634).