diff --git a/autoplan/SKILL.md b/autoplan/SKILL.md index bc01c1121..94168c031 100644 --- a/autoplan/SKILL.md +++ b/autoplan/SKILL.md @@ -825,15 +825,12 @@ echo "CODEX_MODE: $_CODEX_MODE" Branch on the echoed `CODEX_MODE`: - **`disabled`** — the user turned Codex reviews off (`codex_reviews=disabled`). Skip the Codex passes only; the Claude adversarial subagent below STILL runs (it is free and fast). Print: "Codex passes skipped (codex_reviews disabled) — running Claude adversarial only." - **`not_installed`** — Codex CLI absent. Print: "Codex not installed — falling back to a Claude subagent (fresh context, but the same harness; model identity is unknown). Install Codex for an actual outside-model read: `npm install -g @openai/codex`." Fall back to the Claude subagent path. -- **`under_codex`** — stale artifact selected its own harness. Print: "Codex outside review unavailable: harness mismatch; no outside process started. Missing coverage. Repair: setup --host codex." Skip the outside invocation; retain the section's native pass if defined. Conflicting inherited harness markers are not grounds to guess another provider. +- **`under_codex`** — stale artifact selected its own harness. Print: "Codex outside review unavailable: harness mismatch; no outside process started. Missing coverage. Repair: setup --host codex." Skip the outside invocation and follow the workflow's native-review instructions below. Conflicting inherited harness markers are not grounds to guess another provider. - **`not_authed`** — installed but no credentials. Print: "Codex installed but not authenticated — falling back to a Claude subagent (same harness; model identity is unknown). Run `codex login` or set `$CODEX_API_KEY`." Fall back to the Claude subagent path. - **`broken_install`** — the CLI is on PATH but cannot execute (spawn ENOENT, non-executable binary, missing vendor payload). Print: "Codex is installed but its binary cannot run — Codex passes skipped. Reinstall: `npm install -g @openai/codex`." Relay the probe's HINT lines and fall back to the Claude subagent path. This state exists because a missing binary used to land in the model probe's fail-open bucket and report `ready`, so every Codex pass was skipped silently (#2742). - **`model_unusable`** — authed but the account cannot use gstack's selected Codex model (#2477: HTTP 400 on every call). Relay the probe's HINT lines, tell the user the one-line fix (set `GSTACK_CODEX_MODEL=` or pass an explicit `-c model=...` override), and fall back to the Claude subagent path. The ~10s round trip is cached for 1h; timeouts fail open to `ready`. - **`ready`** — run the Codex pass below. -A stale artifact selecting its own harness must report missing coverage and run no outside CLI. Repair: `setup --host codex`. Never infer a replacement provider from inherited environment markers. The invocation below repeats this guard. - - Disabled/unavailable: retain each applicable native pass. Recheck before each outside dispatch. Track provider and completed/unavailable/disabled/skipped per phase; CEO completion covers only CEO. Missing voices: N/A, never CONFIRMED. Skipped scope stays skipped. diff --git a/codex/SKILL.md b/codex/SKILL.md index 176014f20..8ec401baa 100644 --- a/codex/SKILL.md +++ b/codex/SKILL.md @@ -779,16 +779,16 @@ missing work — do NOT call ExitPlanMode: does NOT count — only the structured `## GSTACK REVIEW REPORT` section satisfies this check. 3. Confirm the report has a Runs / Status / Findings table and a VERDICT line - (CODEX / CROSS-MODEL absorbed if applicable). + (OUTSIDE COVERAGE / CROSS-MODEL included when applicable). 4. Confirm the report's FINAL non-whitespace line is the unresolved-decisions status: the exact unbolded `NO UNRESOLVED DECISIONS`, or a bullet of a final `**UNRESOLVED DECISIONS:**` block. BLOCKING, no "if applicable" escape — a - bolded sentinel, any trailing CODEX/CROSS-MODEL/VERDICT/prose, or a missing + bolded sentinel, any trailing report field or prose, or a missing status each FAILS the gate. 5. If a plan file is in context for this skill invocation: confirm `gstack-review-log` was called and `gstack-review-read` was run at least - once. If no plan file is in context (e.g. `/codex consult` against a - diff with no plan), this check short-circuits — checks 1-4 already + once. If no plan file is in context (e.g. a diff review with no plan), + this check short-circuits — checks 1-4 already short-circuit when no plan file exists. Failing this gate and calling ExitPlanMode anyway is a contract violation — diff --git a/document-release/sections/release-body.md b/document-release/sections/release-body.md index 14436ab8b..281c148df 100644 --- a/document-release/sections/release-body.md +++ b/document-release/sections/release-body.md @@ -236,15 +236,12 @@ echo "CODEX_MODE: $_CODEX_MODE" Branch on the echoed `CODEX_MODE`: - **`disabled`** — the user turned Codex reviews off (`codex_reviews=disabled`). Skip this section entirely; do NOT fall back to a Claude subagent — disabled means no extra review step. Print: "Codex review skipped (codex_reviews disabled). Re-enable: `gstack-config set codex_reviews enabled`." - **`not_installed`** — Codex CLI absent. Print: "Codex not installed — falling back to a Claude subagent (fresh context, but the same harness; model identity is unknown). Install Codex for an actual outside-model read: `npm install -g @openai/codex`." Fall back to the Claude subagent path. -- **`under_codex`** — stale artifact selected its own harness. Print: "Codex outside review unavailable: harness mismatch; no outside process started. Missing coverage. Repair: setup --host codex." Skip the outside invocation; retain the section's native pass if defined. Conflicting inherited harness markers are not grounds to guess another provider. +- **`under_codex`** — stale artifact selected its own harness. Print: "Codex outside review unavailable: harness mismatch; no outside process started. Missing coverage. Repair: setup --host codex." Skip the outside invocation and follow the workflow's native-review instructions below. Conflicting inherited harness markers are not grounds to guess another provider. - **`not_authed`** — installed but no credentials. Print: "Codex installed but not authenticated — falling back to a Claude subagent (same harness; model identity is unknown). Run `codex login` or set `$CODEX_API_KEY`." Fall back to the Claude subagent path. - **`broken_install`** — the CLI is on PATH but cannot execute (spawn ENOENT, non-executable binary, missing vendor payload). Print: "Codex is installed but its binary cannot run — Codex passes skipped. Reinstall: `npm install -g @openai/codex`." Relay the probe's HINT lines and fall back to the Claude subagent path. This state exists because a missing binary used to land in the model probe's fail-open bucket and report `ready`, so every Codex pass was skipped silently (#2742). - **`model_unusable`** — authed but the account cannot use gstack's selected Codex model (#2477: HTTP 400 on every call). Relay the probe's HINT lines, tell the user the one-line fix (set `GSTACK_CODEX_MODEL=` or pass an explicit `-c model=...` override), and fall back to the Claude subagent path. The ~10s round trip is cached for 1h; timeouts fail open to `ready`. - **`ready`** — run the Codex pass below. -A stale artifact selecting its own harness must report missing coverage and run no outside CLI. Repair: `setup --host codex`. Never infer a replacement provider from inherited environment markers. The invocation below repeats this guard. - - **Disabled is a terminal branch for this section.** If the preflight prints `CODEX_MODE: disabled`, persist `outside_status: disabled` with the guarded command below, then continue to Step 9. Do not construct a review prompt, invoke an outside CLI, @@ -346,10 +343,10 @@ Immediately before dispatching, check the preflight result again. On `CODEX_MODE: disabled`, finish this section with `outside_status: disabled`; do not dispatch. Otherwise, use this fallback for missing/broken CLI, failed authentication/model selection, a failed preflight, or a failed outside invocation. -The disabled branch never reaches this fallback. In this section, `under_codex` -or `under_current_harness` also follows this native fallback: run no outside CLI, -report the setup repair and `outside_status: unavailable`, then use the native -subagent below. A native result never supplies outside coverage. +The disabled branch never reaches this fallback. +On `CODEX_MODE: under_codex`, report the setup repair and +`outside_status: unavailable`, run no outside CLI, and use the native subagent below. +A native result never supplies outside coverage. Dispatch via the Agent tool with the same prompt, passing `run_in_background: false` (subagents default to background since Claude Code v2.1.198). Bound it at a 5-minute timeout; if it never completes, treat the review as unavailable and continue. Present findings under `DOCUMENTATION REVIEW (Claude subagent):`. If it fails: "Doc review unavailable. Continuing to Step 9." Skip the apply gate, persist `status: unavailable`, `outside_status: unavailable`, and `source: none` below, then continue; unavailable is not a clean review. diff --git a/office-hours/sections/design-and-handoff.md b/office-hours/sections/design-and-handoff.md index 9721262b8..22914a656 100644 --- a/office-hours/sections/design-and-handoff.md +++ b/office-hours/sections/design-and-handoff.md @@ -166,7 +166,8 @@ Supersedes: {prior filename — omit this line if first design on this branch} ## Spec Review Loop -Before presenting the document to the user for approval, run an adversarial review. +Run an adversarial review before presenting the final document to the user. +Follow the calling workflow's approval steps. **Step 1: Dispatch reviewer subagent** diff --git a/plan-ceo-review/SKILL.md b/plan-ceo-review/SKILL.md index ff3c9fcb1..dd5a74328 100644 --- a/plan-ceo-review/SKILL.md +++ b/plan-ceo-review/SKILL.md @@ -932,7 +932,7 @@ Present these approach options via AskUserQuestion using the preamble's AskUserQ ### 0F. Mode Selection After 0C-bis, before 0D; keep labels stable. -Every mode requires your explicit approval for added scope. +Every mode requires explicit user approval for scope changes. The four modes are: 1. **SCOPE EXPANSION:** The plan is good but could be great. Dream big — propose the ambitious version. Every expansion is presented individually for your approval. You opt in to each one. @@ -994,8 +994,8 @@ Both are outcome-framed. Only one makes the user feel the cathedral. Lead with t 3. Keep stated invariants and acceptance criteria; repairs needed to meet them are in scope. **For SCOPE REDUCTION** — run this: -1. Ruthless cut: What is the absolute minimum that ships value to a user? Everything else is deferred. No exceptions. -2. What can be a follow-up PR? Separate "must ship together" from "nice to ship together." +1. Propose minimum scope for the core goal and work to defer. +2. Explain each cut via AskUserQuestion; **STOP** for approval. Put approved cuts in "NOT in scope" and retain the rest. ### 0D-POST. Persist CEO Plan (EXPANSION and SELECTIVE EXPANSION only) @@ -1050,7 +1050,8 @@ After writing the CEO plan, run the spec review loop on it: ## Spec Review Loop -Before presenting the document to the user for approval, run an adversarial review. +Run an adversarial review before presenting the final document to the user. +Follow the calling workflow's approval steps. **Step 1: Dispatch reviewer subagent** @@ -1157,16 +1158,16 @@ missing work — do NOT call ExitPlanMode: does NOT count — only the structured `## GSTACK REVIEW REPORT` section satisfies this check. 3. Confirm the report has a Runs / Status / Findings table and a VERDICT line - (CODEX / CROSS-MODEL absorbed if applicable). + (OUTSIDE COVERAGE / CROSS-MODEL included when applicable). 4. Confirm the report's FINAL non-whitespace line is the unresolved-decisions status: the exact unbolded `NO UNRESOLVED DECISIONS`, or a bullet of a final `**UNRESOLVED DECISIONS:**` block. BLOCKING, no "if applicable" escape — a - bolded sentinel, any trailing CODEX/CROSS-MODEL/VERDICT/prose, or a missing + bolded sentinel, any trailing report field or prose, or a missing status each FAILS the gate. 5. If a plan file is in context for this skill invocation: confirm `gstack-review-log` was called and `gstack-review-read` was run at least - once. If no plan file is in context (e.g. `/codex consult` against a - diff with no plan), this check short-circuits — checks 1-4 already + once. If no plan file is in context (e.g. a diff review with no plan), + this check short-circuits — checks 1-4 already short-circuit when no plan file exists. Failing this gate and calling ExitPlanMode anyway is a contract violation — diff --git a/plan-ceo-review/SKILL.md.tmpl b/plan-ceo-review/SKILL.md.tmpl index 7bc153865..7335e4d43 100644 --- a/plan-ceo-review/SKILL.md.tmpl +++ b/plan-ceo-review/SKILL.md.tmpl @@ -290,7 +290,7 @@ Present these approach options via AskUserQuestion using the preamble's AskUserQ ### 0F. Mode Selection After 0C-bis, before 0D; keep labels stable. -Every mode requires your explicit approval for added scope. +Every mode requires explicit user approval for scope changes. The four modes are: 1. **SCOPE EXPANSION:** The plan is good but could be great. Dream big — propose the ambitious version. Every expansion is presented individually for your approval. You opt in to each one. @@ -352,8 +352,8 @@ Both are outcome-framed. Only one makes the user feel the cathedral. Lead with t 3. Keep stated invariants and acceptance criteria; repairs needed to meet them are in scope. **For SCOPE REDUCTION** — run this: -1. Ruthless cut: What is the absolute minimum that ships value to a user? Everything else is deferred. No exceptions. -2. What can be a follow-up PR? Separate "must ship together" from "nice to ship together." +1. Propose minimum scope for the core goal and work to defer. +2. Explain each cut via AskUserQuestion; **STOP** for approval. Put approved cuts in "NOT in scope" and retain the rest. ### 0D-POST. Persist CEO Plan (EXPANSION and SELECTIVE EXPANSION only) diff --git a/plan-ceo-review/sections/review-sections.md b/plan-ceo-review/sections/review-sections.md index c1f52c8b5..4a806e96a 100644 --- a/plan-ceo-review/sections/review-sections.md +++ b/plan-ceo-review/sections/review-sections.md @@ -362,15 +362,12 @@ echo "CODEX_MODE: $_CODEX_MODE" Branch on the echoed `CODEX_MODE`: - **`disabled`** — the user turned Codex reviews off (`codex_reviews=disabled`). Skip this section entirely; do NOT fall back to a Claude subagent — disabled means no extra review step. Print: "Codex review skipped (codex_reviews disabled). Re-enable: `gstack-config set codex_reviews enabled`." - **`not_installed`** — Codex CLI absent. Print: "Codex not installed — falling back to a Claude subagent (fresh context, but the same harness; model identity is unknown). Install Codex for an actual outside-model read: `npm install -g @openai/codex`." Fall back to the Claude subagent path. -- **`under_codex`** — stale artifact selected its own harness. Print: "Codex outside review unavailable: harness mismatch; no outside process started. Missing coverage. Repair: setup --host codex." Skip the outside invocation; retain the section's native pass if defined. Conflicting inherited harness markers are not grounds to guess another provider. +- **`under_codex`** — stale artifact selected its own harness. Print: "Codex outside review unavailable: harness mismatch; no outside process started. Missing coverage. Repair: setup --host codex." Skip the outside invocation and follow the workflow's native-review instructions below. Conflicting inherited harness markers are not grounds to guess another provider. - **`not_authed`** — installed but no credentials. Print: "Codex installed but not authenticated — falling back to a Claude subagent (same harness; model identity is unknown). Run `codex login` or set `$CODEX_API_KEY`." Fall back to the Claude subagent path. - **`broken_install`** — the CLI is on PATH but cannot execute (spawn ENOENT, non-executable binary, missing vendor payload). Print: "Codex is installed but its binary cannot run — Codex passes skipped. Reinstall: `npm install -g @openai/codex`." Relay the probe's HINT lines and fall back to the Claude subagent path. This state exists because a missing binary used to land in the model probe's fail-open bucket and report `ready`, so every Codex pass was skipped silently (#2742). - **`model_unusable`** — authed but the account cannot use gstack's selected Codex model (#2477: HTTP 400 on every call). Relay the probe's HINT lines, tell the user the one-line fix (set `GSTACK_CODEX_MODEL=` or pass an explicit `-c model=...` override), and fall back to the Claude subagent path. The ~10s round trip is cached for 1h; timeouts fail open to `ready`. - **`ready`** — run the Codex pass below. -A stale artifact selecting its own harness must report missing coverage and run no outside CLI. Repair: `setup --host codex`. Never infer a replacement provider from inherited environment markers. The invocation below repeats this guard. - - **Disabled is a terminal branch for this section.** If the preflight prints `CODEX_MODE: disabled`, persist `outside_status: disabled` with the guarded command below, then continue directly to the workflow's required outputs after this section. Do not construct a challenge, @@ -477,10 +474,10 @@ Immediately before dispatching, check the preflight result again. On `CODEX_MODE: disabled`, finish this section with `outside_status: disabled`; do not dispatch. Otherwise, use this fallback for missing/broken CLI, failed authentication/model selection, a failed preflight, or a failed outside invocation. -The disabled branch never reaches this fallback. In this section, `under_codex` -or `under_current_harness` also follows this native fallback: run no outside CLI, -report the setup repair and `outside_status: unavailable`, then use the native -subagent below. A native result never supplies outside coverage. +The disabled branch never reaches this fallback. +On `CODEX_MODE: under_codex`, report the setup repair and +`outside_status: unavailable`, run no outside CLI, and use the native subagent below. +A native result never supplies outside coverage. Dispatch via the Agent tool with `run_in_background: false` (subagents default to background since Claude Code v2.1.198; the findings must land before the workflow continues). The subagent has fresh context and no conversation bias — but it is the same harness; model identity stays unknown unless the runtime reports it; weigh its agreement accordingly. Bound it the same way as Codex: cap the dispatch at a 5-minute timeout so "never blocking" @@ -711,11 +708,18 @@ this run (an empty file means "ran, no findings" — distinct from "didn't run") ### Completion Summary + +Use the full mode name from Step 0F; replace spaces with underscores only in the +review log's `MODE` field. "System Audit" summarizes repository findings from +Step 0 and the review sections. "Lake Score" counts complete options chosen +out of decisions that compared a complete option with a shortcut; use `N/A` +when there were no such decisions. + ``` +====================================================================+ | MEGA PLAN REVIEW — COMPLETION SUMMARY | +====================================================================+ - | Mode selected | EXPANSION / SELECTIVE / HOLD / REDUCTION | + | Mode selected | [full mode name from Step 0F] | | System Audit | [key findings] | | Step 0 | [mode + key decisions] | | Section 1 (Arch) | ___ issues found | diff --git a/plan-ceo-review/sections/review-sections.md.tmpl b/plan-ceo-review/sections/review-sections.md.tmpl index d3675a735..17126b056 100644 --- a/plan-ceo-review/sections/review-sections.md.tmpl +++ b/plan-ceo-review/sections/review-sections.md.tmpl @@ -410,11 +410,18 @@ List every ASCII diagram in files this plan touches. Still accurate? {{TASKS_SECTION_EMIT:ceo-review}} ### Completion Summary + +Use the full mode name from Step 0F; replace spaces with underscores only in the +review log's `MODE` field. "System Audit" summarizes repository findings from +Step 0 and the review sections. "Lake Score" counts complete options chosen +out of decisions that compared a complete option with a shortcut; use `N/A` +when there were no such decisions. + ``` +====================================================================+ | MEGA PLAN REVIEW — COMPLETION SUMMARY | +====================================================================+ - | Mode selected | EXPANSION / SELECTIVE / HOLD / REDUCTION | + | Mode selected | [full mode name from Step 0F] | | System Audit | [key findings] | | Step 0 | [mode + key decisions] | | Section 1 (Arch) | ___ issues found | diff --git a/plan-design-review/SKILL.md b/plan-design-review/SKILL.md index 02be836c9..05aff32c6 100644 --- a/plan-design-review/SKILL.md +++ b/plan-design-review/SKILL.md @@ -1192,16 +1192,16 @@ missing work — do NOT call ExitPlanMode: does NOT count — only the structured `## GSTACK REVIEW REPORT` section satisfies this check. 3. Confirm the report has a Runs / Status / Findings table and a VERDICT line - (CODEX / CROSS-MODEL absorbed if applicable). + (OUTSIDE COVERAGE / CROSS-MODEL included when applicable). 4. Confirm the report's FINAL non-whitespace line is the unresolved-decisions status: the exact unbolded `NO UNRESOLVED DECISIONS`, or a bullet of a final `**UNRESOLVED DECISIONS:**` block. BLOCKING, no "if applicable" escape — a - bolded sentinel, any trailing CODEX/CROSS-MODEL/VERDICT/prose, or a missing + bolded sentinel, any trailing report field or prose, or a missing status each FAILS the gate. 5. If a plan file is in context for this skill invocation: confirm `gstack-review-log` was called and `gstack-review-read` was run at least - once. If no plan file is in context (e.g. `/codex consult` against a - diff with no plan), this check short-circuits — checks 1-4 already + once. If no plan file is in context (e.g. a diff review with no plan), + this check short-circuits — checks 1-4 already short-circuit when no plan file exists. Failing this gate and calling ExitPlanMode anyway is a contract violation — diff --git a/plan-devex-review/SKILL.md b/plan-devex-review/SKILL.md index 9b260172c..3ec10672a 100644 --- a/plan-devex-review/SKILL.md +++ b/plan-devex-review/SKILL.md @@ -1131,16 +1131,16 @@ missing work — do NOT call ExitPlanMode: does NOT count — only the structured `## GSTACK REVIEW REPORT` section satisfies this check. 3. Confirm the report has a Runs / Status / Findings table and a VERDICT line - (CODEX / CROSS-MODEL absorbed if applicable). + (OUTSIDE COVERAGE / CROSS-MODEL included when applicable). 4. Confirm the report's FINAL non-whitespace line is the unresolved-decisions status: the exact unbolded `NO UNRESOLVED DECISIONS`, or a bullet of a final `**UNRESOLVED DECISIONS:**` block. BLOCKING, no "if applicable" escape — a - bolded sentinel, any trailing CODEX/CROSS-MODEL/VERDICT/prose, or a missing + bolded sentinel, any trailing report field or prose, or a missing status each FAILS the gate. 5. If a plan file is in context for this skill invocation: confirm `gstack-review-log` was called and `gstack-review-read` was run at least - once. If no plan file is in context (e.g. `/codex consult` against a - diff with no plan), this check short-circuits — checks 1-4 already + once. If no plan file is in context (e.g. a diff review with no plan), + this check short-circuits — checks 1-4 already short-circuit when no plan file exists. Failing this gate and calling ExitPlanMode anyway is a contract violation — diff --git a/plan-devex-review/sections/review-sections.md b/plan-devex-review/sections/review-sections.md index 0a28a1b9c..6aa246ea9 100644 --- a/plan-devex-review/sections/review-sections.md +++ b/plan-devex-review/sections/review-sections.md @@ -286,15 +286,12 @@ echo "CODEX_MODE: $_CODEX_MODE" Branch on the echoed `CODEX_MODE`: - **`disabled`** — the user turned Codex reviews off (`codex_reviews=disabled`). Skip this section entirely; do NOT fall back to a Claude subagent — disabled means no extra review step. Print: "Codex review skipped (codex_reviews disabled). Re-enable: `gstack-config set codex_reviews enabled`." - **`not_installed`** — Codex CLI absent. Print: "Codex not installed — falling back to a Claude subagent (fresh context, but the same harness; model identity is unknown). Install Codex for an actual outside-model read: `npm install -g @openai/codex`." Fall back to the Claude subagent path. -- **`under_codex`** — stale artifact selected its own harness. Print: "Codex outside review unavailable: harness mismatch; no outside process started. Missing coverage. Repair: setup --host codex." Skip the outside invocation; retain the section's native pass if defined. Conflicting inherited harness markers are not grounds to guess another provider. +- **`under_codex`** — stale artifact selected its own harness. Print: "Codex outside review unavailable: harness mismatch; no outside process started. Missing coverage. Repair: setup --host codex." Skip the outside invocation and follow the workflow's native-review instructions below. Conflicting inherited harness markers are not grounds to guess another provider. - **`not_authed`** — installed but no credentials. Print: "Codex installed but not authenticated — falling back to a Claude subagent (same harness; model identity is unknown). Run `codex login` or set `$CODEX_API_KEY`." Fall back to the Claude subagent path. - **`broken_install`** — the CLI is on PATH but cannot execute (spawn ENOENT, non-executable binary, missing vendor payload). Print: "Codex is installed but its binary cannot run — Codex passes skipped. Reinstall: `npm install -g @openai/codex`." Relay the probe's HINT lines and fall back to the Claude subagent path. This state exists because a missing binary used to land in the model probe's fail-open bucket and report `ready`, so every Codex pass was skipped silently (#2742). - **`model_unusable`** — authed but the account cannot use gstack's selected Codex model (#2477: HTTP 400 on every call). Relay the probe's HINT lines, tell the user the one-line fix (set `GSTACK_CODEX_MODEL=` or pass an explicit `-c model=...` override), and fall back to the Claude subagent path. The ~10s round trip is cached for 1h; timeouts fail open to `ready`. - **`ready`** — run the Codex pass below. -A stale artifact selecting its own harness must report missing coverage and run no outside CLI. Repair: `setup --host codex`. Never infer a replacement provider from inherited environment markers. The invocation below repeats this guard. - - **Disabled is a terminal branch for this section.** If the preflight prints `CODEX_MODE: disabled`, persist `outside_status: disabled` with the guarded command below, then continue directly to the workflow's required outputs after this section. Do not construct a challenge, @@ -401,10 +398,10 @@ Immediately before dispatching, check the preflight result again. On `CODEX_MODE: disabled`, finish this section with `outside_status: disabled`; do not dispatch. Otherwise, use this fallback for missing/broken CLI, failed authentication/model selection, a failed preflight, or a failed outside invocation. -The disabled branch never reaches this fallback. In this section, `under_codex` -or `under_current_harness` also follows this native fallback: run no outside CLI, -report the setup repair and `outside_status: unavailable`, then use the native -subagent below. A native result never supplies outside coverage. +The disabled branch never reaches this fallback. +On `CODEX_MODE: under_codex`, report the setup repair and +`outside_status: unavailable`, run no outside CLI, and use the native subagent below. +A native result never supplies outside coverage. Dispatch via the Agent tool with `run_in_background: false` (subagents default to background since Claude Code v2.1.198; the findings must land before the workflow continues). The subagent has fresh context and no conversation bias — but it is the same harness; model identity stays unknown unless the runtime reports it; weigh its agreement accordingly. Bound it the same way as Codex: cap the dispatch at a 5-minute timeout so "never blocking" diff --git a/plan-eng-review/SKILL.md b/plan-eng-review/SKILL.md index 6544e883b..ff1458a93 100644 --- a/plan-eng-review/SKILL.md +++ b/plan-eng-review/SKILL.md @@ -736,16 +736,16 @@ missing work — do NOT call ExitPlanMode: does NOT count — only the structured `## GSTACK REVIEW REPORT` section satisfies this check. 3. Confirm the report has a Runs / Status / Findings table and a VERDICT line - (CODEX / CROSS-MODEL absorbed if applicable). + (OUTSIDE COVERAGE / CROSS-MODEL included when applicable). 4. Confirm the report's FINAL non-whitespace line is the unresolved-decisions status: the exact unbolded `NO UNRESOLVED DECISIONS`, or a bullet of a final `**UNRESOLVED DECISIONS:**` block. BLOCKING, no "if applicable" escape — a - bolded sentinel, any trailing CODEX/CROSS-MODEL/VERDICT/prose, or a missing + bolded sentinel, any trailing report field or prose, or a missing status each FAILS the gate. 5. If a plan file is in context for this skill invocation: confirm `gstack-review-log` was called and `gstack-review-read` was run at least - once. If no plan file is in context (e.g. `/codex consult` against a - diff with no plan), this check short-circuits — checks 1-4 already + once. If no plan file is in context (e.g. a diff review with no plan), + this check short-circuits — checks 1-4 already short-circuit when no plan file exists. Failing this gate and calling ExitPlanMode anyway is a contract violation — diff --git a/plan-eng-review/sections/review-sections.md b/plan-eng-review/sections/review-sections.md index 57d06663a..e20769aac 100644 --- a/plan-eng-review/sections/review-sections.md +++ b/plan-eng-review/sections/review-sections.md @@ -391,15 +391,12 @@ echo "CODEX_MODE: $_CODEX_MODE" Branch on the echoed `CODEX_MODE`: - **`disabled`** — the user turned Codex reviews off (`codex_reviews=disabled`). Skip this section entirely; do NOT fall back to a Claude subagent — disabled means no extra review step. Print: "Codex review skipped (codex_reviews disabled). Re-enable: `gstack-config set codex_reviews enabled`." - **`not_installed`** — Codex CLI absent. Print: "Codex not installed — falling back to a Claude subagent (fresh context, but the same harness; model identity is unknown). Install Codex for an actual outside-model read: `npm install -g @openai/codex`." Fall back to the Claude subagent path. -- **`under_codex`** — stale artifact selected its own harness. Print: "Codex outside review unavailable: harness mismatch; no outside process started. Missing coverage. Repair: setup --host codex." Skip the outside invocation; retain the section's native pass if defined. Conflicting inherited harness markers are not grounds to guess another provider. +- **`under_codex`** — stale artifact selected its own harness. Print: "Codex outside review unavailable: harness mismatch; no outside process started. Missing coverage. Repair: setup --host codex." Skip the outside invocation and follow the workflow's native-review instructions below. Conflicting inherited harness markers are not grounds to guess another provider. - **`not_authed`** — installed but no credentials. Print: "Codex installed but not authenticated — falling back to a Claude subagent (same harness; model identity is unknown). Run `codex login` or set `$CODEX_API_KEY`." Fall back to the Claude subagent path. - **`broken_install`** — the CLI is on PATH but cannot execute (spawn ENOENT, non-executable binary, missing vendor payload). Print: "Codex is installed but its binary cannot run — Codex passes skipped. Reinstall: `npm install -g @openai/codex`." Relay the probe's HINT lines and fall back to the Claude subagent path. This state exists because a missing binary used to land in the model probe's fail-open bucket and report `ready`, so every Codex pass was skipped silently (#2742). - **`model_unusable`** — authed but the account cannot use gstack's selected Codex model (#2477: HTTP 400 on every call). Relay the probe's HINT lines, tell the user the one-line fix (set `GSTACK_CODEX_MODEL=` or pass an explicit `-c model=...` override), and fall back to the Claude subagent path. The ~10s round trip is cached for 1h; timeouts fail open to `ready`. - **`ready`** — run the Codex pass below. -A stale artifact selecting its own harness must report missing coverage and run no outside CLI. Repair: `setup --host codex`. Never infer a replacement provider from inherited environment markers. The invocation below repeats this guard. - - **Disabled is a terminal branch for this section.** If the preflight prints `CODEX_MODE: disabled`, persist `outside_status: disabled` with the guarded command below, then continue directly to the workflow's required outputs after this section. Do not construct a challenge, @@ -506,10 +503,10 @@ Immediately before dispatching, check the preflight result again. On `CODEX_MODE: disabled`, finish this section with `outside_status: disabled`; do not dispatch. Otherwise, use this fallback for missing/broken CLI, failed authentication/model selection, a failed preflight, or a failed outside invocation. -The disabled branch never reaches this fallback. In this section, `under_codex` -or `under_current_harness` also follows this native fallback: run no outside CLI, -report the setup repair and `outside_status: unavailable`, then use the native -subagent below. A native result never supplies outside coverage. +The disabled branch never reaches this fallback. +On `CODEX_MODE: under_codex`, report the setup repair and +`outside_status: unavailable`, run no outside CLI, and use the native subagent below. +A native result never supplies outside coverage. Dispatch via the Agent tool with `run_in_background: false` (subagents default to background since Claude Code v2.1.198; the findings must land before the workflow continues). The subagent has fresh context and no conversation bias — but it is the same harness; model identity stays unknown unless the runtime reports it; weigh its agreement accordingly. Bound it the same way as Codex: cap the dispatch at a 5-minute timeout so "never blocking" diff --git a/review/sections/adversarial.md b/review/sections/adversarial.md index 043350702..b00b2f962 100644 --- a/review/sections/adversarial.md +++ b/review/sections/adversarial.md @@ -53,15 +53,12 @@ echo "CODEX_MODE: $_CODEX_MODE" Branch on the echoed `CODEX_MODE`: - **`disabled`** — the user turned Codex reviews off (`codex_reviews=disabled`). Skip the Codex passes only; the Claude adversarial subagent below STILL runs (it is free and fast). Print: "Codex passes skipped (codex_reviews disabled) — running Claude adversarial only." - **`not_installed`** — Codex CLI absent. Print: "Codex not installed — falling back to a Claude subagent (fresh context, but the same harness; model identity is unknown). Install Codex for an actual outside-model read: `npm install -g @openai/codex`." Fall back to the Claude subagent path. -- **`under_codex`** — stale artifact selected its own harness. Print: "Codex outside review unavailable: harness mismatch; no outside process started. Missing coverage. Repair: setup --host codex." Skip the outside invocation; retain the section's native pass if defined. Conflicting inherited harness markers are not grounds to guess another provider. +- **`under_codex`** — stale artifact selected its own harness. Print: "Codex outside review unavailable: harness mismatch; no outside process started. Missing coverage. Repair: setup --host codex." Skip the outside invocation and follow the workflow's native-review instructions below. Conflicting inherited harness markers are not grounds to guess another provider. - **`not_authed`** — installed but no credentials. Print: "Codex installed but not authenticated — falling back to a Claude subagent (same harness; model identity is unknown). Run `codex login` or set `$CODEX_API_KEY`." Fall back to the Claude subagent path. - **`broken_install`** — the CLI is on PATH but cannot execute (spawn ENOENT, non-executable binary, missing vendor payload). Print: "Codex is installed but its binary cannot run — Codex passes skipped. Reinstall: `npm install -g @openai/codex`." Relay the probe's HINT lines and fall back to the Claude subagent path. This state exists because a missing binary used to land in the model probe's fail-open bucket and report `ready`, so every Codex pass was skipped silently (#2742). - **`model_unusable`** — authed but the account cannot use gstack's selected Codex model (#2477: HTTP 400 on every call). Relay the probe's HINT lines, tell the user the one-line fix (set `GSTACK_CODEX_MODEL=` or pass an explicit `-c model=...` override), and fall back to the Claude subagent path. The ~10s round trip is cached for 1h; timeouts fail open to `ready`. - **`ready`** — run the Codex pass below. -A stale artifact selecting its own harness must report missing coverage and run no outside CLI. Repair: `setup --host codex`. Never infer a replacement provider from inherited environment markers. The invocation below repeats this guard. - - For this diff-review path, `CODEX_MODE: disabled` means skip the Codex passes ONLY — the Claude adversarial subagent below still runs (it's free and fast). `ready` runs the Codex passes; `not_installed` / `not_authed` skip them with the printed note and continue with diff --git a/scripts/resolvers/constants.ts b/scripts/resolvers/constants.ts index 19117b114..ef5b35320 100644 --- a/scripts/resolvers/constants.ts +++ b/scripts/resolvers/constants.ts @@ -152,7 +152,7 @@ echo "CODEX_MODE: $${m}" Branch on the echoed \`CODEX_MODE\`: - **\`disabled\`** — the user turned Codex reviews off (\`codex_reviews=disabled\`). ${disabledLine} - **\`not_installed\`** — Codex CLI absent. Print: "Codex not installed — falling back to a Claude subagent (fresh context, but the same harness; model identity is unknown). Install Codex for an actual outside-model read: \`npm install -g @openai/codex\`." Fall back to the Claude subagent path. -- **\`under_codex\`** — stale artifact selected its own harness. Print: "Codex outside review unavailable: harness mismatch; no outside process started. Missing coverage. Repair: setup --host codex." Skip the outside invocation; retain the section's native pass if defined. Conflicting inherited harness markers are not grounds to guess another provider. +- **\`under_codex\`** — stale artifact selected its own harness. Print: "Codex outside review unavailable: harness mismatch; no outside process started. Missing coverage. Repair: setup --host codex." Skip the outside invocation and follow the workflow's native-review instructions below. Conflicting inherited harness markers are not grounds to guess another provider. - **\`not_authed\`** — installed but no credentials. Print: "Codex installed but not authenticated — falling back to a Claude subagent (same harness; model identity is unknown). Run \`codex login\` or set \`$CODEX_API_KEY\`." Fall back to the Claude subagent path. - **\`broken_install\`** — the CLI is on PATH but cannot execute (spawn ENOENT, non-executable binary, missing vendor payload). Print: "Codex is installed but its binary cannot run — Codex passes skipped. Reinstall: \`npm install -g @openai/codex\`." Relay the probe's HINT lines and fall back to the Claude subagent path. This state exists because a missing binary used to land in the model probe's fail-open bucket and report \`ready\`, so every Codex pass was skipped silently (#2742). - **\`model_unusable\`** — authed but the account cannot use gstack's selected Codex model (#2477: HTTP 400 on every call). Relay the probe's HINT lines, tell the user the one-line fix (set \`GSTACK_CODEX_MODEL=\` or pass an explicit \`-c model=...\` override), and fall back to the Claude subagent path. The ~10s round trip is cached for 1h; timeouts fail open to \`ready\`. diff --git a/scripts/resolvers/outside-voice.ts b/scripts/resolvers/outside-voice.ts index 76dbb90a2..e4d4781e6 100644 --- a/scripts/resolvers/outside-voice.ts +++ b/scripts/resolvers/outside-voice.ts @@ -71,7 +71,7 @@ export function outsideVoicePreflight(ctx: TemplateContext, opts: { disabledBeha if (v.id === 'codex' && opts.disabledBehavior !== 'opt-in') { const preflight = outsideVoiceLabels(ctx, codexPreflight(opts)) .replace('```bash\n', `\`\`\`bash\n${outsideVoiceRuntime(ctx)}\n`); - return preflight + '\n\nA stale artifact selecting its own harness must report missing coverage and run no outside CLI. Repair: `setup --host codex`. Never infer a replacement provider from inherited environment markers. The invocation below repeats this guard.\n'; + return preflight; } const bin = toShellPath(ctx.paths.binDir); const probe = v.id === 'codex' diff --git a/scripts/resolvers/review.ts b/scripts/resolvers/review.ts index 6f1fdbff2..b39eb8a5d 100644 --- a/scripts/resolvers/review.ts +++ b/scripts/resolvers/review.ts @@ -203,16 +203,16 @@ ${approvals}1. Read the plan file with the Read tool (after your most recent wri does NOT count — only the structured \`## GSTACK REVIEW REPORT\` section satisfies this check. 3. Confirm the report has a Runs / Status / Findings table and a VERDICT line - (CODEX / CROSS-MODEL absorbed if applicable). + (OUTSIDE COVERAGE / CROSS-MODEL included when applicable). 4. Confirm the report's FINAL non-whitespace line is the unresolved-decisions status: the exact unbolded \`NO UNRESOLVED DECISIONS\`, or a bullet of a final \`**UNRESOLVED DECISIONS:**\` block. BLOCKING, no "if applicable" escape — a - bolded sentinel, any trailing CODEX/CROSS-MODEL/VERDICT/prose, or a missing + bolded sentinel, any trailing report field or prose, or a missing status each FAILS the gate. 5. If a plan file is in context for this skill invocation: confirm \`gstack-review-log\` was called and \`gstack-review-read\` was run at least - once. If no plan file is in context (e.g. \`/codex consult\` against a - diff with no plan), this check short-circuits — checks 1-4 already + once. If no plan file is in context (e.g. a diff review with no plan), + this check short-circuits — checks 1-4 already short-circuit when no plan file exists. Failing this gate and calling ExitPlanMode anyway is a contract violation — @@ -230,7 +230,8 @@ export function generateAntiShortcutClause(_ctx: TemplateContext): string { export function generateSpecReviewLoop(_ctx: TemplateContext): string { return `## Spec Review Loop -Before presenting the document to the user for approval, run an adversarial review. +Run an adversarial review before presenting the final document to the user. +Follow the calling workflow's approval steps. **Step 1: Dispatch reviewer subagent** @@ -706,10 +707,10 @@ Immediately before dispatching, check the preflight result again. On \`CODEX_MODE: disabled\`, finish this section with \`outside_status: disabled\`; do not dispatch. Otherwise, use this fallback for missing/broken CLI, failed authentication/model selection, a failed preflight, or a failed outside invocation. -The disabled branch never reaches this fallback. In this section, \`under_codex\` -or \`under_current_harness\` also follows this native fallback: run no outside CLI, -report the setup repair and \`outside_status: unavailable\`, then use the native -subagent below. A native result never supplies outside coverage. +The disabled branch never reaches this fallback. +On \`CODEX_MODE: ${outsideVoiceFor(ctx).id === 'codex' ? 'under_codex' : 'under_current_harness'}\`, report the setup repair and +\`outside_status: unavailable\`, run no outside CLI, and use the native subagent below. +A native result never supplies outside coverage. Dispatch via the Agent tool with \`run_in_background: false\` (subagents default to background since ${CC_BACKGROUND_DEFAULT_SINCE}; the findings must land before the workflow continues). The subagent has fresh context and no conversation bias — but it is the same harness; model identity stays unknown unless the runtime reports it; weigh its agreement accordingly. Bound it the same way as ${outsideVoiceFor(ctx).label}: cap the dispatch at a 5-minute timeout so "never blocking" @@ -846,10 +847,10 @@ Immediately before dispatching, check the preflight result again. On \`CODEX_MODE: disabled\`, finish this section with \`outside_status: disabled\`; do not dispatch. Otherwise, use this fallback for missing/broken CLI, failed authentication/model selection, a failed preflight, or a failed outside invocation. -The disabled branch never reaches this fallback. In this section, \`under_codex\` -or \`under_current_harness\` also follows this native fallback: run no outside CLI, -report the setup repair and \`outside_status: unavailable\`, then use the native -subagent below. A native result never supplies outside coverage. +The disabled branch never reaches this fallback. +On \`CODEX_MODE: ${outsideVoiceFor(ctx).id === 'codex' ? 'under_codex' : 'under_current_harness'}\`, report the setup repair and +\`outside_status: unavailable\`, run no outside CLI, and use the native subagent below. +A native result never supplies outside coverage. Dispatch via the Agent tool with the same prompt, passing \`run_in_background: false\` (subagents default to background since ${CC_BACKGROUND_DEFAULT_SINCE}). Bound it at a 5-minute timeout; if it never completes, treat the review as unavailable and continue. Present findings under \`DOCUMENTATION REVIEW (${outsideVoiceFor(ctx).nativeLabel} subagent):\`. If it fails: "Doc review unavailable. Continuing to Step 9." Skip the apply gate, persist \`status: unavailable\`, \`outside_status: unavailable\`, and \`source: none\` below, then continue; unavailable is not a clean review. diff --git a/ship/sections/adversarial.md b/ship/sections/adversarial.md index 6f39d60c2..1e704ea3d 100644 --- a/ship/sections/adversarial.md +++ b/ship/sections/adversarial.md @@ -53,15 +53,12 @@ echo "CODEX_MODE: $_CODEX_MODE" Branch on the echoed `CODEX_MODE`: - **`disabled`** — the user turned Codex reviews off (`codex_reviews=disabled`). Skip the Codex passes only; the Claude adversarial subagent below STILL runs (it is free and fast). Print: "Codex passes skipped (codex_reviews disabled) — running Claude adversarial only." - **`not_installed`** — Codex CLI absent. Print: "Codex not installed — falling back to a Claude subagent (fresh context, but the same harness; model identity is unknown). Install Codex for an actual outside-model read: `npm install -g @openai/codex`." Fall back to the Claude subagent path. -- **`under_codex`** — stale artifact selected its own harness. Print: "Codex outside review unavailable: harness mismatch; no outside process started. Missing coverage. Repair: setup --host codex." Skip the outside invocation; retain the section's native pass if defined. Conflicting inherited harness markers are not grounds to guess another provider. +- **`under_codex`** — stale artifact selected its own harness. Print: "Codex outside review unavailable: harness mismatch; no outside process started. Missing coverage. Repair: setup --host codex." Skip the outside invocation and follow the workflow's native-review instructions below. Conflicting inherited harness markers are not grounds to guess another provider. - **`not_authed`** — installed but no credentials. Print: "Codex installed but not authenticated — falling back to a Claude subagent (same harness; model identity is unknown). Run `codex login` or set `$CODEX_API_KEY`." Fall back to the Claude subagent path. - **`broken_install`** — the CLI is on PATH but cannot execute (spawn ENOENT, non-executable binary, missing vendor payload). Print: "Codex is installed but its binary cannot run — Codex passes skipped. Reinstall: `npm install -g @openai/codex`." Relay the probe's HINT lines and fall back to the Claude subagent path. This state exists because a missing binary used to land in the model probe's fail-open bucket and report `ready`, so every Codex pass was skipped silently (#2742). - **`model_unusable`** — authed but the account cannot use gstack's selected Codex model (#2477: HTTP 400 on every call). Relay the probe's HINT lines, tell the user the one-line fix (set `GSTACK_CODEX_MODEL=` or pass an explicit `-c model=...` override), and fall back to the Claude subagent path. The ~10s round trip is cached for 1h; timeouts fail open to `ready`. - **`ready`** — run the Codex pass below. -A stale artifact selecting its own harness must report missing coverage and run no outside CLI. Repair: `setup --host codex`. Never infer a replacement provider from inherited environment markers. The invocation below repeats this guard. - - For this diff-review path, `CODEX_MODE: disabled` means skip the Codex passes ONLY — the Claude adversarial subagent below still runs (it's free and fast). `ready` runs the Codex passes; `not_installed` / `not_authed` skip them with the printed note and continue with diff --git a/test/ceo-mode-preference-al.test.ts b/test/ceo-mode-preference-al.test.ts index 4ad3df93b..f4e5a1aaf 100644 --- a/test/ceo-mode-preference-al.test.ts +++ b/test/ceo-mode-preference-al.test.ts @@ -84,7 +84,7 @@ test('only an explicit user selection or enabled successful mode check bypasses expect(q).toContain('`ASK_NORMALLY` means ask.'); expect(s).toContain('This settles only the mode, not approach or scope approval.'); expect(document).toContain('Do NOT proceed to mode selection (0F) without user approval of the chosen approach.'); - expect(s).toContain('Every mode requires your explicit approval for added scope.'); + expect(s).toContain('Every mode requires explicit user approval for scope changes.'); expect(s).toContain('Keep the approved 0C-bis approach; explain and obtain approval for any mode-required change.'); expect(s).toContain('offer all four modes in one AskUserQuestion'); expect(s).toContain('context defaults for RECOMMENDATION'); diff --git a/test/fixtures/golden/factory-ship-SKILL.md b/test/fixtures/golden/factory-ship-SKILL.md index 9a79e7a56..28c6e4147 100644 --- a/test/fixtures/golden/factory-ship-SKILL.md +++ b/test/fixtures/golden/factory-ship-SKILL.md @@ -2308,15 +2308,12 @@ echo "CODEX_MODE: $_CODEX_MODE" Branch on the echoed `CODEX_MODE`: - **`disabled`** — the user turned Codex reviews off (`codex_reviews=disabled`). Skip the Codex passes only; the factory (in-host) adversarial subagent below STILL runs (it is free and fast). Print: "Codex passes skipped (codex_reviews disabled) — running factory (in-host) adversarial only." - **`not_installed`** — Codex CLI absent. Print: "Codex not installed — falling back to a factory (in-host) subagent (fresh context, but the same harness; model identity is unknown). Install Codex for an actual outside-model read: `npm install -g @openai/codex`." Fall back to the factory (in-host) subagent path. -- **`under_codex`** — stale artifact selected its own harness. Print: "Codex outside review unavailable: harness mismatch; no outside process started. Missing coverage. Repair: setup --host codex." Skip the outside invocation; retain the section's native pass if defined. Conflicting inherited harness markers are not grounds to guess another provider. +- **`under_codex`** — stale artifact selected its own harness. Print: "Codex outside review unavailable: harness mismatch; no outside process started. Missing coverage. Repair: setup --host codex." Skip the outside invocation and follow the workflow's native-review instructions below. Conflicting inherited harness markers are not grounds to guess another provider. - **`not_authed`** — installed but no credentials. Print: "Codex installed but not authenticated — falling back to a factory (in-host) subagent (same harness; model identity is unknown). Run `codex login` or set `$CODEX_API_KEY`." Fall back to the factory (in-host) subagent path. - **`broken_install`** — the CLI is on PATH but cannot execute (spawn ENOENT, non-executable binary, missing vendor payload). Print: "Codex is installed but its binary cannot run — Codex passes skipped. Reinstall: `npm install -g @openai/codex`." Relay the probe's HINT lines and fall back to the factory (in-host) subagent path. This state exists because a missing binary used to land in the model probe's fail-open bucket and report `ready`, so every Codex pass was skipped silently (#2742). - **`model_unusable`** — authed but the account cannot use gstack's selected Codex model (#2477: HTTP 400 on every call). Relay the probe's HINT lines, tell the user the one-line fix (set `GSTACK_CODEX_MODEL=` or pass an explicit `-c model=...` override), and fall back to the factory (in-host) subagent path. The ~10s round trip is cached for 1h; timeouts fail open to `ready`. - **`ready`** — run the Codex pass below. -A stale artifact selecting its own harness must report missing coverage and run no outside CLI. Repair: `setup --host codex`. Never infer a replacement provider from inherited environment markers. The invocation below repeats this guard. - - For this diff-review path, `CODEX_MODE: disabled` means skip the Codex passes ONLY — the factory (in-host) adversarial subagent below still runs (it's free and fast). `ready` runs the Codex passes; `not_installed` / `not_authed` skip them with the printed note and continue with diff --git a/test/outside-voice-preflight.test.ts b/test/outside-voice-preflight.test.ts index fa550815f..356ac384b 100644 --- a/test/outside-voice-preflight.test.ts +++ b/test/outside-voice-preflight.test.ts @@ -5,12 +5,41 @@ import * as os from 'node:os'; import * as path from 'node:path'; import { spawnSync } from 'node:child_process'; import { outsideVoiceCommand, outsideVoicePreflight } from '../scripts/resolvers/outside-voice'; +import { generateCodexDocReview, generateCodexPlanReview } from '../scripts/resolvers/review'; import { HOST_PATHS, type TemplateContext } from '../scripts/resolvers/types'; +import { ALL_HOST_CONFIGS } from '../hosts'; const ROOT = path.resolve(import.meta.dir, '..'); const TEMP = fs.mkdtempSync(path.join(os.tmpdir(), 'gstack-outside-preflight-')); afterAll(() => fs.rmSync(TEMP, { recursive: true, force: true })); +describe('own-harness review fallback instructions', () => { + for (const host of ALL_HOST_CONFIGS) { + for (const [name, render] of [['plan', generateCodexPlanReview], ['documentation', generateCodexDocReview]] as const) { + test(`${host.name}: ${name} fallback names only the mode its preflight emits`, () => { + const ctx: TemplateContext = { host: host.name, skillName: 'review', tmplPath: 'review/SKILL.md.tmpl', paths: HOST_PATHS[host.name] }; + const text = render(ctx); + const mode = host.name === 'codex' ? 'under_current_harness' : 'under_codex'; + const preflight = text.match(/```bash\n([\s\S]*?)\n```/)![1]; + expect(preflight).toContain(mode); + expect([...new Set(text.match(/under_codex|under_current_harness/g))]).toEqual([mode]); + expect(text.includes("retain the section's native pass if defined")).toBe(false); + + const fallback = text.slice(text.indexOf('**Native fallback'), text.indexOf('Dispatch via the Agent tool')); + const ownHarnessBranch = `On \`CODEX_MODE: ${mode}\``; + expect(text.split(ownHarnessBranch)).toHaveLength(2); + expect(fallback).toContain(ownHarnessBranch); + expect(fallback).toContain('`outside_status: unavailable`'); + expect(fallback).toContain('run no outside CLI'); + expect(fallback).toContain('use the native subagent below'); + expect(fallback).toContain('A native result never supplies outside coverage.'); + expect(fallback).toContain('The disabled branch never reaches this fallback.'); + expect(fallback).toContain('`CODEX_MODE: disabled`, finish this section with `outside_status: disabled`;'); + }); + } + } +}); + function fixture() { const dir = fs.mkdtempSync(path.join(TEMP, 'case-')); const repo = path.join(dir, "repo ' $(touch NEVER)");