diff --git a/autoplan/SKILL.md b/autoplan/SKILL.md index 9afcdf391..abc7b8d04 100644 --- a/autoplan/SKILL.md +++ b/autoplan/SKILL.md @@ -1201,7 +1201,7 @@ Override: every AskUserQuestion → auto-decide using the 6 principles. What alternatives were dismissed too quickly? What competitive or market risks are unaddressed? What scope decisions will look foolish in 6 months? Be adversarial. No compliments. Just the strategic blind spots. - File: " -C "$_REPO_ROOT" -s read-only --enable web_search_cached < /dev/null + File: " -C "$_REPO_ROOT" -s read-only -c 'web_search="cached"' < /dev/null _CODEX_EXIT=$? if [ "$_CODEX_EXIT" = "124" ]; then _gstack_codex_log_event "codex_timeout" "600" @@ -1324,7 +1324,7 @@ Override: every AskUserQuestion → auto-decide using the 6 principles. accessibility requirements (keyboard nav, contrast, touch targets) specified or aspirational? Does the plan describe specific UI decisions or generic patterns? What design decisions will haunt the implementer if left ambiguous? - Be opinionated. No hedging." -C "$_REPO_ROOT" -s read-only --enable web_search_cached < /dev/null + Be opinionated. No hedging." -C "$_REPO_ROOT" -s read-only -c 'web_search="cached"' < /dev/null _CODEX_EXIT=$? if [ "$_CODEX_EXIT" = "124" ]; then _gstack_codex_log_event "codex_timeout" "600" @@ -1400,7 +1400,7 @@ Override: every AskUserQuestion → auto-decide using the 6 principles. CEO: Design: - File: " -C "$_REPO_ROOT" -s read-only --enable web_search_cached < /dev/null + File: " -C "$_REPO_ROOT" -s read-only -c 'web_search="cached"' < /dev/null _CODEX_EXIT=$? if [ "$_CODEX_EXIT" = "124" ]; then _gstack_codex_log_event "codex_timeout" "600" @@ -1526,7 +1526,7 @@ Log: "Phase 3.5 skipped — no developer-facing scope detected." 3. API/CLI design: are names guessable? Are defaults sensible? Is it consistent? 4. Docs: can a dev find what they need in under 2 minutes? Are examples copy-paste-complete? 5. Upgrade path: can devs upgrade without fear? Migration guides? Deprecation warnings? - Be adversarial. Think like a developer who is evaluating this against 3 competitors." -C "$_REPO_ROOT" -s read-only --enable web_search_cached < /dev/null + Be adversarial. Think like a developer who is evaluating this against 3 competitors." -C "$_REPO_ROOT" -s read-only -c 'web_search="cached"' < /dev/null _CODEX_EXIT=$? if [ "$_CODEX_EXIT" = "124" ]; then _gstack_codex_log_event "codex_timeout" "600" diff --git a/autoplan/SKILL.md.tmpl b/autoplan/SKILL.md.tmpl index 011bbacdd..1b3d183f9 100644 --- a/autoplan/SKILL.md.tmpl +++ b/autoplan/SKILL.md.tmpl @@ -306,7 +306,7 @@ Override: every AskUserQuestion → auto-decide using the 6 principles. What alternatives were dismissed too quickly? What competitive or market risks are unaddressed? What scope decisions will look foolish in 6 months? Be adversarial. No compliments. Just the strategic blind spots. - File: " -C "$_REPO_ROOT" -s read-only --enable web_search_cached < /dev/null + File: " -C "$_REPO_ROOT" -s read-only {{CODEX_WEB_SEARCH_FLAG}} < /dev/null _CODEX_EXIT=$? if [ "$_CODEX_EXIT" = "124" ]; then _gstack_codex_log_event "codex_timeout" "600" @@ -429,7 +429,7 @@ Override: every AskUserQuestion → auto-decide using the 6 principles. accessibility requirements (keyboard nav, contrast, touch targets) specified or aspirational? Does the plan describe specific UI decisions or generic patterns? What design decisions will haunt the implementer if left ambiguous? - Be opinionated. No hedging." -C "$_REPO_ROOT" -s read-only --enable web_search_cached < /dev/null + Be opinionated. No hedging." -C "$_REPO_ROOT" -s read-only {{CODEX_WEB_SEARCH_FLAG}} < /dev/null _CODEX_EXIT=$? if [ "$_CODEX_EXIT" = "124" ]; then _gstack_codex_log_event "codex_timeout" "600" @@ -505,7 +505,7 @@ Override: every AskUserQuestion → auto-decide using the 6 principles. CEO: Design: - File: " -C "$_REPO_ROOT" -s read-only --enable web_search_cached < /dev/null + File: " -C "$_REPO_ROOT" -s read-only {{CODEX_WEB_SEARCH_FLAG}} < /dev/null _CODEX_EXIT=$? if [ "$_CODEX_EXIT" = "124" ]; then _gstack_codex_log_event "codex_timeout" "600" @@ -631,7 +631,7 @@ Log: "Phase 3.5 skipped — no developer-facing scope detected." 3. API/CLI design: are names guessable? Are defaults sensible? Is it consistent? 4. Docs: can a dev find what they need in under 2 minutes? Are examples copy-paste-complete? 5. Upgrade path: can devs upgrade without fear? Migration guides? Deprecation warnings? - Be adversarial. Think like a developer who is evaluating this against 3 competitors." -C "$_REPO_ROOT" -s read-only --enable web_search_cached < /dev/null + Be adversarial. Think like a developer who is evaluating this against 3 competitors." -C "$_REPO_ROOT" -s read-only {{CODEX_WEB_SEARCH_FLAG}} < /dev/null _CODEX_EXIT=$? if [ "$_CODEX_EXIT" = "124" ]; then _gstack_codex_log_event "codex_timeout" "600" diff --git a/codex/SKILL.md b/codex/SKILL.md index ff35f0a98..700800497 100644 --- a/codex/SKILL.md +++ b/codex/SKILL.md @@ -1030,7 +1030,7 @@ cd "$_REPO_ROOT" # The 330s wrapper sits BELOW the 360s Bash gate so the wrapper fires FIRST # and a stall surfaces as a diagnosable exit 124 with an explicit message, # never as a silent harness kill that downstream reads as "no findings". -_gstack_codex_timeout_wrapper 330 codex review --base -c 'sandbox_mode="read-only"' -c 'model_reasoning_effort="high"' --enable web_search_cached < /dev/null 2>"$TMPERR" +_gstack_codex_timeout_wrapper 330 codex review --base -c 'sandbox_mode="read-only"' -c 'model_reasoning_effort="high"' -c 'web_search="cached"' < /dev/null 2>"$TMPERR" _CODEX_EXIT=$? if [ "$_CODEX_EXIT" = "124" ]; then _gstack_codex_log_event "codex_timeout" "330" @@ -1071,7 +1071,7 @@ _PROMPT_FILE=$(mktemp "$TMP_ROOT/codex-prompt-XXXXXX") git diff "...HEAD" 2>/dev/null printf '\nDIFF_END\n' } > "$_PROMPT_FILE" -_gstack_codex_timeout_wrapper 330 codex exec -s read-only "$(cat "$_PROMPT_FILE")" -c 'model_reasoning_effort="high"' --enable web_search_cached < /dev/null 2>"$TMPERR" +_gstack_codex_timeout_wrapper 330 codex exec -s read-only "$(cat "$_PROMPT_FILE")" -c 'model_reasoning_effort="high"' -c 'web_search="cached"' < /dev/null 2>"$TMPERR" _CODEX_EXIT=$? rm -f "$_PROMPT_FILE" if [ "$_CODEX_EXIT" = "124" ]; then @@ -1352,7 +1352,7 @@ fi # Fix 1+2: wrap with timeout (gtimeout/timeout fallback chain via probe helper), # capture stderr to $TMPERR for auth error detection (was: 2>/dev/null). TMPERR=${TMPERR:-$(mktemp "$TMP_ROOT/codex-err-XXXXXX")} -_gstack_codex_timeout_wrapper 600 codex exec "" -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' --enable web_search_cached --json < /dev/null 2>"$TMPERR" | PYTHONUNBUFFERED=1 "$PYTHON_CMD" -u -c " +_gstack_codex_timeout_wrapper 600 codex exec "" -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' -c 'web_search="cached"' --json < /dev/null 2>"$TMPERR" | PYTHONUNBUFFERED=1 "$PYTHON_CMD" -u -c " import sys, json turn_completed_count = 0 for line in sys.stdin: @@ -1510,7 +1510,7 @@ if [ -z "$PYTHON_CMD" ]; then exit 1 fi # Fix 1: wrap with timeout (gtimeout/timeout fallback chain via probe helper) -_gstack_codex_timeout_wrapper 600 codex exec "" -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="medium"' --enable web_search_cached --json < /dev/null 2>"$TMPERR" | PYTHONUNBUFFERED=1 "$PYTHON_CMD" -u -c " +_gstack_codex_timeout_wrapper 600 codex exec "" -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="medium"' -c 'web_search="cached"' --json < /dev/null 2>"$TMPERR" | PYTHONUNBUFFERED=1 "$PYTHON_CMD" -u -c " import sys, json for line in sys.stdin: line = line.strip() @@ -1564,7 +1564,7 @@ if [ -z "$PYTHON_CMD" ]; then fi cd "$_REPO_ROOT" || exit 1 # Fix 1: wrap with timeout (gtimeout/timeout fallback chain via probe helper) -_gstack_codex_timeout_wrapper 600 codex exec resume "" -c 'sandbox_mode="read-only"' -c 'model_reasoning_effort="medium"' --enable web_search_cached --json < /dev/null 2>"$TMPERR" | PYTHONUNBUFFERED=1 "$PYTHON_CMD" -u -c " +_gstack_codex_timeout_wrapper 600 codex exec resume "" -c 'sandbox_mode="read-only"' -c 'model_reasoning_effort="medium"' -c 'web_search="cached"' --json < /dev/null 2>"$TMPERR" | PYTHONUNBUFFERED=1 "$PYTHON_CMD" -u -c " " # Fix 1: same hang detection pattern as new-session block @@ -1637,8 +1637,13 @@ by mode (see below). tasks (OpenAI issues #8545, #8402, #6931). Users can override with `--xhigh` flag (e.g., `/codex review --xhigh`) when they want maximum reasoning and are willing to wait. -**Web search:** All codex commands use `--enable web_search_cached` so Codex can look up -docs and APIs during review. This is OpenAI's cached index — fast, no extra cost. +**Web search:** All codex commands pass `-c 'web_search="cached"'` so `codex exec` +invocations can look up docs and APIs during review. This is OpenAI's cached index — +fast, no extra cost. Unlike the legacy `--enable`-based spelling (deprecated by +codex >=0.144), the `-c` form explicitly overrides any top-level +`web_search` setting in `~/.codex/config.toml`. Note: native `codex review` disables +web search regardless of configuration, so on the default Review path the flag is a +harmless no-op — only exec-based modes actually search. If the user specifies a model (e.g., `/codex review -m gpt-5.1-codex-max` or `/codex challenge -m gpt-5.2`), the flag to pass depends on the underlying command: diff --git a/codex/SKILL.md.tmpl b/codex/SKILL.md.tmpl index ce3b84295..88f48d00a 100644 --- a/codex/SKILL.md.tmpl +++ b/codex/SKILL.md.tmpl @@ -203,7 +203,7 @@ cd "$_REPO_ROOT" # The 330s wrapper sits BELOW the 360s Bash gate so the wrapper fires FIRST # and a stall surfaces as a diagnosable exit 124 with an explicit message, # never as a silent harness kill that downstream reads as "no findings". -_gstack_codex_timeout_wrapper 330 codex review --base -c 'sandbox_mode="read-only"' -c 'model_reasoning_effort="high"' --enable web_search_cached < /dev/null 2>"$TMPERR" +_gstack_codex_timeout_wrapper 330 codex review --base -c 'sandbox_mode="read-only"' -c 'model_reasoning_effort="high"' {{CODEX_WEB_SEARCH_FLAG}} < /dev/null 2>"$TMPERR" _CODEX_EXIT=$? if [ "$_CODEX_EXIT" = "124" ]; then _gstack_codex_log_event "codex_timeout" "330" @@ -244,7 +244,7 @@ _PROMPT_FILE=$(mktemp "$TMP_ROOT/codex-prompt-XXXXXX") git diff "...HEAD" 2>/dev/null printf '\nDIFF_END\n' } > "$_PROMPT_FILE" -_gstack_codex_timeout_wrapper 330 codex exec -s read-only "$(cat "$_PROMPT_FILE")" -c 'model_reasoning_effort="high"' --enable web_search_cached < /dev/null 2>"$TMPERR" +_gstack_codex_timeout_wrapper 330 codex exec -s read-only "$(cat "$_PROMPT_FILE")" -c 'model_reasoning_effort="high"' {{CODEX_WEB_SEARCH_FLAG}} < /dev/null 2>"$TMPERR" _CODEX_EXIT=$? rm -f "$_PROMPT_FILE" if [ "$_CODEX_EXIT" = "124" ]; then @@ -403,7 +403,7 @@ fi # Fix 1+2: wrap with timeout (gtimeout/timeout fallback chain via probe helper), # capture stderr to $TMPERR for auth error detection (was: 2>/dev/null). TMPERR=${TMPERR:-$(mktemp "$TMP_ROOT/codex-err-XXXXXX")} -_gstack_codex_timeout_wrapper 600 codex exec "" -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' --enable web_search_cached --json < /dev/null 2>"$TMPERR" | PYTHONUNBUFFERED=1 "$PYTHON_CMD" -u -c " +_gstack_codex_timeout_wrapper 600 codex exec "" -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' {{CODEX_WEB_SEARCH_FLAG}} --json < /dev/null 2>"$TMPERR" | PYTHONUNBUFFERED=1 "$PYTHON_CMD" -u -c " import sys, json turn_completed_count = 0 for line in sys.stdin: @@ -561,7 +561,7 @@ if [ -z "$PYTHON_CMD" ]; then exit 1 fi # Fix 1: wrap with timeout (gtimeout/timeout fallback chain via probe helper) -_gstack_codex_timeout_wrapper 600 codex exec "" -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="medium"' --enable web_search_cached --json < /dev/null 2>"$TMPERR" | PYTHONUNBUFFERED=1 "$PYTHON_CMD" -u -c " +_gstack_codex_timeout_wrapper 600 codex exec "" -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="medium"' {{CODEX_WEB_SEARCH_FLAG}} --json < /dev/null 2>"$TMPERR" | PYTHONUNBUFFERED=1 "$PYTHON_CMD" -u -c " import sys, json for line in sys.stdin: line = line.strip() @@ -615,7 +615,7 @@ if [ -z "$PYTHON_CMD" ]; then fi cd "$_REPO_ROOT" || exit 1 # Fix 1: wrap with timeout (gtimeout/timeout fallback chain via probe helper) -_gstack_codex_timeout_wrapper 600 codex exec resume "" -c 'sandbox_mode="read-only"' -c 'model_reasoning_effort="medium"' --enable web_search_cached --json < /dev/null 2>"$TMPERR" | PYTHONUNBUFFERED=1 "$PYTHON_CMD" -u -c " +_gstack_codex_timeout_wrapper 600 codex exec resume "" -c 'sandbox_mode="read-only"' -c 'model_reasoning_effort="medium"' {{CODEX_WEB_SEARCH_FLAG}} --json < /dev/null 2>"$TMPERR" | PYTHONUNBUFFERED=1 "$PYTHON_CMD" -u -c " " # Fix 1: same hang detection pattern as new-session block @@ -688,8 +688,13 @@ by mode (see below). tasks (OpenAI issues #8545, #8402, #6931). Users can override with `--xhigh` flag (e.g., `/codex review --xhigh`) when they want maximum reasoning and are willing to wait. -**Web search:** All codex commands use `--enable web_search_cached` so Codex can look up -docs and APIs during review. This is OpenAI's cached index — fast, no extra cost. +**Web search:** All codex commands pass `{{CODEX_WEB_SEARCH_FLAG}}` so `codex exec` +invocations can look up docs and APIs during review. This is OpenAI's cached index — +fast, no extra cost. Unlike the legacy `--enable`-based spelling (deprecated by +codex >=0.144), the `-c` form explicitly overrides any top-level +`web_search` setting in `~/.codex/config.toml`. Note: native `codex review` disables +web search regardless of configuration, so on the default Review path the flag is a +harmless no-op — only exec-based modes actually search. If the user specifies a model (e.g., `/codex review -m gpt-5.1-codex-max` or `/codex challenge -m gpt-5.2`), the flag to pass depends on the underlying command: diff --git a/design-consultation/SKILL.md b/design-consultation/SKILL.md index 3a6232d95..5f72c9745 100644 --- a/design-consultation/SKILL.md +++ b/design-consultation/SKILL.md @@ -1170,7 +1170,7 @@ codex exec "Given this product context, propose a complete design direction: - Differentiation: 2 deliberate departures from category norms - Anti-slop: no purple gradients, no 3-column icon grids, no centered everything, no decorative blobs -Be opinionated. Be specific. Do not hedge. This is YOUR design direction — own it." -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="medium"' --enable web_search_cached < /dev/null 2>"$TMPERR_DESIGN" +Be opinionated. Be specific. Do not hedge. This is YOUR design direction — own it." -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="medium"' -c 'web_search="cached"' < /dev/null 2>"$TMPERR_DESIGN" ``` Use a 5-minute timeout (`timeout: 300000`). After the command completes, read stderr: ```bash diff --git a/design-review/SKILL.md b/design-review/SKILL.md index 68304d0c8..42bc31d6f 100644 --- a/design-review/SKILL.md +++ b/design-review/SKILL.md @@ -1809,7 +1809,7 @@ HARD REJECTION — flag if ANY apply: 6. Carousel with no narrative purpose 7. App UI made of stacked cards instead of layout -Be specific. Reference file:line for every finding." -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' --enable web_search_cached < /dev/null 2>"$TMPERR_DESIGN" +Be specific. Reference file:line for every finding." -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' -c 'web_search="cached"' < /dev/null 2>"$TMPERR_DESIGN" ``` Use a 5-minute timeout (`timeout: 300000`). After the command completes, read stderr: ```bash diff --git a/document-release/sections/release-body.md b/document-release/sections/release-body.md index 0f05f13b5..6efdaf259 100644 --- a/document-release/sections/release-body.md +++ b/document-release/sections/release-body.md @@ -428,7 +428,7 @@ THE DOCS AND DIFF: " ```bash TMPERR_DOC=$(mktemp /tmp/codex-docreview-XXXXXXXX) _REPO_ROOT=$(git rev-parse --show-toplevel) || { echo "ERROR: not in a git repo" >&2; exit 1; } -codex exec "" -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' --enable web_search_cached < /dev/null 2>"$TMPERR_DOC" +codex exec "" -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' -c 'web_search="cached"' < /dev/null 2>"$TMPERR_DOC" ``` Use a 5-minute timeout (`timeout: 300000`). After the command completes, read stderr: diff --git a/office-hours/SKILL.md b/office-hours/SKILL.md index 4584e4421..3343c5e41 100644 --- a/office-hours/SKILL.md +++ b/office-hours/SKILL.md @@ -1377,7 +1377,7 @@ Then add the context block and mode-appropriate instructions: ```bash TMPERR_OH=$(mktemp /tmp/codex-oh-err-XXXXXXXX) _REPO_ROOT=$(git rev-parse --show-toplevel) || { echo "ERROR: not in a git repo" >&2; exit 1; } -codex exec "$(cat "$CODEX_PROMPT_FILE")" -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' --enable web_search_cached < /dev/null 2>"$TMPERR_OH" +codex exec "$(cat "$CODEX_PROMPT_FILE")" -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' -c 'web_search="cached"' < /dev/null 2>"$TMPERR_OH" ``` Use a 5-minute timeout (`timeout: 300000`). After the command completes, read stderr: @@ -1627,7 +1627,7 @@ If user chooses A, launch both voices simultaneously: ```bash TMPERR_SKETCH=$(mktemp /tmp/codex-sketch-XXXXXXXX) _REPO_ROOT=$(git rev-parse --show-toplevel) || { echo "ERROR: not in a git repo" >&2; exit 1; } -codex exec "For this product approach, provide: a visual thesis (one sentence — mood, material, energy), a content plan (hero → support → detail → CTA), and 2 interaction ideas that change page feel. Apply beautiful defaults: composition-first, brand-first, cardless, poster not document. Be opinionated." -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="medium"' --enable web_search_cached < /dev/null 2>"$TMPERR_SKETCH" +codex exec "For this product approach, provide: a visual thesis (one sentence — mood, material, energy), a content plan (hero → support → detail → CTA), and 2 interaction ideas that change page feel. Apply beautiful defaults: composition-first, brand-first, cardless, poster not document. Be opinionated." -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="medium"' -c 'web_search="cached"' < /dev/null 2>"$TMPERR_SKETCH" ``` Use a 5-minute timeout (`timeout: 300000`). After completion: `cat "$TMPERR_SKETCH" && rm -f "$TMPERR_SKETCH"` diff --git a/plan-ceo-review/sections/review-sections.md b/plan-ceo-review/sections/review-sections.md index 71bae4d93..bed5c088e 100644 --- a/plan-ceo-review/sections/review-sections.md +++ b/plan-ceo-review/sections/review-sections.md @@ -315,7 +315,7 @@ THE PLAN: ```bash TMPERR_PV=$(mktemp /tmp/codex-planreview-XXXXXXXX) _REPO_ROOT=$(git rev-parse --show-toplevel) || { echo "ERROR: not in a git repo" >&2; exit 1; } -codex exec "" -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' --enable web_search_cached < /dev/null 2>"$TMPERR_PV" +codex exec "" -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' -c 'web_search="cached"' < /dev/null 2>"$TMPERR_PV" ``` Use a 5-minute timeout (`timeout: 300000`). After the command completes, read stderr: diff --git a/plan-design-review/SKILL.md b/plan-design-review/SKILL.md index 0e2940c7f..a9fadaaa1 100644 --- a/plan-design-review/SKILL.md +++ b/plan-design-review/SKILL.md @@ -1411,7 +1411,7 @@ HARD RULES — first classify as MARKETING/LANDING PAGE vs APP UI vs HYBRID, the - APP UI: Calm surface hierarchy, dense but readable, utility language, minimal chrome - UNIVERSAL: CSS variables for colors, no default font stacks, one job per section, cards earn existence -For each finding: what's wrong, what will happen if it ships unresolved, and the specific fix. Be opinionated. No hedging." -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' --enable web_search_cached < /dev/null 2>"$TMPERR_DESIGN" +For each finding: what's wrong, what will happen if it ships unresolved, and the specific fix. Be opinionated. No hedging." -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' -c 'web_search="cached"' < /dev/null 2>"$TMPERR_DESIGN" ``` Use a 5-minute timeout (`timeout: 300000`). After the command completes, read stderr: ```bash diff --git a/plan-devex-review/sections/review-sections.md b/plan-devex-review/sections/review-sections.md index e4ce30a95..82e79e7f7 100644 --- a/plan-devex-review/sections/review-sections.md +++ b/plan-devex-review/sections/review-sections.md @@ -301,7 +301,7 @@ THE PLAN: ```bash TMPERR_PV=$(mktemp /tmp/codex-planreview-XXXXXXXX) _REPO_ROOT=$(git rev-parse --show-toplevel) || { echo "ERROR: not in a git repo" >&2; exit 1; } -codex exec "" -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' --enable web_search_cached < /dev/null 2>"$TMPERR_PV" +codex exec "" -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' -c 'web_search="cached"' < /dev/null 2>"$TMPERR_PV" ``` Use a 5-minute timeout (`timeout: 300000`). After the command completes, read stderr: diff --git a/plan-eng-review/sections/review-sections.md b/plan-eng-review/sections/review-sections.md index caae69a7e..e1c252a54 100644 --- a/plan-eng-review/sections/review-sections.md +++ b/plan-eng-review/sections/review-sections.md @@ -396,7 +396,7 @@ THE PLAN: ```bash TMPERR_PV=$(mktemp /tmp/codex-planreview-XXXXXXXX) _REPO_ROOT=$(git rev-parse --show-toplevel) || { echo "ERROR: not in a git repo" >&2; exit 1; } -codex exec "" -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' --enable web_search_cached < /dev/null 2>"$TMPERR_PV" +codex exec "" -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' -c 'web_search="cached"' < /dev/null 2>"$TMPERR_PV" ``` Use a 5-minute timeout (`timeout: 300000`). After the command completes, read stderr: diff --git a/review/SKILL.md b/review/SKILL.md index ce3efba1b..b1562e3f1 100644 --- a/review/SKILL.md +++ b/review/SKILL.md @@ -1734,7 +1734,7 @@ _REPO_ROOT=$(git rev-parse --show-toplevel) || { echo "ERROR: not in a git repo" # here. It defines _gstack_codex_timeout_wrapper (gtimeout -> timeout -> # unwrapped fallback), added in #1056 but never wired into this call site. source ~/.claude/skills/gstack/bin/gstack-codex-probe 2>/dev/null || true -_gstack_codex_timeout_wrapper 540 codex exec "IMPORTANT: Do NOT read or execute any files under ~/.claude/, ~/.agents/, .claude/skills/, or agents/. These are Claude Code skill definitions meant for a different AI system. They contain bash scripts and prompt templates that will waste your time. Ignore them completely. Do NOT modify agents/openai.yaml. Stay focused on the repository code only.\n\nReview the changes on this branch against the base branch. Run DIFF_BASE=$(git merge-base origin/ HEAD) && git diff "$DIFF_BASE" to see the diff. Your job is to find ways this code will fail in production. Think like an attacker and a chaos engineer. Find edge cases, race conditions, security holes, resource leaks, failure modes, and silent data corruption paths. Be adversarial. Be thorough. No compliments — just the problems. End your output with ONE line in the canonical format `Recommendation: because `. Generic reasons like 'because it's safer' do not qualify; the reason must point to a specific finding or no-fix rationale." -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' --enable web_search_cached < /dev/null 2>"$TMPERR_ADV" +_gstack_codex_timeout_wrapper 540 codex exec "IMPORTANT: Do NOT read or execute any files under ~/.claude/, ~/.agents/, .claude/skills/, or agents/. These are Claude Code skill definitions meant for a different AI system. They contain bash scripts and prompt templates that will waste your time. Ignore them completely. Do NOT modify agents/openai.yaml. Stay focused on the repository code only.\n\nReview the changes on this branch against the base branch. Run DIFF_BASE=$(git merge-base origin/ HEAD) && git diff "$DIFF_BASE" to see the diff. Your job is to find ways this code will fail in production. Think like an attacker and a chaos engineer. Find edge cases, race conditions, security holes, resource leaks, failure modes, and silent data corruption paths. Be adversarial. Be thorough. No compliments — just the problems. End your output with ONE line in the canonical format `Recommendation: because `. Generic reasons like 'because it's safer' do not qualify; the reason must point to a specific finding or no-fix rationale." -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' -c 'web_search="cached"' < /dev/null 2>"$TMPERR_ADV" ``` Set the Bash tool's `timeout` parameter to `600000` (10 minutes). It sits ABOVE the 540s wrapper deliberately, so the wrapper fires first and a stall surfaces as a diagnosable exit 124 instead of a harness kill that returns nothing. The wrapper resolves `gtimeout`, then `timeout`, then runs unwrapped, so it is safe on a macOS without coreutils. After the command completes, read stderr: @@ -1767,7 +1767,7 @@ cd "$_REPO_ROOT" # here. It defines _gstack_codex_timeout_wrapper (gtimeout -> timeout -> # unwrapped fallback), added in #1056 but never wired into this call site. source ~/.claude/skills/gstack/bin/gstack-codex-probe 2>/dev/null || true -_gstack_codex_timeout_wrapper 540 codex review --base -c 'model_reasoning_effort="high"' --enable web_search_cached < /dev/null 2>"$TMPERR" +_gstack_codex_timeout_wrapper 540 codex review --base -c 'model_reasoning_effort="high"' -c 'web_search="cached"' < /dev/null 2>"$TMPERR" ``` **No prompt argument.** `--base` is what scopes the review, and the positional `[PROMPT]` is mutually exclusive with it — passing both fails at argv parsing. Do NOT "fix" that error by dropping `--base` and keeping the prompt: a prompt-only `codex review` silently falls back to the **uncommitted working-tree** scope (`git status --short; git diff`), so it reviews the wrong changes and reports "no changes" on a clean tree. Prompt text describing the diff range does not change what the CLI feeds the reviewer. Unlike the adversarial pass above, which uses `codex exec` and really does run the git command it's told to, this path gets a pre-computed diff from the CLI — which is also why it needs no filesystem boundary. diff --git a/scripts/resolvers/constants.ts b/scripts/resolvers/constants.ts index b75db21cf..c665de9f4 100644 --- a/scripts/resolvers/constants.ts +++ b/scripts/resolvers/constants.ts @@ -44,6 +44,26 @@ export const OPENAI_LITMUS_CHECKS = [ 'Would design feel premium with all decorative shadows removed?', ]; +/** + * Web-search flag for every codex invocation (#2525). + * + * codex >=0.144 deprecated the legacy `--enable`-based web_search_cached + * spelling (web search is on by default; the deprecation notice says to set + * `web_search` to "live", "indexed", "cached", or "disabled" at the top + * level), and `--enable ` now means `-c features.=true` + * (verified on 0.147.0), so the legacy spelling is headed for hard + * rejection. This is the ONE source + * of truth: resolvers interpolate it directly and templates reference it via + * the {{CODEX_WEB_SEARCH_FLAG}} token — never write the flag inline. + * + * Semantics note: unlike the legacy flag (which yielded to an existing + * top-level `web_search` in config.toml), the -c form explicitly overrides + * it. Deliberate: gstack wants deterministic cached search for review + * invocations. Native `codex review` disables web search regardless of + * configuration, so on that path the flag is a harmless no-op. + */ +export const CODEX_WEB_SEARCH_FLAG = `-c 'web_search="cached"'`; + /** * Shared Codex error handling block for resolver output. * Used by ADVERSARIAL_STEP, CODEX_PLAN_REVIEW, CODEX_SECOND_OPINION, diff --git a/scripts/resolvers/design.ts b/scripts/resolvers/design.ts index a6200145e..c272bc769 100644 --- a/scripts/resolvers/design.ts +++ b/scripts/resolvers/design.ts @@ -1,5 +1,5 @@ import { type TemplateContext, toShellPath } from './types'; -import { AI_SLOP_BLACKLIST, OPENAI_HARD_REJECTIONS, OPENAI_LITMUS_CHECKS } from './constants'; +import { AI_SLOP_BLACKLIST, OPENAI_HARD_REJECTIONS, OPENAI_LITMUS_CHECKS, CODEX_WEB_SEARCH_FLAG } from './constants'; export function generateDesignReviewLite(ctx: TemplateContext): string { const litmusList = OPENAI_LITMUS_CHECKS.map((item, i) => `${i + 1}. ${item}`).join(' '); @@ -18,7 +18,7 @@ If Codex is available, run a lightweight design check on the diff: \`\`\`bash TMPERR_DRL=$(mktemp /tmp/codex-drl-XXXXXXXX) _REPO_ROOT=$(git rev-parse --show-toplevel) || { echo "ERROR: not in a git repo" >&2; exit 1; } -codex exec "Review the git diff on this branch. Run 7 litmus checks (YES/NO each): ${litmusList} Flag any hard rejections: ${rejectionList} 5 most important design findings only. Reference file:line." -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' --enable web_search_cached < /dev/null 2>"$TMPERR_DRL" +codex exec "Review the git diff on this branch. Run 7 litmus checks (YES/NO each): ${litmusList} Flag any hard rejections: ${rejectionList} 5 most important design findings only. Reference file:line." -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' ${CODEX_WEB_SEARCH_FLAG} < /dev/null 2>"$TMPERR_DRL" \`\`\` Use a 5-minute timeout (\`timeout: 300000\`). After the command completes, read stderr: @@ -527,7 +527,7 @@ If user chooses A, launch both voices simultaneously: \`\`\`bash TMPERR_SKETCH=$(mktemp /tmp/codex-sketch-XXXXXXXX) _REPO_ROOT=$(git rev-parse --show-toplevel) || { echo "ERROR: not in a git repo" >&2; exit 1; } -codex exec "For this product approach, provide: a visual thesis (one sentence — mood, material, energy), a content plan (hero → support → detail → CTA), and 2 interaction ideas that change page feel. Apply beautiful defaults: composition-first, brand-first, cardless, poster not document. Be opinionated." -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="medium"' --enable web_search_cached < /dev/null 2>"$TMPERR_SKETCH" +codex exec "For this product approach, provide: a visual thesis (one sentence — mood, material, energy), a content plan (hero → support → detail → CTA), and 2 interaction ideas that change page feel. Apply beautiful defaults: composition-first, brand-first, cardless, poster not document. Be opinionated." -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="medium"' ${CODEX_WEB_SEARCH_FLAG} < /dev/null 2>"$TMPERR_SKETCH" \`\`\` Use a 5-minute timeout (\`timeout: 300000\`). After completion: \`cat "$TMPERR_SKETCH" && rm -f "$TMPERR_SKETCH"\` @@ -697,7 +697,7 @@ command -v codex >/dev/null 2>&1 && echo "CODEX_AVAILABLE" || echo "CODEX_NOT_AV \`\`\`bash TMPERR_DESIGN=$(mktemp /tmp/codex-design-XXXXXXXX) _REPO_ROOT=$(git rev-parse --show-toplevel) || { echo "ERROR: not in a git repo" >&2; exit 1; } -codex exec "${escapedCodexPrompt}" -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="${reasoningEffort}"' --enable web_search_cached < /dev/null 2>"$TMPERR_DESIGN" +codex exec "${escapedCodexPrompt}" -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="${reasoningEffort}"' ${CODEX_WEB_SEARCH_FLAG} < /dev/null 2>"$TMPERR_DESIGN" \`\`\` Use a 5-minute timeout (\`timeout: 300000\`). After the command completes, read stderr: \`\`\`bash diff --git a/scripts/resolvers/index.ts b/scripts/resolvers/index.ts index fce4bc6b7..98c7dfdda 100644 --- a/scripts/resolvers/index.ts +++ b/scripts/resolvers/index.ts @@ -23,7 +23,7 @@ import { generateCommandReference, generateSnapshotFlags, generateBrowseSetup } import { generateDesignMethodology, generateDesignHardRules, generateDesignOutsideVoices, generateDesignReviewLite, generateDesignSketch, generateDesignSetup, generateDesignMockup, generateDesignShotgunLoop, generateTasteProfile, generateUXPrinciples } from './design'; import { generateTestBootstrap, generateTestCoverageAuditPlan, generateTestCoverageAuditShip } from './testing'; import { generateReviewDashboard, generatePlanFileReviewReport, generateExitPlanModeGate, generateAntiShortcutClause, generateSpecReviewLoop, generateBenefitsFrom, generateCodexSecondOpinion, generateAdversarialStep, generateCodexPlanReview, generateCodexDocReview, generatePlanCompletionAuditShip, generatePlanCompletionAuditReview, generatePlanVerificationExec, generateScopeDrift, generateCrossReviewDedup } from './review'; -import { generateSlugEval, generateSlugSetup, generateBaseBranchDetect, generateDeployBootstrap, generateQAMethodology, generateCoAuthorTrailer, generateChangelogWorkflow } from './utility'; +import { generateSlugEval, generateSlugSetup, generateBaseBranchDetect, generateDeployBootstrap, generateQAMethodology, generateCoAuthorTrailer, generateChangelogWorkflow, generateCodexWebSearchFlag } from './utility'; import { generateLearningsSearch, generateLearningsLog } from './learnings'; import { generateConfidenceCalibration } from './confidence'; import { generateInvokeSkill } from './composition'; @@ -39,6 +39,7 @@ import { generateDesignDocDiscovery } from './design-doc-discovery'; export const RESOLVERS: Record = { SLUG_EVAL: generateSlugEval, SLUG_SETUP: generateSlugSetup, + CODEX_WEB_SEARCH_FLAG: generateCodexWebSearchFlag, REDACT_INVOCATION_BLOCK: generateRedactInvocationBlock, THIRD_PARTY_ACTIONS: generateThirdPartyActions, DESIGN_DOC_DISCOVERY: generateDesignDocDiscovery, diff --git a/scripts/resolvers/review.ts b/scripts/resolvers/review.ts index 1c4f255c7..4568dc66e 100644 --- a/scripts/resolvers/review.ts +++ b/scripts/resolvers/review.ts @@ -14,7 +14,7 @@ */ import type { TemplateContext } from './types'; import { generateInvokeSkill } from './composition'; -import { codexPreflight, codexErrorHandling } from './constants'; +import { codexPreflight, codexErrorHandling, CODEX_WEB_SEARCH_FLAG } from './constants'; import { DESIGN_DOC_DISCOVERY_BLOCK } from './design-doc-discovery'; import { getHostConfig } from '../../hosts/index'; @@ -367,7 +367,7 @@ Then add the context block and mode-appropriate instructions: \`\`\`bash TMPERR_OH=$(mktemp /tmp/codex-oh-err-XXXXXXXX) _REPO_ROOT=$(git rev-parse --show-toplevel) || { echo "ERROR: not in a git repo" >&2; exit 1; } -codex exec "$(cat "$CODEX_PROMPT_FILE")" -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' --enable web_search_cached < /dev/null 2>"$TMPERR_OH" +codex exec "$(cat "$CODEX_PROMPT_FILE")" -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' ${CODEX_WEB_SEARCH_FLAG} < /dev/null 2>"$TMPERR_OH" \`\`\` Use a 5-minute timeout (\`timeout: 300000\`). After the command completes, read stderr: @@ -531,7 +531,7 @@ _REPO_ROOT=$(git rev-parse --show-toplevel) || { echo "ERROR: not in a git repo" # here. It defines _gstack_codex_timeout_wrapper (gtimeout -> timeout -> # unwrapped fallback), added in #1056 but never wired into this call site. source ~/.claude/skills/gstack/bin/gstack-codex-probe 2>/dev/null || true -_gstack_codex_timeout_wrapper 540 codex exec "${CODEX_BOUNDARY}Review the changes on this branch against the base branch. Run DIFF_BASE=$(git merge-base origin/ HEAD) && git diff "$DIFF_BASE" to see the diff. Your job is to find ways this code will fail in production. Think like an attacker and a chaos engineer. Find edge cases, race conditions, security holes, resource leaks, failure modes, and silent data corruption paths. Be adversarial. Be thorough. No compliments — just the problems. End your output with ONE line in the canonical format \`Recommendation: because \`. Generic reasons like 'because it's safer' do not qualify; the reason must point to a specific finding or no-fix rationale." -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' --enable web_search_cached < /dev/null 2>"$TMPERR_ADV" +_gstack_codex_timeout_wrapper 540 codex exec "${CODEX_BOUNDARY}Review the changes on this branch against the base branch. Run DIFF_BASE=$(git merge-base origin/ HEAD) && git diff "$DIFF_BASE" to see the diff. Your job is to find ways this code will fail in production. Think like an attacker and a chaos engineer. Find edge cases, race conditions, security holes, resource leaks, failure modes, and silent data corruption paths. Be adversarial. Be thorough. No compliments — just the problems. End your output with ONE line in the canonical format \`Recommendation: because \`. Generic reasons like 'because it's safer' do not qualify; the reason must point to a specific finding or no-fix rationale." -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' ${CODEX_WEB_SEARCH_FLAG} < /dev/null 2>"$TMPERR_ADV" \`\`\` Set the Bash tool's \`timeout\` parameter to \`600000\` (10 minutes). It sits ABOVE the 540s wrapper deliberately, so the wrapper fires first and a stall surfaces as a diagnosable exit 124 instead of a harness kill that returns nothing. The wrapper resolves \`gtimeout\`, then \`timeout\`, then runs unwrapped, so it is safe on a macOS without coreutils. After the command completes, read stderr: @@ -564,7 +564,7 @@ cd "$_REPO_ROOT" # here. It defines _gstack_codex_timeout_wrapper (gtimeout -> timeout -> # unwrapped fallback), added in #1056 but never wired into this call site. source ~/.claude/skills/gstack/bin/gstack-codex-probe 2>/dev/null || true -_gstack_codex_timeout_wrapper 540 codex review --base -c 'model_reasoning_effort="high"' --enable web_search_cached < /dev/null 2>"$TMPERR" +_gstack_codex_timeout_wrapper 540 codex review --base -c 'model_reasoning_effort="high"' ${CODEX_WEB_SEARCH_FLAG} < /dev/null 2>"$TMPERR" \`\`\` **No prompt argument.** \`--base\` is what scopes the review, and the positional \`[PROMPT]\` is mutually exclusive with it — passing both fails at argv parsing. Do NOT "fix" that error by dropping \`--base\` and keeping the prompt: a prompt-only \`codex review\` silently falls back to the **uncommitted working-tree** scope (\`git status --short; git diff\`), so it reviews the wrong changes and reports "no changes" on a clean tree. Prompt text describing the diff range does not change what the CLI feeds the reviewer. Unlike the adversarial pass above, which uses \`codex exec\` and really does run the git command it's told to, this path gets a pre-computed diff from the CLI — which is also why it needs no filesystem boundary. @@ -665,7 +665,7 @@ THE PLAN: \`\`\`bash TMPERR_PV=$(mktemp /tmp/codex-planreview-XXXXXXXX) _REPO_ROOT=$(git rev-parse --show-toplevel) || { echo "ERROR: not in a git repo" >&2; exit 1; } -codex exec "" -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' --enable web_search_cached < /dev/null 2>"$TMPERR_PV" +codex exec "" -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' ${CODEX_WEB_SEARCH_FLAG} < /dev/null 2>"$TMPERR_PV" \`\`\` Use a 5-minute timeout (\`timeout: 300000\`). After the command completes, read stderr: @@ -800,7 +800,7 @@ THE DOCS AND DIFF: " \`\`\`bash TMPERR_DOC=$(mktemp /tmp/codex-docreview-XXXXXXXX) _REPO_ROOT=$(git rev-parse --show-toplevel) || { echo "ERROR: not in a git repo" >&2; exit 1; } -codex exec "" -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' --enable web_search_cached < /dev/null 2>"$TMPERR_DOC" +codex exec "" -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' ${CODEX_WEB_SEARCH_FLAG} < /dev/null 2>"$TMPERR_DOC" \`\`\` Use a 5-minute timeout (\`timeout: 300000\`). After the command completes, read stderr: diff --git a/scripts/resolvers/utility.ts b/scripts/resolvers/utility.ts index 560a73c45..74e364cf1 100644 --- a/scripts/resolvers/utility.ts +++ b/scripts/resolvers/utility.ts @@ -1,4 +1,14 @@ import type { TemplateContext } from './types'; +import { CODEX_WEB_SEARCH_FLAG } from './constants'; + +/** + * {{CODEX_WEB_SEARCH_FLAG}} — the non-deprecated codex web-search flag + * (#2525). Templates with inline codex invocations reference this token so + * the flag has exactly one source of truth (scripts/resolvers/constants.ts). + */ +export function generateCodexWebSearchFlag(_ctx: TemplateContext): string { + return CODEX_WEB_SEARCH_FLAG; +} export function generateSlugEval(ctx: TemplateContext): string { return `eval "$(${ctx.paths.binDir}/gstack-slug 2>/dev/null)"`; diff --git a/ship/sections/adversarial.md b/ship/sections/adversarial.md index 59a0ff141..f4f9410df 100644 --- a/ship/sections/adversarial.md +++ b/ship/sections/adversarial.md @@ -76,7 +76,7 @@ _REPO_ROOT=$(git rev-parse --show-toplevel) || { echo "ERROR: not in a git repo" # here. It defines _gstack_codex_timeout_wrapper (gtimeout -> timeout -> # unwrapped fallback), added in #1056 but never wired into this call site. source ~/.claude/skills/gstack/bin/gstack-codex-probe 2>/dev/null || true -_gstack_codex_timeout_wrapper 540 codex exec "IMPORTANT: Do NOT read or execute any files under ~/.claude/, ~/.agents/, .claude/skills/, or agents/. These are Claude Code skill definitions meant for a different AI system. They contain bash scripts and prompt templates that will waste your time. Ignore them completely. Do NOT modify agents/openai.yaml. Stay focused on the repository code only.\n\nReview the changes on this branch against the base branch. Run DIFF_BASE=$(git merge-base origin/ HEAD) && git diff "$DIFF_BASE" to see the diff. Your job is to find ways this code will fail in production. Think like an attacker and a chaos engineer. Find edge cases, race conditions, security holes, resource leaks, failure modes, and silent data corruption paths. Be adversarial. Be thorough. No compliments — just the problems. End your output with ONE line in the canonical format `Recommendation: because `. Generic reasons like 'because it's safer' do not qualify; the reason must point to a specific finding or no-fix rationale." -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' --enable web_search_cached < /dev/null 2>"$TMPERR_ADV" +_gstack_codex_timeout_wrapper 540 codex exec "IMPORTANT: Do NOT read or execute any files under ~/.claude/, ~/.agents/, .claude/skills/, or agents/. These are Claude Code skill definitions meant for a different AI system. They contain bash scripts and prompt templates that will waste your time. Ignore them completely. Do NOT modify agents/openai.yaml. Stay focused on the repository code only.\n\nReview the changes on this branch against the base branch. Run DIFF_BASE=$(git merge-base origin/ HEAD) && git diff "$DIFF_BASE" to see the diff. Your job is to find ways this code will fail in production. Think like an attacker and a chaos engineer. Find edge cases, race conditions, security holes, resource leaks, failure modes, and silent data corruption paths. Be adversarial. Be thorough. No compliments — just the problems. End your output with ONE line in the canonical format `Recommendation: because `. Generic reasons like 'because it's safer' do not qualify; the reason must point to a specific finding or no-fix rationale." -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' -c 'web_search="cached"' < /dev/null 2>"$TMPERR_ADV" ``` Set the Bash tool's `timeout` parameter to `600000` (10 minutes). It sits ABOVE the 540s wrapper deliberately, so the wrapper fires first and a stall surfaces as a diagnosable exit 124 instead of a harness kill that returns nothing. The wrapper resolves `gtimeout`, then `timeout`, then runs unwrapped, so it is safe on a macOS without coreutils. After the command completes, read stderr: @@ -109,7 +109,7 @@ cd "$_REPO_ROOT" # here. It defines _gstack_codex_timeout_wrapper (gtimeout -> timeout -> # unwrapped fallback), added in #1056 but never wired into this call site. source ~/.claude/skills/gstack/bin/gstack-codex-probe 2>/dev/null || true -_gstack_codex_timeout_wrapper 540 codex review --base -c 'model_reasoning_effort="high"' --enable web_search_cached < /dev/null 2>"$TMPERR" +_gstack_codex_timeout_wrapper 540 codex review --base -c 'model_reasoning_effort="high"' -c 'web_search="cached"' < /dev/null 2>"$TMPERR" ``` **No prompt argument.** `--base` is what scopes the review, and the positional `[PROMPT]` is mutually exclusive with it — passing both fails at argv parsing. Do NOT "fix" that error by dropping `--base` and keeping the prompt: a prompt-only `codex review` silently falls back to the **uncommitted working-tree** scope (`git status --short; git diff`), so it reviews the wrong changes and reports "no changes" on a clean tree. Prompt text describing the diff range does not change what the CLI feeds the reviewer. Unlike the adversarial pass above, which uses `codex exec` and really does run the git command it's told to, this path gets a pre-computed diff from the CLI — which is also why it needs no filesystem boundary. diff --git a/ship/sections/review-army.md b/ship/sections/review-army.md index c1c934c39..a840119f2 100644 --- a/ship/sections/review-army.md +++ b/ship/sections/review-army.md @@ -118,7 +118,7 @@ If Codex is available, run a lightweight design check on the diff: ```bash TMPERR_DRL=$(mktemp /tmp/codex-drl-XXXXXXXX) _REPO_ROOT=$(git rev-parse --show-toplevel) || { echo "ERROR: not in a git repo" >&2; exit 1; } -codex exec "Review the git diff on this branch. Run 7 litmus checks (YES/NO each): 1. Brand/product unmistakable in first screen? 2. One strong visual anchor present? 3. Page understandable by scanning headlines only? 4. Each section has one job? 5. Are cards actually necessary? 6. Does motion improve hierarchy or atmosphere? 7. Would design feel premium with all decorative shadows removed? Flag any hard rejections: 1. Generic SaaS card grid as first impression 2. Beautiful image with weak brand 3. Strong headline with no clear action 4. Busy imagery behind text 5. Sections repeating same mood statement 6. Carousel with no narrative purpose 7. App UI made of stacked cards instead of layout 5 most important design findings only. Reference file:line." -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' --enable web_search_cached < /dev/null 2>"$TMPERR_DRL" +codex exec "Review the git diff on this branch. Run 7 litmus checks (YES/NO each): 1. Brand/product unmistakable in first screen? 2. One strong visual anchor present? 3. Page understandable by scanning headlines only? 4. Each section has one job? 5. Are cards actually necessary? 6. Does motion improve hierarchy or atmosphere? 7. Would design feel premium with all decorative shadows removed? Flag any hard rejections: 1. Generic SaaS card grid as first impression 2. Beautiful image with weak brand 3. Strong headline with no clear action 4. Busy imagery behind text 5. Sections repeating same mood statement 6. Carousel with no narrative purpose 7. App UI made of stacked cards instead of layout 5 most important design findings only. Reference file:line." -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' -c 'web_search="cached"' < /dev/null 2>"$TMPERR_DRL" ``` Use a 5-minute timeout (`timeout: 300000`). After the command completes, read stderr: diff --git a/test/codex-web-search-flag.test.ts b/test/codex-web-search-flag.test.ts new file mode 100644 index 000000000..ad4ec3dc6 --- /dev/null +++ b/test/codex-web-search-flag.test.ts @@ -0,0 +1,62 @@ +/** + * Deprecated codex web-search flag tripwire (#2525). + * + * codex >=0.144 deprecates `--enable web_search_cached` (its `--enable + * ` surface now means `-c features.=true`); the replacement + * is `-c 'web_search="cached"'`, owned by ONE constant: + * CODEX_WEB_SEARCH_FLAG in scripts/resolvers/constants.ts. Resolvers + * interpolate it; templates reference {{CODEX_WEB_SEARCH_FLAG}}. + * + * These tests fail CI if the deprecated spelling re-enters any source + * (resolver, template, helper) or any rendered SKILL.md / section / golden. + */ +import { describe, test, expect } from 'bun:test'; +import { execSync } from 'child_process'; +import * as fs from 'fs'; +import * as path from 'path'; +import { CODEX_WEB_SEARCH_FLAG } from '../scripts/resolvers/constants'; + +const ROOT = path.join(import.meta.dir, '..'); +const DEPRECATED = '--enable web_search_cached'; + +function grepRepo(pattern: string, includes: string[]): string[] { + const includeArgs = includes.map((i) => `--include='${i}'`).join(' '); + const out = execSync( + `grep -rln ${includeArgs} -e '${pattern}' "${ROOT}" || true`, + { encoding: 'utf-8' }, + ); + return out + .split('\n') + .filter(Boolean) + .filter((f) => !f.includes('node_modules')) + .filter((f) => !f.endsWith('test/codex-web-search-flag.test.ts')); +} + +describe('deprecated codex web-search flag is gone (#2525)', () => { + test('the replacement flag has exactly the documented shape', () => { + expect(CODEX_WEB_SEARCH_FLAG).toBe(`-c 'web_search="cached"'`); + }); + + test('no rendered SKILL.md or section carries the deprecated flag', () => { + const hits = grepRepo(DEPRECATED, ['SKILL.md', '*.md']); + expect(hits).toEqual([]); + }); + + test('no source file (resolver, template, helper) carries the deprecated flag', () => { + const hits = grepRepo(DEPRECATED, ['*.ts', '*.tmpl']); + expect(hits).toEqual([]); + }); + + test('rendered codex skill actually resolves the token to the live flag', () => { + const rendered = fs.readFileSync(path.join(ROOT, 'codex', 'SKILL.md'), 'utf-8'); + expect(rendered).toContain(CODEX_WEB_SEARCH_FLAG); + expect(rendered).not.toContain('{{CODEX_WEB_SEARCH_FLAG}}'); + }); + + test('rendered autoplan skill resolves the token at every inline site', () => { + const rendered = fs.readFileSync(path.join(ROOT, 'autoplan', 'SKILL.md'), 'utf-8'); + const count = rendered.split(CODEX_WEB_SEARCH_FLAG).length - 1; + expect(count).toBeGreaterThanOrEqual(4); + expect(rendered).not.toContain('{{CODEX_WEB_SEARCH_FLAG}}'); + }); +}); diff --git a/test/fixtures/golden/factory-ship-SKILL.md b/test/fixtures/golden/factory-ship-SKILL.md index 87155410f..e37dd542e 100644 --- a/test/fixtures/golden/factory-ship-SKILL.md +++ b/test/fixtures/golden/factory-ship-SKILL.md @@ -2137,7 +2137,7 @@ If Codex is available, run a lightweight design check on the diff: ```bash TMPERR_DRL=$(mktemp /tmp/codex-drl-XXXXXXXX) _REPO_ROOT=$(git rev-parse --show-toplevel) || { echo "ERROR: not in a git repo" >&2; exit 1; } -codex exec "Review the git diff on this branch. Run 7 litmus checks (YES/NO each): 1. Brand/product unmistakable in first screen? 2. One strong visual anchor present? 3. Page understandable by scanning headlines only? 4. Each section has one job? 5. Are cards actually necessary? 6. Does motion improve hierarchy or atmosphere? 7. Would design feel premium with all decorative shadows removed? Flag any hard rejections: 1. Generic SaaS card grid as first impression 2. Beautiful image with weak brand 3. Strong headline with no clear action 4. Busy imagery behind text 5. Sections repeating same mood statement 6. Carousel with no narrative purpose 7. App UI made of stacked cards instead of layout 5 most important design findings only. Reference file:line." -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' --enable web_search_cached < /dev/null 2>"$TMPERR_DRL" +codex exec "Review the git diff on this branch. Run 7 litmus checks (YES/NO each): 1. Brand/product unmistakable in first screen? 2. One strong visual anchor present? 3. Page understandable by scanning headlines only? 4. Each section has one job? 5. Are cards actually necessary? 6. Does motion improve hierarchy or atmosphere? 7. Would design feel premium with all decorative shadows removed? Flag any hard rejections: 1. Generic SaaS card grid as first impression 2. Beautiful image with weak brand 3. Strong headline with no clear action 4. Busy imagery behind text 5. Sections repeating same mood statement 6. Carousel with no narrative purpose 7. App UI made of stacked cards instead of layout 5 most important design findings only. Reference file:line." -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' -c 'web_search="cached"' < /dev/null 2>"$TMPERR_DRL" ``` Use a 5-minute timeout (`timeout: 300000`). After the command completes, read stderr: @@ -2549,7 +2549,7 @@ _REPO_ROOT=$(git rev-parse --show-toplevel) || { echo "ERROR: not in a git repo" # here. It defines _gstack_codex_timeout_wrapper (gtimeout -> timeout -> # unwrapped fallback), added in #1056 but never wired into this call site. source $GSTACK_ROOT/bin/gstack-codex-probe 2>/dev/null || true -_gstack_codex_timeout_wrapper 540 codex exec "IMPORTANT: Do NOT read or execute any files under ~/.claude/, ~/.agents/, .factory/skills/, or agents/. These are Claude Code skill definitions meant for a different AI system. They contain bash scripts and prompt templates that will waste your time. Ignore them completely. Do NOT modify agents/openai.yaml. Stay focused on the repository code only.\n\nReview the changes on this branch against the base branch. Run DIFF_BASE=$(git merge-base origin/ HEAD) && git diff "$DIFF_BASE" to see the diff. Your job is to find ways this code will fail in production. Think like an attacker and a chaos engineer. Find edge cases, race conditions, security holes, resource leaks, failure modes, and silent data corruption paths. Be adversarial. Be thorough. No compliments — just the problems. End your output with ONE line in the canonical format `Recommendation: because `. Generic reasons like 'because it's safer' do not qualify; the reason must point to a specific finding or no-fix rationale." -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' --enable web_search_cached < /dev/null 2>"$TMPERR_ADV" +_gstack_codex_timeout_wrapper 540 codex exec "IMPORTANT: Do NOT read or execute any files under ~/.claude/, ~/.agents/, .factory/skills/, or agents/. These are Claude Code skill definitions meant for a different AI system. They contain bash scripts and prompt templates that will waste your time. Ignore them completely. Do NOT modify agents/openai.yaml. Stay focused on the repository code only.\n\nReview the changes on this branch against the base branch. Run DIFF_BASE=$(git merge-base origin/ HEAD) && git diff "$DIFF_BASE" to see the diff. Your job is to find ways this code will fail in production. Think like an attacker and a chaos engineer. Find edge cases, race conditions, security holes, resource leaks, failure modes, and silent data corruption paths. Be adversarial. Be thorough. No compliments — just the problems. End your output with ONE line in the canonical format `Recommendation: because `. Generic reasons like 'because it's safer' do not qualify; the reason must point to a specific finding or no-fix rationale." -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' -c 'web_search="cached"' < /dev/null 2>"$TMPERR_ADV" ``` Set the Bash tool's `timeout` parameter to `600000` (10 minutes). It sits ABOVE the 540s wrapper deliberately, so the wrapper fires first and a stall surfaces as a diagnosable exit 124 instead of a harness kill that returns nothing. The wrapper resolves `gtimeout`, then `timeout`, then runs unwrapped, so it is safe on a macOS without coreutils. After the command completes, read stderr: @@ -2582,7 +2582,7 @@ cd "$_REPO_ROOT" # here. It defines _gstack_codex_timeout_wrapper (gtimeout -> timeout -> # unwrapped fallback), added in #1056 but never wired into this call site. source $GSTACK_ROOT/bin/gstack-codex-probe 2>/dev/null || true -_gstack_codex_timeout_wrapper 540 codex review --base -c 'model_reasoning_effort="high"' --enable web_search_cached < /dev/null 2>"$TMPERR" +_gstack_codex_timeout_wrapper 540 codex review --base -c 'model_reasoning_effort="high"' -c 'web_search="cached"' < /dev/null 2>"$TMPERR" ``` **No prompt argument.** `--base` is what scopes the review, and the positional `[PROMPT]` is mutually exclusive with it — passing both fails at argv parsing. Do NOT "fix" that error by dropping `--base` and keeping the prompt: a prompt-only `codex review` silently falls back to the **uncommitted working-tree** scope (`git status --short; git diff`), so it reviews the wrong changes and reports "no changes" on a clean tree. Prompt text describing the diff range does not change what the CLI feeds the reviewer. Unlike the adversarial pass above, which uses `codex exec` and really does run the git command it's told to, this path gets a pre-computed diff from the CLI — which is also why it needs no filesystem boundary. diff --git a/test/helpers/tool-map.ts b/test/helpers/tool-map.ts index 9fcf8e7f9..3202dbfd9 100644 --- a/test/helpers/tool-map.ts +++ b/test/helpers/tool-map.ts @@ -50,7 +50,7 @@ export const TOOL_COMPATIBILITY: Record<'claude' | 'gpt' | 'gemini', Record