The picker shows Medium for a specialist running at the global effort
- Dominant language
- TypeScript
- Stars
- 1
- Forks
- 0
- Avg merge
- 1h 21m
- Merged PRs (30d)
- 41
Description
The model picker seeds its Thinking Effort control from the row alone, but the proxy that actually reads the setting falls back to the global one. So a specialist running at the global effort is shown as running at "medium".
Found while reviewing #98. Not caused by it — the seeding line predates it — but #98 changes how long the mismatch lasts, so it is worth its own ticket now rather than later.
## The evidence
The dialog is given the row's value and nothing else. `src/client/components/App.tsx:634` and `src/client/components/DispatchModal.tsx:104`:
```tsx
reasoningEffort={row.reasoningEffort}
```
`src/client/components/ModelDialog.tsx:197` seeds the control from it with a hard-coded default:
```ts
const seeded = reasoningEffort ?? "medium";
```
The daemon does not resolve it that way. `src/daemon/gemini.ts:409-430`:
```ts
let reasoningEffort = "medium";
...
if (row && row.reasoningEffort) {
reasoningEffort = row.reasoningEffort;
} else {
const settings = ...getSettings();
if (settings && settings.reasoningEffort) {
reasoningEffort = settings.reasoningEffort; // <- the picker never consults this
}
}
```
`row.reasoningEffort` is optional (`src/shared/types.ts:66`) and `src/daemon/registry.ts:773` restores it with no default, so it is `undefined` for every specialist whose session record predates the field.
## What it looks like
Set the house-rules effort to **High** (`Settings → Reasoning effort`, `src/client/components/SettingsDialog.tsx:118`). Open the picker on a specialist with no stored effort. The control reads **Medium**. The specialist is running at High.
Before #98 the mismatch was self-correcting in the worst possible way: any model pick wrote `"medium"` onto the row, so the display became true by silently downgrading the specialist. #98 correctly stops writing a value the developer never chose — which means the display now stays wrong indefinitely. Strictly better than before, still wrong.
## Acceptance criteria
- [ ] With a global effort set and a row that has none, the picker shows the global value, not `"medium"`.
- [ ] With the global unset and a row that has none, it shows whatever the daemon would actually use.
- [ ] The displayed value and `gemini.ts`'s resolved value agree in every combination of (row set / row unset) × (global set / global unset).
- [ ] Showing the inherited value does not cause it to be written to the row — leaving the control alone must still send nothing, as #98 established.
- [ ] The new-specialist dialog seeds from the same resolution, so a new tab does not claim an effort it will not get.
## Out of scope
- The resolution logic in `gemini.ts` itself. It is right; the cockpit is the one that disagrees with it.
- Tidying `gemini.ts:410-416`, which carries three comments of somebody reasoning aloud about whether `registry.list()` exists. Real, but its own job.
- Making reasoning effort apply to Anthropic's models.
- Anything about where the control sits — that was #99.
## Verification
```
pnpm typecheck
pnpm test tests/model-picker.test.tsx tests/model-costs.test.tsx tests/dispatch-modal.test.tsx tests/new-session-dialog.test.tsx
```
Manual check a green build will not catch: set the house rules effort to High, open the picker on a tab that has never had an effort set, and confirm High is the one shown as current.
## Related
- #98 — found while reviewing it; changes how persistent this is.
- #99 — same control, different problem.
Contributor guide
Research direction
Start with the seeding logic in src/client/components/ModelDialog.tsx:197 and the row inputs in App.tsx:634 and DispatchModal.tsx:104; compare them with resolution in src/daemon/gemini.ts:409-430 and the row definition in src/shared/types.ts:66. Run the listed picker, dispatch, and new-session tests, then verify that inherited and explicit values display consistently without writing inherited values to rows.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- frontend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100