Skip to content

fix: emit a thinking-effort flag for grok, which silently dropped it - #5858

Merged
atomantic merged 1 commit into
mainfrom
next/issue-5854
Sep 2, 2026
Merged

fix: emit a thinking-effort flag for grok, which silently dropped it#5858
atomantic merged 1 commit into
mainfrom
next/issue-5854

Conversation

@atomantic

Copy link
Copy Markdown
Owner

Summary

A thinking-effort level saved against a grok provider never reached the CLI — and the effort select was hidden, so nothing revealed the setting was inert. This affected task pins, pipeline stages, scheduled tasks, and reviewer rows alike.

effortLevelsForProvider had no grok arm and returned null, which short-circuits resolveCliEffort so buildEffortArgs emits nothing. Grok has accepted an effort flag all along — --reasoning-effort <EFFORT>, aliased --effort, which is exactly what buildEffortArgs already emits for every non-codex/cursor vendor. Only the ladder was missing.

The ladder is read off the CLI rather than guessed:

$ grok --reasoning-effort bogus -p hi
--effort/--reasoning-effort: unknown effort level 'bogus'; use one of: xhigh, high, medium, low

No max/minimal, so a level saved against claude or codex clamps to xhigh, the same contract agy's narrower ladder already has.

  • GROK_EFFORT_LEVELS + isGrokProvider in server/lib/providerModels.js, mirrored in client/src/utils/providers.js. The predicate is defined inline rather than imported from grok.js — that module imports providerModels, so importing back would cycle. The bare grok id is the HTTP API provider and is excluded: no CLI, no flag to carry a level.
  • hasEffortFlag now also matches --reasoning-effort. Grok's parser accepts a duplicate flag and takes the last one, so without this a user who baked --reasoning-effort high into their provider args got a second injected --effort that silently overrode their pin — the opposite of that function's documented "a baked pin wins" contract.

Two surfaces picked it up on their own

REVIEWER_EFFORT_LEVELS is derived from effortLevelsForProvider ("a CLI that gains or loses a tier moves both at once"), so grok became an effort-selectable reviewer server-side with no edit. Its hand-written client mirror in reviewerPins.js needed the matching entry. The Effort select and reviewer picker then render grok's tiers with no component change — the design working as intended.

Tests that had used grok as their canonical "provider with no effort control" now use kimi, which genuinely has none, so each keeps its original point rather than being deleted.

Test plan

  • server/lib/providerModels.test.js — ladder for the grok-cli/grok-tui ids, a path-configured command, and Grok.exe; null for the grok API provider. resolveCliEffort clamps max/ultraxhigh and minimallow. buildEffortArgs emits ['--effort', <level>], and emits nothing when --reasoning-effort is already baked in (both separated and joined forms). hasEffortFlag gets the long form in both shapes plus its dangling/valueless cases.
  • client/src/utils/providers.test.js — the server-mirror parity cases now assert the ladder on both implementations, including the clamp.
  • server/lib/cosValidation.test.js — grok as an effort-selectable reviewer: reviewerEffortLevels, EFFORT_SELECTABLE_REVIEWERS, drop-don't-clamp on max, the settings-scalar fold, and reviewerEffortArgs.
  • server/services/agentTuiSpawning.test.js — grok's TUI gets the flag (it is a root-level flag on the same binary), and an out-of-ladder level clamps.
  • clientEffortSelect and ReviewerPicker offer grok low|medium|high|xhigh and no max.
  • Full suites: server 37,478 passed / 0 failed; client 10,769 passed. The residual red in both runs is pre-existing load contention, green in isolation — server imageGen.multipart (20/20 alone) and five client page suites (190/190 alone), the class tracked in ChiefOfStaff page tests flake under full-suite load by querying an unsettled page mount #5857.

Closes #5854

…ly dropped it

A level saved against a grok provider — a task pin, a pipeline stage, a
scheduled task, or a reviewer row — never reached the CLI, and the effort select
was hidden, so nothing revealed the setting was inert.

`effortLevelsForProvider` had no grok arm and returned null, which short-circuits
`resolveCliEffort` and makes `buildEffortArgs` emit nothing. Grok has accepted an
effort flag all along: `--reasoning-effort <EFFORT>`, aliased `--effort`, which
is exactly what `buildEffortArgs` already emits for every non-codex/cursor
vendor. Only the ladder was missing.

The ladder is grok's own, read off the CLI rather than guessed —
`grok --reasoning-effort bogus` answers `use one of: xhigh, high, medium, low`.
There is no `max`/`minimal`, so a level saved against claude or codex clamps to
`xhigh` the way an out-of-range level already clamps on agy.

- `GROK_EFFORT_LEVELS` + `isGrokProvider` in `server/lib/providerModels.js`,
  mirrored in `client/src/utils/providers.js`. The predicate is defined inline
  rather than imported from `grok.js`, which imports providerModels and would
  cycle. The bare `grok` id is the HTTP API provider and is excluded — no CLI,
  no flag to carry a level.
- `hasEffortFlag` now also recognizes `--reasoning-effort`. Grok's parser accepts
  a duplicate flag and takes the last one, so without this a user who baked
  `--reasoning-effort high` into their provider args would get a second injected
  `--effort` that silently overrode their pin — the opposite of that function's
  documented "a baked pin wins" contract.

Two surfaces picked the ladder up on their own, which is the design working:
`REVIEWER_EFFORT_LEVELS` derives from `effortLevelsForProvider`, so grok became
an effort-selectable reviewer server-side; its hand-written client mirror in
`reviewerPins.js` needed the matching entry. The Effort select and reviewer
picker then render grok's tiers with no component change.

Tests that had used grok as their canonical "provider with no effort control"
now use kimi, which genuinely has none, so each keeps its original point.

Closes #5854
@atomantic
atomantic merged commit 5cdaaf5 into main Sep 2, 2026
7 checks passed
@atomantic
atomantic deleted the next/issue-5854 branch September 2, 2026 17:27
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.

Grok CLI providers silently drop a saved thinking-effort level

1 participant