feat(blueprint): postflop subgame wiring + range expansion (Phase 4, #68)#177
Merged
Conversation
) Add a thin Python glue layer that bridges the Premium-A 169-class preflop blueprint (Phase 1) to the postflop range-vs-range Nash solver. The existing chained orchestrator does NOT consume a pre-existing Blueprint asset (it runs its own Stage 1 preflop solve via Route A aggregation), so this PR ships a separate entry point operating from blueprint data. New surface in poker_solver.blueprint_subgame: - derive_continuation_ranges_from_blueprint: walks a preflop action sequence through the blueprint's history-keyed infosets, multiplying per-class action probabilities to produce per-class reach into a given terminal. - expand_classes_to_range: 169-class -> 1326-combo expansion (uniform within class), with board-blocker filtering and per-combo weights threaded into a Range. - solve_postflop_from_blueprint: end-to-end pipeline (lookup -> expand -> postflop solve) returning a BlueprintPostflopResult that carries per-stage wall times for verification. Integration test (tests/test_blueprint_subgame_wiring.py, 15 cases): - Range expansion: uniform within class, weight-scaling across classes, board-blocker filtering, error paths. - Reach derivation: root reach == 1.0; polarized AA shove (10/90) propagates 0.1 reach for AA at continuation; missing-infoset raises; class filtering; bad hero_player rejected. - End-to-end on Qs 7h 2d flop: blueprint -> 1326 expansion -> Rust vector-form CFR returns a simplex-valid strategy; wall time on a 2-class fixture is ~0.9 s (30 iters). No engine code modified. No 169-class engine code modified. Chained orchestrator (chained.py) untouched per Phase 4 scope. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
# Conflicts: # poker_solver/__init__.py
amaster97
added a commit
that referenced
this pull request
May 28, 2026
Preemptive draft for v1.9.0 — ready for ship-trigger after audit clears. Covers the Premium-A blueprint shipping milestone: - 27 precomputed preflop blueprint shards (PR #171 + asset commit 1783bef): 169-class engine 178x/406x/448x speedup; ~21 MB bundle shipped under assets/blueprints/. - Blueprint loader API (PR #174), stack-depth interpolation (PR #173), postflop subgame wiring (PR #177), top-level SolverRouter (PR #181), UI integration (PR #178). - Vector-form BR walk (PR #170): W2.3 strict-PASS, persona table 17/0/0/0 (recorded in PR #184). - CS-bug fix (PR #165): preflop State::initial honors config.initial_contributions. - B10 per-combo frequency train (PRs #149/#154/#158/#160): W2.2 Sarah Range.diff -> PASS. - DCFR optimization ledger (docs/rust_optimization_ledger.md): empirical speedups for PRs #114/#139/#150/#157/#162/#170/#171. Known limitations disclosed honestly: - Flop live-solve OOMs in v1.9.0; flop = blueprint-only. v1.10 task #70 addresses (docs/v1_10_postflop_optimization_plan.md). - top_k_per_side is a speed knob, not a correctness flag. - "Realtime postflop" claim scoped precisely: turn + river only. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced May 28, 2026
amaster97
added a commit
that referenced
this pull request
May 28, 2026
#196) Audits #69 (v1.9.0) and #71 (v1.10.0) both flagged that the persona- table claimed Wendy (Premium-A consumer) coverage existed but the W5.x workflows had never been authored. This PR ships the five W5.x persona tests via tests/test_w5_premium_a_personas.py, restores the persona acceptance spec at docs/pr13_prep/persona_acceptance_spec.md (lost when the docs/pr13_prep/ directory was historically purged), and bumps the snapshot count 17 → 22 in docs/persona_status_2026-05-28-w5x.md. The five workflows: W5.1 — Blueprint Casual Lookup (100 BB / no-ante / AKs, <100 ms warm-cache, 10 cells populated) — PR #174 (BlueprintLoader) W5.2 — Interpolated Depth Lookup (67 BB = 0.65 * v60 + 0.35 * v80 convex blend) — PR #173 (interp) + PR #181 (router) W5.3 — Blueprint → Postflop Chained on Qs7h2d, synthetic 2-class smoke fixture (production-scale OOM-blocked per the v1.10 perf roadmap; documented as a deferred follow-up) — PR #177 + PR #182 + PR #181 W5.4 — Custom Range Fallback (B10 override forces custom_live_solve, not blueprint_lookup) — PR #181 + B10 PRs #149/#154/#158 W5.5 — Ante Selection (40 BB / 72o shifts L1>0.05 across no/half/ full ante) — 27-shard bundle (chore `1783bef`) + PR #174 13/13 tests PASS in 1.13 s on M-series arm64. No engine code touched; docs + tests only. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 tasks
amaster97
added a commit
that referenced
this pull request
May 28, 2026
Updates README + USAGE to reflect v1.10.0 ship state (combined v1.9.0 Premium-A + v1.10 postflop optimization MINOR bump) per the v1.9.0 audit (task #69) findings. v1.9.0 was drafted but never tagged; both docs were stuck at v1.8.x prose. README.md (+150/-80 net): - Status: bump v1.8.0 -> v1.10.0; strike v1.6.0 fork-bomb warning (resolved in v1.8.0 PR #42 727206e; left a historical mention of what was fixed) - Preflop blueprint mode: expand from 3 sentences to a full section covering the four-API surface (BlueprintLoader/interp/subgame/ SolverRouter), Phase 6 UI wiring (PR #178 chart widget source badges + chained tab + live-solve confirmation modal), B10 per-combo editor (PRs #149/#154/#158/#160), Phase 7+8 docs (PRs #175/#176), and v1.10 flop unblock (task #70) - "What's new in v1.10.0" replaces "Recent changes (since v1.8.0)"; cites per-PR for Premium-A train + v1.10 postflop optimization - UI section: chart widget + chained tab now consume real solver (PR #178); standalone ad-hoc tab still mock (PR 10b pending) - Known issues: strike v1.6.0 fork-bomb (resolved), replace with ad-hoc-signing + arm64-only framing USAGE.md (+185/-100 net): - Header: v1.8.x -> v1.10.0; rewrite document baseline + v1.10.0 section pointer paragraph - Path A (.dmg): remove "DO NOT LAUNCH" warning, document Gatekeeper override flow for ad-hoc-signed bundle - New §5.10 "CLI BB-normalization (v1.9.0; canonical in v1.10.0)" covering --pot N --stack M canonical flags + --pot-bb/--stack-bb deprecation warning (PR #152) - §5.9 Preflop blueprint: extend with chained postflop subgame example (solve_postflop_from_blueprint, PR #177) + top-level SolverRouter example (PR #181) + honest perf framing (flop unblocked but benchmark numbers TBD) - §7b Known perf cliffs: bump from v1.7.x to v1.10.0; document flop unblock from v1.9.0 OOM-killed; preserve aggregator-recommended framing for production-scale chart generation - §7 Known limitations: bump from v1.0.0 to v1.10.0; UI partial-real framing (chart widget + chained tab real; standalone tab still mock) - §8 What's coming: drop completed items; flag v1.10 perf benchmark publication as next-up + PR 10b standalone-tab swap - --version output: bump 1.8.0 -> 1.10.0 Ship date: 2026-MM-DD placeholder; honest framing throughout that flop top_k=169 wall numbers are TBD by combined-stack benchmark (task #70 PRs #186-#190 + PR-1 arena + PR-3 vector flop). Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Premium-A Phase 4 (issue #68) — thin Python glue layer that bridges the 169-class preflop blueprint (Phase 1, PR #167 / PR #171) to the postflop range-vs-range Nash solver. The existing chained orchestrator does NOT consume a pre-existing
Blueprintasset (it runs its own Stage 1 preflop solve), so this PR adds a separate entry point operating directly on blueprint data — Phase 4 scope is independent of Phases 2 (loader) and 3 (interpolation).New surface in
poker_solver.blueprint_subgame(also re-exported from the top-level package):derive_continuation_ranges_from_blueprint: walks a preflop action sequence through the blueprint's history-keyed infosets, multiplying per-class action probabilities to produce per-class reach.expand_classes_to_range: 169-class -> 1326-combo expansion (uniform within class), with board-blocker filtering and per-combo weights threaded into aRange.solve_postflop_from_blueprint: full pipeline (lookup -> expand -> postflop solve) returning aBlueprintPostflopResultwith per-stage wall times.Scope hygiene
chained.py) modified. Wider refactor (Phase 4 subplan §4 suggests replacing chained.py's Stage 1 with a blueprint lookup) is deferred — out of this phase's scope.Test plan
tests/test_blueprint_subgame_wiring.py— 15 cases, all passing locally:hero_playerrejected.Qs 7h 2dflop: blueprint -> 1326 expansion -> Rust vector-form CFR returns a simplex-valid strategy.ruff checkclean on new files +__init__.py.tests/test_blueprint_pipeline.py24/24 pass;tests/test_chained_orchestrator.pycollects 9 tests, no broken imports).Wall-time sample
End-to-end blueprint lookup -> 1326 expansion -> postflop subgame solve on a 2-class fixture (AA + KK) on
Qs 7h 2d, 30 iterations:Lookup + expansion are pure Python, microsecond-scale. Solve cost dominates (Rust vector-form CFR, dominated by the 30-iter setting). Production iter counts (500-2000) would scale roughly linearly here.
What this unblocks
Phase 5 (top-level routing layer
Solver.solve(spot)) can now route postflop spots throughsolve_postflop_from_blueprintonce Phases 2 + 3 land the loader / interpolation. Phase 5 will likely also wrap or replacechained.py's Stage 1 to share the blueprint cache.Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
🤖 Generated with Claude Code