### Summary On a stock Windows machine (Git for Windows only — no jq, no real Python on `PATH`), every bash-variant script that reads `.specify/feature.json` fails with `ERROR: Feature directory not found ...` immediately after a successful `specify init --script sh`. The cause is that the JSON parser fallback chain in `common.sh` selects `python3` based on **existence** (`command -v`), but on Windows `python3` resolves to the **Microsoft Store App Execution Alias stub**, which exists on `PATH` yet fails at runtime. The chain then swallows the runtime failure and returns an empty value, and the `grep/sed` last-resort parser is unreachable because the chain is `if/elif/else` on availability, not on parse success. ### Environment - Spec Kit `v0.12.3` (installed via `uv tool`/`uvx` from the git tag) - Windows 11, Git for Windows (bash 5.2.37, MSYS), run under Git Bash - No `jq` installed (Git for Windows does not ship one) - No real Python on `PATH`; `C:\Users\<user>\AppData\Local\Microsoft\WindowsApps\python3.exe` stub present (Windows default) ### Reproduction ```bash # on the machine described above, in Git Bash uvx --from "git+https://github.com/github/spec-kit.git@v0.12.3" \ specify init target --integration generic \ --integration-options "--commands-dir .agent/commands" \ --script sh --ignore-agent-tools cd target && git init -b main . && git add -A && git commit -m scaffold bash .specify/scripts/bash/create-new-feature.sh --json --short-name demo "demo feature" # ^ succeeds, persists .specify/feature.json = {"feature_directory":"specs/001-demo"} bash .specify/scripts/bash/setup-plan.sh --json # ERROR: Feature directory not found. Set SPECIFY_FEATURE_DIRECTORY or ensure # .specify/feature.json contains feature_directory. ``` `feature.json` exists and contains the key — it just can't be read: ```bash $ command -v python3 /c/Users/<user>/AppData/Local/Microsoft/WindowsApps/python3 $ python3 -c "print(42)"; echo exit=$? Python was not found; run without arguments to install from the Microsoft Store, ... exit=49 ``` ### Root cause `scripts/bash/common.sh`, `read_feature_json_feature_directory()` (v0.12.3, ~lines 95–120): ```bash if command -v jq >/dev/null 2>&1; then ... jq ... elif command -v python3 >/dev/null 2>&1; then # <- stub passes this test if ! _fd=$(python3 -c "..." 2>/dev/null); then # <- fails at runtime (exit 49) _fd='' # <- failure swallowed fi else ... grep/sed fallback ... # <- unreachable fi ``` `create-new-feature.sh` masks the problem on its own persist path (it falls back to `printf` for writing), so the failure only appears one script later, which makes it look like state corruption rather than a parser issue. Notably, CI runners (GitHub Actions `windows-latest` etc.) never see this: they ship both `jq` and a real `python3`. It only bites real end-user Windows machines — which are exactly the machines the sh-variant + Git Bash path is meant to serve. ### Suggested fix Any of these would do (first is smallest): 1. Runtime-probe instead of existence-probe: `python3 -c 'print(0)' >/dev/null 2>&1` before committing to the python3 branch (the stub also fails this, exit 49). 2. Fall through the chain on parse failure rather than returning empty (`jq` → `python3` → `grep/sed` as successive *attempts*, not exclusive branches). 3. Prefer `python` over `python3` on MSYS/Windows, or check both. The same existence-vs-runtime pattern may exist in other scripts that shell out to `python3`; worth a quick grep. ### Workaround (for anyone else hitting this) Install jq, disable the `python3` App Execution Alias, or expose a real interpreter as `python3` (e.g. one managed by `uv python install`).