Two causes, both dealt with.
A fresh QWebEngineView paints white, and _ensure_web put it on screen empty —
so on a dark theme that white rectangle sat there for the whole first scan.
It is now blanked to the app's own background colour the moment it is created,
before it is ever shown.
And the work itself moved off the click. MainWindow warms GraphRAG up 3s after
the window appears — building the browser view (~140ms) and the first graph
(~485ms) while nothing is waiting on them. Clicking GraphRAG then costs 78ms
with zero scans and zero setHtml calls, where before it was ~625ms of empty
view.
This spends the memory the lazy construction was saving, a few seconds after
startup rather than never — which is the trade you asked for. Startup itself is
untouched: the checker asserts neither the view nor the graph exists at the
moment the window opens.
check_graphrag_rescan now covers the warm-up too, and fails if it stops running.
24/24 checkers pass; check_combo_popup took a teardown segfault in the suite and
passed 3/3 standalone.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Measured what a visit costs: 140ms to construct the QWebEngineView the first
time, 485ms to walk the folder and lay the graph out, and a setHtml of the whole
D3 page to show it. The setHtml is the flash — the page really is reloaded.
Once built it is not repeated: three round trips in and out rescanned nothing.
What did repeat was project switching. _refresh_project_combo scanned
immediately on any change, and the rail's picker put that one click away from
every screen — so the graph was rebuilt again and again for a tab usually not on
screen, and the visit after a switch always paid for a reload.
It now marks _needs_scan and lets auto_scan_and_fit() pick it up when GraphRAG
is actually opened: two switches from Cowork cost 0 scans, and opening it after
costs exactly 1.
The first visit per run still builds the browser view and scans, which is the
lazy construction the code chose deliberately to keep startup light. That one is
a trade, not a bug; say if you would rather pay it at startup.
check_graphrag_rescan covers all three: no rebuild on an unchanged re-entry, no
scan while off-screen, exactly one on opening.
24/24 checkers pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>