Commit Graph
117 Commits
Author SHA1 Message Date
Claude 0b623ec39e feat: add lobby UI, build integration, and test suite (Phases 9, 11, 12)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 02:56:16 +00:00
ClaudeandClaude Opus 4.6 d489f84825 feat: implement game UI components, WebSocket hook, routing (Phases 3-8)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 02:43:43 +00:00
ClaudeandClaude Opus 4.6 d1bed9ac20 feat: scaffold React+TS frontend with types and Tailwind tokens (Phases 1, 2, 10)
Phase 1 — Project Scaffold:
- Vite + React-TS project in frontend/ with Tailwind v3, PostCSS, Autoprefixer
- clsx and react-router-dom installed
- Vite proxy configured for /api and /ws to localhost:8000
- Tailwind directives in src/index.css
- Makefile targets: frontend-dev, frontend-build
- app.py updated to serve frontend/dist/ with SPA catch-all fallback

Phase 2 — Type Definitions:
- TypeScript types in frontend/src/types/game.ts (Phase, Card, Player,
  GameState, WsIncoming, NarrationLine)
- Constants in frontend/src/constants.ts (SEAT_COLOURS, PHASES)

Phase 10 — Tailwind Colour Tokens:
- Custom color tokens for bg, accent, life, seat, card color groups
- Additional tokens from index.html audit: border, phase, btn, text, highlight
- Custom pulse animation keyframe

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 02:35:50 +00:00
KoalaTrapLord 3f38a9885f Slim install script from 3.2MB to git clone approach (~8KB) - closes #31
This script installs the Commander AI Lab environment by checking prerequisites, cloning the repository, and installing dependencies.
2026-03-17 16:20:19 -04:00
KoalaTrapLord 940836db7e Add GitHub Actions CI workflow (lint + test on push) - closes #33 2026-03-17 16:18:50 -04:00
KoalaTrapLord fd74f157e8 Phase 4: Slim lab_api.py to thin main() - closes #25
Refactor lab_api.py to streamline imports, improve logging, and enhance argument parsing.
2026-03-17 16:17:53 -04:00
KoalaTrapLord 179a53c0af Implement Moxfield deck source adapter (closes #35) 2026-03-17 15:59:10 -04: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
KoalaTrapLord 7baae153ae Phase 1b: Extract Config, BatchState, AI_PROFILES into models/state.py (#8) 2026-03-17 01:57:22 -04:00
KoalaTrapLord eadf54c670 Phase 1a: Extract Pydantic models into models/requests.py + models/responses.py (#7) 2026-03-17 01:45:57 -04:00
KoalaTrapLord 312d13949d feat: extract ML endpoints into routes/ml.py (#36)
Moved all 15 /api/ml/* endpoints, 4 state dicts, and 3 background
pipeline functions from lab_api.py into routes/ml.py. Wired via
app.include_router(ml_router) in lab_api.py.
2026-03-17 00:41:31 -04:00
KoalaTrapLord 192c307ca7 refactor(#42): deduplicate sim thread functions in deepseek.py 2026-03-17 00:20:51 -04:00
KoalaTrapLord 5cb6e6ce81 refactor(#41): remove duplicate _get_deepseek_brain from deepseek.py, import from shared 2026-03-17 00:08:04 -04:00
KoalaTrapLord 01af4d7bcf cleanup(#38): delete stale ROUTES_WIRING.md
This doc referenced the old routes._wire autoload pattern and only listed 5 routers. The project now uses 9 direct include_router() calls. Closes #38.
2026-03-17 00:05:19 -04:00
KoalaTrapLord 301b9d38c8 fix(#40): use Path().parent.parent for correct src/ resolution in routes/deepseek.py 2026-03-17 00:02:22 -04:00
KoalaTrapLord 09b0708c4d fix(models): commander_tax int→dict to match engine per-commander tax tracking 2026-03-16 23:58:07 -04:00
KoalaTrapLord 1121e1cb26 feat: add commander_bonus weight to score_card()
Commanders get +5.0 priority in AI spell selection, making the
AI prioritize casting its commander when affordable.
2026-03-17 03:38:14 +00:00
KoalaTrapLord 4bade21220 feat: route commander deaths to command zone instead of graveyard
Added _send_to_graveyard() helper that checks card.is_commander
and routes to command_zone (resetting tapped/turn_played) or
graveyard. Applied to all 4 death paths: removal, board wipe,
blocker death, and attacker death in combat.
2026-03-17 03:36:36 +00:00
KoalaTrapLord 46421fe8c4 feat: add commander casting from command zone with tax tracking
Second pass in _play_spells() checks command_zone for castable
commanders, applies commander_tax, taps lands, places on
battlefield, and increments tax by 2 for subsequent casts.
2026-03-17 03:34:25 +00:00
KoalaTrapLord da5e9bd74f feat: set is_commander during deck loading, place in command_zone
- Add commander_names param to run(), run_n(), _create_state()
- Commander card flagged is_commander=True and placed in
  player.command_zone instead of shuffled into library/hand
- Only first matching card is extracted (handles singleton rule)
- Backward compatible: commander_names defaults to None
2026-03-17 03:31:35 +00:00
KoalaTrapLord 019a710acd feat: add command_zone and commander_tax to Player dataclass
Adds command_zone (list[Card]) and commander_tax (int, +2 per cast)
to the base Player model so the headless engine can track commander
zone and tax natively without requiring CommanderPlayer wrappers.
2026-03-17 03:18:06 +00:00
KoalaTrapLord 08509b753f fix: add httpx and websockets to runtime dependencies (fixes #37)
Both were missing from [project.dependencies] in pyproject.toml and
requirements.txt. httpx is used in web/routers/art.py, and websockets
is needed for the FastAPI WebSocket endpoints in ws.py and lobby.py.

Closes #37
2026-03-17 02:04:09 +00:00
Commander AI Lab 872f6c38ca security: remove hardcoded API keys, add .env support (fixes #26)
- Remove plaintext Ximilar and Perplexity API keys from start-lab.bat
- Remove hardcoded key defaults from lab_api.py, lab_api_backup.py, lab_api_new.py
- start-lab.bat now reads from environment variables or .env file
- Add .env.example with placeholder values
- .env already in .gitignore (confirmed)
- Git history purged of all key values via git-filter-repo

Closes #26
2026-03-17 02:00:15 +00:00
KoalaTrapLord 9f7fbef7f8 fix: implement all 19 simulator audit bug fixes
Bug fixes across 7 Python files from the deep-dive audit:

engine.py (bugs 1-6):
- Fix summoning sickness (was disabled after turn 0)
- Move untap step before draw (correct MTG ordering)
- Rebuild playable list each iteration (fix mana overspend)
- Menace now allows 2+ blockers instead of preventing all
- Add double strike damage handling (blocked + unblocked)
- (Finish position sort already correct, no change needed)

game_state.py (bugs 7,9,18,19):
- Add .players property returning commander_players
- Add get_legal_moves()/apply_move() stubs
- Initialize commander zone in from_sim_state()
- Sync land_drop_used from engine stats

turn_manager.py (bugs 8,10,11):
- Use sim_state.get_battlefield() + card.tapped attr access
- Replace asyncio.get_event_loop() with get_running_loop()
- Fix APNAP iterations counter (always increment)
- Fix drawn.name and discarded.name (was dict .get())

threat_assessor.py (bugs 12,13,14):
- Use game_state.battlefield(seat) for card iteration
- Use Card dataclass attrs (c.type_line, c.oracle_text, etc)
- Move import re to module top level

models.py (bug 15):
- Word-boundary regex in has_keyword() (fixes reach/ward FPs)

prompt_builder.py (bug 16):
- Remove @staticmethod from module-level _category_label()

rules.py (bug 17):
- Evaluate ramp detection independently of is_removal flag
2026-03-16 20:50:09 +00:00
KoalaTrapLord 2f117eedcb fix: Java 17 compat - inline ternary in this() call instead of local var 2026-03-16 20:34:05 +00:00
KoalaTrapLord 8f8abb79c6 fix: match actual Forge verbose log format - cast/played/Life:/Zone Change: patterns 2026-03-16 20:25:35 +00:00
KoalaTrapLord 78898f6da0 fix: regex patterns match Forge verbose output, single-winner resolution, 300s clock for 4p 2026-03-16 17:34:12 +00:00
KoalaTrapLord 69242a8f6e fix: remove duplicate numPlayers declaration in parseForgeOutput 2026-03-16 17:13:48 +00:00
KoalaTrapLord 2b6ccac3ea fix: hardcoded 3-element arrays in BatchRunner causing empty stats for 4-player games 2026-03-16 17:09:57 +00:00
KoalaTrapLord 94bb369866 feat: add --deck4/--commander4 support for 4-player games in LabCli + BatchRunner 2026-03-16 02:28:06 +00:00
KoalaTrapLord b57fc9dc2f fix: add missing stdlib imports (threading, os, re, csv, io, datetime) across route modules 2026-03-16 01:55:17 +00:00
KoalaTrapLord e1f2b5d89f fix: add missing os import to collection.py 2026-03-16 01:53:17 +00:00
KoalaTrapLord 9b354e019b fix: add missing Path import to collection.py 2026-03-16 01:42:37 +00:00
KoalaTrapLord ac3b76793b fix: add missing Path, os, threading imports to routes/collection.py 2026-03-15 21:05:35 -04:00
KoalaTrapLord c60719a0a9 refactor: extract deckgen (14) + coach (12) routes
- routes/deckgen.py: classic generator, Perplexity V1, V3 generator + exports
  Helpers: _resolve_commander, _generate_deck, _build_collection_summary,
  _call_pplx_api, _fill_basic_lands, etc.
  Uses _coach._deck_gen_v3 via module reference for V3 state
- routes/coach.py: all coaching endpoints + init_coach_service(),
  _build_deck_report_from_db, globals (_coach_service, _deck_gen_v3, etc.)
- lab_api.py: 3265 -> 1063 lines (16 remaining: ML + SPA catch-all)
- Total: 90 extracted + 16 remaining = 106 endpoints verified
2026-03-15 07:26:09 +00:00
KoalaTrapLord 87a2090c68 refactor: extract scanner (6) + deepseek/sim (9) routes
- routes/scanner.py: scan, scan/add, re-enrich, auto-classify, auto-classify-all, edhrec
- routes/deepseek.py: sim/run, sim/status, sim/result, sim/run-from-deck,
  sim/run-deepseek, deepseek/connect, deepseek/status, deepseek/configure, deepseek/logs
- lab_api.py: 4464 -> 3265 lines (42 remaining endpoints)
- Total: 64 extracted + 42 remaining = 106 endpoints verified
2026-03-15 06:56:02 +00:00
KoalaTrapLord 463b7c1483 Phase 8: Full multiplayer — lobby, private hands, LAN discovery, spectator mode, chat 2026-03-14 23:04:32 -04:00
KoalaTrapLord a093ab4949 Phase 7: Integration tests, AI benchmarking suite, conftest, pytest config, coverage setup 2026-03-14 21:13:26 -04:00
KoalaTrapLord b6b1616dad Phase 6: AI politics engine (deal-making, threat comms, spite logic) + targeting memory 2026-03-14 20:42:48 -04:00
KoalaTrapLord 92bb9b9445 Phase 5: FastAPI server, WebSocket game channel, Scryfall art proxy, REST API, static web client, tests 2026-03-14 20:36:06 -04:00
KoalaTrapLord 3c3dceb737 Phase 4: Add Pygame prototype GUI (gui/ package + tests/test_phase4.py) 2026-03-14 20:10:43 -04:00
KoalaTrapLord 605ff774ed Phase 3: Add turn_manager.py, threat_assessor.py, tests/test_phase3.py 2026-03-14 19:35:50 -04:00
KoalaTrapLord 441ba7dd74 Phase 2: Add ai_opponent.py, personality_prompts.py, tests/test_phase2.py 2026-03-14 16:53:43 -04:00
KoalaTrapLord d0e2824038 Phase 1: Add game_state.py, prompt_builder.py, state_logger.py 2026-03-14 16:43:16 -04:00
KoalaTrapLord 8a6fbfaa8a fix: 3 post-refactor bugs (COMMANDER_META, PRECON_INDEX, startup)
Task 1: Move BUILTIN_COMMANDERS + load_commander_meta() to shared.py
        Fix import_routes.py to use _shared.COMMANDER_META (module ref)
Task 2: Rewrite precon.py to use _shared.PRECON_INDEX (module ref)
Task 3: Add @app.on_event('startup') safety net for uvicorn --reload
2026-03-14 19:08:21 +00:00
KoalaTrapLord 36077c94ab refactor: extract 49 endpoints into 5 route modules
- Extract collection (10), deckbuilder (18), precon (4), import (5), lab (12) routes
- All share helpers/models/state from routes/shared.py
- Gut lab_api.py from 8872 to 4487 lines (57 remaining endpoints)
- Delete routes/_wire.py and routes/_autoload.py (replaced by include_router)
- Add _scryfall_fuzzy_lookup to shared.py
- 106 total endpoints verified: 49 extracted + 57 remaining
2026-03-14 18:55:32 +00:00