Skip to content

#92776: fix(agents): prevent indefinite session model pinning from polluted fallback origin#93275

Closed
wings1029 wants to merge 1 commit into
openclaw:mainfrom
wings1029:fix/issue-92776-model-pinning
Closed

#92776: fix(agents): prevent indefinite session model pinning from polluted fallback origin#93275
wings1029 wants to merge 1 commit into
openclaw:mainfrom
wings1029:fix/issue-92776-model-pinning

Conversation

@wings1029

Copy link
Copy Markdown
Contributor

Summary

  • Fix indefinite session model pinning caused by polluted
    modelOverrideFallbackOrigin fields. When the origin recorded the
    failing model instead of the configured primary, the snap-back probe
    (resolveAutoFallbackPrimaryProbe) returned undefined on every turn,
    leaving the session permanently stuck on a degraded fallback model.
  • Fix: use the current configured primary as the probe origin instead of
    requiring a matching persisted origin. Also relax
    entryMatchesAutoFallbackPrimaryProbe to match on the fallback
    override alone, so polluted session entries can be updated.

Fixes #92776

Linked context

Real behavior proof

Behavior addressed: Session model pinning no longer persists
indefinitely when modelOverrideFallbackOrigin is polluted. The
snap-back probe now uses the configured primary as origin, ensuring it
fires on every turn until the primary becomes available.

Real setup tested: Linux 4.19.112, Node.js v22.21.1, OpenClaw main,
vitest.

Exact steps or command run after fix:

node scripts/run-vitest.mjs src/agents/agent-scope.test.ts
node scripts/run-vitest.mjs src/agents/agent-command.live-model-switch.test.ts
node scripts/run-vitest.mjs src/auto-reply/reply/agent-runner-execution.test.ts

After-fix evidence:

✓ src/agents/agent-scope.test.ts (44 tests | 44 passed)
  - resolves a viable auto-fallback primary probe with all metadata
  - skips primary probes for strict or stale fallback selections
    (updated: origin-mismatch now returns valid probe instead of undefined)
  - identifies legacy auto fallback overrides without origin metadata

✓ src/agents/agent-command.live-model-switch.test.ts (64 tests | 64 passed)
✓ src/auto-reply/reply/agent-runner-execution.test.ts (201 tests | 201 passed)

All 309 tests pass.

Observed result after the fix: When origin doesn't match the current
primary (polluted or stale), the probe returns a valid probe targeting
the current primary instead of undefined. The probe fires, the primary
is tried, and if available, the override is cleared (snap-back).

What was not tested: End-to-end session with polluted origin on a
live OpenClaw instance with real provider chain.

Proof limitations or environment constraints: Unit test environment.
The behavioral change is verified through existing and updated test
coverage for resolveAutoFallbackPrimaryProbe.

Tests and validation

node scripts/run-vitest.mjs src/agents/agent-scope.test.ts
node scripts/run-vitest.mjs src/agents/agent-command.live-model-switch.test.ts
node scripts/run-vitest.mjs src/auto-reply/reply/agent-runner-execution.test.ts

Updated test: "skips primary probes for strict or stale fallback
selections" — when origin differs from primary, the probe now returns
a valid probe ({provider: primary, model: primary, fallbackProvider: override, fallbackModel: override}) instead of undefined.

Risk checklist

Did user-visible behavior change? (Yes)

  • Sessions stuck on degraded fallback models due to polluted origin
    will snap back to the configured primary when it becomes available.

Did config, environment, or migration behavior change? (No)

Did security, auth, secrets, network, or tool execution behavior change? (No)

What is the highest-risk area?

  • Changing the probe guard logic could cause the primary model to be
    probed more aggressively. The existing minIntervalMs throttle (default
    5 min) prevents excessive probing.

How is that risk mitigated?

  • Probe interval throttle unchanged.
  • If the primary is available, the override is cleared (desired behavior).
  • If the primary is still unavailable, fallback chain runs as before.
  • Existing test coverage validates both paths.

Current review state

What is the next action?

  • ClawSweeper review.

What is still waiting on author, maintainer, CI, or external proof?

  • E2E proof with live polluted session (requires real provider chain
    and multi-turn scenario). Unit tests cover the behavioral change.

Which bot or reviewer comments were addressed?

  • ✅ Fix matches the reporter's sketch: use configured primary as origin
    rather than requiring persisted origin to match exactly.
  • ✅ One-shot migration is unnecessary — the relaxed guard means existing
    polluted sessions will snap back on their next turn without migration.

…allback origin

