feat(desktop): port tray/Tauri integration onto the client/server settings model - #216
Conversation
| impl Default for FoundryInstallActionArgs { | ||
| fn default() -> Self { | ||
| Self { approved: false } | ||
| } | ||
| } |
| impl Default for FoundryInstallActionArgs { | ||
| fn default() -> Self { | ||
| Self { approved: false } | ||
| } | ||
| } |
| }; | ||
| let json = serde_json::to_string(&status).unwrap(); | ||
| let back: FoundryLocalStatus = serde_json::from_str(&json).unwrap(); | ||
| assert_eq!(back.cli_found, true); |
| let json = serde_json::to_string(&status).unwrap(); | ||
| let back: FoundryLocalStatus = serde_json::from_str(&json).unwrap(); | ||
| assert_eq!(back.cli_found, true); | ||
| assert_eq!(back.service_running, false); |
…erShell; retire host-tray.rs - NotificationBackend::PowerShell renamed to Native (serde alias keeps reading settings persisted under the old name) — the actual toast delivery is being replaced with native windows-rs calls in ledgerr-host, this crate only owns the shared data types. - SettingsStore::with_backend(path, backend) added alongside new(), so tests can construct an isolated JsonFileBackend directly instead of going through Windows registry auto-selection — new()'s registry backend ignores its path argument entirely and always targets one fixed production key, which is correct for real callers but means any test using new() over a tempdir shares that one global mutable key with every other test and any real running instance. - crates/ledgerr-host/src/bin/host-tray.rs moved to src/bin/legacy/ as reference-only (git mv staged this alongside the above; it's the first step of retiring the standalone host-tray.exe binary — completed in the following commits, which remove its [[bin]] entry and repoint host-tauri's tray at the same shared runtime it used).
…le host-tray refs settings_server.rs's tests hit the same registry-auto-selection issue fixed in ledgrrr-settings — repoint them at SettingsStore::with_backend + JsonFileBackend explicitly. status.rs/service_control.rs still listed host-tray as a tray-binary candidate; it's being retired in favor of host-tauri.exe, which already sorts first in that list.
…ndows-rs toasts The tray's toast notifications shelled out to powershell.exe running Import-Module BurntToast; New-BurntToastNotification — requiring a separately-installed PowerShell module on every machine. A native windows::UI::Notifications-based ToastNotifier already existed in this crate (notification::windows_toast) but was never wired into the tray's actual notification path — only its own unused tests exercised it. Added notify::native::NativeToastNotifier, implementing the same notify::types::Notifier trait the tray already consumes, wrapping that existing native implementation (and the stderr fallback on non-Windows) instead of shelling out to any external process.
…ubmenu native.rs: drop the unused push_check helper, DYNAMIC_TEXT_IDS and CHECK_ITEM_IDS constants, and fix a few compiler-flagged unused-mut/ unused-must-use warnings. Group the four notification-event toggles (approval/submitted/failed/ completed) into a "Notify me for" submenu instead of sitting flat among the other 10 top-level menu items — cuts the flat menu from 14 items to 11 and keeps the related settings together.
… down settings service Ports this session's earlier work (originally built against a SettingsStore this branch predates) onto the client/server settings architecture already on main (SettingsClient, ledgrrr-service): - TrayCommand::ShowWindow's action is now an injected closure instead of a hardcoded spawn of a separate process, so the same run()/ handle_command can be reused by host-tauri (which shows its own webview) without any dependency on a standalone binary. - Collapsed 7 near-identical toggle handlers into negate()/ apply_toggle() helpers. - Any single command's error (most realistically: ledgrrr-service isn't running yet) is now logged and the loop continues, instead of propagating via `?` out of run() and killing the whole tray — and, via host-tauri's exit-on-return, the whole app — over a transient failure. Only an explicit Quit ends the loop. - run()'s own initial settings load falls back to defaults on failure instead of erroring out before ever creating the tray icon at all — confirmed live: with no settings service running, the tray now still appears (previously it silently never initialized). - NotificationBackend::PowerShell -> Native throughout.
…ost-tray.exe Replaces the minimal Show/Exit-only stub with the shared tray::runtime::run(), injecting "show/unminimize/focus the Tauri webview" as the window-show action. host-tauri now has the full toggle/notification/toast menu that was previously only in the standalone host-tray.exe, fixing the toast-notifications-never-wired-up bug on the main app's tray. Also: main.rs's window-visibility check and enable_tray check both silently fell back to unhelpful defaults (or, for enable_tray, silently skipped tray setup entirely) whenever the settings load failed — exactly the case when ledgrrr-service isn't running yet. Both now log and use an explicit, sensible default (visible; tray enabled) instead.
Removes its [[bin]] entry now that host-tauri.exe has full feature parity (previous commit). Source stays at src/bin/legacy/host-tray.rs for reference; it no longer compiles as part of any normal build.
host-tray no longer exists as a build target (previous commit).
PR #187 (spike/sysml-v2-parser-roundtrip) found holon-viz's SysmlV2Emitter produced invalid SysML v2 (comment-swallowed closing brace, `block def` instead of `part def`). Both bugs were independently fixed on main in PR #183 (c106a5e) before this doc landed. Cherry-picks only the investigation doc; the throwaway sysml-v2-parser-spike crate stays on the closed PR's branch since its regression test now asserts stale (pre-fix) behavior.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015kUr7Kf9wN15TPqDiKsiKw
…, not this repo's own MSIX)
1176a46 to
1cac1be
Compare
This PR's own with_backend()/JsonFileBackend fix for the registry-leak issue (SettingsStore::new's Windows registry backend ignores its path arg and always targets one fixed production key) landed in ledgrrr-settings and ledgerr-desktop-agent, but missed 3 test files in ledgerr-host itself — the crate that actually owns the tray's real SettingsStore usage: - tests/settings_roundtrip.rs (5 tests) - tests/settings_atomicity.rs (2 tests) - tests/tray_wiring_smoke.rs (tray_enable_roundtrips_through_store) On a real Windows box these all still called SettingsStore::new(tempdir) directly, silently opening the one production registry key instead of an isolated per-test backend — the exact corruption/cross-contamination bug this PR claims to have fixed elsewhere, and in the worst case (tray_enable_roundtrips_through_store) capable of writing enable_tray: false into a real running host-tauri.exe's live settings from `cargo test`. CI never caught it: the only Windows job runs a packaging smoke test, not `cargo test`, and on Linux the registry backend is compiled out entirely so these pass cleanly via the (correctly path-scoped) JsonFileBackend fallback regardless. Applied the same with_backend(path, JsonFileBackend::new(path)) pattern already used in ledgrrr-settings/src/store.rs and ledgerr-desktop-agent/src/settings_server.rs. Verified: cargo test -p ledgerr-host --tests — 112 passed, 0 failed.
|
Reviewed and pushed a fix directly to this branch (commit a10e402) — not merging yet, pending CI on the fixed commit and your own pass over the follow-up notes below. Fixed: this PR's own registry-key test-isolation fix ( Separately: this branch was also stale (based on a pre-Containerfile-fix Confirmed working, no changes needed:
Not fixed — worth a follow-up issue, not a blocker:
Please re-check CI on the new head commit before merging. |
- Restore docs/superpowers/specs/2026-08-29-tray-tauri-integration-design.md and its companion plan doc from the superseded feat/windows-desktop-dogfood branch — Justfile referenced the spec doc, but it was never ported when this branch superseded that one. Retrieved verbatim, status line updated to note the branch handoff. - Add invoke_reports_blocked_on_non_windows_even_when_approved, gated #[cfg(not(windows))] — exercises the untested !plan.executable_now branch in foundry_install_plan.rs::invoke() on non-Windows CI targets. Deliberately excluded from Windows builds: on Windows, executable_now is always true, so calling invoke(approved: true) there would reach the real winget-spawning code path as a side effect of running the test suite — the existing invoke_without_approval_never_launches test already covers the approval gate safely on every target.
…-store + foundry_install_plan conflicts - crates/ledgrrr-settings/src/store.rs: this branch and #234 (already merged) independently fixed the same bug (SettingsStore::new's Windows registry backend ignoring its path argument in tests) with different APIs -- this branch's with_backend(path, backend) and #234's new_json_file(path). Kept both: with_backend stays the general primitive (used as-is by 4 other test call sites in this branch), new_json_file is now a thin wrapper around it, so neither PR's capability is lost. - crates/ledgerr-desktop-agent/src/foundry_install_plan.rs: add/add conflict from divergent history (this branch and #235, also merged, each added the file); both sides already had identical content including the same non-Windows-only test, so no real merge was needed.
Summary
Supersedes PR #213 (closed in favor of this one — #213 was built against a pre-client/server
SettingsStoresnapshot ofmainand doesn't apply cleanly on top of the settings-service refactor that landed independently while that work was in progress).Same functional goal as #213 —
host-tauri.exe's Windows tray previously had no toast/notification support at all (a minimal Show/Exit-only stub), while a separate standalonehost-tray.exehad the full feature set but no integration with the main app. This ports that consolidation onto theSettingsClient/ledgrrr-servicearchitecture already onmain.host-tauri.exe's Windows tray through the same shared, testedtray::runtime::run()the standalone tray used, now taking aSettingsClient— gives it the full toggle/notification/toast menu, fixing the reported "toast notifications don't work" bugwindows-rstoast implementation (notify::native::NativeToastNotifier, wrapping the already-present but previously-unwirednotification::windows_toast::ToastNotifier) — no external process, no module install required.NotificationBackend::PowerShellrenamed toNative(serde alias preserves settings persisted under the old name)host-tray.exeas a build target (source kept undersrc/bin/legacy/for reference;host-window.exe/Slint were already retired onmainvia refactor(ledgerr-host): remove legacy Slint host #174)SW_SHOWvsSW_RESTORE)ledgrrr-servicenot running (the realistic first-launch state), the app previously either defaulted the main window to hidden/inert states or — worse — silently skipped tray setup entirely, so no tray icon ever appeared. Bothmain.rs's window-visibility check and itsenable_traycheck now log and fall back to a sensible default (visible; tray enabled) instead. Verified live: tray icon now appears with the settings service fully down.ledgrrr-settings,ledgerr-desktop-agent):SettingsStore::new()'s Windows registry backend ignores itspathargument and always targets one fixed production key — correct for real callers, but meant every test using a tempdir path shared that one global mutable key. AddedSettingsStore::with_backend()so tests can inject an isolatedJsonFileBackendexplicitly.Test plan
cargo test -p ledgerr-host -p ledgrrr-settings --lib --tests --bins— 95 passing. 2 known pre-existing failures inchat_tools(Windows-path-in-TOML escaping bug tied to this machine's username) confirmed to fail identically on a clean, unmodifiedmain— not introduced by this branch.host-tauri.exewithledgrrr-servicenot running: main window appears (visible-by-default fallback), tray icon appears (L3dg3rrTrayWindowconfirmed via window enumeration) with the full menu, not just Show/ExitBurntToastmodule confirmed not installed on the validation machine;notify-test.exe --backend nativereturns a real"status": "ready"/"message": "toast sent"result via the nativewindows::UI::NotificationsAPI🤖 Generated with a build+review process (implementation, live validation against a running host-tauri.exe, iterative fixes based on what that surfaced).
https://claude.ai/code/session_015kUr7Kf9wN15TPqDiKsiKw