Backend PR #3135 · Trainer · September 2026
Feature explainer · for product

All Positions:
train the whole table

Today the Trainer lets you practice one seat per hand — you're the Button, everyone else is a bot. This PR teaches the backend a second mode where you play every seat that faces a real decision. One hand, up to six perspectives.

✓ Approved by review ✓ All CI green Behind feature flag Pairs with FE PR #6686

The 30-second version

Think of a chess coach who makes you play both sides of the board so you stop seeing the game from just one chair. Same idea here: instead of grinding "Button vs Big Blind" a hundred times, you sit down and the hand comes to you — whichever seat has a decision worth making, you make it.

🧑
YOU · BTN
🧑
YOU · SB (taken over)
🤖
BOT · BB
🤖
BOT · UTG
🤖
BOT · MP
🧑
YOU · CO (taken over)
Your main seatSeats you took overBots (folded or folding)

How a hand plays out

1

Bots play the boring parts

The engine lets bot seats act automatically (using solver frequencies) until a seat reaches a decision that's actually interesting to train.

2

The "is this worth your time?" gate

Before handing you a seat, the backend peeks at what the solver would do there. If that seat would just fold, it folds quietly and moves on — you never get interrupted for a trivial fold. If the seat would do something real (call, raise), it becomes yours.

3

Takeover: the seat gets dealt in

The seat is dealt a hand consistent with the action it's about to face, its cards flip face-up for you, and it stays yours for the rest of the hand. You can end up controlling several seats at once.

4

Every decision is graded

All your moves — across all your seats — get the usual correctness grading and show up in stats and hand history, per seat.

What this means for the product

More training per hand

A single dealt hand now generates several graded decisions instead of one. Higher density = faster improvement and longer sessions.

A genuinely new mode, cheaply

It reuses the existing trainer engine, solutions, and grading. No new solver work, no new infrastructure — it's a smarter loop around what we already have.

Safe to roll out

Off by default. It's gated by a feature flag per user, and old clients that never send the new setting keep today's behavior exactly.

Full-hand only (for now)

The mode requires "full hand" training scope — it deliberately doesn't combine with street/spot drills in v1. Smaller surface, fewer edge cases.

The numbers

11
commits: 4 feature phases + 4 review/quality rounds
929
backend tests passing (dozens new for this mode)
0
breaking API changes — everything is additive

Trade-offs we accepted (and why they're fine)

DecisionPlain-language meaningRisk level
Old fields kept aliveThe app's old "hero hand" field still works so existing app versions don't break. We carry a little duplicate data for a while.Low — cleanup later
Short-lived cache not versionedIn-progress hands live in a 1-hour cache. We didn't build migration logic for old cached hands — they simply expire within the hour of deploy.Low — self-heals in 1h
Rare recovery loses one detailIf that cache expires mid-hand (rare), the hand is rebuilt from permanent storage. One edge case: a hand where you hadn't taken over any seat yet quietly resumes as a classic single-seat hand. Logged and tracked; a lossless fix is scoped if it ever matters.Low — rare + graceful
Setting can be "unset"Users who never touched the setting have it empty, which means "classic mode". Matches how our other trainer settings behave.None — by design
One open item
After this deploys to dev, we do a quick load check (review item R17): the takeover gate asks the solver a few extra questions per hand, and we want to confirm that's negligible under real traffic before broad rollout.

Rollout picture

Backend ready

This PR — approved, all checks green, mergeable. A live per-PR preview environment is being provisioned for hands-on testing.

Frontend ready

Companion PR #6686: a "Play Mode" toggle in Trainer settings (Single position / All positions), taken-over seats shown face-up. CI green, awaiting review.

3

Then

Merge both → deploy to dev → R17 load check → enable the flag for internal users → decide the rollout cohort.

If you remember one thing
This turns every trained hand from one graded decision into a whole table of them — built almost entirely from parts we already had, shipped off by default behind a flag.