Left action panel revised to show triggers list + Create Token/Auto-Arrange.
CMD DMG badges added to center life-panel score areas (click opens matrix).
Removed renderEnhancedPanels calls that split the battlefield on damage adjust.
Added encoding='utf-8' to all bare open() calls across 17 Python files to
prevent cp1252 crashes on MTG card text with smart quotes/em-dashes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Forge DecisionExporter writes action={"type":"cast"} without a card
field — action.get("card") and action.get("raw") always returned "",
causing every cast to fall through to the CAST_CREATURE default.
Fix: when card_name is empty, scan the active player's hand against
the removal / draw / ramp / commander name databases and pick the
highest-priority match found. Priority order mirrors cast importance:
removal > ramp > draw > commander > creature (default)
A hand-level match is a reasonable proxy for the decision made:
Forge's AI picks the highest-priority action from available options,
so if the hand contains a removal spell during main phase, the cast
action almost certainly represents that removal spell being played.
Also fixes print_label_distribution: was sorting by dict key (string)
instead of by index, causing the display order to be alphabetical
rather than matching the MacroAction enum order — making cast_creature
appear at position 0 in the sorted output even when it had counts.
Now prints in descending count order with correct enum-keyed lookup.
Replace all print() calls with structured logging using the Python
logging module. This provides:
- Named loggers per subsystem: commander_ai_lab.api, .batch, .sim,
.coach, .deckgen, .collection, .scanner, .ml, .cache, .pplx
- Dual output: console (StreamHandler) + rotating file (RotatingFileHandler)
at logs/commander-ai-lab.log (25 MB x 5 backups = 125 MB max)
- Configurable via env vars: CAL_LOG_DIR, CAL_LOG_MAX_MB, CAL_LOG_BACKUP_COUNT
- --verbose / -v flag for DEBUG-level output
- overnight-run.py: separate rotating log at logs/overnight-run.log (10 MB x 5)
- Sub-module loggers in ml/, scanner/, deck_sources/, src/ all propagate
to the root commander_ai_lab logger
- Stripped redundant [TAG] prefixes from messages (logger name carries context)
- Format: '2026-03-13 14:00:00 INFO [commander_ai_lab.batch] message'
Files changed: lab_api.py, overnight-run.py, and 11 sub-module .py files
176 total print() calls converted (101 in lab_api.py, 76 in sub-modules)