feat(menubar): say whether a quota window lasts until its reset - #1287
Open
ozymandiashh wants to merge 1 commit into
Open
feat(menubar): say whether a quota window lasts until its reset#1287ozymandiashh wants to merge 1 commit into
ozymandiashh wants to merge 1 commit into
Conversation
The Plan tab has answered "am I going to make it?" since getagentseal#726/getagentseal#728, but the two surfaces people actually glance at — the Capacity Dock's window columns and the agent-tab quota hover card — still only said when the window resets, which is the one fact that does not answer the question. Both now draw one line under the bar, off the same projection: `Lasts until reset` while the linear projection lands at or under 100% at reset, `Runs out in 2d 8h` when it overflows on a window long enough for a whole-window rate to be defensible, and `Won't last until reset` when it overflows on a window of 6 hours or less, which keeps getagentseal#726's ETA suppression rather than crying wolf over one burst. It stays silent in the first 3% of a window, on an exhausted window, without a reset time, and on clock skew — the same guards `QuotaPace.evaluate` already has, which stays the only pace math in the app. `QuotaSummary.Window` carries no window length, so rather than thread one through ~15 adapter call sites the length is inferred from the normalized label the adapters already derive from the exact API duration ("Weekly", "5-hour", "Weekly · Opus", "Monthly usage limit"). Calendar months are measured back from the reset date in UTC, mirroring how the Codex spend window is derived; a label that implies no length keeps the row silent rather than guessing one. The dock reserves the line's height whether or not a column has a verdict, because the glance panel's frame is computed rather than fitted: a projection crossing in or out of silence must not resize the bubble under the pointer. The hover card is fitted, so there the line collapses. Closes getagentseal#1215
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
Lasts until reset,Runs out in 2d 8h, orWon't last until reseton windows of 6 hours or less, where a linear run-out ETA is not defensible.QuotaPace.evaluatestays the only pace math in the app, and this is a(text, willOverflow)reduction of its result — so the three surfaces cannot disagree. All of menubar: quota windows show no pace — add run-out projection (deficit, lasts-to-reset / runs-out-in) #726's guards come along: silent in the first 3% of a window, on an exhausted window, without a reset time, and on clock skew, with the <= 6h ETA suppression kept rather than crying wolf over one burst.QuotaSummary.Windowcarries no window length, so rather than thread one through ~15 adapter call sites,QuotaPace.inferredWindowSeconds(label:resetsAt:)reads it from the normalized label the adapters already derive from the exact API duration (Weekly,5-hour,Weekly · Opus,Monthly usage limit). Calendar months are measured back from the reset date in UTC, mirroring how the Codex spend window is derived. A label that implies no length (Copilot'sPremium requests, Cursor'sTeam pool) keeps the row silent instead of guessing.Closes #1215
Testing
npm testpasses — not applicable, no TypeScript touched;cd mac && swift buildsucceeds (Build complete, 53.76s)npm run buildsucceeds — not applicable; macOS target onlymac/Tests/CodeBurnMenubarTests/QuotaPaceVerdictTests.swiftadds 12 XCTest cases over the pure(utilization, elapsed fraction, window length) -> String?mapping: all four outcomes(lasts / runs out with an ETA / won't last on a 5h and on an exactly-6h window / silent), the
early-window silence at 2% and 1% elapsed with 5% speaking, exhausted, missing reset and clock
skew, the countdown wording, the
percent0...1 conversion, and label inference includingWeekly · Opus,GPT-5.3-Codex-Spark · 5-hour,Gemini Models · Five-hour,Monthly usage limitagainst a February-in-UTC reset, and the bucket labels that must staysilent.
CapacityDockGlanceTestsis updated for the three hard-coded panel heights thereserved line moves.
Note: my machine has a CLT-only Swift toolchain with no swift-testing module, so the test
target does not compile locally (
error: no such module 'Testing'from an existing test file)and I could not run
swift test. To avoid shipping unverified assertions I executed everyexpectation in the new file against the real
QuotaPace.swiftthrough a standaloneswiftcharness — 43/43 pass — but CI's
swift testis the real check here.