resolveAutoFallbackPrimaryProbe required the persisted
modelOverrideFallbackOrigin to match the current configured
primary before firing the snap-back probe. When the origin
fields were polluted with the failing model instead of the
configured primary (openclaw#92776), the guard returned undefined
and the probe never fired — leaving the session permanently
stuck on a degraded fallback model.

Fix: use the current configured primary as the probe origin
instead of requiring a matching persisted origin. This ensures
the snap-back probe always fires, attempting to clear the
auto-fallback override once the primary becomes available.

Also relax entryMatchesAutoFallbackPrimaryProbe to match on
the fallback override alone (provider/model) without requiring
the persisted origin to match — polluted session entries must
still be updatable after the probe fires.

Test: updated 'skips primary probes for strict or stale
fallback selections' — when origin differs from primary, the
probe now returns a valid probe targeting the current primary
instead of undefined.

Fixes openclaw#92776.

Co-Authored-By: Claude <[email protected]>
@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: XS proof: supplied External PR includes structured after-fix real behavior proof. labels Jun 15, 2026
@clawsweeper

clawsweeper Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Thanks for the context here. I swept through the related work, and this is now duplicate or superseded.

Close as superseded: #92819 is already the open canonical fix for the same linked session-pinning bug, has maintainer-modifiable branch state and proof marked sufficient, and covers the broader prepared-selection/session cleanup boundary that this narrower PR does not.

Canonical path: Use #92819 as the canonical fix path for the linked issue, because it carries the fuller stale-origin cleanup and prior review/proof context.

So I’m closing this here and keeping the remaining discussion on #92819.

Review details

Best possible solution:

Use #92819 as the canonical fix path for the linked issue, because it carries the fuller stale-origin cleanup and prior review/proof context.

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

Yes. Current main returns no primary probe when an auto fallback entry's persisted origin differs from the configured primary, matching the linked polluted-session report.

Is this the best way to solve the issue?

No. This is a plausible narrow fix, but #92819 is the better current landing path because it owns the same bug with broader guarded cleanup across reply and direct agent-command selection.

Security review:

Security review cleared: The diff only changes TypeScript agent fallback/session logic and tests; no dependency, workflow, permission, secret, or artifact-download surface is touched.

AGENTS.md: found and applied where relevant.

What I checked:

  • Same linked bug: The linked issue lists both this PR and Fix stale auto-fallback origin model selection #92819 as closing references for the same polluted fallback-origin session-pinning report.
  • Current-main source reproduction: Current main's probe guard exits when the persisted fallback origin differs from the current primary, matching the reported source-level failure that both PRs target. (src/agents/agent-scope.ts:166, 8682d0701b27)
  • This PR is a narrow guard change: This PR only changes src/agents/agent-scope.ts and its unit test to use the configured primary and relax entry matching; it does not carry the broader reply/direct cleanup boundary from the canonical PR. (src/agents/agent-scope.ts:151, e4f9eb9e6539)
  • Canonical PR is open and viable: Fix stale auto-fallback origin model selection #92819 is open, maintainer-modifiable, has proof:sufficient, and its latest durable ClawSweeper review says the previous blocker was addressed and the remaining action is maintainer compatibility review. (bc3d1299f438)
  • Canonical PR covers stale-origin classification: The canonical PR adds a shared stale-origin classifier for auto fallback pins whose recorded origin no longer matches the current primary and whose stored override is not already the primary. (src/agents/auto-fallback-stale-origin.ts:32, bc3d1299f438)
  • Canonical PR covers guarded direct cleanup: The canonical PR guards direct stale-origin durable cleanup with captured-row matching before clearing model/auth override fields after a visible run. (src/agents/agent-command.ts:2012, bc3d1299f438)

Likely related people:

  • steipete: Authored and merged the auto model fallback transition and primary-probe work that owns the snap-back behavior this PR repairs. (role: recent fallback recovery contributor and merger; confidence: high; commits: 4b0f16d496e5, b9768569b2e1; files: src/agents/agent-scope.ts, docs/concepts/model-failover.md, src/auto-reply/reply/agent-runner.ts)
  • neeravmakwana: Authored the merged legacy auto fallback cleanup that touched the same agent-command, agent-scope, get-reply, and model-selection paths. (role: adjacent bugfix author; confidence: high; commits: 711ab45025a2; files: src/agents/agent-command.ts, src/agents/agent-scope.ts, src/auto-reply/reply/get-reply.ts)
  • mushuiyu_xydt: Current blame for the central helper points to commit 44e6caf, though the history appears snapshot-like and not necessarily the original feature introduction. (role: recent area contributor; confidence: medium; commits: 44e6caff5401; files: src/agents/agent-scope.ts)

Codex review notes: model internal, reasoning high; reviewed against 8682d0701b27.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P1 High-priority user-facing bug, regression, or broken workflow. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. labels Jun 15, 2026
@openclaw-clownfish

Copy link
Copy Markdown
Contributor

Thanks @zhiqiang26 for the focused fix and proof on this. I am closing #93275 as superseded by the open canonical path in #92819 for #92776.

Both PRs target the same stale auto-fallback origin/session-pinning failure. #92819 is the broader prepared-selection fix path: it carries the shared stale-origin classifier, reply-side deferred cleanup, direct agent-command handling, maintainer-modifiable branch state, and the current review/proof context. I am keeping the canonical thread open there so validation and follow-up stay in one place.

Credit for this narrower source PR stays visible here, and Clownfish will preserve attribution if details from this work are carried forward. If this PR covers a different reproduction path or #92819 misses something after it lands, please reply and we can reopen or split it back out.

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

Labels

agents Agent runtime and tooling clownfish Tracked by Clownfish automation merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. P1 High-priority user-facing bug, regression, or broken workflow. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: XS status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

1 participant