mirror of
https://github.com/github/spec-kit.git
synced 2026-08-03 06:26:30 +08:00
fix(workflows): dispatch prompt steps via the resolved executable (#3793)
PromptStep._try_dispatch runs `subprocess.run(exec_args, ...)` with an
UNRESOLVED argv[0] -- a bare name like `claude`. On Windows subprocess.run calls
CreateProcess, which does not consult PATHEXT, so an agent CLI installed as a
`.cmd`/`.bat` shim (the usual npm layout) raises FileNotFoundError [WinError 2].
That OSError is swallowed by the method's `except OSError: return None`, and
execute() then reports "CLI not found or not installed" -- even though the
step's own preflight `shutil.which(...)` two lines earlier just found it.
The sibling path does not have this bug: IntegrationBase.dispatch_command (used
by the `command` step) resolves argv[0] through shutil.which first, added in
8e5643d for exactly this reason. Same machine, same integration, CLI present as
a .cmd shim:
type: prompt -> failed "integration 'claude' CLI not found or not installed."
type: command -> completed
Primitive confirmation: bare `subprocess.run(["fakeagent"])` raises
[WinError 2] while `subprocess.run([shutil.which("fakeagent")])` runs fine.
Reuse the path the preflight already resolved (`fallback_cli_path`) instead of
calling which() again, so the shim is executed. On POSIX it is the same
executable, so behaviour is unchanged there.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -169,6 +169,17 @@ class PromptStep(StepBase):
|
||||
if not exec_args:
|
||||
return None
|
||||
|
||||
# Windows: ``subprocess.run`` calls ``CreateProcess``, which does not
|
||||
# consult ``PATHEXT``, so a bare command name like ``claude`` installed
|
||||
# as ``claude.cmd`` (the usual npm shim layout) fails with
|
||||
# ``WinError 2``. That OSError is swallowed below and reported as "CLI
|
||||
# not found or not installed" -- even though the preflight above just
|
||||
# found it. Reuse the already-resolved path so the shim is executed,
|
||||
# mirroring ``IntegrationBase.dispatch_command``, which the ``command``
|
||||
# step already goes through. On POSIX this is the same executable.
|
||||
if fallback_cli_path:
|
||||
exec_args = [fallback_cli_path, *exec_args[1:]]
|
||||
|
||||
import subprocess
|
||||
|
||||
project_root = (
|
||||
|
||||
Reference in New Issue
Block a user