@@ -111,16 +111,26 @@ DESCRIPTION >
111111 - impactScoreRaw: MAX across the project's repos (each repo's own value is already a MAX over its
112112 published packages) — matches the spec's "MAX(packages.impact) over packages published by any
113113 repo in the project," since max-of-maxes = max-over-all.
114+ - healthScoreV2: sum of the three per-category medians below, null-guarded per IN-1248 (NULL when
115+ fewer than 2 categories are present). `quantileExactOrNull` is used instead of `quantileExact` so
116+ the guard and coalesce can see NULL explicitly — `quantileExact` returns 0 on an empty set, which
117+ would defeat the "< 2 categories → NULL" rule.
114118 - maintainerHealthScoreV2 / securitySupplyChainScoreV2 / developmentActivityScoreV2 (IN-1212):
115- independent per-category medians (`quantileExact(0.5)`) over repos where that category is non-NULL —
116- their repo set differs from healthScoreV2 (which includes repos with one imputed category), so they
117- do not necessarily reconcile with the project score. NULL when every repo is NULL for a category.
119+ independent per-category medians (`quantileExact(0.5)`) over repos where that category is non-NULL.
120+ NULL when every repo is NULL for a category.
118121
119122SQL >
120123 SELECT
121124 rep.insightsProjectId AS insightsProjectId,
122- quantileExact(0.5)
123- (hv2.healthScoreV2) AS healthScoreV2,
125+ if(
126+ (quantileExactOrNull(0.5)(hv2.maintainerHealthScoreV2) IS NOT NULL)
127+ + (quantileExactOrNull(0.5)(hv2.securitySupplyChainScoreV2) IS NOT NULL)
128+ + (quantileExactOrNull(0.5)(hv2.developmentActivityScoreV2) IS NOT NULL) < 2,
129+ NULL,
130+ coalesce(quantileExactOrNull(0.5)(hv2.maintainerHealthScoreV2), 0)
131+ + coalesce(quantileExactOrNull(0.5)(hv2.securitySupplyChainScoreV2), 0)
132+ + coalesce(quantileExactOrNull(0.5)(hv2.developmentActivityScoreV2), 0)
133+ ) AS healthScoreV2,
124134 if(
125135 empty(groupArray(hv2.lifecycleLabelV2)),
126136 NULL,
0 commit comments