Commit Graph
72 Commits
Author SHA1 Message Date
rgriffith e843528d8b Phase 6: ELO Tracking & Model Tournament (#70)
- Create ml/eval/elo_tracker.py:
  - EloTracker class with standard ELO formula (K=32, start=1200)
  - EloResult dataclass for tournament output
  - EloHistory class for JSON persistence (data/elo_history.json)
  - run_elo_tournament(): round-robin ELO-rated matches using
    existing run_match() from tournament.py
  - run_generation_tournament(): discovers gen-*/best_policy.pt
    checkpoints and runs cross-generation ELO tournament
  - CLI entry point: python -m ml.eval.elo_tracker

- Add ELO API endpoints to routes/ml.py:
  - POST /api/ml/elo/tournament — start background ELO tournament
  - GET  /api/ml/elo/tournament/status — poll progress
  - GET  /api/ml/elo/history — load ELO history from disk

- Integrate ELO convergence in distillation_loop.py:
  - New config fields: elo_convergence_enabled (default False),
    elo_convergence_threshold (20.0), elo_tournament_episodes (30)
  - New field: GenerationRecord.elo_rating
  - _run_elo_mini_tournament() runs after quality gate pass
  - _check_convergence() checks ELO delta when enabled

- Add ELO UI to distillation page:
  - ELO Ratings panel with canvas multi-line chart showing per-model
    ELO progression across generations
  - Run Tournament button with progress indicator
  - ELO leaderboard table with rank, rating, and visual bars
  - Responsive chart resize handling

Closes #70
2026-03-22 00:31:02 +00:00
rgriffith 106ec716a5 Phase 5: Distillation UI Integration & Monitoring (#69)
- Add distillation API endpoints to routes/ml.py:
  - POST /api/ml/distill/start — start closed-loop distillation pipeline
  - GET  /api/ml/distill/status — poll loop status and generation data
  - POST /api/ml/distill/stop — graceful stop after current generation
  - GET  /api/ml/distill/history — load persisted generation history

- Add 'Distill' nav entry in ui/nav.js with loop icon

- Create ui/distillation.html:
  - Status overview cards (status, generation, best win rate, gate passes)
  - Control panel with hyperparameter inputs for supervised, PPO, and
    quality gate settings
  - Start/Stop buttons with progress bar and phase badge
  - Win rate trend chart (canvas-based, no dependencies)
  - Data composition stacked bar chart (Forge vs PPO per generation)
  - Generation history table with status, metrics, and gate results

- Create ui/distillation.js:
  - Polling loop for real-time status updates during distillation
  - Canvas chart rendering for win rate trends and data composition
  - History table rendering with color-coded status tags
  - Responsive resize handling for charts

- Create ui/distillation.css:
  - Page-specific styles following training.css patterns
  - Chart container, history table, and responsive grid styles

Closes #69
2026-03-22 00:18:43 +00:00
KoalaTrapLord dc66ed78e5 fix(lab): remove shadowed _ml_logging_enabled redeclaration (closes #64) 2026-03-22 00:10:12 +00:00
KoalaTrapLord 871934d101 fix: raise VALIDATOR_TIMEOUT default from 60s to 120s (#71) 2026-03-21 19:40:19 -04:00
KoalaTrapLord 6612f3d213 fix: use correct key best_val_acc in training completion message 2026-03-21 15:21:35 -04:00
KoalaTrapLord 1397f93b91 feat(ml): wire ML decision flush in _finish_sim for all sim threads 2026-03-21 14:30:47 -04:00
KoalaTrapLord 8c34cb0966 feat: Phase 8 — surface player_explanation in simulation results JSON
Extract player_explanation from validation dict in each turn log
entry within _run_game_loop(). The React frontend can now render
validator explanations when player_explanation is non-null.
2026-03-21 13:37:09 -04:00
KoalaTrapLord c67ce422d8 refactor: rename LM_STUDIO/LMStudioClient to LLM/LLMClient in routes/coach.py 2026-03-21 13:34:21 -04:00
KoalaTrapLord 8b527d7c30 fix: remove duplicate ml_log=True kwarg in deepseek.py 2026-03-21 12:48:56 -04:00
KoalaTrapLord 963a5db638 fix(ml): enable ml_log=True in deepseek route engine calls 2026-03-21 12:41:01 -04:00
KoalaTrapLord b0a34ae9e2 Update DeepSeek port from 1234 to 11434 in coach.py 2026-03-20 21:52:39 -04:00
KoalaTrapLord 488575f3df fix(routes): correct indentation of validator line in _run_sim_thread_deepseek 2026-03-20 21:42:11 -04:00
KoalaTrapLord fd7f0258f3 feat(routes): add validator singleton and /api/validator endpoints 2026-03-20 21:27:15 -04:00
KoalaTrapLord 678cc13fe0 feat: enable ML logging by default in lab.py 2026-03-20 21:05:37 -04:00
KoalaTrapLord 19f83a546b feat: enable ML logging by default in shared.py 2026-03-20 21:01:40 -04:00
KoalaTrapLord 80f63f192a fix: update DeepSeek endpoint IP in coach.py 2026-03-20 11:06:30 -04:00
KoalaTrapLord 69ce5b340e fix: normalize indentation in _finish_sim (line 184-185) 2026-03-19 17:13:13 -04:00
KoalaTrapLord 8be96ab47d fix: use coach.report_generator for deck report generation 2026-03-19 17:05:03 -04:00
KoalaTrapLord e2653b3f72 fix: align sim results path with coach (routes/results) 2026-03-19 17:03:00 -04:00
KoalaTrapLord 7efac34279 fix: persist sim results to disk + auto-generate deck reports 2026-03-19 16:59:55 -04:00
KoalaTrapLord 76139477be fix: replace pplx.model with getattr, update V3 error messages for Ollama 2026-03-19 15:26:15 -04:00
KoalaTrapLord 4ec6ed57d5 fix: add missing urllib imports to deckbuilder.py for Scryfall card lookup 2026-03-19 15:11:33 -04:00
KoalaTrapLord f6ed40a253 fix: correct indentation in init_coach_service V3 deck gen block 2026-03-19 14:46:16 -04:00
KoalaTrapLord 0bbc78ef23 fix: rewire routes/coach.py to use DeckBuilderAdapter + fix IndentationError 2026-03-19 14:02:23 -04:00
KoalaTrapLord a80e8908e1 fix: indent _deck_gen_v3_error inside if block in coach.py 2026-03-19 13:35:44 -04:00
KoalaTrapLord 86af4b6de5 fix: close missing paren in _call_pplx_api client.post() 2026-03-19 13:16:22 -04:00
KoalaTrapLord cc481bd71b feat: switch deck generation from Perplexity to local Ollama (gpt-oss:20b) 2026-03-19 10:26:24 -04:00
KoalaTrapLord 2b355ed9ba Fix NameError: _coach_embeddings not defined in V3 status endpoint 2026-03-19 08:05:26 -04:00
KoalaTrapLord 75568bfdb1 fix: expose full V3 init traceback in _deck_gen_v3_error for easier debugging 2026-03-19 06:27:04 -04:00
KoalaTrapLord 87abfd801e Fix V3 500 error: replace json_schema response_format with json_object
- Sonar does not support response_format type json_schema
- Switch to {"type": "json_object"} which Sonar supports
- Keep json_schema/schema_name params for call-site compatibility (ignored)
- Add exc_info=True to V3 generate error logging for full tracebacks
2026-03-19 10:04:36 +00:00
rgriffith 9a46b0f80c fix: remove duplicate Scryfall/helper defs from collection.py that shadowed working imports
collection.py re-defined _ScryfallCache, _scryfall_cache,
_scryfall_rate_limit, _fetch_scryfall_api, _enrich_from_scryfall,
_parse_finish, _parse_text_line, _auto_infer_mapping, _parse_csv_content,
_TYPE_PRIORITY, and _TYPE_TARGETS locally (lines 333-509).

These local definitions shadowed the correct imports from
routes/shared.py -> services/scryfall.py. Critically, the local
_fetch_scryfall_api used Request and urlopen without importing them,
causing a NameError at runtime that was silently swallowed by the
broad except clause — making every card fail Scryfall enrichment
during collection import.

Removed all ~470 lines of duplicate code. The import endpoint now
correctly uses the functions imported from shared.py, which have
proper urllib imports and a working Scryfall cache.
2026-03-19 09:43:26 +00:00
Computer c6329d377a fix: register missing /api/ml and /api/health routes 2026-03-19 06:48:41 +00:00
KoalaTrapLord 3f7f40d626 Make _call_pplx_api async with httpx.AsyncClient
- Replace blocking urlopen with async httpx.AsyncClient
- Add await at both call sites (deck_research, deck_generate_ai)
- Uvicorn event loop no longer stalled during Perplexity API calls
2026-03-19 06:32:18 +00:00
KoalaTrapLord bc023ab6f6 Fix indentation in coach.py _build_deck_report_from_db (2-space -> 4-space) 2026-03-19 06:26:27 +00:00
KoalaTrapLord e3f0787c73 Optimize deckgen: push colour-identity filtering into SQL with json_each
- Replace SELECT * + Python-side color loop in _get_collection_for_colors()
  with projected SELECT + NOT EXISTS json_each() sub-query
- Apply same pattern to _build_collection_summary(), removing card_fits_identity()
- Add partial index idx_ce_quantity on collection_entries(quantity) WHERE qty > 0
- Handle NULL and empty-string color_identity via CASE guard
- Fix colorless commander bug: old code skipped color check entirely for []
- Add scripts/bench_deckgen.py benchmark (3-5x speedup on filtered queries)
- Add tests/test_deckgen_color_filter.py with 7 regression tests
2026-03-19 06:18:32 +00:00
KoalaTrapLord 2936fd37eb Refactor routes/ml.py: replace state dicts with dataclasses + threading locks
- Add @dataclass classes _TrainingState, _PPOState, _TournamentState with snapshot() method
- Wrap all state mutations in threading.Lock() for thread safety
- Replace dict bracket access with attribute access
- Remove unnecessary global declarations from pipeline functions
2026-03-19 06:06:11 +00:00
Computer 2d8a55fdc6 refactor: use _write_dck_file and _build_dck_lines in deckgen.py 2026-03-19 05:11:38 +00:00
KoalaTrapLord c980e1b6d5 refactor: remove inline Pydantic models from deckgen.py, import from models.requests 2026-03-19 00:55:17 -04:00
KoalaTrapLord 7c7be013c2 refactor: remove inline Pydantic models from coach.py, import from models.requests 2026-03-19 00:53:33 -04:00
KoalaTrapLord 6534380f67 fix: replace full-table scan with parameterized WHERE in _build_deck_report_from_db (closes #60) 2026-03-19 00:40:28 -04:00
KoalaTrapLord a95ae45e18 fix: remove API key prefix exposure from /api/pplx/status endpoint 2026-03-19 00:05:33 -04:00
ClaudeandClaude Opus 4.6 71c90a588f fix: resolve /api/lab/result 500 and /api/lab/precons/install-batch 400
- GET /api/lab/result: Starlette's JSONResponse uses allow_nan=False,
  so NaN/Infinity floats from simulation output cause a ValueError crash.
  Add _sanitize_floats() to replace non-finite floats with null before
  returning. Also wrap json.load in try/except for better error reporting.

- POST /api/lab/precons/install-batch: Frontend sends {"names": [...]}
  but backend expected {"fileNames": [...]}. Accept both field names.

- POST /api/lab/precons/install: Same mismatch — frontend sends {"name"}
  but backend expected {"fileName"}. Accept both field names.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 06:11:14 +00:00
Commander AI Lab Agent fbc3bdb6b5 fix: add _resolve_precon_dir() auto-detection so CFG.precon_dir is not empty
The precon deck list was missing after the monolith refactor because
PRECON_DIR was hardcoded in services/precon_service.py with no CLI arg,
env var, or auto-resolve fallback — unlike forge_jar, forge_dir, etc.

Changes:
- Add precon_dir field to Config class (models/state.py)
- Add --precon-dir CLI arg and PRECON_DIR env var support
- Add _resolve_precon_dir() with project-root, parent-dir, and
  forge_dir-relative detection; creates dir as fallback for downloads
- Refactor precon_service.py to use _get_precon_dir() helper that reads
  CFG.precon_dir at runtime instead of a hardcoded module-level Path
- Update routes/precon.py to use _get_precon_dir() for install endpoints
- Wire _on_startup to resolve precon_dir for uvicorn-direct launches
- Remove unused PRECON_DIR/PRECON_INDEX imports from routes/lab.py
- Audit confirms all other CFG path fields already have fallbacks
2026-03-18 04:56:03 +00:00
ClaudeandClaude Opus 4.6 70ad16fc79 fix: add missing _get_deepseek_brain and _run_deepseek_batch_thread to forge_runner.py
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 04:31:14 +00:00
Commander AI LabandClaude Opus 4.6 3f66a8ed15 feat: add 4-player batch simulator React page with N-player API endpoint
- Add POST /api/sim/run-n-player endpoint accepting 2-4 deck IDs for
  N-player batch simulations using the existing engine.run_n() method
- Add _run_sim_thread_n_player tracking per-seat wins and stats
- Create SimulatorPage.tsx with 4 deck selection slots, config row,
  progress bar, results table, CSS bar chart, and per-game logs
- Add simulator types in frontend/src/types/simulator.ts
- Add /simulator route and nav bar to App.tsx

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 03:39:03 +00:00
KoalaTrapLord 554b166787 Phase 2d/2e/2f: Extract forge_runner, precon_service, import_service/helpers into services/ 2026-03-17 15:22:19 -04:00
KoalaTrapLord 874561f423 Phase 2c: Extract card analysis to services/card_analysis.py (#12) 2026-03-17 05:14:35 -04:00
KoalaTrapLord c7309d1ace Phase 2b: Extract deck service to services/deck_service.py (#11) 2026-03-17 05:05:52 -04:00
KoalaTrapLord 5aee93dfae Phase 1c: Extract datPhase 2a: Extract Scryfall client to services/scryfall.py (#10)abase service to services/database.py (#9) 2026-03-17 04:54:36 -04:00
KoalaTrapLord e14a6f9500 Phase 1c: Extract database service to services/database.py (#9) 2026-03-17 04:40:44 -04:00