Keep the usage endpoint under its rate limit (1.0.1) #7

Merged
ClaudiuSchuster merged 4 commits from oss-oo/refresh-floor into main 2026-10-27 11:19:40 +00:00
Owner

Keeps the applet under the usage endpoint's rate limit. This morning a 1-minute refresh interval got about every second request rejected with HTTP 429 for hours.

  • 2-minute floor: settings-schema.json refresh-interval.min is 2, and the applet treats a stored shorter value as 2 minutes.

  • Request spacing: the helper asks the endpoint at most once every 110 seconds per access token, counted between send times (REQUEST_SPACING), so the regular refreshes alone always reach it. recent-answers.json (0600, truncated token fingerprints, pruned on write) keeps each answer that long. A refresh in between, from Refresh now, a reload or a setting change, gets that answer again:

    • after a success, the snapshot as source.cached, with no history sample;
    • after a failure (EndpointError: HTTP 429, other statuses, unreadable or empty answers), the same failure, replayed as before;
    • after a rejection (TokenRejected, HTTP 401/403), the same rejection, and the next source is tried without asking.

    Only a request that could not complete (unreachable endpoint, timeout) is repeated right away. Held-back answers are raised as the base classes, so they never postpone the next request. last-snapshot.json keeps its 1.0.0 format.

  • Docs: README, SECURITY.md, docs/README.md, CHANGELOG and version 1.0.1. The repository's release rule now names the owner's standing approval of 2026-10-27; the independent review stays mandatory.

Validation

  • make verify and Prettier are green; 96 Python tests (83 before) and 14 CJS suites pass.
  • 18 of 18 real mutants are caught, measured against passing unmutated baselines.
  • The suite stays green with the clock shifted by +1 h, +4 d, +30 d and +1 y.
  • CI runs 1939 (091d4b8), 1944 (bf45943), 1945 (0e06320) and 1946 (68cb4be) succeeded.
  • The independent review took three rounds:
    • round 1 found two defects (the spacing was measured from the answer time, and unsendable tokens crashed the helper) and three gaps (failures and rejections went unrecorded, all tokens shared one state slot, and a reset exception blocked reuse), all fixed in bf45943;
    • round 2 confirmed those fixes and raised three nits, fixed in 0e06320;
    • round 3 found no new defect, and its optional wording point is in 68cb4be.

🤖 Generated with Claude Code

Keeps the applet under the usage endpoint's rate limit. This morning a 1-minute refresh interval got about every second request rejected with HTTP 429 for hours. - **2-minute floor:** `settings-schema.json` `refresh-interval.min` is 2, and the applet treats a stored shorter value as 2 minutes. - **Request spacing:** the helper asks the endpoint at most once every 110 seconds per access token, counted between send times (`REQUEST_SPACING`), so the regular refreshes alone always reach it. `recent-answers.json` (0600, truncated token fingerprints, pruned on write) keeps each answer that long. A refresh in between, from _Refresh now_, a reload or a setting change, gets that answer again: - after a success, the snapshot as `source.cached`, with no history sample; - after a failure (`EndpointError`: HTTP 429, other statuses, unreadable or empty answers), the same failure, replayed as before; - after a rejection (`TokenRejected`, HTTP 401/403), the same rejection, and the next source is tried without asking. Only a request that could not complete (unreachable endpoint, timeout) is repeated right away. Held-back answers are raised as the base classes, so they never postpone the next request. `last-snapshot.json` keeps its 1.0.0 format. - **Docs:** README, SECURITY.md, docs/README.md, CHANGELOG and version 1.0.1. The repository's release rule now names the owner's standing approval of 2026-10-27; the independent review stays mandatory. **Validation** - `make verify` and Prettier are green; 96 Python tests (83 before) and 14 CJS suites pass. - 18 of 18 real mutants are caught, measured against passing unmutated baselines. - The suite stays green with the clock shifted by +1 h, +4 d, +30 d and +1 y. - CI runs 1939 (091d4b8), 1944 (bf45943), 1945 (0e06320) and 1946 (68cb4be) succeeded. - The independent review took three rounds: - round 1 found two defects (the spacing was measured from the answer time, and unsendable tokens crashed the helper) and three gaps (failures and rejections went unrecorded, all tokens shared one state slot, and a reset exception blocked reuse), all fixed in bf45943; - round 2 confirmed those fixes and raised three nits, fixed in 0e06320; - round 3 found no new defect, and its optional wording point is in 68cb4be. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Keep the usage endpoint under its rate limit (1.0.1)
All checks were successful
Checks / Functional checks (pull_request) Successful in 32s
091d4b8127
- The refresh interval starts at 2 minutes (schema minimum 2; the applet
  treats a stored shorter value as 2): at a one-minute pace the usage
  endpoint rejected about every second request with HTTP 429.
- The helper asks the endpoint at most every 110 seconds per access token.
  In between it reuses the endpoint's last answer: the saved snapshot after
  a success (source.cached, no history sample) or the busy message after an
  HTTP 429 (EndpointBusy), without postponing the next regular request.
- Docs, changelog and version 1.0.1; the repository's release rule names the
  owner's standing approval of 2026-10-27, the independent review stays.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Space requests by send time, per token, for every answer
All checks were successful
Checks / Functional checks (pull_request) Successful in 36s
bf459439e0
Review round 1 of 1.0.1:
- The spacing counts from the send time, so a slow answer no longer holds
  back the next regular refresh.
- Every answer is kept per token fingerprint in recent-answers.json for
  REQUEST_SPACING: a success (its snapshot is reused as source.cached), a
  failure (HTTP 429, other statuses, unreadable answers: the same error and
  replay) and a rejection (TokenRejected for 401/403: the next source is
  tried without asking). Only a request without any answer is repeated
  right away. last-snapshot.json is back to its 1.0.0 format.
- A token no request could carry is never fingerprinted: it falls through
  to the sign-in prompt as in 1.0.0 instead of crashing the helper.
- No reset exception: within the spacing the endpoint's last answer stands.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Count an empty answer as an endpoint failure; precise spacing docs
All checks were successful
Checks / Functional checks (pull_request) Successful in 32s
0e06320275
Review round 2 of 1.0.1 (nits):
- An HTTP 200 without any usage window is an EndpointError inside the
  request block: it is kept as a failed answer, held back within the
  spacing and replayed like any other endpoint failure.
- Docs: the regular refreshes alone always reach the endpoint (one right
  after a manual refresh gets that answer); only a request that could not
  complete (unreachable, timeout) repeats at once. SECURITY.md names
  recent-answers.json as the second place the snapshot is kept and the
  server detail a failure message may carry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SECURITY.md: recent-answers.json keeps the snapshot until a later write prunes it
All checks were successful
Checks / Functional checks (pull_request) Successful in 32s
68cb4bee45
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ClaudiuSchuster deleted branch oss-oo/refresh-floor 2026-10-27 11:19:40 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
OSS-Singularity/cinnamon-claude-usage!7
No description provided.