Skip to content

feat: cost CI runs against stored production statistics (#3353 analyzer half)#154

Merged
veksen merged 1 commit into
mainfrom
feat-ci-consume-prod-stats
Jun 18, 2026
Merged

feat: cost CI runs against stored production statistics (#3353 analyzer half)#154
veksen merged 1 commit into
mainfrom
feat-ci-consume-prod-stats

Conversation

@veksen

@veksen veksen commented Jun 18, 2026

Copy link
Copy Markdown
Member

What

At CI time, the analyzer now pulls the project's stored production statistics over the relay RPC getProductionStats() and costs queries with Statistics.statsModeFromExport(...) when a snapshot exists — instead of always scoring against synthetic fromAssumption (10M-row / 0.9-correlation) defaults.

The resulting statisticsMode already flows through to the Site API CI payload (reportContext.statisticsMode), so runs modeled on real prod cardinality are labelled as such on the dashboard (the Site indicator shipped in Query-Doctor/Site).

How

  • main.ts (runInCI) — pull api.getProductionStats() (scoped server-side to this CI connection's project; no args). On RPC failure → warn + fall back to synthetic. Pass into Runner.build.
  • runner.ts (determineStatsMode) — new precedence: API production stats → explicit stats file → synthetic assumption. Reuses the existing static StatisticsStrategy path the file branch already used, so no new sync/restore machinery. Replaces the standing TODO: grab recent stats from API if they exist.
  • @query-doctor/core bumped ^0.10.3 → ^0.10.4 (the published version that carries the getProductionStats contract).

Why this is safe / backwards-compatible

  • Existing callers of Runner.build pass no productionStats, so determineStatsMode skips the new branch and behaves exactly as before — a no-op for every pre-existing path.
  • Not re-validating the RPC stats with ExportedStats.array().parse() is intentional and matches the sibling updateStatistics path (api-client.ts): trusted backend data validated on write, unlike the untrusted file path.

Tests

  • 4 new unit tests for Runner.determineStatsMode precedence (export-when-present, precedence over a file path, empty/no-stats → synthetic). npm run typecheck clean.
  • Full suite has unrelated local testcontainers flakiness (FATAL: database system is in recovery mode) — 0 assertion failures, my changed symbols in 0 failure traces. Trust CI for the integration tier.

Dependency / coordination

  • Requires @query-doctor/core@>=0.10.4 published (done) — it carries ServerApi.getProductionStats.
  • Counterpart to the merged Site-side slices: #3352 (relay RPC + GET endpoint), #3354 (MCP consume), and the #3353 Site-half indicator.

🤖 Generated with Claude Code

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Query Doctor Analysis

3 queries analyzed

0 regressed · 0 improved · 0 new · 0 removed

2 pre-existing issues

Using assumed statistics (10000000 rows/table). For better results, sync production stats.

More detail → get_ci_run({ runId: "019edcc2-921a-70af-92f7-a0254e49fa46" }) · view run · docs

At CI time, pull the project's stored production stats over the relay
RPC (getProductionStats, @query-doctor/core 0.10.4) and cost queries
with fromStatisticsExport when present, falling back to the synthetic
assumption otherwise. The resulting statisticsMode flows through to the
Site API payload, so runs modeled on real prod cardinality are labelled
as such instead of being scored on 10M-row / 0.9-correlation defaults.

Stats-mode precedence in determineStatsMode is now: API production
stats > explicit stats file > synthetic assumption. This replaces the
standing "grab recent stats from API if they exist" TODO.

Closes the analyzer half of #3353 (Query-Doctor/Site).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@veksen veksen force-pushed the feat-ci-consume-prod-stats branch from bf5bf26 to 3a1d2c3 Compare June 18, 2026 22:02
@veksen veksen marked this pull request as ready for review June 18, 2026 22:06
@veksen veksen merged commit f7b099f into main Jun 18, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant