Repository navigation
Description
fix(ai): antigravity quota transformModels fallback publishes a phantom all-null "5h" window for models with no quota figure
Verified 2026-11-06 on origin/main 529cf7fa05 (merge of PR #1908), in a laptop worktree (~/git/fleet/probe-2026-11-06-creator-2135, kept).
The defect
packages/ai/src/quota/providers/antigravity.ts, transformModels (the per-model fallback branch, ~:376-398): when a model has no matched summary group, the branch builds a window from the model's own quotaInfo — but it publishes that window unconditionally, even when quotaInfo carries no quota figure at all:
remainingFractionmissing →usedPercent: null(correctly propagated as unknown, per fix(ai): antigravity quota buckets keyed only by derived label — an unrecognized bucket overwrites the real 5h window, same-label buckets silently drop, missing remainingFraction counts as fully remaining #1768).resetTimemissing →resetAt: null, and the label derivation falls through to the default: label"5h",windowSeconds: 18000— a duration and a window kind the payload never sent.- The result is assigned as
transformed[name] = { windows: { "5h": <all-null window> } }with no figure check.
That is exactly the phantom-window shape the window contract exists to forbid — rule 4 in packages/ai/src/quota/types.ts ("No figure, no window — an empty/all-null/zero-limit window-shaped object publishes no window") — and the shape two sibling providers already disposition explicitly:
- codex (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): "a window without a usable used_percent carries no quota figure, so it is dropped… a duration/reset with no percent is dispositioned the same way (dropped, not published with a null percent)".
- meta key-endpoint (fix(ai): meta quota key-endpoint path publishes phantom all-null windows for figure-less subs_usage objects #1907, fixed this week): figure-less
subs_usageobjects dropped instead of publishing phantom all-null windows beside real ones.
Antigravity's summary path learned the #1768 lessons (unknown buckets skipped, missing fraction = null), but the per-model fallback path — the path taken by every model when the summary carries no usable group for it — never got the figure check.
Runtime probe (laptop worktree, probe-antigravity.ts, kept in the worktree)
Driving the real exported transformModels with an empty summary-group list:
{ models: { "gemini-x": {} } }→"gemini-x": { windows: { "5h": { usedPercent: null, remainingPercent: null, windowSeconds: 18000, resetAfterSeconds: null, resetAt: null, resetAtFormatted: null } } }— a phantom 5h window minted from no data at all.{ models: { "gemini-x": { quotaInfo: {} } } }→ identical phantom 5h all-null window.{ models: { "gemini-x": { quotaInfo: { resetTime: "2027-01-01T00:00:00Z" } } } }(reset only, no fraction) → a"weekly"window withusedPercent: null— the label/duration are fabricated from the reset distance alone (>36h → weekly), the reset-only spelling codex 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 drops.- Control
{ quotaInfo: { remainingFraction: 0.5, resetTime: … } }→ real window:usedPercent: 50, remainingPercent: 50under"5h"(correct, unchanged).
Because fetchWithCandidates returns ok: true whenever transformModels yields at least one model entry, a models payload whose entries all lack quotaInfo reads as a successful quota read full of all-null windows.
Why it matters
These per-model windows are the antigravity provider's whole published usage (usage: { windows: {}, models }). A phantom window tells downstream consumers (the aggregator, the dashboard, quota-aware placement) that a 5-hour window exists with unknown usage, instead of the honest answer — this model carries no quota figure. It also fabricates the window's kind: the same figure-less model is labelled 5h, daily, or weekly purely by how far away an unrelated reset timestamp sits, or by default when there is none.
Acceptance criteria
- A model whose fallback
quotaInfocarries no usableremainingFractionpublishes no window (the model entry is omitted, or carries empty windows — one disposition, chosen and recorded in the closing note; the codex 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 / meta fix(ai): meta quota key-endpoint path publishes phantom all-null windows for figure-less subs_usage objects #1907 drop-the-window disposition is the precedent). - A reset-only
quotaInfo(reset present, fraction absent) likewise publishes no window — no label is derived from a reset alone. - The real-figure control is unchanged: a present
remainingFractionstill publishes its window with the existing label derivation (5h/daily/weekly by reset distance). -
packages/ai/test/quota.test.tspins: model with noquotaInfo, model with emptyquotaInfo, reset-onlyquotaInfo, and the real-fraction control. - Existing quota suite stays green; the summary-group path (
transformSummary/ matched-group branch) is unchanged.
Dedup
Searched open + closed issues for "antigravity transformModels", "antigravity phantom window", and "antigravity quotaInfo" this run: no covering issue. #1768 (closed) covered bucket labelling / keep-first / missing-fraction-as-1 in the summary path; it did not cover the fallback branch publishing a window with no figure. #1909 (open) is only about the stale inventory rows for #1768/#1785.
Activity
dezren39 commentedon Nov 7, 2026
🤖 Agent note · filed
probe-antigravity.tsin laptop worktree ~/git/fleet/probe-2026-11-06-creator-2135 (origin/main 529cf7f); body file bodies/opencode-antigravity-transformmodels-phantom-window.md in the goal hidden_files.developing-today commentedon Nov 7, 2026
Picked up by
repo-worker-opencode-a— working this now. (Fleet queue fallback mode: the queue backend is down, so this issue's comments carry the claim. The claim stays live whilerepo-worker-opencode-aposts progress markers; after 30 minutes of silence any other worker may pick this up.)developing-today commentedon Nov 7, 2026
Progress from
repo-worker-opencode-a: triaged-confirmed at main 10f3058: transformModels fallback assigns the window unconditionally with default 5h label even when remainingFraction is null; routing task/small-fixdeveloping-today commentedon Nov 7, 2026
Triage — CONFIRMED (lane opencode-a, fallback mode)
Verified fresh against
origin/main@10f305865fe8(laptop primary~/git/opencode, clean, on main):transformModelsinpackages/ai/src/quota/providers/antigravity.ts(exported at :342): the per-model fallback branch (theelseat ~:376) computesremainingFraction/usedPercentas nullable, derives a label from the reset distance alone (default"5h"/FIVE_HOUR_WINDOW_SECONDSwhen there is no reset at all), and then assignstransformed[name] = { windows: { [label]: toUsageWindow({ usedPercent, … }) } }unconditionally — there is no figure check anywhere in the branch.quotaInfopublishes an all-null"5h"window minted from no data, and a reset-onlyquotaInfopublishes a null-percent window whose label is fabricated from the reset distance — both exactly as the filed probe shows, and both contrary to window-contract rule 4 ("no figure, no window") inpackages/ai/src/quota/types.ts. The matched-group branch above it is guarded (matchedGroup && Object.keys(…).length > 0); only the fallback lacks the check.Routing:
task/triage→task/small-fix, back toqueue/queuedwithstatus/needs-triage. Disposition (omit the model entry vs empty windows) is delegated to the fix by the criteria, with the codex #1762 / meta #1907 drop-the-window precedent named; tests pin no-quotaInfo, empty quotaInfo, reset-only, and the real-fraction control. No Drew decision needed.agent-note:v1 · agent: repo-queue-opencode-worker-a · lane: opencode-a · mode: fallback (queue backend down, code#6619)
5 remaining items
dezren39 commentedon Nov 7, 2026
Picked up by
repo-worker-opencode— working this now. (Fleet queue fallback mode: the queue backend is down, so this issue's comments carry the claim. The claim stays live whilerepo-worker-opencodeposts progress markers; after 30 minutes of silence any other worker may pick this up.)dezren39 commentedon Nov 7, 2026
Progress from
repo-worker-opencode: verified: inspecting transformModels fallback branch on fresh main; next: worktree + figure checkdezren39 commentedon Nov 7, 2026
Progress from
repo-worker-opencode: implementation_complete: figure check in transformModels fallback, quota suite 131 pass, neg control 4 fail stashed; next: PR + mergeMerge pull request #1937 from developing-today-forks/queue/1912-1912-…
dezren39 commentedon Nov 7, 2026
Released by
repo-worker-opencode(outcome: done). fixed_merged: PR #1937 MERGED 19a8142 (branch queue/1912-1912-antigravity-phantom); disposition: figure-less fallback models omitted entirely (rule 4, codex #1762/meta #1907 precedent); quota.test.ts 131 pass, neg control 4/5 new tests fail stashed; issue CLOSED; backlog + sweep.log updated