@@ -101,15 +101,16 @@ function writeRemoteRunArtifact(
101101 cloneDir : string ,
102102 experiment : string ,
103103 timestamp : string ,
104- resultRecord : object ,
104+ resultRecords : object | object [ ] ,
105105) : string {
106106 const isoTimestamp = timestamp . replace (
107107 / ^ ( \d { 4 } - \d { 2 } - \d { 2 } ) T ( \d { 2 } ) - ( \d { 2 } ) - ( \d { 2 } ) - ( \d { 3 } ) Z $ / ,
108108 '$1T$2:$3:$4.$5Z' ,
109109 ) ;
110110 const runDir = path . join ( cloneDir , '.agentv' , 'results' , 'runs' , experiment , timestamp ) ;
111111 mkdirSync ( runDir , { recursive : true } ) ;
112- writeFileSync ( path . join ( runDir , 'index.jsonl' ) , toJsonl ( resultRecord ) ) ;
112+ const records = Array . isArray ( resultRecords ) ? resultRecords : [ resultRecords ] ;
113+ writeFileSync ( path . join ( runDir , 'index.jsonl' ) , toJsonl ( ...records ) ) ;
113114 writeFileSync (
114115 path . join ( runDir , 'benchmark.json' ) ,
115116 JSON . stringify (
@@ -768,6 +769,64 @@ describe('serve app', () => {
768769 expect ( detailData . results [ 0 ] ) . toMatchObject ( { testId : 'test-greeting' } ) ;
769770 } , 15000 ) ;
770771
772+ it ( 'computes git-native remote run list totals from materialized index rows' , async ( ) => {
773+ const { remoteDir, cloneDir } = initializeRemoteRepo ( tempDir ) ;
774+ const secondPass = {
775+ ...RESULT_A ,
776+ test_id : 'test-tool-use' ,
777+ timestamp : '2026-03-18T10:00:02.000Z' ,
778+ score : 0.95 ,
779+ } ;
780+ const failingResult = {
781+ ...RESULT_B ,
782+ timestamp : '2026-03-18T10:00:03.000Z' ,
783+ score : 0.4 ,
784+ } ;
785+ const runId = writeRemoteRunArtifact ( cloneDir , 'green-uat' , '2026-03-26T10-00-00-000Z' , [
786+ RESULT_A ,
787+ secondPass ,
788+ failingResult ,
789+ ] ) ;
790+
791+ mkdirSync ( path . join ( tempDir , '.agentv' ) , { recursive : true } ) ;
792+ writeFileSync (
793+ path . join ( tempDir , '.agentv' , 'config.yaml' ) ,
794+ `results:
795+ mode: github
796+ repo: file://${ remoteDir }
797+ path: ${ cloneDir }
798+ ` ,
799+ ) ;
800+
801+ const app = createApp ( [ ] , tempDir , tempDir , undefined , { studioDir } ) ;
802+
803+ const listRes = await app . request ( '/api/runs' ) ;
804+ expect ( listRes . status ) . toBe ( 200 ) ;
805+ const listData = ( await listRes . json ( ) ) as {
806+ runs : Array < {
807+ filename : string ;
808+ test_count : number ;
809+ pass_rate : number ;
810+ avg_score : number ;
811+ experiment ?: string ;
812+ timestamp : string ;
813+ } > ;
814+ } ;
815+ expect ( listData . runs ) . toHaveLength ( 1 ) ;
816+ expect ( listData . runs [ 0 ] . filename ) . toBe ( `remote::${ runId } ` ) ;
817+ expect ( listData . runs [ 0 ] . experiment ) . toBe ( 'green-uat' ) ;
818+ expect ( listData . runs [ 0 ] . timestamp ) . toBe ( '2026-03-26T10:00:00.000Z' ) ;
819+ expect ( listData . runs [ 0 ] . test_count ) . toBe ( 3 ) ;
820+ expect ( Math . round ( listData . runs [ 0 ] . pass_rate * listData . runs [ 0 ] . test_count ) ) . toBe ( 2 ) ;
821+ expect ( listData . runs [ 0 ] . pass_rate ) . toBeCloseTo ( 2 / 3 , 5 ) ;
822+ expect ( listData . runs [ 0 ] . avg_score ) . toBeCloseTo ( ( 1 + 0.95 + 0.4 ) / 3 , 5 ) ;
823+
824+ const detailRes = await app . request ( `/api/runs/${ encodeURIComponent ( `remote::${ runId } ` ) } ` ) ;
825+ expect ( detailRes . status ) . toBe ( 200 ) ;
826+ const detailData = ( await detailRes . json ( ) ) as { results : Array < { testId : string } > } ;
827+ expect ( detailData . results ) . toHaveLength ( 3 ) ;
828+ } , 15000 ) ;
829+
771830 it ( 'loads externally pushed remote runs after sync even when the clone has not checked out the files' , async ( ) => {
772831 const { remoteDir, cloneDir, seedDir } = initializeRemoteRepo ( tempDir ) ;
773832 const runId = writeRemoteRunArtifact (
0 commit comments