feat: show partial Health Score label and capped total IN-1262 - #2145
feat: show partial Health Score label and capped total IN-1262#2145gaspergrom wants to merge 3 commits into
Conversation
Signed-off-by: Gašper Grom <gasper.grom@gmail.com>
There was a problem hiding this comment.
Pull request overview
Adds project-level partial Health Score labels and capped denominators using Tinybird-provided metadata.
Changes:
- Propagates partial-score fields through API responses and components.
- Updates gauges, pills, breakdowns, badges, tests, and documentation.
- Leaves repository-filtered scores non-partial by design.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
frontend/types/project.ts |
Adds partial-score fields. |
frontend/types/overview/responses.types.ts |
Extends overview response types. |
frontend/server/api/project/[slug]/overview/health-score-v2.get.ts |
Returns partial-score metadata. |
frontend/server/api/badge/health-score.ts |
Adds partial badge labels. |
frontend/config/trust-score.ts |
Adds partial detection and labeling. |
frontend/config/trust-score.test.ts |
Tests partial-score helpers. |
frontend/app/components/uikit/chart/configs/gauge.chart.ts |
Supports configurable gauge maxima. |
frontend/app/components/modules/project/views/overview.vue |
Passes capped maximum downstream. |
frontend/app/components/modules/project/components/overview/trust-score/health-score-ring.vue |
Displays capped ring totals. |
frontend/app/components/modules/project/components/overview/trust-score-v2.vue |
Adds partial labels and tooltip. |
frontend/app/components/modules/project/components/overview/health-breakdown-section.vue |
Shows capped breakdown totals. |
frontend/app/components/modules/collection/components/details/collection-project-item.vue |
Passes maximum to the desktop pill. |
frontend/app/components/modules/collection/components/details/collection-health-score-pill.vue |
Scales capped totals and progress. |
frontend/docs/metrics/health-score/index.md |
Documents partial scores. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| maintainerHealthScoreV2?: number | null; | ||
| securitySupplyChainScoreV2?: number | null; | ||
| developmentActivityScoreV2?: number | null; | ||
| healthMaxScore?: number | null; |
| :maintainer-health-score-v2="project.maintainerHealthScoreV2" | ||
| :security-supply-chain-score-v2="project.securitySupplyChainScoreV2" | ||
| :development-activity-score-v2="project.developmentActivityScoreV2" | ||
| :health-max-score="project.healthMaxScore" |
| - If **all 3 categories** are available, the Health Score is computed normally. | ||
| - If **exactly 1 category** is unavailable, the score is computed from the 2 available categories and shown with a **partial** indicator to signal that not all signals were observed. | ||
| - If **all 3 categories** are available, the Health Score is computed normally, out of a maximum of 100. | ||
| - If **exactly 1 category** is unavailable, the score is computed from the 2 available categories and shown out of a reduced maximum: 60 if Maintainer Health (40 pts) is missing, 65 if Security and Supply Chain (35 pts) is missing, or 75 if Development Activity (25 pts) is missing. The rating label carries a **" - Partial"** suffix (for example, "Healthy - Partial") to signal that not all categories were observed, and a tooltip next to the score explains which category is missing. |
Collections page pill sourced only healthMaxScore for progress-bar rescaling but rendered the bare band label, unlike the Health Breakdown section already patched for IN-1262. Reuse getHealthScoreV2Config/isPartialHealthScore, and pass healthMaxScore through the mobile card view that was missing it. Signed-off-by: Gašper Grom <gasper.grom@gmail.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.
Suppressed comments (2)
frontend/config/trust-score.ts:51
undefinedis treated as partial because it differs from bothnulland100. The badge caller passes the Tinybird field directly, so when the upstream response omits this newly added field—as the documented independent deploy path allows—the badge incorrectly renders"... - Partial". Treat a missing value the same asnulland add anundefinedregression case.
export const isPartialHealthScore = (healthMaxScore: number | null): boolean =>
healthMaxScore !== null && healthMaxScore !== 100;
frontend/docs/metrics/health-score/index.md:228
- The documentation says the tooltip identifies which category is missing, but the implemented tooltip only lists all three possibilities and never identifies one. Update this claim to match the UI (or derive the missing category from
healthMaxScore).
- If **exactly 1 category** is unavailable, the score is computed from the 2 available categories and shown out of a reduced maximum: 60 if Maintainer Health (40 pts) is missing, 65 if Security and Supply Chain (35 pts) is missing, or 75 if Development Activity (25 pts) is missing. The rating label carries a **" - Partial"** suffix (for example, "Healthy - Partial") to signal that not all categories were observed, and a tooltip next to the score explains which category is missing.
| <lfx-tooltip | ||
| v-if="isPartial" | ||
| placement="top" | ||
| > | ||
| <lfx-icon |
Signed-off-by: Gašper Grom <gasper.grom@gmail.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 14 out of 14 changed files in this pull request and generated no new comments.
Suppressed comments (2)
frontend/app/components/modules/collection/components/details/collection-health-score-pill.vue:130
- This component has an existing regression suite in
frontend/test/collection-detail-components.test.ts, but the new partial path is not covered. Please add a case with a cappedhealthMaxScorethat asserts the- Partiallabel, reduced denominator, and rescaled progress value, plus the null/100 fallback, so these coupled display calculations cannot regress independently.
const progressBarValue = computed(() => (props.score / (props.healthMaxScore ?? 100)) * 100);
frontend/app/components/modules/project/components/overview/trust-score-v2.vue:48
- The new explanation is only reachable through
LfxTooltip, which hardcodes a hover trigger, and its slottedLfxIconrenders a non-focusable<i>. Keyboard and touch users therefore cannot discover which category is missing. Please expose this text through a focus/click-capable, labelled control (or render it inline) so the partial-score explanation is available without hover.
<lfx-tooltip
v-if="isPartial"
placement="top"
>
<lfx-icon
Summary
project_insightsfields (coveredCategoryCount,healthMaxScore) added in crowd.dev#4548 to show a "- Partial" suffix on the Health Score label and cap the displayed total at the reduced max (e.g. "45 out of 65" instead of "out of 100") when exactly one of the three v2 categories is missing data.isPartialHealthScore()treats anyhealthMaxScoreother thannullor100as partial, so the UI never recomputes category coverage itself — Tinybird is the single source of truth for whether a score is partial and what its denominator is.repo_health_score_v2_breakdown(repo-scoped queries): that pipe has nocoveredCategoryCount/healthMaxScorefields, so a repo-filtered selection always renders as non-partial (healthMaxScore: null) by design — this PR does not add partial support at the repo level.Changes
frontend/config/trust-score.tsgetHealthScoreV2Config()takes anisPartialflag and appends "- Partial" to the label; addsisPartialHealthScore(healthMaxScore)frontend/config/trust-score.test.tsfrontend/server/api/badge/health-score.tshealthMaxScoreand passes it throughisPartialHealthScore()togetHealthScoreV2Config()frontend/server/api/project/[slug]/overview/health-score-v2.get.tscoveredCategoryCount/healthMaxScorethrough fromproject_insights; hardcodes both tonullon the repo-filtered branch, which reads fromrepo_health_score_v2_breakdownfrontend/types/project.tscoveredCategoryCount,healthMaxScoretoProjectInsightsTinybirdandProjectInsightsfrontend/types/overview/responses.types.tsHealthScoreV2Resultsfrontend/app/components/modules/project/components/details/collection-health-score-pill.vuefrontend/app/components/modules/project/components/details/collection-project-item.vuefrontend/app/components/modules/project/components/overview/health-breakdown-section.vuefrontend/app/components/modules/project/components/overview/trust-score-v2.vuecoveredCategoryCount/healthMaxScoreinto the score display and adds the partial tooltipfrontend/app/components/modules/project/components/overview/trust-score/health-score-ring.vuefrontend/app/components/modules/project/views/overview.vuefrontend/app/components/uikit/chart/configs/gauge.chart.tsfrontend/docs/metrics/health-score/index.mdJIRA
IN-1262 — Implement Partial Health Score labels and capped totals for projects with 1 missing category
Deploy order
coveredCategoryCount/healthMaxScoreto theproject_insightsTinybird pipe that this PR reads.healthMaxScoreis absent/undefined from the pipe response,isPartialHealthScore()treats that as non-partial, and the UI falls back to the legacy "out of 100" display with no suffix. Once step 1 is live, real partial data renders without a further insights deploy.DB migrations
No DB migrations.
Test plan
pnpm test --runinfrontend/: 249/249 tests passed across 42/42 files. The process itself exits non-zero only from a pre-existingCannot find dependency 'vitest-environment-nuxt'warning in the local dev environment, confirmed via git-stash isolation to predate this branch.pnpm run tsc-checkpasses clean.repo_health_score_v2_breakdowndoesn't carry the two new fields./api/badge/health-score) reflects "- Partial" in its label text for a partial project.Known issue (not fixed in this PR)
QA surfaced a pre-existing bug in
frontend/server/api/badge/health-score.tswhile exercising this feature's badge code path: the handler never validates that theprojectquery param is present before callingfetchFromTinybird({ slug: project }). An omittedprojectparam currently falls through to a 302 redirect built from fallback/undefined-slug data instead of a 404 or 400. This predates and is unrelated to this ticket's changes — reporting it here, not fixing it under IN-1262.Checklist
git commit --signoff -Son every commit — single commit1bb517ddf, signed off.