From 47e1ccc162e887d9b97031091398933f9f5359a3 Mon Sep 17 00:00:00 2001 From: adibarra <93070681+adibarra@users.noreply.github.com> Date: Wed, 1 Apr 2026 17:17:32 -0500 Subject: [PATCH 01/12] feat: add "Add to chart" buttons to changelog and remove intermediate dates picker --- .../components/inference/ui/ChartControls.tsx | 36 +------- .../components/inference/ui/ChartDisplay.tsx | 16 +++- .../inference/ui/ComparisonChangelog.test.ts | 92 +++++++++++++++++++ .../inference/ui/ComparisonChangelog.tsx | 79 +++++++++++++--- .../hooks/api/use-comparison-changelogs.ts | 11 +-- 5 files changed, 173 insertions(+), 61 deletions(-) create mode 100644 packages/app/src/components/inference/ui/ComparisonChangelog.test.ts diff --git a/packages/app/src/components/inference/ui/ChartControls.tsx b/packages/app/src/components/inference/ui/ChartControls.tsx index d322202..48d3f6f 100644 --- a/packages/app/src/components/inference/ui/ChartControls.tsx +++ b/packages/app/src/components/inference/ui/ChartControls.tsx @@ -10,7 +10,6 @@ import { } from '@/components/ui/chart-selectors'; import { DateRangePicker } from '@/components/ui/date-range-picker'; import { LabelWithTooltip } from '@/components/ui/label-with-tooltip'; -import { MultiDatePicker } from '@/components/ui/multi-date-picker'; import { MultiSelect } from '@/components/ui/multi-select'; import { Select, @@ -76,14 +75,9 @@ const GROUPED_Y_AXIS_OPTIONS = METRIC_GROUPS.map((group) => ({ interface ChartControlsProps { /** Hide GPU Config selector and related date pickers (used by Historical Trends tab) */ hideGpuComparison?: boolean; - /** Intermediate dates within the comparison range that have changelog entries */ - intermediateDates?: string[]; } -export default function ChartControls({ - hideGpuComparison = false, - intermediateDates = [], -}: ChartControlsProps) { +export default function ChartControls({ hideGpuComparison = false }: ChartControlsProps) { const { selectedModel, setSelectedModel, @@ -99,8 +93,6 @@ export default function ChartControls({ availableGPUs, selectedDateRange, setSelectedDateRange, - selectedDates, - setSelectedDates, dateRangeAvailableDates, isCheckingAvailableDates, availablePrecisions, @@ -345,32 +337,6 @@ export default function ChartControls({ /> )} - - {!hideGpuComparison && - selectedGPUs.length > 0 && - selectedDateRange.startDate && - selectedDateRange.endDate && - intermediateDates.length > 0 && ( -
- - { - setSelectedDates(value); - track('inference_intermediate_dates_selected', { - dates: value.join(','), - }); - }} - availableDates={intermediateDates} - maxDates={2} - placeholder="Select intermediate dates" - /> -
- )} diff --git a/packages/app/src/components/inference/ui/ChartDisplay.tsx b/packages/app/src/components/inference/ui/ChartDisplay.tsx index e799b2a..868c932 100644 --- a/packages/app/src/components/inference/ui/ChartDisplay.tsx +++ b/packages/app/src/components/inference/ui/ChartDisplay.tsx @@ -111,6 +111,8 @@ export default function ChartDisplay() { selectedE2eXAxisMetric, selectedGPUs, selectedPrecisions, + selectedDates, + setSelectedDates, selectedDateRange, dateRangeAvailableDates, selectedModel, @@ -127,7 +129,6 @@ export default function ChartDisplay() { const { changelogs, - intermediateDates, loading: changelogsLoading, totalDatesQueried, } = useComparisonChangelogs(selectedGPUs, selectedDateRange, dateRangeAvailableDates); @@ -677,7 +678,7 @@ export default function ChartDisplay() { - + {selectedGPUs.length === 0 && } {selectedGPUs.length > 0 && ( @@ -687,6 +688,17 @@ export default function ChartDisplay() { selectedPrecisions={selectedPrecisions} loading={changelogsLoading} totalDatesQueried={totalDatesQueried} + selectedDates={selectedDates} + selectedDateRange={selectedDateRange} + onAddDate={(date) => { + if (!selectedDates.includes(date)) { + setSelectedDates([...selectedDates, date]); + } + }} + onAddAllDates={(dates) => { + const merged = [...new Set([...selectedDates, ...dates])]; + setSelectedDates(merged); + }} /> )} diff --git a/packages/app/src/components/inference/ui/ComparisonChangelog.test.ts b/packages/app/src/components/inference/ui/ComparisonChangelog.test.ts new file mode 100644 index 0000000..2f3c519 --- /dev/null +++ b/packages/app/src/components/inference/ui/ComparisonChangelog.test.ts @@ -0,0 +1,92 @@ +import { describe, expect, it } from 'vitest'; + +/** + * Tests for the "add to chart" logic used in ComparisonChangelog. + * Verifies date filtering: which dates are on chart, which are addable. + */ + +interface MockChangelog { + date: string; + entries: { config_keys: string[]; description: string; pr_link: string | null }[]; +} + +function computeDatesOnChart( + selectedDates: string[], + selectedDateRange: { startDate: string; endDate: string }, +): Set { + const set = new Set(selectedDates); + if (selectedDateRange.startDate) set.add(selectedDateRange.startDate); + if (selectedDateRange.endDate) set.add(selectedDateRange.endDate); + return set; +} + +function computeAddableDates( + filteredChangelogs: MockChangelog[], + datesOnChart: Set, +): string[] { + return filteredChangelogs.map((c) => c.date).filter((d) => !datesOnChart.has(d)); +} + +const changelogs: MockChangelog[] = [ + { + date: '2026-01-15', + entries: [{ config_keys: ['dsr1-fp8-h200-sglang'], description: 'Update', pr_link: null }], + }, + { + date: '2026-01-20', + entries: [{ config_keys: ['dsr1-fp8-h200-sglang'], description: 'Bump', pr_link: null }], + }, + { + date: '2026-01-25', + entries: [{ config_keys: ['dsr1-fp8-h200-sglang'], description: 'Tweak', pr_link: null }], + }, +]; + +describe('ComparisonChangelog add-to-chart logic', () => { + it('all dates are addable when none are selected', () => { + const onChart = computeDatesOnChart([], { startDate: '', endDate: '' }); + const addable = computeAddableDates(changelogs, onChart); + expect(addable).toEqual(['2026-01-15', '2026-01-20', '2026-01-25']); + }); + + it('dates in selectedDates are marked as on chart', () => { + const onChart = computeDatesOnChart(['2026-01-15', '2026-01-20'], { + startDate: '', + endDate: '', + }); + expect(onChart.has('2026-01-15')).toBe(true); + expect(onChart.has('2026-01-20')).toBe(true); + expect(onChart.has('2026-01-25')).toBe(false); + const addable = computeAddableDates(changelogs, onChart); + expect(addable).toEqual(['2026-01-25']); + }); + + it('range endpoints are marked as on chart', () => { + const onChart = computeDatesOnChart([], { + startDate: '2026-01-15', + endDate: '2026-01-25', + }); + expect(onChart.has('2026-01-15')).toBe(true); + expect(onChart.has('2026-01-25')).toBe(true); + const addable = computeAddableDates(changelogs, onChart); + expect(addable).toEqual(['2026-01-20']); + }); + + it('addable excludes both selectedDates and range endpoints', () => { + const onChart = computeDatesOnChart(['2026-01-20'], { + startDate: '2026-01-15', + endDate: '2026-01-25', + }); + const addable = computeAddableDates(changelogs, onChart); + expect(addable).toEqual([]); + }); + + it('returns empty addable when all dates are already on chart', () => { + const onChart = computeDatesOnChart(['2026-01-15', '2026-01-20', '2026-01-25'], { + startDate: '', + endDate: '', + }); + const addable = computeAddableDates(changelogs, onChart); + expect(addable).toEqual([]); + }); +}); diff --git a/packages/app/src/components/inference/ui/ComparisonChangelog.tsx b/packages/app/src/components/inference/ui/ComparisonChangelog.tsx index 882b1ee..cc0bf3c 100644 --- a/packages/app/src/components/inference/ui/ComparisonChangelog.tsx +++ b/packages/app/src/components/inference/ui/ComparisonChangelog.tsx @@ -1,6 +1,6 @@ 'use client'; -import { ChevronDown, ChevronUp, FileText } from 'lucide-react'; +import { Check, ChevronDown, ChevronUp, FileText, Plus } from 'lucide-react'; import { useMemo, useState } from 'react'; import { track } from '@/lib/analytics'; @@ -19,6 +19,10 @@ interface ComparisonChangelogProps { selectedPrecisions: string[]; loading?: boolean; totalDatesQueried: number; + selectedDates: string[]; + selectedDateRange: { startDate: string; endDate: string }; + onAddDate: (date: string) => void; + onAddAllDates: (dates: string[]) => void; } export default function ComparisonChangelog({ @@ -27,6 +31,10 @@ export default function ComparisonChangelog({ selectedPrecisions, loading, totalDatesQueried, + selectedDates, + selectedDateRange, + onAddDate, + onAddAllDates, }: ComparisonChangelogProps) { const [isExpanded, setIsExpanded] = useState(true); @@ -50,6 +58,18 @@ export default function ComparisonChangelog({ .sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime()); }, [changelogs, selectedGPUs, selectedPrecisions]); + const datesOnChart = useMemo(() => { + const set = new Set(selectedDates); + if (selectedDateRange.startDate) set.add(selectedDateRange.startDate); + if (selectedDateRange.endDate) set.add(selectedDateRange.endDate); + return set; + }, [selectedDates, selectedDateRange]); + + const addableDates = useMemo( + () => filteredChangelogs.map((c) => c.date).filter((d) => !datesOnChart.has(d)), + [filteredChangelogs, datesOnChart], + ); + const handleToggle = () => { const newState = !isExpanded; setIsExpanded(newState); @@ -65,22 +85,35 @@ export default function ComparisonChangelog({ return (
-
- {isExpanded ? ( - - ) : ( - + {isExpanded ? ( + + ) : ( + + )} + + {isExpanded && addableDates.length > 0 && ( + )} - +
{item.date} + {datesOnChart.has(item.date) ? ( + + + On chart + + ) : ( + + )} {item.entries.length > 0 ? ( <> diff --git a/packages/app/src/hooks/api/use-comparison-changelogs.ts b/packages/app/src/hooks/api/use-comparison-changelogs.ts index 48aec9f..3b1aed2 100644 --- a/packages/app/src/hooks/api/use-comparison-changelogs.ts +++ b/packages/app/src/hooks/api/use-comparison-changelogs.ts @@ -72,16 +72,7 @@ export function useComparisonChangelogs( return results; }, [hasGPUs, datesToQuery, queries]); - // Intermediate dates with any changelog entries (excluding start/end when date range is set) - const intermediateDates = useMemo(() => { - if (!hasGPUs || !hasDateRange) return []; - return changelogs - .filter((c) => c.date !== selectedDateRange.startDate && c.date !== selectedDateRange.endDate) - .map((c) => c.date) - .sort(); - }, [hasGPUs, hasDateRange, changelogs, selectedDateRange.startDate, selectedDateRange.endDate]); - const loading = queries.some((q) => q.isLoading); - return { changelogs, intermediateDates, loading, totalDatesQueried: datesToQuery.length }; + return { changelogs, loading, totalDatesQueried: datesToQuery.length }; } From 0f3b51ac7753dec84c364c62d3f13da18b9e437d Mon Sep 17 00:00:00 2001 From: adibarra <93070681+adibarra@users.noreply.github.com> Date: Wed, 1 Apr 2026 17:18:53 -0500 Subject: [PATCH 02/12] feat: clicking "On chart" removes date from chart --- .../components/inference/ui/ChartDisplay.tsx | 3 +++ .../inference/ui/ComparisonChangelog.tsx | 24 +++++++++++++++---- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/packages/app/src/components/inference/ui/ChartDisplay.tsx b/packages/app/src/components/inference/ui/ChartDisplay.tsx index 868c932..a9c3423 100644 --- a/packages/app/src/components/inference/ui/ChartDisplay.tsx +++ b/packages/app/src/components/inference/ui/ChartDisplay.tsx @@ -695,6 +695,9 @@ export default function ChartDisplay() { setSelectedDates([...selectedDates, date]); } }} + onRemoveDate={(date) => { + setSelectedDates(selectedDates.filter((d) => d !== date)); + }} onAddAllDates={(dates) => { const merged = [...new Set([...selectedDates, ...dates])]; setSelectedDates(merged); diff --git a/packages/app/src/components/inference/ui/ComparisonChangelog.tsx b/packages/app/src/components/inference/ui/ComparisonChangelog.tsx index cc0bf3c..3f0523d 100644 --- a/packages/app/src/components/inference/ui/ComparisonChangelog.tsx +++ b/packages/app/src/components/inference/ui/ComparisonChangelog.tsx @@ -22,6 +22,7 @@ interface ComparisonChangelogProps { selectedDates: string[]; selectedDateRange: { startDate: string; endDate: string }; onAddDate: (date: string) => void; + onRemoveDate: (date: string) => void; onAddAllDates: (dates: string[]) => void; } @@ -34,6 +35,7 @@ export default function ComparisonChangelog({ selectedDates, selectedDateRange, onAddDate, + onRemoveDate, onAddAllDates, }: ComparisonChangelogProps) { const [isExpanded, setIsExpanded] = useState(true); @@ -132,10 +134,24 @@ export default function ComparisonChangelog({
{item.date} {datesOnChart.has(item.date) ? ( - - - On chart - + selectedDates.includes(item.date) ? ( + + ) : ( + + + On chart + + ) ) : ( ) : ( - + On chart ) From c1d82e6d775bcd5d3e97960b83fa73a994583d57 Mon Sep 17 00:00:00 2001 From: adibarra <93070681+adibarra@users.noreply.github.com> Date: Wed, 1 Apr 2026 17:34:35 -0500 Subject: [PATCH 04/12] feat: always show range endpoints in changelog even without entries --- .../inference/ui/ComparisonChangelog.tsx | 42 ++++++++++++------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/packages/app/src/components/inference/ui/ComparisonChangelog.tsx b/packages/app/src/components/inference/ui/ComparisonChangelog.tsx index ea79c7e..8c2d7ac 100644 --- a/packages/app/src/components/inference/ui/ComparisonChangelog.tsx +++ b/packages/app/src/components/inference/ui/ComparisonChangelog.tsx @@ -40,25 +40,37 @@ export default function ComparisonChangelog({ }: ComparisonChangelogProps) { const [isExpanded, setIsExpanded] = useState(true); - // Filter changelog entries to only show those matching selected GPUs and precisions + // Filter changelog entries to only show those matching selected GPUs and precisions. + // Always keep range endpoints visible even if they have no matching entries. const filteredChangelogs = useMemo(() => { const precSet = new Set(selectedPrecisions); + const rangeEndpoints = new Set(); + if (selectedDateRange.startDate) rangeEndpoints.add(selectedDateRange.startDate); + if (selectedDateRange.endDate) rangeEndpoints.add(selectedDateRange.endDate); - return changelogs - .map((item) => ({ - ...item, - entries: item.entries.filter((entry) => - entry.config_keys.some((key) => { - const precision = key.split('-')[1]; - return ( - precSet.has(precision) && selectedGPUs.some((gpu) => configKeyMatchesHwKey(key, gpu)) - ); - }), - ), - })) - .filter((item) => item.entries.length > 0) + const mapped = changelogs.map((item) => ({ + ...item, + entries: item.entries.filter((entry) => + entry.config_keys.some((key) => { + const precision = key.split('-')[1]; + return ( + precSet.has(precision) && selectedGPUs.some((gpu) => configKeyMatchesHwKey(key, gpu)) + ); + }), + ), + })); + + // Ensure range endpoints are always present + for (const endpoint of rangeEndpoints) { + if (!mapped.some((item) => item.date === endpoint)) { + mapped.push({ date: endpoint, entries: [] }); + } + } + + return mapped + .filter((item) => item.entries.length > 0 || rangeEndpoints.has(item.date)) .sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime()); - }, [changelogs, selectedGPUs, selectedPrecisions]); + }, [changelogs, selectedGPUs, selectedPrecisions, selectedDateRange]); const datesOnChart = useMemo(() => { const set = new Set(selectedDates); From 9f4c1c356e9aaa95941a23c36832e72d5d64eebf Mon Sep 17 00:00:00 2001 From: adibarra <93070681+adibarra@users.noreply.github.com> Date: Wed, 1 Apr 2026 17:36:18 -0500 Subject: [PATCH 05/12] fix: move no-changes message to next line matching entry layout --- .../inference/ui/ComparisonChangelog.tsx | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/packages/app/src/components/inference/ui/ComparisonChangelog.tsx b/packages/app/src/components/inference/ui/ComparisonChangelog.tsx index 8c2d7ac..c5333b8 100644 --- a/packages/app/src/components/inference/ui/ComparisonChangelog.tsx +++ b/packages/app/src/components/inference/ui/ComparisonChangelog.tsx @@ -203,19 +203,21 @@ export default function ComparisonChangelog({ )} - ) : ( - - {item.date < '2025-12-30' - ? 'No changelog data (tracking began Dec 30, 2025)' - : 'No config changes recorded'} - - )} + ) : null}
- {item.entries.map((entry, entryIndex) => ( -
- {formatChangelogDescription(entry.description)} -
- ))} + {item.entries.length > 0 ? ( + item.entries.map((entry, entryIndex) => ( +
+ {formatChangelogDescription(entry.description)} +
+ )) + ) : ( + + {item.date < '2025-12-30' + ? 'No changelog data (tracking began Dec 30, 2025)' + : 'No config changes recorded'} + + )}
)) )} From 42c8b8eb07bf121f86927cd2c6f3810b5b55e62c Mon Sep 17 00:00:00 2001 From: adibarra <93070681+adibarra@users.noreply.github.com> Date: Wed, 1 Apr 2026 17:39:04 -0500 Subject: [PATCH 06/12] fix: differentiate initial config vs unchanged config in changelog --- .../app/src/components/inference/ui/ComparisonChangelog.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/app/src/components/inference/ui/ComparisonChangelog.tsx b/packages/app/src/components/inference/ui/ComparisonChangelog.tsx index c5333b8..9e14de2 100644 --- a/packages/app/src/components/inference/ui/ComparisonChangelog.tsx +++ b/packages/app/src/components/inference/ui/ComparisonChangelog.tsx @@ -215,7 +215,9 @@ export default function ComparisonChangelog({ {item.date < '2025-12-30' ? 'No changelog data (tracking began Dec 30, 2025)' - : 'No config changes recorded'} + : filteredChangelogs.some((c) => c.date < item.date && c.entries.length > 0) + ? 'No config changes — same configuration as previous run' + : 'Initial configuration — no changelog entry recorded'} )}
From 8ae955eaf16198b75cb92dac2ff55a5c227acae3 Mon Sep 17 00:00:00 2001 From: adibarra <93070681+adibarra@users.noreply.github.com> Date: Wed, 1 Apr 2026 17:46:14 -0500 Subject: [PATCH 07/12] style: use brand color for add-to-chart buttons --- .../app/src/components/inference/ui/ComparisonChangelog.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/app/src/components/inference/ui/ComparisonChangelog.tsx b/packages/app/src/components/inference/ui/ComparisonChangelog.tsx index 9e14de2..8792c01 100644 --- a/packages/app/src/components/inference/ui/ComparisonChangelog.tsx +++ b/packages/app/src/components/inference/ui/ComparisonChangelog.tsx @@ -121,7 +121,7 @@ export default function ComparisonChangelog({ onAddAllDates(addableDates); track('inference_changelog_add_all_dates', { count: addableDates.length }); }} - className="text-xs font-medium text-primary hover:text-primary/80 transition-colors flex items-center gap-1" + className="text-xs font-medium text-brand hover:text-brand/80 transition-colors flex items-center gap-1" > Add all to chart @@ -171,7 +171,7 @@ export default function ComparisonChangelog({ onAddDate(item.date); track('inference_changelog_add_date', { date: item.date }); }} - className="text-xs font-medium text-primary hover:text-primary/80 transition-colors flex items-center gap-0.5" + className="text-xs font-medium text-brand hover:text-brand/80 transition-colors flex items-center gap-0.5" > Add to chart From a54854aaba254114354ef4ed24bd120142f17a29 Mon Sep 17 00:00:00 2001 From: adibarra <93070681+adibarra@users.noreply.github.com> Date: Wed, 1 Apr 2026 17:49:03 -0500 Subject: [PATCH 08/12] feat: show first GPU appearance in changelog, move add-to-chart after links --- .../components/inference/ui/ChartDisplay.tsx | 1 + .../inference/ui/ComparisonChangelog.tsx | 94 ++++++++++--------- 2 files changed, 53 insertions(+), 42 deletions(-) diff --git a/packages/app/src/components/inference/ui/ChartDisplay.tsx b/packages/app/src/components/inference/ui/ChartDisplay.tsx index a9c3423..fb51267 100644 --- a/packages/app/src/components/inference/ui/ChartDisplay.tsx +++ b/packages/app/src/components/inference/ui/ChartDisplay.tsx @@ -702,6 +702,7 @@ export default function ChartDisplay() { const merged = [...new Set([...selectedDates, ...dates])]; setSelectedDates(merged); }} + firstAvailableDate={dateRangeAvailableDates[0]} /> )} diff --git a/packages/app/src/components/inference/ui/ComparisonChangelog.tsx b/packages/app/src/components/inference/ui/ComparisonChangelog.tsx index 8792c01..6087a90 100644 --- a/packages/app/src/components/inference/ui/ComparisonChangelog.tsx +++ b/packages/app/src/components/inference/ui/ComparisonChangelog.tsx @@ -24,6 +24,8 @@ interface ComparisonChangelogProps { onAddDate: (date: string) => void; onRemoveDate: (date: string) => void; onAddAllDates: (dates: string[]) => void; + /** Earliest date the selected GPU config has benchmark data */ + firstAvailableDate?: string; } export default function ComparisonChangelog({ @@ -37,16 +39,22 @@ export default function ComparisonChangelog({ onAddDate, onRemoveDate, onAddAllDates, + firstAvailableDate, }: ComparisonChangelogProps) { const [isExpanded, setIsExpanded] = useState(true); // Filter changelog entries to only show those matching selected GPUs and precisions. - // Always keep range endpoints visible even if they have no matching entries. + // Always keep range endpoints and first appearance date visible. + const pinnedDates = useMemo(() => { + const set = new Set(); + if (selectedDateRange.startDate) set.add(selectedDateRange.startDate); + if (selectedDateRange.endDate) set.add(selectedDateRange.endDate); + if (firstAvailableDate) set.add(firstAvailableDate); + return set; + }, [selectedDateRange, firstAvailableDate]); + const filteredChangelogs = useMemo(() => { const precSet = new Set(selectedPrecisions); - const rangeEndpoints = new Set(); - if (selectedDateRange.startDate) rangeEndpoints.add(selectedDateRange.startDate); - if (selectedDateRange.endDate) rangeEndpoints.add(selectedDateRange.endDate); const mapped = changelogs.map((item) => ({ ...item, @@ -60,17 +68,17 @@ export default function ComparisonChangelog({ ), })); - // Ensure range endpoints are always present - for (const endpoint of rangeEndpoints) { - if (!mapped.some((item) => item.date === endpoint)) { - mapped.push({ date: endpoint, entries: [] }); + // Ensure pinned dates are always present + for (const date of pinnedDates) { + if (!mapped.some((item) => item.date === date)) { + mapped.push({ date, entries: [] }); } } return mapped - .filter((item) => item.entries.length > 0 || rangeEndpoints.has(item.date)) + .filter((item) => item.entries.length > 0 || pinnedDates.has(item.date)) .sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime()); - }, [changelogs, selectedGPUs, selectedPrecisions, selectedDateRange]); + }, [changelogs, selectedGPUs, selectedPrecisions, pinnedDates]); const datesOnChart = useMemo(() => { const set = new Set(selectedDates); @@ -145,6 +153,33 @@ export default function ComparisonChangelog({
{item.date} + {item.entries.length > 0 && ( + <> + + {item.headRef && ( + + Git Commit + + + )} + {item.runUrl && ( + + Workflow Run + + + )} + + )} {datesOnChart.has(item.date) ? ( selectedDates.includes(item.date) ? (
{item.entries.length > 0 ? ( item.entries.map((entry, entryIndex) => ( @@ -213,11 +221,13 @@ export default function ComparisonChangelog({ )) ) : ( - {item.date < '2025-12-30' - ? 'No changelog data (tracking began Dec 30, 2025)' - : filteredChangelogs.some((c) => c.date < item.date && c.entries.length > 0) - ? 'No config changes — same configuration as previous run' - : 'Initial configuration — no changelog entry recorded'} + {item.date === firstAvailableDate + ? 'First benchmark run for this configuration' + : item.date < '2025-12-30' + ? 'No changelog data (tracking began Dec 30, 2025)' + : filteredChangelogs.some((c) => c.date < item.date && c.entries.length > 0) + ? 'No config changes — same configuration as previous run' + : 'Initial configuration — no changelog entry recorded'} )}
From 2298da916a17675abf4a25c17043f802b95a064b Mon Sep 17 00:00:00 2001 From: adibarra <93070681+adibarra@users.noreply.github.com> Date: Wed, 1 Apr 2026 17:49:38 -0500 Subject: [PATCH 09/12] fix: replace "On chart" with "Remove from chart" and minus icon --- .../app/src/components/inference/ui/ComparisonChangelog.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/app/src/components/inference/ui/ComparisonChangelog.tsx b/packages/app/src/components/inference/ui/ComparisonChangelog.tsx index 6087a90..f195e7f 100644 --- a/packages/app/src/components/inference/ui/ComparisonChangelog.tsx +++ b/packages/app/src/components/inference/ui/ComparisonChangelog.tsx @@ -1,6 +1,6 @@ 'use client'; -import { Check, ChevronDown, ChevronUp, FileText, Lock, Plus } from 'lucide-react'; +import { ChevronDown, ChevronUp, FileText, Lock, Minus, Plus } from 'lucide-react'; import { useMemo, useState } from 'react'; import { track } from '@/lib/analytics'; @@ -190,8 +190,8 @@ export default function ComparisonChangelog({ }} className="text-xs font-medium text-muted-foreground hover:text-destructive transition-colors flex items-center gap-0.5" > - - On chart + + Remove from chart ) : ( From 02e3e4df1d3ef1171ae7b80e018038dc5dfae279 Mon Sep 17 00:00:00 2001 From: adibarra <93070681+adibarra@users.noreply.github.com> Date: Wed, 1 Apr 2026 17:53:13 -0500 Subject: [PATCH 10/12] fix: remove extra top margin on first legend group --- packages/app/src/components/ui/chart-legend.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/app/src/components/ui/chart-legend.tsx b/packages/app/src/components/ui/chart-legend.tsx index 9d11d08..c8662ce 100644 --- a/packages/app/src/components/ui/chart-legend.tsx +++ b/packages/app/src/components/ui/chart-legend.tsx @@ -395,7 +395,8 @@ export default function ChartLegend({
0 && 'mt-2', allHidden && 'h-0 m-0! p-0! overflow-hidden', )} > From 01c0faba7d80b4a34bad41ca5ae0068e0a3d816f Mon Sep 17 00:00:00 2001 From: adibarra <93070681+adibarra@users.noreply.github.com> Date: Wed, 1 Apr 2026 17:54:36 -0500 Subject: [PATCH 11/12] feat: show config name per changelog entry when multiple GPUs selected --- .../app/src/components/inference/ui/ComparisonChangelog.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/app/src/components/inference/ui/ComparisonChangelog.tsx b/packages/app/src/components/inference/ui/ComparisonChangelog.tsx index f195e7f..9c6fef3 100644 --- a/packages/app/src/components/inference/ui/ComparisonChangelog.tsx +++ b/packages/app/src/components/inference/ui/ComparisonChangelog.tsx @@ -10,6 +10,7 @@ import type { ComparisonChangelog as ComparisonChangelogType } from '@/hooks/api import { configKeyMatchesHwKey, formatChangelogDescription, + formatConfigKeys, } from '@/components/inference/utils/changelogFormatters'; import { updateRepoUrl } from '@/lib/utils'; @@ -216,6 +217,11 @@ export default function ComparisonChangelog({ {item.entries.length > 0 ? ( item.entries.map((entry, entryIndex) => (
+ {selectedGPUs.length > 1 && ( + + {entry.config_keys.map(formatConfigKeys).join(', ')} + + )} {formatChangelogDescription(entry.description)}
)) From 7d67b0d8496a41f1c7246addb02944640dcddeec Mon Sep 17 00:00:00 2001 From: adibarra <93070681+adibarra@users.noreply.github.com> Date: Wed, 1 Apr 2026 17:56:12 -0500 Subject: [PATCH 12/12] fix: show GPU display name instead of full config key in changelog --- .../inference/ui/ComparisonChangelog.tsx | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/packages/app/src/components/inference/ui/ComparisonChangelog.tsx b/packages/app/src/components/inference/ui/ComparisonChangelog.tsx index 9c6fef3..d35b00c 100644 --- a/packages/app/src/components/inference/ui/ComparisonChangelog.tsx +++ b/packages/app/src/components/inference/ui/ComparisonChangelog.tsx @@ -10,9 +10,9 @@ import type { ComparisonChangelog as ComparisonChangelogType } from '@/hooks/api import { configKeyMatchesHwKey, formatChangelogDescription, - formatConfigKeys, } from '@/components/inference/utils/changelogFormatters'; -import { updateRepoUrl } from '@/lib/utils'; +import { HARDWARE_CONFIG } from '@/lib/constants'; +import { getDisplayLabel, updateRepoUrl } from '@/lib/utils'; interface ComparisonChangelogProps { changelogs: ComparisonChangelogType[]; @@ -217,11 +217,20 @@ export default function ComparisonChangelog({ {item.entries.length > 0 ? ( item.entries.map((entry, entryIndex) => (
- {selectedGPUs.length > 1 && ( - - {entry.config_keys.map(formatConfigKeys).join(', ')} - - )} + {selectedGPUs.length > 1 && + (() => { + const matchingGpus = selectedGPUs.filter((gpu) => + entry.config_keys.some((key) => configKeyMatchesHwKey(key, gpu)), + ); + const labels = matchingGpus.map((gpu) => + HARDWARE_CONFIG[gpu] ? getDisplayLabel(HARDWARE_CONFIG[gpu]) : gpu, + ); + return labels.length > 0 ? ( + + {labels.join(', ')} + + ) : null; + })()} {formatChangelogDescription(entry.description)}
))