@@ -172,6 +172,27 @@ describe("script declaration contracts", () => {
172172 ) . toEqual ( { checked : 1 , issues : [ ] } ) ;
173173 } ) ;
174174
175+ it ( "fails closed on cyclic star graphs" , ( ) => {
176+ const root = fs . mkdtempSync ( path . join ( os . tmpdir ( ) , "openclaw-script-declarations-" ) ) ;
177+ tempDirs . push ( root ) ;
178+ fs . mkdirSync ( path . join ( root , "scripts" ) , { recursive : true } ) ;
179+ fs . writeFileSync ( path . join ( root , "scripts" , "a.mjs" ) , 'export * from "./b.mjs";\n' ) ;
180+ fs . writeFileSync (
181+ path . join ( root , "scripts" , "b.mjs" ) ,
182+ 'export const value = 1;\nexport * from "./a.mjs";\n' ,
183+ ) ;
184+ fs . writeFileSync ( path . join ( root , "scripts" , "a.d.mts" ) , "export const value: 1;\n" ) ;
185+ fs . writeFileSync ( path . join ( root , "scripts" , "b.d.mts" ) , "export const value: 1;\n" ) ;
186+
187+ const result = verifyScriptDeclarationContracts ( {
188+ root,
189+ files : [ "scripts/a.d.mts" , "scripts/a.mjs" , "scripts/b.d.mts" , "scripts/b.mjs" ] ,
190+ } ) ;
191+ expect ( result . checked ) . toBe ( 2 ) ;
192+ expect ( result . issues ) . toHaveLength ( 2 ) ;
193+ expect ( result . issues . every ( ( issue ) => issue . includes ( "cyclic star re-export" ) ) ) . toBe ( true ) ;
194+ } ) ;
195+
175196 it ( "fails closed on explicit re-exports of ambiguous bindings" , ( ) => {
176197 const root = fs . mkdtempSync ( path . join ( os . tmpdir ( ) , "openclaw-script-declarations-" ) ) ;
177198 tempDirs . push ( root ) ;
0 commit comments