diff --git a/automation/patcher.py b/automation/patcher.py index a1f415f..08b4e79 100644 --- a/automation/patcher.py +++ b/automation/patcher.py @@ -16,6 +16,7 @@ from pathlib import Path from typing import Any import json +import shlex from automation.ai_config import ( DEFAULT_COMMAND_CHAIN, @@ -674,18 +675,27 @@ def _run_codex_command(command: str, prompt: str, cwd: Path) -> tuple[str, str, def _ensure_codex_json(command: str) -> str: - """Ensure codex command runs via `codex exec --json --color=never` for machine parsing.""" - parts = command.strip().split() - if len(parts) >= 2 and parts[1] == "exec": - base = command - else: - base = command.replace("codex", "codex exec", 1) + """Ensure codex command runs via `codex exec --json --color=never -` for machine parsing.""" + tokens = shlex.split(command) + if not tokens: + return command - if "--json" not in base: - base = f"{base} --json" - if "--color" not in base: - base = f"{base} --color=never" - return base + if tokens[0] != "codex": + return command + + if len(tokens) == 1 or tokens[1] != "exec": + tokens.insert(1, "exec") + + if "--json" not in tokens: + tokens.append("--json") + + if not any(t.startswith("--color") for t in tokens): + tokens.append("--color=never") + + if "-" not in tokens: + tokens.append("-") + + return shlex.join(tokens) def _extract_codex_last_message(stdout_text: str) -> str: diff --git a/tests/test_patcher.py b/tests/test_patcher.py index 24cb8e5..136ff42 100644 --- a/tests/test_patcher.py +++ b/tests/test_patcher.py @@ -5,7 +5,12 @@ import pytest from automation.config import RulesConfig from automation.ai_config import DEFAULT_SENTINEL -from automation.patcher import ModelConfig, PatchGenerationError, generate_output +from automation.patcher import ( + ModelConfig, + PatchGenerationError, + generate_output, + _ensure_codex_json, +) @pytest.fixture() @@ -59,11 +64,12 @@ diff --git a/Docs/features/FR_1/discussions/example.discussion.sum.md b/Docs/fea assert output_file.exists() assert output_file.read_text(encoding="utf-8") == "Line one\nLine two\n" - staged = subprocess.run( - ["git", "diff", "--cached", "--name-only"], - cwd=temp_repo, - check=True, - capture_output=True, - text=True, - ).stdout.split() - assert "Docs/features/FR_1/discussions/example.discussion.sum.md" in staged + +def test_ensure_codex_json_adds_exec_and_stdin() -> None: + cmd = "codex --model gpt-5" + rewritten = _ensure_codex_json(cmd) + # Should include exec, --json, --color=never, and '-' for stdin + assert "codex exec" in rewritten + assert "--json" in rewritten + assert "--color=never" in rewritten + assert rewritten.rstrip().endswith(" -") or " - " in rewritten