Skip to content

Re-select group sessions stuck on an old provider - #1131

Merged
Birfy merged 1 commit into
mainfrom
cursor/fix-1127-group-session-model-ffa1
Oct 25, 2026
Merged

Birfy merged 1 commit into
mainfrom
cursor/fix-1127-group-session-model-ffa1

Conversation

@Birfy

@Birfy Birfy commented Oct 25, 2026

Copy link
Copy Markdown
Collaborator

Written-by: Dev

Owner: Dev
Reviewer: Reviewer

Fixes #1127

What changed

A group session could keep requesting the previous provider after the Bot record already said the new model was applied (appliedModel matched, modelStale unset). applyModel returned before touching those sessions, and opening an existing group session only repaired a stale Bot.

A settled apply now re-selects a group session whose last request used another provider or model. Opening that session does the same before the next turn. The Bot's own chat, and any session that is not one of its group sessions, stay as they are. A session whose route cannot be read is left alone, so the #289 settled early return still holds. A fresh part starts on the Bot's model instead of copying the previous request header.

Verification at the tip

Tip SHA: 1ebd550dcde7b652cc3293ce960170f442591c3c

Ran:

  • Red at base, tests only: node --import ./test/harness-resolve.mjs --test --test-name-pattern '1127|289' test/models.test.js test/room-participant.test.js — 3 failed, 3 passed. Settled applyModel left g1 on deepseek-official/deepseek-flash; a refusing drifted session did not set modelStale; opening the existing session made 0 selectModel calls. #289 and force-apply passed on that tip.
  • At the tip: TZ=UTC npm run verify — exit 0. arch-docs OK (13 changed files). ds-bot patches check ok. core 1475 pass, social 489, tree 125, timeline 125, .github/scripts 417, interop 37, live-e2e unit 16. node .github/scripts/check-empty-catch.mjs exit 0. node .github/scripts/changelog.mjs check exit 0. node core/scripts/build-client.mjs --check exit 0.

Not run:

  • Smoke bench (dev/bench.sh / dev/smoke.mjs). It needs a DeepSeek Harness checkout with apps/web and pnpm; this environment has the npm harness packages only.
  • A live retest on the owner home. The unit tests seed the reported state (group session on provider A, appliedModel already B, modelStale unset) and assert selectSessionModel plus the next request header.

Root cause

applyModel returned when appliedModel already equalled the desired model and modelStale was unset, so it never called selectSessionModel on existing group sessions. room-participant.js open() called applyModel only when modelStale was set. A DSH session whose last request was still deepseek-official/deepseek-flash therefore survived a Models change that had already recorded opencsitool/.... Force-apply (updateBot passes { force: true }) already re-selected every group session; the hole was the settled record and the next turn. A fresh part also copied that stale request header onto the next part.

Open in Web Open in Cursor 

applyModel returned early once appliedModel matched and modelStale was
unset, and reopening a group session only repaired a stale Bot. A
session whose last request still named another provider kept that
route. Re-select those sessions on the settled apply and before the
next turn, and start a fresh part on the Bot's model.

Fixes #1127

Co-authored-by: Danyang Chen <birfychen@gmail.com>
@Birfy Birfy added agent-pr Pull request opened by an agent bug Something isn't working labels Oct 25, 2026 — with Cursor
@cursor

cursor Bot commented Oct 25, 2026

Copy link
Copy Markdown

Verdict: PASS at 1ebd550
Written-by: Reviewer

Ran:

  • GH_REPO=ThinkFlowLab/FlyBot node .github/scripts/risk-gate.mjs --pr 1131 → pass (risk-tier: T2; basis: core/src/host/models.js=T2, core/src/host/parts.js=T2, core/src/host/room-participant.js=T2)
  • TZ=UTC node --import ./test/harness-resolve.mjs --test --test-name-pattern '1127|289' test/models.test.js test/room-participant.test.js test/fresh-part-model.test.js (worktree at 1ebd550) → pass, 7/7
  • Same command after restoring core/src/host/models.js, parts.js and room-participant.js from origin/main d797cbe → fail, 4 failed / 3 passed. Settled apply left g1 on deepseek-official/deepseek-flash; a refusing drifted session did not set modelStale; opening the existing session made 0 selectModel calls; freshPartModel is not exported. Models: a group session whose model selection failed is never repaired (applyModel early return); old 'no model set up' lines stay in room history #289 retry and force-apply stayed green.
  • node scripts/ds-bot-patches.mjs check → pass (core equals ds-bot + patches)
  • node core/scripts/check-arch-docs.mjs → pass (13 changed files)
  • node .github/scripts/check-empty-catch.mjs → pass
  • node .github/scripts/changelog.mjs check → pass
  • TZ=UTC npm run lint (core/) → pass (existing warnings only; arch-docs OK)
  • TZ=UTC npm test (core/) → 1255 pass, 35 fail; every failure is Cannot find package 'esbuild' because npm ci was not run in this worktree. No host assertion failed.

Not run:

  • Smoke bench (dev/bench.sh / dev/smoke.mjs) and a live retest on the owner home.
  • Full npm run verify (plugin suites, package, client --check). esbuild is not installed here, so the 35 client-file loads could not start.
  • GitHub tests-ok is green on this tip (check run 121120052062). That job was not re-run here. enqueue-guard on this tip is red only because no Verifier report named 1ebd550 yet.

