docs/cost-history.md
Cost history and daily models
The provider popup shows Today and the selected period side by side. History, period models, and projects expand on demand. Cost errors and pricing notices remain visible when the details are collapsed.
Data and display rules
- Day models come from the selected
cost.daily[].modelBreakdowns[]record. Missing day models never fall back to period totals. - Display at most six models per day and report truncation. Period models also expose truncation and an explicit empty state.
- Missing costs and token counts remain unknown. Measured zero stays zero; filling calendar gaps only fills metrics actually observed in the snapshot.
- Model names are strings. Numeric names are not coerced into display labels. Tied model amounts use the label as a stable ordering tiebreaker.
- Standard/Fast totals remain blocked on an official CLI contract. No service tier is inferred from model names or amounts.
These rules are implemented in ProviderNormalizer.js, CostPresentation.js, and ProviderCostSection.qml.
Selection rules
Hover previews stay inside the chart. Pointer or keyboard selection pins a day
without fetching data. A background refresh retains the pinned date even when
its chart position changes; a missing or ambiguous date clears the pin.
sourceIndex cannot identify a day across different snapshots.
Provider, account, and history range changes clear the pin and expanded details, including when cached data is reused. Account identity follows the account picker's canonical label, including organization-only identities. Metric changes clear the pin but preserve explicitly expanded period details. Period efficiency stays in the period view, available through All days; it is not shown as a daily figure. A single measurable day remains selectable to inspect its models.
History, trust, and project totals
costHistoryMetric selects cost or tokens across charts from the same loaded
payload; the selected metric also controls bar scaling. Metric and day selection
must not add CLI calls. historyCoverageIsEstablished controls the collecting
history notice; a missing flag counts as established for legacy payloads.
ProviderNormalizer.normalizeCostTrustMetadata bounds coverage and provenance.
CostPresentation.costTrustSummary qualifies provider and global amounts with
one shared notice. Missing legacy metadata stays quiet. Keep pricing coverage
separate from history collection coverage and never expose raw provenance in QML.
normalizeCostProjects retains bounded names and optional amounts, discarding
paths and nested source records. Preserve unknown amounts and duplicate names;
keep provider currencies separate. Signal truncation at 128 inspected projects
per provider or 128 displayed rows overall. Project rows never contribute to
provider or global totals. The usage guide describes
the range/metric controls and expandable presentation.
Official CLI 0.56.2 emits Antigravity token-only history through the generic cost
envelope. Absent costs stay absent in daily/model normalization. Its established
empty snapshot uses zero dollar totals despite costs being unavailable, so
normalizeProviderCostTotals masks that provider sentinel until an official
availability field exists. Token charts remain usable while cost totals and
cost-mode charts stay unavailable. Cursor cost is rejected by that Linux release;
neither case authorizes provider fetching or source parsing in QML. The scoped
0.57.0 probes
confirm Cursor is still rejected; they do not retest established-empty
Antigravity history.
Track explicit cost availability, Cursor Linux cost, and service-tier totals in TODO.
Pinned CLI evidence
The scoped implementation used official CodexBar v0.56.8, commit
6ef82690b4a718a21fac42b72a102df07e475509, and its
CLICostCommand.swift.
The existing daily model fields are modelName, cost, and totalTokens.
This adds no command or provider-specific source and does not replace the full
0.56.2 parity baseline.
The official Linux x86_64 release archive was checksum-verified with SHA-256
ab98788e12840e5689ae505bf62731e0ea0db1c77e63dceda1589b6e795ac5b8.
An isolated probe with two synthetic days and two models ran
cost --provider codex --days 7 --format json --json-only --refresh --provider-native-only
without network access. It exited 0 with empty stderr. The fixture and recorded
output are linked in the
historical probe report.
Regression coverage
Normalizer tests and
presentation tests cover the data rules.
The popup smoke scenarios cover pinned-day refreshes, reordering, missing days,
cached account changes, ranges, missing token counts, and incomplete models.
Run make check for logic and wiring, and make smoke for the real applet with
synthetic data. Executed check results belong in the PR.