Skip to content

design(ai): a figure that cannot exist is not a figure — one figure contract for the quota parsers' amounts, balances, counts and percents #1942

Closed
8 of 8 issues completed

Description

@dezren39

design(ai): a figure that cannot exist is not a figure — one figure contract for the quota parsers' amounts, balances, counts and percents

Design doc: files/designs/opencode-quota-figure-contract.md in the keep-the-four-repos-healthy goal workspace. Grounded on main 05702ca18d. Filed by the repo design architect (2026-11-07 pass) after reading ROADMAP.md / TODO.md / planning, the central register (files/potential-projects.md), the kind/design list, and the quota sources on current main.

Summary

#1794 stated the window contract — what a parser may put into usage.windows, under what key — and deliberately scoped balances out of windows (its rule 4). No design has ever stated the contract for the figures themselves: every number a quota parser publishes, in a window's percent fields, in a valueLabel amount / balance / count, and in the wire scalars that scale those numbers. In the two days since #1794 phase 1 landed (#1795), that unstated layer produced fifteen filings, seven still open:

The precedents exist one provider at a time, exactly as the window rules did before #1794: meta parseBillingBanner returns null for minor < 0; opencode-go toMicroCents returns null for amount < 0; turso carries a private numNonNegative; command-code gates monthlyRemaining >= 0 (#1744) and clamps percent and label from one figure (#1821); deepseek filters total_balance > 0 (#1800). The shared layer (packages/ai/src/quota/utils.ts, read verbatim on current main) offers toNumber (negative included), clampPercent and formatMoney (formats a negative verbatim) — no amount reader, no pair check, no precision rule. Each open filing asks its fixer to re-derive the same dispositions alone, in one provider, again.

The contract

