Skip to content

Conversation

@ethanndickson
Copy link
Member

@ethanndickson ethanndickson commented Feb 3, 2026

Summary

  • Context switch warnings now trigger only after explicit model changes (user selection or explicit agent switch), not on workspace entry/mount or background localStorage sync.
  • Added in-memory tracking for workspace model changes (user|agent|sync) with stale-entry protection (no-op guard + divergence clearing).
  • Normalized gateway vs canonical model IDs so "same model" doesn't look like a switch; allow same-model warnings only when the effective context limit changes (e.g. 1M toggle).
  • Added regression tests for the new behavior and small banner tweaks for testability/a11y.

Background

The context switch warning banner was showing up when the workspace model changed due to background state reconciliation (workspace entry seeding, localStorage sync, default/policy refreshes). This created noisy banners unrelated to user intent.

Design / Approach

Origin-gating (explicit vs sync)

  • New helper module: src/browser/utils/modelChange.ts.
  • Model changes are tagged with an origin:
    • user: user explicitly selected a model
    • agent: agent mode switch explicitly changed the default model
    • sync: background reconciliation (mount, workspace entry, localStorage sync, default refresh)
  • Context switch warnings are evaluated only when the warning hook consumes a pending explicit change for the observed model.

Stale-entry protection (prevents false positives)

