Skip to content

fix(ai): claude quota transform silently overwrites duplicate limits entries (last wins) — diverges from the #1750 keep-first convention #1781

Closed

Description

@dezren39

Summary

The Claude quota transform (packages/ai/src/quota/providers/claude.ts, toClaudeUsage) silently overwrites duplicate limits entries — last wins. addWindow assigns target[key] = ... unconditionally (claude.ts:152–164), and scoped model windows are stored by unconditional assignment models[modelName] = ... (claude.ts:185). That diverges from the keep-first convention the suite has now adopted three times for the identical shape: #1750 (opendesign coding-plan windows), #1769 (cline-pass limit entries, fixed in PR #1773), and #1762's collision handling for codex. Claude's transform was pinned in #1750 for the legacy-fallback behavior, but no test exercises duplicate limits entries.

Evidence (verified this run, main 32fc03b)

Probe on the laptop (~/git/fleet/probe-2026-11-05-claude-quota/probe.ts, kept) importing toClaudeUsage:

  • CASE1 — limits [session 20% (reset 2026-12-01), session 80% (reset 2026-12-02), weekly_all 30%, weekly_all 70%]: published 5h = 80% with the second reset, 7d = 70% — both first entries silently dropped.
  • CASE2 — two weekly_scoped entries for the same model ("Claude Sonnet", 30% then 60%): published model window = 60% with the second reset; the 30% entry is gone.
  • CASE3 (control) — a duplicate session entry with percent: null does not overwrite (20% survives), because addWindow returns early when percent is null and there is no valueLabel. The overwrite therefore happens exactly when the duplicate carries a real figure — the case that matters.

Why it matters

Claude is a plan pool the fork rotates across. If Anthropic's usage payload ever carries repeated limit entries (per-model splits, plan migrations, a kind repeated during a rollout), the published usage silently becomes whichever entry sorts last, with nothing recording that a choice was made — the exact failure #1750/#1769 treated as a defect in the sibling providers. The transform is otherwise well-pinned after #1750; this is the one input shape left unpinned and convention-divergent.

Acceptance criteria

Activity

  1. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    kind/testTest coverage, test infrastructure, or test-only fixes
    task/triageQueue packet kind: verify, reproduce, and route this item
    source/creatorFiled by the new-issue-creator job
    priority/lowNice to have; do when convenient
    queue/queuedHas a queued task in the Supabase agent queue
    app/aiPackage: ai (pkgs/ or apps/ in this repo)
    effort/sSmall: expected under 2 hours of work
    on Nov 5, 2026
  2. dezren39 commented on Nov 5, 2026

    @dezren39
    Author

    🤖 Agent note · filed

  3. dezren39 commented on Nov 6, 2026

    @dezren39
    Author

    🤖 Agent note · adopted as phase 2 of design #1794 (one window contract for the provider quota parsers; doc: files/designs/opencode-quota-window-contract.md, keep-the-four-repos-healthy goal workspace). This issue is the contract's claude application: rule 2 (duplicates keep the first — the #1750/#1769 convention — per kind and per model scope). Linked as a sub-issue of #1794; its queue lifecycle is untouched and it is not re-enqueued. When it lands, design phase 1's inventory row for claude duplicates flips from known-lossy to conforming.

  4. dezren39 commented on Nov 8, 2026

    @dezren39
    Author

    Partial verification — staying open (2026-11-07 done-task-only audit, tracking: developing-today/code#7016).

    Queue task(s) [10788] were marked done, and some work did land:

    No merged change closes this issue's full scope, so the done status is not treated as completion. Remainder re-queued as triage task 11507.

  5. added
    work/assignedAn agent holds this item via the queue (claimed task)
    queue/claimedA queue worker has claimed the task for this item
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 8, 2026
  6. dezren39 commented on Nov 8, 2026

    @dezren39
    Author

    🤖 Agent note · picked up

  7. developing-today commented on Nov 8, 2026

    @developing-today

    🤖 Agent note · triaged

  8. added
    task/fixQueued scoped fix task
    queue/queuedHas a queued task in the Supabase agent queue
    and removed
    task/triageQueue packet kind: verify, reproduce, and route this item
    queue/claimedA queue worker has claimed the task for this item
    work/assignedAn agent holds this item via the queue (claimed task)
    on Nov 8, 2026
  9. added a commit that references this issue on Nov 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    app/aiPackage: ai (pkgs/ or apps/ in this repo)area/typescriptTypeScript code areaeffort/sSmall: expected under 2 hours of workkind/bugSomething isn't working (prefixed form of the classic bug label)kind/testTest coverage, test infrastructure, or test-only fixespriority/lowNice to have; do when convenientqueue/queuedHas a queued task in the Supabase agent queuesource/creatorFiled by the new-issue-creator jobtask/fixQueued scoped fix task

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions