Skip to content

fix(bandit): repair PairedModel when Thompson sampling switches model#754

Open
rohith500 wants to merge 2 commits into
workweave:mainfrom
rohith500:fix/bandit-repair-paired-model
Open

fix(bandit): repair PairedModel when Thompson sampling switches model#754
rohith500 wants to merge 2 commits into
workweave:mainfrom
rohith500:fix/bandit-repair-paired-model

Conversation

@rohith500

@rohith500 rohith500 commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Summary

Bug: When x-weave-router-strategy: bandit Thompson-samples the cluster scorer's runner-up, bandit.Router rewrote Model but left Metadata.PairedModel pointing at that same slug. writeNewPin persisted {pinned_model, paired_model} as identical values, which silently disabled Stage 2 bandSwapServed for the pin's life (LARGE and SMALL resolved to one model).

Fix: On a real model switch, recompute the runner-up against the served model — same contract as banditexplore.repairBandPair. Argmax draws leave the scorer pair untouched.

Fixes #753

What changed

File Change
internal/router/bandit/bandit.go Call repairBandPair after annotate when TS switches off the argmax
internal/router/bandit/bandit_test.go Regression tests with one-line behavior comments (AGENTS.md style)

Verification

Local (author):

  • make check — all checks passed
  • go test ./internal/router/bandit/... -race
  • Stress 5000 trials on real testdata posterior: 0 collapses after fix (was 100% collapse on runner-up serves)

GitHub Actions (fork PR):

  • Cursor Bugbot — pass
  • Test / Comment Length / Cluster Routing — currently action_required (first-time contributor workflow approval). A maintainer needs to click Approve and run workflows on the PR checks tab before these can go green.

Checklist (CONTRIBUTING.md / AGENTS.md)

  • Topic branch (not on main)
  • Conventional Commits + DCO Signed-off-by
  • Test comments state asserted behavior only (no issue/PR refs, no pre-fix narration)
  • Linked issue

Mirror banditexplore.repairBandPair so serving the scorer's runner-up
cannot collapse the session-pin band pair and silently disable Stage 2
band swap.

Fixes workweave#753

Signed-off-by: N Rohith Reddy <rohithreddy2202@gmail.com>
@greptile-apps

greptile-apps Bot commented Jul 16, 2026

Copy link
Copy Markdown

PR author is not in the allowed authors list.

Match AGENTS.md: concise comments that state the asserted behavior,
without scenario narration.

Signed-off-by: N Rohith Reddy <rohithreddy2202@gmail.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor

Thanks for this, @rohith500 — subtle bug, nicely fixed. 🙏

When Thompson sampling serves the runner-up, the scorer's PairedModel was still computed against the old argmax and could collapse onto the served model; recomputing it against the served pick (repairBandPair) is the right fix. I read it against the repo conventions (AGENTS.md) and it conforms — no changes needed:

  • GodocrepairBandPair carries a clear doc comment, and the inline comment explains why the runner-up must be recomputed rather than restating the code.
  • Package conventions — it follows the local internal/router/bandit style (the package deliberately keeps provider/model as plain strings and doesn't import internal/providers, so the test fixtures match).
  • Tests — non-tautological: TestRoute_RepairsBandPairWhenServingRunnerUp asserts the pair is recomputed to the prior argmax (and doesn't collapse), and the argmax-keep case verifies the scorer's pair is left untouched.

Approving from a conventions standpoint — great find.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(bandit): repair PairedModel when Thompson sampling serves the runner-up

1 participant