review and adversarial-review accept --model/-m (handleReviewCommand, valueOptions: ["base", "scope", "model", "cwd"], aliasMap: { m: "model" }), but they pass the raw string straight to executeReviewRun → runAppServerReview → thread/start. normalizeRequestedModel() — the function that resolves MODEL_ALIASES — is only ever called on the task path.
main (1.0.6), plugins/codex/scripts/codex-companion.mjs:
- L103
function normalizeRequestedModel(model) — resolves MODEL_ALIASES (spark → gpt-5.3-codex-spark)
- L773
const model = normalizeRequestedModel(options.model); — inside handleReview (task). The only call site.
- L714
valueOptions: [..., "model", ...] — handleReviewCommand accepts the flag
- L746
model: options.model, — forwarded raw, never normalized
The alias is documented for the runtime in skills/codex-cli-runtime/SKILL.md ("Map spark to --model gpt-5.3-codex-spark") and agents/codex-rescue.md, with nothing marking it as task-only, so --model spark on a review reads as supported.
Repro
node scripts/codex-companion.mjs review --wait --scope working-tree --model spark
Actual (exit 1):
[codex] Codex error: {"type":"error","status":400,"error":{"type":"invalid_request_error",
"message":"The 'spark' model is not supported when using Codex with a ChatGPT account."}}
Expected: the same run the full slug already gives (exit 0, review emitted):
node scripts/codex-companion.mjs review --wait --scope working-tree --model gpt-5.3-codex-spark
Verified 26 Aug 2026 against plugin 1.0.4 with codex-cli 0.149.1 on macOS 15 (arm64), ChatGPT sign-in. Code paths re-checked against main @ 1.0.6 — unchanged.
Why it is worth more than a one-line alias fix
The server message names the account type as the cause, which is wrong here and expensive to chase: the account is fine, the model is fine (the full slug works on the same account seconds later), and the literal string spark never was a model id. openai/codex#15648 is people landing on that same sentence. Anyone who reads the runtime skill, types the documented alias, and hits this has no path from the error text to the real cause.
Suggested fix
Call normalizeRequestedModel(options.model) in handleReviewCommand the way handleReview does, so both command families resolve aliases identically. Happy to send the PR.
Related: #654 (the flag is undocumented for these two commands), #651 / #476 (--effort has the same task-vs-review asymmetry).
reviewandadversarial-reviewaccept--model/-m(handleReviewCommand,valueOptions: ["base", "scope", "model", "cwd"],aliasMap: { m: "model" }), but they pass the raw string straight toexecuteReviewRun→runAppServerReview→thread/start.normalizeRequestedModel()— the function that resolvesMODEL_ALIASES— is only ever called on thetaskpath.main(1.0.6),plugins/codex/scripts/codex-companion.mjs:function normalizeRequestedModel(model)— resolvesMODEL_ALIASES(spark→gpt-5.3-codex-spark)const model = normalizeRequestedModel(options.model);— insidehandleReview(task). The only call site.valueOptions: [..., "model", ...]—handleReviewCommandaccepts the flagmodel: options.model,— forwarded raw, never normalizedThe alias is documented for the runtime in
skills/codex-cli-runtime/SKILL.md("Mapsparkto--model gpt-5.3-codex-spark") andagents/codex-rescue.md, with nothing marking it as task-only, so--model sparkon a review reads as supported.Repro
Actual (exit 1):
Expected: the same run the full slug already gives (exit 0, review emitted):
Verified 26 Aug 2026 against plugin 1.0.4 with
codex-cli0.149.1 on macOS 15 (arm64), ChatGPT sign-in. Code paths re-checked againstmain@ 1.0.6 — unchanged.Why it is worth more than a one-line alias fix
The server message names the account type as the cause, which is wrong here and expensive to chase: the account is fine, the model is fine (the full slug works on the same account seconds later), and the literal string
sparknever was a model id. openai/codex#15648 is people landing on that same sentence. Anyone who reads the runtime skill, types the documented alias, and hits this has no path from the error text to the real cause.Suggested fix
Call
normalizeRequestedModel(options.model)inhandleReviewCommandthe wayhandleReviewdoes, so both command families resolve aliases identically. Happy to send the PR.Related: #654 (the flag is undocumented for these two commands), #651 / #476 (
--efforthas the same task-vs-review asymmetry).