pokertools-arena 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,202 @@
1
+ # CONTEXT — canonical decision semantics
2
+
3
+ This document describes the benchmark's fairness contract: what every model
4
+ receives, how a decision is turned into a legal PokerTools action, and which
5
+ properties are asserted by automated tests.
6
+
7
+ ## One canonical contract
8
+
9
+ `src/lib/decision-core.js` is the shared, DOM-free core. Production browser code
10
+ (`src/app.js`), the Node diagnostics harness (`tools/diagnostics/*.js`) and the tests all
11
+ call the same functions. Nothing re-implements decision generation.
12
+
13
+ The canonical chain is:
14
+
15
+ ```
16
+ engine state
17
+ → serializeForAgent(engine, seat, meta, legalActions, recentHands, publicPlayerStats, actionHistory)
18
+ → applyBenchmarkMode(state, mode) // Strategy adds deterministic heroHand
19
+ → legalActionFamilies(legalActions, { toCall }) // stage 1 choice set
20
+ → aggressiveSizesForState(state, family) // stage 2 choice set
21
+ → decideHierarchical(...) // one family call + optional size call
22
+ → resolveHierarchicalAction(...) // one final engine action
23
+ → engine.validate(...) // final legality check
24
+ ```
25
+
26
+ ## Information policy
27
+
28
+ Private (per seat):
29
+
30
+ - hero hole cards only.
31
+
32
+ Public (identical for every seat):
33
+
34
+ - board, pot, blinds, ante, street, button, tournament state, stacks, positions,
35
+ current-hand public actions, recent completed public hands,
36
+ deterministic `publicPlayerStats`, legal action families and (when relevant)
37
+ legal sizes.
38
+
39
+ Optional in Strategy mode:
40
+
41
+ - deterministic `heroHand` (`{ category, description }`), generated by
42
+ `@pokertools/evaluator`, describing the hero only.
43
+
44
+ Never exposed:
45
+
46
+ - opponent hole cards, opponent hand evaluation, other models' reasoning,
47
+ other models' probabilities, provider telemetry, hidden deck, future cards,
48
+ future actions.
49
+
50
+ ## Action families
51
+
52
+ ```
53
+ toCall == 0 → CHECK + (BET or RAISE, whichever the engine makes legal)
54
+ toCall > 0 → FOLD + CALL + (RAISE if legal)
55
+ ```
56
+
57
+ - CHECK and FOLD never coexist (folding a free check is strictly dominated).
58
+ - BET and RAISE never coexist.
59
+ - A family is only exposed if it resolves to a valid PokerTools action.
60
+ - A limped pot where `toCall == 0` and an existing bet is present exposes
61
+ CHECK + RAISE, never BET.
62
+
63
+ ## Deterministic sizing
64
+
65
+ `legalAggressiveSizes(engine, seat, family)` (engine-validated) and
66
+ `aggressiveSizesForState(state, family)` (diagnostics) share the same planner:
67
+
68
+ - at most four buckets: `SMALL` (≈33% pot), `MEDIUM` (≈67% pot),
69
+ `LARGE` (≈100% pot), `ALL_IN`;
70
+ - raises are based on the current price, minimum raise, pot and effective stack;
71
+ - amounts are clamped to the available stack and the minimum legal bet/raise;
72
+ - identical amounts are deduplicated and near-duplicates removed
73
+ (within `max(2, 15% of min(bb, pot))`);
74
+ - all-in is kept only when materially larger than the remaining candidates;
75
+ - fewer than four buckets are returned when fewer are genuinely distinct
76
+ (e.g. only `ALL_IN`, or `SMALL`/`ALL_IN` on a short stack).
77
+
78
+ ## Model interface
79
+
80
+ Stage 1 (family), Jev:
81
+
82
+ ```json
83
+ { "action_family": { "type": "choice", "instructions": "…", "criteria": { "check": "Check", "bet": "Bet" } } }
84
+ ```
85
+
86
+ Stage 1 (family), chat: JSON schema with a single `actionFamily` enum whose
87
+ values are exactly the canonical families.
88
+
89
+ Stage 2 (size), Jev:
90
+
91
+ ```json
92
+ { "bet_size": { "type": "choice", "instructions": "…", "criteria": { "small": "Bet 1,150 chips (8% pot)", "all_in": "Bet 5,369 chips all-in" } } }
93
+ ```
94
+
95
+ Stage 2 (size), chat: JSON schema with a single `sizeId` enum whose values are
96
+ exactly the same size ids presented to Jev.
97
+
98
+ The primary decision contract contains **no prose field**.
99
+
100
+ ## Action clock
101
+
102
+ `decideHierarchical` creates one `combineAbort(timeoutMs, …)` signal for the
103
+ whole decision and passes it to both stages. The family call and the size call
104
+ share the same remaining time; a model never receives a fresh full timer for the
105
+ sizing stage. Paused time is excluded exactly as before.
106
+
107
+ ## Spectator explanations
108
+
109
+ Spectator explanations are:
110
+
111
+ - optional (disabled by default);
112
+ - never part of the decision contract;
113
+ - never fed into future model context;
114
+ - not counted in primary decision latency;
115
+ - generated after the action is applied in an isolated serial queue;
116
+ - never fabricated for Jev (it shows typed probability telemetry instead).
117
+
118
+ ## Benchmark mode
119
+
120
+ `benchmarkMode` is tournament-wide (`strategy` | `raw`). `heroHand` is
121
+ deterministic and describes the hero only. It cannot vary by seat.
122
+
123
+ ## Representation mode
124
+
125
+ `representation` is tournament-wide (`canonical_json` | `compact_json` |
126
+ `markdown`). All seats receive the same semantic state; only serialization
127
+ differs.
128
+
129
+ ## Automated fairness assertions
130
+
131
+ See `tests/unit/hierarchical-decision-tests.mjs` and `tests/unit/decision-diagnostics.mjs`:
132
+
133
+ 1. All models receive the same canonical decision semantics.
134
+ 2. Action families are identical for the same engine state.
135
+ 3. Sizing candidates are identical for the same engine state.
136
+ 4. Strategy/Raw mode applies globally, never per seat.
137
+ 5. `heroHand` is deterministic.
138
+ 6. `heroHand` only describes the hero.
139
+ 7. Opponent cards remain hidden.
140
+ 8. Opponent hand evaluation is never exposed.
141
+ 9. `recentHands` and `publicPlayerStats` remain equivalent across adapters.
142
+ 10. Jev criteria correspond exactly to the chat schemas' enums.
143
+ 11. Chat models cannot select a size not presented to Jev.
144
+ 12. Jev cannot select a size not presented to chat models.
145
+ 13. Final engine actions are validated after both stages.
146
+ 14. Free CHECK never exposes FOLD.
147
+ 15. The total action timer spans both hierarchical stages.
148
+ 16. Spectator explanations cannot affect future model context.
149
+ 17. Spectator explanation latency is not counted as primary action latency.
150
+ 18. Diagnostic perfect-information fixtures cannot enter tournament mode.
151
+
152
+ ## Fixed-state corpus (0.4.0)
153
+
154
+ `tools/diagnostics/corpus.js` is the reusable, immutable fixed-state corpus.
155
+ Every action entry is production-shaped and is used unchanged for flat and
156
+ hierarchical decisions, for every model, for Strategy and Raw modes, and for
157
+ every representation. Gold answers (`expected`) exist only where strict
158
+ dominance, perfect information, or an explicitly declared synthetic opponent
159
+ policy makes the answer deterministic. Ambiguous states carry `expected: null`.
160
+
161
+ The primary architecture comparison is the paired fixed-state test in
162
+ `tools/diagnostics/paired.js`. Real tournament A/B is end-to-end behavioral
163
+ validation only, because actions change future states.
164
+
165
+ ## Family vs sizing correctness
166
+
167
+ `familyCorrect`, `sizeCorrect` and `finalCorrect` are distinct. A model that
168
+ returns `BET SMALL` where the only chip-maximising size is `ALL-IN` is reported
169
+ as **family pass / sizing fail**, never as one generic failure. Sizing accuracy
170
+ is always conditional on a correct family.
171
+
172
+ ## Statistics
173
+
174
+ - `familyEntropyBits`, `sizingEntropyBits` and `flatActionEntropyBits` name the
175
+ probability domain. A generic “entropy” is never reported.
176
+ - Behavioral proportions always carry sample size and a Wilson 95% interval.
177
+ - `fragmentation_flip_rate` is the paired share of runs whose broad family
178
+ changes when only the number of same-family sizing choices changes.
179
+
180
+ ## Counters
181
+
182
+ `tools/diagnostics/counters.js` defines one canonical set:
183
+ `pokerDecisions`, `familyModelCalls`, `sizingModelCalls`, `spectatorModelCalls`,
184
+ `totalModelCalls`, `httpRequests`, `httpRetries`, `rateLimitResponses`,
185
+ `decisionErrors`, `fallbackActions`, `protocolFallbacks`. A hierarchical
186
+ aggressive decision is one poker decision, two model calls and two or more HTTP
187
+ requests if retries occur.
188
+
189
+ ## Additional fairness assertions (0.4.0)
190
+
191
+ 19. The fixed corpus is semantically identical across architecture variants except for the action contract.
192
+ 20. Paired flat/hierarchical runs use the same hero cards, board, stacks, history, memory and public stats.
193
+ 21. Representation variants carry identical semantic state.
194
+ 22. Strategy mode supplies a deterministic `heroHand` to every model; Raw supplies it to none.
195
+ 23. Jev and chat adapters receive the same family set and the same size set.
196
+ 24. Both hierarchical stages share one total action clock.
197
+ 25. The tournament objective is identical for every seat.
198
+ 26. No per-model production prompt tuning exists.
199
+ 27. No provider-specific poker facts are injected.
200
+ 28. Spectator explanations are disabled in rigorous runs.
201
+ 29. Diagnostic-only hidden information is structurally impossible in tournament mode.
202
+ 30. All human-readable release totals derive from one machine-readable summary.
@@ -0,0 +1,102 @@
1
+ # pokertools-arena 0.4.0 — benchmark methodology & results
2
+
3
+ Generated: 2026-09-19T18:19:58.352Z
4
+ Methodology: paired fixed-state corpus; deterministic interleaving with recorded experiment seed.
5
+
6
+ ## Totals (single source of truth)
7
+
8
+ poker decisions: 79 · model calls: 97 · HTTP requests: 97 · retries: 0 · decision errors: 0 · fallbacks: 0
9
+
10
+ > A hierarchical aggressive poker decision is **1 poker decision**, **2 model calls** and **2+ HTTP requests** if retries occur. These counters are never interchangeable.
11
+
12
+ ## 1. Methodology
13
+
14
+ Fixed-state paired corpus is the primary architecture comparison; every state is identical across flat and hierarchical, execution is deterministically interleaved with a recorded seed, family and sizing correctness are reported separately, and behavioral proportions carry Wilson 95% intervals. Real tournaments are end-to-end validation only.
15
+
16
+ ## 2. Strict correctness
17
+
18
+ | Architecture | Family accuracy | Sizing (given family) | Final accuracy | n |
19
+ | --- | --- | --- | --- | --- |
20
+ | flat | 23/24 (96%) | 4/4 (100%) | 23/24 (96%) | 24 |
21
+ | hierarchical | 24/24 (100%) | 3/4 (75%) | 23/24 (96%) | 24 |
22
+
23
+ ## 3. Family correctness
24
+
25
+ | Model | Architecture | Family correct | Family accuracy | 95% CI | n |
26
+ | --- | --- | --- | --- | --- | --- |
27
+ | Gemma | flat | 14/14 | 100% | 78%–100% | 14 |
28
+ | Gemma | hierarchical | 14/14 | 100% | 78%–100% | 14 |
29
+ | Qwen | flat | 5/6 | 83% | 44%–97% | 6 |
30
+ | Qwen | hierarchical | 6/6 | 100% | 61%–100% | 6 |
31
+ | Jev | flat | 6/6 | 100% | 61%–100% | 6 |
32
+ | Jev | hierarchical | 6/6 | 100% | 61%–100% | 6 |
33
+
34
+ ## 4. Sizing correctness (conditional on correct family)
35
+
36
+ | Model | Architecture | Sizing correct | Sizing accuracy | 95% CI | n |
37
+ | --- | --- | --- | --- | --- | --- |
38
+ | Gemma | flat | 2/2 | 100% | 34%–100% | 2 |
39
+ | Gemma | hierarchical | 2/2 | 100% | 34%–100% | 2 |
40
+ | Qwen | flat | 1/1 | 100% | 21%–100% | 1 |
41
+ | Qwen | hierarchical | 0/1 | 0% | 0%–79% | 1 |
42
+ | Jev | flat | 1/1 | 100% | 21%–100% | 1 |
43
+ | Jev | hierarchical | 1/1 | 100% | 21%–100% | 1 |
44
+
45
+ ## 5. Action fragmentation
46
+
47
+ _No fragmentation data._
48
+
49
+ ## 6. Flat vs hierarchical paired comparison
50
+
51
+ | Model | Flat family | Hier family | Family agreement | 95% CI | Flips | n |
52
+ | --- | --- | --- | --- | --- | --- | --- |
53
+ | Gemma | 14/14 (100%) | 14/14 (100%) | 96% | 82%–99% | 1 | 27 |
54
+ | Qwen | 5/6 (83%) | 6/6 (100%) | 83% | 44%–97% | 1 | 6 |
55
+ | Jev | 6/6 (100%) | 6/6 (100%) | 100% | 61%–100% | 0 | 6 |
56
+
57
+ ## 7. Strategy vs Raw cognition
58
+
59
+ Strategy (deterministic heroHand for every model) and Raw cognition (models infer hand strength) are separate benchmark tracks and are never aggregated into one model score.
60
+
61
+ ## 8. Representation sensitivity
62
+
63
+ _No data._
64
+
65
+ ## 9. Performance
66
+
67
+ | Model | Architecture | Poker decisions | Model calls | HTTP requests | Mean latency | P95 | Tokens | Cost |
68
+ | --- | --- | --- | --- | --- | --- | --- | --- | --- |
69
+ | Gemma | paired | 55 | 69 | — | 1857ms | 2237ms | 63031 | — |
70
+ | Qwen | paired | 12 | 14 | — | 6797ms | 9262ms | 15062 | — |
71
+ | Jev | paired | 12 | 14 | — | 581ms | 1314ms | 16609 | — |
72
+
73
+ ## 10. Real tournament behavior (end-to-end validation)
74
+
75
+ No real tournament A/B run was attached to this release.
76
+
77
+ ## 11. Jev telemetry
78
+
79
+ | Architecture | Aggressive family mass | Selected family probability | Top−second gap | Family entropy (bits) | Sizing entropy (bits) |
80
+ | --- | --- | --- | --- | --- | --- |
81
+ | flat | 0% | 0% | 82% | 0.401 | — |
82
+ | hierarchical | 37% | 86% | 73% | 0.469 | 0.424 |
83
+
84
+ ## 12. Fairness verification
85
+
86
+ - Fixed corpus states are byte-identical across architecture variants except for the action contract.
87
+ - Paired flat/hierarchical runs use the same hero cards, board, stacks, history, memory and public stats.
88
+ - Representation variants carry identical semantic state (offline assertion).
89
+ - Strategy mode supplies a deterministic heroHand to every model; Raw mode supplies it to none.
90
+ - Jev and chat adapters receive exactly the same family and size enums (offline assertion).
91
+ - The total action clock is shared across both hierarchical stages.
92
+ - Spectator explanations are disabled in rigorous runs; when enabled they are isolated and counter-separated.
93
+ - No per-model production prompt tuning exists and no provider-specific poker facts are injected.
94
+ - Diagnostic-only hidden information is structurally impossible in tournament mode.
95
+
96
+ ## 13. Limitations
97
+
98
+ - Behavioral proportion estimates are only as strong as the cell sample size; small cells carry wide Wilson intervals.
99
+ - Paired architecture agreement measures decision-policy stability on fixed states, not win-rate superiority.
100
+ - Tournament win rate is not a conclusion at these sample sizes, and tournament trajectories diverge after the first different action.
101
+ - Provider rate limits and model version drift can affect reproducibility even for identical fixed states.
102
+
@@ -0,0 +1,337 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "version": "0.4.0",
4
+ "generatedAt": "2026-09-19T18:19:58.352Z",
5
+ "experiments": [
6
+ "paired"
7
+ ],
8
+ "counters": {
9
+ "pokerDecisions": 79,
10
+ "familyModelCalls": 79,
11
+ "sizingModelCalls": 18,
12
+ "spectatorModelCalls": 0,
13
+ "totalModelCalls": 97,
14
+ "httpRequests": 97,
15
+ "httpRetries": 0,
16
+ "rateLimitResponses": 0,
17
+ "decisionErrors": 0,
18
+ "fallbackActions": 0,
19
+ "protocolFallbacks": 2
20
+ },
21
+ "sections": {
22
+ "methodology": "Fixed-state paired corpus is the primary architecture comparison; every state is identical across flat and hierarchical, execution is deterministically interleaved with a recorded seed, family and sizing correctness are reported separately, and behavioral proportions carry Wilson 95% intervals. Real tournaments are end-to-end validation only.",
23
+ "strict": [
24
+ {
25
+ "architecture": "flat",
26
+ "family": {
27
+ "successes": 23,
28
+ "trials": 24,
29
+ "rate": 0.9583333333333334,
30
+ "ci95": {
31
+ "low": 0.7975777375115778,
32
+ "high": 0.992606734645195
33
+ }
34
+ },
35
+ "sizingGivenCorrectFamily": {
36
+ "successes": 4,
37
+ "trials": 4,
38
+ "rate": 1,
39
+ "ci95": {
40
+ "low": 0.5100999795960008,
41
+ "high": 1
42
+ }
43
+ },
44
+ "final": {
45
+ "successes": 23,
46
+ "trials": 24,
47
+ "rate": 0.9583333333333334,
48
+ "ci95": {
49
+ "low": 0.7975777375115778,
50
+ "high": 0.992606734645195
51
+ }
52
+ }
53
+ },
54
+ {
55
+ "architecture": "hierarchical",
56
+ "family": {
57
+ "successes": 24,
58
+ "trials": 24,
59
+ "rate": 1,
60
+ "ci95": {
61
+ "low": 0.8620194241710247,
62
+ "high": 1
63
+ }
64
+ },
65
+ "sizingGivenCorrectFamily": {
66
+ "successes": 3,
67
+ "trials": 4,
68
+ "rate": 0.75,
69
+ "ci95": {
70
+ "low": 0.3006360524426366,
71
+ "high": 0.9544139373553637
72
+ }
73
+ },
74
+ "final": {
75
+ "successes": 23,
76
+ "trials": 24,
77
+ "rate": 0.9583333333333334,
78
+ "ci95": {
79
+ "low": 0.7975777375115778,
80
+ "high": 0.992606734645195
81
+ }
82
+ }
83
+ }
84
+ ],
85
+ "family": [
86
+ {
87
+ "model": "Gemma",
88
+ "architecture": "flat",
89
+ "successes": 14,
90
+ "trials": 14,
91
+ "rate": 1,
92
+ "ci95": {
93
+ "low": 0.7846829880728186,
94
+ "high": 1
95
+ }
96
+ },
97
+ {
98
+ "model": "Gemma",
99
+ "architecture": "hierarchical",
100
+ "successes": 14,
101
+ "trials": 14,
102
+ "rate": 1,
103
+ "ci95": {
104
+ "low": 0.7846829880728186,
105
+ "high": 1
106
+ }
107
+ },
108
+ {
109
+ "model": "Qwen",
110
+ "architecture": "flat",
111
+ "successes": 5,
112
+ "trials": 6,
113
+ "rate": 0.8333333333333334,
114
+ "ci95": {
115
+ "low": 0.43649056343635395,
116
+ "high": 0.9699474141282697
117
+ }
118
+ },
119
+ {
120
+ "model": "Qwen",
121
+ "architecture": "hierarchical",
122
+ "successes": 6,
123
+ "trials": 6,
124
+ "rate": 1,
125
+ "ci95": {
126
+ "low": 0.6096569663469354,
127
+ "high": 0.9999999999999999
128
+ }
129
+ },
130
+ {
131
+ "model": "Jev",
132
+ "architecture": "flat",
133
+ "successes": 6,
134
+ "trials": 6,
135
+ "rate": 1,
136
+ "ci95": {
137
+ "low": 0.6096569663469354,
138
+ "high": 0.9999999999999999
139
+ }
140
+ },
141
+ {
142
+ "model": "Jev",
143
+ "architecture": "hierarchical",
144
+ "successes": 6,
145
+ "trials": 6,
146
+ "rate": 1,
147
+ "ci95": {
148
+ "low": 0.6096569663469354,
149
+ "high": 0.9999999999999999
150
+ }
151
+ }
152
+ ],
153
+ "sizing": [
154
+ {
155
+ "model": "Gemma",
156
+ "architecture": "flat",
157
+ "successes": 2,
158
+ "trials": 2,
159
+ "rate": 1,
160
+ "ci95": {
161
+ "low": 0.34237195288961925,
162
+ "high": 1
163
+ }
164
+ },
165
+ {
166
+ "model": "Gemma",
167
+ "architecture": "hierarchical",
168
+ "successes": 2,
169
+ "trials": 2,
170
+ "rate": 1,
171
+ "ci95": {
172
+ "low": 0.34237195288961925,
173
+ "high": 1
174
+ }
175
+ },
176
+ {
177
+ "model": "Qwen",
178
+ "architecture": "flat",
179
+ "successes": 1,
180
+ "trials": 1,
181
+ "rate": 1,
182
+ "ci95": {
183
+ "low": 0.20654329147389294,
184
+ "high": 1
185
+ }
186
+ },
187
+ {
188
+ "model": "Qwen",
189
+ "architecture": "hierarchical",
190
+ "successes": 0,
191
+ "trials": 1,
192
+ "rate": 0,
193
+ "ci95": {
194
+ "low": 0,
195
+ "high": 0.7934567085261071
196
+ }
197
+ },
198
+ {
199
+ "model": "Jev",
200
+ "architecture": "flat",
201
+ "successes": 1,
202
+ "trials": 1,
203
+ "rate": 1,
204
+ "ci95": {
205
+ "low": 0.20654329147389294,
206
+ "high": 1
207
+ }
208
+ },
209
+ {
210
+ "model": "Jev",
211
+ "architecture": "hierarchical",
212
+ "successes": 1,
213
+ "trials": 1,
214
+ "rate": 1,
215
+ "ci95": {
216
+ "low": 0.20654329147389294,
217
+ "high": 1
218
+ }
219
+ }
220
+ ],
221
+ "fragmentation": null,
222
+ "paired": [
223
+ {
224
+ "model": "Gemma",
225
+ "flatFamily": "14/14 (100%)",
226
+ "hierarchicalFamily": "14/14 (100%)",
227
+ "familyAgreement": 0.9629629629629629,
228
+ "ci95": {
229
+ "low": 0.8171614606584348,
230
+ "high": 0.9934320234669025
231
+ },
232
+ "familyFlips": 1,
233
+ "n": 27
234
+ },
235
+ {
236
+ "model": "Qwen",
237
+ "flatFamily": "5/6 (83%)",
238
+ "hierarchicalFamily": "6/6 (100%)",
239
+ "familyAgreement": 0.8333333333333334,
240
+ "ci95": {
241
+ "low": 0.43649056343635395,
242
+ "high": 0.9699474141282697
243
+ },
244
+ "familyFlips": 1,
245
+ "n": 6
246
+ },
247
+ {
248
+ "model": "Jev",
249
+ "flatFamily": "6/6 (100%)",
250
+ "hierarchicalFamily": "6/6 (100%)",
251
+ "familyAgreement": 1,
252
+ "ci95": {
253
+ "low": 0.6096569663469354,
254
+ "high": 0.9999999999999999
255
+ },
256
+ "familyFlips": 0,
257
+ "n": 6
258
+ }
259
+ ],
260
+ "strategyVsRaw": "Strategy (deterministic heroHand for every model) and Raw cognition (models infer hand strength) are separate benchmark tracks and are never aggregated into one model score.",
261
+ "representations": [],
262
+ "performance": [
263
+ {
264
+ "model": "Gemma",
265
+ "modelId": "google/gemma-4-26b-a4b-it",
266
+ "architecture": "paired",
267
+ "pokerDecisions": 55,
268
+ "modelCalls": 69,
269
+ "httpRequests": null,
270
+ "latencyMean": 1856.7818181818182,
271
+ "latencyP95": 2237,
272
+ "tokens": 63031,
273
+ "cost": null
274
+ },
275
+ {
276
+ "model": "Qwen",
277
+ "modelId": "qwen/qwen3.8-flash",
278
+ "architecture": "paired",
279
+ "pokerDecisions": 12,
280
+ "modelCalls": 14,
281
+ "httpRequests": null,
282
+ "latencyMean": 6797,
283
+ "latencyP95": 9262,
284
+ "tokens": 15062,
285
+ "cost": null
286
+ },
287
+ {
288
+ "model": "Jev",
289
+ "modelId": "typesafe/jev-1.13",
290
+ "architecture": "paired",
291
+ "pokerDecisions": 12,
292
+ "modelCalls": 14,
293
+ "httpRequests": null,
294
+ "latencyMean": 580.75,
295
+ "latencyP95": 1314,
296
+ "tokens": 16609,
297
+ "cost": null
298
+ }
299
+ ],
300
+ "tournament": "No real tournament A/B run was attached to this release.",
301
+ "jevTelemetry": [
302
+ {
303
+ "architecture": "flat",
304
+ "aggressiveFamilyMass": null,
305
+ "selectedFamilyProbability": 0,
306
+ "familyTopSecondGap": 0.8233333333333333,
307
+ "familyEntropyBits": 0.40138271077233806,
308
+ "sizingEntropyBits": null
309
+ },
310
+ {
311
+ "architecture": "hierarchical",
312
+ "aggressiveFamilyMass": 0.37166666666666665,
313
+ "selectedFamilyProbability": 0.8649999999999999,
314
+ "familyTopSecondGap": 0.73,
315
+ "familyEntropyBits": 0.4692699804388758,
316
+ "sizingEntropyBits": 0.42444237994881645
317
+ }
318
+ ],
319
+ "fairness": [
320
+ "Fixed corpus states are byte-identical across architecture variants except for the action contract.",
321
+ "Paired flat/hierarchical runs use the same hero cards, board, stacks, history, memory and public stats.",
322
+ "Representation variants carry identical semantic state (offline assertion).",
323
+ "Strategy mode supplies a deterministic heroHand to every model; Raw mode supplies it to none.",
324
+ "Jev and chat adapters receive exactly the same family and size enums (offline assertion).",
325
+ "The total action clock is shared across both hierarchical stages.",
326
+ "Spectator explanations are disabled in rigorous runs; when enabled they are isolated and counter-separated.",
327
+ "No per-model production prompt tuning exists and no provider-specific poker facts are injected.",
328
+ "Diagnostic-only hidden information is structurally impossible in tournament mode."
329
+ ]
330
+ },
331
+ "caveats": [
332
+ "Behavioral proportion estimates are only as strong as the cell sample size; small cells carry wide Wilson intervals.",
333
+ "Paired architecture agreement measures decision-policy stability on fixed states, not win-rate superiority.",
334
+ "Tournament win rate is not a conclusion at these sample sizes, and tournament trajectories diverge after the first different action.",
335
+ "Provider rate limits and model version drift can affect reproducibility even for identical fixed states."
336
+ ]
337
+ }
@@ -0,0 +1,15 @@
1
+ # Third-party notices
2
+
3
+ `pokertools-arena` bundles the following third-party packages at build time:
4
+
5
+ - **@pokertools/engine** (1.0.20) — MIT — the browser poker rules engine used to
6
+ deal hands, validate legal actions and settle pots.
7
+ - **@pokertools/evaluator** (1.0.20) — MIT — deterministic five-card poker hand
8
+ evaluation used to generate the Strategy-mode `heroHand` classification.
9
+
10
+ Development-only tooling:
11
+
12
+ - **esbuild** — MIT — used only to produce the static `dist/` build.
13
+
14
+ No third-party package is used to generate model decisions, prompts, scores or
15
+ fairness assertions.