@event4u/agent-config 5.7.0 → 5.9.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.
Files changed (164) hide show
  1. package/.agent-src/commands/agent-handoff.md +1 -1
  2. package/.agent-src/commands/agent-status.md +1 -1
  3. package/.agent-src/commands/agents/audit.md +1 -1
  4. package/.agent-src/commands/agents/init.md +1 -1
  5. package/.agent-src/commands/agents/user/accept.md +3 -3
  6. package/.agent-src/commands/agents/user/init.md +4 -4
  7. package/.agent-src/commands/agents/user/show.md +3 -3
  8. package/.agent-src/commands/agents/user/update.md +3 -3
  9. package/.agent-src/commands/agents/user.md +1 -1
  10. package/.agent-src/commands/agents.md +1 -1
  11. package/.agent-src/commands/analytics/prune.md +1 -1
  12. package/.agent-src/commands/analytics/show.md +1 -1
  13. package/.agent-src/commands/analytics.md +1 -1
  14. package/.agent-src/commands/bug-fix.md +1 -1
  15. package/.agent-src/commands/challenge-me.md +1 -1
  16. package/.agent-src/commands/chat-history/import.md +1 -1
  17. package/.agent-src/commands/chat-history/learn.md +1 -1
  18. package/.agent-src/commands/chat-history/show.md +1 -1
  19. package/.agent-src/commands/chat-history.md +1 -1
  20. package/.agent-src/commands/check-current-md.md +1 -1
  21. package/.agent-src/commands/condense.md +1 -1
  22. package/.agent-src/commands/context.md +1 -1
  23. package/.agent-src/commands/cost-report.md +1 -1
  24. package/.agent-src/commands/council.md +3 -3
  25. package/.agent-src/commands/create-pr/description-only.md +1 -1
  26. package/.agent-src/commands/create-pr.md +1 -1
  27. package/.agent-src/commands/e2e-heal.md +1 -1
  28. package/.agent-src/commands/e2e-plan.md +1 -1
  29. package/.agent-src/commands/feature.md +1 -1
  30. package/.agent-src/commands/fix/ci.md +1 -1
  31. package/.agent-src/commands/fix/portability.md +1 -1
  32. package/.agent-src/commands/fix/pr-bot-comments.md +1 -1
  33. package/.agent-src/commands/fix/pr-comments.md +1 -1
  34. package/.agent-src/commands/fix/pr-developer-comments.md +1 -1
  35. package/.agent-src/commands/fix/refs.md +1 -1
  36. package/.agent-src/commands/fix/seeder.md +1 -1
  37. package/.agent-src/commands/fix.md +1 -1
  38. package/.agent-src/commands/judge.md +1 -1
  39. package/.agent-src/commands/knowledge/cross-repo.md +1 -1
  40. package/.agent-src/commands/knowledge/forget.md +1 -1
  41. package/.agent-src/commands/knowledge/ingest.md +1 -1
  42. package/.agent-src/commands/knowledge/list.md +1 -1
  43. package/.agent-src/commands/knowledge.md +1 -1
  44. package/.agent-src/commands/memory/add.md +1 -1
  45. package/.agent-src/commands/memory/learn-low-impact.md +1 -1
  46. package/.agent-src/commands/memory/load.md +1 -1
  47. package/.agent-src/commands/memory/mine-session.md +1 -1
  48. package/.agent-src/commands/memory/promote.md +1 -1
  49. package/.agent-src/commands/memory/propose.md +1 -1
  50. package/.agent-src/commands/memory.md +1 -1
  51. package/.agent-src/commands/mode.md +1 -1
  52. package/.agent-src/commands/optimize/agents-dir.md +1 -1
  53. package/.agent-src/commands/optimize/augmentignore.md +1 -1
  54. package/.agent-src/commands/optimize/rtk.md +1 -1
  55. package/.agent-src/commands/optimize/skills.md +1 -1
  56. package/.agent-src/commands/optimize.md +1 -1
  57. package/.agent-src/commands/orchestrate.md +1 -1
  58. package/.agent-src/commands/override/create.md +1 -1
  59. package/.agent-src/commands/override/manage.md +1 -1
  60. package/.agent-src/commands/override.md +1 -1
  61. package/.agent-src/commands/package-reset.md +1 -1
  62. package/.agent-src/commands/prediction-pool.md +31 -12
  63. package/.agent-src/commands/profile/activate.md +81 -0
  64. package/.agent-src/commands/profile/deactivate.md +68 -0
  65. package/.agent-src/commands/profile/show.md +70 -0
  66. package/.agent-src/commands/profile.md +68 -0
  67. package/.agent-src/commands/project-health.md +1 -1
  68. package/.agent-src/commands/quality-fix.md +1 -1
  69. package/.agent-src/commands/roadmap/process-full.md +1 -1
  70. package/.agent-src/commands/roadmap/process-phase.md +1 -1
  71. package/.agent-src/commands/roadmap/process-step.md +1 -1
  72. package/.agent-src/commands/roadmap.md +1 -1
  73. package/.agent-src/commands/set-cost-profile.md +1 -1
  74. package/.agent-src/commands/skill/preview.md +3 -3
  75. package/.agent-src/commands/skill.md +1 -1
  76. package/.agent-src/commands/skills/discover.md +1 -1
  77. package/.agent-src/commands/skills.md +1 -1
  78. package/.agent-src/commands/sync-agent-settings.md +1 -1
  79. package/.agent-src/commands/sync-gitignore/fix.md +1 -1
  80. package/.agent-src/commands/sync-gitignore.md +1 -1
  81. package/.agent-src/commands/update-form-request-messages.md +1 -1
  82. package/.agent-src/skills/check-refs/SKILL.md +1 -1
  83. package/.agent-src/skills/finishing-a-development-branch/SKILL.md +1 -1
  84. package/.agent-src/skills/git-workflow/SKILL.md +1 -1
  85. package/.agent-src/skills/jira-integration/SKILL.md +1 -1
  86. package/.agent-src/skills/markitdown/SKILL.md +1 -1
  87. package/.agent-src/skills/prediction-pool-optimizer/SKILL.md +195 -77
  88. package/.agent-src/skills/prediction-pool-optimizer/evals/triggers.json +3 -1
  89. package/.agent-src/skills/prediction-pool-optimizer/reference/ev-fixtures.md +111 -16
  90. package/.agent-src/skills/prediction-pool-optimizer/reference/odds-and-bonus.md +109 -0
  91. package/.agent-src/skills/rtk-output-filtering/SKILL.md +1 -1
  92. package/.agent-src/skills/script-writing/SKILL.md +1 -1
  93. package/.agent-src/skills/token-optimizer/SKILL.md +1 -1
  94. package/.agent-src/skills/using-git-worktrees/SKILL.md +1 -1
  95. package/.agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  96. package/.agent-src/templates/scripts/work_engine/_lib/agent_settings.py +52 -5
  97. package/.claude-plugin/marketplace.json +370 -366
  98. package/CHANGELOG.md +77 -0
  99. package/README.md +2 -2
  100. package/config/discovery/session-profiles.yml +37 -0
  101. package/dist/discovery/deprecation-report.md +1 -1
  102. package/dist/discovery/discovery-manifest.json +183 -95
  103. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  104. package/dist/discovery/discovery-manifest.summary.md +3 -3
  105. package/dist/discovery/orphan-report.md +1 -1
  106. package/dist/discovery/packs.json +9 -5
  107. package/dist/discovery/trust-report.md +2 -2
  108. package/dist/discovery/workspaces.json +8 -4
  109. package/dist/mcp/registry-manifest.json +3 -3
  110. package/docs/architecture.md +1 -1
  111. package/docs/catalog.md +7 -3
  112. package/docs/contracts/command-clusters.md +2 -0
  113. package/docs/contracts/session-profile-overlay.md +120 -0
  114. package/docs/customization.md +26 -0
  115. package/docs/decisions/ADR-010-profile-pack-preset-boundary.md +36 -0
  116. package/docs/decisions/ADR-038-canonical-settings-path.md +66 -0
  117. package/docs/decisions/ADR-039-claude-skills-untracked.md +139 -0
  118. package/docs/decisions/INDEX.md +2 -0
  119. package/docs/development.md +12 -0
  120. package/docs/getting-started.md +1 -1
  121. package/docs/guidelines/agent-infra/layered-settings.md +8 -2
  122. package/docs/skills-catalog.md +5 -1
  123. package/llms.txt +4 -0
  124. package/package.json +1 -1
  125. package/scripts/__pycache__/validate_frontmatter.cpython-312.pyc +0 -0
  126. package/scripts/_cli/cmd_doctor.py +180 -16
  127. package/scripts/_cli/cmd_versions.py +2 -2
  128. package/scripts/_lib/__pycache__/__init__.cpython-312.pyc +0 -0
  129. package/scripts/_lib/__pycache__/agent_src.cpython-312.pyc +0 -0
  130. package/scripts/_lib/agent_settings.py +52 -5
  131. package/scripts/_lib/agent_src.py +30 -0
  132. package/scripts/ai_council/session.py +5 -1
  133. package/scripts/audit_command_surface.py +7 -1
  134. package/scripts/audit_initial_context.py +10 -2
  135. package/scripts/check_gate_paths.py +117 -0
  136. package/scripts/check_references.py +51 -2
  137. package/scripts/check_release_published.py +145 -0
  138. package/scripts/check_test_coverage_diff.py +180 -0
  139. package/scripts/compile_router.py +5 -1
  140. package/scripts/condense.py +79 -2
  141. package/scripts/config/session_profiles.py +492 -0
  142. package/scripts/council_cli.py +5 -1
  143. package/scripts/hook_manifest.yaml +15 -7
  144. package/scripts/hooks/dispatch_hook.py +8 -0
  145. package/scripts/install-hooks.sh +2 -1
  146. package/scripts/install.py +76 -5
  147. package/scripts/inventory_abstraction_budget.py +6 -1
  148. package/scripts/lint_agents_md.py +11 -4
  149. package/scripts/lint_hook_concern_budget.py +5 -1
  150. package/scripts/lint_marketplace.py +18 -7
  151. package/scripts/lint_roadmap_ci_steps.py +5 -1
  152. package/scripts/lint_roadmap_complexity.py +5 -1
  153. package/scripts/mcp_server/prompts.py +5 -1
  154. package/scripts/prediction-pool/pool_winsim.py +236 -0
  155. package/scripts/prediction-pool/score_ev.py +188 -0
  156. package/scripts/profile_staleness_hook.py +69 -0
  157. package/scripts/release.py +54 -31
  158. package/scripts/roadmap_progress_hook.py +56 -6
  159. package/scripts/smoke_quickstart.py +3 -2
  160. package/scripts/sync_agent_settings.py +8 -3
  161. package/scripts/validate_agent_settings.py +5 -1
  162. package/scripts/validate_decision_engine.py +5 -1
  163. package/scripts/measure_roadmap_trajectory.py +0 -112
  164. package/scripts/verify_roadmap_closure.py +0 -327
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  model_tier: high
3
3
  name: prediction-pool-optimizer
4
- description: "Optimize prediction-pool tips (kicktipp etc.): pool rules + market odds → the expected-points-maximizing tip per match. Triggers 'optimize my pool tips', 'best kicktipp picks', 'predict'."
4
+ description: "Optimize prediction-pool tips (kicktipp etc.): rules + multi-book consensus odds → expected-points-max answer for every question, scores AND bonus. Triggers 'optimize my pool tips', 'predict'."
5
5
  domain: product
6
6
  personas: []
7
7
  workspaces:
@@ -18,19 +18,22 @@ install:
18
18
 
19
19
  # prediction-pool-optimizer
20
20
 
21
- > Turn a prediction pool's **scoring rules** plus **market odds** into the
22
- > tip that maximizes **expected points** — not the most likely outcome.
23
- > Sport-agnostic core with per-sport probability blocks. Consumed by
24
- > [`/prediction-pool`](../../commands/prediction-pool.md). The optimization target is
25
- > the pool's score, so the chain is always **rules → odds → expected value
26
- > participant field tip**, never "who wins this match?".
21
+ > Turn a prediction pool's **scoring rules** plus a **consensus of the major
22
+ > bookmakers' odds** into the answer that maximizes **expected points** — not
23
+ > the most likely outcome for **every open question in the pool**: match
24
+ > scores AND every bonus / award / special question (top scorer, group
25
+ > winners, champion, most cards …). Sport-agnostic core with per-sport
26
+ > probability blocks. Consumed by [`/prediction-pool`](../../commands/prediction-pool.md).
27
+ > The optimization target is the pool's score, so the chain is always
28
+ > **rules → odds → expected value → participant field → answer**, never
29
+ > "who wins this match?".
27
30
 
