diff --git a/lib/lib-review-loop b/lib/lib-review-loop index 94b49e0..37400c7 100644 --- a/lib/lib-review-loop +++ b/lib/lib-review-loop @@ -151,17 +151,25 @@ run_claude() { # Run Codex CLI with a prompt. Wraps the prompt with a preamble that prevents # conversational output, and disables MCP servers to avoid artifact creation. +# +# --sandbox workspace-write, not --full-auto: codex-cli dropped --full-auto from +# the `exec` subcommand (gone as of 0.147.0), and an unknown flag is a hard +# parse error, so the agent never starts and the loop exits with no review. +# workspace-write is the equivalent policy -- `exec` is already non-interactive, +# so there are no approvals to auto-accept, only the sandbox to widen far enough +# that the reviewer can write agent-code-review.md. # $1: prompt text run_codex() { local prompt="$1" local wrapped="Execute the following task now. Do not introduce yourself. Begin immediately. $prompt" - echo "$wrapped" | codex exec --full-auto --config 'mcp_servers={}' - + echo "$wrapped" | codex exec --sandbox workspace-write --config 'mcp_servers={}' - } # Run Antigravity CLI with a prompt in non-interactive headless mode. -# Uses --dangerously-skip-permissions for auto-approval (equivalent to Codex --full-auto). +# Uses --dangerously-skip-permissions for auto-approval (the Codex equivalent is +# --sandbox workspace-write; see run_codex). # The prompt MUST be piped via stdin without -p: since agy 1.1.1, passing any # -p value disables stdin reading, and whitespace-only -p values are rejected # as an empty prompt. A piped stdin prompt alone still enters print mode. diff --git a/test/lib-review-loop.bats b/test/lib-review-loop.bats index 0f0987f..8c6ac94 100644 --- a/test/lib-review-loop.bats +++ b/test/lib-review-loop.bats @@ -558,3 +558,59 @@ make_run_dir() { # make_run_dir run is_inside_dir "logs/a.log" ""; assert_failure run is_inside_dir "logs/a.log" "$root/nope"; assert_failure } + +# ========================================================================= +# Codex invocation +# +# The flags run_codex passes are a compatibility surface, not an internal +# detail: codex rejects an unknown flag at parse time, so a stale one means +# the agent never starts and the loop ends with no review written. That +# failure looked like a codex problem rather than ours, so pin the contract. +# ========================================================================= + +stub_codex() { # records the argv it was invoked with, then succeeds + local dir="$BATS_TEST_TMPDIR/bin" + mkdir -p "$dir" + { + echo '#!/usr/bin/env bash' + echo 'cat >/dev/null' + printf 'printf "%%s\\n" "$@" > %q\n' "$BATS_TEST_TMPDIR/codex-argv" + } > "$dir/codex" + chmod +x "$dir/codex" + PATH="$dir:$PATH" +} + +@test "run_codex does not pass --full-auto, which codex exec no longer accepts" { + source_lib + stub_codex + run run_agent codex "a prompt" "Read" + assert_success + run cat "$BATS_TEST_TMPDIR/codex-argv" + refute_output --partial "--full-auto" +} + +@test "run_codex requests a sandbox that can write the review file" { + source_lib + stub_codex + run run_agent codex "a prompt" "Read" + assert_success + run cat "$BATS_TEST_TMPDIR/codex-argv" + # read-only would let the agent run but silently fail to write + # agent-code-review.md, which the loop reports as a dead codex. + assert_output --partial "--sandbox" + assert_output --partial "workspace-write" +} + +@test "run_codex still runs exec non-interactively with MCP servers disabled" { + source_lib + stub_codex + run run_agent codex "a prompt" "Read" + assert_success + run cat "$BATS_TEST_TMPDIR/codex-argv" + assert_output --partial "exec" + assert_output --partial "mcp_servers={}" + # The trailing "-" is what makes codex read the prompt from stdin. + # assert_line matches a whole argument: --partial would also be satisfied + # by the hyphens in --sandbox, so it would pass with the "-" removed. + assert_line "-" +}