fix: repair codex and grok headless backends, update default models - #3
Merged
Conversation
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 execstreams its whole session log to stdout: version banner, workdir/model/session-id block,hook:lines, MCP and skill-loadingERRORlines, the echoed prompt, and a trailing token count.codex.shdidexec codex exec "$(cat FILE)"with no output capture, so all of that became the "improved prompt".--output-last-message; only emit the session log on failure, so the caller's rate-limit detection can still cascade.Reading additional input from stdin...and appended a duplicate<stdin>block.--sandbox read-only. The generator previously ran withsandbox: 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 modelslists exactly one model,grok-4.5. The shipped defaultgrok-composer-2.5-fastfails withInvalid params: "unknown model id", so the backend never ran at all.grok.shitself was fine.Defaults and fallback chains now target
grok-4.5. The retiredgrok-composer-*/grok-buildaliases are still accepted rather than deleted — an explicit request cascades togrok-4.5instead 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.shnow 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
awkpass, because an early-exiting reader would SIGPIPE the producer underset -o pipefail(the trap documented inCLAUDE.md).Default generator models
claudesonnetclaude-opus-5grokgrok-composer-2.5-fastgrok-4.5codexgpt-5.5gpt-5.6-terrageminiunchanged.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 fullclaude-opus-5id, withopus-5/opus5registered as aliases for it.Every JSON table was edited alongside its hardcoded Bash twin. Verified identical resolution with and without
jqon the PATH.Tests
smoke-test.shhardcoded the retired ids, so it is updated in the same change. It was tightened, not loosened:grep -q composer) to an exact match ongrok-4.5opus-5normalization and composer-cascade cases82 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.