Findings: no actionable findings against #1127.

Acceptance:

  1. A settled applyModel (appliedModel already matches, modelStale unset) re-selects group sessions whose last requestHeader provider/model differs, and leaves the Bot's own chat and any other session alone. Opening an existing group session calls rebindSessionModel before the next turn. In DSH 0.2.0-rc.2, selectModel appends a durable model/selection and selectForNextRequest is what the next request uses; requestHeader stays the last logged header until that request. Calling selectSessionModel is the same repair force-apply already uses.
  2. The sticky-route tests are red on origin/main and green at this tip. Models: a group session whose model selection failed is never repaired (applyModel early return); old 'no model set up' lines stay in room history #289 modelStale retry and force-apply stay green on both.
  3. freshPartModel takes the Bot's desired ref when one exists. moveOn passes desiredModel ahead of the previous request header, so a fresh part does not copy that header's provider, model, or reasoning effort onto the new session. The old header is only the fallback when the Bot has no model.

Security fence / display names: not in this diff.

Residual, not a fail: liveRoute compares provider and model only. An effort-only sticky header is not re-selected while the record is settled. Changing bot.effort still takes the full apply path, because appliedEffort would differ. The reported failure is the provider route.

This PASS is not merge authority. I am not enqueueing.

1 similar comment
@Birfy

Birfy commented Oct 25, 2026

Copy link
Copy Markdown
Collaborator Author

Verdict: PASS at 1ebd550
Written-by: Reviewer

Ran:

  • GH_REPO=ThinkFlowLab/FlyBot node .github/scripts/risk-gate.mjs --pr 1131 → pass (risk-tier: T2; basis: core/src/host/models.js=T2, core/src/host/parts.js=T2, core/src/host/room-participant.js=T2)
  • TZ=UTC node --import ./test/harness-resolve.mjs --test --test-name-pattern '1127|289' test/models.test.js test/room-participant.test.js test/fresh-part-model.test.js (worktree at 1ebd550) → pass, 7/7
  • Same command after restoring core/src/host/models.js, parts.js and room-participant.js from origin/main d797cbe → fail, 4 failed / 3 passed. Settled apply left g1 on deepseek-official/deepseek-flash; a refusing drifted session did not set modelStale; opening the existing session made 0 selectModel calls; freshPartModel is not exported. Models: a group session whose model selection failed is never repaired (applyModel early return); old 'no model set up' lines stay in room history #289 retry and force-apply stayed green.
  • node scripts/ds-bot-patches.mjs check → pass (core equals ds-bot + patches)
  • node core/scripts/check-arch-docs.mjs → pass (13 changed files)
  • node .github/scripts/check-empty-catch.mjs → pass
  • node .github/scripts/changelog.mjs check → pass
  • TZ=UTC npm run lint (core/) → pass (existing warnings only; arch-docs OK)
  • TZ=UTC npm test (core/) → 1255 pass, 35 fail; every failure is Cannot find package 'esbuild' because npm ci was not run in this worktree. No host assertion failed.

Not run:

  • Smoke bench (dev/bench.sh / dev/smoke.mjs) and a live retest on the owner home.
  • Full npm run verify (plugin suites, package, client --check). esbuild is not installed here, so the 35 client-file loads could not start.
  • GitHub tests-ok is green on this tip (check run 121120052062). That job was not re-run here. enqueue-guard on this tip is red only because no Verifier report named 1ebd550 yet.

Findings: no actionable findings against #1127.

Acceptance:

  1. A settled applyModel (appliedModel already matches, modelStale unset) re-selects group sessions whose last requestHeader provider/model differs, and leaves the Bot's own chat and any other session alone. Opening an existing group session calls rebindSessionModel before the next turn. In DSH 0.2.0-rc.2, selectModel appends a durable model/selection and selectForNextRequest is what the next request uses; requestHeader stays the last logged header until that request. Calling selectSessionModel is the same repair force-apply already uses.
  2. The sticky-route tests are red on origin/main and green at this tip. Models: a group session whose model selection failed is never repaired (applyModel early return); old 'no model set up' lines stay in room history #289 modelStale retry and force-apply stay green on both.
  3. freshPartModel takes the Bot's desired ref when one exists. moveOn passes desiredModel ahead of the previous request header, so a fresh part does not copy that header's provider, model, or reasoning effort onto the new session. The old header is only the fallback when the Bot has no model.

Security fence / display names: not in this diff.

Residual, not a fail: liveRoute compares provider and model only. An effort-only sticky header is not re-selected while the record is settled. Changing bot.effort still takes the full apply path, because appliedEffort would differ. The reported failure is the provider route.

This PASS is not merge authority. I am not enqueueing.

@github-actions github-actions Bot added the pass label Oct 25, 2026
@Birfy
Birfy added this pull request to the merge queue Oct 25, 2026
Merged via the queue into main with commit 781121b Oct 25, 2026
12 of 13 checks passed
@Birfy
Birfy deleted the cursor/fix-1127-group-session-model-ffa1 branch October 25, 2026 08:45
@github-actions github-actions Bot removed the agent-pr Pull request opened by an agent label Oct 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working pass

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Changing Bot model leaves existing group sessions on old provider (MISSING_CREDENTIAL)

2 participants