@@ -1049,9 +1049,10 @@ describe("createExecutor", () => {
10491049 expect ( rowsAfter . map ( ( row ) => row . generation ) . sort ( ) , "A did not replace the rows" ) . toEqual (
10501050 rowsBefore . map ( ( row ) => row . generation ) . sort ( ) ,
10511051 ) ;
1052- // And A reported the persisted rows, not the ones it discovered and
1053- // failed to write — so its caller cannot disagree with the next list.
1054- // A discovered `extra`; persisted has no `extra`; the report must not.
1052+ // And A reported the persisted rows, VALIDATED against the manifest,
1053+ // not the ones it discovered and failed to write — so its caller
1054+ // cannot disagree with the next list. A discovered `extra`; persisted
1055+ // has no `extra`; the report must not.
10551056 expect (
10561057 reported . map ( ( tool ) => String ( tool . name ) ) . sort ( ) ,
10571058 "refresh reports what is persisted" ,
@@ -1086,6 +1087,77 @@ describe("createExecutor", () => {
10861087 } ) ,
10871088 ) ;
10881089
1090+ // D1 commits the winner's manifest before its row batch. A loser that
1091+ // reads the rows in that window must NOT report the previous build's rows
1092+ // as if they were current: `describeAll` refuses that state (manifest names
1093+ // the new generation, rows carry the old), so the loser reports nothing.
1094+ it . effect ( "a lost claim reports nothing while the winner's rows have not landed" , ( ) =>
1095+ Effect . gen ( function * ( ) {
1096+ const config = makeTestConfig ( { plugins : [ demoPlugin ] as const } ) ;
1097+ const raceState : { armed : boolean } = { armed : false } ;
1098+ const wrap = ( inner : FumaDb ) : FumaDb =>
1099+ new Proxy ( inner , {
1100+ get ( target , prop ) {
1101+ if ( prop === "withContext" ) {
1102+ return ( context : unknown ) =>
1103+ wrap ( ( target . withContext as ( c : unknown ) => FumaDb ) ( context ) ) ;
1104+ }
1105+ if ( prop === "transaction" ) {
1106+ return ( run : ( tx : FumaDb ) => Promise < unknown > ) =>
1107+ ( target . transaction as ( r : ( tx : FumaDb ) => Promise < unknown > ) => Promise < unknown > ) (
1108+ ( tx ) => run ( wrap ( tx ) ) ,
1109+ ) ;
1110+ }
1111+ if ( prop === "replaceMany" ) {
1112+ return async ( plan : unknown ) => {
1113+ if ( raceState . armed ) {
1114+ raceState . armed = false ;
1115+ // B claims AND has already committed its manifest for a
1116+ // generation whose rows are not in the table yet — the D1
1117+ // guard-then-batch window.
1118+ await ( target . updateMany as ( t : unknown , q : unknown ) => Promise < unknown > ) (
1119+ "connection" ,
1120+ {
1121+ where : ( b : { ( c : string , op : string , v : unknown ) : unknown } ) =>
1122+ b ( "integration" , "=" , String ( INTEG ) ) ,
1123+ set : {
1124+ tools_synced_at : null ,
1125+ tools_rebuild : "build-B" ,
1126+ tools_manifest : { generation : "gen-B" , tools : 2 , definitions : 6 } ,
1127+ } ,
1128+ } ,
1129+ ) ;
1130+ }
1131+ return ( target . replaceMany as ( p : unknown ) => Promise < { applied : boolean } > ) ( plan ) ;
1132+ } ;
1133+ }
1134+ return Reflect . get ( target , prop ) ;
1135+ } ,
1136+ } ) ;
1137+ const executor = yield * createExecutor ( { ...config , db : wrap ( config . db ) } ) ;
1138+ yield * executor . demo . seed ( ) ;
1139+ yield * executor . connections . create ( {
1140+ owner : "org" ,
1141+ name : CONN ,
1142+ integration : INTEG ,
1143+ template : TEMPLATE ,
1144+ from : { provider : ProviderKey . make ( "memory" ) , id : ProviderItemId . make ( "v" ) } ,
1145+ } ) ;
1146+ expect ( ( yield * executor . tools . describeAll ( ) ) . length ) . toBeGreaterThan ( 0 ) ;
1147+
1148+ raceState . armed = true ;
1149+ const reported = yield * executor . connections . refresh ( {
1150+ owner : "org" ,
1151+ integration : INTEG ,
1152+ name : CONN ,
1153+ } ) ;
1154+ expect ( raceState . armed , "B interleaved" ) . toBe ( false ) ;
1155+ // The rows in the table are the OLD build's; the manifest is B's. That
1156+ // is not a servable catalog, and the loser must not pretend it is.
1157+ expect ( reported , "nothing is reported while the winner lands" ) . toEqual ( [ ] ) ;
1158+ } ) ,
1159+ ) ;
1160+
10891161 it . effect ( "execute dispatches a connection-produced tool to the owning plugin" , ( ) =>
10901162 Effect . gen ( function * ( ) {
10911163 const executor = yield * makeTestExecutor ( {
0 commit comments