@@ -346,10 +346,14 @@ describe("syncMemoryWikiBridgeSources", () => {
346346 await expect ( fs . readFile ( externalTarget , "utf8" ) ) . resolves . toBe ( "external target\n" ) ;
347347 } ) ;
348348
349- it ( "reports non-symlink bridge source write safety failures without symlink wording" , async ( ) => {
350- const workspaceDir = await createBridgeWorkspace ( "not-file-workspace" ) ;
349+ async function createDirectoryCollisionFixture ( params : {
350+ workspaceName : string ;
351+ vaultName : string ;
352+ populateDirectory ?: boolean ;
353+ } ) {
354+ const workspaceDir = await createBridgeWorkspace ( params . workspaceName ) ;
351355 const { rootDir : vaultDir , config } = await createVault ( {
352- rootDir : nextCaseRoot ( "not-file-vault" ) ,
356+ rootDir : nextCaseRoot ( params . vaultName ) ,
353357 config : {
354358 vaultMode : "bridge" ,
355359 bridge : {
@@ -381,8 +385,19 @@ describe("syncMemoryWikiBridgeSources", () => {
381385 const pageAbsPath = path . join ( vaultDir , pagePath ) ;
382386 await fs . rm ( pageAbsPath ) ;
383387 await fs . mkdir ( pageAbsPath ) ;
384- await fs . writeFile ( path . join ( pageAbsPath , "child.md" ) , "blocking child\n" , "utf8" ) ;
388+ if ( params . populateDirectory ) {
389+ await fs . writeFile ( path . join ( pageAbsPath , "child.md" ) , "blocking child\n" , "utf8" ) ;
390+ }
385391 await fs . writeFile ( memoryPath , "# Updated Durable Memory\n" , "utf8" ) ;
392+ return { appConfig, config, pageAbsPath } ;
393+ }
394+
395+ it ( "reports non-symlink bridge source write safety failures without symlink wording" , async ( ) => {
396+ const { appConfig, config } = await createDirectoryCollisionFixture ( {
397+ workspaceName : "not-file-workspace" ,
398+ vaultName : "not-file-vault" ,
399+ populateDirectory : true ,
400+ } ) ;
386401
387402 const second = syncMemoryWikiBridgeSources ( { config, appConfig } ) ;
388403 await expect ( second ) . rejects . toThrow (
@@ -391,6 +406,20 @@ describe("syncMemoryWikiBridgeSources", () => {
391406 await expect ( second ) . rejects . not . toThrow ( "through symlink" ) ;
392407 } ) ;
393408
409+ it ( "does not remove empty directory bridge source collisions as hardlinks" , async ( ) => {
410+ const { appConfig, config, pageAbsPath } = await createDirectoryCollisionFixture ( {
411+ workspaceName : "empty-directory-workspace" ,
412+ vaultName : "empty-directory-vault" ,
413+ } ) ;
414+
415+ const second = syncMemoryWikiBridgeSources ( { config, appConfig } ) ;
416+ await expect ( second ) . rejects . toThrow (
417+ / R e f u s i n g t o w r i t e i m p o r t e d s o u r c e p a g e \( ( n o t - f i l e | p a t h - m i s m a t c h ) \) : s o u r c e s \/ / u,
418+ ) ;
419+ await expect ( second ) . rejects . not . toThrow ( "through symlink" ) ;
420+ await expect ( fs . stat ( pageAbsPath ) ) . resolves . toSatisfy ( ( stat ) => stat . isDirectory ( ) ) ;
421+ } ) ;
422+
394423 it ( "replaces bridge source page hardlinks without clobbering their target" , async ( ) => {
395424 const workspaceDir = await createBridgeWorkspace ( "hardlink-workspace" ) ;
396425 const { rootDir : vaultDir , config } = await createVault ( {
0 commit comments