@@ -856,6 +856,64 @@ describe("UI components", () => {
856856 }
857857 } ) ;
858858
859+ test ( "DiffPane keeps bottom scroll stable when offscreen agent notes are windowed out" , async ( ) => {
860+ const theme = resolveTheme ( "midnight" , null ) ;
861+ const firstFile = createTallDiffFile ( "first" , "first.ts" , 18 ) ;
862+ firstFile . agent = {
863+ path : firstFile . path ,
864+ summary : "first.ts note" ,
865+ annotations : [
866+ {
867+ newRange : [ 2 , 2 ] ,
868+ summary : "Offscreen note should still reserve geometry at EOF." ,
869+ rationale :
870+ "If measurement drops this note after first.ts leaves the viewport, max scroll shrinks." ,
871+ } ,
872+ ] ,
873+ } ;
874+ const files = [ firstFile , createTallDiffFile ( "last" , "last.ts" , 24 ) ] ;
875+ const scrollRef = createRef < ScrollBoxRenderable > ( ) ;
876+ const props = createDiffPaneProps ( files , theme , {
877+ diffContentWidth : 88 ,
878+ headerLabelWidth : 48 ,
879+ headerStatsWidth : 16 ,
880+ scrollRef,
881+ selectedFileId : undefined ,
882+ separatorWidth : 84 ,
883+ showAgentNotes : true ,
884+ width : 92 ,
885+ } ) ;
886+ const setup = await testRender ( < DiffPane { ...props } /> , {
887+ width : 96 ,
888+ height : 10 ,
889+ } ) ;
890+
891+ try {
892+ await settleDiffPane ( setup ) ;
893+
894+ let bottomScrollTop = 0 ;
895+ await act ( async ( ) => {
896+ scrollRef . current ?. scrollTo ( 1_000_000 ) ;
897+ bottomScrollTop = scrollRef . current ?. scrollTop ?? 0 ;
898+ } ) ;
899+ expect ( bottomScrollTop ) . toBeGreaterThan ( 0 ) ;
900+
901+ await settleDiffPane ( setup ) ;
902+ expect ( scrollRef . current ?. scrollTop ?? 0 ) . toBe ( bottomScrollTop ) ;
903+
904+ await act ( async ( ) => {
905+ scrollRef . current ?. scrollTo ( bottomScrollTop + 1 ) ;
906+ } ) ;
907+ await settleDiffPane ( setup ) ;
908+
909+ expect ( scrollRef . current ?. scrollTop ?? 0 ) . toBe ( bottomScrollTop ) ;
910+ } finally {
911+ await act ( async ( ) => {
912+ setup . renderer . destroy ( ) ;
913+ } ) ;
914+ }
915+ } ) ;
916+
859917 test ( "DiffPane lets manual scrolling move away from a bottom-clamped file-top alignment" , async ( ) => {
860918 const theme = resolveTheme ( "midnight" , null ) ;
861919 const files = [
0 commit comments