Repository navigation
fix(g6): hidden windows stop rendering; judge leaves VRAM between cycles; DB budget - #967
Merged
Merged
Conversation
runyourempire
force-pushed
the
fix/g6-idle-cpu
branch
from
October 16, 2026 22:24
2663a13 to
92fb060
Compare
…les; DB budget Idle CPU: Tauri's hide() and minimise hide only the native window; wry never sets the WebView2 controller's IsVisible to false. The pre-warmed toast and brief windows, once shown and hidden again, kept visibilityState "visible", requestAnimationFrame at the display rate and their infinite animations (toast dot-pulse, brief pulse-opacity) running. New webview_visibility plugin subclasses each host window and mirrors WM_SHOWWINDOW / minimise / restore into controller.SetIsVisible, so every hide path (toast and brief timers, close-to-tray, minimise) stops rendering and document.hidden now tells the truth. Judge VRAM: keep_alive 30m -> 5m (bridges the lanes of one cycle, never two cycles), and the cycle's last judge lane (verdict drain) unloads the routed local judge. A user-set OLLAMA_KEEP_ALIVE or an Ollama main model is left alone. G6 DB budget: 500 MiB for the projected steady state at default retention with every interest off (stack sources only), decided on the high end of the projection. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018hjX3pEMmC7CHfG41PiPj7
…l toast, JS-driven hides - release_after_cycle unloads only a judge 4DA routed itself (never an Ollama main model), never while a judge lane of this process runs (LaneGuard from refresh_if_stale), never when OLLAMA_KEEP_ALIVE is set (reuses llm::ollama_keep_alive_for). - A reload inside a timed judge call (another process unloaded the model after this lane's warm-up) is subtracted from the call's time using Ollama's load_duration, so it cannot trip SLOW_CALL. - CriticalAlertBanner: delete the document.hidden -> new Notification effect. It was dead while document.hidden was always false and would now fire an ungated duplicate of the Rust critical toast, which already goes through the interruption gate. - Toast and brief windows: the page's own script ends every showing (hover pause, exit animation, then notification-hidden / briefing-hidden); the backend timer is a fallback (script + 60 s). - g6DbVerdict is pending without dbstat (non-item tables unmeasured). - A show of a minimised window keeps its webview asleep. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018hjX3pEMmC7CHfG41PiPj7
… toast fallback mirrors the page - release_target: a non-"ollama" provider (e.g. openai-compatible) pointed at the local Ollama whose model is the routed judge keeps it loaded (names compared trimmed, implicit :latest stripped). - Toast fallback hide: +60 s only once the page reported ready; a page that never loaded is hidden on the script's schedule + 400 ms. - Rust default toast duration mirrors notification.js (|| 4000, e.g. the flood path's "high"); the include_str! pin covers the default. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018hjX3pEMmC7CHfG41PiPj7
runyourempire
force-pushed
the
fix/g6-idle-cpu
branch
from
October 16, 2026 23:20
92fb060 to
423b7ab
Compare
runyourempire
enabled auto-merge
October 16, 2026 23:22
github-merge-queue
Bot
removed this pull request from the merge queue due to failed status checks
Oct 16, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Launch gate G6 (resources): idle CPU, judge VRAM, DB budget.
1. Hidden windows stop rendering (idle CPU root cause)
Tauri's
hide()and a minimise hide only the native window. wry sets the WebView2 controller'sIsVisibleonce, at creation, and never changes it on a window-level hide. Measured on a debug build after a toast and the desktop brief had been shown and hidden again:visibilityState "visible".requestAnimationFrameran at the display rate (241 fps)..priority-dot.alertdot-pulseand the brief's.synthesis-textpulse-opacity.eval_jsdropped both renderers to 0% and the GPU process to 0.05%.Fix: new
src-tauri/src/webview_visibility.rs, a plugin registered once inlib.rs.WM_SHOWWINDOWand minimise/restore intocontroller.SetIsVisible.document.hiddennow tells the truth, whichsrc/lib/motion-gate.tsalready assumed.visiblewhile on screen andhiddenwith 0 rAF frames once dismissed.2. Judge VRAM
OLLAMA_KEEP_ALIVEdrops from 30m to 5m. That is long enough to bridge the judge lanes of one cycle and shorter than the ~10 min between cycles. It applies to every 4DA request to Ollama (briefs, digests, search, judge lanes), not only the judge; 5m is also Ollama's own default.run_pending_verdict_drain, used by both the GUI scheduler and the headless engine) now unloads the routed local judge (local_judge::release_after_cycle).may_route_localis false, so nothing is released, tested), the model while any judge lane in this process is still running (aLaneGuardfromrefresh_if_stalecounts in-flight lanes, tested), and anything when the user setOLLAMA_KEEP_ALIVE(reusesllm::ollama_keep_alive_for).load_durationis subtracted from that call's time before the breaker judges it (local_judge::observe_load, tested), so a reload never tripsSLOW_CALL.local_judge::warmbefore each lane, outside the breaker's timing.3. G6 DB budget
G6_DB_BUDGET_BYTES= 500 MiB for the projected steady-state DB at default retention (30 days) with every interest off, i.e. stack sources only.STACK_SOURCESin the script is pinned by a test tosources/source_class.rs.4. Review fixes (round 2)
CriticalAlertBanner: deleted thedocument.hidden->new Notification(...)effect. It was dead whiledocument.hiddenwas always false; this PR would have made it live as an UNGATED native toast that duplicated the Rust critical toast. The Rust side already raises the critical toast through the interruption gate (monitoring_notifications->notification_window::dispatch, every threshold mode). No test covered the effect.notification-hidden/briefing-hiddenhides the window). The backend timer is a fallback only: toast = the script's duration + 60 s, brief = 300 s + 60 s. Before, the backend hid the toast on its own timer (4 s forwatchagainst the script's 6 s), cutting the exit animation and ignoring hover. Tests pin the Rust durations tonotification.js/briefing.js.visibilityState "hidden"with 0 animation frames afterwards.g6DbVerdictreturnspendingwhen dbstat was unavailable: without it the non-item tables count as 0 and a small interests-off projection could pass falsely (tested).webview_visibility: a show of a minimised window keeps the webview asleep (tested); comment on the one-webview-per-window subclass id.5. Review fixes (round 3)
release_targetalso never unloads the judge when it is the user's own configured model under a non-"ollama" provider (e.g.openai-compatiblepointed at the local Ollama): names compared trimmed, with an implicit:lateststripped (a_compatible_provider_on_the_same_local_model_is_never_unloaded).WINDOW_READY); a page that never loaded is hidden on the script's schedule + 400 ms, so it cannot leave an empty window up for a minute (tested).notification.js(DISMISS_DURATIONS[p] || 4000, e.g. the flood path's "high"); theinclude_str!pin covers the default and the exit delay.Measurements: release build, idle, % of one core
Measurement caveat: the "before" run had shown both a toast and the desktop brief. The "after" run showed two alert toasts (the
dot-pulsecase) but no brief: no morning brief fired during it, and a release build has no IPC bridge to trigger one. The brief case is covered by the debug-build causal check above, where both hidden windows were measured.Both runs used an isolated profile: identifier
com.4da.app.g6rel,FOURDA_DATA_DIRon a read-onlyVACUUM INTOcopy of the live DB, and LLM providernone. Each was 90 s on a visible, unfocused main window between engine cycles.pnpm run gatesG6: PENDING.gatesmeasures idle on a running app through the bridge, and these release numbers come from the isolated instance above.Checks
tsc --noEmitclean.check-file-sizes: warnings only.cargo fmtclean.cargo test --lib: 6262 passed, 1 failed. The failure issettings::secret_storage_tests::failed_hydration_then_save_never_deletes_or_overwrites_the_keychain, which passes 3/3 when run alone, so it looks like a parallel-run flake in shared test state. This PR does not touch that code.SignalsPanel.test.tsxandFirstRunTransition.test.tsxfailed to start at 100% CPU).Not in this PR
notification_clickedhides the window directly).@tauri-apps/api2.11 vstauri2.12; updater and opener plugins likewise). A localtauri buildneeds--ignore-version-mismatches. It is handled separately.🤖 Generated with Claude Code
https://claude.ai/code/session_018hjX3pEMmC7CHfG41PiPj7