Skip to content

fix: render signal-scores heatmap as a true percentile-band distribution IN-1304 - #2213

Merged
gaspergrom merged 1 commit into
mainfrom
fix/IN-1304-signal-scores-decile-heatmap
Sep 16, 2026
Merged

gaspergrom merged 1 commit into
mainfrom
fix/IN-1304-signal-scores-decile-heatmap

Conversation

@gaspergrom

Copy link
Copy Markdown
Collaborator

Summary

The "Where the strongest repositories pull ahead" heatmap (added in #2204) only plotted two data points per signal — top-20% and median — recolored as heatmap cells instead of bars. That doesn't deliver an actual percentile distribution, just the same two-point comparison in a different chart type.

This switches the widget to a genuine percentile-band heatmap: 11 signals × 10 columns (10th through 100th percentile, in steps of 10), so each row shows the real spread of repository scores across the whole range.

  • types/report/health-score-coverage-signal-scores.types.ts — row/data shapes now carry all 10 percentile columns (p10_pct..p100_pct) instead of p80_pct/median_pct
  • server/data/tinybird/report/health-score-coverage-signal-scores.ts — mapper updated to the new shape
  • signal-scores.vue — heatmap now renders 10 columns with "10th"..."Max" labels; tooltip shows the exact percentile and percentage on hover
  • Tests updated to the new row/data shape

Deploy ordering — read before merging

This depends on a companion pipe change: linuxfoundation/crowd.dev#4637, which extends health_score_report_signal_scores to return the 10 percentile columns instead of p80_pct/median_pct.

That pipe has NOT been deployed to production yet — it's a breaking schema change and deploying it before this frontend PR is live would break the widget silently (rendering undefined values with no error). Deploy order must be:

  1. Merge and deploy this frontend PR (or have it ready to deploy immediately)
  2. Push crowd.dev#4637's pipe to production
  3. Confirm the live widget renders correctly against the new pipe output

Do not push the pipe to production ahead of this PR going live, and don't merge this PR expecting it to auto-deploy days before the pipe does — coordinate the two.

Test plan

  • pnpm tsc-check — clean
  • pnpm lint:fix — 0 errors (pre-existing unrelated warnings only)
  • Unit tests for the mapper updated and passing
  • Visually verified the heatmap renders correctly (10 columns, correct labels, working hover tooltips) via a temporary local mock standing in for the not-yet-deployed pipe response — reverted before commit, not part of this diff
  • Final live verification against the real production pipe, once crowd.dev#4637 deploys

…ion IN-1304

The previous heatmap only plotted top-20% vs median per signal - two data
points recolored as heatmap cells, not an actual distribution. Switch to
the full p10-p100 decile spread (matching a backend pipe change that
extends health_score_report_signal_scores to return 10 percentile columns
instead of p80/median), so each row shows where a signal genuinely spreads
repositories apart across the whole range, not just at two fixed points.

Depends on linuxfoundation/crowd.dev#4637 deploying to production before
this can go live - the pipe currently still serves the old p80_pct/median_pct
shape, so this frontend change must not deploy ahead of that pipe push, or
the widget will render undefined values.

Signed-off-by: Gašper Grom <gasper.grom@gmail.com>
Copilot AI balanced review requested due to automatic review settings September 16, 2026 02:51

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Updates the signal-scores widget to visualize ten percentile points per signal, dependent on the companion Tinybird schema change.

Changes:

  • Adds percentile types and mapping.
  • Expands the heatmap and tooltip to ten columns.
  • Updates mapper tests.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
health-score-coverage-signal-scores.types.ts Defines percentile data shapes.
health-score-coverage-signal-scores.ts Maps Tinybird percentile fields.
health-score-coverage-signal-scores.test.ts Updates mapper fixtures and assertions.
signal-scores.vue Renders the expanded heatmap.

Note

Copilot is running an experiment and ran this review at Balanced.


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +29 to +33
percentiles: Object.fromEntries(
SIGNAL_SCORE_PERCENTILES.map((p) => [
p,
row[`p${p}_pct` as keyof HealthScoreCoverageSignalScoreRow] as number,
]),
Comment on lines +126 to +127
const percentileLabel = (p: (typeof SIGNAL_SCORE_PERCENTILES)[number]): string => (p === 100 ? 'Max' : `${p}th`);
const columns = SIGNAL_SCORE_PERCENTILES.map(percentileLabel);
Comment on lines +203 to +206
const percentile = SIGNAL_SCORE_PERCENTILES[columnIndex];
if (!signal || percentile === undefined) return '';
const columnLabel = percentile === 100 ? 'Highest scoring repositories' : `${percentile}th percentile`;
return `${rowLabel(signal)}<br/>${columnLabel}: ${percent}%`;
@gaspergrom
gaspergrom requested a review from epipav September 16, 2026 03:02
@themarolt
themarolt self-requested a review September 16, 2026 04:53
percentiles: Object.fromEntries(
SIGNAL_SCORE_PERCENTILES.map((p) => [
p,
row[`p${p}_pct` as keyof HealthScoreCoverageSignalScoreRow] as number,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

per the PR's own deploy order (frontend first, pipe second), this reads the old-shape row until #4637 ships - row['p10_pct'] etc. don't exist on that row, so 8 of 10 percentiles come back undefined and the chart renders NaN cells in prod. /api/report/health-score-coverage/** is cached in redis for a day, so that stretches past the pipe deploy too unless the cache gets purged. worth making this additive (fall back to the old columns when the new ones are missing) or purging the cache as part of the deploy step - or is the plan to accept a short NaN window and purge manually?

@gaspergrom
gaspergrom merged commit 3e116a4 into main Sep 16, 2026
11 checks passed
@gaspergrom
gaspergrom deleted the fix/IN-1304-signal-scores-decile-heatmap branch September 16, 2026 09:01
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.

4 participants