fix: clarify outside review fallback and CEO decisions

Render one applicable own-harness fallback path and retain native review,
disabled policy, and missing-coverage semantics. Align report field names
and mode labels, and make the existing per-cut scope approval explicit.

Regenerate skill outputs and keep the workflow judge's model, thresholds,
and retry policy unchanged.
This commit is contained in:
Garry Tan committed 2026-09-11 18:11:57 +00:00
1 parent 5114f8c59f
commit 4ce67de60b
21 files changed
+116 -94

No files matched your search

+1 -4
View File
@@ -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=<supported-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.
+4 -4
View File
@@ -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 —
+5 -8
View File
@@ -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=<supported-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.
+2 -1
View File
@@ -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**
+9 -8
View File
@@ -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 —
+3 -3
View File
@@ -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)
+13 -9
View File
@@ -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=<supported-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 |
@@ -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 |
+4 -4
View File
@@ -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 —
+4 -4
View File
@@ -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 —
@@ -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=<supported-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"
+4 -4
View File
@@ -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 —
+5 -8
View File
@@ -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=<supported-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"
+1 -4
View File
@@ -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=<supported-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
+1 -1
View File
@@ -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=<supported-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\`.
+1 -1
View File
@@ -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'
+14 -13
View File
@@ -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.
+1 -4
View File
@@ -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=<supported-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
+1 -1
View File
@@ -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');
+1 -4
View File
@@ -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=<supported-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
+29
View File
@@ -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)");