Skip to content

fix: repair codex and grok headless backends, update default models - #3

Merged
owenob1 merged 1 commit into
mainfrom
fix/backend-defaults-2026-07
Jul 31, 2026
Merged

fix: repair codex and grok headless backends, update default models#3
owenob1 merged 1 commit into
mainfrom
fix/backend-defaults-2026-07

Conversation

@owenob1

@owenob1 owenob1 commented Jul 31, 2026

Copy link
Copy Markdown
Owner

Neither the codex nor the grok headless backend could produce a usable prompt. Both root causes were confirmed by probing the CLIs directly, not inferred.

codex — the session log was the prompt

codex exec streams its whole session log to stdout: version banner, workdir/model/session-id block, hook: lines, MCP and skill-loading ERROR lines, the echoed prompt, and a trailing token count. codex.sh did exec codex exec "$(cat FILE)" with no output capture, so all of that became the "improved prompt".

  • Take the agent's final message from --output-last-message; only emit the session log on failure, so the caller's rate-limit detection can still cascade.
  • Close stdin — codex printed Reading additional input from stdin... and appended a duplicate <stdin> block.
  • Run --sandbox read-only. The generator previously ran with sandbox: danger-full-access + approval: never, letting it execute the user's request rather than only improve the prompt — a direct violation of the skill's improvement-only contract.

grok — the default model no longer exists

grok models lists exactly one model, grok-4.5. The shipped default grok-composer-2.5-fast fails with Invalid params: "unknown model id", so the backend never ran at all. grok.sh itself was fine.

Defaults and fallback chains now target grok-4.5. The retired grok-composer-* / grok-build aliases are still accepted rather than deleted — an explicit request cascades to grok-4.5 instead of dead-ending, which preserves user intent rather than silently rewriting it.

grok narration leaked into the XML

Grok prefixed a line like I'll read the full offloaded prompt... before <context>. generate-prompt.sh now drops anything ahead of the first XML tag.

Note this is backend-agnostic — it changes output for every backend, not just grok. Implemented as a single non-exiting awk pass, because an early-exiting reader would SIGPIPE the producer under set -o pipefail (the trap documented in CLAUDE.md).

Default generator models

backend was now
claude sonnet claude-opus-5
grok grok-composer-2.5-fast grok-4.5
codex gpt-5.5 gpt-5.6-terra

gemini unchanged.

The claude CLI rejects the bare string opus-5 (There's an issue with the selected model (opus-5)), so the shipped default is the full claude-opus-5 id, with opus-5 / opus5 registered as aliases for it.

Every JSON table was edited alongside its hardcoded Bash twin. Verified identical resolution with and without jq on the PATH.

Tests

smoke-test.sh hardcoded the retired ids, so it is updated in the same change. It was tightened, not loosened:

  • grok's cascade assertion went from a substring match (grep -q composer) to an exact match on grok-4.5
  • added opus-5 normalization and composer-cascade cases

82 checks green at HEAD → 84 green after. All three backends verified end-to-end, including an explicit negative assertion that no banner/hook/token-count lines survive in codex output.

Neither backend could produce a usable prompt.

codex: `codex exec` streams its whole session log to stdout — version
banner, workdir/model/session-id block, `hook:` lines, MCP and
skill-loading ERROR lines, the echoed prompt, and a trailing token
count — and codex.sh piped all of it through as the improved prompt.
Take the agent's final message from --output-last-message instead, and
only emit the session log on failure so rate-limit detection can still
cascade. Also close stdin (codex was appending a duplicate <stdin>
block) and run --sandbox read-only: the generator previously ran with
danger-full-access + approval never, letting it execute the user's
request rather than only improve the prompt.

grok: the shipped default `grok-composer-2.5-fast` is retired. `grok
models` lists only grok-4.5, and the old id fails with
`Invalid params: "unknown model id"`, so the backend never ran. Point
defaults and chains at grok-4.5; retired composer/grok-build aliases
are still accepted but now cascade to grok-4.5 instead of dead-ending.

grok also prefixed a narration line before <context>. Strip anything
ahead of the first XML tag in generate-prompt.sh — this applies to
every backend, not just grok. Single non-exiting awk pass, because an
early-exiting reader would SIGPIPE the producer under pipefail.

Default generator models: claude -> claude-opus-5, grok -> grok-4.5,
codex -> gpt-5.6-terra. The claude CLI rejects the bare string
`opus-5`, so the shipped default is the full claude-opus-5 id and
`opus-5` is registered as an alias for it.

Every table is edited alongside its hardcoded Bash twin; verified
identical resolution with and without jq on the PATH.

smoke-test.sh hardcoded the retired ids, so it is updated here too:
tightened grok's cascade assertion from a substring match to an exact
match, and added opus-5 normalization and composer-cascade cases.

Suite: 82 checks green at HEAD, 84 green after.
@owenob1
owenob1 merged commit 1543555 into main Jul 31, 2026
1 check passed
@owenob1
owenob1 deleted the fix/backend-defaults-2026-07 branch July 31, 2026 05:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant