Skip to content

fix(ui): keep chat model selected after session switch#88380

Merged
steipete merged 1 commit into
openclaw:mainfrom
brokemac79:fix/issue-86597-webchat-model-picker-switch
May 30, 2026
Merged

fix(ui): keep chat model selected after session switch#88380
steipete merged 1 commit into
openclaw:mainfrom
brokemac79:fix/issue-86597-webchat-model-picker-switch

Conversation

@brokemac79

@brokemac79 brokemac79 commented May 30, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Fixes the WebChat model picker display after switching away from a session and back.
  • Binds the model <select> value to the resolved session override so the DOM cannot keep showing the default option while state still points at the persisted override.
  • Adds a focused component regression and a Chromium Control UI E2E regression for the A -> B -> A session switch path.
  • Adds source aliases for private workspace packages in the Control UI E2E harness so the browser app can resolve @openclaw/net-policy/* from source during local Vite E2E runs.

Closes #86597

Real behavior proof

Behavior or issue addressed: WebChat model picker display-only regression from #86597. After selecting bedrock/claude-opus-4.5 in session A, switching to session B, then switching back to session A, the picker should visibly show the selected override instead of Default (GPT-5.5).

Real environment tested: Local Windows checkout of this PR branch (b134fd5533) running the real Control UI source in Chromium through the repo's Vite Control UI E2E harness. This exercises the browser-rendered chat header, session picker, model picker, WebSocket request path, and actual DOM selected value. No live provider credentials are required because this bug is Control UI display state only.

Exact steps or command run after this patch: node scripts/run-vitest.mjs run --config test/vitest/vitest.ui-e2e.config.ts --configLoader runner ui/src/ui/e2e/chat-flow.e2e.test.ts -t "keeps a session model override selected after switching away and back" --reporter=dot --pool=forks --no-file-parallelism

Evidence after fix: Rerun after rebasing onto current main:

RUN  v4.1.7 C:/oc-work/oc86597-prepr

----·-

Test Files  1 passed (1)
Tests  1 passed | 5 skipped (6)
Duration  3.95s

The browser E2E asserts the visible select[data-chat-model-select="true"] value through the user flow:

initial session A select value: ""
after selecting override in session A: "bedrock/claude-opus-4.5"
after switching to session B: ""
after switching back to session A: "bedrock/claude-opus-4.5"

Observed result after fix: The picker remains visibly selected as bedrock/claude-opus-4.5 after switching away from session A and back. Before the fix, the resolved UI state still had currentOverride="bedrock/claude-opus-4.5", but the actual DOM select value stayed "" and displayed the default option.

What was not tested: A live provider call or real Gateway persistence roundtrip was not used, because the issue is limited to Control UI display binding and the browser proof exercises the rendered UI with deterministic Gateway responses. Provider routing, model execution, and Gateway session persistence are intentionally unchanged.

Validation

Latest focused validation after rebasing onto current main:

  • node scripts/run-vitest.mjs run ui/src/ui/views/chat.test.ts -t "keeps the selected model visible after switching away and back to a session" --reporter=dot --pool=forks --no-file-parallelism -> passed.
  • node scripts/run-vitest.mjs run --config test/vitest/vitest.ui-e2e.config.ts --configLoader runner ui/src/ui/e2e/chat-flow.e2e.test.ts -t "keeps a session model override selected after switching away and back" --reporter=dot --pool=forks --no-file-parallelism -> passed.
  • git diff --check origin/main...HEAD -> passed.

Broader validation run before the latest upstream-main churn:

  • node scripts/run-vitest.mjs run ui/src/ui/views/chat.test.ts ui/src/ui/chat-model-select-state.test.ts --reporter=dot --pool=forks --no-file-parallelism -> 2 files passed, 72 tests passed.
  • node scripts/run-vitest.mjs run ui/src/ui/app-chat.test.ts --reporter=dot --pool=forks --no-file-parallelism -> 1 file passed, 58 tests passed.
  • node scripts/run-vitest.mjs run --config test/vitest/vitest.ui-e2e.config.ts --configLoader runner ui/src/ui/e2e/chat-flow.e2e.test.ts --reporter=dot --pool=forks --no-file-parallelism -> 1 file passed, 6 tests passed.
  • node scripts/run-oxlint.mjs --tsconfig config/tsconfig/oxlint.core.json ui/src/test-helpers/control-ui-e2e.ts ui/src/ui/chat/session-controls.ts ui/src/ui/e2e/chat-flow.e2e.test.ts ui/src/ui/views/chat.test.ts --type-aware --report-unused-disable-directives-severity error --threads=1 -> passed.
  • node scripts/run-tsgo.mjs -p tsconfig.core.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/core.tsbuildinfo -> passed.
  • node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.core.test.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/core-test.tsbuildinfo -> passed.
  • codex review --uncommitted -> no actionable regressions found.

Current CI note: the branch was rebased onto current main. The previously red upstream-main type/build failures pass locally on this branch (test/tsconfig/tsconfig.extensions.test.json and tsconfig.plugin-sdk.dts.json). Current main still has an unrelated runtime-config failure in src/config/sessions.cache.test.ts (falls back to full projection when untouched entries need prompt blob repair), which reproduces locally and is outside this PR's four-file WebChat/UI diff. GitHub CI is rerunning on the refreshed head.

Risk

Low. The runtime change is limited to binding the existing resolved model override into the DOM select value. The E2E harness alias only affects local Control UI browser tests and resolves private workspace packages from source for Vite.

@openclaw-barnacle openclaw-barnacle Bot added app: web-ui App: web-ui size: S proof: supplied External PR includes structured after-fix real behavior proof. labels May 30, 2026
@clawsweeper

clawsweeper Bot commented May 30, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed May 30, 2026, 1:19 PM ET / 17:19 UTC.

Summary
The PR binds the WebChat model select value to the resolved session override, adds component and Chromium E2E regressions for the A-to-B-to-A switch path, and adds test-only Vite aliases for the net-policy workspace package.

PR surface: Source +13, Tests +159. Total +172 across 4 files.

Reproducibility: yes. The linked report gives a concrete A-to-B-to-A session-switch path, and the PR adds focused component and Chromium E2E tests that encode the failure mode; I did not run tests because this review is read-only.

Review metrics: none identified.

Merge readiness
Overall: 🦞 diamond lobster
Proof: 🦞 diamond lobster
Patch quality: 🦞 diamond lobster
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Risk before merge

  • [P1] Two broad GitHub check-runs for the latest head were still in progress when inspected, so merge should wait for those to settle or be accounted for.

Maintainer options:

  1. Decide the mitigation before merge
    Merge this focused UI binding fix after the latest head checks settle, then let the linked bug report at [Bug]: WebChat model picker displays default model after switching sessions, even though model override is persisted #86597 close through the PR.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • No ClawSweeper repair lane is needed; the patch has no actionable defect, so maintainers should proceed with normal review and merge once head checks settle.

Security
Cleared: The diff changes a UI binding and test-only Vite aliases; it does not alter secrets handling, dependencies, workflows, package resolution for production, or privileged code execution paths.

Review details

Best possible solution:

Merge this focused UI binding fix after the latest head checks settle, then let the linked bug report at #86597 close through the PR.

Do we have a high-confidence way to reproduce the issue?

Yes. The linked report gives a concrete A-to-B-to-A session-switch path, and the PR adds focused component and Chromium E2E tests that encode the failure mode; I did not run tests because this review is read-only.

Is this the best way to solve the issue?

Yes. Binding the select property to the resolved override with Lit's live directive is the narrowest maintainable fix for a DOM display value that can drift from state without duplicating session-cache logic.

AGENTS.md: found and applied where relevant.

Codex review notes: model gpt-5.5, reasoning high; reviewed against 3fffb34ba0c0.

Label changes

Label changes:

  • add proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes after-fix terminal E2E output and DOM select values for the real browser-rendered Control UI path, and the final head has a successful Real behavior proof check.
  • add rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • remove rating: 🐚 platinum hermit: Current PR rating is rating: 🦞 diamond lobster, so this older rating label is no longer current.

Label justifications:

  • P2: This is a normal-priority WebChat display-state bugfix with limited blast radius and focused regression coverage.
  • rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The PR body includes after-fix terminal E2E output and DOM select values for the real browser-rendered Control UI path, and the final head has a successful Real behavior proof check.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes after-fix terminal E2E output and DOM select values for the real browser-rendered Control UI path, and the final head has a successful Real behavior proof check.
Evidence reviewed

PR surface:

Source +13, Tests +159. Total +172 across 4 files.

View PR surface stats
Area Files Added Removed Net
Source 2 13 0 +13
Tests 2 159 0 +159
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 4 172 0 +172

What I checked:

  • Current main behavior: Current main renders the chat model select with selected option attributes but no select property value binding, which matches the stale DOM value failure described by the linked report. (ui/src/ui/chat/session-controls.ts:813, 3fffb34ba0c0)
  • Patch source: The PR adds .value=${live(currentOverride)} to the model select, so Lit compares against the live DOM value and resets the select when the resolved override changes after session switching. (ui/src/ui/chat/session-controls.ts:814, 38b52d50000c)
  • Component regression: The new component test patches session A to bedrock/claude-opus-4.5, renders session B, then renders session A again and asserts the select value remains the override. (ui/src/ui/views/chat.test.ts:2343, 38b52d50000c)
  • Browser regression: The new mocked Gateway E2E exercises the rendered Control UI in Chromium and asserts the DOM select input value after switching away from and back to session A. (ui/src/ui/e2e/chat-flow.e2e.test.ts:231, 38b52d50000c)
  • Dependency contract: Lit 3.3.3's live directive is explicitly intended for property bindings where the live DOM value may differ from Lit's previous committed value, including <input .value=${live(x)}>-style bindings.
  • Validation/proof status: Unauthenticated GitHub check-run inspection for head 38b52d5 showed Real behavior proof, checks-node-core-ui, lint/type/build-related checks, and the relevant fast checks succeeding, with two broad check-runs still in progress when inspected. (38b52d50000c)

Likely related people:

  • steipete: Available current-main history points the WebChat session-controls, chat-model select state, and adjacent tests to commit 697bafa9c97d65eadd9984522a3a7d9bc1f0cc39. (role: recent area contributor; confidence: medium; commits: 697bafa9c97d; files: ui/src/ui/chat/session-controls.ts, ui/src/ui/chat-model-select-state.ts, ui/src/ui/views/chat.test.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. P2 Normal backlog priority with limited blast radius. labels May 30, 2026
@brokemac79
brokemac79 force-pushed the fix/issue-86597-webchat-model-picker-switch branch from 16cb7c1 to 3dada17 Compare May 30, 2026 16:34
@openclaw-barnacle openclaw-barnacle Bot added triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. and removed proof: sufficient ClawSweeper judged the real behavior proof convincing. proof: supplied External PR includes structured after-fix real behavior proof. labels May 30, 2026
@brokemac79
brokemac79 force-pushed the fix/issue-86597-webchat-model-picker-switch branch from 3dada17 to 4ea53f0 Compare May 30, 2026 16:42
@openclaw-barnacle openclaw-barnacle Bot added proof: supplied External PR includes structured after-fix real behavior proof. and removed triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. labels May 30, 2026
@brokemac79
brokemac79 force-pushed the fix/issue-86597-webchat-model-picker-switch branch from 4ea53f0 to b134fd5 Compare May 30, 2026 16:46
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 30, 2026
@brokemac79
brokemac79 force-pushed the fix/issue-86597-webchat-model-picker-switch branch from b134fd5 to 38b52d5 Compare May 30, 2026 17:13
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 30, 2026
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. labels May 30, 2026
@steipete steipete self-assigned this May 30, 2026
@steipete
steipete force-pushed the fix/issue-86597-webchat-model-picker-switch branch from 38b52d5 to 01821c4 Compare May 30, 2026 19:47
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 30, 2026
@steipete

Copy link
Copy Markdown
Contributor

Verification for rebased head 01821c40fe8cf06055771c5940c78d8afc981a2a:

  • node scripts/run-vitest.mjs run ui/src/ui/views/chat.test.ts -t "keeps the selected model visible after switching away and back to a session" --reporter=dot --pool=forks --no-file-parallelism
  • node scripts/run-vitest.mjs run --config test/vitest/vitest.ui-e2e.config.ts --configLoader runner ui/src/ui/e2e/chat-flow.e2e.test.ts -t "keeps a session model override selected after switching away and back" --reporter=dot --pool=forks --no-file-parallelism
  • .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main -> clean, no accepted/actionable findings
  • GitHub CI run 26693271626 is green, including the previously failing checks-node-agentic-commands-doctor and checks-node-core-runtime-infra-state lanes.

Proof gap: no manual browser pass; the changed behavior is covered by the focused unit and UI e2e regression tests above.

@steipete steipete left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved after focused regression proof, clean autoreview, and green CI on rebased head.

@steipete
steipete merged commit d11e82a into openclaw:main May 30, 2026
83 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app: web-ui App: web-ui P2 Normal backlog priority with limited blast radius. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. size: S status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: WebChat model picker displays default model after switching sessions, even though model override is persisted

2 participants