diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl index aa6337e..1662a1a 100644 --- a/.beads/issues.jsonl +++ b/.beads/issues.jsonl @@ -4,8 +4,8 @@ {"_type":"issue","id":"alphago-xdh","title":"Add Go (7x7) game with ko, suicide, area scoring","description":"Marquee game: pass action (action_size=size^2+1), capture via flood-fill, no-suicide rule, simple single-point ko, two-pass termination, Tromp-Taylor area scoring with half-integer komi (decisive). Configurable size (default 7) + komi. Registered via central registry. Tests cover captures, suicide vs capturing-suicide, ko ban + clear, scoring/komi.","status":"closed","priority":2,"issue_type":"task","owner":"charles@weill.dev","created_at":"2026-05-26T19:06:51Z","created_by":"Charles Weill","updated_at":"2026-05-26T19:07:44Z","started_at":"2026-05-26T19:06:52Z","closed_at":"2026-05-26T19:07:44Z","close_reason":"Go merged in #16","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"alphago-to6","title":"Add Gomoku (five-in-a-row) game","description":"New game module exercising the game-agnostic pipeline: placement game (no gravity), configurable board size/connect (default 9x9 connect-5), registered via the central registry. Adds tests for win directions, connect-5 non-win at 4, tiny-board draw, canonical encoding, validation.","status":"closed","priority":2,"issue_type":"task","owner":"charles@weill.dev","created_at":"2026-05-26T18:53:03Z","created_by":"Charles Weill","updated_at":"2026-05-26T18:54:20Z","started_at":"2026-05-26T18:53:03Z","closed_at":"2026-05-26T18:54:20Z","close_reason":"Gomoku merged in #15","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"alphago-sq0","title":"Centralize game registry (single GAMES table)","description":"Game-name-\u003eGame lookup was duplicated in benchmark.py, play.py, arena.py (each with its own _game_from_name + hardcoded argparse choices). Centralize into alphazero/games/__init__.py (GAMES, game_from_name, GAME_CHOICES) so adding a game is one entry. Unblocks Gomoku/Go without 4-file edits.","status":"closed","priority":2,"issue_type":"task","owner":"charles@weill.dev","created_at":"2026-05-26T18:37:28Z","created_by":"Charles Weill","updated_at":"2026-05-26T18:45:31Z","started_at":"2026-05-26T18:37:28Z","closed_at":"2026-05-26T18:45:31Z","close_reason":"Central registry merged in #13","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"alphago-0oz","title":"Wire batched MCTS into training self-play (currently sequential)","description":"Batched/leaf-parallel MCTS (#9, 2.76-4.18x in benchmark) is only reachable via benchmark.py --mcts-batch-size. Training self-play builds self_play_mcts_cfg={num_simulations,dirichlet_eps} (arena.py:974), so MCTS uses default batch_size=1 (mcts.py:70) -\u003e sequential. wandb config for the 5 C4 runs confirms no batch key. Add a self-play MCTS batch-size knob threaded into self_play_mcts_cfg + the Modal entrypoint so the speedup applies to real training (~0.4 -\u003e ~1.1-1.7 self-play games/sec expected).","status":"in_progress","priority":2,"issue_type":"task","owner":"charles@weill.dev","created_at":"2026-05-26T18:12:28Z","created_by":"Charles Weill","updated_at":"2026-05-26T19:41:04Z","started_at":"2026-05-26T19:41:04Z","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"alphago-geq","title":"Add Modal smoke test to CI","description":"CI (.github/workflows/ci.yml) has no modal coverage, which is why #7 silently deleting modal_app.py went unnoticed. Add a lightweight check (import/app-definition assertion, or a 1-iteration modal run smoke) so a broken or missing Modal entrypoint fails CI.","status":"open","priority":2,"issue_type":"task","owner":"charles@weill.dev","created_at":"2026-05-26T18:12:28Z","created_by":"Charles Weill","updated_at":"2026-05-26T18:12:28Z","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"alphago-0oz","title":"Wire batched MCTS into training self-play (currently sequential)","description":"Batched/leaf-parallel MCTS (#9, 2.76-4.18x in benchmark) is only reachable via benchmark.py --mcts-batch-size. Training self-play builds self_play_mcts_cfg={num_simulations,dirichlet_eps} (arena.py:974), so MCTS uses default batch_size=1 (mcts.py:70) -\u003e sequential. wandb config for the 5 C4 runs confirms no batch key. Add a self-play MCTS batch-size knob threaded into self_play_mcts_cfg + the Modal entrypoint so the speedup applies to real training (~0.4 -\u003e ~1.1-1.7 self-play games/sec expected).","status":"closed","priority":2,"issue_type":"task","owner":"charles@weill.dev","created_at":"2026-05-26T18:12:28Z","created_by":"Charles Weill","updated_at":"2026-05-26T19:41:48Z","started_at":"2026-05-26T19:41:04Z","closed_at":"2026-05-26T19:41:48Z","close_reason":"Batched MCTS wired into training self-play; merged in #17","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"alphago-geq","title":"Add Modal smoke test to CI","description":"CI (.github/workflows/ci.yml) has no modal coverage, which is why #7 silently deleting modal_app.py went unnoticed. Add a lightweight check (import/app-definition assertion, or a 1-iteration modal run smoke) so a broken or missing Modal entrypoint fails CI.","status":"in_progress","priority":2,"issue_type":"task","owner":"charles@weill.dev","created_at":"2026-05-26T18:12:28Z","created_by":"Charles Weill","updated_at":"2026-05-26T19:45:23Z","started_at":"2026-05-26T19:45:23Z","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"alphago-1sg","title":"Add CI (GitHub Actions: uv sync + pytest + ubs on PRs)","description":"No CI exists; tests and ubs are run by hand. Add a GitHub Actions workflow that runs uv sync --extra dev, uv run pytest, and ubs on PRs/pushes to catch regressions. NOTE: get explicit approval for any step that downloads+executes binaries (per AGENTS.md); pin action versions to SHAs.","status":"closed","priority":2,"issue_type":"feature","assignee":"Charles Weill","owner":"charles@weill.dev","created_at":"2026-05-26T06:10:02Z","created_by":"Charles Weill","updated_at":"2026-05-26T07:25:05Z","started_at":"2026-05-26T06:22:21Z","closed_at":"2026-05-26T07:25:05Z","close_reason":"Merged to main (#9/#10)","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"alphago-7ck","title":"Implement batched / leaf-parallel MCTS","description":"MCTS currently does sequential single-position network inference, which is the throughput bottleneck and the reason GPU does not help. Implement batched/leaf-parallel MCTS (collect leaves, evaluate the network in a batch) and/or vectorized parallel self-play. Measured by the benchmark bead alphago-bqz; this implements the speedup.","status":"closed","priority":2,"issue_type":"feature","assignee":"Charles Weill","owner":"charles@weill.dev","created_at":"2026-05-26T06:10:02Z","created_by":"Charles Weill","updated_at":"2026-05-26T07:25:05Z","started_at":"2026-05-26T06:22:20Z","closed_at":"2026-05-26T07:25:05Z","close_reason":"Merged to main (#9/#10)","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"alphago-8ud","title":"Diagnose/fix Agent Mail MCP for ntm workers","description":"Every ntm worker this session failed to start mcp_agent_mail (HTTP handshake to 127.0.0.1 failed), so workers had no lease-based file-reservation coordination (we worked around it with disjoint files + central commits). Diagnose and fix so multi-agent file leasing works -- important before scaling parallel worktree rounds.","status":"closed","priority":2,"issue_type":"task","assignee":"Charles Weill","owner":"charles@weill.dev","created_at":"2026-05-26T06:10:02Z","created_by":"Charles Weill","updated_at":"2026-05-26T07:25:06Z","started_at":"2026-05-26T06:22:21Z","closed_at":"2026-05-26T07:25:06Z","close_reason":"Merged to main (#9/#10)","dependency_count":0,"dependent_count":0,"comment_count":0} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 77fcb70..2771bd3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,6 +32,9 @@ jobs: - name: Run tests run: uv run pytest + - name: Modal entrypoint smoke (real modal, no cloud build) + run: uv run --extra modal pytest tests/test_modal_app.py -q + - name: Run UBS if available shell: bash run: | diff --git a/tests/test_modal_app.py b/tests/test_modal_app.py index d1374b9..5a89199 100644 --- a/tests/test_modal_app.py +++ b/tests/test_modal_app.py @@ -113,6 +113,23 @@ def from_name(name: str) -> SimpleNamespace: assert module.app.entrypoint.__defaults__[:4] == ("tictactoe", None, None, None) +def test_modal_app_constructs_with_real_modal() -> None: + # Smoke test against the real modal package (skipped when it isn't + # installed). Guards the #7-style regression where modal_app.py was emptied: + # the fake-modal tests above cannot catch a broken real-modal app/image. + pytest.importorskip("modal") + + module = load_modal_app() + + assert module.app is not None, "modal_app.app is None — entrypoint missing" + assert module.app.name == "alphazero" + assert module.image is not None, "modal_app.image is None" + # Under real modal these are wrapped objects (a Function / local entrypoint), + # not plain callables; their existence proves the app was constructed. + assert module.train_remote is not None + assert module.main is not None + + def test_modal_app_game_defaults_are_game_specific(monkeypatch) -> None: real_import = builtins.__import__