How this app grades you

Every grade names its source. Next to each verdict sits a provenance label and a tap-able ? that opens the short version of this page from anywhere in the app. The label isn't decoration — it tells you how much to trust the number beside it. This page is the full accounting of where each level comes from.

The trust ladder

  1. Solver-verified

    A direct result from the pinned TexasSolver build for the named neutral range model and river configuration. It verifies that modeled decision, not an opponent's true cards or strategy; concrete EVs, frequencies, response branches for the raise lines, and provenance sit behind Why?. A result is published only when the residual exploitability derived from the solver artifact itself — never the solver's own printout — is at most 2% of the pot at a fixed solve budget. Roughly one river spot in ten in the measured corpus plateaus above that ceiling; those refuse and keep their heuristic label.

  2. Nash-anchored

    The entire push/fold chart set: every seat's shove-or-fold range and every call-off range at short-stack depths. All 176 of the 208 shipped range charts carry this label (read live from each chart's own confidence field, not transcribed). They come from an in-house offline equilibrium solve of the 9-seat sequential push/fold game — chip EV, no antes, uniform stacks, over-calls modeled — gated on reproducing published Nash anchors within ±3pp, with the measured leftover exploitability recorded in the artifact metadata rather than asserted.

  3. GTO chart (hand-built)

    Every other preflop chart: hand-built ranges informed by published GTO opening and defense frequencies, never exported from a solver run (DATA_PROVENANCE.md records exactly what was cross-checked and what wasn't). Treat these as a strong guideline, not gospel to the decimal — a hand's 50/50 mix here was authored to represent indifference, not independently verified against a true equilibrium.

  4. Heuristic estimate

    Immediate postflop feedback. Not a solve of any kind: a simplified EV model built from equity-times-pot arithmetic. It estimates what a villain still holds after each action (using the range-narrowing constants printed below), checks your hand's equity against that estimated range, and discounts for how much of the equity you'd actually realize with streets left to play. Trust the direction more than the number.

What the verdicts mean

Preflop verdicts come from the chart's frequencies for your exact hand: Best is the chart's most-frequent action, Correct is an action it plays some of the time, and misses are banded by how far the chart is from ever taking your pick with any hand. A miss already in the Wrong band escalates to Blunder only when you fold a hand the chart plays as a pure action and the hand sits in the top decile of that pure set (ranked by the app's board-free hand ordering) — folding AA to a 3-bet is the canonical case; taking a non-fold line with the same hand stays Wrong. The mirror also holds: a Wrong that misses by a whisker — your hand sits within about 3 rungs of the hands the chart does play that way — demotes to Inaccuracy, so a range-edge judgment call stops grading like a real mistake. And one off-menu action loses its leniency: limping or flatting a hand in the top decile of the chart's pure raising range (limping AA) grades Wrong rather than the gentler off-menu Inaccuracy — the premium you gave up is the miss. Postflop verdicts are banded on EV lost against the grade's best line: estimated action EVs for immediate feedback, or the accepted solver action table for a solver-verified row.

Postflop verdict bands — EV lost vs the grade's best line, per 10bb of pot — larger pots scale the thresholds proportionally.
VerdictEV lost
Bestup to 0.1bb
Correct0.1 – 0.35bb
Inaccuracy0.35 – 1bb
Wrong1 – 3bb
Blunderover 3bb

Heuristic multiway pots widen these bands — ×1.5 with 3 players, ×2 with 4+ — because with more players in the pot there is no single 'correct' line to grade against.

"Correct" means two different things. On a preflop grade it means the chart plays your action with this hand, just not as its most-frequent pick. On a postflop grade it means your line's EV lost fell inside the Correct band above.

For heuristic estimates, fold severity is judged against the best passive line — a speculative raise the model likes doesn't convict your fold; the per-decision EV-lost number in hand review still shows the full comparison, while your averaged EV-lost stats use the fold-aware number.

The model's dials, printed in full

The Heuristic estimate label above can afford to be honest because that model is small enough to print whole. When estimating what a villain still holds after they act, it keeps a fraction of their range that depends on the action — every constant below is read directly from the shipped NEUTRAL parameter set (postflopHeuristic.ts), not retyped:

ConstantValueMeaning
totalKeep(r)46% → 35.4%Fraction of range kept after a bet, continuous in the bet's pot ratio r — the values shown are a 0.45x bet and a pot bet; the formula is 0.62 / (1 + 0.75r), clamped to [0.08, 0.75]
RAISE_TIGHTEN0.4A raise (not a first bet) multiplies its keep by this — raising ranges are tighter
RAISE_SLICE_TIGHTEN0.6Scales the slice of a villain's continue range modeled as raising your bet (the raise-risk branch below) — a NEW constant initialized from RAISE_TIGHTEN's value and calibrated independently of the raise-facing tree
RAISE_EQ_FLOOR0.75Equity-vs-callers floor for crediting your bet when it gets raised — a NEW constant initialized from RERAISE_EQ_FLOOR's value and calibrated independently of the raise-facing tree
RAISE_SLICE_CONTINUE_CAP0.5The raise slice never takes more than this fraction of the continue range — the call slice your continue equity is measured against stays non-degenerate
STAB_R0.5The hypothetical stab size (× pot) villain is modeled betting when your first-to-act check hands them the action — the check-react model below prices your check against it
IO_MIN_OUTS7Minimum clean outs to a straight or better before a draw can receive implied-odds credit
IO_FRAC0.4Fraction of the bounded future pot that the call row may count as realizable future value
IO_CAP_BB1.8Maximum implied-odds credit, in big blinds
IO_SHORTFALL_FULL0.05Direct-odds shortfall through which a qualifying draw receives full tapered credit
IO_SHORTFALL_ZERO0.1Direct-odds shortfall at which the tapered credit reaches zero
IO_GRACE0.02Breakeven guard-band width that keeps the credit continuous around direct odds
BLUFF_SHARE_PEAK0.3Peak bluff share of a betting range (at exactly pot size); the share falls toward 0 for both tiny bets and huge jams — a jam range is value-heavy
BLUFF_TAIL_FRAC0.12The bluff share is carried by the bottom slice of ranks, weighted by combo mass
betKeepOffset0Optional archetype shift for a caller's range estimate; Play-mode hand review supplies the assigned villain, while neutral callers use the value shown here
CHECK_CAP_FRAC0.2A check caps the top slice of the range (this fraction of ranks) instead of trimming its air — a checking range keeps its weak hands
SLOWPLAY_RESIDUAL0.25The capped top slice keeps this multiplier (draws on wet boards are exempt — a check-back with a draw is routine, not a slowplay)
UNCAP_RESTORE0.9When a previously-capped player later bets, capped hands are restored to this weight before the bet reshapes the range — delayed strength isn't stripped
callKeepOffset0Additive shift to the MDF-based call keep baseline below (0 at NEUTRAL)
wetBoardDrawBonus0.15Extra keep-fraction for combinatorial draws when the board is wet

A bet's keep-fraction now falls continuously with its size — totalKeep keeps 46% of ranks after a small 0.45x bet but only 35.4% after a pot bet — and the composed range is polarized: a top slice at full weight (with a decay tail capped at 0.15 of ranks), plus a bottom-of-range bluff slice whose combo mass is sized to the bet's bluff share (peaking at 0.3 for a pot bet, falling toward zero for a jam — the shipped jam bluff floor is 0). A raise multiplies the keep by 0.4, floored at 0.04 so even a jam range is never empty — a raising range is a condensed slice, not a rebranded betting range. Play-mode hand review uses the assigned villain archetype when it estimates the range behind an observed bet or call, so the same action can retain a different range share for a Station and a Nit. Trainer, walkthroughs, and bots' own reads use neutral defaults. Archetype conditioning changes the estimated range, never the objective strength of the cards themselves.

A related boundary governs the read-based notes shown under a reviewed hand. The estimated range may be archetype-conditioned, as above, but the response the grade prices is always the neutral one — so a note explains how you would adjust against a specific opponent once the read is confirmed, and never moves the verdict beside it. Where a review also prints how the numbers shift against that opponent, that is the same model re-run with that opponent's response dial in place of the neutral one (which for a loose caller widens their continuing range rather than narrowing it) — an alternative measurement, never a second grade.

A call doesn't get one of the fixed keep constants above — it's sized continuously off the same MDF math the MDF topic teaches. continueKeep(ratio, p) sets the keep fraction to 1 − dampedAlpha(ratio) — exactly the MDF keep 1 / (1 + ratio) for bets of half pot and up; tiny sizes (r < 0.5) deliberately keep more, via the tinyBetDefenseDamp ramp printed below — where ratio is the preceding bet's size relative to the pot it was betting into, plus callKeepOffset, clamped to [0.05, 0.95]. A villain who calls a big bet is presumed to have narrowed to a tighter slice of their range than one who calls a small one — continuously, not in one of two fixed buckets. Three ratios plugged into the live function at NEUTRAL (callKeepOffset = 0):

Bet ratio (risk / pot)1 / (1 + ratio)continueKeep(ratio, NEUTRAL)
0.566.7%66.7%
150.0%50.0%
233.3%33.3%

Villain keeps a shrinking slice of their range the bigger the bet they called: two-thirds against a half-pot bet, half against a pot-size bet, only a third against an overbet. The three observation kinds route to three mechanisms: a call feeds the percentile-cut narrowing above (narrowRange), a bet or raise composes the polarized slice-structured range the composition table describes, and a check caps the top of the range while keeping everything else — with one sequencing rule: a check followed by that player's own bet or raise on the same street is discarded entirely (a check-raise is one decision, not a passive read followed by an aggressive one).

The keep fraction only tells half the story: even a hand that survives range-narrowing doesn't always get to realize 100% of its raw equity, because more streets (and more of villain's own decisions) still have to play out. The model discounts every check/call/bet candidate by an equity realization factor read off the street and whether hero is in position — read straight from the shipped realizationFactor() function, not retyped:

StreetIn positionOut of position
Flop95%82%
Turn97%88%
River100%100%

River is always 100% either way — no more cards to come, so equity is the pot share, full stop. Earlier streets and out-of-position spots realize less, because acting first into more remaining streets gives the in-position player more chances to extract (or deny) value hero's raw equity number doesn't account for on its own. That's why the reasoning text under a Play-mode check or call sometimes reads "realizing ~82% of X% equity out of position" instead of just quoting the raw equity number.

Bluff, value, or both: how bet feedback is worded

The reasoning under a bet or raise is worded by your equity against the hands that call it. Below 25% (BLUFF_EQUITY_THRESHOLD) the fold is doing essentially all the work, so the feedback walks through the no-equity bluff baseline and tags the line as a bluff. At or above 50% (VALUE_EQUITY_THRESHOLD) you're literally ahead of the range that continues, and the feedback names it a value bet. Between the two it names both profit sources — folds now, plus real equity when called. The Value betting lesson teaches the concept in full.

One honesty note: the 25% line is not only wording. The same "bluff" classification feeds the sizing-tolerance rule described below — a sizing disagreement between two aggressive lines only bands at the VALUE_SIZING_TOLERANCE discount when neither line is classified a bluff — and it shapes how the practice bots size their own bets. The 50% line, by contrast, is purely how the feedback is worded.

Sizing, the candidate menu, and the geometric cap

When the model asks "what was the best line here?", the bets it considers come from a fixed per-street menu of pot fractions (CANDIDATE_BET_FRACS), plus the all-in — every value below read live from the shipped table:

StreetCandidate bet sizes (× pot)CALLED_RATIO_CAP
Flop0.33×, 0.5×, 0.66×, 1×, 1.25× + all-in1.25×
Turn0.5×, 1×, 1.5×, 1.75× + all-in1.75×
River0.5×, 1×, 1.5×, 2× + all-in2×

Candidates are deduplicated by the size the model actually prices — two menu entries that cap to the same effective risk collapse into one, keeping the smallest amount. That effective risk is the CALLED_RATIO_CAP column: a bet above the street's cap (1.25× pot on the flop, 1.75× on the turn, 2× on the river) is modeled as if it were the capped geometric size — piling on more than the cap can't manufacture EV, because no competent line puts that much in as one street's bet.

At the other extreme, defenders are modeled as over-defending tiny bets: tinyBetDefenseDamp multiplies the MDF fold rate by 0.4 + 0.6·(r / 0.5), clamped to [0.4, 1] — at r = 0.1 that's 0.52, at r = 0.5 it's back to 1. So a pure min-bet bluff is strictly −EV in this model. At sane sizes (r ≥ 0.5) the exact zero-EV MDF cancellation the MDF topic teaches survives as the model's reference point — a bluff into a fresh, MDF-shaped range prices out near zero — but the realized number is range-dependent, because shipped fold equity reads the actual narrowed range (the mass-based reading two paragraphs down), not the formula.

Three more dials shape what the grade calls a leak. A strong made hand that checks the flop or turn earns a trap credit — 0.45 of the pot for a strong made hand, 0.13 for a bare high-equity hand — scaled by (1 − wetness) and the multiway factor, flop and turn only; bots read the model with the credit switched off, so it never changes how opponents play, only how checks grade. One split to know: the credit now applies only where the check-react model below does not — checks that close the street, and multiway checks, keep the flat credit; a heads-up check that hands villain the action is instead priced against villain's actual modeled response (the stab, and your best answer to it), which absorbs the slowplay value the flat credit used to approximate. VALUE_SIZING_TOLERANCE (0.5) bands sane-size value-sizing disagreements at half weight — picking 0.5× pot where the model prefers 1× is a preference, not a leak. BORDERLINE_WINDOW_BB (0.2) is the half-width of the "(borderline)" hedge around each band edge — scoped off the Best edge, so a clean Best never hedges. On the flop and turn, a borderline read normally triggers an automatic 4× re-measure before the verdict ships, and the badge only survives if the re-measure still can't separate the bands. Narrow river assignments are enumerated exactly; wide multiway rivers use the seeded 10,000-sample estimate with no automatic refinement pass. Every candidate — betting lines included — is discounted at your actual position's realization row.

When you raise a bet, the model plays it against a real response: the bettor's range is re-built for the size they chose (the composition above), then split into a fold slice (bottom-up, capped on the river so value never folds — fold equity is 0.85× the damped MDF rate on earlier streets), a re-raise slice (the top 0.3 of the value region — your raise can get 3-bet: the model prices the 3-bet pot-sized, your loss in it is floored at the chips your raise put in — you can still fold — and only hands above 0.75 equity vs the calling range get any 3-bet-calling credit), and a call slice in between, with your equity measured against exactly that call slice. At plain bet nodes, fold equity is read off the same narrowed range your continue equity uses (combo mass, not a formula), so a pure bluff's EV is range-dependent by design: positive into a range that's been checking (capped, air-heavy), near zero into a sane fresh range, negative into a strong one — the model can finally teach when to bluff, not just how often.

Your plain bets now carry a villain-response branch of their own. The continue range a bet leaves behind is cut into a call slice and a raise slice — taken top-down by rank, sized as max(RAISE_KEEP_FLOOR, RAISE_SLICE_TIGHTEN · totalKeep(r_v)) of the range entering the node, and never more than 0.5 of the continue mass (that keep expression is transcribed from the shipped cut — the constants in it render live above; if the formula ever changes, this sentence is re-derived with it) — and the bet's EV blends three outcomes: everyone folds, the call slice calls (your continue equity re-targets exactly that call slice), or the raise slice raises, priced pot-sized. The raise branch is credited or docked by your equity against the range a raise would re-reveal — including the slowplays a quiet line never fully rules out — taken as the more conservative of a rank-based read and an equity-based read (the equity arm engages only above 0.75 vs the callers). Checks got the mirror-image treatment: when your first-to-act check hands villain the action, the model composes villain's 0.5×-pot stab range, prices your best response to the stab — fold, call, or check-raise, the check-raise counted only when your equity clears the same 25% bluff gate the wording section uses — and blends it with the times villain checks back. Two-sided by construction: a monster's check gains the trap value the stab pays it, and an air check loses the pot-share a stab takes away.

The multiway dials

With three or more players live, the model classifies your hand and discounts realization with five more dials — read live from multiway.ts, not retyped:

DialValueMeaning
STRONG_EQ0.6Equity at or above this classifies the hand as strong
DRAW_EQ0.3Equity at or above this (unmade, pre-river) classifies as a draw
COUNT_DISCOUNT_PER_PLAYER0.05Realization lost per extra live opponent, marginal/weak hands only
COUNT_DISCOUNT_CAP0.15Ceiling on the per-player headcount discount
SANDWICH_PENALTY0.05Extra discount for passive lines that don't close the action this street — strong hands are exempt

One convention to know: bet and raise candidates never take the sandwich penalty — aggressive lines are discounted only by the hand-class headcount discount above. And with more players live, each defender defends like a defender: the keep-fraction the model applies to any one opponent is headcount-independent, while the chance everyone folds shrinks multiplicatively — fold-through tightens with every extra player, which is why multiway pure bluffs grade strictly losing.

What the model still gets wrong (on purpose)

  • on a heads-up flop or turn, the model gives bounded implied-odds credit only to clean straight-or-better draws with at least 7 clean outs in a narrow direct-odds-shortfall window, capped at 1.8 bb — deep-shortfall draws still fold, and gutshots get no credit; multiway and river decisions receive no future-value credit
  • multiway checks keep the flatter trap-credit approximation; only a heads-up check that passes the action to villain receives the explicit check-react response branch
  • when you face a bet, the facing-bet range is the app’s action-narrowed estimate, not a solver's observed betting distribution; fold, call, and raise accounting is explicit, but the conditional range remains heuristic
  • initiative does not add a separate realization bonus: realization follows street, position, texture, range strength, and player count because the controlled benchmark did not isolate a stable extra initiative effect

The five questions before you act

Every immediate postflop estimate this app hands out is the model running the same five questions you can run at the table — in this order:

  1. What's his range? Start from position and the preflop action — the same charts the preflop grades use. An early-position opener's range looks nothing like a button steal's, before a single postflop card matters.
  2. How does his action narrow it? A check keeps the range but discounts its strongest slice (slowplays are rare), and a bet keeps a polarized slice that shrinks continuously as the size grows — value on top, a mass-weighted bluff tail on the bottom. And the narrowing runs forward too: when you bet, the model splits what continues into callers and the raise slice whose raise would re-reveal the strength a quiet line hid. The composition and cap constants printed above are the model's version of exactly this step.
  3. What's my equity against that range? Against the whole narrowed range — not against the one scary hand you're imagining, and not against a random hand either.
  4. What price am I being offered? Pot odds: calling c to win a pot of p needs c / (p + c) equity to break even — the arithmetic from the pot odds topic, unchanged. For qualifying draws, the model now credits bounded future value on top of that direct-odds price. When you're the one betting, remember the price isn't final: your bet can be raised, and the model's breakeven story for a bet now carries that raise-risk branch alongside the fold and call branches.
  5. How much of that equity will I actually realize? Out of position with streets still to come, you keep less than the raw number — the realization table above is the model's discount for exactly that.

When a grade surprises you, walk the five questions and find the one you and the model answered differently. That disagreement is the lesson — whichever of you turns out to be right.