Add automatic versioned repricing of persisted usage - #10
Merged
Merged
Conversation
When the compiled pricing ruleset advances, the selected statsai binary reprices normalized events, summaries, task spans, and dirty sync rollups without a raw provider rescan. Stores priced by a newer ruleset are refused. statsai-dev --prod-data now requires an exact pricing-ruleset match, and build.json schema 2 records that version. Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Repricing now recomputes linked task spans from current persisted events even when event payloads already match the catalog, pages only spans with event links, and batch-loads those events. Incremental sync coverage now includes passthrough summaries and dirty task buckets. Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Keep the current official catalog date and Grok 4.6 rates as the descriptive pricing identifier, and preserve quota CLI imports next to the pricing-ruleset version export so automatic reprice still compiles against the current store and sync surface.
Schema 22 is current. Keep the pin so a later schema bump still forces a check that the daily_rollups table stays off the report/sync/snapshot path.
Corrupt event, summary, and span payloads no longer fail closed the whole operational store. Pages always advance past those ids, dangling span links clear stale cost, and the applied ruleset still advances.
Status, doctor, quota, conversation, account, source, subscription, and privacy open the store without a ruleset pass. Scan, report, import, export, task, sync, and daemon still reprice first. Snapshot already did. Add an open_operational_store happy-path test.
A corrupt sibling row in the same day bucket was still aborting the reprice transaction after the paging pass skipped it.
starkdmi
marked this pull request as ready for review
August 27, 2026 07:10
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ba094cd43f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Import copied estimated-only costs as-is after ensure_current_pricing. When the store was already at this ruleset, that pass no-op'd and the stale figure stayed. Overlay the compiled catalog at import time; provider-reported amounts are unchanged.
PRICING_CATALOG_VERSION is only read by the import overlay test.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Compatibility with current main
Merged current
maininto this branch (account-plan CLI, quota-cycle sync, Grok 4.6 pricing, repository-rename rollup buckets). Conflict resolutions:PRICING_RULESET_VERSION = 1and the current catalog stringofficial:2026-08-19. Existing stores have no applied ruleset yet, so the first pass includes Grok 4.6 rates.QuotaQueryimport next toPRICING_RULESET_VERSION.Code review follow-ups
task_span_event_linksclear stale span cost rather than leaving it.BEGIN IMMEDIATEtransaction (atomic rollback + concurrent no-op). It is no longer started from diagnostic commands. Scan, report, import, export, task, sync, daemon, and snapshot reprice; status, doctor, quota, conversation, account, source, subscription, and privacy open withStore::open.Store::openand does not reprice. The selectedstatsaibinary owns the ruleset so a store-linked menubar cannot apply a different compiled catalog.open_operational_storehappy path, command-routing coverage, and import overlay afteralready_current.Quota windows can still print
estimated_cost_micro_usd. That figure stays stale until a price-derived command runs. That is the intended trade-off.Problem
Pricing is calculated while provider records are parsed. After a pricing-rule change, persisted
UsageEventrows keep old or missing estimated cost until an expensive raw rescan (statsai scan --provider … --no-cache) plus rollup rebuild. That defeats the reusable cloned-database workflow:--fullsync alone does not reprice anything.Solution
The selected
statsaibinary now owns a monotonicPRICING_RULESET_VERSIONand, before price-derived commands use that data, applies that ruleset to the store.PRICING_RULESET_VERSIONis separate from the descriptivePRICING_CATALOG_VERSION. Catalog strings are not ordered lexicographically. Every semantic pricing-rule change must increment the numeric version.local_metadata(pricing.applied_ruleset_version,pricing.applied_catalog_version). Missing metadata is treated as a legacy store that needs one initial pass. No schema migration.Store::open.statsai-devlinksstatsai-storeand may compile a different catalog than the exact-SHA binary it launches.store clone-toand supported-version probes stay reprice-free.estimate_cost_at. Only pricing-derived fields are written. Identity, usage, timestamps, source metadata, and provider-reported cost/provenance are preserved. Unknown models stay unpriced while the store-level applied version still advances.pricing_changes_between) remain unknown rather than applying one price across the period.daily_rollupsis unused by report/sync/snapshot and is left unchanged (covered by test). Linked task spans are recomputed from current persisted events even when those events already match the catalog, then work items for those project buckets are rebuilt and marked dirty.sync_rollupsare refreshed and marked dirty. Repriced passthrough summaries change payload hash. Ordinarystatsai sync --sink httpuploads both without--rebuild-rollupsor--full.Transaction boundary
ensure_pricing_rulesetuseswith_immediate_transaction(busy-retry,BEGIN IMMEDIATE):Only rows whose serialized pricing state changed are written. Event updates reuse the in-memory row (no extra read). Task-span refresh pages only spans with
task_span_event_linksand batch-loads those events.Downgrade behavior
If the store was processed by a newer ruleset than the running binary supports, normal operation is refused with an explicit forward-pricing-version error (analogous to the schema-17 forward guard). The old binary does not reprice backward or insert events priced with old rules into a newer-priced store. Invalid applied-version metadata also fails closed.
Production-data safety
statsai-dev --prod-dataremains fail-closed:statsai store supported-pricing-ruleset-versionprints the compiled ruleset without opening a store.build.jsonschema is 2 and includespricing_ruleset_version.database_applied_pricing_ruleset_version(no migrate, no reprice).--prod-datais allowed only when schema and pricing ruleset exactly match. Missing, older, or newer production pricing is refused.statsai-devstores are still auto-repriced by the selected exact-SHA binary.Large-fixture measurement
On-disk fixture of 512 legacy
codex-auto-reviewevents, streamed in pages of 256:The test asserts the pass stays well under 30s. The whole store is not loaded into memory at once.
Tests
Store, CLI, pricing, artifact, and
--prod-datatests cover legacy auto-review reprice, the 2026-07-30 date boundary, metadata-after-success, no-op, provider-reported survival, unknown models, in-window and boundary summaries, dirty rollups, incremental HTTP sync of rollups and passthrough summaries without--full, stale spans when events already match, unlinked spans left unchanged, dangling links clearing cost, unreadable payloads skipped, dirty task buckets, injected rollback, concurrent callers, forward-version refusal (store andopen_operational_store),open_operational_storehappy path, diagnostic vs price-derived command routing, import overlay afteralready_current, invalid metadata fail-closed,--prod-datamismatches, and schema-2 manifest verification.Operator notes
--prod-datarequires exact schema and pricing-version compatibility.statsai importoverlays the current catalog on estimated-only imported summaries even when the store is already at this ruleset.