Dependency upgrade (ESLint 9 / Vite 8 / Vitest 4 / TS 6 / Prettier 3) + react-hooks v7 fixes + autostart Run-key fix (0.0.49) - #54
Merged
Conversation
Refresh Cargo.lock within semver: tauri 2.11.2->2.11.5, tray-icon, openssl, time, wasm-bindgen and ~50 transitive patch/minor bumps. cargo test + clippy green. auto-launch stays 0.5.0 (pinned by tauri-plugin-autostart 2.5.1). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…Vitest 4, TS 6, Prettier 3) Upgrade all client dependencies to their latest usable majors and satisfy the newer lint/type rules. npm audit: 0 vulnerabilities (was 7). Dependencies: - eslint 8->9 with a flat config (eslint.config.js; .eslintrc.cjs + .eslintignore removed). eslint 10 is blocked ecosystem-wide by eslint-plugin-react / typescript-eslint peers. Switch @typescript-eslint/* to the typescript-eslint umbrella; add @eslint/js + globals. - vite 5->8, @vitejs/plugin-react 4->6, vitest 2->4, @vitest/coverage-v8 2->4, happy-dom 15->20, typescript 5.3->6, prettier 2->3, plus in-range bumps. - Add explicit vite-node (dropped by vitest 4; needed by gen:docs/check:docs). - Add "node" to tsconfig types (was provided transitively before the bump). react-hooks (React Compiler rules) - fix all 115 flagged sites, behavior-preserving: - latest-ref writes (ref.current = x during render) -> commit effects - effect sync-to-prop setState -> store-previous render-phase guard - purity (Date.now/Math.random in render) -> lazy init / effect - immutability + preserve-manual-memoization -> dep-array & restructure fixes - Canvas.tsx ref-sync effect: 8 immutability sites use a scoped, documented disable - a latest-ref mirror cannot satisfy both refs and immutability, and this project does not run the React Compiler. Test fixes for the upgrades: - happy-dom 20 dropped window.prompt/confirm/alert -> stub in test-setup - vitest 4 Mock<Procedure|Constructable> typing (BackgroundPanel, llm/source) - TS 6 startViewTransition DOM type (viewTransition) - downshift 9.4 combobox: open the sensor field by role, not the shared caret Prettier 3 reformat across the tree. All gates green: check, lint (0 warnings), 2762 unit tests, build, check:docs, 34 e2e. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… login
auto-launch 0.5.0's enable() formats the HKCU\...\Run value as
format!("{} {}", path, args.join(" ")); with our empty args that yields an
unquoted path plus a trailing space (C:\...\widgetsack.exe ). Windows' logon
Run-key launcher silently refuses that malformed command, so the app never
autostarted even though the toggle, the durable HKCU pref, and Task Manager's
StartupApproved list all reported it enabled -- the plugin's is_enabled() only
checks that the value exists, not its content.
Write the Run value ourselves (enable_autostart): quoted so an install path
with spaces still launches, and trailing-space-free, mirroring the
StartupApproved "enabled" marker. reconcile() and set_autostart_enabled() use it
for the enable path; the plugin's read/disable paths are unchanged. Add a
run_command() pure seam with regression tests.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Autostart Run-key fix + full dependency upgrade (Rust cargo update; client toolchain to ESLint 9 flat config / Vite 8 / Vitest 4 / TS 6 / Prettier 3, happy-dom 20, 0 vulnerabilities) + all 115 react-hooks (React Compiler) rule fixes. Gates: cargo test+clippy, tsc, eslint(0), 2762 unit, build, check:docs, 34 e2e. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
gyng
added a commit
that referenced
this pull request
Jul 9, 2026
- typescript 6.0.3 -> 7.0.2 (native compiler): zero code changes needed; tsc --noEmit drops from ~8.0s to ~1.7s (fast mode; a bimodal ~6.3s mode — suspected Defender scanning the native binary — still beats TS6). - typescript-eslint has no TS7 support (peer <6.1.0, crashes on the changed API), so lint moves to oxlint 1.73 (.oxlintrc.json): typescript/unicorn/oxc/ react plugins, correctness category + explicit overrides mirroring the old recommended tiers. Zero-warnings gate unchanged (--max-warnings=0). Must-keeps preserved: typescript/no-explicit-any, react/rules-of-hooks, react/exhaustive-deps. KNOWN COVERAGE LOSS: 14 of 16 react-hooks v7 (React-Compiler-era) rules have no oxlint equivalent yet — the #54 fixes stay in code but are no longer machine-enforced. Also lost: react/prop-types (moot under TS), react/no-deprecated. - Formatting moves from Prettier to oxfmt 0.58 (.oxfmtrc.json via --migrate=prettier: tabs, single quotes, no trailing commas, width 100). Covers TS/TSX/JS/JSX/CSS/JSON/MD/HTML — no lost coverage; the one-time reformat touched 4 files, whitespace-only. - eslint-disable comments renamed to oxlint-disable (tool-assisted, 11 files); legacy @typescript-eslint/* rule names inside them still resolve. A handful of newly-surfaced correctness findings fixed (useless spread fallbacks, new Array(n) holes, unsafe ?. in tests). - Removed devDeps: eslint, @eslint/js, typescript-eslint, eslint-plugin-react, eslint-plugin-react-hooks, eslint-config-prettier, globals, prettier. - AGENTS.md formatting/linting section updated. Gates: tsc clean, oxfmt+oxlint clean, 2768 unit tests, build, check:docs, 34 Playwright e2e. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
gyng
added a commit
that referenced
this pull request
Jul 9, 2026
…int/oxfmt (0.0.50) (#55) * fix(keepalive): survive zero windows — prevent last-window exit + respawn main widgetsack is a tray app, but Tauri's default exits the process when the last window closes. Zero windows is reachable BY DESIGN: an empty-primary `main` self-destructs to reclaim its renderer (overlay.ts setMainWindowVisible), so a layout whose widgets all sit on one secondary monitor lives on a single overlay window — and any transient failure to spawn it (monitor not yet enumerated at logon, WebView2 hiccup, monitor DDC-switched away) silently ended the process. This was the "didn't autostart" failure of 2026-07-10. - keepalive.rs (new): should_prevent_exit pure seam (+tests); on_zero_windows schedules a rate-limited (30s) respawn of the hidden `main`, whose own Canvas init re-runs the reconcile cycle — spawning overlays for whatever monitors exist NOW, then self-destroying again if the primary is still empty. Retries pace themselves off the event cycle (no polling); one attempt in flight; self-reschedules if window creation itself fails. - main.rs: .run(context) → .build(context).run(handler); ExitRequested with code None is prevented. Tray Quit (app.exit(0) → code Some(0)) still exits. - command.rs: respawn_main_hidden made pub(crate) + a `reason` log tag shared by the layout-watcher and keepalive recovery paths. Runtime-verified with a debug --multi instance on a layout whose only populated monitor key matches no connected display: the app survives repeated zero-window cycles (keepalive → respawn → self-destroy) and recovers the overlay as soon as the layout regains a real monitor. cargo test (200 incl. 2 new), clippy, fmt all clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(reliability): overlay/log hardening + instant display recovery (0.0.50) Follow-ups to the zero-window keepalive, from the post-incident review: - log_client command (command.rs) + overlay.ts logClient helper: overlay lifecycle failures (reconcile, spawn, self-fit, main destroy/recreate) now land in the persistent rotating log file as target "client" instead of dying with the webview console — the 2026-07-10 postmortem cost hours because these paths were console-only. - populatedMonitorKeys returns null on a load_layout/parse failure and reconcileOverlays skips the pass entirely — "couldn't read the layout" is no longer treated as "layout is empty" (which closed every working overlay on a transient IPC hiccup). - reconcileOverlays is single-flight with a trailing rerun (new pure core/singleFlight.ts + tests): concurrent passes (init, layout_changed, topology watcher) no longer race to create the same overlay label. - displaywatch.rs: hidden-window WM_DISPLAYCHANGE watcher respawns `main` the moment a monitor returns while the app is at zero windows — instant recovery instead of keepalive's 30s retry. (Deliberately a hidden top-level window, not HWND_MESSAGE: message-only windows don't receive broadcast messages.) - GSMTC SessionManager failure now degrades gracefully (media disabled, app starts) instead of a startup .expect crash; the rx consumer became `while let` so a closed channel can't hot-spin. - cargo update (24 crates within semver; no tauri/wry/softbuffer bumps were available — the upstream softbuffer !dc.is_null() panic remains open). - Version 0.0.50. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * chore(toolchain): TypeScript 7 + oxlint/oxfmt replace eslint+prettier - typescript 6.0.3 -> 7.0.2 (native compiler): zero code changes needed; tsc --noEmit drops from ~8.0s to ~1.7s (fast mode; a bimodal ~6.3s mode — suspected Defender scanning the native binary — still beats TS6). - typescript-eslint has no TS7 support (peer <6.1.0, crashes on the changed API), so lint moves to oxlint 1.73 (.oxlintrc.json): typescript/unicorn/oxc/ react plugins, correctness category + explicit overrides mirroring the old recommended tiers. Zero-warnings gate unchanged (--max-warnings=0). Must-keeps preserved: typescript/no-explicit-any, react/rules-of-hooks, react/exhaustive-deps. KNOWN COVERAGE LOSS: 14 of 16 react-hooks v7 (React-Compiler-era) rules have no oxlint equivalent yet — the #54 fixes stay in code but are no longer machine-enforced. Also lost: react/prop-types (moot under TS), react/no-deprecated. - Formatting moves from Prettier to oxfmt 0.58 (.oxfmtrc.json via --migrate=prettier: tabs, single quotes, no trailing commas, width 100). Covers TS/TSX/JS/JSX/CSS/JSON/MD/HTML — no lost coverage; the one-time reformat touched 4 files, whitespace-only. - eslint-disable comments renamed to oxlint-disable (tool-assisted, 11 files); legacy @typescript-eslint/* rule names inside them still resolve. A handful of newly-surfaced correctness findings fixed (useless spread fallbacks, new Array(n) holes, unsafe ?. in tests). - Removed devDeps: eslint, @eslint/js, typescript-eslint, eslint-plugin-react, eslint-plugin-react-hooks, eslint-config-prettier, globals, prettier. - AGENTS.md formatting/linting section updated. Gates: tsc clean, oxfmt+oxlint clean, 2768 unit tests, build, check:docs, 34 Playwright e2e. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
gyng
added a commit
that referenced
this pull request
Jul 9, 2026
Conflict resolution notes: - NowPlaying.tsx was binary-diffed on BOTH sides: the trackKey line embedded literal NUL (0x00) separator bytes in the source. Converted them to the \0 escape sequence (identical string value) so the file is text again and future merges work. - Re-expressed the branch's hasMedia fix in main''s post-#54 (react-hooks v7) structure: the layer-drop lives in the adjust-during-render (now keyed on hasSession && hasMedia), the crossfade effect early-outs via a commit-effect-written hasMediaRef (deps stay [artKey, hasSession]), and the thumb stack renders only while a track is present. - The branch''s regression test passes against the adaptation (2769 unit tests). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
gyng
added a commit
that referenced
this pull request
Jul 9, 2026
…#57) Coverage had slid to 97.69/93.45/96.39/98.89 unnoticed (Vitest 2->4 remap changes in #54 plus untested-code drift) because CI ran test:unit, never the thresholds. This restores it above the original v0.0.48 baseline and makes regression impossible to miss: - ~400 new tests across 5 parallel clusters (Inspector/editor panels, meters, plugins+llm+formula, lib/core, canvas+widgets misc): 2769 -> 3151 tests. Inspector.tsx alone went 81.1% -> 99.7% stmts. All test-only; no source changes, no coverage-ignore pragmas (standing policy). Residue is documented unreachable defensive arms / library-internal branches, each justified in the PR notes. - CI client job now runs test:coverage instead of test:unit, so the vite.config ratchet gates every PR. - Thresholds re-ratcheted: statements 99->99.25, lines 99->99.5, functions 96->99.5, branches 95->98.5 (~0.4pp slack for cross-platform v8 remap jitter). - Also hardened one pre-existing flaky test (MonitorSourcesEditor rescan raced a disabled button under parallel load). Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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.
Consolidated release branch for 0.0.49. Three areas, each independently verified; all gates green.
1. Autostart Run-key fix
auto-launch0.5.0 wrote the…\Run\widgetsackvalue as a bare, unquoted path plus a trailing space (C:\…\widgetsack.exe), which Windows' logon launcher silently refuses to execute — so the app never started at login even though the toggle, the durable pref, and Task Manager all reported it enabled. We now write the Run value ourselves (quoted, no trailing space), with a purerun_command()seam + regression tests.2. Full dependency upgrade
cargo update(tauri 2.11.2→2.11.5 + ~50 transitive bumps).eslint-plugin-react/typescript-eslintpeers), Vite 5→8, Vitest 2→4, TypeScript 5.3→6, Prettier 2→3, happy-dom 15→20,@vitejs/plugin-react4→6, plus in-range bumps. Switched to thetypescript-eslintumbrella; added@eslint/js,globals, and an explicitvite-node(dropped by vitest 4). npm audit: 0 vulnerabilities (was 7).Mocktyping, TS 6startViewTransitiontype,@types/node, downshift 9.4 combobox query.3. react-hooks v7 (React Compiler) rules — all 115 sites fixed
Behavior-preserving: latest-ref writes → commit effects; effect sync-to-prop → store-previous render-phase guard; purity → lazy init/effect; immutability/memoization → dep-array & restructure. Canvas.tsx's ref-sync effect keeps 8 immutability sites under a scoped, documented disable (a latest-ref mirror can't satisfy both
refsandimmutability, and we don't run the compiler).Verification
cargo test+cargo clippy·tsc·eslint .(0) · Prettier · 2762 unit tests ·vite build·check:docs· 34 Playwright e2e.🤖 Generated with Claude Code