fix(site): remember reasoning effort per model on new chat#27457
Conversation
|
/coder-agents-review |
|
Chat: Review posted | View chat Review history
deep-review v0.9.0 | Round 1 | Last posted: Round 1, 7 findings (2 P3, 1 P4, 1 Nit, 3 Note), COMMENT. Review Finding inventoryFinding inventory - PR #27457Findings
Round logRound 1Netero first pass (1 Note, CRF-1) then 13-reviewer panel (bisky, hisoka, mafu-san, mafuuu, pariston, ging-ts, ging-react, gon, leorio, nami, komugi, robin, + meruem wildcard). Panel: 2 P3, 1 P4, 1 Nit, 3 Notes. No P0-P2. Ging-ts, ging-react, gon, robin, mafu-san, nami returned no actionable findings. CRF-2 verified against code (handleModelChange unconditionally sets hasUserSelectedModel=true). Event: COMMENT. Reviewed against f17d488..ca23321. About deep-reviewCRF = Coder Review Finding (P0-P4, Nit, Note)
|
There was a problem hiding this comment.
This is a tight, well-tested fix. The per-model Record plus a localStorage layer cleanly separates the two symptoms (the cross-model leak vs the lack of cross-session memory), and it deliberately closes the stale-value shadowing trap (CRF-22) litigated on the superseded #27377 by validating the stored value against the model's current effort set before it enters the precedence chain. Test density is high (171 test / 65 production LOC) and the three new stories drive the real slider and the real submit payload rather than asserting mock echoes.
Severity count: 0 P0-P2, 2 P3, 1 P4, 1 Nit, 3 Notes.
The two P3s are worth a look before merge. CRF-2: the root-override effort is gated behind !hasValidUserSelectedModel, so selecting your override's own model in the dropdown drops the override effort back to the model default (verified: handleModelChange always sets the flag), which contradicts the PR's "the override still applies when nothing is persisted." CRF-3: effort persists on every slider move rather than on chat creation, so an unsubmitted preview durably outranks the account override next session, asymmetric with the sibling lastModelConfigID commit-on-create behavior. Both are bounded but deserve a deliberate call rather than silent acceptance.
Process note: the precedence and stale-value logic is covered only by Storybook play assertions, and the blocking CI job runs vitest run --project=unit only, so a regression in that chain produces no failing blocking-CI signal. This is a repo-wide infrastructure gap, not introduced here, and the author followed the project's story-based convention; flagged as CRF-1 so the coverage assumption is explicit.
Hisoka, on the diff: "I came looking for a fight. This one held its ground."
🤖 This review was automatically generated with Coder Agents.
DanielleMaywood
left a comment
There was a problem hiding this comment.
Resolutions in 1ed7672:
- CRF-2: fixed. Dropped the
!hasValidUserSelectedModelterm;selectedModel === rootOverrideModelIDalready scopes the override and it sits last in the chain, so a per-model or persisted pick still wins. New storyManualReselectKeepsRootOverrideEffortpins it. - CRF-3: deliberate keep of persist-on-change. It is what "remember the previously selected level" means to a user; persisting only at create would lose the choice when the create fails or the user navigates away. Description already says "selected", not "used".
- CRF-4: the meta-level
beforeEach: localStorage.clear()(line 125) already runs for every story includingSubmitsReasoningEffort, providing the invariant. No story-level clear added; a redundant one on the new story was also removed. - CRF-5: declined. The unit test covers the no-throw contract; the in-memory path is simple and its failure mode benign. Not worth a story.
- CRF-1/6/7: noted, no change (repo-wide CI gap; bounded unpruned keys the reviewer called not worth machinery; single-candidate stale validation the reviewer rated low impact).
When we split the reasoning (thinking) effort selector out of the model config, the New chat page never remembered the previously used effort for a model. The effort was held in a single transient state value: it reset to the model default on every mount and leaked across models, so selecting "high" for model A and "medium" for model B showed "medium" when switching back to A.
Effort is now persisted per model config ID in localStorage (
agents.reasoning-effort.<id>), read on the New chat form, and restored when switching models. The persisted per-model value takes precedence over a root personal model override'sreasoning_effort(the user's own most recent choice wins across sessions); the override still applies when nothing is persisted, and a stored value that is no longer valid for the model's current effort set is ignored so it cannot shadow the override. Storage failures (private mode, quota) degrade gracefully to in-memory-only memory.Scope is deliberately limited to the New chat page. The existing-chat page's
last_reasoning_effortbehavior and the edit path are unchanged from main.Refs CODAGT-799
Supersedes #27377
Note
🤖 This PR was written by Coder Agent on behalf of Danielle Maywood