Skip to content

VALID_REASONING_EFFORTS rejects max and ultra locally, so the flagship model's top two reasoning tiers are unreachable from the plugin #751

Open

Description

@rjredelm

Summary

normalizeReasoningEffort() rejects max and ultra before the CLI is ever invoked, so
the top two reasoning tiers of the current flagship model are unreachable from the plugin.

scripts/codex-companion.mjs:71 (v1.0.6):

const VALID_REASONING_EFFORTS = new Set(["none", "minimal", "low", "medium", "high", "xhigh"]);

#485 notes the --effort hint omits these values and files it as cosmetic. The hint is
the smaller half: this Set is a hard gate, and it fails the request locally with no API
call, so raising it is a functional fix rather than a docs one.

Current levels

From codex debug models → supported_reasoning_levels, listed models only:

model supported reasoning levels
gpt-6-astra low, medium, high, xhigh, max, ultra
gpt-5.6-sol low, medium, high, xhigh, max, ultra
gpt-5.6-terra low, medium, high, xhigh, max, ultra
gpt-5.6-luna low, medium, high, xhigh, max
gpt-5.5 low, medium, high, xhigh
gpt-5.4-mini low, medium, high, xhigh

ultra is described in the catalog as "Maximum reasoning with automatic task delegation"
— a distinct capability, and the flagship's headline mode, not just one more notch.

Repro

$ node scripts/codex-companion.mjs task --model gpt-6-astra --effort ultra "Reply with the single word: ok"
Unsupported reasoning effort "ultra". Use one of: none, minimal, low, medium, high, xhigh.
exit 1

Verified after widening the Set

Adding max and ultra to VALID_REASONING_EFFORTS (no other change), values read from
the session rollout JSONL rather than exit codes:

invocation recorded model recorded reasoning_effort result
--model gpt-6-astra --effort ultra gpt-6-astra ultra exit 0, ~6 s, 17,210 tokens, no error lines
--model gpt-5.6-luna --effort max gpt-5.6-luna max exit 0
--model gpt-5.6-luna --effort ultra gpt-5.6-luna ultra exit 0

The gate still discriminates after widening: --effort bogus is rejected locally, exit 1,
no API call.

Two things worth a maintainer's eye

1. Per-model effort validity is not enforced on this path. Row 3 is ultra on
gpt-5.6-luna, whose catalog entry stops at max. It was accepted and recorded rather
than rejected. If per-model validity is meant to hold, nothing on this path enforces it.
(The rollout shows the request carried ultra; it does not show whether the server
clamped it.)

2. none and minimal are accepted by the plugin but appear in no listed model's
supported_reasoning_levels.
Same drift, opposite direction — possibly legacy values
worth pruning in the same pass.

Suggested fix

Immediate: add max and ultra to VALID_REASONING_EFFORTS, and update the three places
that spell the list out — the usage string (scripts/codex-companion.mjs:82), the error
text (:124), commands/rescue.md:3, and skills/codex-cli-runtime/SKILL.md:35.

Better: derive the set from codex debug models, cached with a static fallback. This Set
and MODEL_ALIASES (see #687) are both hardcoded copies of vocabularies the CLI already
resolves at runtime, and both have now drifted behind it. A plugin release currently pins
a model vocabulary that the API can invalidate at any time, and the user sees either a 400
or a local rejection naming values that are no longer the real set.

Environment

  • Plugin codex v1.0.6 (db52e28f4d9ded852ab3942cea316258ae4ef346)
  • codex-cli 0.153.4
  • macOS 25.6.0 (arm64), Node v24.15.0, ChatGPT sign-in

Related: #485 (hint omission, filed as cosmetic), #687 (the MODEL_ALIASES half of the
same drift), #476 / #651 (--effort task-vs-review asymmetry).

