Repository navigation
Description
Summary
The ClinePass quota provider (packages/ai/src/quota/providers/cline-pass.ts) builds its windows record by unconditional assignment — windows[kind.key] = ... (cline-pass.ts:86) — so when the usage-limits response carries two entries of the same type, the later entry silently overwrites the earlier one. That is the opposite of the convention the suite adopted in #1750 for opendesign coding-plan windows ("duplicate durations keep the first entry instead of silently overwriting"). The mapping is also entirely unpinned: packages/ai/test/quota.test.ts never imports cline-pass, and the parse logic is embedded in fetchForKey rather than an exported pure function (it is still testable end-to-end via the injectable fetchImpl, as the probe below shows).
Evidence (verified this run, main 4b9febf)
Probe on the laptop (~/git/fleet/probe-2026-11-05-cline-pass/probe.ts) calling provider.fetchQuotaForCredential with a stubbed fetchImpl returning:
{ "data": { "limits": [
{ "type": "five_hour", "percentUsed": 10, "resetsAt": "2026-11-06T00:00:00Z" },
{ "type": "five_hour", "percentUsed": 90, "resetsAt": "2026-11-06T01:00:00Z" },
{ "type": "weekly", "percentUsed": "42", "resetsAt": "2026-11-12T00:00:00Z" },
{ "type": "weekly", "percentUsed": 7, "resetsAt": "2026-11-13T00:00:00Z" },
{ "type": "monthly", "percentUsed": 55, "resetsAt": "2026-12-01T00:00:00Z" }
] } }Published windows: 5h → 90% used (the 10% entry silently dropped), weekly → 7% used (the "42" entry silently dropped), monthly → 55%. No error, no log, no indication a duplicate ever existed. Whether first-wins or last-wins is correct for Cline's wire is currently an undocumented accident of loop order; #1750 already settled the house convention as keep-first for the identical shape in opendesign.
Why it matters
ClinePass is one of the plan pools the fork rotates across. If Cline ever returns split or repeated limit entries (per-model splits, plan migrations), the published usage flips to whichever entry happens to sort last, with nothing recording that a choice was made. The parser also has no test pinning its string/number percentUsed handling, unknown-type skipping, or the empty-windows "No quota data in response" path — the same unpinned-parser gap #1725 / #1750 closed for the other providers.
Acceptance criteria
- Duplicate
typeentries keep the first entry, per the test(ai): quota suite pins none of claude / meta-billing / opendesign's pure parsers — billing banner rejects numeric strings, claude transform drops legacy windows when limits is non-empty, coding-plan publishes a zero-limit window #1750 convention (or a different disposition is chosen and documented in the code + this issue's closing note). - The limits→windows mapping is pinned in
packages/ai/test/quota.test.ts(viafetchQuotaForCredentialwith a stubbedfetchImpl, or an extracted pure parser): happy path for all three window kinds, numeric-stringpercentUsed, missingpercentUsed(entry skipped), unknowntype(skipped), duplicatetype, and the all-invalid → "No quota data in response" result. - Existing quota suite stays green; gate state not regressed (the three quota-era gates already red on main belong to fix(ci): three gates red on main — PR #1722's quota subcommand landed 16 undispositioned sites, and turso bypasses the PR's own bounded reader #1724 — do not conflate).
Activity
dezren39 commentedon Nov 5, 2026
🤖 Agent note · filed
developing-today commentedon Nov 5, 2026
Triage (task 10761, lane opencode-a): CONFIRMED LIVE on current main; disposition DECIDED — keep-first, matching the #1750 convention.
Re-verified this shift against a fresh raw read of
packages/ai/src/quota/providers/cline-pass.tson main: the limits loop assignswindows[kind.key] = toUsageWindow({...})unconditionally, so a duplicate limit entry of the same type silently overwrites the earlier one (last wins, no trace). The mapping is unpinned:packages/ai/test/quota.test.tsdoes not import cline-pass (the parse logic is embedded in the fetch path and is testable via the injectablefetchImpl/fetchQuotaForCredential, as the filing probe showed).Decision — the fix (enqueued separately, dedupe key
repo-health:v1:fix:developing-today/opencode:issue:1769): on a duplicate window kind, keep the FIRST entry and skip later duplicates, with a code comment naming the convention. This is the same disposition adopted for the identical shape in #1750 (OpenDesign coding-plan duplicate durations, merged today in PR #1766): duplicate entries for the same window are a payload anomaly, not an update, and the first entry is the API's primary report. No alternative disposition was recorded because consistency across the quota module's parsers is itself the fix for this class — a per-provider exception would recreate the divergence this issue files.Pinning tests required in the fix (
packages/ai/test/quota.test.ts, driving the provider with a stubbed fetch, mirroring the filing probe): duplicate five_hour entries publish the first percent; duplicate weekly entries publish the first; distinct types publish both; a payload with no usable limits returns the existing "No quota data in response" contract; existing quota tests keep passing.Triaged by: lane opencode-a, task 10761 — keep-first disposition recorded; fix enqueued separately
Merge pull request #1773 from developing-today-forks/queue/10762-1769…
developing-today commentedon Nov 5, 2026
Merged — PR #1773 landed as 9eea0a5 and this issue auto-closed. Verification on the PR branch (laptop):
bun test test/quota.test.ts35/35 pass; both ai tsgo configs exit 0; PR mergeable, no Codex reviews posted.Completed by: lane opencode-a, task 10762