@@ -288,6 +288,50 @@ def test_explicit_number_zero_is_honored(self, git_repo: Path):
288288 assert data ["FEATURE_NUM" ] == "000"
289289 assert data ["BRANCH_NAME" ] == "000-zero"
290290
291+ def test_explicit_conflicting_number_uses_next_spec_prefix (self , git_repo : Path ):
292+ """An explicit number is advanced when its spec prefix already exists."""
293+ (git_repo / "specs" / "001-existing" ).mkdir (parents = True )
294+ (git_repo / "specs" / "1000-latest" ).mkdir ()
295+
296+ result = run_script (
297+ git_repo ,
298+ "--json" ,
299+ "--dry-run" ,
300+ "--number" ,
301+ "1" ,
302+ "--short-name" ,
303+ "test" ,
304+ "Test feature" ,
305+ )
306+
307+ assert result .returncode == 0 , result .stderr
308+ data = json .loads (result .stdout )
309+ assert data ["FEATURE_NUM" ] == "1001"
310+ assert data ["BRANCH_NAME" ] == "1001-test"
311+ assert "--number 001 conflicts with an existing spec directory" in result .stderr
312+ assert "using 1001 instead" in result .stderr
313+
314+ def test_explicit_number_ignores_matching_file (self , git_repo : Path ):
315+ """A matching file does not count as a conflicting spec directory."""
316+ specs_dir = git_repo / "specs"
317+ specs_dir .mkdir ()
318+ (specs_dir / "001-placeholder" ).write_text ("not a directory" , encoding = "utf-8" )
319+
320+ result = run_script (
321+ git_repo ,
322+ "--json" ,
323+ "--dry-run" ,
324+ "--number" ,
325+ "1" ,
326+ "--short-name" ,
327+ "test" ,
328+ "Test feature" ,
329+ )
330+
331+ assert result .returncode == 0 , result .stderr
332+ assert json .loads (result .stdout )["FEATURE_NUM" ] == "001"
333+ assert "conflicts with an existing spec directory" not in result .stderr
334+
291335
292336class TestSequentialBranchPowerShell :
293337 def test_powershell_scanner_uses_long_tryparse_for_large_prefixes (self ):
@@ -332,6 +376,50 @@ def test_explicit_number_zero_is_honored_matching_bash(self, ps_git_repo: Path):
332376 assert data ["FEATURE_NUM" ] == "000"
333377 assert data ["BRANCH_NAME" ] == "000-zero"
334378
379+ @pytest .mark .skipif (not _has_pwsh (), reason = "pwsh not installed" )
380+ def test_explicit_conflicting_number_uses_next_spec_prefix (
381+ self , ps_git_repo : Path
382+ ):
383+ """PowerShell advances an explicit number when its spec prefix exists."""
384+ script = ps_git_repo / "scripts" / "powershell" / "create-new-feature.ps1"
385+ (ps_git_repo / "specs" / "001-existing" ).mkdir (parents = True )
386+ (ps_git_repo / "specs" / "1000-latest" ).mkdir ()
387+
388+ result = subprocess .run (
389+ [
390+ "pwsh" , "-NoProfile" , "-File" , str (script ), "-Json" , "-DryRun" ,
391+ "-Number" , "1" , "-ShortName" , "test" , "Test feature" ,
392+ ],
393+ cwd = ps_git_repo , capture_output = True , text = True ,
394+ )
395+
396+ assert result .returncode == 0 , result .stderr
397+ data = json .loads (result .stdout )
398+ assert data ["FEATURE_NUM" ] == "1001"
399+ assert data ["BRANCH_NAME" ] == "1001-test"
400+ assert "-Number 001 conflicts with an existing spec directory" in result .stderr
401+ assert "using 1001 instead" in result .stderr
402+
403+ @pytest .mark .skipif (not _has_pwsh (), reason = "pwsh not installed" )
404+ def test_explicit_number_ignores_matching_file (self , ps_git_repo : Path ):
405+ """PowerShell ignores files that resemble numbered spec directories."""
406+ script = ps_git_repo / "scripts" / "powershell" / "create-new-feature.ps1"
407+ specs_dir = ps_git_repo / "specs"
408+ specs_dir .mkdir ()
409+ (specs_dir / "001-placeholder" ).write_text ("not a directory" , encoding = "utf-8" )
410+
411+ result = subprocess .run (
412+ [
413+ "pwsh" , "-NoProfile" , "-File" , str (script ), "-Json" , "-DryRun" ,
414+ "-Number" , "1" , "-ShortName" , "test" , "Test feature" ,
415+ ],
416+ cwd = ps_git_repo , capture_output = True , text = True ,
417+ )
418+
419+ assert result .returncode == 0 , result .stderr
420+ assert json .loads (result .stdout )["FEATURE_NUM" ] == "001"
421+ assert "conflicts with an existing spec directory" not in result .stderr
422+
335423 @pytest .mark .skipif (not _has_pwsh (), reason = "pwsh not installed" )
336424 def test_missing_spec_template_warns_matching_bash (self , ps_git_repo : Path ):
337425 """When no spec template can be resolved, create-new-feature.ps1 must warn on
@@ -531,14 +619,15 @@ def test_allow_existing_reuses_existing_feature_dir(self, git_repo: Path):
531619 assert feature_dir .is_dir ()
532620 assert (feature_dir / "spec.md" ).exists ()
533621
534- def test_without_flag_still_errors (self , git_repo : Path ):
535- """T009: Existing feature directories still fail without the flag ."""
622+ def test_without_flag_auto_corrects_existing_prefix (self , git_repo : Path ):
623+ """T009: Existing prefix advances when exact reuse is not allowed ."""
536624 (git_repo / "specs" / "007-no-flag" ).mkdir (parents = True )
537625 result = run_script (
538626 git_repo , "--short-name" , "no-flag" , "--number" , "7" , "No flag feature" ,
539627 )
540- assert result .returncode != 0 , "should fail without --allow-existing-branch"
541- assert "already exists" in result .stderr
628+ assert result .returncode == 0 , result .stderr
629+ assert (git_repo / "specs" / "008-no-flag" ).is_dir ()
630+ assert "using 008 instead" in result .stderr
542631
543632 def test_allow_existing_no_overwrite_spec (self , git_repo : Path ):
544633 """T010: Pre-create spec.md with content, verify it is preserved."""
@@ -598,6 +687,26 @@ def test_powershell_reuses_existing_feature_dir(self):
598687 assert "Feature directory '$featureDir' already exists" in contents
599688 assert "-not $AllowExistingBranch" in contents
600689
690+ @pytest .mark .skipif (not _has_pwsh (), reason = "pwsh not installed" )
691+ def test_powershell_reuses_exact_feature_dir (self , ps_git_repo : Path ):
692+ """PowerShell exact-directory reuse bypasses prefix auto-correction."""
693+ script = ps_git_repo / "scripts" / "powershell" / "create-new-feature.ps1"
694+ feature_dir = ps_git_repo / "specs" / "004-pre-exist"
695+ feature_dir .mkdir (parents = True )
696+
697+ result = subprocess .run (
698+ [
699+ "pwsh" , "-NoProfile" , "-File" , str (script ), "-Json" ,
700+ "-AllowExistingBranch" , "-Number" , "4" , "-ShortName" ,
701+ "pre-exist" , "Pre-existing feature" ,
702+ ],
703+ cwd = ps_git_repo , capture_output = True , text = True ,
704+ )
705+
706+ assert result .returncode == 0 , result .stderr
707+ assert json .loads (result .stdout )["BRANCH_NAME" ] == "004-pre-exist"
708+ assert (feature_dir / "spec.md" ).is_file ()
709+
601710 @pytest .mark .skipif (not _has_pwsh (), reason = "pwsh not installed" )
602711 @pytest .mark .skipif (
603712 os .name != "nt" or shutil .which ("powershell.exe" ) is None ,
0 commit comments