Skip to content

v1.7.0: aggregator->vector wiring + CLI subcommands

Choose a tag to compare

@amaster97 amaster97 released this 23 May 23:06
· 270 commits to main since this release

What's New

solve_range_vs_range_nash direct API (PR 43)

Joint range Nash equilibrium routed through the Rust vector-form CFR. Distinct from the aggregator pattern's per-combo blueprint approach; 12 tests including W3.5-style monotone polarization validation.

CLI subcommands (PR 39)

  • poker-solver pushfold - preflop push/fold chart lookup
  • poker-solver river - river-only solve
  • poker-solver parity - Brown reference parity comparison

Status notes

  • v1.6.1 engine bundle: HELD pending acceptance gate redefinition (deep-cap Brown apples-to-apples reveals architectural divergence in payoff convention)
  • PR 44 .dmg packaging fix: verified on disk; ready for Gate 5 attachment

Test results

  • Rust lib: 50/50 passing
  • Python nash wrapper: 12/12 passing
  • CLI subcommands: 6/6 passing (1 env-skipped)

Post-release validation findings (2026-05-23 late)

Persona acceptance retesting after this release surfaced an API semantics nuance that users should understand. Initial retests suggested a wrapper bug; a subsequent diff-test investigation confirmed there is no bug -- but the result clarifies how solve_range_vs_range_nash interprets range inputs.

Class-label inputs vs. combo-level inputs

solve_range_vs_range_nash accepts ranges as class labels (e.g., AA, KK, AKs, AKo). Internally, the wrapper expands each class to its full combo set: AA -> 6 combos, KK -> 6, AKs -> 4, AKo -> 12, etc. A 15-class symmetric input expands to ~79 combos per player.

The class-expanded range can have a Nash equilibrium that differs meaningfully from a hand-curated combo subset of the same hand classes. For example, on a monotone Ts8s6s4c2d-ish board:

  • A hand-curated 15-combo input (one specific combo per class) yields AA pure-check
  • The full class-expansion (79 combos) yields AA mixing toward small bets -- because in the larger range, AA dominates more of villain's range AND its specific suit combos (AhAd, AhAc, etc.) block villain's AKs/AKo bluff candidates

Both are valid Nash equilibria for their respective inputs. Neither is a bug.

Workflow guidance

  • For population-level frequency reads on production ranges: use solve_range_vs_range (aggregator path, faster, designed for blueprint-style analysis)
  • For tight per-combo pot-odds bluff-catch decisions: use solve_range_vs_range_nash with hand-curated combo lists (use 4-char labels like AhKh, JhJd instead of class labels like AKs, JJ)
  • For Nash on full class-expanded ranges: use class labels as designed; understand that the answer reflects the class-expanded range's Nash, not a subset's

Performance scope

Nash path scales linearly in iterations but super-linearly in street depth and class count. Viable envelopes (Sarah's <=5 min budget):

  • River: any practical size
  • Turn: <=4 classes x <=200 iter, OR <=8 classes x <=100 iter
  • Flop: NOT interactive on Nash path; use the aggregator (solve_range_vs_range, ~1 s/flop solve)

See USAGE.md section 5.6 for code examples and full guidance.

What v1.7.0 ships

  • True joint Nash for class-expanded ranges via solve_range_vs_range_nash [shipped]
  • Distinct from aggregator's per-combo blueprint pattern [shipped]
  • 12 tests in tests/test_range_vs_range_nash.py validating correctness on small fixtures [shipped]
  • CLI subcommands: pushfold, river, parity [shipped]

See CHANGELOG.md for full details.


Post-publication notes (2026-05-26)

Three days after v1.7.0 shipped, the release roadmap was restructured. Readers landing here from search engines or release lists should know:

  • v1.6.1 hold has been LIFTED. The hold listed above ("v1.6.1 engine bundle: HELD pending acceptance gate redefinition") was lifted on 2026-05-26 per the ship review. See docs/v1_6_1_ship_hold_review_2026-05-26.md.

  • A83 deep-cap divergence cause corrected. The status note above attributed the divergence to "architectural divergence in payoff convention." The actual cause is Nash multiplicity at deep-cap indifference manifolds (empirically confirmed via three independent DCFR-math audits + a Track A bench). It is a design difference vs. Brown/Pluribus, not a bug. See docs/a83_nash_multiplicity_confirmed_2026-05-26.md.

  • Next release boundary is v1.8.0. v1.6.1 and v1.7.1 will not ship as separate tagged releases; their fixes shipped piecewise on main and are folded into v1.8.0. See docs/v1_7_1_tag_decision_2026-05-26.md.

The solve_range_vs_range_nash API-semantics note above remains accurate.