Skip to content

feat(studio): score-driven Safe Synthesizer report gauges [ASTD-310]#849

Open
marcusds wants to merge 3 commits into
mainfrom
astd-310-report-colors-quality-privacy-swap/mschwab
Open

feat(studio): score-driven Safe Synthesizer report gauges [ASTD-310]#849
marcusds wants to merge 3 commits into
mainfrom
astd-310-report-colors-quality-privacy-swap/mschwab

Conversation

@marcusds

@marcusds marcusds commented Jul 22, 2026

Copy link
Copy Markdown
Contributor
Screenshot 2026-07-23 at 9 10 11 AM

Summary

Fixes ASTD-310 — SQS/DPS gauge colors swapped between the Safe Synthesizer report summary and detail views.

Rather than picking a canonical blue/purple mapping, this aligns Studio with the redesigned evaluation report (NVIDIA-NeMo/Safe-Synthesizer#653), which drives gauge color off the score value, not the metric. Because both SQS and DPS use identical score-tier coloring in every view, the summary/detail mismatch can no longer occur.

Changes

  • New ScoreGauge (packages/common), replacing Dial:
    • lg: red→green gradient ring + white score marker + N / of 10 center (report summary + detail main gauges).
    • sm: single-tier ring for sub-metrics and the jobs table.
    • Exports scoreColor / scoreTier / SCORE_TIER_COLORS. Tiers: ≥8 #22c55e, ≥6 #84cc16, ≥4 #eab308, ≥2 #f97316, else #ef4444; 0/NaN → gray.
  • Migrated all four Dial consumers (ReportSummaryPanel, TitledDial, ScoreTable, SafeSynthesizerJobsDataView) and dropped every per-metric color prop.
  • Retired the now-unused Dial component (+ test + barrel export).

Test plan

  • @nemo/common suite — 1319 passed (incl. new ScoreGauge tests)
  • Report summary + ScorePanel tests — 40 passed (reworked off old dial-color assertions)
  • @nemo/common typecheck + eslint clean
  • Studio typecheck has 2 pre-existing failures unrelated to this change (axe-core, ExperimentGroupDataView)

Notes

Summary by CodeRabbit

Summary

  • New Features

    • Introduced ScoreGauge, a tier-colored score visualization with segmented gradients, a marker, and an unavailable state shown as “—”.
  • Changes

    • Replaced Dial-based quality/privacy gauges across job views and score panels/tables with ScoreGauge, using the raw 0–10 score values and updated unavailable/formatting behavior.
  • Tests

    • Added and updated Jest/RTL coverage to validate tier mapping, unavailable handling, score clamping, and the new gauge rendering.

Replace the fixed blue/purple SQS/DPS dials with a score-driven ScoreGauge
matching the redesigned evaluation report (NVIDIA-NeMo/Safe-Synthesizer#653):
a red->green gradient ring with a score marker for large gauges and a
single-tier ring for sub-metrics. Gauge color is now a function of the score
tier, identical for both metrics in every view, so the summary/detail color
mismatch (ASTD-310) can no longer occur.

Migrate all four Dial consumers (report summary, detail panels, score table,
jobs data view), drop the per-metric color props, and retire the now-unused
Dial component.

Signed-off-by: mschwab <[email protected]>
@marcusds
marcusds requested review from a team as code owners July 22, 2026 21:18
@github-actions github-actions Bot added the feat label Jul 22, 2026
@marcusds
marcusds marked this pull request as draft July 22, 2026 21:23
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

ScoreGauge replaces Dial, classifies raw 0–10 scores, renders SVG gauge states, and is integrated into Safe Synthesizer panels, summaries, tables, and job-list columns. Tests now validate score propagation, clamping, tier colors, and unavailable values.

Sequence Diagram(s)

sequenceDiagram
  participant ScorePanel
  participant TitledDial
  participant ScoreGauge
  participant SVG
  ScorePanel->>TitledDial: pass raw score
  TitledDial->>ScoreGauge: render large gauge
  ScoreGauge->>SVG: draw tier arcs and marker
  SVG-->>ScoreGauge: render score or unavailable state
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly reflects the main change: migrating Safe Synthesizer gauges to score-driven rendering.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch astd-310-report-colors-quality-privacy-swap/mschwab

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
web/packages/common/src/components/ScoreGauge/index.test.tsx (1)

45-65: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

No component-level test for score clamping.

scoreTier/scoreColor are tested against negative/NaN inputs, but ScoreGauge itself is never rendered with a score >10 or negative to verify the clamp (Math.min(Math.max(score, 0), 10), Line 87 of index.tsx) actually caps the displayed/percentage output.

✅ Suggested additional test
+  it('clamps an out-of-range score to 10', () => {
+    render(<ScoreGauge score={15} size="lg" />);
+    expect(screen.getByTestId('gauge-display')).toHaveTextContent('10.0');
+  });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/packages/common/src/components/ScoreGauge/index.test.tsx` around lines 45
- 65, Extend the ScoreGauge tests to render scores above 10 and below 0,
verifying the component clamps them to the 0–10 range in both displayed value
and progress/percentage output. Add these cases alongside the existing tests in
the ScoreGauge describe block, using the gauge-display and relevant progress or
marker attributes to assert the clamped results.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@web/packages/studio/src/routes/SafeSynthesizerJobReportRoute/components/ScorePanels/TitledDial.tsx`:
- Line 6: Update the React import in TitledDial.tsx to use a type-only import
for FC, since FC is referenced only as a type.

---

Nitpick comments:
In `@web/packages/common/src/components/ScoreGauge/index.test.tsx`:
- Around line 45-65: Extend the ScoreGauge tests to render scores above 10 and
below 0, verifying the component clamps them to the 0–10 range in both displayed
value and progress/percentage output. Add these cases alongside the existing
tests in the ScoreGauge describe block, using the gauge-display and relevant
progress or marker attributes to assert the clamped results.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 46b1ba93-74d7-4f09-9311-db7266cfb867

📥 Commits

Reviewing files that changed from the base of the PR and between 80deef9 and 29667d1.

📒 Files selected for processing (14)
  • web/packages/common/src/components/Dial/index.test.tsx
  • web/packages/common/src/components/Dial/index.tsx
  • web/packages/common/src/components/ScoreGauge/index.test.tsx
  • web/packages/common/src/components/ScoreGauge/index.tsx
  • web/packages/common/src/components/index.ts
  • web/packages/studio/src/components/dataViews/SafeSynthesizerJobsDataView/index.tsx
  • web/packages/studio/src/routes/SafeSynthesizerJobDetailsRoute/components/ReportSummaryPanel.test.tsx
  • web/packages/studio/src/routes/SafeSynthesizerJobDetailsRoute/components/ReportSummaryPanel.tsx
  • web/packages/studio/src/routes/SafeSynthesizerJobReportRoute/components/ScorePanels/DataPrivacyPanel.test.tsx
  • web/packages/studio/src/routes/SafeSynthesizerJobReportRoute/components/ScorePanels/DataPrivacyPanel.tsx
  • web/packages/studio/src/routes/SafeSynthesizerJobReportRoute/components/ScorePanels/ScoreTable.tsx
  • web/packages/studio/src/routes/SafeSynthesizerJobReportRoute/components/ScorePanels/SyntheticQualityPanel.test.tsx
  • web/packages/studio/src/routes/SafeSynthesizerJobReportRoute/components/ScorePanels/SyntheticQualityPanel.tsx
  • web/packages/studio/src/routes/SafeSynthesizerJobReportRoute/components/ScorePanels/TitledDial.tsx
💤 Files with no reviewable changes (2)
  • web/packages/common/src/components/Dial/index.test.tsx
  • web/packages/common/src/components/Dial/index.tsx

@marcusds
marcusds marked this pull request as ready for review July 23, 2026 16:17
- Use a type-only import for FC in TitledDial
- Add ScoreGauge test covering out-of-range score clamping

Signed-off-by: mschwab <[email protected]>
@marcusds
marcusds force-pushed the astd-310-report-colors-quality-privacy-swap/mschwab branch from 7bb8baf to 649a61e Compare July 23, 2026 16:20
@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor
Suite Lines Covered Line Rate Branch Rate
Unit Tests 27117/34832 77.8% 62.1%
Integration Tests 15921/33544 47.5% 19.9%

…D-310]

Move the score-tier constants and gauge geometry into consts.ts and the
pure helper functions into utils.ts. index.tsx keeps only the component and
re-exports both modules so existing import paths are unchanged.

Signed-off-by: mschwab <[email protected]>

@coderabbitai coderabbitai Bot 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.

🧹 Nitpick comments (2)
web/packages/common/src/components/ScoreGauge/utils.ts (1)

16-53: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Prefer arrow functions for the short pure helpers.

Convert scoreTier, scoreColor, point, arcPath, and interpolate to exported arrow-function constants; none require hoisting.

As per coding guidelines, “Prefer arrow functions for short, pure functions in TypeScript.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/packages/common/src/components/ScoreGauge/utils.ts` around lines 16 - 53,
Convert the exported pure helpers scoreTier, scoreColor, point, arcPath, and
interpolate from function declarations to exported arrow-function constants,
preserving their parameters, return types, and existing logic.

Source: Coding guidelines

web/packages/common/src/components/ScoreGauge/index.tsx (1)

25-29: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Annotate the public component return type.

ScoreGauge is exported without an explicit return type. Add the repository’s standard React element return annotation.

As per coding guidelines, “Use explicit return types for public APIs and complex functions in TypeScript.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/packages/common/src/components/ScoreGauge/index.tsx` around lines 25 -
29, Update the exported ScoreGauge component’s signature to include the
repository-standard explicit React element return type, while preserving its
existing props, calculations, and rendering behavior.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@web/packages/common/src/components/ScoreGauge/index.tsx`:
- Around line 25-29: Update the exported ScoreGauge component’s signature to
include the repository-standard explicit React element return type, while
preserving its existing props, calculations, and rendering behavior.

In `@web/packages/common/src/components/ScoreGauge/utils.ts`:
- Around line 16-53: Convert the exported pure helpers scoreTier, scoreColor,
point, arcPath, and interpolate from function declarations to exported
arrow-function constants, preserving their parameters, return types, and
existing logic.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 675ce020-a36a-4554-b293-2bf980a8cfed

📥 Commits

Reviewing files that changed from the base of the PR and between 649a61e and c3335d1.

📒 Files selected for processing (3)
  • web/packages/common/src/components/ScoreGauge/consts.ts
  • web/packages/common/src/components/ScoreGauge/index.tsx
  • web/packages/common/src/components/ScoreGauge/utils.ts

@marcusds
marcusds added this pull request to the merge queue Jul 23, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants