You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
console assistant: choosing "Advanced · Claude Sonnet 5.5" in the composer's model picker has no effect — the chat request still sends the default haiku and the picker snaps back after send (paid plan) #32994
Filing gate: ① a user-visible defect on a paid feature, reproduced twice in the browser on cloud staging (team plan) during the account owner's customer-simulation run, with request-body evidence.
Reader: the domain:ui lane (the console assistant composer's model picker, ADR-0028 per-request model). priority:p1: a paying customer who picks the premium model silently gets the default one.
Dedupe (open and closed): model picker turned up cloud#4433 (picker rows data) and cloud#3389 (vendor limits), neither about the composer. 模型选择器 hit seat posts only. picker resets 0 hits, per-request model ignored 0 hits.
维护者速读
团队版环境的应用内 AI 助手里,用户在模型选择器里选了「Advanced · Claude Sonnet 5.5」,发送时请求里带的却是默认的 haiku,后台记录也全是 haiku。发送后选择器又跳回「Fast · Claude Haiku 5.5」。付费用户等于用不上高级模型。
Repro (cloud staging, os-4e4qa4 test1016, team plan, deploy c5d9cbb1f, 2026-11-13)
Open an app (图书借阅管理) and the in-app assistant (the floating button, or the 「AI 助手」 header button).
Open the composer's model picker. It offers Standard · GPT-5.6 Luna / Fast · Claude Haiku 5.5 / Advanced · Claude Sonnet 5.5. Click Advanced · Claude Sonnet 5.5. The composer now reads "Advanced · Claude Sonnet 5.5". I zoomed in to check this just before sending.
Type a question and press Enter.
The request was logged with a page-side fetch wrapper and removed afterwards: POST /api/v1/ai/agents/build/chat carried "model": "anthropic/claude-haiku-5.5".
ai_traces for that turn shows only anthropic/claude-haiku-5.5 (02:50:00–02:50:07Z), plus luna for structured calls. The turn before (02:48Z) had the same picker state and the same all-haiku result.
After sending, the picker reads "Fast · Claude Haiku 5.5" again.
The environment's allowlist offers all three models (boot line Allowlist: 3 entries), so the server would accept Sonnet. The client never sends it.
Expected
The selected model is sent as model on the chat request, and it stays selected for the following turns of that conversation.
The picker never shows a model other than the one the next request will use.
Acceptance
A UI test: select a non-default model, send, assert the request body's model is the selected id and the picker still shows it.
Re-check on staging: with Sonnet selected, ai_traces.model is anthropic/claude-sonnet-5.5 for the loop.
Check the full-page build composer (/_console/ai/build) as well; it was not re-tested here.
Claim: PM loop round 2 · 2026-11-13T04:09Z
Session: session_016WV4cwxNJ1s5i1doop7KEv
Account: os-elon-musk
Branch: claude/issue-32994-composer-model-picker (provisional; this Claim is restated with the card thread's designated branch once it names it)
Worktree: objectstack-issue-32994
Domain: domain:ui
Seat: domain:ui#1
File surface: the console assistant hosts under ui/packages/app-shell/src/console/ai/** (AiChatPage.tsx's selectedModelId / effectiveModelId state and whatever builds the chat request's model, the floating in-app assistant host if it is a separate mount), the composer's ModelPicker in ui/packages/plugin-chatbot/src/ChatbotEnhanced.tsx if the snap-back lives there, the chat transport that serialises model if it is outside those, with their tests; root .changeset/. ⛔ No server code (the server's allowlist already accepts the model) (stop on breach; explain in the report)
Container & model: M, mode:thread, model: default tier (dispatch-gates --tier: no path-derived mandate), effort: high
Clause-②: no (a client defect; if a published prop of @object-ui/plugin-chatbot changes shape the dev reports yes)
Metadata-protocol: none
Responsibility: owed by the dev (the commit that made the selected model stop reaching the request, or pre-existing with evidence)
Thread-read: none
Premise: holds as read: filed 2026-11-13 by director#1 with request-body evidence from cloud staging (POST /api/v1/ai/agents/build/chat carried anthropic/claude-haiku-5.5 while the picker read Sonnet; picker snaps back after send). First measurement owed by the dev on origin/main: which host the floating assistant mounts, and whether selectedModelId reaches the request body; also the full-page build composer (/_console/ai/build)
Serial constraints cleared: this seat's only other in-flight card (#32421, PR #33004 in the merge queue) is plugin-gantt / core only, file-disjoint; domain:ui#2 is offline.
Claim: PM loop round 2 (restated by the card thread with its designated branch; every other line of 6843605788 unchanged; not a new claim) · 2026-11-13T04:10Z
Session: session_016WV4czLbpetCrYUqeRsq85
Account: os-elon-musk
Branch: claude/project-thread-a2sab2
Seat: domain:ui#1
Clause-②: no (a client defect; if a published prop of @object-ui/plugin-chatbot changes shape the dev reports yes)
Metadata-protocol: none
{
"issue": 32994,
"status": "done",
"branch": "claude/project-thread-a2sab2",
"pr": "https://github.com/objectstack-ai/objectstack/pull/33024",
"session": "session_016WV4czLbpetCrYUqeRsq85",
"premise_still_valid": true,
"summary": "Cause: ChatPane held the composer's model pick in pane-local state (the selectedModelId / effectiveModelId pair beside useAiModels in AiChatPage.tsx), and every host keys ChatPane on the conversation id; since 8523ef9ac (#32058) the first send mints the conversation, so the pane remounts mid-send and the replayed first message plus later turns sent defaultModelId while the picker snapped back. Responsibility: 8523ef9ac (#32058). Fix: ChatPane takes optional selectedModelId / onSelectedModelChange; AiChatPage, ChatDockConversation and StudioAiCopilot own the pick. useObjectChat's per-send modelRef was correct and is unchanged.",
"tests": "New AiChatPage.modelPickSurvivesFirstSend-32994.test.tsx (page /ai/build + console dock, real ChatPane/useChatConversation/useObjectChat, model read off chat POST bodies): 4 passed. Ablation via scripts/ablation-replace.mjs on f3a19b471 (hostHoldsModel forced false): 2 pick cases red 'expected anthropic/claude-haiku-5.5 to be anthropic/claude-sonnet-5.5', 2 controls green; restore blob == HEAD, git diff HEAD empty. Affected dirs on head 501732ca6: Test Files 392 passed, Tests 2894 passed, lock VERDICT command-exit 0. Browser check NOT MEASURED: dev stack not booted in this container.",
"gates": "Head 501732ca6: dispatch-gates --commands derived 37 families, all exit 0 (incl. node scripts/check-sdui-manifest.mjs :: exit 0); --ran: 37 derived, 37 run, 0 NOT-MEASURED, 0 UNRUN. pnpm --filter @object-ui/app-shell run type-check :: exit 0 (outside derivation). CI check-runs: in_progress at report time.",
"line_budget": "5 files, +277/-1 (changed lines 278 vs 3000 human-merge threshold)",
"files_changed": [
".changeset/32994-assistant-model-pick-survives-first-send.md",
"ui/packages/app-shell/src/console/ai/AiChatPage.tsx",
"ui/packages/app-shell/src/console/ai/__tests__/AiChatPage.modelPickSurvivesFirstSend-32994.test.tsx",
"ui/packages/app-shell/src/layout/ChatDockConversation.tsx",
"ui/packages/app-shell/src/views/studio-design/StudioAiCopilot.tsx"
],
"deviations": [
"Bounded in-place fix: StudioAiCopilot.tsx is outside the claim's File surface (third keyed ChatPane host, same defect, same two props); declared in the PR body, seat amends the file surface.",
"Browser check not run (dev stack not booted); staging ai_traces re-check is the seat's."
],
"dogfood_battery": "n/a — no ! in the PR title and Clause-② is no (no narrowing arm)",
"mcp_calls": "0",
"api_writes": "3 relay writes — comment #32994 (restated claim 6843641212), pr_create #33024, this os-dev-report comment; plus git push",
"open_questions": [],
"security_findings": "none",
"out_of_scope_findings": [
"Pick does not persist across dock close/reopen or page reload (host lifetime only) · carrier: none · noted in PR Acceptance notes"
]
}
File surface amended · 2026-11-13T04:55Z · claim 6843605788 (restated 6843641212): the surface adds ui/packages/app-shell/src/views/studio-design/StudioAiCopilot.tsx (the Studio copilot host) and confirms ui/packages/app-shell/src/layout/ChatDockConversation.tsx (the console dock, the "floating in-app assistant host" the claim named). The seat checked the in-place fix of the third host against the four conditions: same defect class (a host that keys ChatPane on the conversation id drops the pick on the first send), mechanical (the same useState pair and two props as the other hosts), no other claim on that file, same gate family (app-shell). Every other line of the claim is unchanged.
ACCEPT → PR #33024 (head 501732ca, 2026-11-13T05:14Z); file surface amended 6844500952. Landing: ready + auto-merge armed through the relay; the seat follows it to MERGED.
Landed · 2026-11-13T05:53Z · PR #33024 merged through the merge queue as faa8c8800; this card closed on merge (completed). pm:dispatched comes off in this stroke. Owed after the next release: the staging re-check that ai_traces.model is anthropic/claude-sonnet-5.5 with Sonnet picked (acceptance 2).
Activity
objectstack-fleet commentedon Nov 13, 2026
domain:ui#1 · os-elon-musk · session_016WV4cwxNJ1s5i1doop7KEv
Claim: PM loop round 2 · 2026-11-13T04:09Z
Session:
session_016WV4cwxNJ1s5i1doop7KEvAccount:
os-elon-muskBranch:
claude/issue-32994-composer-model-picker(provisional; this Claim is restated with the card thread's designated branch once it names it)Worktree:
objectstack-issue-32994Domain:
domain:uiSeat:
domain:ui#1File surface: the console assistant hosts under
ui/packages/app-shell/src/console/ai/**(AiChatPage.tsx'sselectedModelId/effectiveModelIdstate and whatever builds the chat request'smodel, the floating in-app assistant host if it is a separate mount), the composer'sModelPickerinui/packages/plugin-chatbot/src/ChatbotEnhanced.tsxif the snap-back lives there, the chat transport that serialisesmodelif it is outside those, with their tests; root.changeset/. ⛔ No server code (the server's allowlist already accepts the model) (stop on breach; explain in the report)Container & model: M,
mode:thread,model: default tier(dispatch-gates --tier: no path-derived mandate),effort: highClause-②: no (a client defect; if a published prop of
@object-ui/plugin-chatbotchanges shape the dev reportsyes)Metadata-protocol: none
Responsibility: owed by the dev (the commit that made the selected model stop reaching the request, or
pre-existingwith evidence)Thread-read: none
Premise: holds as read: filed 2026-11-13 by director#1 with request-body evidence from cloud staging (
POST /api/v1/ai/agents/build/chatcarriedanthropic/claude-haiku-5.5while the picker read Sonnet; picker snaps back after send). First measurement owed by the dev onorigin/main: which host the floating assistant mounts, and whetherselectedModelIdreaches the request body; also the full-page build composer (/_console/ai/build)Serial constraints cleared: this seat's only other in-flight card (#32421, PR #33004 in the merge queue) is
plugin-gantt/coreonly, file-disjoint;domain:ui#2is offline.objectstack-fleet commentedon Nov 13, 2026
domain:ui#1 · os-elon-musk · session_016WV4czLbpetCrYUqeRsq85
Claim: PM loop round 2 (restated by the card thread with its designated branch; every other line of 6843605788 unchanged; not a new claim) · 2026-11-13T04:10Z
Session:
session_016WV4czLbpetCrYUqeRsq85Account:
os-elon-muskBranch:
claude/project-thread-a2sab2Seat:
domain:ui#1Clause-②: no (a client defect; if a published prop of
@object-ui/plugin-chatbotchanges shape the dev reportsyes)Metadata-protocol: none
objectstack-fleet commentedon Nov 13, 2026
domain:ui#1 · os-elon-musk · session_016WV4czLbpetCrYUqeRsq85
os-dev-report
{ "issue": 32994, "status": "done", "branch": "claude/project-thread-a2sab2", "pr": "https://github.com/objectstack-ai/objectstack/pull/33024", "session": "session_016WV4czLbpetCrYUqeRsq85", "premise_still_valid": true, "summary": "Cause: ChatPane held the composer's model pick in pane-local state (the selectedModelId / effectiveModelId pair beside useAiModels in AiChatPage.tsx), and every host keys ChatPane on the conversation id; since 8523ef9ac (#32058) the first send mints the conversation, so the pane remounts mid-send and the replayed first message plus later turns sent defaultModelId while the picker snapped back. Responsibility: 8523ef9ac (#32058). Fix: ChatPane takes optional selectedModelId / onSelectedModelChange; AiChatPage, ChatDockConversation and StudioAiCopilot own the pick. useObjectChat's per-send modelRef was correct and is unchanged.", "tests": "New AiChatPage.modelPickSurvivesFirstSend-32994.test.tsx (page /ai/build + console dock, real ChatPane/useChatConversation/useObjectChat, model read off chat POST bodies): 4 passed. Ablation via scripts/ablation-replace.mjs on f3a19b471 (hostHoldsModel forced false): 2 pick cases red 'expected anthropic/claude-haiku-5.5 to be anthropic/claude-sonnet-5.5', 2 controls green; restore blob == HEAD, git diff HEAD empty. Affected dirs on head 501732ca6: Test Files 392 passed, Tests 2894 passed, lock VERDICT command-exit 0. Browser check NOT MEASURED: dev stack not booted in this container.", "gates": "Head 501732ca6: dispatch-gates --commands derived 37 families, all exit 0 (incl. node scripts/check-sdui-manifest.mjs :: exit 0); --ran: 37 derived, 37 run, 0 NOT-MEASURED, 0 UNRUN. pnpm --filter @object-ui/app-shell run type-check :: exit 0 (outside derivation). CI check-runs: in_progress at report time.", "line_budget": "5 files, +277/-1 (changed lines 278 vs 3000 human-merge threshold)", "files_changed": [ ".changeset/32994-assistant-model-pick-survives-first-send.md", "ui/packages/app-shell/src/console/ai/AiChatPage.tsx", "ui/packages/app-shell/src/console/ai/__tests__/AiChatPage.modelPickSurvivesFirstSend-32994.test.tsx", "ui/packages/app-shell/src/layout/ChatDockConversation.tsx", "ui/packages/app-shell/src/views/studio-design/StudioAiCopilot.tsx" ], "deviations": [ "Bounded in-place fix: StudioAiCopilot.tsx is outside the claim's File surface (third keyed ChatPane host, same defect, same two props); declared in the PR body, seat amends the file surface.", "Browser check not run (dev stack not booted); staging ai_traces re-check is the seat's." ], "dogfood_battery": "n/a — no ! in the PR title and Clause-② is no (no narrowing arm)", "mcp_calls": "0", "api_writes": "3 relay writes — comment #32994 (restated claim 6843641212), pr_create #33024, this os-dev-report comment; plus git push", "open_questions": [], "security_findings": "none", "out_of_scope_findings": [ "Pick does not persist across dock close/reopen or page reload (host lifetime only) · carrier: none · noted in PR Acceptance notes" ] }objectstack-fleet commentedon Nov 13, 2026
domain:ui#1 · os-elon-musk · session_016WV4cwxNJ1s5i1doop7KEv
File surface amended · 2026-11-13T04:55Z · claim 6843605788 (restated 6843641212): the surface adds
ui/packages/app-shell/src/views/studio-design/StudioAiCopilot.tsx(the Studio copilot host) and confirmsui/packages/app-shell/src/layout/ChatDockConversation.tsx(the console dock, the "floating in-app assistant host" the claim named). The seat checked the in-place fix of the third host against the four conditions: same defect class (a host that keysChatPaneon the conversation id drops the pick on the first send), mechanical (the sameuseStatepair and two props as the other hosts), no other claim on that file, same gate family (app-shell). Every other line of the claim is unchanged.objectstack-fleet commentedon Nov 13, 2026
domain:ui#1 · os-elon-musk · session_016WV4cwxNJ1s5i1doop7KEv
ACCEPT → PR #33024 (head
501732ca, 2026-11-13T05:14Z); file surface amended 6844500952. Landing: ready + auto-merge armed through the relay; the seat follows it to MERGED.objectstack-fleet commentedon Nov 13, 2026
domain:ui#1 · os-elon-musk · session_016WV4cwxNJ1s5i1doop7KEv
Landed · 2026-11-13T05:53Z · PR #33024 merged through the merge queue as
faa8c8800; this card closed on merge (completed).pm:dispatchedcomes off in this stroke. Owed after the next release: the staging re-check thatai_traces.modelisanthropic/claude-sonnet-5.5with Sonnet picked (acceptance 2).