Activity

  1. aleozlx commented on Sep 12, 2026

    @aleozlx

    Independent confirmation on Windows, plus a data point that complicates the suggested fix:
    for one model there are three disagreeing vocabularies, and the catalog is not a superset
    of the API's.

    Hitting your point 2 from the other side — --effort minimal passes the plugin's local gate
    and is then rejected by the API:

    $ node scripts/codex-companion.mjs task --background --fresh --effort minimal "Reply with exactly: OK"
    $ node scripts/codex-companion.mjs result <job-id>
    {
      "type": "error",
      "error": {
        "type": "invalid_request_error",
        "code": "unsupported_value",
        "message": "Unsupported value: 'minimal' is not supported with the 'gpt-5.6-terra' model. Supported values are: 'none', 'low', 'medium', 'high', 'xhigh', and 'max'.",
        "param": "reasoning.effort"
      },
      "status": 400
    }
    

    Lining that server message up against the other two sources, all for gpt-5.6-terra:

    source what it says is valid
    VALID_REASONING_EFFORTS (plugin) none, minimal, low, medium, high, xhigh
    codex debug models (catalog) low, medium, high, xhigh, max, ultra
    the API's own 400 text none, low, medium, high, xhigh, max

    No two agree, and every value is contested by something:

    • minimal — plugin only. Rejected by the API, as above.
    • none — plugin and API, absent from the catalog.
    • max — catalog and API, blocked by the plugin. This issue.
    • ultra — catalog only. The API's error text does not list it for this model, yet your
      table shows ultra completing on gpt-6-astra and gpt-5.6-luna.

    The last two rows are the ones I would flag for the "derive it from codex debug models"
    plan. Deriving strictly from the catalog would drop none, which the API names as supported,
    and would offer ultra, which the API's own enumeration for this model omits even though it
    demonstrably runs. So the error text is not a reliable enumeration either — it is a third
    approximation rather than the authority, and a derived Set would trade one drift for another.

    That is an argument for the immediate half of your fix over the clever half: widening the Set
    is a straightforward correctness win, whereas picking a single authoritative source needs one
    that is actually authoritative, and none of these three is. The gate may be better as a
    typo-catcher that rejects unknown shapes while letting the API arbitrate per-model validity,
    since it already cannot enforce that (your point 1).

    Environment

    Windows 11 (26200), plugin codex v1.0.5, codex-cli 0.153.4, Node v24.19.0, ChatGPT
    sign-in, model = "gpt-5.6-terra" pinned in ~/.codex/config.toml by the Codex desktop app.

    Tangential, since this was my trigger too: when that 400 comes back, status reports the
    whole reason as Summary: {. Filed separately as #757 — unrelated to the vocabulary, but it
    is why the rejection took a while to see.

  2. wagneripjr commented on Oct 21, 2026

    @wagneripjr

    The three open PRs for this (#616, #637, #761) each add max and ultra to VALID_REASONING_EFFORTS. That fixes today's symptom but keeps the root cause: a hardcoded copy of a list that Codex already validates server-side, and that varies per model. It will go stale again with the next tier.

    Proposal: drop the allowlist and let Codex validate. normalizeReasoningEffort becomes trim + lowercase, --effort forwards whatever was asked.

    Unsupported values still fail fast with a clearer, model-aware message. With Codex CLI 0.163.0 on the default model:

    $ node scripts/codex-companion.mjs task --effort bogus "Reply with the single word ok."
    [codex] Codex error: {"type":"error","error":{"message":"Invalid response.create payload: Invalid value: 'bogus'. Supported values are: 'none', 'minimal', 'low', 'medium', 'high', 'xhigh', and 'max'.","type":"invalid_request_error",...},"status":400}
    [codex] Turn failed.
    

    Note ultra is absent there: support genuinely is per-model, so any local list is wrong for some model either way.

    Implementation with tests (per-effort forwarding incl. max/ultra/case-normalisation, unset when omitted, --resume and --background paths) and help/skill/README updates: wagneripjr@0630113

    Happy to open it as a PR (minus the version bump) if maintainers prefer this approach over extending the list.

  3. danielkassar commented on Nov 3, 2026

    @danielkassar

    I can confirm this issue still affects openai/codex-plugin-cc as of November 3, 2026.

    Environment:

    • macOS
    • Claude Code Desktop / Claude Code 2.1.309
    • Codex CLI 0.166.0
    • ChatGPT authentication

    Reproduction:

    Delegating to gpt-6-luna with --effort max fails before Codex is invoked.

    The installed codex-companion.mjs only accepts none, minimal, low, medium, high, and xhigh.

    The Codex CLI configuration supports max, but the plugin rejects it locally.

    Update — Local workaround confirmed

    I manually extended VALID_REASONING_EFFORTS in the installed codex-companion.mjs to include max and ultra.

    After applying the change:

    • Delegation to gpt-6-luna with --effort max completed successfully.
    • Codex returned the expected response: Hello from Codex. Delegation successful.
    • The completed Codex session's rollout log confirmed gpt-6-luna with reasoning_effort: max.
    • No fallback model was used.
    • Execution was read-only, with no repository modifications.

    This confirms that the plugin's local validation was the blocker in my environment, rather than Codex lacking support for max.

    Note: I verified max, but have not independently tested ultra.

    The workaround modifies the installed plugin cache and may be overwritten by plugin updates.

    It would be helpful to merge an upstream fix, ideally avoiding a hardcoded reasoning-effort allowlist that can become outdated as new models and effort levels are introduced.

    Are there plans to merge one of the existing fixes (#616, #637, or #761)?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions