arenamcp 2.8.0__tar.gz

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 (515) hide show
  1. arenamcp-2.8.0/.env.example +28 -0
  2. arenamcp-2.8.0/.github/workflows/installer.yml +88 -0
  3. arenamcp-2.8.0/.github/workflows/publish-pypi.yml +46 -0
  4. arenamcp-2.8.0/.github/workflows/tests.yml +67 -0
  5. arenamcp-2.8.0/.gitignore +69 -0
  6. arenamcp-2.8.0/.pre-commit-config.yaml +31 -0
  7. arenamcp-2.8.0/AGENTS.md +87 -0
  8. arenamcp-2.8.0/DEV.md +85 -0
  9. arenamcp-2.8.0/GEMINI.md +158 -0
  10. arenamcp-2.8.0/INSTALL.md +126 -0
  11. arenamcp-2.8.0/PKG-INFO +122 -0
  12. arenamcp-2.8.0/README.md +58 -0
  13. arenamcp-2.8.0/RELEASE.md +70 -0
  14. arenamcp-2.8.0/TODO.md +98 -0
  15. arenamcp-2.8.0/assets/BepInEx/core/0Harmony.dll +0 -0
  16. arenamcp-2.8.0/assets/BepInEx/core/0Harmony.xml +4288 -0
  17. arenamcp-2.8.0/assets/BepInEx/core/0Harmony20.dll +0 -0
  18. arenamcp-2.8.0/assets/BepInEx/core/BepInEx.Harmony.dll +0 -0
  19. arenamcp-2.8.0/assets/BepInEx/core/BepInEx.Harmony.xml +86 -0
  20. arenamcp-2.8.0/assets/BepInEx/core/BepInEx.Preloader.dll +0 -0
  21. arenamcp-2.8.0/assets/BepInEx/core/BepInEx.Preloader.xml +169 -0
  22. arenamcp-2.8.0/assets/BepInEx/core/BepInEx.dll +0 -0
  23. arenamcp-2.8.0/assets/BepInEx/core/BepInEx.xml +1737 -0
  24. arenamcp-2.8.0/assets/BepInEx/core/HarmonyXInterop.dll +0 -0
  25. arenamcp-2.8.0/assets/BepInEx/core/Mono.Cecil.Mdb.dll +0 -0
  26. arenamcp-2.8.0/assets/BepInEx/core/Mono.Cecil.Pdb.dll +0 -0
  27. arenamcp-2.8.0/assets/BepInEx/core/Mono.Cecil.Rocks.dll +0 -0
  28. arenamcp-2.8.0/assets/BepInEx/core/Mono.Cecil.dll +0 -0
  29. arenamcp-2.8.0/assets/BepInEx/core/MonoMod.RuntimeDetour.dll +0 -0
  30. arenamcp-2.8.0/assets/BepInEx/core/MonoMod.RuntimeDetour.xml +178 -0
  31. arenamcp-2.8.0/assets/BepInEx/core/MonoMod.Utils.dll +0 -0
  32. arenamcp-2.8.0/assets/BepInEx/core/MonoMod.Utils.xml +1470 -0
  33. arenamcp-2.8.0/assets/doorstop_config.ini +39 -0
  34. arenamcp-2.8.0/assets/icon.png +0 -0
  35. arenamcp-2.8.0/assets/winhttp.dll +0 -0
  36. arenamcp-2.8.0/bepinex-plugin/MtgaCoachBridge/BotBattleBridge.cs +499 -0
  37. arenamcp-2.8.0/bepinex-plugin/MtgaCoachBridge/MtgaCoachBridge.csproj +71 -0
  38. arenamcp-2.8.0/bepinex-plugin/MtgaCoachBridge/MtgaCoachHost.cs +130 -0
  39. arenamcp-2.8.0/bepinex-plugin/MtgaCoachBridge/Plugin.cs +4815 -0
  40. arenamcp-2.8.0/bepinex-plugin/MtgaCoachBridge/PracticeMatchBridge.cs +220 -0
  41. arenamcp-2.8.0/bepinex-plugin/README.md +82 -0
  42. arenamcp-2.8.0/configs/run_diverse.yml +64 -0
  43. arenamcp-2.8.0/favicon.ico +0 -0
  44. arenamcp-2.8.0/gateway/README.md +56 -0
  45. arenamcp-2.8.0/gateway/config.yaml +92 -0
  46. arenamcp-2.8.0/gateway/docker-compose.yml +46 -0
  47. arenamcp-2.8.0/icon.ico +0 -0
  48. arenamcp-2.8.0/install.bat +43 -0
  49. arenamcp-2.8.0/installer/build-installer.ps1 +97 -0
  50. arenamcp-2.8.0/installer/mtga_coach_dev.ico +0 -0
  51. arenamcp-2.8.0/installer/mtgacoach.iss +195 -0
  52. arenamcp-2.8.0/launch.bat +104 -0
  53. arenamcp-2.8.0/launch.vbs +39 -0
  54. arenamcp-2.8.0/launcher.py +566 -0
  55. arenamcp-2.8.0/launcher_gui.py +614 -0
  56. arenamcp-2.8.0/model-survey-2026-07-30.md +465 -0
  57. arenamcp-2.8.0/mtga_coach.ico +0 -0
  58. arenamcp-2.8.0/play-real.sh +33 -0
  59. arenamcp-2.8.0/pyproject.toml +173 -0
  60. arenamcp-2.8.0/requirements.txt +56 -0
  61. arenamcp-2.8.0/scripts/build_release.ps1 +85 -0
  62. arenamcp-2.8.0/scripts/launch_desktop.py +72 -0
  63. arenamcp-2.8.0/scripts/launch_installed.py +79 -0
  64. arenamcp-2.8.0/scripts/update_dev_shortcut.py +21 -0
  65. arenamcp-2.8.0/selfplay.sh +31 -0
  66. arenamcp-2.8.0/setup_wizard.py +1255 -0
  67. arenamcp-2.8.0/src/arenamcp/__init__.py +162 -0
  68. arenamcp-2.8.0/src/arenamcp/action_detector.py +198 -0
  69. arenamcp-2.8.0/src/arenamcp/action_planner.py +2860 -0
  70. arenamcp-2.8.0/src/arenamcp/arena_replay.py +346 -0
  71. arenamcp-2.8.0/src/arenamcp/audio.py +147 -0
  72. arenamcp-2.8.0/src/arenamcp/autopilot.py +4529 -0
  73. arenamcp-2.8.0/src/arenamcp/autopilot_bridge.py +1905 -0
  74. arenamcp-2.8.0/src/arenamcp/autopilot_exec.py +1368 -0
  75. arenamcp-2.8.0/src/arenamcp/autopilot_models.py +76 -0
  76. arenamcp-2.8.0/src/arenamcp/autopilot_targets.py +114 -0
  77. arenamcp-2.8.0/src/arenamcp/backend_detect.py +188 -0
  78. arenamcp-2.8.0/src/arenamcp/backend_health.py +244 -0
  79. arenamcp-2.8.0/src/arenamcp/backends/__init__.py +14 -0
  80. arenamcp-2.8.0/src/arenamcp/backends/base.py +18 -0
  81. arenamcp-2.8.0/src/arenamcp/backends/proxy.py +732 -0
  82. arenamcp-2.8.0/src/arenamcp/bugreport.py +247 -0
  83. arenamcp-2.8.0/src/arenamcp/cache_utils.py +75 -0
  84. arenamcp-2.8.0/src/arenamcp/card_db.py +655 -0
  85. arenamcp-2.8.0/src/arenamcp/client_metadata.py +48 -0
  86. arenamcp-2.8.0/src/arenamcp/coach.py +4115 -0
  87. arenamcp-2.8.0/src/arenamcp/coach_postprocess.py +1547 -0
  88. arenamcp-2.8.0/src/arenamcp/coach_prompt_utils.py +314 -0
  89. arenamcp-2.8.0/src/arenamcp/coach_prompts.py +359 -0
  90. arenamcp-2.8.0/src/arenamcp/coach_triggers.py +497 -0
  91. arenamcp-2.8.0/src/arenamcp/combat_solver.py +592 -0
  92. arenamcp-2.8.0/src/arenamcp/decision_arbiter.py +98 -0
  93. arenamcp-2.8.0/src/arenamcp/decisions.py +569 -0
  94. arenamcp-2.8.0/src/arenamcp/deck_builder.py +846 -0
  95. arenamcp-2.8.0/src/arenamcp/desktop/__init__.py +5 -0
  96. arenamcp-2.8.0/src/arenamcp/desktop/__main__.py +4 -0
  97. arenamcp-2.8.0/src/arenamcp/desktop/advice_panel.py +409 -0
  98. arenamcp-2.8.0/src/arenamcp/desktop/app.py +320 -0
  99. arenamcp-2.8.0/src/arenamcp/desktop/audio.py +116 -0
  100. arenamcp-2.8.0/src/arenamcp/desktop/brain_stream_window.py +664 -0
  101. arenamcp-2.8.0/src/arenamcp/desktop/card_overlay.py +503 -0
  102. arenamcp-2.8.0/src/arenamcp/desktop/coach_process.py +227 -0
  103. arenamcp-2.8.0/src/arenamcp/desktop/coach_tab.py +2480 -0
  104. arenamcp-2.8.0/src/arenamcp/desktop/compact_coach.py +1139 -0
  105. arenamcp-2.8.0/src/arenamcp/desktop/hotkeys.py +62 -0
  106. arenamcp-2.8.0/src/arenamcp/desktop/hotkeys_darwin.py +203 -0
  107. arenamcp-2.8.0/src/arenamcp/desktop/hud.py +458 -0
  108. arenamcp-2.8.0/src/arenamcp/desktop/main_window.py +1090 -0
  109. arenamcp-2.8.0/src/arenamcp/desktop/match_overlay.py +1012 -0
  110. arenamcp-2.8.0/src/arenamcp/desktop/performance_tab.py +230 -0
  111. arenamcp-2.8.0/src/arenamcp/desktop/repair_tab.py +231 -0
  112. arenamcp-2.8.0/src/arenamcp/desktop/runtime.py +1219 -0
  113. arenamcp-2.8.0/src/arenamcp/desktop/setup_splash.py +472 -0
  114. arenamcp-2.8.0/src/arenamcp/desktop/theme.py +344 -0
  115. arenamcp-2.8.0/src/arenamcp/desktop/tts_manager.py +362 -0
  116. arenamcp-2.8.0/src/arenamcp/desktop/tts_worker.py +133 -0
  117. arenamcp-2.8.0/src/arenamcp/desktop/ui_watchdog.py +103 -0
  118. arenamcp-2.8.0/src/arenamcp/desktop/window_tracking.py +251 -0
  119. arenamcp-2.8.0/src/arenamcp/diagnose.py +535 -0
  120. arenamcp-2.8.0/src/arenamcp/draft_eval.py +787 -0
  121. arenamcp-2.8.0/src/arenamcp/draft_guidance.py +981 -0
  122. arenamcp-2.8.0/src/arenamcp/draftstate.py +420 -0
  123. arenamcp-2.8.0/src/arenamcp/draftstats.py +277 -0
  124. arenamcp-2.8.0/src/arenamcp/dynamic_cards.py +89 -0
  125. arenamcp-2.8.0/src/arenamcp/edhrec.py +216 -0
  126. arenamcp-2.8.0/src/arenamcp/game_plan.py +415 -0
  127. arenamcp-2.8.0/src/arenamcp/gamestate.py +3133 -0
  128. arenamcp-2.8.0/src/arenamcp/gamestate_decisions.py +1039 -0
  129. arenamcp-2.8.0/src/arenamcp/gamestate_models.py +259 -0
  130. arenamcp-2.8.0/src/arenamcp/gamestate_persistence.py +231 -0
  131. arenamcp-2.8.0/src/arenamcp/gamestate_transforms.py +228 -0
  132. arenamcp-2.8.0/src/arenamcp/gre_action_matcher.py +405 -0
  133. arenamcp-2.8.0/src/arenamcp/gre_bridge.py +2350 -0
  134. arenamcp-2.8.0/src/arenamcp/gre_serializer.py +673 -0
  135. arenamcp-2.8.0/src/arenamcp/input_controller.py +871 -0
  136. arenamcp-2.8.0/src/arenamcp/log_utils.py +197 -0
  137. arenamcp-2.8.0/src/arenamcp/logging_config.py +79 -0
  138. arenamcp-2.8.0/src/arenamcp/magezero_client.py +184 -0
  139. arenamcp-2.8.0/src/arenamcp/match_evaluator.py +233 -0
  140. arenamcp-2.8.0/src/arenamcp/match_history.py +382 -0
  141. arenamcp-2.8.0/src/arenamcp/match_packets.py +194 -0
  142. arenamcp-2.8.0/src/arenamcp/match_review.py +408 -0
  143. arenamcp-2.8.0/src/arenamcp/match_validator.py +686 -0
  144. arenamcp-2.8.0/src/arenamcp/mcts_evaluator.py +558 -0
  145. arenamcp-2.8.0/src/arenamcp/mtgadb.py +628 -0
  146. arenamcp-2.8.0/src/arenamcp/mtggoldfish.py +194 -0
  147. arenamcp-2.8.0/src/arenamcp/mtgjson.py +417 -0
  148. arenamcp-2.8.0/src/arenamcp/opponent_model.py +279 -0
  149. arenamcp-2.8.0/src/arenamcp/parser.py +347 -0
  150. arenamcp-2.8.0/src/arenamcp/pipe_adapter.py +1296 -0
  151. arenamcp-2.8.0/src/arenamcp/platform_integration.py +357 -0
  152. arenamcp-2.8.0/src/arenamcp/play_real_matches.py +575 -0
  153. arenamcp-2.8.0/src/arenamcp/proton_launch.py +268 -0
  154. arenamcp-2.8.0/src/arenamcp/realtime.py +697 -0
  155. arenamcp-2.8.0/src/arenamcp/repair_cli.py +50 -0
  156. arenamcp-2.8.0/src/arenamcp/repair_engine.py +646 -0
  157. arenamcp-2.8.0/src/arenamcp/replay_converter.py +193 -0
  158. arenamcp-2.8.0/src/arenamcp/request_tracker.py +181 -0
  159. arenamcp-2.8.0/src/arenamcp/resources/MtgaCoachBridge.dll +0 -0
  160. arenamcp-2.8.0/src/arenamcp/resources/__init__.py +0 -0
  161. arenamcp-2.8.0/src/arenamcp/resources/bepinex/BepInEx/core/0Harmony.dll +0 -0
  162. arenamcp-2.8.0/src/arenamcp/resources/bepinex/BepInEx/core/0Harmony.xml +4288 -0
  163. arenamcp-2.8.0/src/arenamcp/resources/bepinex/BepInEx/core/0Harmony20.dll +0 -0
  164. arenamcp-2.8.0/src/arenamcp/resources/bepinex/BepInEx/core/BepInEx.Harmony.dll +0 -0
  165. arenamcp-2.8.0/src/arenamcp/resources/bepinex/BepInEx/core/BepInEx.Harmony.xml +86 -0
  166. arenamcp-2.8.0/src/arenamcp/resources/bepinex/BepInEx/core/BepInEx.Preloader.dll +0 -0
  167. arenamcp-2.8.0/src/arenamcp/resources/bepinex/BepInEx/core/BepInEx.Preloader.xml +169 -0
  168. arenamcp-2.8.0/src/arenamcp/resources/bepinex/BepInEx/core/BepInEx.dll +0 -0
  169. arenamcp-2.8.0/src/arenamcp/resources/bepinex/BepInEx/core/BepInEx.xml +1737 -0
  170. arenamcp-2.8.0/src/arenamcp/resources/bepinex/BepInEx/core/HarmonyXInterop.dll +0 -0
  171. arenamcp-2.8.0/src/arenamcp/resources/bepinex/BepInEx/core/Mono.Cecil.Mdb.dll +0 -0
  172. arenamcp-2.8.0/src/arenamcp/resources/bepinex/BepInEx/core/Mono.Cecil.Pdb.dll +0 -0
  173. arenamcp-2.8.0/src/arenamcp/resources/bepinex/BepInEx/core/Mono.Cecil.Rocks.dll +0 -0
  174. arenamcp-2.8.0/src/arenamcp/resources/bepinex/BepInEx/core/Mono.Cecil.dll +0 -0
  175. arenamcp-2.8.0/src/arenamcp/resources/bepinex/BepInEx/core/MonoMod.RuntimeDetour.dll +0 -0
  176. arenamcp-2.8.0/src/arenamcp/resources/bepinex/BepInEx/core/MonoMod.RuntimeDetour.xml +178 -0
  177. arenamcp-2.8.0/src/arenamcp/resources/bepinex/BepInEx/core/MonoMod.Utils.dll +0 -0
  178. arenamcp-2.8.0/src/arenamcp/resources/bepinex/BepInEx/core/MonoMod.Utils.xml +1470 -0
  179. arenamcp-2.8.0/src/arenamcp/resources/bepinex/doorstop_config.ini +39 -0
  180. arenamcp-2.8.0/src/arenamcp/resources/bepinex/winhttp.dll +0 -0
  181. arenamcp-2.8.0/src/arenamcp/rules_data.py +1004 -0
  182. arenamcp-2.8.0/src/arenamcp/rules_db.py +312 -0
  183. arenamcp-2.8.0/src/arenamcp/rules_engine.py +1238 -0
  184. arenamcp-2.8.0/src/arenamcp/screen_capture.py +266 -0
  185. arenamcp-2.8.0/src/arenamcp/screen_mapper.py +963 -0
  186. arenamcp-2.8.0/src/arenamcp/scryfall.py +358 -0
  187. arenamcp-2.8.0/src/arenamcp/sealed_eval.py +310 -0
  188. arenamcp-2.8.0/src/arenamcp/self_play.py +886 -0
  189. arenamcp-2.8.0/src/arenamcp/server.py +2620 -0
  190. arenamcp-2.8.0/src/arenamcp/settings.py +270 -0
  191. arenamcp-2.8.0/src/arenamcp/stall_corpus.py +68 -0
  192. arenamcp-2.8.0/src/arenamcp/standalone.py +4213 -0
  193. arenamcp-2.8.0/src/arenamcp/standalone_deck.py +565 -0
  194. arenamcp-2.8.0/src/arenamcp/standalone_diagnostics.py +934 -0
  195. arenamcp-2.8.0/src/arenamcp/standalone_mcp.py +76 -0
  196. arenamcp-2.8.0/src/arenamcp/standalone_postmatch.py +901 -0
  197. arenamcp-2.8.0/src/arenamcp/standalone_ui.py +113 -0
  198. arenamcp-2.8.0/src/arenamcp/standalone_voice.py +232 -0
  199. arenamcp-2.8.0/src/arenamcp/subscription.py +308 -0
  200. arenamcp-2.8.0/src/arenamcp/synergy.py +569 -0
  201. arenamcp-2.8.0/src/arenamcp/trajectory_recorder.py +253 -0
  202. arenamcp-2.8.0/src/arenamcp/transcription.py +115 -0
  203. arenamcp-2.8.0/src/arenamcp/triggers.py +225 -0
  204. arenamcp-2.8.0/src/arenamcp/tts.py +924 -0
  205. arenamcp-2.8.0/src/arenamcp/updater.py +183 -0
  206. arenamcp-2.8.0/src/arenamcp/vision_mapper.py +1006 -0
  207. arenamcp-2.8.0/src/arenamcp/voice.py +294 -0
  208. arenamcp-2.8.0/src/arenamcp/watcher.py +654 -0
  209. arenamcp-2.8.0/tests/conftest.py +50 -0
  210. arenamcp-2.8.0/tests/fixtures/stalls/momentum_breaker_unpayable.json +19 -0
  211. arenamcp-2.8.0/tests/fixtures/stalls/nurturing_presence_select_targets.json +17 -0
  212. arenamcp-2.8.0/tests/fixtures/stalls/ruthless_negotiation_player_target.json +17 -0
  213. arenamcp-2.8.0/tests/test_ability_affordability.py +441 -0
  214. arenamcp-2.8.0/tests/test_ability_source_naming.py +109 -0
  215. arenamcp-2.8.0/tests/test_action_planner_land_drop_first.py +116 -0
  216. arenamcp-2.8.0/tests/test_action_planner_legality.py +189 -0
  217. arenamcp-2.8.0/tests/test_action_planner_turn_intent.py +199 -0
  218. arenamcp-2.8.0/tests/test_action_planner_turn_plan.py +375 -0
  219. arenamcp-2.8.0/tests/test_actions_available_typed.py +88 -0
  220. arenamcp-2.8.0/tests/test_attack_tax.py +100 -0
  221. arenamcp-2.8.0/tests/test_autopilot_bridge_attackers.py +254 -0
  222. arenamcp-2.8.0/tests/test_autopilot_bridge_gap_hint.py +101 -0
  223. arenamcp-2.8.0/tests/test_autopilot_bridge_lock.py +518 -0
  224. arenamcp-2.8.0/tests/test_autopilot_card_name_normalize.py +78 -0
  225. arenamcp-2.8.0/tests/test_autopilot_livelock.py +355 -0
  226. arenamcp-2.8.0/tests/test_autopilot_optional_cost_gate.py +145 -0
  227. arenamcp-2.8.0/tests/test_autopilot_safe_default_group.py +171 -0
  228. arenamcp-2.8.0/tests/test_autopilot_solver_attacks.py +139 -0
  229. arenamcp-2.8.0/tests/test_autopilot_stale_vs_bridge.py +382 -0
  230. arenamcp-2.8.0/tests/test_backend_health.py +277 -0
  231. arenamcp-2.8.0/tests/test_baseline_plan.py +132 -0
  232. arenamcp-2.8.0/tests/test_battlefield_land_oracle.py +221 -0
  233. arenamcp-2.8.0/tests/test_block_advice_specificity.py +333 -0
  234. arenamcp-2.8.0/tests/test_brain_stream_window.py +307 -0
  235. arenamcp-2.8.0/tests/test_bridge_blocker_enrichment.py +193 -0
  236. arenamcp-2.8.0/tests/test_bridge_offline_recovery.py +176 -0
  237. arenamcp-2.8.0/tests/test_bridge_prompt_enrichment.py +235 -0
  238. arenamcp-2.8.0/tests/test_bridge_x_chooser.py +368 -0
  239. arenamcp-2.8.0/tests/test_bugreport.py +112 -0
  240. arenamcp-2.8.0/tests/test_build_curriculum.py +247 -0
  241. arenamcp-2.8.0/tests/test_build_dataset_contracts.py +32 -0
  242. arenamcp-2.8.0/tests/test_build_mixture_manifest.py +232 -0
  243. arenamcp-2.8.0/tests/test_build_play_decisions.py +476 -0
  244. arenamcp-2.8.0/tests/test_build_strategic_casts.py +231 -0
  245. arenamcp-2.8.0/tests/test_card_db_type_lines.py +283 -0
  246. arenamcp-2.8.0/tests/test_card_overlay_badges.py +44 -0
  247. arenamcp-2.8.0/tests/test_card_prewarming.py +77 -0
  248. arenamcp-2.8.0/tests/test_coach_advice_matching.py +201 -0
  249. arenamcp-2.8.0/tests/test_coach_postprocess_color_castability.py +121 -0
  250. arenamcp-2.8.0/tests/test_coach_postprocess_lands.py +208 -0
  251. arenamcp-2.8.0/tests/test_combat_balance.py +260 -0
  252. arenamcp-2.8.0/tests/test_combat_label_integrity.py +126 -0
  253. arenamcp-2.8.0/tests/test_compact_coach.py +107 -0
  254. arenamcp-2.8.0/tests/test_contract_validators.py +58 -0
  255. arenamcp-2.8.0/tests/test_corpus_selfcheck.py +300 -0
  256. arenamcp-2.8.0/tests/test_decision_arbiter.py +108 -0
  257. arenamcp-2.8.0/tests/test_decisions.py +155 -0
  258. arenamcp-2.8.0/tests/test_deck_builder_tiered.py +118 -0
  259. arenamcp-2.8.0/tests/test_deck_inventory.py +247 -0
  260. arenamcp-2.8.0/tests/test_desktop_audio.py +43 -0
  261. arenamcp-2.8.0/tests/test_desktop_hotkeys.py +73 -0
  262. arenamcp-2.8.0/tests/test_desktop_runtime.py +105 -0
  263. arenamcp-2.8.0/tests/test_desktop_runtime_darwin.py +436 -0
  264. arenamcp-2.8.0/tests/test_draft_eval_preference_locking.py +89 -0
  265. arenamcp-2.8.0/tests/test_draft_guidance.py +578 -0
  266. arenamcp-2.8.0/tests/test_draft_guidance_wiring.py +7 -0
  267. arenamcp-2.8.0/tests/test_dynamic_cards.py +85 -0
  268. arenamcp-2.8.0/tests/test_equip_target_selection.py +41 -0
  269. arenamcp-2.8.0/tests/test_eval_pipeline_smoke.py +202 -0
  270. arenamcp-2.8.0/tests/test_eval_run_backend_binding.py +152 -0
  271. arenamcp-2.8.0/tests/test_fail_closed_gating.py +259 -0
  272. arenamcp-2.8.0/tests/test_fallback_tagging.py +265 -0
  273. arenamcp-2.8.0/tests/test_game_plan.py +181 -0
  274. arenamcp-2.8.0/tests/test_gamestate_checkpoint.py +142 -0
  275. arenamcp-2.8.0/tests/test_gamestate_gre_normalization.py +219 -0
  276. arenamcp-2.8.0/tests/test_gamestate_lands_played_inference.py +149 -0
  277. arenamcp-2.8.0/tests/test_gate_combat_decisions.py +751 -0
  278. arenamcp-2.8.0/tests/test_gate_play_decisions.py +871 -0
  279. arenamcp-2.8.0/tests/test_gate_stats.py +25 -0
  280. arenamcp-2.8.0/tests/test_gre_bridge_read_timeout.py +144 -0
  281. arenamcp-2.8.0/tests/test_health_tag_visibility.py +201 -0
  282. arenamcp-2.8.0/tests/test_hotkeys_and_vision_darwin.py +220 -0
  283. arenamcp-2.8.0/tests/test_ingest_manasight.py +854 -0
  284. arenamcp-2.8.0/tests/test_input_controller_virtual_screen.py +74 -0
  285. arenamcp-2.8.0/tests/test_library_summary.py +122 -0
  286. arenamcp-2.8.0/tests/test_litellm_exporter.py +186 -0
  287. arenamcp-2.8.0/tests/test_magezero_bridge_leaks.py +267 -0
  288. arenamcp-2.8.0/tests/test_magezero_card_map.py +261 -0
  289. arenamcp-2.8.0/tests/test_magezero_combat.py +374 -0
  290. arenamcp-2.8.0/tests/test_magezero_combat_micro.py +477 -0
  291. arenamcp-2.8.0/tests/test_magezero_filters.py +699 -0
  292. arenamcp-2.8.0/tests/test_magezero_hdf5_to_corpus.py +178 -0
  293. arenamcp-2.8.0/tests/test_manual_play_detect_p14.py +68 -0
  294. arenamcp-2.8.0/tests/test_match_evaluator.py +152 -0
  295. arenamcp-2.8.0/tests/test_match_packets.py +150 -0
  296. arenamcp-2.8.0/tests/test_match_packets_p09.py +49 -0
  297. arenamcp-2.8.0/tests/test_match_review.py +139 -0
  298. arenamcp-2.8.0/tests/test_match_state_resume.py +32 -0
  299. arenamcp-2.8.0/tests/test_match_weighted_win_rate.py +219 -0
  300. arenamcp-2.8.0/tests/test_mcts_evaluator.py +336 -0
  301. arenamcp-2.8.0/tests/test_meaningful_advice_filter.py +283 -0
  302. arenamcp-2.8.0/tests/test_menu_pick_r3.py +189 -0
  303. arenamcp-2.8.0/tests/test_model_registry.py +286 -0
  304. arenamcp-2.8.0/tests/test_mtgadb.py +179 -0
  305. arenamcp-2.8.0/tests/test_mulligan_advice_guard.py +118 -0
  306. arenamcp-2.8.0/tests/test_mulligan_deck_analysis_order.py +86 -0
  307. arenamcp-2.8.0/tests/test_multi_spell_postprocess.py +187 -0
  308. arenamcp-2.8.0/tests/test_no_provision_splash.py +23 -0
  309. arenamcp-2.8.0/tests/test_oracle_coverage.py +268 -0
  310. arenamcp-2.8.0/tests/test_paired_bootstrap.py +28 -0
  311. arenamcp-2.8.0/tests/test_parse_magezero_log.py +1233 -0
  312. arenamcp-2.8.0/tests/test_patreon_litellm.py +199 -0
  313. arenamcp-2.8.0/tests/test_pay_costs_flow.py +261 -0
  314. arenamcp-2.8.0/tests/test_pay_costs_race.py +127 -0
  315. arenamcp-2.8.0/tests/test_performance_tab.py +234 -0
  316. arenamcp-2.8.0/tests/test_pipe_voice_output.py +63 -0
  317. arenamcp-2.8.0/tests/test_plan_framing_gate.py +49 -0
  318. arenamcp-2.8.0/tests/test_planner_combat_voice.py +50 -0
  319. arenamcp-2.8.0/tests/test_platform_darwin.py +282 -0
  320. arenamcp-2.8.0/tests/test_proxy_backend_errors.py +125 -0
  321. arenamcp-2.8.0/tests/test_proxy_backend_timeout.py +81 -0
  322. arenamcp-2.8.0/tests/test_proxy_reasoning_salvage.py +109 -0
  323. arenamcp-2.8.0/tests/test_proxy_server_responses.py +242 -0
  324. arenamcp-2.8.0/tests/test_proxy_server_signup.py +91 -0
  325. arenamcp-2.8.0/tests/test_proxy_thinking_control.py +93 -0
  326. arenamcp-2.8.0/tests/test_queue_bot_match.py +44 -0
  327. arenamcp-2.8.0/tests/test_raw_card_token_resolution.py +104 -0
  328. arenamcp-2.8.0/tests/test_release_versioning.py +226 -0
  329. arenamcp-2.8.0/tests/test_repair_darwin.py +283 -0
  330. arenamcp-2.8.0/tests/test_repair_engine.py +115 -0
  331. arenamcp-2.8.0/tests/test_replay_seat_detection.py +340 -0
  332. arenamcp-2.8.0/tests/test_request_tracker.py +121 -0
  333. arenamcp-2.8.0/tests/test_run_wp3_pipeline.py +132 -0
  334. arenamcp-2.8.0/tests/test_self_play_orchestrator.py +80 -0
  335. arenamcp-2.8.0/tests/test_self_play_recording.py +336 -0
  336. arenamcp-2.8.0/tests/test_server_bridge_overlay.py +311 -0
  337. arenamcp-2.8.0/tests/test_settings_scryfall.py +209 -0
  338. arenamcp-2.8.0/tests/test_sideboard_and_analyze.py +292 -0
  339. arenamcp-2.8.0/tests/test_stack_and_solver_prompt.py +327 -0
  340. arenamcp-2.8.0/tests/test_stall_corpus.py +47 -0
  341. arenamcp-2.8.0/tests/test_standalone_draft_hud.py +97 -0
  342. arenamcp-2.8.0/tests/test_standalone_generic_selection.py +68 -0
  343. arenamcp-2.8.0/tests/test_standalone_speak_advice.py +55 -0
  344. arenamcp-2.8.0/tests/test_state_replay.py +114 -0
  345. arenamcp-2.8.0/tests/test_takeover_reclassify_p18.py +63 -0
  346. arenamcp-2.8.0/tests/test_target_selection_disjunction.py +159 -0
  347. arenamcp-2.8.0/tests/test_target_selection_grounding.py +219 -0
  348. arenamcp-2.8.0/tests/test_target_selection_regressions.py +391 -0
  349. arenamcp-2.8.0/tests/test_target_selection_scoring.py +122 -0
  350. arenamcp-2.8.0/tests/test_targeting_fallback_decline.py +172 -0
  351. arenamcp-2.8.0/tests/test_taxonomy.py +770 -0
  352. arenamcp-2.8.0/tests/test_temperature_fallback.py +19 -0
  353. arenamcp-2.8.0/tests/test_threat_advice.py +404 -0
  354. arenamcp-2.8.0/tests/test_train_chat_template.py +86 -0
  355. arenamcp-2.8.0/tests/test_train_ddp.py +73 -0
  356. arenamcp-2.8.0/tests/test_train_early_stopping.py +140 -0
  357. arenamcp-2.8.0/tests/test_trial_client.py +171 -0
  358. arenamcp-2.8.0/tests/test_trial_endpoint.py +208 -0
  359. arenamcp-2.8.0/tests/test_typed_decision_path.py +265 -0
  360. arenamcp-2.8.0/tests/test_unseen_deck_gate.py +609 -0
  361. arenamcp-2.8.0/tests/test_validate_run_config.py +163 -0
  362. arenamcp-2.8.0/tests/test_validators.py +298 -0
  363. arenamcp-2.8.0/tests/test_voice_darwin.py +262 -0
  364. arenamcp-2.8.0/tests/test_watcher_startup.py +93 -0
  365. arenamcp-2.8.0/tests/test_window_identity_r1.py +170 -0
  366. arenamcp-2.8.0/tests/test_window_tracking.py +457 -0
  367. arenamcp-2.8.0/tests/test_x_chooser_plumbing.py +162 -0
  368. arenamcp-2.8.0/tools/eval/README.md +174 -0
  369. arenamcp-2.8.0/tools/eval/__init__.py +1 -0
  370. arenamcp-2.8.0/tools/eval/auto.py +396 -0
  371. arenamcp-2.8.0/tools/eval/bot_battle/__init__.py +0 -0
  372. arenamcp-2.8.0/tools/eval/bot_battle/smoke_test.py +99 -0
  373. arenamcp-2.8.0/tools/eval/build_corpus.py +47 -0
  374. arenamcp-2.8.0/tools/eval/coach_prompt_ablation.py +240 -0
  375. arenamcp-2.8.0/tools/eval/forge_fidelity.py +1317 -0
  376. arenamcp-2.8.0/tools/eval/judge.py +237 -0
  377. arenamcp-2.8.0/tools/eval/replay/__init__.py +0 -0
  378. arenamcp-2.8.0/tools/eval/replay/decisions.py +297 -0
  379. arenamcp-2.8.0/tools/eval/replay/menu_groundtruth.py +1369 -0
  380. arenamcp-2.8.0/tools/eval/replay/prompts.py +684 -0
  381. arenamcp-2.8.0/tools/eval/replay/reader.py +211 -0
  382. arenamcp-2.8.0/tools/eval/replay/run.py +589 -0
  383. arenamcp-2.8.0/tools/eval/replay/score.py +454 -0
  384. arenamcp-2.8.0/tools/eval/replay/state.py +346 -0
  385. arenamcp-2.8.0/tools/eval/replay/strategic_groundtruth.py +1391 -0
  386. arenamcp-2.8.0/tools/eval/replay_stalls.py +111 -0
  387. arenamcp-2.8.0/tools/eval/report.py +204 -0
  388. arenamcp-2.8.0/tools/eval/run.py +300 -0
  389. arenamcp-2.8.0/tools/eval/run_baseline.py +104 -0
  390. arenamcp-2.8.0/tools/eval/seventeenlands/README.md +134 -0
  391. arenamcp-2.8.0/tools/eval/seventeenlands/__init__.py +5 -0
  392. arenamcp-2.8.0/tools/eval/seventeenlands/build_mulligan_prompts.py +411 -0
  393. arenamcp-2.8.0/tools/eval/seventeenlands/build_turn_action_prompts.py +524 -0
  394. arenamcp-2.8.0/tools/eval/seventeenlands/download.py +115 -0
  395. arenamcp-2.8.0/tools/eval/seventeenlands/loader.py +115 -0
  396. arenamcp-2.8.0/tools/eval/seventeenlands/score_mulligan.py +335 -0
  397. arenamcp-2.8.0/tools/eval/seventeenlands/score_turn_actions.py +276 -0
  398. arenamcp-2.8.0/tools/eval/upload_results.py +63 -0
  399. arenamcp-2.8.0/tools/monitoring/grafana/apply_dashboards.sh +92 -0
  400. arenamcp-2.8.0/tools/monitoring/grafana/gpu-fleet.json +2889 -0
  401. arenamcp-2.8.0/tools/monitoring/grafana/vllm-gemma.json +1884 -0
  402. arenamcp-2.8.0/tools/monitoring/litellm_exporter/README.md +68 -0
  403. arenamcp-2.8.0/tools/monitoring/litellm_exporter/exporter.py +297 -0
  404. arenamcp-2.8.0/tools/training/_dryrun_prompt_debug.py +101 -0
  405. arenamcp-2.8.0/tools/training/build_bridge_dataset.py +729 -0
  406. arenamcp-2.8.0/tools/training/build_combat_decisions.py +2403 -0
  407. arenamcp-2.8.0/tools/training/build_curriculum.py +929 -0
  408. arenamcp-2.8.0/tools/training/build_dataset.py +589 -0
  409. arenamcp-2.8.0/tools/training/build_gate_corpus_v2.py +184 -0
  410. arenamcp-2.8.0/tools/training/build_magezero_bridge.py +713 -0
  411. arenamcp-2.8.0/tools/training/build_magezero_combat.py +939 -0
  412. arenamcp-2.8.0/tools/training/build_play_decisions.py +988 -0
  413. arenamcp-2.8.0/tools/training/build_strategic_casts.py +979 -0
  414. arenamcp-2.8.0/tools/training/build_tripwires.py +307 -0
  415. arenamcp-2.8.0/tools/training/corpus_selfcheck.py +264 -0
  416. arenamcp-2.8.0/tools/training/extract_real_menus.py +180 -0
  417. arenamcp-2.8.0/tools/training/formatting.py +72 -0
  418. arenamcp-2.8.0/tools/training/gate_combat_decisions.py +2229 -0
  419. arenamcp-2.8.0/tools/training/gate_level_one.py +220 -0
  420. arenamcp-2.8.0/tools/training/gate_level_one_quiz.py +274 -0
  421. arenamcp-2.8.0/tools/training/gate_play_decisions.py +2479 -0
  422. arenamcp-2.8.0/tools/training/gate_quiz_local.py +130 -0
  423. arenamcp-2.8.0/tools/training/gate_stage0.py +458 -0
  424. arenamcp-2.8.0/tools/training/ingest_17lands.py +362 -0
  425. arenamcp-2.8.0/tools/training/ingest_manasight.py +1623 -0
  426. arenamcp-2.8.0/tools/training/magezero_actions.py +130 -0
  427. arenamcp-2.8.0/tools/training/magezero_card_map.json +986 -0
  428. arenamcp-2.8.0/tools/training/magezero_combat_micro.py +1050 -0
  429. arenamcp-2.8.0/tools/training/magezero_filters.py +553 -0
  430. arenamcp-2.8.0/tools/training/magezero_hdf5_to_corpus.py +344 -0
  431. arenamcp-2.8.0/tools/training/measure_prompt_lengths.py +67 -0
  432. arenamcp-2.8.0/tools/training/menu_fidelity.py +681 -0
  433. arenamcp-2.8.0/tools/training/mine_level_one_skills.py +1452 -0
  434. arenamcp-2.8.0/tools/training/mine_strategic_tripwires.py +741 -0
  435. arenamcp-2.8.0/tools/training/oracle_coverage.py +456 -0
  436. arenamcp-2.8.0/tools/training/parse_magezero_log.py +1296 -0
  437. arenamcp-2.8.0/tools/training/registry.py +454 -0
  438. arenamcp-2.8.0/tools/training/relabel_dsv4.py +459 -0
  439. arenamcp-2.8.0/tools/training/run_pipeline.py +637 -0
  440. arenamcp-2.8.0/tools/training/run_wp3_pipeline.py +1127 -0
  441. arenamcp-2.8.0/tools/training/split_combat_gate.py +673 -0
  442. arenamcp-2.8.0/tools/training/synthesize_menu.py +1067 -0
  443. arenamcp-2.8.0/tools/training/taxonomy/__init__.py +1 -0
  444. arenamcp-2.8.0/tools/training/taxonomy/annotate.py +176 -0
  445. arenamcp-2.8.0/tools/training/taxonomy/build_taxonomy.py +944 -0
  446. arenamcp-2.8.0/tools/training/taxonomy/card_taxonomy.json +385226 -0
  447. arenamcp-2.8.0/tools/training/train.py +537 -0
  448. arenamcp-2.8.0/tools/training/validators.py +220 -0
  449. arenamcp-2.8.0/tools/training/wp3/B5_ROCM_FEASIBILITY.md +183 -0
  450. arenamcp-2.8.0/tools/training/wp3/PROGRESS-build_magezero_bridge.md +31 -0
  451. arenamcp-2.8.0/tools/training/wp3/PROGRESS-cuda-serving.md +121 -0
  452. arenamcp-2.8.0/tools/training/wp3/PROGRESS-distributed-runner.md +147 -0
  453. arenamcp-2.8.0/tools/training/wp3/PROGRESS-qwen-c1-verify.md +98 -0
  454. arenamcp-2.8.0/tools/training/wp3/PROGRESS-qwen-c2-latency.md +363 -0
  455. arenamcp-2.8.0/tools/training/wp3/PROGRESS-qwen-c6-command-zone.md +34 -0
  456. arenamcp-2.8.0/tools/training/wp3/PROGRESS-qwen-c8-xchooser-verify.md +54 -0
  457. arenamcp-2.8.0/tools/training/wp3/PROGRESS-smoke.md +149 -0
  458. arenamcp-2.8.0/tools/training/wp3/PROGRESS-wp3-b1-parser.md +109 -0
  459. arenamcp-2.8.0/tools/training/wp3/PROGRESS-wp3-b2-filters.md +49 -0
  460. arenamcp-2.8.0/tools/training/wp3/PROGRESS-wp3-baseline-arm.md +50 -0
  461. arenamcp-2.8.0/tools/training/wp3/PROGRESS-wp3-card-map.md +48 -0
  462. arenamcp-2.8.0/tools/training/wp3/PROGRESS-wp3-combat-adapter.md +80 -0
  463. arenamcp-2.8.0/tools/training/wp3/PROGRESS-wp3-combat-adapter2.md +175 -0
  464. arenamcp-2.8.0/tools/training/wp3/PROGRESS-wp3-combat-rebalance.md +51 -0
  465. arenamcp-2.8.0/tools/training/wp3/PROGRESS-wp3-deck-diversity.md +48 -0
  466. arenamcp-2.8.0/tools/training/wp3/PROGRESS-wp3-gate-eval-prep.md +143 -0
  467. arenamcp-2.8.0/tools/training/wp3/PROGRESS-wp3-hand-attribution.md +119 -0
  468. arenamcp-2.8.0/tools/training/wp3/PROGRESS-wp3-integration.md +69 -0
  469. arenamcp-2.8.0/tools/training/wp3/PROGRESS-wp3-issue-triage.md +46 -0
  470. arenamcp-2.8.0/tools/training/wp3/PROGRESS-wp3-issue-triage2.md +34 -0
  471. arenamcp-2.8.0/tools/training/wp3/PROGRESS-wp3-menu-parity.md +121 -0
  472. arenamcp-2.8.0/tools/training/wp3/PROGRESS-wp3-next-run-prep.md +167 -0
  473. arenamcp-2.8.0/tools/training/wp3/PROGRESS-wp3-oracle-coverage.md +154 -0
  474. arenamcp-2.8.0/tools/training/wp3/PROGRESS-wp3-taxonomy.md +18 -0
  475. arenamcp-2.8.0/tools/training/wp3/PROGRESS-wp3-unseen-gate-slice.md +134 -0
  476. arenamcp-2.8.0/tools/training/wp3/PROGRESS-wt-bridge-x-chooser.md +54 -0
  477. arenamcp-2.8.0/tools/training/wp3/PROGRESS-wt-gpu-dashboard.md +70 -0
  478. arenamcp-2.8.0/tools/training/wp3/TEACHER_AUDITION.md +153 -0
  479. arenamcp-2.8.0/tools/training/wp3/baseline_plan.py +191 -0
  480. arenamcp-2.8.0/tools/training/wp3/build_mixture_manifest.py +582 -0
  481. arenamcp-2.8.0/tools/training/wp3/build_unseen_gate_corpus.py +524 -0
  482. arenamcp-2.8.0/tools/training/wp3/deck_inventory.json +573 -0
  483. arenamcp-2.8.0/tools/training/wp3/deck_inventory.md +91 -0
  484. arenamcp-2.8.0/tools/training/wp3/deck_inventory.py +476 -0
  485. arenamcp-2.8.0/tools/training/wp3/enrich_card_map.py +219 -0
  486. arenamcp-2.8.0/tools/training/wp3/fixture_bridge_out.jsonl +14 -0
  487. arenamcp-2.8.0/tools/training/wp3/fixture_combat_decisions.jsonl +14 -0
  488. arenamcp-2.8.0/tools/training/wp3/fixture_decisions.jsonl +20 -0
  489. arenamcp-2.8.0/tools/training/wp3/fixtures/fixture_combat_interleaved.log +261 -0
  490. arenamcp-2.8.0/tools/training/wp3/issue-triage.md +185 -0
  491. arenamcp-2.8.0/tools/training/wp3/mz_budget_sweep.py +147 -0
  492. arenamcp-2.8.0/tools/training/wp3/next_run_diverse.yml +77 -0
  493. arenamcp-2.8.0/tools/training/wp3/resolve_cards.py +200 -0
  494. arenamcp-2.8.0/tools/training/wp3/run_b5_gate_eval.py +986 -0
  495. arenamcp-2.8.0/tools/training/wp3/run_baseline.yml +50 -0
  496. arenamcp-2.8.0/tools/training/wp3/sample_combat_records.py +62 -0
  497. arenamcp-2.8.0/tools/training/wp3/score_tripwires.py +154 -0
  498. arenamcp-2.8.0/tools/training/wp3/sweep_base_two_server.yml +71 -0
  499. arenamcp-2.8.0/tools/training/wp3/validate_run_config.py +158 -0
  500. arenamcp-2.8.0/tools/training/wp_audit.md +194 -0
  501. arenamcp-2.8.0/uv.lock +6691 -0
  502. arenamcp-2.8.0/website/.env.example +18 -0
  503. arenamcp-2.8.0/website/Dockerfile +23 -0
  504. arenamcp-2.8.0/website/SETUP.md +192 -0
  505. arenamcp-2.8.0/website/app.py +1942 -0
  506. arenamcp-2.8.0/website/config.yaml +64 -0
  507. arenamcp-2.8.0/website/db.py +598 -0
  508. arenamcp-2.8.0/website/docker-compose.yml +18 -0
  509. arenamcp-2.8.0/website/patreon.py +476 -0
  510. arenamcp-2.8.0/website/providers.py +251 -0
  511. arenamcp-2.8.0/website/requirements.txt +6 -0
  512. arenamcp-2.8.0/website/templates/admin.html +2174 -0
  513. arenamcp-2.8.0/website/templates/landing.html +333 -0
  514. arenamcp-2.8.0/website/templates/subscribe.html +250 -0
  515. arenamcp-2.8.0/windows_integration.py +681 -0