A figure that cannot exist is not a figure. For every number a quota parser publishes — percent, amount, balance, count, in a field or in a valueLabel — and for every wire scalar that scales one:

  1. Impossible figures read as absent. Negative money / balance / spend publishes as absent, never as a formatted label (meta / opencode-go / turso / command-code precedent, generalised). Zero is a real figure and publishes unchanged.
  2. A pair is judged as a pair. remaining ≤ limit etc.: individual well-formedness is not enough. The disposition of an impossible pair is whole-window and named per provider in the inventory — read-as-absent, or clamp-with-the-real-figure-annotated (fix(ai): Command Code quota monthly window vanishes when remaining credits exceed the hard-coded 10 included — an over-limit payload reads as 'could not be parsed' #1744's shape) — never split between percent (clamped) and label (raw). Extends design(ai): parse the window you were sent, or none — one window contract for the provider quota parsers #1794 rule 5 from derived fields to the raw pair.
  3. Scaling inputs are figures too. An exponent / divisor / multiplier from the wire is validated against its closed range before it scales anything (money exponents: ISO 4217 0–3). Out of range reads the scaled figure as absent; sibling figures on the same window still publish.
  4. Precision is part of the figure. A published percent keeps the wire's precision; rounding is a display act (CLI, fix(cli): quota renders unrounded percents — 33.33333333333333% used for a one-third-full window #1797), never a parser act.
  5. A result whose only figure is impossible is no result. Refusing impossible figures that empties a result fires the provider's existing no-data contract (ok: false) — fix(ai): claude quota returns ok:true with empty windows for a 200 payload carrying no usable quota data #1915/fix(ai): codex quota windows keyed only by derived duration label — a missing or shared limit_window_seconds silently drops one window, and an empty window object mints a phantom all-null window #1762 extended from figure-less to impossible-only payloads.
  6. Every figure path is pinned against this contract. One shared figure probe matrix (negative, zero control, impossible pair, out-of-range scaling input, sub-percent precision) per parser that publishes figures; the figure inventory rides the same types.ts table as the window inventory — not a second table to drift (docs(ai): quota window-contract inventory verdicts do not reflect the open known-lossy filings — six rows certify or omit parsers with live lossy issues, and turso's row has no verdict at all #1939 is the warning).

Named exception: turso's publish-truthfully over-100% disposition (#1743) stands — a provider's stated disposition governs its out-of-range figures, as under window rule 5. The contract forbids unstated and split dispositions, not stated ones.

Phases

Grounding

Acceptance criteria

Activity

  1. added
    task/triageQueue packet kind: verify, reproduce, and route this item
    priority/normalOrdinary priority (the default)
    app/aiPackage: ai (pkgs/ or apps/ in this repo)
    kind/designA design proposal (design-architect): multi-step, phased, decision-bearing
    on Nov 7, 2026
  2. added
    work/assignedAn agent holds this item via the queue (claimed task)
    queue/claimedA queue worker has claimed the task for this item
    on Nov 8, 2026
  3. dezren39 commented on Nov 8, 2026

    @dezren39
    Author

    🤖 Agent note · triaged

  4. added
    effort/lLarge: multi-day or open-ended; expect staged check-ins
    meta/enrichedIntake review done: acceptance criteria, links, and normalized labels added
    and removed
    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
  5. dezren39 commented on Nov 8, 2026

    @dezren39
    Author

    Intake review

    Related: issue #1794 (the window contract — this design is its figure-layer sibling, composed not duplicated); adopted filings #1928, #1924, #1919 (negative figures), #1897, #1879, #1920, #1941 (pairs / scaling / precision); #1939 (inventory drift — cited as the warning against a second table); #587 and #992 (adjacent layers, out of scope).

    Still live (monitor check this run): design filed 2026-11-07 by the design architect; no merged PR states a figure contract in types.ts — the shared layer (packages/ai/src/quota/utils.ts) still offers only toNumber / clampPercent / formatMoney with no amount reader, pair check, or precision rule.

    Notes: Fifteen filings in two days trace to this one unstated layer — the contract's value is that phase 2/3 fixers stop re-deriving dispositions per provider. Phase 1 is deliberately tests/docs only; the behaviour changes all live in the adopted sub-issues.

    Risks: Inventory drift is the named failure mode (#1939) — the figure section must ride the existing types.ts table, not a new one. Named exceptions (turso) must stay explicit so the probe matrix doesn't flatten a stated disposition.

    Suggested approach: land phase 1 (contract + inventory section + probe matrix over the conforming parsers) first; let phases 2/3 close through their own queue tasks; treat phase 4 (shared helpers in utils.ts) as a separate filing decision once the matrix is in place.

    — fleet monitor intake (repo-fleet-monitor, 2026-11-07 run); acceptance criteria appended to the body and labels normalized this pass.

  6. dezren39 commented on Nov 8, 2026

    @dezren39
    Author

    Program tending — completion proposal: all eight sub-issues of this design are now CLOSED (REST-verified this run): #1879, #1897, #1919, #1920, #1924, #1928, #1941, #1943 — the last, #1943, closed 2026-11-08T12:31:37Z. This issue's last activity is the 2026-11-08T04:40Z intake review, which predates the final closures — sub-issue progress is 8/8 closed.

    Proposal: close this design issue as completed — the figure contract's adopted filings have all landed. Any residual figure-parsing gap belongs on a fresh, scoped issue rather than keeping the design open.

  7. dezren39 commented on Nov 8, 2026

    @dezren39
    Author

    🤖 Triage — closing as completed · issue-sweep-rotating feeder

    Verified fresh on 2026-11-08 against current main 781493259274e4c78be2cd5fd6dadfb5a098ed67:

    Acceptance criteria are therefore met. Closing as completed — this is a clerical triage close, no code changed by the feeder.

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)effort/lLarge: multi-day or open-ended; expect staged check-inskind/designA design proposal (design-architect): multi-step, phased, decision-bearingmeta/enrichedIntake review done: acceptance criteria, links, and normalized labels addedpriority/normalOrdinary priority (the default)source/design-architectFiled by the repo design architect jobstatus/needs-triageNot yet triaged; needs a first looktask/triageQueue packet kind: verify, reproduce, and route this item

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions