Skip to content

fix(usage): poll the plan limits even when the chat is not on screen - #50

Merged
serialexperimentslainnnn merged 1 commit into
developfrom
bugfix/reset-usage
Aug 10, 2026
Merged

serialexperimentslainnnn merged 1 commit into
developfrom
bugfix/reset-usage

Conversation

@serialexperimentslainnnn

Copy link
Copy Markdown
Owner

The bug

The plan-limit poll was gated on isShowing:

Timer(USAGE_POLL_MS) { if (isShowing) requestUsage() }   // before

A collapsed tool window, or a chat tab that was not the selected one, asked for nothing at all. And a quota window is not this plugin's state — other sessions, other devices and claude.ai spend the same windows, and a reset is a wall-clock event that owes nothing to the IDE. So the figure on screen was whatever the last probe happened to catch, and it moved again only when something else triggered one: a turn, or opening the dashboard. "It only updates when I talk to the agent" is exactly what a visibility-gated poll looks like from outside.

The gate is gone and the period is 30 s. The event-driven refreshes (turn edges, rate_limit_event, dashboard open, session ready) are unchanged. What the gate saved was one control request per half minute against a process that is already running.

Added

The countdown, in the chat. Reset time: 4h 18m on its own line under each window's bar, sentence in the tooltip:

Current session [###-----] 6.0%     All models [###-----] 18.0%    Fable [###-----] 17.0%
Reset time: 4h 18m                  Reset time: 70h 38m            Reset time: 70h 37m

A percentage alone does not say whether it is urgent: 90% with eight minutes left and 90% with six hours left are different situations, and only the dashboard was answering that. Under the bar rather than beside it, because the row is already three items wide per window and a fourth made the countdown the first thing to be squeezed out — the one case where it matters most. One implementation (CC.resetIn/resetInShort in app-core), now shared with the dashboard card, and RateLimitInfo.resetsAtIso() puts the epoch→ISO conversion on the model so an event-sourced window and a report-sourced one are interchangeable to both surfaces.

Diagnostics

Every get_usage poll logs the reply verbatim at INFO. The derived per-window lines cannot say whether a number is stale — a window the reply omits leaves no line, and one carried forward looks fresh. It earned its place immediately: a live capture showed two of three consecutive polls returning the header-seeded shape (five_hour/seven_day only, no limits[], resets_at rounded to .000Z), which is the degraded reply 5.1.0's merge exists for — and confirmed the binary does not cache the endpoint.

Process

docs/RELEASE_PROCEDURE.md §6 now states that the release PR is closed to late commits, cosmetic ones above all: a commit pushed onto an open release PR invalidates every gate that passed on it, and main publishes.

Gates — clean locally (clean … --rerun-tasks)

Gate Result
test 781 tests, 0 failures
koverVerify / detekt / spotlessCheck pass
verifyPlugin Compatible IC-251 → IU-262
buildPlugin 0 node_modules, META-INF/{LICENSE,THIRD-PARTY-NOTICES.md} present
npm test / lint / format 113/113, clean
npm audit --omit=dev 0 vulnerabilities

Manually validated in IntelliJ IDEA 2026.2 against a live session — including the case that failed: tool window collapsed and a different tab selected.

🤖 Generated with Claude Code

The poll was gated on isShowing, so a collapsed tool window or a chat tab that was not the selected
one asked for nothing at all. A quota window is not this plugin's state: other sessions, other
devices and claude.ai spend the same windows, and a reset is a wall-clock event that owes nothing to
the IDE. So the figure on screen was whatever the last probe happened to catch, and it only moved
again when something else triggered one -- a turn, or opening the dashboard. "It only updates when I
talk to the agent" is what a visibility-gated poll looks like from outside. The gate is gone and the
period is 30s; the event-driven refreshes are unchanged.

The bar row now carries the countdown: "Reset time: 4h 18m" on its own line under each window's bar,
with the sentence in the tooltip. A percentage alone does not say whether it is urgent -- 90% with
eight minutes left and 90% with six hours left are different situations, and only the dashboard was
answering that. Under the bar rather than beside it, because the row is already three items wide per
window and a fourth made the countdown the first thing to be squeezed out. One implementation in
app-core (CC.resetIn/resetInShort), shared with the dashboard card, and RateLimitInfo.resetsAtIso()
puts the epoch-to-ISO conversion on the model so an event-sourced window and a report-sourced one
are interchangeable to both surfaces.

Every get_usage poll now logs the reply verbatim at INFO. The derived per-window lines cannot say
whether a number is stale, because a window the reply omits leaves no line and a carried-forward one
looks fresh. It earned its place immediately: a live capture showed two of three consecutive polls
returning the header-seeded shape (five_hour/seven_day only, no limits[]), which is the degraded
reply 5.1.0's merge exists for, and confirmed the binary does not cache the endpoint.

The release procedure now states that the release PR is closed to late commits, cosmetic ones above
all: a commit pushed onto an open release PR invalidates the gates that passed on it, and main
publishes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@serialexperimentslainnnn
serialexperimentslainnnn merged commit d0d52a6 into develop Aug 10, 2026
13 of 17 checks passed
@serialexperimentslainnnn
serialexperimentslainnnn deleted the bugfix/reset-usage branch August 10, 2026 18:35
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