* chore: align CI Python matrix with devguide release lifecycle
Run the pytest matrix only on the bugfix (maintenance) releases — 3.13
and 3.14 — instead of 3.11/3.12/3.13, and point the ruff lint job at the
latest interpreter (3.14). The supported floor stays at requires-python
>= 3.11 (oldest non-EOL security release): older security versions are
supported by claim and fixed reactively rather than gated on a wide
per-commit matrix. Also add macos-latest to the OS matrix so macOS
regressions are caught.
Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: make bash scripts portable to bash 3.2 (macOS system /bin/bash)
Adding macos-latest to the CI matrix surfaced two pre-existing bash 3.2
incompatibilities (macOS ships bash 3.2 as /bin/bash):
1. update-agent-context.sh embedded Python heredocs inside $(...) command
substitution. bash 3.2 mis-parses an apostrophe in a heredoc body
nested in $(...), failing with "unexpected EOF while looking for
matching `''". Removed the apostrophes from the affected $()-nested
heredoc body and documented the constraint to prevent regressions.
2. create-new-feature-branch.sh and create-new-feature.sh used the
bash 4+ ${word^^} uppercase parameter expansion, which errors as a
"bad substitution" on bash 3.2 and caused short uppercase acronyms
(e.g. "GO") to be dropped from derived branch names. Replaced with a
portable `tr '[:lower:]' '[:upper:]'` pipeline.
Verified the full test suite passes under bash 3.2.57 and shellcheck
(--severity=error) is clean.
Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: address review feedback on bash 3.2 portability changes
- create-new-feature.sh: replace the non-portable `\b...\b` grep
word-boundary (BSD grep treats `\b` as a backspace, so the acronym
branch could silently fail) with `grep -qw`, matching its twin
create-new-feature-branch.sh, and pipe the description via
`printf '%s'` instead of `echo`.
- create-new-feature-branch.sh: switch the acronym check to
`printf '%s'` as well so both twins are identical and avoid `echo`
on user-provided text.
- update-agent-context.sh: reword the apostrophe-free self-seeding
comment to be clearer and less easy to misread.
Verified under bash 3.2.57 (full bash-script suite green) and
shellcheck --severity=error.
Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* ci: add windows-latest to test matrix
Add windows-latest to the pytest job OS matrix so tests run on both
Ubuntu and Windows for all Python versions.
Closes#2232
* test: skip bash-specific tests on Windows
Add sys.platform skip markers to all test classes and methods that
execute bash scripts via subprocess, so they are skipped on Windows
where bash is not available. Mixed classes with both bash and pwsh
tests have markers on individual bash methods only.
* test: fix 3 Windows-specific test failures
- test_manifest: use platform-appropriate absolute path (C:\ on Windows
vs /tmp on POSIX) since /tmp is not absolute on Windows
- test_extensions: add agent_scripts.ps entry and platform-conditional
assertions for codex skill fallback variant test
- test_timestamp_branches: use json.dumps() instead of f-string to
properly escape Windows backslash paths in feature.json
* test: extract requires_bash marker and fix PS test skip
Address PR review feedback:
- Define a reusable requires_bash marker in conftest.py and use it
across all 3 test files instead of repeating the skipif inline
- Move test_powershell_scanner_uses_long_tryparse_for_large_prefixes
into its own TestSequentialBranchPowerShell class so it is not
incorrectly skipped on Windows by the class-level bash marker
* test: use runtime bash check instead of platform check
Replace sys.platform == 'win32' with an actual bash invocation test
to handle environments where bash exists but is non-functional (e.g.,
WSL stub on Windows without an installed distro).
* test: reject WSL bash, accept only MSYS/MINGW on Windows
On Windows, verify uname -s reports MSYS, MINGW, or CYGWIN so the WSL
launcher (System32\bash.exe) is rejected — it cannot handle native
Windows paths used by test fixtures. Add SPECKIT_TEST_BASH=1 env var
escape hatch to force-enable bash tests in non-standard setups.
* ci: add comment explaining Windows bash test behavior
* test: early-reject WSL launcher, fix remaining f-string JSON
- Check resolved bash path for System32 before spawning any subprocess
to avoid WSL init prompts and timeout during test collection
- Convert remaining feature_json f-string writes to json.dumps() so
paths with backslashes produce valid JSON on Windows
* test: use bare 'bash' for detection to match test invocation
On Windows, subprocess.run(['bash', ...]) uses CreateProcess which
searches System32 before PATH — finding WSL bash even when
shutil.which('bash') returns Git-for-Windows. Probe with bare 'bash'
(same as test helpers) so the detection matches actual test behavior.