@@ -0,0 +1,28 @@
1
+ # mtgacoach Configuration
2
+ # Copy this file to .env and configure as needed
3
+
4
+ # License key for online mode (mtgacoach.com)
5
+ # Get yours at https://mtgacoach.com/subscribe
6
+ # Can also be set via the TUI with: /key YOUR_LICENSE_KEY
7
+ # MTGACOACH_LICENSE_KEY=
8
+
9
+ # Local model configuration (vLLM by default; Ollama / LM Studio also supported)
10
+ # These can also be set via the TUI with: /local
11
+ # Default vLLM chat endpoint:
12
+ # LOCAL_URL=http://localhost:8000/v1
13
+ # LOCAL_MODEL=gemma4:e2b
14
+ # To fall back to Ollama, point LOCAL_URL at port 11434 instead:
15
+ # LOCAL_URL=http://localhost:11434/v1
16
+ # LOCAL_MODEL=llama3.2
17
+
18
+ # Optional embeddings endpoint (vLLM container at :8001 serving nomic-embed-text)
19
+ # EMBEDDING_URL=http://localhost:8001/v1
20
+ # EMBEDDING_MODEL=nomic-embed-text
21
+
22
+ # Launcher maintenance
23
+ # Automatically trim Player.log before launch when MTGA is not already running.
24
+ ARENAMCP_TRIM_PLAYER_LOG=1
25
+ # Trim when Player.log exceeds this size in MB.
26
+ ARENAMCP_PLAYER_LOG_MAX_MB=64
27
+ # Keep the newest tail of Player.log at this size in MB.
28
+ ARENAMCP_PLAYER_LOG_KEEP_MB=8
@@ -0,0 +1,88 @@
1
+ name: build-installer
2
+
3
+ # Builds mtgacoach-Setup.exe on a Windows runner and attaches it to the
4
+ # release for the pushed tag, alongside the Python wheel (.whl) artifact.
5
+ on:
6
+ push:
7
+ tags: ["v*"]
8
+ workflow_dispatch:
9
+ inputs:
10
+ release_tag:
11
+ description: "Existing release tag to attach the installer to (e.g. v2.4.0)"
12
+ required: false
13
+ default: ""
14
+
15
+ jobs:
16
+ installer:
17
+ runs-on: windows-latest
18
+ permissions:
19
+ contents: write
20
+ steps:
21
+ - uses: actions/checkout@v4
22
+
23
+ - name: Set up Python
24
+ uses: actions/setup-python@v5
25
+ with:
26
+ python-version: "3.12"
27
+
28
+ - name: Install build dependencies
29
+ run: |
30
+ python -m pip install --upgrade pip
31
+ pip install build hatchling pyinstaller
32
+ pip install -e .[desktop,full]
33
+
34
+ - name: Build Python wheel
35
+ run: python -m build --wheel
36
+
37
+ - name: Build standalone executable (PyInstaller)
38
+ run: pyinstaller mtgacoach.spec --noconfirm
39
+
40
+ - name: Install Inno Setup
41
+ run: choco install innosetup --no-progress -y
42
+
43
+ - name: Build installer
44
+ shell: pwsh
45
+ run: |
46
+ # Version source of truth: src/arenamcp/__init__.py. pyproject.toml
47
+ # uses hatch dynamic versioning and has no literal `version = "..."`
48
+ # line, so the old fallback could never resolve a version.
49
+ $versionMatch = Select-String -Path "src\arenamcp\__init__.py" -Pattern '^\s*__version__\s*=\s*"([^"]+)"' | Select-Object -First 1
50
+ if (-not $versionMatch) { throw "Could not read __version__ from src/arenamcp/__init__.py" }
51
+ $packageVersion = $versionMatch.Matches[0].Groups[1].Value
52
+
53
+ $version = "${{ inputs.release_tag || github.ref_name }}".TrimStart("v")
54
+ if ($version -notmatch '^\d') { $version = $packageVersion }
55
+ if ($version -ne $packageVersion) {
56
+ Write-Host "::warning::Release tag version '$version' does not match package __version__ '$packageVersion' - the installer asset will be stamped '$version'."
57
+ }
58
+
59
+ & "C:\Program Files (x86)\Inno Setup 6\ISCC.exe" /DAppVersion=$version installer\mtgacoach.iss
60
+ if (-not (Test-Path dist\installer\mtgacoach-Setup.exe)) { throw "installer not produced" }
61
+
62
+ - name: Attach to release
63
+ if: startsWith(github.ref, 'refs/tags/') || inputs.release_tag != ''
64
+ shell: pwsh
65
+ env:
66
+ GH_TOKEN: ${{ github.token }}
67
+ run: |
68
+ $tag = "${{ inputs.release_tag }}"
69
+ if (-not $tag) { $tag = "${{ github.ref_name }}" }
70
+ gh release upload "$tag" dist/installer/mtgacoach-Setup.exe --clobber
71
+ Get-ChildItem -Path dist\*.whl | ForEach-Object {
72
+ gh release upload "$tag" $_.FullName --clobber
73
+ }
74
+
75
+ - name: Upload installer artifact (non-tag runs)
76
+ if: ${{ !startsWith(github.ref, 'refs/tags/') && inputs.release_tag == '' }}
77
+ uses: actions/upload-artifact@v4
78
+ with:
79
+ name: mtgacoach-Setup
80
+ path: dist/installer/mtgacoach-Setup.exe
81
+
82
+ - name: Upload wheel artifact (non-tag runs)
83
+ if: ${{ !startsWith(github.ref, 'refs/tags/') && inputs.release_tag == '' }}
84
+ uses: actions/upload-artifact@v4
85
+ with:
86
+ name: mtgacoach-wheel
87
+ path: dist/*.whl
88
+
@@ -0,0 +1,46 @@
1
+ name: publish-pypi
2
+
3
+ # Publishes arenamcp to PyPI when a GitHub Release is published, using PyPI
4
+ # Trusted Publishing (OIDC) — no API token is stored anywhere.
5
+ #
6
+ # ONE-TIME SETUP (pypi.org web UI): Account → Publishing → "Add a new
7
+ # pending publisher":
8
+ # PyPI project name: arenamcp
9
+ # Owner: josharmour
10
+ # Repository: mtgacoach
11
+ # Workflow name: publish-pypi.yml
12
+ # Environment: pypi
13
+ # After the first successful publish the pending publisher becomes permanent.
14
+
15
+ on:
16
+ release:
17
+ types: [published]
18
+ workflow_dispatch:
19
+
20
+ jobs:
21
+ build:
22
+ runs-on: ubuntu-latest
23
+ steps:
24
+ - uses: actions/checkout@v4
25
+ - uses: actions/setup-python@v5
26
+ with:
27
+ python-version: "3.12"
28
+ - run: python -m pip install --upgrade build
29
+ - run: python -m build
30
+ - uses: actions/upload-artifact@v4
31
+ with:
32
+ name: dist
33
+ path: dist/
34
+
35
+ publish:
36
+ needs: build
37
+ runs-on: ubuntu-latest
38
+ environment: pypi
39
+ permissions:
40
+ id-token: write # OIDC token for Trusted Publishing
41
+ steps:
42
+ - uses: actions/download-artifact@v4
43
+ with:
44
+ name: dist
45
+ path: dist/
46
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,67 @@
1
+ name: tests
2
+
3
+ # The single CI workflow: one pytest run, one ruff run, per push/PR.
4
+ #
5
+ # 2026-07-24 consolidation: this ran alongside ci.yml, and BOTH executed the
6
+ # full ~700-test suite on every push to master with divergent configs
7
+ # (ci.yml: Python 3.11 + .[dev,full]; tests.yml: Python 3.12 + .[dev]).
8
+ # That doubled CI cost and, worse, meant a change could be green in one
9
+ # environment and red in the other. ci.yml has been removed; its
10
+ # dev+full extras (which match the local dev environment the test baseline
11
+ # is measured in) were folded in here.
12
+ #
13
+ # Platform-specific tests (Windows/macOS-only) rely on their own skip guards.
14
+ on:
15
+ push:
16
+ branches: [master, main]
17
+ pull_request:
18
+
19
+ concurrency:
20
+ group: tests-${{ github.ref }}
21
+ cancel-in-progress: true
22
+
23
+ jobs:
24
+ pytest:
25
+ runs-on: ubuntu-latest
26
+ timeout-minutes: 30
27
+ steps:
28
+ - uses: actions/checkout@v4
29
+
30
+ - uses: actions/setup-python@v5
31
+ with:
32
+ python-version: "3.12"
33
+ cache: pip
34
+
35
+ # sounddevice -> portaudio, soundfile -> libsndfile, PySide6 offscreen -> GL/xkb
36
+ - name: System dependencies (Qt offscreen + audio libs)
37
+ run: |
38
+ sudo apt-get update
39
+ sudo apt-get install -y --no-install-recommends \
40
+ libportaudio2 libsndfile1 \
41
+ libgl1 libegl1 libxkbcommon0 libdbus-1-3 libfontconfig1
42
+
43
+ - name: Install package with dev + full extras
44
+ run: |
45
+ python -m pip install --upgrade pip
46
+ python -m pip install -e ".[dev,full]"
47
+
48
+ - name: Run tests
49
+ env:
50
+ ARENAMCP_LOG_FILE: /tmp/arenamcp-pytest.log
51
+ QT_QPA_PLATFORM: offscreen
52
+ run: python -m pytest tests -q --tb=short
53
+
54
+ ruff:
55
+ runs-on: ubuntu-latest
56
+ timeout-minutes: 10
57
+ steps:
58
+ - uses: actions/checkout@v4
59
+ # Pinned: the repo is formatted with 0.15.22. Older pins format
60
+ # differently (0.15.2) or cannot parse [tool.ruff.lint] at all (0.6.9
61
+ # rejects the UP045 selector), so an unpinned/stale ruff fails CI on
62
+ # correctly-formatted code.
63
+ - uses: astral-sh/ruff-action@v3
64
+ with:
65
+ version: "0.15.22"
66
+ - run: ruff check src tests
67
+ - run: ruff format --check src tests
@@ -0,0 +1,69 @@
1
+ .env
2
+ .env.*
3
+ !.env.example
4
+ tmpclaude-*
5
+ __pycache__/
6
+ .venv/
7
+ tools/training/wp3/scryfall_cache.json
8
+ tools/training/data/wp3/
9
+ *.pyc
10
+ debug_log.txt
11
+ log_tail.txt
12
+ last_match_event.txt
13
+ build/
14
+ dist/
15
+ *.egg-info/
16
+ .codex/
17
+ .claude/
18
+ re-output/
19
+ nul
20
+ @eaDir/
21
+ *.planning/
22
+ bug_reports/
23
+ # Synology/deployment configs
24
+ docker-compose.yml
25
+ config.yaml
26
+ *.db
27
+ data/
28
+ # ...except tracked infra-as-code (no secrets; env refs only)
29
+ !gateway/config.yaml
30
+ !gateway/docker-compose.yml
31
+ !website/config.yaml
32
+ !website/docker-compose.yml
33
+ # Dev-only (not for public repo)
34
+ rl-pipeline-fix.md
35
+ tools/*
36
+ !tools/training/
37
+ !tools/monitoring/
38
+ tools/monitoring/*
39
+ !tools/monitoring/grafana/
40
+ tools/training/checkpoints/
41
+ tools/training/data/
42
+ !tools/eval/
43
+ tools/eval/data/
44
+ !tools/monitoring/
45
+ docs/
46
+ CLAUDE.md
47
+ *.spec
48
+ venv/
49
+ .venv/
50
+ .venv_*/
51
+ test_env/
52
+ # BepInEx plugin build artifacts
53
+ bepinex-plugin/**/bin/
54
+ bepinex-plugin/**/obj/
55
+ .DS_Store
56
+ stage0v2_31b_train.log
57
+ *_train.log
58
+ models/
59
+
60
+ # Dev-machine scratch, deliberately untracked (2026-07-27):
61
+ # launch.sh — hardcodes the old WSL path /home/joshu/repos/mtgacoach
62
+ # run_update.py — one-shot regex migration that REWRITES src/arenamcp/server.py
63
+ # in place; its edits are already merged. Keeping it runnable
64
+ # in the repo is a footgun, not history.
65
+ launch.sh
66
+ run_update.py
67
+
68
+ # Local grading worksheet (contains replay-derived game states; not for the public repo)
69
+ tripwire_review_v2.md
@@ -0,0 +1,31 @@
1
+ # Pre-commit hooks — install with: pre-commit install
2
+ repos:
3
+ - repo: https://github.com/pre-commit/pre-commit-hooks
4
+ rev: v4.6.0
5
+ hooks:
6
+ - id: trailing-whitespace
7
+ - id: end-of-file-fixer
8
+ - id: check-yaml
9
+ - id: check-toml
10
+ - id: check-added-large-files
11
+ args: ["--maxkb=500"]
12
+ - id: mixed-line-ending
13
+ args: ["--fix=lf"]
14
+
15
+ - repo: https://github.com/astral-sh/ruff-pre-commit
16
+ rev: v0.15.22
17
+ hooks:
18
+ - id: ruff
19
+ args: [--fix]
20
+ - id: ruff-format
21
+
22
+ # mypy is advisory-only until the baseline is cleaned up module-by-module.
23
+ # Enable locally with: pre-commit run mypy --all-files
24
+ - repo: https://github.com/pre-commit/mirrors-mypy
25
+ rev: v1.11.2
26
+ hooks:
27
+ - id: mypy
28
+ pass_filenames: false
29
+ args: [--config-file=pyproject.toml]
30
+ # Not wired to block commits yet — run manually.
31
+ stages: [manual]
@@ -0,0 +1,87 @@
1
+ # ArenaMCP — Agent Guidance
2
+
3
+ ## Project
4
+ Real-time AI coaching for MTG Arena with in-game overlay (BepInEx-driven ground-truth card positions).
5
+ Python package `arenamcp` under `src/arenamcp/`, desktop PySide6 GUI at `src/arenamcp/desktop/`, BepInEx C# plugin at `bepinex-plugin/MtgaCoachBridge/`.
6
+
7
+ ## Key Architecture
8
+ - **`launcher.py`** — internal TUI runtime launcher (subprocess-based, restarts on exit code 42)
9
+ - **`windows_integration.py`** — Windows install/repair helpers (stdlib-only)
10
+ - **`src/arenamcp/desktop/app.py`** — PySide6 desktop app entrypoint (main entry for users)
11
+ - **`src/arenamcp/server.py`** — FastMCP server bridging MTGA logs to LLM
12
+ - **`src/arenamcp/coach.py`** — Coach engine with pluggable LLM backends
13
+ - **`src/arenamcp/standalone.py`** — TUI/"standalone" client (voice + MCP client)
14
+ - **`src/arenamcp/autopilot.py`** — AI autoplay engine
15
+ - **`tests/`** — pytest test suite (600+ tests)
16
+
17
+ ## Sister Repository: MageZero RL Training (`~/repos/magezero`)
18
+ `mtgacoach` is paired with **`magezero`**, an AlphaZero-style MCTS reinforcement learning engine running inside an instrumented XMage simulator on `blackwell` (`10.0.0.10`).
19
+ - **Role Split**: `mtgacoach` handles live MTG Arena coaching, GRE state extraction, and HUD overlay. `magezero` trains deck-specific policy/value neural networks via distributed self-play.
20
+ - **Canonical RL Docs**: For RL architecture, hardware topology (R9700 vs RTX 6000s), live training status, and strategy, refer directly to `~/repos/magezero/AGENTS.md` and `~/repos/magezero/docs/PLAN_OF_RECORD.md`.
21
+ - **Telemetry Command**: Inspect the live training run on blackwell via:
22
+ ```bash
23
+ ssh joshu@10.0.0.10 'python3 -c "import json, pathlib; runs=sorted(pathlib.Path(\"/home/joshu/repos/magezero/runs\").glob(\"*/run.json\")); d=json.loads(runs[-1].read_text()); print(f\"Run {runs[-1].parent.name} | Gen {d.get(\"current_gen\")} | Stage: {d.get(\"stage\")}\")"'
24
+ ```
25
+
26
+ ## Developer Commands
27
+ ```bash
28
+ # Install (editable, with all extras)
29
+ pip install -e .[dev,full]
30
+
31
+ # Run tests (isolated log file via ARENAMCP_LOG_FILE env var)
32
+ pytest tests -q
33
+
34
+ # Run diagnostics
35
+ python -m arenamcp.diagnose
36
+
37
+ # Launch desktop app (Linux dev)
38
+ PYTHONPATH=src python -m arenamcp.desktop
39
+
40
+ # Launch standalone TUI
41
+ python -m arenamcp.standalone --backend online
42
+ ```
43
+
44
+ ## Local venvs (macOS dev machine)
45
+ - `.venv_mac_311/` — Python 3.11, the working macOS venv (pip, pytest, editable arenamcp). Use this on mac.
46
+ - `.venv/` — Linux/WSL-era venv; pip shebang broken on macOS (points at old ArenaMCP path).
47
+ - Deleted 2026-07-22: `.venv_mac/`, `test_env/` (Python 3.9 — below requires-python >=3.10).
48
+
49
+ ## Tooling (added 2026-07-22)
50
+ - **ruff** (lint + format) and **mypy** (advisory) — configs in `pyproject.toml`.
51
+ - **pre-commit** — `.pre-commit-config.yaml`; `pre-commit install` to enable.
52
+ - **CI** — `.github/workflows/tests.yml` runs ruff + pytest on push/PR (installer.yml unchanged).
53
+ - Version single-sourced in `src/arenamcp/__init__.py` (`__version__`); pyproject reads it via hatch dynamic versioning.
54
+
55
+ ## BepInEx C# Plugin (Linux dev)
56
+ - **Do NOT** use Wine's `csc` — too old for C# 9.0.
57
+ - Use `dotnet` (`.NET 10 SDK` installed).
58
+ - Override `MtgaDir` for Flatpak Steam:
59
+ ```bash
60
+ cd bepinex-plugin/MtgaCoachBridge
61
+ dotnet build -p:MtgaDir="/home/joshu/.var/app/com.valvesoftware.Steam/.local/share/Steam/steamapps/common/MTGA"
62
+ ```
63
+ - Deploy: copy `bin/Debug/net472/MtgaCoachBridge.dll` to MTGA's `BepInEx/plugins/`.
64
+
65
+ ## Testing Quirks
66
+ - `conftest.py` redirects `ARENAMCP_LOG_FILE` to `/tmp/arenamcp-pytest.log` so test noise doesn't pollute `~/.arenamcp/standalone.log`.
67
+ - No linter/formatter config in `pyproject.toml` (only pytest dependency). No pre-commit, no typechecker configured.
68
+ - CI only builds Windows installer via GitHub Actions (`.github/workflows/installer.yml`).
69
+
70
+ ## Packaging
71
+ - **`hatchling`** build backend, single package `src/arenamcp`
72
+ - GUI entrypoint: `mtgacoach-desktop = "arenamcp.desktop.app:main"`
73
+ - Installer: Inno Setup script at `installer/mtgacoach.iss`, built only on `windows-latest` runner (tag push `v*` or `workflow_dispatch`).
74
+
75
+ ## Log Locations (Windows)
76
+ | Log | Path |
77
+ |-----|------|
78
+ | Desktop UI | `%LOCALAPPDATA%\mtgacoach\desktop.log` |
79
+ | Launcher | `%LOCALAPPDATA%\mtgacoach\desktop-launch.log` |
80
+ | Coach runtime | `%USERPROFILE%\.arenamcp\standalone.log` |
81
+ | Bug reports | `%USERPROFILE%\.arenamcp\bug_reports\bug_*.json` |
82
+ | BepInEx | `<MTGA>\BepInEx\LogOutput.log` |
83
+
84
+ ## Development Flow
85
+ - Edits under `src/arenamcp/` take effect on next launch (no C# rebuild needed).
86
+ - `launch.bat` is the canonical Windows entrypoint for repo/manual installs.
87
+ - The coaching engine runs as a subprocess over a JSON pipe protocol (separate from the UI process).
arenamcp-2.8.0/DEV.md ADDED
@@ -0,0 +1,85 @@
1
+ # Development Workflow
2
+
3
+ Use exactly one desktop app during development: the PySide6 app in this repo.
4
+
5
+ ## One-Time Setup
6
+
7
+ Run this command on Windows:
8
+
9
+ ```powershell
10
+ C:\Users\joshu\AppData\Local\mtgacoach\venv\Scripts\python.exe -m pip install -e Z:\mtgacoach[desktop]
11
+ ```
12
+
13
+ `pip install -e` is important: the desktop app runs directly from the repo source tree.
14
+ `[desktop]` now includes the PySide app plus Kokoro desktop-worker dependencies.
15
+
16
+ This repo already contains a Linux `.venv` for WSL work. Do not try to use `Z:\mtgacoach\.venv` as the Windows launch environment.
17
+
18
+ ## Launch
19
+
20
+ Use exactly one launch target:
21
+
22
+ ```powershell
23
+ C:\Users\joshu\AppData\Local\mtgacoach\venv\Scripts\pythonw.exe Z:\mtgacoach\scripts\launch_desktop.py
24
+ ```
25
+
26
+ Recommended shortcut target:
27
+
28
+ - `C:\Users\joshu\AppData\Local\mtgacoach\venv\Scripts\pythonw.exe`
29
+
30
+ Recommended shortcut arguments:
31
+
32
+ - `Z:\mtgacoach\scripts\launch_desktop.py`
33
+
34
+ Recommended shortcut "Start in":
35
+
36
+ - `Z:\mtgacoach`
37
+
38
+ ## What Updates On Next Launch
39
+
40
+ - Any edit under `src\arenamcp\` takes effect on the next app launch.
41
+ - Any edit under `src\arenamcp\desktop\` takes effect on the next app launch.
42
+ - No C# rebuild is part of the normal dev loop anymore.
43
+ - Launch does not depend on the package being importable from an editable install; the launcher script adds `src\` directly.
44
+
45
+ If you change Python dependencies or entrypoints, rerun:
46
+
47
+ ```powershell
48
+ C:\Users\joshu\AppData\Local\mtgacoach\venv\Scripts\python.exe -m pip install -e Z:\mtgacoach[desktop]
49
+ ```
50
+
51
+ ## Do Not Use During Development
52
+
53
+ - `C:\Users\Public\Desktop\mtgacoach.lnk`
54
+ - `C:\Program Files\mtgacoach\...`
55
+ - `mtgacoach-dev.lnk`
56
+
57
+ Those are no longer part of the source-iteration workflow.
58
+
59
+ ## Useful Commands
60
+
61
+ Launch from a terminal without the GUI script wrapper:
62
+
63
+ ```powershell
64
+ C:\Users\joshu\AppData\Local\mtgacoach\venv\Scripts\python.exe -m arenamcp.desktop
65
+ ```
66
+
67
+ Run tests:
68
+
69
+ ```powershell
70
+ C:\Users\joshu\AppData\Local\mtgacoach\venv\Scripts\python.exe -m pytest Z:\mtgacoach\tests -q
71
+ ```
72
+
73
+ ## Logs
74
+
75
+ - Desktop UI log: `%LOCALAPPDATA%\mtgacoach\desktop.log`
76
+ - Desktop launcher log: `%LOCALAPPDATA%\mtgacoach\desktop-launch.log`
77
+ - Coach runtime log: `%USERPROFILE%\.arenamcp\standalone.log`
78
+ - Saved bug reports: `%USERPROFILE%\.arenamcp\bug_reports\bug_*.json`
79
+ - BepInEx log: `<MTGA>\BepInEx\LogOutput.log`
80
+
81
+ ## Notes
82
+
83
+ - The PySide6 app is the full desktop app now: coach UI plus repair/install flows.
84
+ - The coaching engine still runs as a subprocess internally over the existing JSON pipe protocol. That separation is intentional and keeps the UI responsive while preserving the current backend seam.
85
+ - Customer releases come from the packaged PySide installer built by `installer\build-installer.ps1`.
@@ -0,0 +1,158 @@
1
+ # GEMINI.md
2
+
3
+ ## Project Summary
4
+
5
+ `mtgacoach` (`arenamcp`) is an MTGA coaching project with:
6
+ - **Python Core (`src/arenamcp/`)**: Headless coaching engine driving the pipeline.
7
+ - **Desktop UI (`src/arenamcp/desktop/`)**: PySide6-based frontend providing the dashboard, coaching log, repair tools, and transparent, click-through HUD overlay.
8
+ - **BepInEx Plugin (`bepinex-plugin/MtgaCoachBridge/`)**: C# plugin injected into MTGA for direct GRE state access, action submission, and automation.
9
+ - **Proxy Server (`website/`)**: FastAPI gateway at `api.mtgacoach.com` routing subscriber LLM requests, tracking usage, and providing an eval dashboard.
10
+ - **LLM Evaluation Harness (`tools/eval/`)**: Harness for scoring local model quality (mulligans, turn-actions, replays) using real play prompts.
11
+ - **Sister RL Engine (`~/repos/magezero/`)**: Independent AlphaZero-style MCTS self-play training pipeline running in XMage on `blackwell` (`10.0.0.10`). Refer to `~/repos/magezero/AGENTS.md` and `~/repos/magezero/docs/PLAN_OF_RECORD.md` for RL telemetry and status.
12
+
13
+ ## Core Direction & Architecture
14
+
15
+ - **GRE Bridge is Primary**: Real-time game state tracking and action submissions run through the direct Unity GRE named pipe (`\\.\pipe\mtgacoach_bridge_v2`). Python acts as the named pipe server; BepInEx is the client.
16
+ - **Log Parsing as Fallback**: `Player.log` is parsed via a log watcher only as a fallback and for out-of-match/metadata diagnostics.
17
+ - **File System Separation**: Installed files live read-only under `Program Files\mtgacoach`, while mutable runtime files (venv, settings, logs) belong under `%LOCALAPPDATA%\mtgacoach` and `%USERPROFILE%\.arenamcp`.
18
+ - **Local LLM Default**: Default local backend is **vLLM** (`http://localhost:8000/v1`) running `google/gemma-4-E2B-it` (aliased as `gemma4:e2b`), with fallback to Ollama (`localhost:11434`) or LM Studio.
19
+
20
+ ## LLM Evaluation Harness (`tools/eval/`)
21
+
22
+ - Runs idempotent evaluation pipelines using captured prompts (`prompts.jsonl`).
23
+ - **Replay Scorer (`tools/eval/replay/`)**: Replays prompts through backends (`run.py`) and scores them against judge models on **contested decisions** (decisions where the player had a choice, to prevent easy moves from inflating match rate).
24
+ - **Mulligan Scorer**: Uses balanced accuracy (`balanced_higher_wr_rate`) to avoid keep-rate bias. Skips buckets within `MARGIN_THRESHOLD=0.05`.
25
+ - **Turn-action Scorer**: Uses Mean Jaccard (set overlap) as the headline metric.
26
+ - Supports WSL paths to allow running WSL evaluators against Windows MTGA paths.
27
+
28
+ ## Installer & Repair UX
29
+
30
+ - Prefer a **small installer** built by `installer/build-installer.ps1` that packages the application and downloads/creates the venv post-install.
31
+ - The repair UI must offer explicit user-visible actions for:
32
+ - `Create venv`
33
+ - `Setup environment`
34
+ - `Install BepInEx`
35
+ - `Install Plugin`
36
+ - Bridge repair / refresh actions
37
+
38
+ ## Release Rules
39
+
40
+ When revving a release (currently version `2.7.3`):
41
+ 1. Bump version in:
42
+ - `pyproject.toml`
43
+ - `src/arenamcp/__init__.py`
44
+ - `installer/mtgacoach.iss`
45
+ 2. Commit changes.
46
+ 3. Tag `vX.Y.Z`.
47
+ 4. Build the installer (`build-installer.ps1`) and verify the output at `dist/installer/mtgacoach-Setup.exe`.
48
+ 5. Push master and tag.
49
+ 6. Create/update the GitHub release and upload `mtgacoach-Setup.exe`.
50
+
51
+ ## Common Commands
52
+
53
+ ### Setup & Run
54
+ ```powershell
55
+ # Editable dev install (Windows)
56
+ C:\Users\joshu\AppData\Local\mtgacoach\venv\Scripts\python.exe -m pip install -e Z:\mtgacoach[desktop]
57
+
58
+ # Run PySide6 app from source
59
+ C:\Users\joshu\AppData\Local\mtgacoach\venv\Scripts\python.exe -m arenamcp.desktop
60
+
61
+ # Launch app using wrapper script
62
+ C:\Users\joshu\AppData\Local\mtgacoach\venv\Scripts\pythonw.exe Z:\mtgacoach\scripts\launch_desktop.py
63
+ ```
64
+
65
+ ### Build & Test
66
+ ```powershell
67
+ # Run regression tests
68
+ C:\Users\joshu\AppData\Local\mtgacoach\venv\Scripts\python.exe -m pytest Z:\mtgacoach\tests -q
69
+
70
+ # Build BepInEx plugin DLL (C#)
71
+ cd bepinex-plugin/MtgaCoachBridge && dotnet build -c Release
72
+
73
+ # Build Windows installer from WSL
74
+ p=$(wslpath -w /home/joshu/repos/mtgacoach/installer) && powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "\$p='${p}'; Set-Location -LiteralPath \$p; .\build-installer.ps1"
75
+ ```
76
+
77
+ ### Verification & Eval
78
+ ```powershell
79
+ # Verify local vLLM endpoint
80
+ C:\Users\joshu\AppData\Local\mtgacoach\venv\Scripts\python.exe tools/verify_vllm.py
81
+
82
+ # Run replay evaluation harness
83
+ C:\Users\joshu\AppData\Local\mtgacoach\venv\Scripts\python.exe tools/eval/replay/run.py
84
+ ```
85
+ ## Repository Directory & File Map
86
+
87
+ ### Top-Level Layout
88
+ * **`src/`**: The core Python codebase (`arenamcp`). This is the heart of the backend coaching loop, logs, game-state logic, Named Pipe GRE bridge server, and PySide6 desktop UI.
89
+ * **`bepinex-plugin/`**: The C# Unity plugin injected into Magic: The Gathering Arena. It intercepts internal game states and acts as a Named Pipe client connecting directly to Python.
90
+ * **`website/`**: A FastAPI application running on `api.mtgacoach.com` (under Synology/Docker) that validates licenses, routes LLM requests to the LiteLLM gateway (self-hosted models only; the legacy Azure/OpenAI path is decommissioned), and serves the admin evaluation dashboard.
91
+ * **`tools/`**: Diagnostic scripts, vLLM verification tools, and the comprehensive evaluation harness (`tools/eval/`) for measuring LLM output quality.
92
+ * **`installer/`**: Inno Setup script (`mtgacoach.iss`) and build automation scripts (`build-installer.ps1`) to generate the lightweight Windows setup executable.
93
+ * **`dist/`** *(Generated)*: Where release builds of the app and final installer packages are staged.
94
+ * **`venv/`** / **`.venv/`** *(Gitignored)*: Local Python virtual environments used during WSL/Windows development.
95
+ * **`.tools/`** / **`.vscode/`** *(Gitignored)*: IDE configuration and local development helper scripts.
96
+
97
+ ### Python Coaching Engine ([src/arenamcp/](file:///Z:/mtgacoach/src/arenamcp))
98
+
99
+ #### Communication & Protocols
100
+ * [pipe_adapter.py](file:///Z:/mtgacoach/src/arenamcp/pipe_adapter.py) — Establishes the JSON-over-stdio protocol used by the headless coaching subprocess to communicate back to the PySide6 desktop frontend.
101
+ * [gre_bridge.py](file:///Z:/mtgacoach/src/arenamcp/gre_bridge.py) — Runs a local Named Pipe server (`\\.\pipe\mtgacoach_bridge_v2`) to exchange game snapshots and execute automation actions with the BepInEx Unity plugin.
102
+ * [gre_serializer.py](file:///Z:/mtgacoach/src/arenamcp/gre_serializer.py) — Protobuf JSON translator for GRE events.
103
+ * [gre_action_matcher.py](file:///Z:/mtgacoach/src/arenamcp/gre_action_matcher.py) — Maps high-level decisions from the action planner to low-level GRE action objects.
104
+ * [parser.py](file:///Z:/mtgacoach/src/arenamcp/parser.py) & [watcher.py](file:///Z:/mtgacoach/src/arenamcp/watcher.py) — File watcher and parser for `Player.log` acting as a fallback data source.
105
+
106
+ #### State & Decision Engine
107
+ * [gamestate.py](file:///Z:/mtgacoach/src/arenamcp/gamestate.py) — Main game state management. Processes direct GRE bridge protobuf messages and log parsing.
108
+ * [coach.py](file:///Z:/mtgacoach/src/arenamcp/coach.py) — Prompt building, LLM querying, advice post-processing, and fallback deterministic scoring logic.
109
+ * [action_planner.py](file:///Z:/mtgacoach/src/arenamcp/action_planner.py) — Autonomous gameplay planning using LLM-generated actions.
110
+ * [autopilot.py](file:///Z:/mtgacoach/src/arenamcp/autopilot.py) — Core executor for autonomous play, utilizing GRE bridge API and OS level inputs.
111
+ * [combat_solver.py](file:///Z:/mtgacoach/src/arenamcp/combat_solver.py) — Solves complex combat math for planning.
112
+ * [standalone.py](file:///Z:/mtgacoach/src/arenamcp/standalone.py) — Entry point for headless coaching loop, managing trigger states.
113
+
114
+ #### Database & External APIs
115
+ * [scryfall.py](file:///Z:/mtgacoach/src/arenamcp/scryfall.py) — Scryfall REST API client with local disk cache.
116
+ * [draftstats.py](file:///Z:/mtgacoach/src/arenamcp/draftstats.py) & [draft_eval.py](file:///Z:/mtgacoach/src/arenamcp/draft_eval.py) — Queries and processes 17lands data to evaluate draft options.
117
+ * [mtgadb.py](file:///Z:/mtgacoach/src/arenamcp/mtgadb.py) & [mtgjson.py](file:///Z:/mtgacoach/src/arenamcp/mtgjson.py) — Integrates local card lookup SQLite databases.
118
+
119
+ #### Interaction & Desktop Integration
120
+ * [input_controller.py](file:///Z:/mtgacoach/src/arenamcp/input_controller.py) — Coordinates direct OS clicks and key input automation.
121
+ * [screen_mapper.py](file:///Z:/mtgacoach/src/arenamcp/screen_mapper.py) — Calculates positions on screen for card/button interactions.
122
+ * [vision_mapper.py](file:///Z:/mtgacoach/src/arenamcp/vision_mapper.py) — VLM-based pixel-level fallback coordinate resolver.
123
+ * [tts.py](file:///Z:/mtgacoach/src/arenamcp/tts.py) & [transcription.py](file:///Z:/mtgacoach/src/arenamcp/transcription.py) — Text-to-Speech synthesis and transcription integration.
124
+
125
+ ### Desktop UI Subsystem ([src/arenamcp/desktop/](file:///Z:/mtgacoach/src/arenamcp/desktop))
126
+ * [app.py](file:///Z:/mtgacoach/src/arenamcp/desktop/app.py) — PySide6 application runtime initialization.
127
+ * [main_window.py](file:///Z:/mtgacoach/src/arenamcp/desktop/main_window.py) — Main workspace window and tab shell.
128
+ * [coach_tab.py](file:///Z:/mtgacoach/src/arenamcp/desktop/coach_tab.py) — Central control panel for voice settings, engine logs, and session controls.
129
+ * [repair_tab.py](file:///Z:/mtgacoach/src/arenamcp/desktop/repair_tab.py) — Self-healing diagnostic interface (venv setup, environment settings, BepInEx installation, and bridge validation).
130
+ * [hud.py](file:///Z:/mtgacoach/src/arenamcp/desktop/hud.py) & [card_overlay.py](file:///Z:/mtgacoach/src/arenamcp/desktop/card_overlay.py) — Transparent click-through overlay window displaying draft reviews directly on top of MTGA.
131
+ * [coach_process.py](file:///Z:/mtgacoach/src/arenamcp/desktop/coach_process.py) — Manages standard subprocess pipes to start/stop the standalone backend process.
132
+
133
+ ### Unity C# Plugin ([bepinex-plugin/MtgaCoachBridge/](file:///Z:/mtgacoach/bepinex-plugin/MtgaCoachBridge))
134
+ * [Plugin.cs](file:///Z:/mtgacoach/bepinex-plugin/MtgaCoachBridge/Plugin.cs) — Injected DLL logic. Injects into MTGA Unity lifecycle, handles connection to local Named Pipe (`\\.\pipe\mtgacoach_bridge_v2`), and executes marshaled main-thread queries/actions.
135
+ * [BotBattleBridge.cs](file:///Z:/mtgacoach/bepinex-plugin/MtgaCoachBridge/BotBattleBridge.cs) — Intercepts and logs bot match statistics and triggers.
136
+
137
+ ### Proxy Server Backend ([website/](file:///Z:/mtgacoach/website))
138
+ * [app.py](file:///Z:/mtgacoach/website/app.py) — FastAPI server routing LLM requests, validating client keys, and exposing admin portals.
139
+ * [providers.py](file:///Z:/mtgacoach/website/providers.py) — Provider wrappers with priority-based route fallbacks and backoff logic.
140
+ * [db.py](file:///Z:/mtgacoach/website/db.py) — SQLite wrapper tracking client license tokens and server metrics.
141
+ * [templates/admin.html](file:///Z:/mtgacoach/website/templates/admin.html) — Cloud admin evaluation dashboard, displaying real-time latencies, charts, and metrics tables.
142
+
143
+ ### Evaluation Harness ([tools/eval/](file:///Z:/mtgacoach/tools/eval))
144
+ * [run.py](file:///Z:/mtgacoach/tools/eval/run.py) & [judge.py](file:///Z:/mtgacoach/tools/eval/judge.py) — Replays prompt sets through custom backends and uses a self-hosted judge model to grade model output.
145
+ * [report.py](file:///Z:/mtgacoach/tools/eval/report.py) — Generates accuracy tables and markdown report summaries.
146
+ * [replay/run.py](file:///Z:/mtgacoach/tools/eval/replay/run.py) & [replay/score.py](file:///Z:/mtgacoach/tools/eval/replay/score.py) — Runs and scores model outputs on real-game replay prompts, focusing on contested decisions to filter out easy play bias.
147
+ * [seventeenlands/score_mulligan.py](file:///Z:/mtgacoach/tools/eval/seventeenlands/score_mulligan.py) & [seventeenlands/score_turn_actions.py](file:///Z:/mtgacoach/tools/eval/seventeenlands/score_turn_actions.py) — Scores decisions against 17lands data using balanced accuracy and Jaccard metrics.
148
+
149
+ ## Hygiene
150
+
151
+ Do not commit:
152
+ - `.venv/` or `venv/`
153
+ - `.tools/`
154
+ - `bin/` or `obj/`
155
+ - Scratch files (e.g. `.ab` files, `last_match_event.txt`, debug logs)
156
+ - Generated `dist/` or `build/` files
157
+
158
+ `tests/` may be ignored in git by default; use `git add -f tests/...` if you need to add new tests to git.