To avoid "old" explicit-change entries triggering warnings later:

  • No-op guard: don't record an explicit entry when the normalized stored model already equals the requested model (including gateway-vs-canonical equivalents).
  • Divergence guard: if the store reports a totally different model before we observe the target model, drop the explicit entry (it's stale).
  • Rapid A→B protection: if we briefly observe the previous model again while tracking the target, keep the newest pending entry.

What changed (review map)

Core behavior

  • src/browser/utils/modelChange.ts
    • setWorkspaceModelWithOrigin(workspaceId, model, origin) (intended entry point)
    • consumeWorkspaceModelChange(workspaceId, model) (one-shot origin consumption)
    • Reads current persisted model (readPersistedString(getModelKey(workspaceId))) to implement no-op + divergence handling.
  • src/browser/hooks/useContextSwitchWarning.ts
    • Consumes explicit-change origin when pendingModel changes and only queues warnings for user|agent.
    • Defers warnings until usage loads (tokens > 0) for explicit switches.
    • Clears warnings on sync/background model changes.
  • Integration points now consistently set origin:
    • src/browser/contexts/WorkspaceContext.tsx: seeds model from backend with origin: "sync" (no banner on entry).
    • src/browser/components/WorkspaceModeAISync.tsx: tags as agent only for real agentId flips; otherwise sync.
    • src/browser/components/ChatInput/index.tsx + useCreationWorkspace.ts: user selections are user; creation/default sync is sync; explicit agent switches are agent.
  • src/browser/utils/compaction/contextSwitchCheck.ts
    • Compares models via normalizeGatewayModel() to avoid gateway/canonical mismatches.
    • Adds allowSameModel option to allow same-model warnings only when callers know the effective limit changed (used for 1M toggles).

Supporting changes included in this PR

  • src/browser/components/ContextSwitchWarning.tsx
    • Adds data-testid="context-switch-warning" for tests and small a11y tweaks (aria-label dismiss, icon aria-hidden).
  • src/browser/contexts/PolicyContext.tsx + PolicyContext.test.tsx
    • Adds a payload signature guard to avoid redundant state updates on identical policy payloads; tests cover stability + reason updates.
  • src/browser/utils/chatCommands.ts
    • Removes onModelChange from /model command context (single source of truth becomes setPreferredModel / ChatInput plumbing).
  • src/browser/stories/App.chat.stories.tsx
    • Updates story play steps to use setWorkspaceModelWithOrigin(..., "user") so the warning matches new "explicit only" gating.

Validation

  • bun test src/browser/hooks/useContextSwitchWarning.test.ts
  • bun test src/browser/utils/modelChange.test.ts
  • bun test src/browser/components/WorkspaceModeAISync.test.tsx
  • bun test src/browser/utils/compaction/contextSwitchCheck.test.ts
  • make static-check

Notes / Risks

  • Origin tracking is intentionally in-memory only: warnings are action-driven and do not survive reloads between "record" and "observe".
  • Any explicit model change that should be eligible for warnings must go through setWorkspaceModelWithOrigin(..., "user"|"agent").

---

_Generated with `mux` • Model: `openai:gpt-5.2-codex` • Thinking: `xhigh` • Cost: `3.52`_

<!-- mux-attribution: model=openai:gpt-5.2-codex thinking=xhigh costs=13.52 -->
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e2823fabf3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ethanndickson ethanndickson changed the title 🤖 tests: avoid mock.module in context switch warning test 🤖 fix: gate context switch warnings to explicit model switches Feb 3, 2026
@ethanndickson
Copy link
Member Author

@codex review

Addressed the 1M-toggle warning regression by allowing same-model checks only when the effective limit changes, and added coverage for the toggle behavior.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 304b386f18

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ethanndickson
Copy link
Member Author

@codex review

Updated the config/policy refresh path to keep same-model warnings (like 1M toggles) by passing allowSameModel when recomputing existing warnings.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1f29dadc80

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ethanndickson
Copy link
Member Author

@codex review

Cleared stale warnings on zero-token user model switches and added hook coverage.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9f655205c4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ethanndickson
Copy link
Member Author

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 71d2218e00

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ethanndickson
Copy link
Member Author

@codex review

Addressed deferred switch cleanup when tokens are 0, made the agent warning test use the explicit model-change path, and restored the ContextSwitchWarning story via an explicit model switch in play.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 28ca1697e4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ethanndickson
Copy link
Member Author

@codex review

Normalized gateway model strings for explicit switch tracking and added a regression test for gateway-prefixed pending models.

@chatgpt-codex-connector
Copy link

Codex Review: Didn't find any major issues. You're on a roll.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ethanndickson
Copy link
Member Author

@codex review

Latest fixes are up: guarded context-switch warning refresh to avoid policy churn loops, stabilized policy refresh updates, and added regression coverage.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 65bd41e24e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ethanndickson
Copy link
Member Author

@codex review

Addressed flaking warning test and policy reason staleness: refresh guard to avoid re-warn on background model changes, PolicyContext signature includes status.reason, and added PolicyContext regression tests (plus flake rerun).

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a9e02e8721

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ethanndickson
Copy link
Member Author

@codex review

  • Gate model sync effects to record origin "agent" only on real agentId changes; use "sync" on mount/workspace entry/defaults/config changes.
  • Deflake PolicyContext tests (longer waitFor + remove call-order mock) and add WorkspaceModeAISync regression test.

@chatgpt-codex-connector
Copy link

Codex Review: Didn't find any major issues. Nice work!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Follow the same pattern as ProjectContext.test.tsx, WorkspaceContext.test.tsx,
and ThinkingContext.test.tsx: mock @/browser/contexts/API at the top of the
file before importing PolicyProvider.

This fixes CI failures caused by bun module mocks leaking between test files.
When another test file mocks the API context first, our tests would get the
leaked mock (with api: null) instead of our intended stub, causing waitFor
timeouts.

Repro that previously failed:
  bun test src/browser/components/AppLoader.auth.test.tsx src/browser/contexts/PolicyContext.test.tsx
- Normalize gateway vs canonical model comparisons in warning logic
- Move workspace reset dispatch into useLayoutEffect
- Add dismiss button aria-label
- Remove dead onModelChange from SlashCommandContext

---

_Generated with `mux` • Model: `openai:gpt-5.2` • Thinking: `xhigh` • Cost: `$73.99`_

<!-- mux-attribution: model=openai:gpt-5.2 thinking=xhigh costs=73.99 -->
@ethanndickson
Copy link
Member Author

@codex review

Pushed follow-ups:

  • Normalize gateway vs canonical model comparisons
  • Move workspace reset dispatch into useLayoutEffect
  • Add aria-label to dismiss button
  • Remove dead onModelChange from SlashCommandContext

Resolved conflicts by keeping SlashCommandContext free of unused callbacks.

---

_Generated with `mux` • Model: `openai:gpt-5.2` • Thinking: `xhigh` • Cost: `$75.39`_

<!-- mux-attribution: model=openai:gpt-5.2 thinking=xhigh costs=75.39 -->
@ethanndickson
Copy link
Member Author

@codex review

Merged origin/main into the branch and resolved the two conflicts in ChatInput/chatCommands (kept SlashCommandContext free of unused callbacks). Static-check is green.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7bf1af7641

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Skip recording explicit model-change entries when the effective model doesn't change,
and clear pending entries once the workspace model diverges to avoid false warnings
after sync-driven away→back transitions.

Adds targeted unit tests for no-op, divergence, and rapid-switch scenarios.

---

_Generated with `mux` • Model: `openai:gpt-5.2` • Thinking: `xhigh` • Cost: `$77.69`_

<!-- mux-attribution: model=openai:gpt-5.2 thinking=xhigh costs=77.69 -->
@ethanndickson
Copy link
Member Author

@codex review

I pushed a follow-up commit that prevents stale explicit model-change entries from lingering and being consumed after sync-driven away→back transitions. Also adds targeted unit tests for no-op, divergence, and rapid-switch scenarios.

@chatgpt-codex-connector

This comment was marked as resolved.

@ethanndickson
Copy link
Member Author

@codex review

@chatgpt-codex-connector
Copy link

Codex Review: Didn't find any major issues. What shall we delve into next?

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant