From 3a662ec3268d72b664bdba95020d3f05592f01a9 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Sirois Date: Fri, 3 Apr 2026 08:29:01 +0400 Subject: [PATCH 1/2] fix: compute total from uploadable results instead of log entries The `total` counter was incrementing during log parsing, counting raw entries before deduplication and optimization. This caused the CI comment to show a different query count than the site, which only displays queries with uploadable states (improvements_available, no_improvement_found, error). Compute `total` from the deduplicated, optimized results filtered to uploadable states so the CI comment and site always agree. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/runner.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/runner.ts b/src/runner.ts index a48f15a..1058726 100644 --- a/src/runner.ts +++ b/src/runner.ts @@ -84,8 +84,6 @@ export class Runner { error = err; }); - let total = 0; - console.time("total"); const recentQueries: RecentQuery[] = []; for await (const chunk of stream) { @@ -134,7 +132,6 @@ export class Runner { continue; } - total++; const recentQuery = await RecentQuery.fromLogEntry(query, hash); recentQueries.push(recentQuery) } @@ -155,7 +152,7 @@ export class Runner { }); console.log( - `Matched ${this.remote.optimizer.validQueriesProcessed} queries out of ${total}`, + `Matched ${this.remote.optimizer.validQueriesProcessed} queries`, ); const recommendations: ReportIndexRecommendation[] = []; @@ -220,6 +217,9 @@ export class Runner { } } + const uploadableStates = new Set(["improvements_available", "no_improvement_found", "error"]); + const total = allResults.filter((q) => uploadableStates.has(q.optimization.state)).length; + const statistics = deriveIndexStatistics(filteredRecommendations); const timeElapsed = Date.now() - startDate.getTime(); const reportContext: ReportContext = { From 2d5aaa489b625f98ef41ea1d3d3da72b637e07f1 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Sirois Date: Fri, 3 Apr 2026 09:58:54 +0400 Subject: [PATCH 2/2] test: add tests for countUploadableQueries Extract UPLOADABLE_STATES and countUploadableQueries as exported functions so they can be tested. Tests verify: - Only improvements_available, no_improvement_found, error are counted - not_supported, timeout, waiting, optimizing are excluded - countUploadableQueries agrees with buildQueries for every state Co-Authored-By: Claude Opus 4.6 (1M context) --- src/runner.test.ts | 64 ++++++++++++++++++++++++++++++++++++++++++++++ src/runner.ts | 9 +++++-- 2 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 src/runner.test.ts diff --git a/src/runner.test.ts b/src/runner.test.ts new file mode 100644 index 0000000..0cf8b70 --- /dev/null +++ b/src/runner.test.ts @@ -0,0 +1,64 @@ +import { test, expect, describe } from "vitest"; +import { countUploadableQueries, UPLOADABLE_STATES } from "./runner.ts"; +import { buildQueries } from "./reporters/site-api.ts"; +import type { OptimizedQuery } from "./sql/recent-query.ts"; + +function fakeQuery(state: string): OptimizedQuery { + return { + optimization: { state }, + } as OptimizedQuery; +} + +describe("countUploadableQueries", () => { + test("counts improvements_available, no_improvement_found, and error", () => { + const results = [ + fakeQuery("improvements_available"), + fakeQuery("no_improvement_found"), + fakeQuery("error"), + ]; + expect(countUploadableQueries(results)).toBe(3); + }); + + test("excludes not_supported, timeout, waiting, optimizing", () => { + const results = [ + fakeQuery("not_supported"), + fakeQuery("timeout"), + fakeQuery("waiting"), + fakeQuery("optimizing"), + ]; + expect(countUploadableQueries(results)).toBe(0); + }); + + test("counts only uploadable in a mixed set", () => { + const results = [ + fakeQuery("improvements_available"), + fakeQuery("not_supported"), + fakeQuery("no_improvement_found"), + fakeQuery("timeout"), + fakeQuery("error"), + fakeQuery("waiting"), + ]; + expect(countUploadableQueries(results)).toBe(3); + }); +}); + +describe("UPLOADABLE_STATES matches buildQueries filter", () => { + test("buildQueries keeps exactly the same states as UPLOADABLE_STATES", () => { + const allStates = [ + "improvements_available", + "no_improvement_found", + "error", + "not_supported", + "timeout", + "waiting", + "optimizing", + ]; + + for (const state of allStates) { + const results = [fakeQuery(state)]; + const uploaded = buildQueries(results).length; + const counted = countUploadableQueries(results); + expect(counted, `state "${state}"`).toBe(uploaded); + } + }); +}); diff --git a/src/runner.ts b/src/runner.ts index 1058726..720e3a4 100644 --- a/src/runner.ts +++ b/src/runner.ts @@ -217,8 +217,7 @@ export class Runner { } } - const uploadableStates = new Set(["improvements_available", "no_improvement_found", "error"]); - const total = allResults.filter((q) => uploadableStates.has(q.optimization.state)).length; + const total = countUploadableQueries(allResults); const statistics = deriveIndexStatistics(filteredRecommendations); const timeElapsed = Date.now() - startDate.getTime(); @@ -247,4 +246,10 @@ export class Runner { } } +export const UPLOADABLE_STATES = new Set(["improvements_available", "no_improvement_found", "error"]); + +export function countUploadableQueries(results: OptimizedQuery[]): number { + return results.filter((q) => UPLOADABLE_STATES.has(q.optimization.state)).length; +} + export type QueryProcessResult = OptimizedQuery;