project-nomad/admin/inertia/lib/benchmarkScore.ts
chriscrosstalk 03db9da24a
fix(benchmark): partial runs are not the NOMAD Score (relabel + renormalize) (#1088)
A System-Only or AI-Only run is a partial result, not the NOMAD Score
(which is the full-benchmark composite). Two problems addressed:

1. Scoring bug: AI-only runs were NOT renormalized. _calculateNomadScore
   always added the system weights (0.60) to the denominator even for an
   AI-only run (default-zero system scores), so an excellent AI-only run
   scored ~39.8 -- scaled against the full NOMAD 100 where AI is only 40%
   -- while system-only already renormalized correctly. Fix: pass
   systemScores only when the system benchmarks actually ran, so AI-only
   renormalizes to its own 0-100 (39.8 -> ~99.7). Full and System-only
   scores are unchanged.

2. Presentation: partial runs were shown with the full "NOMAD Score"
   label + big gauge, outweighing the small "Partial" notice. Now partial
   runs are relabelled "System Score" / "AI Score" with a PARTIAL badge,
   a muted (neutral) gauge + number, and a "run a Full Benchmark for your
   NOMAD Score" CTA -- applied to both the persistent score section and
   the Phase 3 ScoreReveal via a shared getScoreDisplay() helper. Adds a
   `muted` prop to CircularGauge.

Browser-validated on NOMAD3: AI-only now shows "AI Score" + PARTIAL,
muted gauge, 99.7 (was 39.8); Full still shows "NOMAD Score" green.
Implements the display-layer fix from the Score v2 red-team's W2; the
AI-ceiling saturation (W1) remains v2 work.

Part of #1082.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-04 03:37:41 +00:00

34 lines
1.2 KiB
TypeScript

import type { BenchmarkType } from '../../types/benchmark'
/**
* How a benchmark result's headline score should be presented. A partial run
* (System Only / AI Only) is NOT the NOMAD Score -- the NOMAD Score is the full
* benchmark composite -- so partial results are relabelled and flagged to avoid
* users mistaking a partial number for their NOMAD Score. The stored score for
* a partial run is already renormalized to that category's own 0-100 range
* (see BenchmarkService._calculateNomadScore).
*/
export function getScoreDisplay(type: BenchmarkType): {
label: string
isPartial: boolean
/** Which full benchmark to run to get the real NOMAD Score, for the CTA copy. */
cta: string
} {
switch (type) {
case 'system':
return {
label: 'System Score',
isPartial: true,
cta: 'This is a partial result, not your NOMAD Score. Run a Full Benchmark to get your NOMAD Score.',
}
case 'ai':
return {
label: 'AI Score',
isPartial: true,
cta: 'This is a partial result, not your NOMAD Score. Run a Full Benchmark to get your NOMAD Score.',
}
default:
return { label: 'NOMAD Score', isPartial: false, cta: '' }
}
}