Repository navigation
fix(powershell): treat bracketed project paths literally in create-new-feature - #5399
Conversation
…w-feature create-new-feature.ps1 passed the project path to Set-Location, Test-Path and Get-ChildItem without -LiteralPath, so brackets in that path were read as wildcards: the script stopped at Set-Location, numbered a new feature 001 again, and treated an existing spec.md as missing under -AllowExistingBranch. Fixes github#5398 Assisted-by: OpenCode (model: Claude Opus 5.5, autonomous)
There was a problem hiding this comment.
🟡 Changes recommended
The regression test does not verify byte-for-byte preservation because read_text() normalizes line endings, leaving an active test-coverage issue.
1 open issue
What changed in this PR
This pull request fixes PowerShell feature creation when project paths contain square brackets by treating those paths literally during navigation, numbering, and specification detection.
Changes:
- Uses
-LiteralPathfor project navigation, specs enumeration, and existingspec.mdchecks. - Adds PowerShell/Python parity coverage for bracketed project paths, feature numbering, and existing-spec preservation.
- The preservation assertion currently compares decoded text rather than raw bytes.
| File | Description |
|---|---|
| tests/test_create_new_feature_python_parity.py | Adds regression coverage for bracketed repository paths, feature numbering, and preservation of an existing specification. |
| scripts/powershell/create-new-feature.ps1 | Uses literal path handling for repository navigation, feature discovery, and existing specification checks. |
Review effort: Lite (auto)
read_text() translates line endings, so the check could not tell a preserved spec.md from one rewritten with different newlines. Write the existing spec with CRLF line endings and compare raw bytes. Assisted-by: OpenCode (model: Claude Opus 5.5, autonomous)
There was a problem hiding this comment.
🟢 Approval recommended
No active issues were identified, and the change includes targeted regression coverage for bracketed paths, sequential numbering, and preservation of existing specifications.
No open issues 🎉
1 resolved since last review
Review effort: Lite (auto)
There was a problem hiding this comment.
🟢 Approval recommended
No active issues were identified, and the changes include literal-path handling plus regression coverage for bracketed project paths, feature numbering, and specification preservation.
No open issues 🎉
Review effort: Lite (auto)
|
Thank you! |

Description
Fixes #5398.
In a project whose path contains
[or](for exampleapp [v2]),scripts/powershell/create-new-feature.ps1reads the brackets as wildcards because it passes the project path toSet-Location,Test-PathandGet-ChildItemwithout-LiteralPath:Set-Location $repoRootfails with "Cannot find path ... because it does not exist", so the script exits 1 before creating anything. The Python helper creates the feature in the same project.Get-HighestNumberFromSpecs(Test-Path $SpecsDir,Get-ChildItem -Path $SpecsDir) sees no existing feature directories, so a new feature is numbered001again next to an existing001-*.$needsSpec = -not (Test-Path -PathType Leaf $specFile)reports an existingspec.mdas missing, so-AllowExistingBranchon an existing feature rewrites itsspec.md.This PR switches those four calls to
-LiteralPath.New-Item -Pathalready treats its path literally, so it is unchanged. #4956 and #4970 fixed bracketed feature directories and #5396 covers the template lookup incommon.ps1; neither changes this script, and the two PRs do not overlap. With only this PR, a bracketed project gets a correctly numbered feature, butspec.mdstarts empty with the existing "Spec template not found" warning until #5396 lands. With both applied,spec.mdgets the template.Testing
.\.venv\Scripts\specify.exe --help.\.venv\Scripts\python.exe -m pytest tests -q, using the affected test paths:tests/test_create_new_feature_python_parity.pyandtests/test_timestamp_branches.pygive 54 passed, 191 skipped (the skips are the bash cases, which skip on this Windows machine)New test
test_powershell_handles_bracketed_repo_pathintests/test_create_new_feature_python_parity.pyruns the PowerShell and Python helpers in projects namedps [v2]andpy [v2]that already containspecs/001-login-page/spec.md. It checks that both helpers exit 0 and name the new feature002-payment-export, and that-AllowExistingBranch -Number 1 -ShortName login-pagekeeps the existingspec.mdbyte for byte (the test writes it with CRLF line endings and compares raw bytes). It runs on Windows PowerShell 5.1.26100 here (POWERSHELL_EXEresolves topowershell.exe, sincepwshis not installed):main: fails at the PowerShell exit code (Set-Location : Cannot find path ...);'001-payment-export' == '002-payment-export';$needsSpecline reverted: fails withb'' == b'# My spec\r\n\r\nKeep this.\r\n'(the existingspec.mdis emptied);Sample project (Windows PowerShell 5.1):
specify init 'app [v2]' --integration codex --script ps --ignore-agent-tools --non-interactivefrom v1.4.0, plusspecs\001-login-page. Running.\.specify\scripts\powershell\create-new-feature.ps1 -Json 'Add payment export'fails atSet-Locationwith the shipped script, and prints002-payment-exportwith exit 0 with this change.Also ran
uvx ruff@0.15.0 check src tests(all checks passed) andgit diff --check(clean), and parsed the changed script with the Windows PowerShell 5.1 parser (no errors).AI Disclosure
AI disclosure: OpenCode with Claude Opus 5.5 (max reasoning effort, autonomous agent mode), acting on behalf of @adityajai119, found and reproduced the bug, wrote the fix and the test, ran the checks above, and drafted this description. Both commits carry an
Assisted-by: OpenCode (model: Claude Opus 5.5, autonomous)trailer.