* fix(usage): coalesce account-switch refreshes and harden malformed config values selectAccount queued Qt.callLater(refreshNow) after writing selectedAccounts, whose commandSource binding already fired scheduleUsageRefresh in single-provider mode. Qt.callLater coalesces only identical function references, so every account switch started one usage command and retired it immediately in favour of a second. Both paths now use scheduleUsageRefresh, which coalesces through the scheduled flag and still refreshes in multi-provider mode where the command does not change. Two untrusted-input guards relied on Number() coercion at their boundaries: ProviderDescriptor.normalize accepted schemaVersion values that merely coerce to 1 (true, "1", [1]), and QuotaThresholds.numericPercent turned whitespace, arrays, and Infinity into a 1% warning threshold or a clamped maximum - the exact corruption its comment says it prevents. Both now accept only the documented shapes, matching the descriptor contract's unknown-schema rule. Documentation impact: CHANGELOG Unreleased gained Fixed entries. Docs already describe both contracts correctly; no README, usage guide, or TODO change is needed, and no user-facing strings changed. * test(usage): verify account-switch refresh coalescing Exercise production account-selection functions and command bindings in the Qt event loop. The parent commit triggers two refreshes for single-provider selections; the fixed paths trigger one for cached and uncached accounts in both modes. Narrow threshold validation claims to unexpected helper inputs. Development and changelog agree; config, translations, CLI contracts, and TODO scope are unchanged.
9 files changedLine totals unavailable