diff --git a/scripts/execute.py b/scripts/execute.py index 492a5fb..6f88754 100644 --- a/scripts/execute.py +++ b/scripts/execute.py @@ -12,6 +12,7 @@ import fnmatch import json import os import re +import shutil import subprocess import sys import threading @@ -373,7 +374,7 @@ class StepExecutor: prompt = preamble + step_file.read_text(encoding="utf-8") result = subprocess.run( - ["codex", "exec", "--dangerously-bypass-approvals-and-sandbox", "--json", "-"], + [self._codex_command(), "exec", "--dangerously-bypass-approvals-and-sandbox", "--json", "-"], cwd=self._root, capture_output=True, text=True, input=prompt, timeout=1800, ) @@ -395,6 +396,15 @@ class StepExecutor: # --- 헤더 & 검증 --- + @staticmethod + def _codex_command() -> str: + return ( + shutil.which("codex.cmd") + or shutil.which("codex.exe") + or shutil.which("codex") + or "codex" + ) + def _print_header(self): print(f"\n{'='*60}") print(f" Harness Step Executor") diff --git a/scripts/test_execute.py b/scripts/test_execute.py index 8efe216..e112e32 100644 --- a/scripts/test_execute.py +++ b/scripts/test_execute.py @@ -294,17 +294,31 @@ class ExecuteRunnerSafetyTests(unittest.TestCase): return subprocess.CompletedProcess(cmd, 0, '{"event":"done"}\n', "") with patch.object(execute.subprocess, "run", side_effect=fake_run) as run_mock: - executor._invoke_codex(step, long_preamble) + with patch.object(executor, "_codex_command", return_value="codex.cmd"): + executor._invoke_codex(step, long_preamble) cmd = run_mock.call_args.args[0] kwargs = run_mock.call_args.kwargs self.assertEqual( cmd, - ["codex", "exec", "--dangerously-bypass-approvals-and-sandbox", "--json", "-"], + ["codex.cmd", "exec", "--dangerously-bypass-approvals-and-sandbox", "--json", "-"], ) self.assertEqual(kwargs["input"], long_preamble + "# Step 1\n") self.assertEqual(kwargs["cwd"], str(root)) + def test_codex_command_prefers_windows_cmd_or_exe_shim(self): + execute = load_execute() + + def fake_which(name): + return { + "codex.cmd": "C:/tools/codex.cmd", + "codex.exe": "C:/tools/codex.exe", + "codex": "C:/tools/codex", + }.get(name) + + with patch.object(execute.shutil, "which", side_effect=fake_which): + self.assertEqual(execute.StepExecutor._codex_command(), "C:/tools/codex.cmd") + if __name__ == "__main__": unittest.main()