Skip to content

Commit 83ad4e0

Browse files
NickB03claude
andcommitted
fix(evals): compute alarmCount from findings inside SuiteHeaderCard
No template ever populated config.alarmCount, so the 'X alarms' badge never rendered. Derive the count from computeFindings() using the suite's current snapshot ids so the badge self-wires from data. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 71e2b86 commit 83ad4e0

2 files changed

Lines changed: 31 additions & 5 deletions

File tree

components/evals/dashboard-v2/dashboard.test.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,26 @@ describe('EvalsDashboardV2', () => {
218218
expect(expanded[0].getAttribute('data-feed-row-id')).toBe('traf-latest')
219219
})
220220

221+
it('renders an alarm-count badge on the traffic-monitor suite header when findings exist', () => {
222+
// Scenario: traffic-monitor latest has a ≥5pt drop on response_quality vs
223+
// previous. computeFindings emits one 'drop' finding attached to latest.id.
224+
// TEMPLATE_B's traf-header sets showAlarmCount: true, so the badge should
225+
// self-wire and render "1 alarm".
226+
const data = makeData()
227+
data.trafficMonitor.previous!.evaluatorScores = {
228+
...data.trafficMonitor.previous!.evaluatorScores,
229+
response_quality: 0.92
230+
}
231+
data.trafficMonitor.latest!.evaluatorScores = {
232+
...data.trafficMonitor.latest!.evaluatorScores,
233+
response_quality: 0.8
234+
}
235+
236+
render(<EvalsDashboardV2 data={data} initialLayout="b" />)
237+
238+
expect(screen.getByText(/1 alarm/i)).toBeInTheDocument()
239+
})
240+
221241
it('getTemplate returns a template for every template id', () => {
222242
for (const id of ['a', 'b', 'c'] as const) {
223243
const tpl = getTemplate(id)

components/evals/widgets/suite-header-card.tsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import { formatDistanceToNow } from 'date-fns'
44
import { Activity, BarChart3 } from 'lucide-react'
55

6+
import { computeFindings } from '@/lib/evals/helpers/findings'
67
import type { HealthState } from '@/lib/evals/helpers/health-state'
78
import {
89
healthForScore,
@@ -29,7 +30,6 @@ type Config = {
2930
showChips?: boolean
3031
showSparkline?: boolean
3132
showAlarmCount?: boolean
32-
alarmCount?: number
3333
}
3434

3535
export function SuiteHeaderCard({
@@ -51,6 +51,14 @@ export function SuiteHeaderCard({
5151
suiteKey === 'capability' ? 0.9 : 0.85,
5252
suiteKey === 'capability' ? 0.75 : 0.7
5353
)
54+
const alarmCount = config.showAlarmCount
55+
? computeFindings(data).filter(
56+
f =>
57+
f.severity !== 'improvement' &&
58+
(f.snapshotId === latest.id ||
59+
f.snapshotId === (suite.previous?.id ?? ''))
60+
).length
61+
: 0
5462

5563
if (config.variant === 'rail') {
5664
return (
@@ -100,11 +108,9 @@ export function SuiteHeaderCard({
100108
{config.cadence}
101109
</Badge>
102110
) : null}
103-
{config.showAlarmCount &&
104-
config.alarmCount &&
105-
config.alarmCount > 0 ? (
111+
{alarmCount > 0 ? (
106112
<Badge variant="destructive" className="ml-auto">
107-
{config.alarmCount} alarm{config.alarmCount > 1 ? 's' : ''}
113+
{alarmCount} alarm{alarmCount > 1 ? 's' : ''}
108114
</Badge>
109115
) : null}
110116
</div>

0 commit comments

Comments
 (0)