28
31
  ## When to use
29
32
 
30
- Use when someone wants the best tips for a prediction / betting pool
33
+ When someone wants the best tips for a prediction / betting pool
31
34
  (kicktipp-style company pools — football WM, basketball WM, …) and the
32
- target is **pool points**, not match truth. Triggered by the
33
- [`/prediction-pool`](../../commands/prediction-pool.md) command (Steps 3–5) or directly
35
+ target is **pool points**, not match truth. Triggered by
36
+ [`/prediction-pool`](../../commands/prediction-pool.md) (Steps 3–5) or directly
34
37
  when a user asks to optimize / maximize their pool picks.
35
38
 
36
39
  **The one idea that makes this skill correct:** the highest-probability
@@ -43,39 +46,69 @@ more. **Always optimize the pool's points, never the truth of the match.**
43
46
 
44
47
  - **Rules before tips.** Never produce a tip before the pool's scoring is
45
48
  parsed (Procedure step 1). Strategy is a function of the rules.
46
- - **Odds are the primary signal.** Bookmaker / market probabilities already
47
- fold in form, squad, injuries, travel, climate. Use them as the
48
- calibration base; only override with *current* information (confirmed
49
+ - **Answer EVERY open question.** A pool has scores *and* bonus / award /
50
+ special questions ("which team supplies the top scorer?", "most yellow
51
+ cards?", "champion?"). Scorelines only, bonus questions blank = a **failed
52
+ run** — enumerate every open question in step 1, carry each to an answer
53
+ (steps 5–6). No silent skips.
54
+ - **Odds are the primary signal — multi-book consensus, not one book.**
55
+ Bookmaker probabilities already fold in form, squad, injuries, travel,
56
+ climate. Build the base from a **consensus across the 5–10 biggest
57
+ publicly-viewable books** (step 2), de-vigged, **sharpness-weighted** —
58
+ never mirror a single portal. Override only with *current* info (confirmed
49
59
  lineups, late injuries, suspensions, manager change).
50
- - **No invented numbers.** Emit no probability you cannot derive from odds
51
- or from **actually executed** code. Tournament/outright numbers come from
52
- real outright odds **or** the executed Poisson helper — never a claimed
60
+ - **No invented numbers.** Emit no probability you cannot derive from real
61
+ odds or **actually executed** code. Tournament/outright/award numbers come
62
+ from real markets **or** the executed Poisson helper — never a claimed
53
63
  "I ran 10,000 simulations".
54
- - **One-sentence justification** per tip. Short.
64
+ - **Scorelines computed, not guessed.** EV-max tip per match from the executed
65
+ grid optimiser (`score_ev.py`, step 4a), never the eye. A 3:2 / 4:1 / 1:4 in
66
+ the output = signature of a skipped computation.
67
+ - **One-sentence justification** per answer. Short.
55
68
 
56
69
  ## Procedure
57
70
 
58
- ### 1. Parse the pool rules
71
+ ### 1. Parse the pool rules AND enumerate every open question
59
72
 
60
73
  From the pool's rule page, extract and document:
61
74
 
62
75
  - Points for **exact result** / **goal (point) difference** / **tendency**.
63
- - **Bonus questions** (champion, top scorer, group winners …).
64
- - **Joker / multiplier** rules.
65
- - **Quote / rarity** scoring (rare correct tips score more)? — flips the
66
- whole strategy toward contrarian (step 4).
67
- - Special scorings, **deadlines**, and **strategy limits** (e.g. max N
68
- identical tips).
76
+ - **Every bonus / award / special question** (champion, top scorer, "team of
77
+ the top scorer", group winners, most cards, longest unbeaten,
78
+ will-there-be-a-red-card, over/under totals …). **Write them all down as an
79
+ explicit checklist** this list is the run's contract; every entry must
80
+ reach an answer.
81
+ - **Joker / multiplier** rules, per-question point weights.
82
+ - **Quote / rarity** scoring (rare correct tips score more)? — flips strategy
83
+ toward contrarian (step 4).
84
+ - Special scorings, **per-question deadlines**, **strategy limits** (e.g. max
85
+ N identical tips).
69
86
  - **The goal**: place well, or *win* a large pool? (changes variance — step 4.)
70
87
 
71
- ### 2. Build the data base
72
-
73
- Primary: current bookmaker odds, aggregated market probabilities, model
74
- forecasts (e.g. Opta), Elo/SPI ratings. Secondary (only when it adds signal
75
- the odds have not yet absorbed): confirmed lineups, injuries, suspensions,
76
- manager change, recent form, home advantage, head-to-head, rest/travel,
77
- weather. De-vig the odds (remove the bookmaker margin) before treating them
78
- as probabilities.
88
+ ### 2. Build the data base — a consensus across the major books
89
+
90
+ Primary signal: current bookmaker odds, **aggregated across the 5–10 biggest
91
+ publicly-viewable books**, not a single portal:
92
+
93
+ 1. **Collect** odds for each market (1X2, exact-score, outrights, and each
94
+ special/award market a bonus question needs) from several books.
95
+ Odds-comparison aggregators (Oddschecker, Oddsportal / Betexplorer) show
96
+ many books at once; supplement with named books. Book list + weighting
97
+ recipe in [`reference/odds-and-bonus.md`](reference/odds-and-bonus.md).
98
+ 2. **De-vig each book** independently (remove its margin) → per-book implied
99
+ probabilities. Raw odds sum to >100%; never treat them as probabilities.
100
+ 3. **Aggregate with a healthy weighting**, not a blind average: weight
101
+ **sharp, low-margin books higher** (Pinnacle, Betfair Exchange),
102
+ recreational books lower; weighted mean or trimmed median so one outlier
103
+ book cannot swing the base. Result = the **consensus probability** — the
104
+ calibration base.
105
+ 4. **Single-book outlier = flag, not truth** — investigate *why* (priced-in
106
+ injury? stale line?) before moving off consensus. Cross-portal agreement is
107
+ signal; one portal disagreeing is a prompt to check, not to follow.
108
+
109
+ Secondary (only when it adds signal the consensus has not absorbed): confirmed
110
+ lineups, injuries, suspensions, manager change, recent form, home advantage,
111
+ head-to-head, rest/travel, weather, model forecasts (Opta), Elo/SPI ratings.
79
112
 
80
113
  ### 3. Per-match probabilities (sport block)
81
114
 
@@ -98,7 +131,7 @@ results. Pick the block for the event's sport:
98
131
  - Derive the outcome split straight from de-vigged moneyline odds; estimate
99
132
  a plausible score from the market total. State the model used.
100
133
 
101
- Cross-check the model against the market; on a large divergence, re-check
134
+ Cross-check the model against the consensus; on a large divergence, re-check
102
135
  the data and explain the cause before trusting it.
103
136
 
104
137
  ### 4. Convert to the EV-maximizing tip
@@ -106,32 +139,69 @@ the data and explain the cause before trusting it.
106
139
  Map probabilities to the tip with the **highest expected points under the
107
140
  step-1 rules** — not the prettiest match.
108
141
 
109
- - **Standard fixed-point scoring + goal "place well"** → tip the EV-maximal
110
- result per match. Favourites with modest scorelines dominate. **No
111
- contrarian** only your tip matters for your score, so deliberately
112
- tipping "different" just burns EV.
113
- - **Quote / rarity scoring** → weigh rarer-but-plausible results against
114
- their higher payout; take rarity when `payout × probability` wins.
115
- - **Goal = win a large pool** on a *subset* of matches, take calculated
116
- variance (plausible underdogs) to create upside, poker-tournament style.
117
-
118
- **Participant-field thresholds** (when two tips are close, prefer the one
119
- with the higher edge over the typical participant):
120
-
121
- - Pool **N < 20** → maximize EV, ignore the field.
122
- - **20 ≤ N < 100 and you are in the prize positions** → maximize EV.
123
- - **N 100, or you are outside the top ~20%** → add field-relative
124
- variance (move off the consensus on a subset; rough Kelly-fraction sizing).
142
+ #### 4a. The EV-max scoreline is computed, never eyeballed
143
+
144
+ Don't hand-pick a scoreline. Run the executed grid optimiser builds the full
145
+ Poisson score grid, returns the EV-max tip under the step-1 point tiers:
146
+
147
+ ```bash
148
+ python3 scripts/prediction-pool/score_ev.py --lh <home-xg> --la <away-xg> \
149
+ --tendency <t> --diff <d> --exact <e> # one match
150
+ python3 scripts/prediction-pool/score_ev.py matches.json \
151
+ --tendency <t> --diff <d> --exact <e> # batch, prints a ranked table
152
+ ```
153
+
154
+ Two facts the grid makes unavoidable, intuition gets wrong:
155
+
156
+ - **High scorelines almost never EV-max.** Under partial points a moderate
157
+ favourite peaks at **1:0 / 2:0 / 2:1**; **1:0 wins surprisingly often**, top
158
+ of the surface is *flat* (1:0 vs 2:1 vs 2:0 within hundredths). 3:2 / 4:1 /
159
+ 1:4 never optimal — such a tip means the grid wasn't run.
160
+ - **Draws under-tipped.** A correct draw banks the goal-difference tier on
161
+ every draw scoreline, so in a close match (xG within ~0.4) a 1:1 can
162
+ out-score a 1:0 — and for low-scoring even games (λ ≲ 1.0/side) a 0:0 is the
163
+ EV-max. Let the grid decide; the eye tips too few draws.
164
+
165
+ - **Standard fixed-point scoring + goal "place well"** → tip the grid's EV-max
166
+ per match. **No contrarian** — only your tip scores, tipping "different"
167
+ burns EV.
168
+ - **Quote / rarity scoring** → weigh rarer-but-plausible results against payout;
169
+ take rarity when `payout × probability` wins (raise `--exact` or post-process
170
+ the ranked table by the multiplier).
171
+
172
+ #### 4b. Large pool, goal "win it" — measure P(finish 1st), don't guess
173
+
174
+ Goal = **win** a large pool → target flips from E(points) to **P(finish ahead
175
+ of the field)**; pure EV-max converges with the crowd, can't open a gap.
176
+ Measure it with the executed field simulator, not a "rough Kelly" hand-wave:
177
+
178
+ ```bash
179
+ python3 scripts/prediction-pool/pool_winsim.py pool.json --runs 4000 --max-flips 4
180
+ ```
181
+
182
+ Models the field as softmax-EV tippers, reports `P(win)` for EV-max-everywhere,
183
+ then greedily reports **which few tips to flip** off EV-max (EV cost + P(win)
184
+ gain each). Read it as the field threshold, empirically:
185
+
186
+ - Pool **N < 20** → sim shows flips barely move P(win); maximize EV, ignore the
187
+ field.
188
+ - **20 ≤ N < 100 and in the prize positions** → maximize EV.
189
+ - **N ≥ 100, or outside the top ~20%** → take the sim's suggested flips: a
190
+ handful of higher-variance scorelines on high-consensus matches lift P(win)
191
+ most per unit EV given up. Flip only what the sim says pays — variance you
192
+ don't need is wasted EV.
125
193
 
126
194
  Respect all strategy limits from step 1 (max identical tips, etc.).
127
195
 
128
- ### 5. Tournament & bonus questions (no hallucination)
196
+ ### 5. Tournament, bonus & special questions — answer every one (no hallucination)
129
197
 
130
- For group winners, KO rounds, champion, and bonus questions, use **either**:
198
+ Walk the **step-1 checklist** and answer **each** entry. Pick the method by
199
+ question type — full taxonomy + per-type method in
200
+ [`reference/odds-and-bonus.md`](reference/odds-and-bonus.md):
131
201
 
132
- - real **outright market odds** ("to win group", "to reach final",
133
- "outright winner"), **or**
134
- - the executed Poisson tournament simulator:
202
+ - **Tournament structure** (group winners, KO rounds, finalists, champion):
203
+ real **outright market odds** ("to win group", "to reach final", "outright
204
+ winner") aggregated per step 2, **or** the executed Poisson simulator:
135
205
 
136
206
  ```bash
137
207
  python3 scripts/prediction-pool/poisson_sim.py <teams-xg.json> --runs 20000
@@ -141,48 +211,89 @@ For group winners, KO rounds, champion, and bonus questions, use **either**:
141
211
  advancement / title probabilities. **Run it — never report simulated
142
212
  numbers you did not actually compute.**
143
213
 
144
- Optimize bonus answers on the same expected-points basis. Re-run as late as
145
- the deadline allows: re-check confirmed lineups, injuries, suspensions, and
146
- odds movement, then adjust. The pool's per-match deadline is the only hard
147
- constraint.
214
+ - **Award / player markets** (top scorer, most assists, "which team supplies
215
+ the top scorer", golden boot, most cards): use the matching **special
216
+ market** e.g. aggregate per-player "top goalscorer" odds **by team** to
217
+ answer "which team has the top scorer". No clean market → derive from a
218
+ stated model (squad strength × games-expected) and **label it a model
219
+ estimate**, not a market number.
220
+
221
+ - **Binary / over-under specials** (red card yes/no, over/under total
222
+ goals/cards): de-vig the consensus probability for the line, pick the EV-max
223
+ side under the question's point weight.
224
+
225
+ Optimize every answer on the same expected-points basis as the scores. Re-run
226
+ as late as each question's deadline allows: re-check confirmed lineups,
227
+ injuries, suspensions, odds movement, then adjust. The per-question deadline is
228
+ the only hard constraint.
148
229
 
149
230
  ## Output format
150
231
 
151
232
  1. **Approval table** — one row per match:
152
233
 
153
234
  ```
154
- Match | Tip | Prob / EV | Risk (low/med/high) | 1-line reason | Odds used
235
+ Match | Tip | Prob / EV | Risk (low/med/high) | 1-line reason | Books used
236
+ ```
237
+
238
+ `Books used` names the consensus base (e.g. "consensus of 7 books, sharp-weighted").
239
+
240
+ 2. **Bonus & special answers** — one row per open question from the step-1
241
+ checklist, **every entry answered** (none blank):
242
+
243
+ ```
244
+ Question | Answer | Prob / EV | Risk | 1-line reason | Source (market / model)
155
245
  ```
156
246
 
157
- 2. **Group standings, the full bracket, and bonus-question answers** where
158
- the event has them.
159
- 3. **Self-check note** confirm the tips reconcile with
160
- [`reference/ev-fixtures.md`](reference/ev-fixtures.md) (known pool rules +
161
- market odds a known-good EV tip). If your method disagrees with a
162
- fixture, your method is wrong — find the error (usually a forgotten
163
- partial-points term or un-de-vigged odds), don't ship the tip.
247
+ 3. **Group standings and the full bracket** where the event has them.
248
+ 4. **Self-check note** — (a) tips reconcile with
249
+ [`reference/ev-fixtures.md`](reference/ev-fixtures.md) (known rules + odds
250
+ known-good EV tip); (b) bonus table has the **same number of rows as the
251
+ step-1 checklist** a shorter table means a question was dropped. If your
252
+ method disagrees with a fixture, your method is wrong — find the error
253
+ (usually a forgotten partial-points term, un-de-vigged odds, or following
254
+ one book instead of the consensus), don't ship the tip.
164
255
 
165
256
  Handed back to [`/prediction-pool`](../../commands/prediction-pool.md) for the approval
166
257
  gate — the skill never enters or submits anything.
167
258
 
168
259
  ## Gotcha
169
260
 
170
- - **Tipping the modal result, not the EV-maximal one.** The single most
171
- likely scoreline rarely maximizes partial points compute EV across the
261
+ - **Answering only the scores.** Bonus / award questions carry real points;
262
+ leaving them blank because they are "not a scoreline" forfeits them. The
263
+ step-1 checklist exists so every question is answered.
264
+ - **Following one portal.** A single book can be stale or shaded; build the
265
+ base from a sharp-weighted consensus across several; an outlier is a flag to
266
+ investigate, not a number to copy.
267
+ - **Tipping the modal result, not the EV-maximal one.** The single most likely
268
+ scoreline rarely maximizes partial points — run `score_ev.py` across the
172
269
  result grid, don't eyeball the favourite.
173
- - **Forgetting to de-vig.** Raw bookmaker odds sum to >100%; treating them
174
- as probabilities inflates the favourite. Remove the margin first.
175
- - **Contrarian under fixed points.** Deviating "to stand out" only helps
176
- under quote/rarity rules or a win-a-large-pool goal otherwise it burns EV.
177
- - **Claimed-but-unrun simulation.** Numbers like "I ran 10,000 tournaments"
178
- without executing `poisson_sim.py` are hallucinated run the code or use
179
- outright odds.
270
+ - **Hand-picking a high scoreline.** 3:2 / 4:1 / 1:4 never EV-max under partial
271
+ points moderate favourites peak at 1:0 / 2:0 / 2:1. A high tip = grid
272
+ skipped; run `score_ev.py`.
273
+ - **Under-tipping draws.** A correct draw banks the goal-difference tier on
274
+ every draw scoreline, so a close match can want 1:1 (or 0:0). Let the grid
275
+ decide; the eye tips too few draws.
276
+ - **"Rough Kelly" variance for a large pool.** Don't guess deviation amount —
277
+ run `pool_winsim.py`; returns the exact flips that raise P(finish 1st) most
278
+ per unit EV given up.
279
+ - **Forgetting to de-vig.** Raw bookmaker odds sum to >100%; treating them as
280
+ probabilities inflates the favourite. Remove the margin **per book** before
281
+ aggregating.
282
+ - **Contrarian under fixed points.** Deviating "to stand out" only helps under
283
+ quote/rarity rules or a win-a-large-pool goal — otherwise it burns EV.
284
+ - **Claimed-but-unrun simulation.** "I ran 10,000 tournaments" without
285
+ executing `poisson_sim.py` is hallucinated — run the code or use outright odds.
180
286
 
181
287
  ## Do NOT
182
288
 
289
+ - Leave any open pool question (bonus / award / special) unanswered.
290
+ - Build the base from a single bookmaker, or skip de-vigging before aggregating.
183
291
  - Tip the most likely result instead of the EV-maximal one.
292
+ - Hand-pick a scoreline instead of running `score_ev.py` — never emit a
293
+ 3:2 / 4:1 / 1:4 tip, never EV-max under partial points.
184
294
  - Go contrarian under standard fixed-point scoring with a "place well" goal.
185
- - Report Monte-Carlo numbers without running `poisson_sim.py`.
295
+ - Guess large-pool variance ("rough Kelly") instead of running `pool_winsim.py`.
296
+ - Report Monte-Carlo numbers without running `poisson_sim.py` / `pool_winsim.py`.
186
297
  - Treat raw odds as probabilities without removing the vig.
187
298
  - Give betting or financial advice — this optimizes a game; the human submits.
188
299
 
@@ -190,7 +301,14 @@ gate — the skill never enters or submits anything.
190
301
 
191
302
  - [`/prediction-pool`](../../commands/prediction-pool.md) — the orchestrator (event,
192
303
  persistence, Playwright entry, gates).
304
+ - [`reference/odds-and-bonus.md`](reference/odds-and-bonus.md) — major-book list
305
+ + sharpness-weighted consensus recipe, and the bonus / award / special
306
+ question taxonomy with a per-type method.
193
307
  - [`reference/ev-fixtures.md`](reference/ev-fixtures.md) — known-good
194
308
  rules+odds → EV examples.
309
+ - [`scripts/prediction-pool/score_ev.py`](../../../../scripts/prediction-pool/score_ev.py) —
310
+ executed exact-score EV optimiser (step 4a; λ + rule → EV-max scoreline).
311
+ - [`scripts/prediction-pool/pool_winsim.py`](../../../../scripts/prediction-pool/pool_winsim.py) —
312
+ executed field model + P(finish 1st) simulator and flip-finder (step 4b).
195
313
  - [`scripts/prediction-pool/poisson_sim.py`](../../../../scripts/prediction-pool/poisson_sim.py) —
196
- the executed tournament simulator.
314
+ the executed tournament simulator (step 5).
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "skill": "prediction-pool-optimizer",
3
- "description": "7 should-trigger + 5 should-not-trigger queries. Should-trigger covers DE + EN phrasings and the core intent (pool tips, kicktipp, expected-points optimization across sports). Should-not-trigger covers near-miss neighbours: regulated financial advice (finance pack), plain match-result prediction with no pool, generic web research, AI video, and real-money sportsbook betting (out of scope / refuse).",
3
+ "description": "9 should-trigger + 5 should-not-trigger queries. Should-trigger covers DE + EN phrasings and the core intent (pool tips, kicktipp, expected-points optimization across sports, plus answering the bonus / award questions and using bookmaker-consensus odds). Should-not-trigger covers near-miss neighbours: regulated financial advice (finance pack), plain match-result prediction with no pool, generic web research, AI video, and real-money sportsbook betting (out of scope / refuse).",
4
4
  "queries": [
5
5
  {"q": "optimize my kicktipp tips for the football WM 2026", "trigger": true},
6
6
  {"q": "fill my company Tippspiel for the basketball world cup", "trigger": true},
@@ -9,6 +9,8 @@
9
9
  {"q": "maximiere meine erwarteten Punkte im Tippspiel, nicht nur wer gewinnt", "trigger": true},
10
10
  {"q": "predict our office kicktipp pool for the WM", "trigger": true},
11
11
  {"q": "mach mein Tippspiel für die WM", "trigger": true},
12
+ {"q": "beantworte auch alle Bonusfragen im kicktipp, z.B. welche Mannschaft den Torschützenkönig stellt", "trigger": true},
13
+ {"q": "use the odds from the big betting sites to optimize my pool picks", "trigger": true},
12
14
  {"q": "should we invest in this startup based on a DCF?", "trigger": false, "note": "regulated financial valuation → dcf-modeling / finance pack"},
13
15
  {"q": "who will win tonight's match?", "trigger": false, "note": "plain result prediction, no pool / no scoring rules to optimize"},
14
16
  {"q": "research the best running shoes for me", "trigger": false, "note": "generic web research → research / deep-research"},
@@ -15,16 +15,25 @@ shape you encounter so future runs catch the same class of drift.
15
15
  **Rule:** exact result = 4, goal-difference = 3, tendency = 2, else 0.
16
16
  No quote rule. No strategy limit. Goal: place well.
17
17
 
18
- **Match (football):** de-vigged market Home 62% / Draw 24% / Away 14%.
19
- Most plausible exact results (Poisson on market xG ≈ 1.7 : 0.8):
20
- 2:1 ≈ 9%, 1:0 ≈ 9%, 2:0 ≈ 8%, 1:1 ≈ 8%, 3:1 ≈ 6%.
18
+ **Match (football):** Poisson on market xG 1.7 : 0.8.
21
19
 
22
- **Reasoning:** the single most likely *result* (2:1) and 1:0 both bank the
23
- tendency (2) on a home win plus goal-difference (3) on many neighbours.
24
- Expected points of "2:1" beats "tip the favourite to win 3:0" (lower hit
25
- rate on diff/exact) and beats any draw/away tip (tendency rarely banks).
20
+ **Script-verified** (`score_ev.py --lh 1.7 --la 0.8 --exact 4 --diff 3 --tendency 2`):
26
21
 
27
- **Known-good tip:** **2:1 home.** (Risk: low.) **Not** contrarian — under
22
+ ```
23
+ EV-max tip : 1:0 (EV 1.574)
24
+ 1:0 1.574 <- EV-max
25
+ 2:1 1.530
26
+ 2:0 1.477
27
+ ```
28
+
29
+ **Reasoning:** top of the EV surface is **flat** — 1:0, 2:1, 2:0 all bank the
30
+ tendency (2) plus goal-difference (3) on many neighbours, within hundredths of
31
+ each other. Grid puts **1:0 narrowly first**; eyeballing the modal *result*
32
+ (2:1) lands a near-tie, not the optimum. Run the grid — don't assert the
33
+ favourite's "obvious" score.
34
+
35
+ **Known-good tip:** **1:0 home** (2:1 essentially tied; with the real de-vigged
36
+ λ either can lead — the grid decides). (Risk: low.) **Not** contrarian — under
28
37
  fixed points only your own tip scores, so deviating costs EV.
29
38
 
30
39
  ---
@@ -54,15 +63,17 @@ the multiplier; take the max.
54
63
  **Match (football):** a near-coin-flip favourite, Home 52% / Draw 26% /
55
64
  Away 22%.
56
65
 
57
- **Reasoning:** with N ≥ 100 and you behind, pure EV converges with the
58
- field and cannot create the gap you need. Add field-relative variance on a
59
- *subset*: take a plausible underdog/draw where the consensus is heavy on
60
- the favourite, sized by a rough Kelly fraction. On safe matches, still
61
- tip EV-max.
66
+ **Reasoning:** N ≥ 100 and you behind pure EV converges with the field, can't
67
+ create the gap; target is **P(finish 1st)**, not E(points). Don't guess the
68
+ variance: run `pool_winsim.py` with the pool's `N` and your `my_lead`. Shows
69
+ P(win) collapsing under EV-max-everywhere, returns the **specific flips**
70
+ (higher-variance scorelines on high-consensus matches) that raise P(win) most
71
+ per unit EV given up.
62
72
 
63
- **Known-good tip:** EV-max on the safe matches; **calculated underdog**
64
- (e.g. 1:1 or away) on 2–4 high-consensus matches to manufacture upside.
65
- (Risk: highintentional.)
73
+ **Known-good tip:** EV-max on the safe matches; the **simulator's suggested
74
+ flips** on the 2–4 matches it names, to manufacture upside. (Risk: high —
75
+ intentional.) Verify the sim shows a P(win) gainflips not moving it (small
76
+ N) → don't add variance you don't need.
66
77
 
67
78
  ---
68
79
 
@@ -78,3 +89,87 @@ Margin modelled Gaussian, mean ≈ 6.5, sd ≈ 11.
78
89
  spread). Tip the winner plus the modal margin bucket.
79
90
 
80
91
  **Known-good tip:** **Home win, margin ~5–9.** (Risk: low on winner.)
92
+
93
+ ---
94
+
95
+ ## Fixture 5 — multi-book consensus (de-vig per book, sharp-weighted)
96
+
97
+ **Rule:** any — checks the **odds base**, not the EV map.
98
+
99
+ **Market (football, 1X2):** two books.
100
+ - Book S (sharp, weight 3): 1.80 / 3.60 / 4.50 → de-vig 0.526 / 0.263 / 0.210.
101
+ - Book R (recreational, weight 1): 1.75 / 3.50 / 4.20 → de-vig 0.522 / 0.261 / 0.217.
102
+
103
+ **Reasoning:** de-vig **each book** first (raw `1/o` sums to >1; normalise),
104
+ then sharp-weighted mean per outcome and renormalise. Aggregating raw odds, or
105
+ using one book, is wrong.
106
+
107
+ **Known-good base:** **Home 0.525 / Draw 0.262 / Away 0.212.** A run that fed
108
+ the EV grid one book's raw odds has the wrong base — fix it before the tip.
109
+
110
+ ---
111
+
112
+ ## Fixture 6 — "team of the top scorer" (aggregate player market by team)
113
+
114
+ **Rule:** bonus question = 6 points: "which team supplies the tournament top
115
+ scorer?"
116
+
117
+ **Market (top-goalscorer outright, de-vigged player probabilities):**
118
+ - Team A: A1 14%, A2 5% → team A total **19%**.
119
+ - Team B: B1 16% → team B total **16%**.
120
+ - Team C: C1 9%, C2 4% → team C total **13%**.
121
+
122
+ **Reasoning:** the most-likely *player* (B1, 16%) is on team B, but the
123
+ question asks the **team** — sum each squad's players. Team A 19% beats team B
124
+ 16%. Answer the asked question, not the adjacent one.
125
+
126
+ **Known-good answer:** **Team A.** (Source: market, aggregated by team. Risk:
127
+ medium.) **Not** team B — the modal-player trap.
128
+
129
+ ---
130
+
131
+ ## Fixture 7 — high-scoreline trap (the "EV-optimized" model that wasn't)
132
+
133
+ **Rule:** kicktipp 2 / 3 / 5 — tendency = 2, goal-difference = 3, exact = 5.
134
+
135
+ **Matches (script-verified, `score_ev.py … --tendency 2 --diff 3 --exact 5`):**
136
+
137
+ | Match (λ) | EV-max | a high tip's EV | verdict |
138
+ |---|---|---|---|
139
+ | Senegal–Iraq (2.0:0.7) | **1:0** (1.881) | 4:1 ≈ 1.55 | high tip leaks ~0.33 |
140
+ | Qatar–Switzerland (0.6:2.1) | **0:1** (1.981) | 1:4 ≈ 1.65 | tipping the underdog's goals = costliest move on the board |
141
+ | Spain–CapeVerde (2.3:0.6) | **2:0** (2.033) | 3:1 ≈ 1.88 | only at λ ≳ 2.3 does 2:0 edge past 1:0; never higher |
142
+
143
+ **Reasoning:** under partial points the value sits in the tendency and
144
+ goal-difference tiers, not the exact high score. **1:0 is the optimum
145
+ astonishingly often** (even for clear favourites at λ ≈ 2.0); 2:0 takes over
146
+ only near λ ≈ 2.3–2.4; above that, never. **3:2 / 4:1 / 4:2 / 1:4 are never
147
+ EV-max.** Adding goals — especially the underdog's — only shrinks the hit
148
+ probability without protecting the diff/tendency points.
149
+
150
+ **Known-good behaviour:** any 3:2 / 4:x / x:4 tip in the run → the grid wasn't
151
+ run; `score_ev.py` is the gate. (Risk: low; correctness fixture, not strategy.)
152
+
153
+ ---
154
+
155
+ ## Fixture 8 — draws are under-tipped
156
+
157
+ **Rule:** kicktipp 2 / 3 / 5 (as Fixture 7).
158
+
159
+ **Matches (script-verified, `score_ev.py … --tendency 2 --diff 3 --exact 5`):**
160
+
161
+ ```
162
+ λ 1.0:1.0 -> EV-max 0:0 (1.196), 1:1 tied (1.196) # a draw IS the optimum
163
+ λ 0.9:0.9 -> EV-max 0:0 (1.317), 1:1 second
164
+ λ 1.2:1.2 -> EV-max 1:0 (1.150), draw third (1.091) # 1-goal win edges it
165
+ ```
166
+
167
+ **Reasoning:** people tip too few draws. A correct draw banks the
168
+ goal-difference tier (3) on *every* draw scoreline, so in a **low-scoring even
169
+ match (λ ≲ 1.0/side) the draw — usually 0:0 — is the EV-max**, tied with 1:1.
170
+ As λ rises past ~1.1 a one-goal win edges ahead, but the draw stays in the top
171
+ tips. Grid surfaces this; intuition suppresses it.
172
+
173
+ **Known-good behaviour:** a tip set with **near-zero draws across many
174
+ low-scoring even matches** is a red flag — re-run `score_ev.py`, let the grid
175
+ decide, don't default every close game to 1:0.
@@ -0,0 +1,109 @@
1
+ # Odds aggregation + bonus-question taxonomy
2
+
3
+ Lookup material for `prediction-pool-optimizer`. Two parts:
4
+
5
+ - **A — Multi-book consensus**: which books to read, how to weight them, how
6
+ to fold them into one calibration probability.
7
+ - **B — Bonus / award / special questions**: a type → method table so every
8
+ open question in the pool reaches an answer.
9
+
10
+ Not betting advice; how to read a public market as a probability prior for a
11
+ fun pool.
12
+
13
+ ---
14
+
15
+ ## A. Multi-book consensus — read several, weight by sharpness
16
+
17
+ ### Why not one book
18
+
19
+ A single bookmaker's line can be stale, regionally shaded, or carry a fat
20
+ margin. A consensus across several books is a far better probability estimate,
21
+ and cross-book agreement tells you the market's confidence. **Never mirror one
22
+ portal.**
23
+
24
+ ### Which books (5–10, publicly viewable)
25
+
26
+ Availability varies by region and over time — this list is **illustrative,
27
+ refresh it at run time** and use whatever is publicly viewable from the current
28
+ locale. Fastest way to see many at once = an **odds-comparison aggregator**:
29
+
30
+ - **Aggregators (many books on one page):** Oddschecker, Oddsportal,
31
+ Betexplorer, OddsAlert.
32
+ - **Sharp / low-margin reference books (weight higher):** Pinnacle, Betfair
33
+ Exchange (an exchange = closest thing to a true market price).
34
+ - **Large recreational books (weight lower):** bet365, Bwin, William Hill,
35
+ Unibet, Betano, Tipico, Interwetten, bet-at-home, 888sport, Winamax.
36
+
37
+ Aim for **5–10** spanning both groups. If only recreational books are viewable,
38
+ say so in the run note — the consensus is then softer.
39
+
40
+ ### The recipe
41
+
42
+ 1. **Per market, per book**: collect decimal odds (1X2, exact-score, each
43
+ outright, each special/award market a bonus question needs).
44
+ 2. **De-vig each book independently.** For 1X2 decimal odds `o_H, o_D, o_A`,
45
+ raw implied probs `1/o` sum to `>1` (overround); normalise:
46
+ `p_i = (1/o_i) / Σ(1/o)`. Per book — never aggregate raw odds.
47
+ 3. **Sharpness-weight and combine.** Sharp books > recreational; **weighted
48
+ mean** — or **trimmed median** when books disagree a lot (robust to one
49
+ outlier). A defensible weighting:
50
+
51
+ - Pinnacle / Betfair Exchange → weight 3
52
+ - large recreational books → weight 1
53
+ - aggregator "average" column → weight 1 (already blends many)
54
+
55
+ `p_consensus = Σ(wᵢ · pᵢ) / Σwᵢ` per outcome, then re-normalise the outcome
56
+ set to sum to 1.
57
+ 4. **Outlier handling.** One book far off the others = **flag, not truth**:
58
+ check for a reason (priced-in injury, stale line) before moving the
59
+ consensus. Cross-book agreement = signal; one disagreeing book = investigate.
60
+ 5. **Healthy weighting overall.** The consensus is a **prior**. Blend it with
61
+ the per-sport model (Poisson / Gaussian) and override only with *current*
62
+ info the market has not absorbed (confirmed lineup, late injury,
63
+ suspension, manager change). The pool answer is EV under the rules on top of
64
+ this blended probability — the market informs, it does not dictate.
65
+
66
+ ### Worked mini-example (1X2)
67
+
68
+ Two books, home/draw/away decimal odds:
69
+
70
+ - Book S (sharp, w=3): 1.80 / 3.60 / 4.50 → raw 0.556/0.278/0.222 (sum 1.056)
71
+ → de-vig 0.526/0.263/0.210
72
+ - Book R (recreational, w=1): 1.75 / 3.50 / 4.20 → raw 0.571/0.286/0.238
73
+ (sum 1.095) → de-vig 0.522/0.261/0.217
74
+
75
+ Weighted mean (3:1), per outcome, then renormalise:
76
+ ≈ **Home 0.525 / Draw 0.262 / Away 0.212**. That is the calibration base for
77
+ the per-match EV grid — not either book's raw number.
78
+
79
+ ---
80
+
81
+ ## B. Bonus / award / special questions — type → method
82
+
83
+ Every entry on the step-1 checklist gets an answer. Match the question to a
84
+ row; real market where one exists, a **labelled** model estimate where none
85
+ does. Optimize each on expected points under its point weight.
86
+
87
+ | Question type | Example | Method |
88
+ |---|---|---|
89
+ | **Outright winner** | "Who wins the tournament?" | Outright "to win" market, consensus per A; or `poisson_sim.py` `title_pct`. EV-max under the question's points. |
90
+ | **Group / stage** | "Who wins group X?", "Who advances?" | "To win group" / "to qualify" markets; or `advance_pct` from the simulator. |
91
+ | **Finalists / matchup** | "Who reaches the final?" | "To reach final" market per team; simulator pairing is approximate — prefer the market. |
92
+ | **Top scorer (player)** | "Tournament top scorer?" | "Top goalscorer" outright market, consensus per A; EV-max player (favourite unless rarity scoring rewards a longer shot). |
93
+ | **Team of the top scorer** | "Which team supplies the top scorer?" | Aggregate per-player top-scorer probabilities **by team** (sum each squad); pick the highest-summed team. |
94
+ | **Most assists / cards / etc.** | "Most yellow cards?" | Matching special market if offered; else a labelled model estimate (discipline/aggression proxy). |
95
+ | **Binary special** | "Will there be a red card in match X?" | De-vig the yes/no line to a probability; EV-max side under the points. No market → labelled base-rate estimate. |
96
+ | **Over / under total** | "Over/under total goals / cards?" | De-vig the totals line at the offered threshold; higher-EV side. |
97
+ | **Exact stat** | "How many goals in the final?" | Market totals distribution if available; else per-match Poisson on consensus xG. State the model. |
98
+
99
+ ### Rules for bonus answers
100
+
101
+ - **Answer all of them.** The output's bonus table must have the same number
102
+ of rows as the step-1 checklist. A missing row = a dropped question.
103
+ - **Market first, labelled model second.** Prefer a real special market; none
104
+ exists → derive from a stated model and mark `Source: model`.
105
+ - **Rarity rules apply here too.** Under quote/rarity scoring, a
106
+ plausible-but-rarer answer can out-score the favourite when
107
+ `payout × probability` is higher — same EV logic as the scores.
108
+ - **No hallucinated numbers.** Outright/award probabilities come from real
109
+ markets or the executed simulator — never a claimed-but-unrun simulation.