Skip to content

fix(menubar): keep every enabled provider's ring, refetch stale quota windows - #56

Merged
MisterBrookT merged 1 commit into
mainfrom
fix/menubar-provider-rings
Aug 31, 2026
Merged

MisterBrookT merged 1 commit into
mainfrom
fix/menubar-provider-rings

Conversation

@MisterBrookT

Copy link
Copy Markdown
Owner

What

  • Menubar ranking no longer drops providers without quota data. QuotaStore.mostConstrained(in:count:) → menuBarOrder(in:count:): score is max(5h, 7d), no-data providers sort last and render an empty track. Enabling a provider is an explicit request to see it.
  • quota.py: a cached limits snapshot is now invalid once any of its own *_resets_at has passed. Claude's TTL is 3600s but its 5-hour window resets inside that hour — the stale-but-'fresh' cache was scrubbed by _scrub_expired, so Claude reported no 5-hour usage for up to an hour after every reset.
  • Version 0.9.3 (build 35).

Symptom

Two providers enabled (claude, codex), only the Codex ring drawn.

Verification

  • swift test: 157 passed, 0 failures. QuotaStoreTests rewritten for the no-drop contract (no-data kept and ordered last, input order preserved among no-data, max-of-both-windows, bounds).
  • python3 Resources/quota.py --json now returns five_hour_used_percent: 2.0 alongside seven_day_used_percent: 8.0 for claude; cache file refreshed.
  • Installed build: kaji state shows claude fiveHourPercent: 2, weekPercent: 8; menubar screenshot shows both rings.

… windows

An enabled provider disappeared from the menubar whenever its quota
percentages were missing: the menubar ranking filtered on
`fiveHourPercent != nil`. Enabling a provider is an explicit request to
see it, so ranking now keeps every visible provider — score is the worse
of the 5h/7d windows, no-data providers sort last and render an empty
track. `mostConstrained(in:count:)` becomes `menuBarOrder(in:count:)`;
the unused `store.mostConstrained` property is removed.

The missing data was itself a bug. `quota.py` caches Claude's limits for
an hour, but its 5-hour window can reset inside that hour: the cache
still counted as fresh, `_scrub_expired` then dropped the expired
window, and Claude reported no 5-hour usage for up to a full TTL after
every reset. A cached snapshot is now treated as a miss once any of its
own `*_resets_at` has passed, so the next poll refetches.

Bump to 0.9.3 (build 35).
@MisterBrookT
MisterBrookT merged commit efcf022 into main Aug 31, 2026
2 checks passed
@MisterBrookT
MisterBrookT deleted the fix/menubar-provider-rings branch August 31, 2026 09:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant