Repository navigation
fix(stats): round global prCount at the per-year boundary - #71
Open
detail-app[bot] wants to merge 1 commit into
Open
detail-app[bot] wants to merge 1 commit into
detail-app[bot] wants to merge 1 commit into
Conversation
Contributor
🤖 Augment PR SummarySummary: This PR fixes an inconsistency between the global and yearly outcome statistics. Changes:
Technical Notes: The change makes the global 🤖 Was this summary useful? React with 👍 or 👎 |
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.
Detail bug report: View on Detail
Bug
The unauthenticated
statOutcomes(global) andstatOutcomesByYear(per-year breakdown) endpoints both return the sameStatOutcomestype with anInt prCount, but they rounded that field at different aggregation boundaries:Math.round(Σ_all_years fractional_sum)— oneMath.roundon the aggregate.Math.round(fractional_sum)per year-group, leaving callers to sum.For pre-2025 years
prCountuses the fractional estimatorPRE_2025_PR_RATE = 0.71, soround(Σ f_i) ≠ Σ round(f_i)once pre-2025 events span ≥2 year-groups. Concrete case: two pre-2025 years with 1 matched project each → per-year givesround(0.71)+round(0.71)=2, global gaveround(1.42)=1. The two views of the same field could disagree, with no in-repo consumer to notice. Introduced when the endpoints were added ina18bd13.Fix
Round
prCountat the same per-year-group boundary in both endpoints, so the global value is definitionally equal to the sum of the breakdown:GROUP BYquery into a single sharedprojectsByYearQuery()used by bothcomputeStatOutcomesandcomputeStatOutcomesByYear. The standalone global-aggregateprCountSQL is removed.prCountis nowprojectsByYear.reduce((acc, y) => acc + Math.round(y.prCount), 0)— the sum of the already-rounded per-year values.Sharing the query structurally prevents the two rounding boundaries from drifting apart again, and the
reduce(vs. the oldprCount[0].prCountindexing) is robust to an emptyGROUP BYresult.Testing
src/resolvers/Stats.test.ts): added a regression guard, run withnpx ts-node --transpile-only. It stubs Prisma and calls the privatecompute*methods directly to bypass the 1-hourttlCache. It verifies the headline divergent case (two pre-2025 years → globalprCountis 2, not 1), the empty/no-matched-project path returns 0 without crashing, that allStatOutcomesfields reconcile globally vs. the sum of the per-year view, and the structural invariant that both endpoints issue exactly one shared prCount-shaped query. Reverting the fix makes the suite fail; restoring makes it pass.npx tsc --skipLibCheck --noEmit) passes clean.src/resolvers/Review.test.ts) still passes — shared test infrastructure (env seeding, typediContainer, decorator metadata) is undisturbed.npx eslinton the changed files fails with aDeprecationError: 'originalKeywordKind'parser error, but this is a pre-existing, repo-wide incompatibility between the pinnedeslint@7and the installedtypescript@5.2.2— it reproduces identically on the unchangedReview.test.ts. No new source-level findings are introduced.npx prisma db push --force-reset(prisma migrate deployfails on a pre-existing, unrelated migration-ordering bug in the repo). Seeded Events for 2022, 2023, and 2025 withMATCHEDprojects (2025 with 3/5 carrying aprUrl), started a fresh GraphQL server process per variant, and issued a single unauthenticated query against both endpoints over HTTP. The populated seed returnedstatOutcomes.prCount = 5reconciling with per-year1+1+3 = 5(the old aggregate behavior would have givenround(4.42) = 4); an empty-seed variant returnedprCount = 0andstatOutcomesByYear = []without error. The resolver-level e2e was also confirmed to fail against the unfixed code and pass with the fix.Automatic Fixes PRs can be configured here.