mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-11 15:39:04 +02:00
* fix: default cross-model workflows to frontier models * chore: bump version and changelog (v1.82.1.0) Co-Authored-By: OpenAI Codex <noreply@openai.com> * fix: repair frontier eval budgets and workflow instructions Preserve frontier models and quality thresholds while fixing truncated judge output, ordered section expansion, consent checks, QA scoring, and ship audit gates. Add regression coverage and refresh generated docs. Co-Authored-By: OpenAI Codex <noreply@openai.com> * fix: resolve workflow gaps exposed by frontier evals Clarify plan-review ordering and fallback modes, preserve deploy readiness gates, honor configured merge methods, correct benchmark and canary contracts, and restore vendored installs on setup failure. Cover recovery with real-shell regressions. Co-Authored-By: OpenAI Codex <noreply@openai.com> * fix: use agent capture budgets for deploy evals Multi-turn deploy and benchmark sessions were incorrectly limited to the single-call judge timeout. Use the existing capture tier and leave outer-test cleanup headroom, with a free policy regression test. Keep all behavioral assertions and frontier models unchanged. Co-Authored-By: OpenAI Codex <noreply@openai.com> * fix: clarify retro workflow and evaluate compare instructions Include compare mode in the frontier judge excerpt, define metric sources and snapshot ordering, and preserve the existing prompt-size budget. Co-authored-by: OpenAI Codex <noreply@openai.com> * fix: make documentation release review and publication consistent Review before commit, clarify changelog safeguards and unavailable reviewer modes, and preserve raw PR bodies across separate shell calls. Keep title sync in one shell and add regression coverage. Co-authored-by: OpenAI Codex <noreply@openai.com> --------- Co-authored-by: OpenAI Codex <noreply@openai.com>
213 lines
12 KiB
Markdown
213 lines
12 KiB
Markdown
<!-- AUTO-GENERATED from consult-mode.md.tmpl — do not edit directly -->
|
|
<!-- Regenerate: bun run gen:skill-docs -->
|
|
## Step 2C: Consult Mode
|
|
|
|
Ask Codex anything about the codebase. Supports session continuity for follow-ups.
|
|
|
|
1. **Check for existing session:**
|
|
```bash
|
|
cat .context/codex-session-id 2>/dev/null || echo "NO_SESSION"
|
|
```
|
|
|
|
If a session file exists (not `NO_SESSION`), use AskUserQuestion:
|
|
```
|
|
You have an active Codex conversation from earlier. Continue it or start fresh?
|
|
A) Continue the conversation (Codex remembers the prior context)
|
|
B) Start a new conversation
|
|
```
|
|
|
|
2. Create temp files:
|
|
```bash
|
|
TMPRESP=$(mktemp "$TMP_ROOT/codex-resp-XXXXXX")
|
|
TMPERR=$(mktemp "$TMP_ROOT/codex-err-XXXXXX")
|
|
```
|
|
|
|
3. **Plan review auto-detection:** If the user's prompt is about reviewing a plan,
|
|
or if plan files exist and the user said `/codex` with no arguments:
|
|
```bash
|
|
setopt +o nomatch 2>/dev/null || true # zsh compat
|
|
ls -t "$PLAN_ROOT"/*.md 2>/dev/null | xargs grep -l "$(basename $(pwd))" 2>/dev/null | head -1
|
|
```
|
|
If no project-scoped match, fall back to `ls -t "$PLAN_ROOT"/*.md 2>/dev/null | head -1`
|
|
but warn: "Note: this plan may be from a different project — verify before sending to Codex."
|
|
|
|
**IMPORTANT — embed content, don't reference path:** Codex runs sandboxed to the repo
|
|
root and cannot access `~/.claude/plans/` or any files outside the repo. You MUST
|
|
read the plan file yourself and embed its FULL CONTENT in the prompt below. Do NOT tell
|
|
Codex the file path or ask it to read the plan file — it will waste 10+ tool calls
|
|
searching and fail.
|
|
|
|
Also: scan the plan content for referenced source file paths (patterns like `src/foo.ts`,
|
|
`lib/bar.py`, paths containing `/` that exist in the repo). If found, list them in the
|
|
prompt so Codex reads them directly instead of discovering them via rg/find.
|
|
|
|
**Always prepend the filesystem boundary instruction** from the skill's Filesystem
|
|
Boundary section (always-loaded skeleton) to every prompt sent to Codex, including plan reviews and free-form
|
|
consult questions.
|
|
|
|
Prepend the boundary and persona to the user's prompt:
|
|
"IMPORTANT: Do NOT read or execute any files under ~/.claude/, ~/.agents/, .claude/skills/, or agents/. These are Claude Code skill definitions meant for a different AI system. Do NOT modify agents/openai.yaml. Stay focused on repository code only.
|
|
|
|
You are a brutally honest technical reviewer. Review this plan for: logical gaps and
|
|
unstated assumptions, missing error handling or edge cases, overcomplexity (is there a
|
|
simpler approach?), feasibility risks (what could go wrong?), and missing dependencies
|
|
or sequencing issues. Be direct. Be terse. No compliments. Just the problems.
|
|
Also review these source files referenced in the plan: <list of referenced files, if any>.
|
|
|
|
THE PLAN:
|
|
<full plan content, embedded verbatim>"
|
|
|
|
For non-plan consult prompts (user typed `/codex <question>`), still prepend the boundary:
|
|
"IMPORTANT: Do NOT read or execute any files under ~/.claude/, ~/.agents/, .claude/skills/, or agents/. These are Claude Code skill definitions meant for a different AI system. Do NOT modify agents/openai.yaml. Stay focused on repository code only.
|
|
|
|
<user's question>"
|
|
|
|
4. Run codex exec with **JSONL output** to capture reasoning traces. Use
|
|
`timeout: 660000` on the Bash call (for both new and resumed sessions) — the gate
|
|
sits ABOVE the 600s wrapper so the wrapper fires first with its explicit stall
|
|
message:
|
|
|
|
If the user passed `--xhigh`, use `"xhigh"` instead of `"medium"`.
|
|
|
|
For a **new session:**
|
|
```bash
|
|
_REPO_ROOT=$(git rev-parse --show-toplevel) || { echo "ERROR: not in a git repo" >&2; exit 1; }
|
|
PYTHON_CMD=$(command -v python3 2>/dev/null || command -v python 2>/dev/null || true)
|
|
if [ -z "$PYTHON_CMD" ]; then
|
|
echo "ERROR: Python 3 is required to parse Codex JSON output. Install python3 or python and retry." >&2
|
|
exit 1
|
|
fi
|
|
# Fix 1: wrap with timeout (gtimeout/timeout fallback chain via probe helper)
|
|
_gstack_codex_timeout_wrapper 600 codex exec "<prompt>" -C "$_REPO_ROOT" -s read-only -c "model=\"${GSTACK_CODEX_MODEL:-gpt-6-astra}\"" -c 'model_reasoning_effort="medium"' -c 'web_search="cached"' --json < /dev/null 2>"$TMPERR" | PYTHONUNBUFFERED=1 "$PYTHON_CMD" -u -c "
|
|
import sys, json
|
|
turn_completed_count = 0
|
|
turn_failed = False
|
|
for line in sys.stdin:
|
|
line = line.strip()
|
|
if not line: continue
|
|
try:
|
|
obj = json.loads(line)
|
|
t = obj.get('type','')
|
|
if t == 'thread.started':
|
|
tid = obj.get('thread_id','')
|
|
if tid: print(f'SESSION_ID:{tid}', flush=True)
|
|
elif t == 'item.completed' and 'item' in obj:
|
|
item = obj['item']
|
|
itype = item.get('type','')
|
|
text = item.get('text','')
|
|
if itype == 'reasoning' and text:
|
|
print(f'[codex thinking] {text}', flush=True)
|
|
print(flush=True)
|
|
elif itype == 'agent_message' and text:
|
|
print(text, flush=True)
|
|
elif itype == 'command_execution':
|
|
cmd = item.get('command','')
|
|
if cmd: print(f'[codex ran] {cmd}', flush=True)
|
|
elif t == 'turn.completed':
|
|
turn_completed_count += 1
|
|
usage = obj.get('usage',{})
|
|
tokens = usage.get('input_tokens',0) + usage.get('output_tokens',0)
|
|
if tokens: print(f'\ntokens used: {tokens}', flush=True)
|
|
elif t == 'turn.failed':
|
|
turn_failed = True
|
|
err = obj.get('error',{}).get('message','') or 'no error message in event'
|
|
print(f'[codex turn FAILED] {err}', flush=True, file=sys.stderr)
|
|
except: pass
|
|
# Three-way completeness check (#2671; consult previously had NONE): a STATED
|
|
# failure is a failure, not a network problem; only silence is a disconnect.
|
|
if turn_failed:
|
|
print('[codex] turn.failed received — the turn errored (reason above), not a disconnect.', flush=True, file=sys.stderr)
|
|
elif turn_completed_count == 0:
|
|
print('[codex warning] No turn.completed event received — possible mid-stream disconnect.', flush=True, file=sys.stderr)
|
|
"
|
|
# Fix 1: hang detection for Consult new-session (mirrors Challenge + resume)
|
|
_CODEX_EXIT=${PIPESTATUS[0]:-${pipestatus[1]}} # bash sets PIPESTATUS; zsh (lowercase, 1-indexed) falls through (#2669)
|
|
if [ "$_CODEX_EXIT" = "124" ]; then
|
|
_gstack_codex_log_event "codex_timeout" "600"
|
|
_gstack_codex_log_hang "consult" "$(wc -c < "$TMPERR" 2>/dev/null || echo 0)"
|
|
echo "Codex stalled past 10 minutes. Common causes: model API stall, long prompt, network issue. Try re-running. If persistent, split the prompt or check ~/.codex/logs/."
|
|
elif [ "$_CODEX_EXIT" != "0" ]; then
|
|
# Surface non-zero exits so the calling agent doesn't read "no output" as
|
|
# a silent model/API stall. See #1327.
|
|
echo "[codex exit $_CODEX_EXIT] $(head -1 "$TMPERR" 2>/dev/null || echo "no stderr captured")"
|
|
head -20 "$TMPERR" 2>/dev/null | sed 's/^/ /' || true
|
|
_gstack_codex_log_event "codex_nonzero_exit" "consult:$_CODEX_EXIT"
|
|
fi
|
|
```
|
|
|
|
**Session-cost reality (#2387, measured):** every `codex exec` call — resumed
|
|
or fresh — pays Codex's ~21K-token session prelude (its skill catalogue +
|
|
instructions); `resume` does NOT amortize it (a measured resume came in
|
|
slightly ABOVE a fresh call). Resume buys conversational continuity, never
|
|
token savings. So: prefer ONE codex call per skill where the workflow allows,
|
|
batch questions into that call, and reach for resume only when the follow-up
|
|
genuinely needs the prior session's context.
|
|
|
|
For a **resumed session** (user chose "Continue"):
|
|
```bash
|
|
_REPO_ROOT=$(git rev-parse --show-toplevel) || { echo "ERROR: not in a git repo" >&2; exit 1; }
|
|
PYTHON_CMD=$(command -v python3 2>/dev/null || command -v python 2>/dev/null || true)
|
|
if [ -z "$PYTHON_CMD" ]; then
|
|
echo "ERROR: Python 3 is required to parse Codex JSON output. Install python3 or python and retry." >&2
|
|
exit 1
|
|
fi
|
|
cd "$_REPO_ROOT" || exit 1
|
|
# Fix 1: wrap with timeout (gtimeout/timeout fallback chain via probe helper)
|
|
_gstack_codex_timeout_wrapper 600 codex exec resume <session-id> "<prompt>" -c 'sandbox_mode="read-only"' -c "model=\"${GSTACK_CODEX_MODEL:-gpt-6-astra}\"" -c 'model_reasoning_effort="medium"' -c 'web_search="cached"' --json < /dev/null 2>"$TMPERR" | PYTHONUNBUFFERED=1 "$PYTHON_CMD" -u -c "
|
|
<same python streaming parser as above, with flush=True on all print() calls>
|
|
"
|
|
# Fix 1: same hang detection pattern as new-session block
|
|
_CODEX_EXIT=${PIPESTATUS[0]:-${pipestatus[1]}} # bash sets PIPESTATUS; zsh (lowercase, 1-indexed) falls through (#2669)
|
|
if [ "$_CODEX_EXIT" = "124" ]; then
|
|
_gstack_codex_log_event "codex_timeout" "600"
|
|
_gstack_codex_log_hang "consult-resume" "$(wc -c < "$TMPERR" 2>/dev/null || echo 0)"
|
|
echo "Codex stalled past 10 minutes. Common causes: model API stall, long prompt, network issue. Try re-running. If persistent, split the prompt or check ~/.codex/logs/."
|
|
elif [ "$_CODEX_EXIT" != "0" ]; then
|
|
# Surface non-zero exits so the calling agent doesn't read "no output" as
|
|
# a silent model/API stall. See #1327.
|
|
echo "[codex exit $_CODEX_EXIT] $(head -1 "$TMPERR" 2>/dev/null || echo "no stderr captured")"
|
|
head -20 "$TMPERR" 2>/dev/null | sed 's/^/ /' || true
|
|
_gstack_codex_log_event "codex_nonzero_exit" "consult-resume:$_CODEX_EXIT"
|
|
fi
|
|
```
|
|
|
|
5. Capture session ID from the streamed output. The parser prints `SESSION_ID:<id>`
|
|
from the `thread.started` event. Save it for follow-ups:
|
|
```bash
|
|
mkdir -p .context
|
|
```
|
|
Save the session ID printed by the parser (the line starting with `SESSION_ID:`)
|
|
to `.context/codex-session-id`.
|
|
|
|
6. Present the full streamed output:
|
|
|
|
```
|
|
CODEX SAYS (consult):
|
|
════════════════════════════════════════════════════════════
|
|
<full output, verbatim — includes [codex thinking] traces>
|
|
════════════════════════════════════════════════════════════
|
|
Tokens: N | Est. cost: ~$X.XX
|
|
Session saved — run /codex again to continue this conversation.
|
|
```
|
|
|
|
7. After presenting, note any points where Codex's analysis differs from your own
|
|
understanding. If there is a disagreement, flag it:
|
|
"Note: Claude Code disagrees on X because Y."
|
|
|
|
8. **Synthesis recommendation (REQUIRED).** Emit ONE recommendation line
|
|
summarizing what the user should do based on Codex's consult output, in the
|
|
canonical format the AskUserQuestion judge grades:
|
|
|
|
```
|
|
Recommendation: <action> because <one-line reason that names the most actionable insight from Codex>
|
|
```
|
|
|
|
Examples (the strongest reasons compare Codex's insight against an alternative — different recommendation, status-quo, or another Codex point):
|
|
- `Recommendation: Adopt Codex's sharding suggestion because it eliminates the head-of-line blocking the current writer-pool has, while the cache-layer alternative Codex also floated still has a single-writer hot path.`
|
|
- `Recommendation: Reject Codex's "use SQLite instead" suggestion because the team's Postgres operational experience outweighs the simplicity gain at the projected scale, and Codex's secondary suggestion (read replicas) handles the read-load concern that motivated the SQLite pivot.`
|
|
- `Recommendation: Investigate Codex's flagged migration ordering before D3 lands because it surfaces a real foreign-key cycle that the in-house schema review missed, while the styling concern Codex also raised can wait for a follow-up.`
|
|
|
|
The reason must engage with a specific Codex insight and compare against an alternative (a different recommendation, status-quo, or another Codex point). Generic synthesis ("because Codex raised good points") fails the format. **Never silently auto-decide; always emit the line.**
|
|
|
|
---
|