@@ -522,6 +522,36 @@ async def test_graph_repairs_failed_file_patch_and_reconfirms(tmp_path) -> None:
522522 assert "analysis ok" in str (resumed ["messages" ][- 1 ].content )
523523
524524
525+ async def test_graph_repairs_new_file_name_collision_with_unused_name (tmp_path ) -> None :
526+ existing = tmp_path / "disk_info.sh"
527+ alternate = tmp_path / "disk_info_1.sh"
528+ existing .write_text ("#!/bin/sh\n echo existing\n " , encoding = "utf-8" )
529+ first_plan = file_patch_plan_json (str (existing ), "#!/bin/sh\n echo disk\n " )
530+ repaired_plan = file_patch_plan_json (str (alternate ), "#!/bin/sh\n echo disk\n " )
531+ graph , _provider = _graph (tmp_path , [first_plan , repaired_plan , "analysis ok" ])
532+ config = {"configurable" : {"thread_id" : "new-file-collision" }}
533+
534+ await graph .ainvoke (
535+ initial_state ("create a new disk info shell script in tmp" , source = CommandSource .USER ),
536+ config = config ,
537+ )
538+ snapshot = await graph .aget_state (config )
539+ interrupts = snapshot .tasks [0 ].interrupts
540+
541+ assert interrupts [0 ].value ["type" ] == "confirm_file_patch"
542+ assert interrupts [0 ].value ["repair_attempt" ] == 1
543+ assert str (alternate ) in interrupts [0 ].value ["files_changed" ]
544+ assert str (existing ) not in interrupts [0 ].value ["files_changed" ]
545+
546+ resumed = await graph .ainvoke (
547+ Command (resume = {"decision" : "yes" , "latency_ms" : 1 }), config = config
548+ )
549+
550+ assert existing .read_text (encoding = "utf-8" ) == "#!/bin/sh\n echo existing\n "
551+ assert alternate .read_text (encoding = "utf-8" ) == "#!/bin/sh\n echo disk\n "
552+ assert "analysis ok" in str (resumed ["messages" ][- 1 ].content )
553+
554+
525555async def test_graph_blocks_file_patch_outside_allow_roots (tmp_path ) -> None :
526556 target = tmp_path / "blocked" / "demo.sh"
527557 graph , _provider = _graph (
0 commit comments