@@ -30,32 +30,73 @@ export default function ComparisonChangelog({
3030} : ComparisonChangelogProps ) {
3131 const [ isExpanded , setIsExpanded ] = useState ( false ) ;
3232
33- // Filter changelog entries to only show those matching selected GPUs and precisions
33+ // Filter changelog entries to only show those matching selected GPUs and precisions.
34+ // For GPUs without a direct entry on a date, walk backwards to the most recent prior changelog.
3435 const filteredChangelogs = useMemo ( ( ) => {
3536 const precSet = new Set ( selectedPrecisions ) ;
37+ const sorted = [ ...changelogs ] . sort (
38+ ( a , b ) => new Date ( a . date ) . getTime ( ) - new Date ( b . date ) . getTime ( ) ,
39+ ) ;
3640
37- return changelogs
38- . map ( ( item ) => ( {
39- ...item ,
40- entries : item . entries . filter ( ( entry ) =>
41- entry . config_keys . some ( ( key ) => {
42- const precision = key . split ( '-' ) [ 1 ] ;
43- return (
44- precSet . has ( precision ) && selectedGPUs . some ( ( gpu ) => configKeyMatchesHwKey ( key , gpu ) )
41+ const matchesGpu = ( key : string ) => {
42+ const precision = key . split ( '-' ) [ 1 ] ;
43+ return precSet . has ( precision ) && selectedGPUs . some ( ( gpu ) => configKeyMatchesHwKey ( key , gpu ) ) ;
44+ } ;
45+
46+ return sorted
47+ . map ( ( item ) => {
48+ // Direct entries matching selected GPUs/precisions
49+ const directEntries = item . entries . filter ( ( entry ) => entry . config_keys . some ( matchesGpu ) ) ;
50+
51+ // Find GPUs that have direct entries on this date
52+ const coveredGPUs = new Set < string > ( ) ;
53+ for ( const entry of directEntries ) {
54+ for ( const key of entry . config_keys ) {
55+ if ( ! matchesGpu ( key ) ) continue ;
56+ for ( const gpu of selectedGPUs ) {
57+ if ( configKeyMatchesHwKey ( key , gpu ) ) coveredGPUs . add ( gpu ) ;
58+ }
59+ }
60+ }
61+
62+ // For uncovered GPUs, walk backwards through earlier dates
63+ const inheritedEntries : {
64+ config_keys : string [ ] ;
65+ description : string ;
66+ pr_link : string | null ;
67+ inheritedFromDate : string ;
68+ } [ ] = [ ] ;
69+
70+ for ( const gpu of selectedGPUs ) {
71+ if ( coveredGPUs . has ( gpu ) ) continue ;
72+ // Walk backwards through sorted changelogs before this date
73+ for ( let i = sorted . indexOf ( item ) - 1 ; i >= 0 ; i -- ) {
74+ const prior = sorted [ i ] ;
75+ const match = prior . entries . find ( ( entry ) =>
76+ entry . config_keys . some ( ( key ) => matchesGpu ( key ) && configKeyMatchesHwKey ( key , gpu ) ) ,
4577 ) ;
46- } ) ,
47- ) ,
48- } ) )
49- . filter ( ( item ) => item . entries . length > 0 ) ;
50- } , [ changelogs , selectedGPUs , selectedPrecisions ] ) ;
78+ if ( match ) {
79+ // Avoid duplicates if same entry covers multiple uncovered GPUs
80+ if (
81+ ! inheritedEntries . some (
82+ ( e ) => e . inheritedFromDate === prior . date && e . description === match . description ,
83+ )
84+ ) {
85+ inheritedEntries . push ( { ...match , inheritedFromDate : prior . date } ) ;
86+ }
87+ break ;
88+ }
89+ }
90+ }
5191
52- const sortedChangelogs = useMemo (
53- ( ) =>
54- [ ...filteredChangelogs ] . sort (
55- ( a , b ) => new Date ( a . date ) . getTime ( ) - new Date ( b . date ) . getTime ( ) ,
56- ) ,
57- [ filteredChangelogs ] ,
58- ) ;
92+ return {
93+ ...item ,
94+ entries : directEntries ,
95+ inheritedEntries,
96+ } ;
97+ } )
98+ . filter ( ( item ) => item . entries . length > 0 || item . inheritedEntries . length > 0 ) ;
99+ } , [ changelogs , selectedGPUs , selectedPrecisions ] ) ;
59100
60101 const handleToggle = ( ) => {
61102 const newState = ! isExpanded ;
@@ -95,13 +136,13 @@ export default function ComparisonChangelog({
95136 } `}
96137 >
97138 < div className = "px-4 pt-2 pb-4 flex flex-col gap-3" >
98- { sortedChangelogs . length === 0 ? (
139+ { filteredChangelogs . length === 0 ? (
99140 < p className = "text-sm text-muted-foreground" >
100141 No config changelog data matching the selected GPUs and precisions for this date
101142 range. Changelog tracking began Dec 30, 2025.
102143 </ p >
103144 ) : (
104- sortedChangelogs . map ( ( item ) => (
145+ filteredChangelogs . map ( ( item ) => (
105146 < div key = { item . date } className = "flex flex-col gap-1" >
106147 < div className = "flex items-center gap-2 flex-wrap" >
107148 < span className = "text-sm font-semibold" > { item . date } </ span >
@@ -144,6 +185,15 @@ export default function ComparisonChangelog({
144185 { formatChangelogDescription ( entry . description ) }
145186 </ div >
146187 ) ) }
188+ { item . inheritedEntries . map ( ( entry , entryIndex ) => (
189+ < div
190+ key = { `inherited-${ entryIndex } ` }
191+ className = "text-sm text-muted-foreground pl-5 italic"
192+ >
193+ < span className = "text-xs opacity-70" > (from { entry . inheritedFromDate } )</ span > { ' ' }
194+ { formatChangelogDescription ( entry . description ) }
195+ </ div >
196+ ) ) }
147197 </ div >
148198 ) )
149199 ) }
0 commit comments