diff --git a/README.md b/README.md index cf867207..fea15b1f 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ codeclash run configs/test/battlesnake.yaml Once this works, you should be set up to run a real tournament! To run *Claude Sonnet 4.5* against *o3* in a *BattleSnake* tournament with *5 rounds* and *1000 competition simulations* per round, run: ```bash -uv run codeclash run configs/examples/BattleSnake__claude-sonnet-4-5-20250929__o3__r5__s1000.yaml +uv run codeclash run configs/pvp/BattleSnake__claude-sonnet-4-5-20250929__o3__r15__s1000.yaml ``` ## ⚔️ How It Works diff --git a/codeclash/agents/mini_anthropic_model.py b/codeclash/agents/mini_anthropic_model.py index 9e6432f9..554fa984 100644 --- a/codeclash/agents/mini_anthropic_model.py +++ b/codeclash/agents/mini_anthropic_model.py @@ -11,7 +11,7 @@ `model_class: codeclash.agents.mini_anthropic_model.AnthropicModel` and provide the API key, base URL, and model name (see the `*_env` config fields, which keep endpoint-specific values in the environment rather than in committed configs). Requires the optional `anthropic` dependency -(`uv pip install -e '.[llama]'`). See configs/ablations/ladder/robotrumble_llama.yaml. +(`uv pip install -e '.[llama]'`). See configs/ladder/robotrumble_llama.yaml. """ import json diff --git a/codeclash/agents/utils.py b/codeclash/agents/utils.py index 81c2c9dd..2f2aef7a 100644 --- a/codeclash/agents/utils.py +++ b/codeclash/agents/utils.py @@ -26,6 +26,7 @@ class GameContext(BaseModel): round: int rounds: int working_dir: str + arena_description: str = "" def _render_prompt_templates(self) -> dict: context = self.model_dump() diff --git a/codeclash/analysis/code_evolve/main.py b/codeclash/analysis/code_evolve/main.py index b749acd2..5504e389 100644 --- a/codeclash/analysis/code_evolve/main.py +++ b/codeclash/analysis/code_evolve/main.py @@ -18,7 +18,7 @@ from codeclash.arenas import ARENAS from codeclash.constants import LOCAL_LOG_DIR -MODELS_PATH = Path("configs/models.yaml") +MODELS_PATH = Path("configs/mini/model_roster.yaml") TARGET_ROUNDS = [1, 15, 5, 10] diff --git a/codeclash/arenas/arena.py b/codeclash/arenas/arena.py index 5076a9f9..174cee17 100644 --- a/codeclash/arenas/arena.py +++ b/codeclash/arenas/arena.py @@ -2,6 +2,7 @@ import os import random import subprocess +import threading import time from abc import ABC, abstractmethod from pathlib import Path @@ -75,6 +76,10 @@ class CodeArena(ABC): default_args: dict = {} submission: str + # Serializes image builds across concurrent pairs (e.g. `ladder make --workers N`), so + # worker threads don't all race `docker build` on a cold start and fail with "already exists". + _build_lock = threading.Lock() + def __init__(self, config: dict, *, tournament_id: str, local_output_dir: Path, keep_containers: bool = False): """The CodeArena class is responsible for running games, i.e., taking a list of code from different agents/players and running them against each other. @@ -127,36 +132,38 @@ def build_image(self): if is_running_in_aws_batch(): pull_game_container_aws_ecr(game_name=self.name, image_name=self.image_name, logger=self.logger) - # Check if container exists using subprocess - self.logger.debug(f"Checking if container {self.image_name} exists") - result = subprocess.run( - f"docker images -q {self.image_name}", - shell=True, - capture_output=True, - text=True, - ) - if result.stdout.strip(): - self.logger.debug(f"Container {self.image_name} exists") - return + # Hold the lock across check-and-build so concurrent pairs don't race: the first thread + # builds while the rest wait, then find the image already present and skip. + with CodeArena._build_lock: + self.logger.debug(f"Checking if container {self.image_name} exists") + result = subprocess.run( + f"docker images -q {self.image_name}", + shell=True, + capture_output=True, + text=True, + ) + if result.stdout.strip(): + self.logger.debug(f"Container {self.image_name} exists") + return - self.logger.info( - f"Building Docker image {self.image_name}. This may take 1-5 minutes and only work on Linux for some games." - ) + self.logger.info( + f"Building Docker image {self.image_name}. This may take 1-5 minutes and only work on Linux for some games." + ) - # NOTE: Assuming Dockerfile is declared in same directory as the arena. - arena_file = Path(inspect.getfile(self.__class__)) - folder_path = arena_file.parent - result = subprocess.run( - f"docker build --no-cache -t {self.image_name} -f {folder_path}/{self.name}.Dockerfile .", - shell=True, - capture_output=True, - text=True, - ) - if result.returncode == 0: - self.logger.info(f"✅ Built Docker image {self.image_name}") - else: - self.logger.error(f"❌ Failed to build Docker image: {result.stderr}\n{result.stdout}{result.stderr}") - raise RuntimeError(f"Failed to build Docker image: {result.stderr}") + # NOTE: Assuming Dockerfile is declared in same directory as the arena. + arena_file = Path(inspect.getfile(self.__class__)) + folder_path = arena_file.parent + result = subprocess.run( + f"docker build --no-cache -t {self.image_name} -f {folder_path}/{self.name}.Dockerfile .", + shell=True, + capture_output=True, + text=True, + ) + if result.returncode == 0: + self.logger.info(f"✅ Built Docker image {self.image_name}") + else: + self.logger.error(f"❌ Failed to build Docker image: {result.stderr}\n{result.stdout}{result.stderr}") + raise RuntimeError(f"Failed to build Docker image: {result.stderr}") def copy_logs_from_env(self, round_num: int) -> None: """Copy logs from the game's environment to the local machine.""" diff --git a/codeclash/arenas/battlesnake/battlesnake.py b/codeclash/arenas/battlesnake/battlesnake.py index 36639ec6..6f6eece3 100644 --- a/codeclash/arenas/battlesnake/battlesnake.py +++ b/codeclash/arenas/battlesnake/battlesnake.py @@ -203,4 +203,9 @@ def validate_code(self, agent: Player) -> tuple[bool, str | None]: error_msg.append(f"There should be a `{func}` function implemented in `{self.submission}`") if len(error_msg) > 0: return False, "\n".join(error_msg + ["Don't change the function signatures!"]) + if "__main__" not in bot_content: + return False, ( + f'`{self.submission}` must keep its `if __name__ == "__main__"` block that starts ' + "the server, or the bot fails to launch." + ) return True, None diff --git a/codeclash/cli/ladder.py b/codeclash/cli/ladder.py index 040505ea..e4807827 100644 --- a/codeclash/cli/ladder.py +++ b/codeclash/cli/ladder.py @@ -2,6 +2,7 @@ import copy import getpass +import json import time from concurrent.futures import ThreadPoolExecutor, as_completed from pathlib import Path @@ -18,43 +19,53 @@ logger = get_logger("ladder") -def _resolve_ladder_rules(ladder_rules: dict, rounds: int) -> tuple[float, int]: - """Validate the optional ``ladder_rules`` block and return ``(min_round_win_fraction, win_last_k)``. +def _resolve_ladder_rules(ladder_rules: dict, rounds: int) -> tuple[int, int]: + """Validate the required ``ladder_rules`` block and return ``(min_round_wins, win_last_k)``. - Defaults: win at least ``min_round_win_fraction`` (0.4) of the *agent* rounds AND win the last - ``win_last_k`` (1) round(s). The baseline round 0 (identical, un-edited codebases) is excluded - from this count — it reflects game variance, not the agent — so the fraction is taken over the - ``rounds`` rounds the agent actually edits. + Both keys must be specified explicitly in the config (no defaults): + - ``min_round_wins``: the whole number of *agent* rounds the player must win to advance + (a ``>=`` threshold). Must be ``1 <= min_round_wins <= rounds``. + - ``win_last_k``: the player must win the last ``win_last_k`` round(s). ``1`` means just the final + round; ``0`` disables the trailing-rounds requirement entirely. Must be ``<= min_round_wins``. + + The baseline round 0 (identical, un-edited codebases) is excluded from the count — it reflects + game variance, not the agent — so wins are counted over the ``rounds`` rounds the agent actually + edits (rounds 1..``rounds``). """ - min_round_win_fraction = ladder_rules.get("min_round_win_fraction", 0.4) - win_last_k = ladder_rules.get("win_last_k", 1) + if "min_round_wins" not in ladder_rules: + typer.echo("ladder_rules.min_round_wins is required; specify it explicitly in the config.") + raise typer.Exit(1) + if "win_last_k" not in ladder_rules: + typer.echo("ladder_rules.win_last_k is required; specify it explicitly in the config.") + raise typer.Exit(1) + min_round_wins = ladder_rules["min_round_wins"] + win_last_k = ladder_rules["win_last_k"] + + # min_round_wins: whole number of agent rounds the player must win (round 0 excluded). + if isinstance(min_round_wins, bool) or not isinstance(min_round_wins, int): + typer.echo(f"ladder_rules.min_round_wins must be an integer, got {min_round_wins!r}.") + raise typer.Exit(1) + if not 1 <= min_round_wins <= rounds: + typer.echo(f"ladder_rules.min_round_wins must be in [1, {rounds}] (tournament.rounds), got {min_round_wins}.") + raise typer.Exit(1) - # win_last_k: number of trailing rounds the player must win (1 == just the final round). + # win_last_k: number of trailing rounds the player must win (1 == just the final round, 0 == disabled). if isinstance(win_last_k, bool) or not isinstance(win_last_k, int): typer.echo(f"ladder_rules.win_last_k must be an integer, got {win_last_k!r}.") raise typer.Exit(1) - if win_last_k < 1: + if win_last_k < 0: typer.echo( - f"ladder_rules.win_last_k must be >= 1, got {win_last_k}. Use 1 to require winning only the final round." + f"ladder_rules.win_last_k must be >= 0, got {win_last_k}. " + "Use 0 to disable the trailing-rounds requirement, or 1 to require winning only the final round." ) raise typer.Exit(1) - if win_last_k > rounds: - typer.echo(f"ladder_rules.win_last_k ({win_last_k}) cannot exceed tournament.rounds ({rounds}).") - raise typer.Exit(1) - - # min_round_win_fraction: player must win >= this fraction of the agent rounds (round 0 excluded). - if isinstance(min_round_win_fraction, bool) or not isinstance(min_round_win_fraction, (int, float)): - typer.echo(f"ladder_rules.min_round_win_fraction must be a number, got {min_round_win_fraction!r}.") - raise typer.Exit(1) - if not 0 <= min_round_win_fraction <= 1: + if win_last_k > min_round_wins: typer.echo( - f"ladder_rules.min_round_win_fraction must be in [0, 1], got {min_round_win_fraction}. " - "The player must win >= this fraction of the agent rounds; 1 requires winning all of them, " - "0 drops the fraction requirement." + f"ladder_rules.win_last_k ({win_last_k}) cannot exceed ladder_rules.min_round_wins ({min_round_wins})." ) raise typer.Exit(1) - return float(min_round_win_fraction), win_last_k + return min_round_wins, win_last_k ladder_app = typer.Typer( @@ -74,7 +85,7 @@ def make( ): """Build a ladder: run PvP tournaments across all pairs of players (for ranking). - [dim]• codeclash ladder make configs/ablations/ladder/make_battlesnake.yaml[/dim] + [dim]• codeclash ladder make configs/ladder/make_battlesnake.yaml[/dim] """ yaml_content = config_path.read_text() preprocessed_yaml = resolve_includes(yaml_content, base_dir=CONFIG_DIR) @@ -141,20 +152,25 @@ def run( config["tournament"]["rounds"], config["game"]["sims_per_round"], ) - min_round_win_fraction, win_last_k = _resolve_ladder_rules(config.get("ladder_rules", {}), rounds) + min_round_wins, win_last_k = _resolve_ladder_rules(config.get("ladder_rules", {}), rounds) timestamp = time.strftime("%y%m%d%H%M%S") del config["player"] del config["ladder"] config.pop("ladder_rules", None) - print( - f"Ladder advancement rule: win >= {min_round_win_fraction:.0%} of {rounds} agent rounds " - f"(baseline round 0 excluded) and win the last {win_last_k} round(s)." + last_k_rule = "disabled" if win_last_k == 0 else f"win the last {win_last_k} round(s)" + advancement_rule = ( + f"Ladder advancement rule: win >= {min_round_wins} of {rounds} agent rounds " + f"(baseline round 0 excluded) and {last_k_rule}." ) + print(advancement_rule) + logger.info(advancement_rule) ladder_folder = f"LadderTournament.{config['game']['name']}.r{rounds}.s{sims}.{player['name']}.{timestamp}" player["branch"] = ladder_folder parent_dir = LOCAL_LOG_DIR / getpass.getuser() / ladder_folder + rungs_cleared = 0 + advanced = False for idx, opponent in enumerate(ladder): opponent_rank = len(ladder) - idx opponent["name"] = opponent["branch_init"].replace("human/", "").replace("/", "_") @@ -190,24 +206,37 @@ def run( metadata = yaml.safe_load(f) round_winners = [r["winner"] for k, r in metadata["round_stats"].items() if int(k) != 0] - # Advancement rule (configurable via `ladder_rules`): win at least - # `min_round_win_fraction` of the agent rounds AND win the last `win_last_k` rounds. + # Advancement rule (required via `ladder_rules`): win at least `min_round_wins` of the + # agent rounds AND win the last `win_last_k` rounds. win_last_k == 0 disables the + # trailing-rounds requirement. player_wins = sum(1 for w in round_winners if w == player["name"]) - won_majority = player_wins >= len(round_winners) * min_round_win_fraction - won_last_k = all(w == player["name"] for w in round_winners[-win_last_k:]) + won_majority = player_wins >= min_round_wins + won_last_k = win_last_k == 0 or all(w == player["name"] for w in round_winners[-win_last_k:]) + advanced = won_majority and won_last_k - if not won_majority or not won_last_k: + # Record this rung's outcome in its metadata.json (durable gameplay log). The rule itself + # (min_round_wins, win_last_k) is constant across the run and lives in the ladder summary. + metadata["ladder_advancement"] = { + "player_wins": player_wins, + "won_last_k": won_last_k, + "cleared": advanced, + } + with open(metadata_path, "w") as f: + json.dump(metadata, f, indent=2) + + if not advanced: # Player failed the advancement rule; the ladder challenge ends here. print("=" * 10) print( f"{player['name']} did not clear {opponent['name']} " f"(rank {opponent_rank}/{len(ladder)}): won {player_wins}/{len(round_winners)} agent rounds " - f"(needed >= {min_round_win_fraction:.0%}), last {win_last_k} round(s) won: {won_last_k}.\n" + f"(needed >= {min_round_wins}), last {win_last_k} round(s) won: {won_last_k}.\n" "Ladder challenge ends." ) print("=" * 10) break + rungs_cleared += 1 print("=" * 10) print( f"{player['name']} successfully beat {opponent['name']} (rank {opponent_rank}/{len(ladder)}) " @@ -216,5 +245,22 @@ def run( ) print("=" * 10) + # Persist the overall climb result to a ladder-level metadata.json in the run's parent dir. + ladder_summary = { + "player": player["name"], + "game": config["game"]["name"], + "rounds": rounds, + "min_round_wins": min_round_wins, + "win_last_k": win_last_k, + "ladder_size": len(ladder), + "rungs_cleared": rungs_cleared, + "final_opponent": opponent["name"], + "final_opponent_rank": opponent_rank, + "cleared_ladder": rungs_cleared == len(ladder), + } + parent_dir.mkdir(parents=True, exist_ok=True) + with open(parent_dir / "metadata.json", "w") as f: + json.dump(ladder_summary, f, indent=2) + print(f"Ladder tournament complete. Logs saved to {parent_dir}") print(f"Final opponent faced: {opponent['name']} (rank {opponent_rank}/{len(ladder)} in ladder)") diff --git a/codeclash/tournaments/pvp.py b/codeclash/tournaments/pvp.py index 65c4e1d0..e8274c72 100644 --- a/codeclash/tournaments/pvp.py +++ b/codeclash/tournaments/pvp.py @@ -79,6 +79,7 @@ def get_agent(self, agent_config: dict, prompts: dict) -> Player: round=1, rounds=self.rounds, working_dir=str(DIR_WORK), + arena_description=self.game.description, ) return get_agent(agent_config, game_context, environment) diff --git a/codeclash/utils/generate_confs.py b/codeclash/utils/generate_confs.py index 6cc2b109..3fb9544c 100644 --- a/codeclash/utils/generate_confs.py +++ b/codeclash/utils/generate_confs.py @@ -3,14 +3,14 @@ Each configuration file specifies a tournament between two models in a given arena, including the number of rounds and simulations per round. The configurations are saved -as YAML files in the specified output directory (default: configs/main/). +as YAML files in the specified output directory (default: configs/pvp/). Also generates a tracking JSON file at configs/tracker.json to keep track of the number of tournaments and rounds played for each pair of models in each arena. Usage: -python codeclash/utils/generate_confs.py -m configs/models.yaml -r 15 -s 1000 +python codeclash/utils/generate_confs.py -m configs/mini/model_roster.yaml -r 15 -s 1000 """ import argparse @@ -184,7 +184,7 @@ def main(models, arenas, rounds: int, simulations: int, record_ratio: float, out "-m", "--models", type=str, - default="configs/models.yaml", + default="configs/mini/model_roster.yaml", help="Path to model configurations.", ) parser.add_argument( @@ -218,7 +218,7 @@ def main(models, arenas, rounds: int, simulations: int, record_ratio: float, out "-o", "--output", type=Path, - default=Path("configs/main/"), + default=Path("configs/pvp/"), help="Output directory for configuration files (default: main/).", ) args = parser.parse_args() diff --git a/codeclash/viewer/static/js/picker.js b/codeclash/viewer/static/js/picker.js index 25ada9bc..1aaff0c5 100644 --- a/codeclash/viewer/static/js/picker.js +++ b/codeclash/viewer/static/js/picker.js @@ -503,7 +503,7 @@ async function fillTextareaWithAWSSubmitCommands() { // Format output as AWS submit commands const commands = successfulResults.map( (result) => - `aws/run_job.py -- aws/docker_and_sync.sh codeclash run configs/main/${result.config_name}`, + `aws/run_job.py -- aws/docker_and_sync.sh codeclash run configs/pvp/${result.config_name}`, ); textarea.value = commands.join("\n"); diff --git a/configs/ablations/ladder/corewar__gemini_3_5_flash.yaml b/configs/ablations/ladder/corewar__gemini_3_5_flash.yaml deleted file mode 100644 index ef5f1220..00000000 --- a/configs/ablations/ladder/corewar__gemini_3_5_flash.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# CoreWar ladder climbed by gemini-3-5-flash. Requires LLAMA_API_KEY in .env. -# uv run codeclash ladder run configs/ablations/ladder/corewar__gemini_3_5_flash.yaml -tournament: - rounds: 5 -ladder_rules: - min_round_win_fraction: 0.5 # advance only on a strict majority of rounds - win_last_k: 1 # ...and win the last K rounds (K=1 == just the final round) -game: - name: CoreWar - sims_per_round: 2000 -player: - agent: mini - name: gemini-3-5-flash - branch_init: human/pspace - config: - agent: !include mini/default.yaml - model: !include mini/models/llama_gemini_3_5_flash.yaml - push: True -prompts: - game_description: |- - Core War ladder -ladder: !include ablations/ladder/rungs/corewar.yaml diff --git a/configs/ablations/ladder/corewar__gpt_5_5.yaml b/configs/ablations/ladder/corewar__gpt_5_5.yaml deleted file mode 100644 index ee3c5186..00000000 --- a/configs/ablations/ladder/corewar__gpt_5_5.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# CoreWar ladder climbed by gpt-5-5. Requires LLAMA_API_KEY in .env. -# uv run codeclash ladder run configs/ablations/ladder/corewar__gpt_5_5.yaml -tournament: - rounds: 5 -ladder_rules: - min_round_win_fraction: 0.5 # advance only on a strict majority of rounds - win_last_k: 1 # ...and win the last K rounds (K=1 == just the final round) -game: - name: CoreWar - sims_per_round: 2000 -player: - agent: mini - name: gpt-5-5 - branch_init: human/pspace - config: - agent: !include mini/default.yaml - model: !include mini/models/llama_gpt_5_5.yaml - push: True -prompts: - game_description: |- - Core War ladder -ladder: !include ablations/ladder/rungs/corewar.yaml diff --git a/configs/ablations/ladder/corewar__opus_4_7.yaml b/configs/ablations/ladder/corewar__opus_4_7.yaml deleted file mode 100644 index a3991526..00000000 --- a/configs/ablations/ladder/corewar__opus_4_7.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# CoreWar ladder climbed by opus-4-7. Requires LLAMA_API_KEY in .env. -# uv run codeclash ladder run configs/ablations/ladder/corewar__opus_4_7.yaml -tournament: - rounds: 5 -ladder_rules: - min_round_win_fraction: 0.5 # advance only on a strict majority of rounds - win_last_k: 1 # ...and win the last K rounds (K=1 == just the final round) -game: - name: CoreWar - sims_per_round: 2000 -player: - agent: mini - name: opus-4-7 - branch_init: human/pspace - config: - agent: !include mini/default.yaml - model: !include mini/models/llama_opus_4_7.yaml - push: True -prompts: - game_description: |- - Core War ladder -ladder: !include ablations/ladder/rungs/corewar.yaml diff --git a/configs/ablations/ladder/corewar__opus_4_8.yaml b/configs/ablations/ladder/corewar__opus_4_8.yaml deleted file mode 100644 index dc0ef353..00000000 --- a/configs/ablations/ladder/corewar__opus_4_8.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# CoreWar ladder climbed by opus-4-8. Requires LLAMA_API_KEY in .env. -# uv run codeclash ladder run configs/ablations/ladder/corewar__opus_4_8.yaml -tournament: - rounds: 5 -ladder_rules: - min_round_win_fraction: 0.5 # advance only on a strict majority of rounds - win_last_k: 1 # ...and win the last K rounds (K=1 == just the final round) -game: - name: CoreWar - sims_per_round: 2000 -player: - agent: mini - name: opus-4-8 - branch_init: human/pspace - config: - agent: !include mini/default.yaml - model: !include mini/models/llama_opus_4_8.yaml - push: True -prompts: - game_description: |- - Core War ladder -ladder: !include ablations/ladder/rungs/corewar.yaml diff --git a/configs/ablations/ladder/corewar__sonnet_5.yaml b/configs/ablations/ladder/corewar__sonnet_5.yaml deleted file mode 100644 index a429c6b5..00000000 --- a/configs/ablations/ladder/corewar__sonnet_5.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# CoreWar ladder climbed by sonnet-5. Requires LLAMA_API_KEY in .env. -# uv run codeclash ladder run configs/ablations/ladder/corewar__sonnet_5.yaml -tournament: - rounds: 5 -ladder_rules: - min_round_win_fraction: 0.5 # advance only on a strict majority of rounds - win_last_k: 1 # ...and win the last K rounds (K=1 == just the final round) -game: - name: CoreWar - sims_per_round: 2000 -player: - agent: mini - name: sonnet-5 - branch_init: human/pspace - config: - agent: !include mini/default.yaml - model: !include mini/models/llama_sonnet_5.yaml - push: True -prompts: - game_description: |- - Core War ladder -ladder: !include ablations/ladder/rungs/corewar.yaml diff --git a/configs/ablations/ladder/robotrumble__gemini_3_5_flash.yaml b/configs/ablations/ladder/robotrumble__gemini_3_5_flash.yaml deleted file mode 100644 index 673edb08..00000000 --- a/configs/ablations/ladder/robotrumble__gemini_3_5_flash.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# RobotRumble ladder climbed by gemini-3-5-flash. Requires LLAMA_API_KEY in .env. -# uv run codeclash ladder run configs/ablations/ladder/robotrumble__gemini_3_5_flash.yaml -tournament: - rounds: 5 -ladder_rules: - min_round_win_fraction: 0.5 # advance only on a strict majority of rounds - win_last_k: 1 # ...and win the last K rounds (K=1 == just the final round) -game: - name: RobotRumble - sims_per_round: 250 - args: - raw: false -player: - agent: mini - name: gemini-3-5-flash - branch_init: human/anton/anton3000 - config: - agent: !include mini/default.yaml - model: !include mini/models/llama_gemini_3_5_flash.yaml - push: True -prompts: - game_description: |- - RobotRumble ladder -ladder: !include ablations/ladder/rungs/robotrumble.yaml diff --git a/configs/ablations/ladder/robotrumble__gpt_5_5.yaml b/configs/ablations/ladder/robotrumble__gpt_5_5.yaml deleted file mode 100644 index cb0e0eb5..00000000 --- a/configs/ablations/ladder/robotrumble__gpt_5_5.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# RobotRumble ladder climbed by gpt-5-5. Requires LLAMA_API_KEY in .env. -# uv run codeclash ladder run configs/ablations/ladder/robotrumble__gpt_5_5.yaml -tournament: - rounds: 5 -ladder_rules: - min_round_win_fraction: 0.5 # advance only on a strict majority of rounds - win_last_k: 1 # ...and win the last K rounds (K=1 == just the final round) -game: - name: RobotRumble - sims_per_round: 250 - args: - raw: false -player: - agent: mini - name: gpt-5-5 - branch_init: human/anton/anton3000 - config: - agent: !include mini/default.yaml - model: !include mini/models/llama_gpt_5_5.yaml - push: True -prompts: - game_description: |- - RobotRumble ladder -ladder: !include ablations/ladder/rungs/robotrumble.yaml diff --git a/configs/ablations/ladder/robotrumble__opus_4_7.yaml b/configs/ablations/ladder/robotrumble__opus_4_7.yaml deleted file mode 100644 index 54e73ba6..00000000 --- a/configs/ablations/ladder/robotrumble__opus_4_7.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# RobotRumble ladder climbed by opus-4-7. Requires LLAMA_API_KEY in .env. -# uv run codeclash ladder run configs/ablations/ladder/robotrumble__opus_4_7.yaml -tournament: - rounds: 5 -ladder_rules: - min_round_win_fraction: 0.5 # advance only on a strict majority of rounds - win_last_k: 1 # ...and win the last K rounds (K=1 == just the final round) -game: - name: RobotRumble - sims_per_round: 250 - args: - raw: false -player: - agent: mini - name: opus-4-7 - branch_init: human/anton/anton3000 - config: - agent: !include mini/default.yaml - model: !include mini/models/llama_opus_4_7.yaml - push: True -prompts: - game_description: |- - RobotRumble ladder -ladder: !include ablations/ladder/rungs/robotrumble.yaml diff --git a/configs/ablations/ladder/robotrumble__opus_4_8.yaml b/configs/ablations/ladder/robotrumble__opus_4_8.yaml deleted file mode 100644 index 83a49437..00000000 --- a/configs/ablations/ladder/robotrumble__opus_4_8.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# RobotRumble ladder climbed by opus-4-8. Requires LLAMA_API_KEY in .env. -# uv run codeclash ladder run configs/ablations/ladder/robotrumble__opus_4_8.yaml -tournament: - rounds: 5 -ladder_rules: - min_round_win_fraction: 0.5 # advance only on a strict majority of rounds - win_last_k: 1 # ...and win the last K rounds (K=1 == just the final round) -game: - name: RobotRumble - sims_per_round: 250 - args: - raw: false -player: - agent: mini - name: opus-4-8 - branch_init: human/anton/anton3000 - config: - agent: !include mini/default.yaml - model: !include mini/models/llama_opus_4_8.yaml - push: True -prompts: - game_description: |- - RobotRumble ladder -ladder: !include ablations/ladder/rungs/robotrumble.yaml diff --git a/configs/ablations/ladder/robotrumble__sonnet_5.yaml b/configs/ablations/ladder/robotrumble__sonnet_5.yaml deleted file mode 100644 index 79cf31e0..00000000 --- a/configs/ablations/ladder/robotrumble__sonnet_5.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# RobotRumble ladder climbed by sonnet-5. Requires LLAMA_API_KEY in .env. -# uv run codeclash ladder run configs/ablations/ladder/robotrumble__sonnet_5.yaml -tournament: - rounds: 5 -ladder_rules: - min_round_win_fraction: 0.5 # advance only on a strict majority of rounds - win_last_k: 1 # ...and win the last K rounds (K=1 == just the final round) -game: - name: RobotRumble - sims_per_round: 250 - args: - raw: false -player: - agent: mini - name: sonnet-5 - branch_init: human/anton/anton3000 - config: - agent: !include mini/default.yaml - model: !include mini/models/llama_sonnet_5.yaml - push: True -prompts: - game_description: |- - RobotRumble ladder -ladder: !include ablations/ladder/rungs/robotrumble.yaml diff --git a/configs/ablations/vs_human/README.md b/configs/ablations/vs_human/README.md deleted file mode 100644 index d1f5cebf..00000000 --- a/configs/ablations/vs_human/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# vs. Human - -These set of configurations correspond to Section 4.1 of the original paper, specifically the subsection *On RobotRumble, models trail substantially behind expert human programmers*. - -Each configuration pits a model against an open source codebase written by a human expert for a particular arena. Across a tournament spanning 15 rounds, the model is allowed the evolve the codebase as it sees fit to beat the human expert's solution. The human's solution is *not* changing for the duration of the tournament. - -To make models compete against static human solutions, do the following two steps. - -1. Make sure the human solution is working and pushed as a branch to the corresponding arena. E.g. [gigachad](https://github.com/CodeClash-ai/RobotRumble/tree/human/entropicdrifter/gigachad) for RobotRumble. -2. Then, in your configuration, simply specify one of the players as a `dummy` agent, with `branch_init` set to the branch name, such as: - -```yaml -players: -- agent: dummy - branch_init: human/entropicdrifter/gigachad - name: gigachad -``` diff --git a/configs/ablations/vs_human/RobotRumble__claude-sonnet-4-20250514__vs__seven-of-nine__r15__s250.yaml b/configs/ablations/vs_human/RobotRumble__claude-sonnet-4-20250514__vs__seven-of-nine__r15__s250.yaml deleted file mode 100644 index e7e91d4e..00000000 --- a/configs/ablations/vs_human/RobotRumble__claude-sonnet-4-20250514__vs__seven-of-nine__r15__s250.yaml +++ /dev/null @@ -1,33 +0,0 @@ -tournament: - rounds: 15 -game: - name: RobotRumble - sims_per_round: 250 - args: - raw: true -players: -- agent: mini - name: claude-sonnet-4-20250514 - branch_init: starter/python - config: - agent: !include mini/default.yaml - model: - model_name: '@anthropic/claude-sonnet-4-20250514' - model_class: portkey - model_kwargs: - temperature: 0.2 - max_tokens: 4096 -- agent: dummy - name: seven-of-nine - branch_init: human/entropicdrifter/seven-of-nine -prompts: - game_description: | - You are a software developer ({{player_id}}) competing in a coding game called RobotRumble. - RobotRumble is a turn-based coding battle where you program a team of robots in Python to move, attack, and outmaneuver your opponent on a grid. - Every decision is driven by your code, and victory comes from crafting logic that positions robots smartly, times attacks well, and adapts over the 100-turn match. - - The game is played in {{rounds}} rounds. For every round, you (and your competitor) edit program code that controls your bot. This is round {{round}}. - After you and your competitor finish editing your codebases, the game is run automatically. - - Your task: improve the bot in `robot.py`, located in {{working_dir}}. - {{working_dir}} is your codebase, which contains both your bot and supporting assets. diff --git a/configs/ablations/vs_human/RobotRumble__claude-sonnet-4-5-20250929__vs__gigachad__r15__s250.yaml b/configs/ablations/vs_human/RobotRumble__claude-sonnet-4-5-20250929__vs__gigachad__r15__s250.yaml deleted file mode 100644 index fe803313..00000000 --- a/configs/ablations/vs_human/RobotRumble__claude-sonnet-4-5-20250929__vs__gigachad__r15__s250.yaml +++ /dev/null @@ -1,31 +0,0 @@ -tournament: - rounds: 15 -game: - name: RobotRumble - sims_per_round: 250 -players: -- agent: mini - name: claude-sonnet-4-5-20250929 - branch_init: starter/python - config: - agent: !include mini/default.yaml - model: - model_name: '@anthropic/claude-sonnet-4-5-20250929' - model_class: portkey - model_kwargs: - temperature: 0.2 - max_tokens: 4096 -- agent: dummy - name: gigachad - branch_init: human/entropicdrifter/gigachad -prompts: - game_description: | - You are a software developer ({{player_id}}) competing in a coding game called RobotRumble. - RobotRumble is a turn-based coding battle where you program a team of robots in Python to move, attack, and outmaneuver your opponent on a grid. - Every decision is driven by your code, and victory comes from crafting logic that positions robots smartly, times attacks well, and adapts over the 100-turn match. - - The game is played in {{rounds}} rounds. For every round, you (and your competitor) edit program code that controls your bot. This is round {{round}}. - After you and your competitor finish editing your codebases, the game is run automatically. - - Your task: improve the bot in `robot.py`, located in {{working_dir}}. - {{working_dir}} is your codebase, which contains both your bot and supporting assets. diff --git a/configs/ablations/vs_human/RobotRumble__claude-sonnet-4-5-20250929__vs__seven-of-nine__r15__s250.yaml b/configs/ablations/vs_human/RobotRumble__claude-sonnet-4-5-20250929__vs__seven-of-nine__r15__s250.yaml deleted file mode 100644 index 119179d0..00000000 --- a/configs/ablations/vs_human/RobotRumble__claude-sonnet-4-5-20250929__vs__seven-of-nine__r15__s250.yaml +++ /dev/null @@ -1,33 +0,0 @@ -tournament: - rounds: 15 -game: - name: RobotRumble - sims_per_round: 250 - args: - raw: true -players: -- agent: mini - name: claude-sonnet-4-5-20250929 - branch_init: starter/python - config: - agent: !include mini/default.yaml - model: - model_name: '@anthropic/claude-sonnet-4-5-20250929' - model_class: portkey - model_kwargs: - temperature: 0.2 - max_tokens: 4096 -- agent: dummy - name: seven-of-nine - branch_init: human/entropicdrifter/seven-of-nine -prompts: - game_description: | - You are a software developer ({{player_id}}) competing in a coding game called RobotRumble. - RobotRumble is a turn-based coding battle where you program a team of robots in Python to move, attack, and outmaneuver your opponent on a grid. - Every decision is driven by your code, and victory comes from crafting logic that positions robots smartly, times attacks well, and adapts over the 100-turn match. - - The game is played in {{rounds}} rounds. For every round, you (and your competitor) edit program code that controls your bot. This is round {{round}}. - After you and your competitor finish editing your codebases, the game is run automatically. - - Your task: improve the bot in `robot.py`, located in {{working_dir}}. - {{working_dir}} is your codebase, which contains both your bot and supporting assets. diff --git a/configs/ablations/vs_human/RobotRumble__gemini-2.5-pro__vs__seven-of-nine__r15__s250.yaml b/configs/ablations/vs_human/RobotRumble__gemini-2.5-pro__vs__seven-of-nine__r15__s250.yaml deleted file mode 100644 index 03730af0..00000000 --- a/configs/ablations/vs_human/RobotRumble__gemini-2.5-pro__vs__seven-of-nine__r15__s250.yaml +++ /dev/null @@ -1,32 +0,0 @@ -tournament: - rounds: 15 -game: - name: RobotRumble - sims_per_round: 250 - args: - raw: true -players: -- agent: mini - name: gemini-2.5-pro - branch_init: starter/python - config: - agent: !include mini/default.yaml - model: - model_name: '@google/gemini-2.5-pro' - model_class: portkey - model_kwargs: - temperature: 0.2 -- agent: dummy - name: seven-of-nine - branch_init: human/entropicdrifter/seven-of-nine -prompts: - game_description: | - You are a software developer ({{player_id}}) competing in a coding game called RobotRumble. - RobotRumble is a turn-based coding battle where you program a team of robots in Python to move, attack, and outmaneuver your opponent on a grid. - Every decision is driven by your code, and victory comes from crafting logic that positions robots smartly, times attacks well, and adapts over the 100-turn match. - - The game is played in {{rounds}} rounds. For every round, you (and your competitor) edit program code that controls your bot. This is round {{round}}. - After you and your competitor finish editing your codebases, the game is run automatically. - - Your task: improve the bot in `robot.py`, located in {{working_dir}}. - {{working_dir}} is your codebase, which contains both your bot and supporting assets. diff --git a/configs/ablations/vs_human/RobotRumble__gpt-5-mini__vs__seven-of-nine__r15__s250.yaml b/configs/ablations/vs_human/RobotRumble__gpt-5-mini__vs__seven-of-nine__r15__s250.yaml deleted file mode 100644 index 5eb43c50..00000000 --- a/configs/ablations/vs_human/RobotRumble__gpt-5-mini__vs__seven-of-nine__r15__s250.yaml +++ /dev/null @@ -1,30 +0,0 @@ -tournament: - rounds: 15 -game: - name: RobotRumble - sims_per_round: 250 - args: - raw: true -players: -- agent: mini - name: gpt-5-mini - branch_init: starter/python - config: - agent: !include mini/default.yaml - model: - model_name: '@openai/gpt-5-mini' - model_class: portkey -- agent: dummy - name: seven-of-nine - branch_init: human/entropicdrifter/seven-of-nine -prompts: - game_description: | - You are a software developer ({{player_id}}) competing in a coding game called RobotRumble. - RobotRumble is a turn-based coding battle where you program a team of robots in Python to move, attack, and outmaneuver your opponent on a grid. - Every decision is driven by your code, and victory comes from crafting logic that positions robots smartly, times attacks well, and adapts over the 100-turn match. - - The game is played in {{rounds}} rounds. For every round, you (and your competitor) edit program code that controls your bot. This is round {{round}}. - After you and your competitor finish editing your codebases, the game is run automatically. - - Your task: improve the bot in `robot.py`, located in {{working_dir}}. - {{working_dir}} is your codebase, which contains both your bot and supporting assets. diff --git a/configs/ablations/vs_human/RobotRumble__gpt-5__vs__seven-of-nine__r15__s250.yaml b/configs/ablations/vs_human/RobotRumble__gpt-5__vs__seven-of-nine__r15__s250.yaml deleted file mode 100644 index c14a2536..00000000 --- a/configs/ablations/vs_human/RobotRumble__gpt-5__vs__seven-of-nine__r15__s250.yaml +++ /dev/null @@ -1,30 +0,0 @@ -tournament: - rounds: 15 -game: - name: RobotRumble - sims_per_round: 250 - args: - raw: true -players: -- agent: mini - name: gpt-5 - branch_init: starter/python - config: - agent: !include mini/default.yaml - model: - model_name: '@openai/gpt-5' - model_class: portkey -- agent: dummy - name: seven-of-nine - branch_init: human/entropicdrifter/seven-of-nine -prompts: - game_description: | - You are a software developer ({{player_id}}) competing in a coding game called RobotRumble. - RobotRumble is a turn-based coding battle where you program a team of robots in Python to move, attack, and outmaneuver your opponent on a grid. - Every decision is driven by your code, and victory comes from crafting logic that positions robots smartly, times attacks well, and adapts over the 100-turn match. - - The game is played in {{rounds}} rounds. For every round, you (and your competitor) edit program code that controls your bot. This is round {{round}}. - After you and your competitor finish editing your codebases, the game is run automatically. - - Your task: improve the bot in `robot.py`, located in {{working_dir}}. - {{working_dir}} is your codebase, which contains both your bot and supporting assets. diff --git a/configs/ablations/vs_human/RobotRumble__grok-code-fast-1__vs__seven-of-nine__r15__s250.yaml b/configs/ablations/vs_human/RobotRumble__grok-code-fast-1__vs__seven-of-nine__r15__s250.yaml deleted file mode 100644 index 03a11585..00000000 --- a/configs/ablations/vs_human/RobotRumble__grok-code-fast-1__vs__seven-of-nine__r15__s250.yaml +++ /dev/null @@ -1,33 +0,0 @@ -tournament: - rounds: 15 -game: - name: RobotRumble - sims_per_round: 250 - args: - raw: true -players: -- agent: mini - name: grok-code-fast-1 - branch_init: starter/python - config: - agent: !include mini/default.yaml - model: - model_name: '@x-ai/grok-code-fast-1' - model_class: portkey - litellm_model_name_override: xai/grok-code-fast-1 - model_kwargs: - temperature: 0.2 -- agent: dummy - name: seven-of-nine - branch_init: human/entropicdrifter/seven-of-nine -prompts: - game_description: | - You are a software developer ({{player_id}}) competing in a coding game called RobotRumble. - RobotRumble is a turn-based coding battle where you program a team of robots in Python to move, attack, and outmaneuver your opponent on a grid. - Every decision is driven by your code, and victory comes from crafting logic that positions robots smartly, times attacks well, and adapts over the 100-turn match. - - The game is played in {{rounds}} rounds. For every round, you (and your competitor) edit program code that controls your bot. This is round {{round}}. - After you and your competitor finish editing your codebases, the game is run automatically. - - Your task: improve the bot in `robot.py`, located in {{working_dir}}. - {{working_dir}} is your codebase, which contains both your bot and supporting assets. diff --git a/configs/ablations/vs_human/RobotRumble__o3__vs__seven-of-nine__r15__s250.yaml b/configs/ablations/vs_human/RobotRumble__o3__vs__seven-of-nine__r15__s250.yaml deleted file mode 100644 index 3e95b5e1..00000000 --- a/configs/ablations/vs_human/RobotRumble__o3__vs__seven-of-nine__r15__s250.yaml +++ /dev/null @@ -1,30 +0,0 @@ -tournament: - rounds: 15 -game: - name: RobotRumble - sims_per_round: 250 - args: - raw: true -players: -- agent: mini - name: o3 - branch_init: starter/python - config: - agent: !include mini/default.yaml - model: - model_name: '@openai/o3' - model_class: portkey -- agent: dummy - name: seven-of-nine - branch_init: human/entropicdrifter/seven-of-nine -prompts: - game_description: | - You are a software developer ({{player_id}}) competing in a coding game called RobotRumble. - RobotRumble is a turn-based coding battle where you program a team of robots in Python to move, attack, and outmaneuver your opponent on a grid. - Every decision is driven by your code, and victory comes from crafting logic that positions robots smartly, times attacks well, and adapts over the 100-turn match. - - The game is played in {{rounds}} rounds. For every round, you (and your competitor) edit program code that controls your bot. This is round {{round}}. - After you and your competitor finish editing your codebases, the game is run automatically. - - Your task: improve the bot in `robot.py`, located in {{working_dir}}. - {{working_dir}} is your codebase, which contains both your bot and supporting assets. diff --git a/configs/ablations/vs_human/RobotRumble__qwen3-coder-plus-2025-09-23__vs__seven-of-nine__r15__s250.yaml b/configs/ablations/vs_human/RobotRumble__qwen3-coder-plus-2025-09-23__vs__seven-of-nine__r15__s250.yaml deleted file mode 100644 index 4b7f1caf..00000000 --- a/configs/ablations/vs_human/RobotRumble__qwen3-coder-plus-2025-09-23__vs__seven-of-nine__r15__s250.yaml +++ /dev/null @@ -1,31 +0,0 @@ -tournament: - rounds: 15 -game: - name: RobotRumble - sims_per_round: 250 - args: - raw: true -players: -- agent: mini - name: qwen3-coder-plus-2025-09-23 - branch_init: starter/python - config: - agent: !include mini/default.yaml - model: - model_name: dashscope/qwen3-coder-plus-2025-09-23 - model_kwargs: - temperature: 0.2 -- agent: dummy - name: seven-of-nine - branch_init: human/entropicdrifter/seven-of-nine -prompts: - game_description: | - You are a software developer ({{player_id}}) competing in a coding game called RobotRumble. - RobotRumble is a turn-based coding battle where you program a team of robots in Python to move, attack, and outmaneuver your opponent on a grid. - Every decision is driven by your code, and victory comes from crafting logic that positions robots smartly, times attacks well, and adapts over the 100-turn match. - - The game is played in {{rounds}} rounds. For every round, you (and your competitor) edit program code that controls your bot. This is round {{round}}. - After you and your competitor finish editing your codebases, the game is run automatically. - - Your task: improve the bot in `robot.py`, located in {{working_dir}}. - {{working_dir}} is your codebase, which contains both your bot and supporting assets. diff --git a/configs/examples/BattleSnake__claude-sonnet-4-5-20250929__o3__r5__s1000.yaml b/configs/examples/BattleSnake__claude-sonnet-4-5-20250929__o3__r5__s1000.yaml deleted file mode 100644 index 58413752..00000000 --- a/configs/examples/BattleSnake__claude-sonnet-4-5-20250929__o3__r5__s1000.yaml +++ /dev/null @@ -1,37 +0,0 @@ -tournament: - rounds: 5 -game: - name: BattleSnake - sims_per_round: 1000 - args: - width: 11 - height: 11 - browser: false -players: -- agent: mini - name: claude-sonnet-4-5-20250929 - config: - agent: !include mini/default.yaml - model: - model_name: 'anthropic/claude-sonnet-4-5-20250929' - model_kwargs: - temperature: 0.2 - max_tokens: 4096 -- agent: mini - name: o3 - config: - agent: !include mini/default.yaml - model: - model_name: 'openai/o3' -prompts: - game_description: |- - You are a software developer ({{player_id}}) competing in a coding game called BattleSnake. - Your bot (`main.py`) controls a snake on a grid-based board. - Snakes collect food, avoid collisions, and try to outlast their opponents. - - The game is played in 15 rounds. For every round, you (and your competitors) edit program code that controls your bot. This is round {{round}}. - After you and your competitor finish editing your codebases, the game is run automatically. - - Your task: improve the bot in `main.py`, located in {{working_dir}}. - {{working_dir}} is your codebase, which contains both your both and supporting assets. - All of your commands will be executed in the {{working_dir}} directory (see notes below). diff --git a/configs/examples/Bridge__claude-3-5-haiku__r2__s10.yaml b/configs/examples/Bridge__claude-3-5-haiku__r2__s10.yaml deleted file mode 100644 index 0853e30b..00000000 --- a/configs/examples/Bridge__claude-3-5-haiku__r2__s10.yaml +++ /dev/null @@ -1,74 +0,0 @@ -tournament: - rounds: 2 -game: - name: Bridge - sims_per_round: 10 -players: -- agent: mini - name: north - config: - agent: !include mini/default.yaml - model: - model_name: 'anthropic/claude-3-5-haiku-20241022' - model_kwargs: - temperature: 0.2 - max_tokens: 4096 -- agent: mini - name: east - config: - agent: !include mini/default.yaml - model: - model_name: 'anthropic/claude-3-5-haiku-20241022' - model_kwargs: - temperature: 0.2 - max_tokens: 4096 -- agent: mini - name: south - config: - agent: !include mini/default.yaml - model: - model_name: 'anthropic/claude-3-5-haiku-20241022' - model_kwargs: - temperature: 0.2 - max_tokens: 4096 -- agent: mini - name: west - config: - agent: !include mini/default.yaml - model: - model_name: 'anthropic/claude-3-5-haiku-20241022' - model_kwargs: - temperature: 0.2 - max_tokens: 4096 -prompts: - game_description: |- - You are a software developer ({{player_id}}) competing in a coding game called Bridge. - Bridge is a 4-player trick-taking card game played in partnerships: North/South vs East/West. - - Your position: {{player_id}} (North=0, East=1, South=2, West=3) - Teams: North/South (positions 0/2) vs East/West (positions 1/3) - - The game is played in {{total_rounds}} rounds. For every round, you (and your competitors) edit program code that controls your bot. This is round {{round}}. - After everyone finishes editing their codebases, the game is run automatically. - - Your task: improve the bot in `bridge_agent.py`, located in {{working_dir}}. - {{working_dir}} is your codebase, which contains both your bot and supporting assets. - All of your commands will be executed in the {{working_dir}} directory. - - Your bot must implement two functions: - - get_bid(game_state) -> str: Make bidding decisions during the auction - - play_card(game_state) -> str: Play a card during the play phase - - game_state contains: - - position: Your seat (0-3) - - hand: Your cards (e.g., ["AS", "KH", "7D", "TC"]) - - legal_bids/legal_cards: Valid moves you can make - - bids: Previous bids in the auction - - current_trick: Cards played in current trick - - contract: The final contract (after bidding) - - tricks_won: Tricks won by each team - - Card notation: where rank is A,K,Q,J,T,9,8,7,6,5,4,3,2 and suit is S,H,D,C - Bid notation: "PASS" or level(1-7) + strain(C,D,H,S,NT) like "1H", "3NT", "7S" - - Check examples/random_agent.py in the workspace for a starting template. diff --git a/configs/examples/CoreWar__claude-sonnet-4-5-20250929__o3__r5__s1000.yaml b/configs/examples/CoreWar__claude-sonnet-4-5-20250929__o3__r5__s1000.yaml deleted file mode 100644 index 615f339d..00000000 --- a/configs/examples/CoreWar__claude-sonnet-4-5-20250929__o3__r5__s1000.yaml +++ /dev/null @@ -1,34 +0,0 @@ -tournament: - rounds: 5 -game: - name: CoreWar - sims_per_round: 1000 - args: {} -players: -- agent: mini - name: claude-sonnet-4-5-20250929 - config: - agent: !include mini/default.yaml - model: - model_name: 'anthropic/claude-sonnet-4-5-20250929' - model_kwargs: - temperature: 0.2 - max_tokens: 4096 -- agent: mini - name: o3 - config: - agent: !include mini/default.yaml - model: - model_name: 'openai/o3' -prompts: - game_description: |- - You are a software developer ({{player_id}}) competing in a coding game called CoreWar. - CoreWar is a programming battle where you write "warriors" in an assembly-like language called Redcode to compete within a virtual machine (MARS), aiming to eliminate your rivals by making their code self-terminate. - Victory comes from crafting clever tactics—replicators, scanners, bombers—that exploit memory layout and instruction timing to control the core. - - The game is played in 15 rounds. For every round, you (and your competitors) edit program code that controls your bot. This is round {{round}}. - After you and your competitor finish editing your codebases, the game is run automatically. - - Your task: improve the bot in `warrior.red`, located in {{working_dir}}. - {{working_dir}} is your codebase, which contains both your both and supporting assets. - All of your commands will be executed in the {{working_dir}} directory (see notes below). diff --git a/configs/examples/Halite__claude-sonnet-4-5-20250929__o3__r5__s250.yaml b/configs/examples/Halite__claude-sonnet-4-5-20250929__o3__r5__s250.yaml deleted file mode 100644 index 6f484b0e..00000000 --- a/configs/examples/Halite__claude-sonnet-4-5-20250929__o3__r5__s250.yaml +++ /dev/null @@ -1,45 +0,0 @@ -tournament: - rounds: 5 -game: - name: Halite - sims_per_round: 250 - args: {} -players: -- agent: mini - name: claude-sonnet-4-5-20250929 - config: - agent: !include mini/default.yaml - model: - model_name: 'anthropic/claude-sonnet-4-5-20250929' - model_kwargs: - temperature: 0.2 - max_tokens: 4096 -- agent: mini - name: o3 - config: - agent: !include mini/default.yaml - model: - model_name: 'openai/o3' -prompts: - game_description: |- - You are a software developer ({{player_id}}) competing in a coding game called Halite. - Halite is a multi-player turn-based strategy game where bots compete on a rectangular grid to capture territory and accumulate strength. - Players control pieces that can move across the map to conquer neutral and enemy territory, with each cell providing production that increases the strength of pieces occupying it. - The goal is to control the most territory by the end of the game through strategic expansion, consolidation of forces, and tactical combat decisions. - - You have the choice of writing your Halite bot in one of four programming languages: C, C++, OCaml, or Rust. - Example implementations can be found under the `airesources/` folder. - Your submission should be stored in the `submission/` folder. This folder currently contains an example C bot, but feel free to use any of the supported languages. - Please make sure your main file is named `main.`, where `` is the appropriate file extension for your chosen programming language. - You may include additional files as needed, but please ensure: - 1. The `submission/` folder contains only files relevant to your bot. - 2. The `submission/` folder ONLY contains a single bot (no multiple bots in one submission). - 3. Your bot can be compiled. See `runGame.sh` under the corresponding `submission//` folder to see how we will compile and run your bot. - - - The game is played in 15 rounds. For every round, you (and your competitors) edit program code that controls your bot. This is round {{round}}. - After you and your competitor finish editing your codebases, the game is run automatically. - - Your task: improve the bot in `submission`, located in {{working_dir}}. - {{working_dir}} is your codebase, which contains both your both and supporting assets. - All of your commands will be executed in the {{working_dir}} directory (see notes below). diff --git a/configs/examples/HuskyBench__claude-sonnet-4-5-20250929__o3__r5__s100.yaml b/configs/examples/HuskyBench__claude-sonnet-4-5-20250929__o3__r5__s100.yaml deleted file mode 100644 index 6b383dd5..00000000 --- a/configs/examples/HuskyBench__claude-sonnet-4-5-20250929__o3__r5__s100.yaml +++ /dev/null @@ -1,36 +0,0 @@ -tournament: - rounds: 5 -game: - name: HuskyBench - sims_per_round: 100 - args: {} -players: -- agent: mini - name: claude-sonnet-4-5-20250929 - config: - agent: !include mini/default.yaml - model: - model_name: 'anthropic/claude-sonnet-4-5-20250929' - model_kwargs: - temperature: 0.2 - max_tokens: 4096 -- agent: mini - name: o3 - config: - agent: !include mini/default.yaml - model: - model_name: 'openai/o3' -prompts: - game_description: |- - You are a software developer ({{player_id}}) competing in a coding game called HuskyBench. - In this game, you will write code to control a poker-playing bot, aiming to outsmart your opponents and win chips. - Victory comes from crafting clever strategies—bluffing, reading opponents, and managing your chip stack effectively. - Be mindful of your bot's efficiency - your code should complete a simulation within 10 seconds to avoid forfeiting the round. - You can use run_game.sh to check if your bot runs in time. - - The game is played in 15 rounds. For every round, you (and your competitors) edit program code that controls your bot. This is round {{round}}. - After you and your competitor finish editing your codebases, the game is run automatically. - - Your task: improve the bot in `client/player.py`, located in {{working_dir}}. - {{working_dir}} is your codebase, which contains both your both and supporting assets. - All of your commands will be executed in the {{working_dir}} directory (see notes below). diff --git a/configs/examples/RoboCode__claude-sonnet-4-5-20250929__o3__r5__s250.yaml b/configs/examples/RoboCode__claude-sonnet-4-5-20250929__o3__r5__s250.yaml deleted file mode 100644 index 20742e5c..00000000 --- a/configs/examples/RoboCode__claude-sonnet-4-5-20250929__o3__r5__s250.yaml +++ /dev/null @@ -1,39 +0,0 @@ -tournament: - rounds: 5 -game: - name: RoboCode - sims_per_round: 250 - args: - nodisplay: true - nosound: true - record_ratio: 0.2 -players: -- agent: mini - name: claudesonnet4520250929 - config: - agent: !include mini/default.yaml - model: - model_name: 'anthropic/claude-sonnet-4-5-20250929' - model_kwargs: - temperature: 0.2 - max_tokens: 4096 -- agent: mini - name: o3 - config: - agent: !include mini/default.yaml - model: - model_name: 'openai/o3' -prompts: - game_description: |- - You are a software developer ({{player_id}}) competing in a coding game called RoboCode. - Robocode (Tank Royale) is a programming game where your code is the tank: each turn your bot sends intents—speed plus body/gun/radar turn rates and firepower—based on the game state it perceives via radar. - Your program decides how to move, aim, and fire in a deterministic, turn-based arena to outlast other bots. - Your bot logic must be written in Java and located in the `robots/custom/` directory. - Keep the main bot class named `MyTank.java`, but you can include additional Java files if you'd like. - - The game is played in 15 rounds. For every round, you (and your competitors) edit program code that controls your bot. This is round {{round}}. - After you and your competitor finish editing your codebases, the game is run automatically. - - Your task: improve the bot in `robots/custom/`, located in {{working_dir}}. - {{working_dir}} is your codebase, which contains both your both and supporting assets. - All of your commands will be executed in the {{working_dir}} directory (see notes below). diff --git a/configs/examples/RobotRumble__claude-sonnet-4-5-20250929__o3__r5__s250.yaml b/configs/examples/RobotRumble__claude-sonnet-4-5-20250929__o3__r5__s250.yaml deleted file mode 100644 index 45a0a795..00000000 --- a/configs/examples/RobotRumble__claude-sonnet-4-5-20250929__o3__r5__s250.yaml +++ /dev/null @@ -1,36 +0,0 @@ -tournament: - rounds: 5 -game: - name: RobotRumble - sims_per_round: 250 - args: - raw: true -players: -- agent: mini - name: claude-sonnet-4-5-20250929 - config: - agent: !include mini/default.yaml - model: - model_name: 'anthropic/claude-sonnet-4-5-20250929' - model_kwargs: - temperature: 0.2 - max_tokens: 4096 -- agent: mini - name: o3 - config: - agent: !include mini/default.yaml - model: - model_name: 'openai/o3' -prompts: - game_description: |- - You are a software developer ({{player_id}}) competing in a coding game called RobotRumble. - RobotRumble is a turn-based coding battle where you program a team of robots in Python to move, attack, and outmaneuver your opponent on a grid. - Every decision is driven by your code, and victory comes from crafting logic that positions robots smartly, times attacks well, and adapts over the 100-turn match. - NOTE: Please ensure that your code runs efficiently (under 60 seconds). Code that exceeds this run time will automatically forfeit the round. - - The game is played in 15 rounds. For every round, you (and your competitors) edit program code that controls your bot. This is round {{round}}. - After you and your competitor finish editing your codebases, the game is run automatically. - - Your task: improve the bot in `robot.js`, located in {{working_dir}}. - {{working_dir}} is your codebase, which contains both your both and supporting assets. - All of your commands will be executed in the {{working_dir}} directory (see notes below). diff --git a/configs/ablations/ladder/README.md b/configs/ladder/README.md similarity index 65% rename from configs/ablations/ladder/README.md rename to configs/ladder/README.md index 99d5e6c4..48895252 100644 --- a/configs/ablations/ladder/README.md +++ b/configs/ladder/README.md @@ -5,7 +5,7 @@ For a more static and hill-climb-able version of CodeClash, we introduce CC:Ladd For instance, for RobotRumble, we created a ladder by doing the following steps: 1. From the online [leaderboard](https://robotrumble.org/boards/2), we manually crawled all open source, published bots and pushed them as branches to the [CC:RobotRumble](https://github.com/CodeClash-ai/RobotRumble) repository. 2. We then created the `robotrumble.yaml` file in this folder. -3. Next, from the repository root, we run `uv run codeclash ladder run configs/ablations/ladder/robotrumble.yaml`, which runs PvP Tournaments against all pairs of branches. +3. Next, from the repository root, we run `uv run codeclash ladder run configs/ladder/robotrumble.yaml`, which runs PvP Tournaments against all pairs of branches. 4. From these logs, we then calculate win rate to rank all models. You can follow these steps to create your own "CC:" ladder. @@ -19,7 +19,7 @@ Each arena has a few kinds of config in this folder: - `make_.yaml` — the round-robin used to **build** the ladder (`ladder make`), running PvP tournaments across all pairs of human bots to rank them. - `.yaml` — the **run** config (`ladder run`): a climber ascends the ranked ladder rung by rung until it loses. - `__.yaml` — per-model run configs (e.g. `battlesnake__opus_4_8.yaml`) that swap in a specific model via `model: !include mini/models/llama_.yaml`. -- `rungs/.yaml` — the ranked opponent list (worst first, strongest last), shared by both `.yaml` and every `__.yaml` through `ladder: !include ablations/ladder/rungs/.yaml`. Edit the ladder in this one file and every config for that arena picks it up. +- `rungs/.yaml` — the ranked opponent list (worst first, strongest last), shared by both `.yaml` and every `__.yaml` through `ladder: !include ladder/rungs/.yaml`. Edit the ladder in this one file and every config for that arena picks it up. ## Ladder advancement rule (`ladder_rules`) @@ -27,11 +27,11 @@ Each run config carries a `ladder_rules` block controlling what it takes to clea ```yaml ladder_rules: - min_round_win_fraction: 0.5 # must win strictly more than this fraction of rounds - win_last_k: 1 # ...and must win the last K rounds (1 == just the final round) + min_round_wins: 2 # must win >= this many of the agent rounds to advance (round 0 excluded) + win_last_k: 0 # ...and must win the last K rounds (1 == just the final round, 0 == disabled) ``` -The defaults shown above reproduce the historical behavior (strict majority of rounds **and** win the final round); the block is optional and falls back to these values if omitted. Validation: +Both keys are **required** — there are no defaults; a config that omits either one errors out. `min_round_wins` is a whole number: the player advances when `player_wins >= min_round_wins`. The baseline round 0 (identical, un-edited codebases) is excluded, so with `tournament.rounds: 5` there are 5 scored agent rounds (rounds 1–5). Validation: -- `win_last_k` must be an integer with `1 <= win_last_k <= tournament.rounds`. -- `min_round_win_fraction` must be a number in `[0, 1)`; `0` drops the majority requirement (e.g. `min_round_win_fraction: 0` + `win_last_k: 1` means "just win the final round"). +- `min_round_wins` must be an integer with `1 <= min_round_wins <= tournament.rounds`. +- `win_last_k` must be an integer with `0 <= win_last_k <= min_round_wins`. `0` **disables** the trailing-rounds requirement; `1` means "just win the final round". diff --git a/configs/ablations/ladder/battlesnake.yaml b/configs/ladder/battlesnake.yaml similarity index 68% rename from configs/ablations/ladder/battlesnake.yaml rename to configs/ladder/battlesnake.yaml index 689a5d68..7468756b 100644 --- a/configs/ablations/ladder/battlesnake.yaml +++ b/configs/ladder/battlesnake.yaml @@ -1,12 +1,10 @@ # CC:Ladder for BattleSnake — the ranked ladder of human bots (worst opponent first, # strongest last), derived from the round-robin in make_battlesnake.yaml # (Bradley-Terry/Elo over 1225 pairwise tournaments). An LM climber ascends rung by -# rung until it loses. Run: uv run codeclash ladder run configs/ablations/ladder/battlesnake.yaml +# rung until it loses. Run: uv run codeclash ladder run configs/ladder/battlesnake.yaml tournament: rounds: 5 -ladder_rules: - min_round_win_fraction: 0.5 # advance only on a strict majority of rounds - win_last_k: 1 # ...and win the last K rounds (K=1 == just the final round) +ladder_rules: !include ladder/ladder_rules.yaml game: name: BattleSnake sims_per_round: 250 @@ -26,7 +24,5 @@ player: temperature: 0.2 max_tokens: 4096 push: True -prompts: - game_description: |- - BattleSnake ladder -ladder: !include ablations/ladder/rungs/battlesnake.yaml +prompts: !include ladder/ladder_prompt.yaml +ladder: !include ladder/rungs/battlesnake.yaml diff --git a/configs/ablations/ladder/battlesnake__gemini_3_5_flash.yaml b/configs/ladder/battlesnake__gemini_3_5_flash.yaml similarity index 52% rename from configs/ablations/ladder/battlesnake__gemini_3_5_flash.yaml rename to configs/ladder/battlesnake__gemini_3_5_flash.yaml index f5f2eca2..4f3cdd3d 100644 --- a/configs/ablations/ladder/battlesnake__gemini_3_5_flash.yaml +++ b/configs/ladder/battlesnake__gemini_3_5_flash.yaml @@ -1,10 +1,8 @@ # BattleSnake ladder climbed by gemini-3-5-flash. Requires LLAMA_API_KEY in .env. -# uv run codeclash ladder run configs/ablations/ladder/battlesnake__gemini_3_5_flash.yaml +# uv run codeclash ladder run configs/ladder/battlesnake__gemini_3_5_flash.yaml tournament: rounds: 5 -ladder_rules: - min_round_win_fraction: 0.5 # advance only on a strict majority of rounds - win_last_k: 1 # ...and win the last K rounds (K=1 == just the final round) +ladder_rules: !include ladder/ladder_rules.yaml game: name: BattleSnake sims_per_round: 250 @@ -20,7 +18,5 @@ player: agent: !include mini/default.yaml model: !include mini/models/llama_gemini_3_5_flash.yaml push: True -prompts: - game_description: |- - BattleSnake ladder -ladder: !include ablations/ladder/rungs/battlesnake.yaml +prompts: !include ladder/ladder_prompt.yaml +ladder: !include ladder/rungs/battlesnake.yaml diff --git a/configs/ablations/ladder/battlesnake__gpt_5_5.yaml b/configs/ladder/battlesnake__gpt_5_5.yaml similarity index 51% rename from configs/ablations/ladder/battlesnake__gpt_5_5.yaml rename to configs/ladder/battlesnake__gpt_5_5.yaml index 44c02b13..b18970ff 100644 --- a/configs/ablations/ladder/battlesnake__gpt_5_5.yaml +++ b/configs/ladder/battlesnake__gpt_5_5.yaml @@ -1,10 +1,8 @@ # BattleSnake ladder climbed by gpt-5-5. Requires LLAMA_API_KEY in .env. -# uv run codeclash ladder run configs/ablations/ladder/battlesnake__gpt_5_5.yaml +# uv run codeclash ladder run configs/ladder/battlesnake__gpt_5_5.yaml tournament: rounds: 5 -ladder_rules: - min_round_win_fraction: 0.5 # advance only on a strict majority of rounds - win_last_k: 1 # ...and win the last K rounds (K=1 == just the final round) +ladder_rules: !include ladder/ladder_rules.yaml game: name: BattleSnake sims_per_round: 250 @@ -20,7 +18,5 @@ player: agent: !include mini/default.yaml model: !include mini/models/llama_gpt_5_5.yaml push: True -prompts: - game_description: |- - BattleSnake ladder -ladder: !include ablations/ladder/rungs/battlesnake.yaml +prompts: !include ladder/ladder_prompt.yaml +ladder: !include ladder/rungs/battlesnake.yaml diff --git a/configs/ablations/ladder/battlesnake__opus_4_7.yaml b/configs/ladder/battlesnake__opus_4_7.yaml similarity index 51% rename from configs/ablations/ladder/battlesnake__opus_4_7.yaml rename to configs/ladder/battlesnake__opus_4_7.yaml index 7bca867e..f3161f5c 100644 --- a/configs/ablations/ladder/battlesnake__opus_4_7.yaml +++ b/configs/ladder/battlesnake__opus_4_7.yaml @@ -1,10 +1,8 @@ # BattleSnake ladder climbed by opus-4-7. Requires LLAMA_API_KEY in .env. -# uv run codeclash ladder run configs/ablations/ladder/battlesnake__opus_4_7.yaml +# uv run codeclash ladder run configs/ladder/battlesnake__opus_4_7.yaml tournament: rounds: 5 -ladder_rules: - min_round_win_fraction: 0.5 # advance only on a strict majority of rounds - win_last_k: 1 # ...and win the last K rounds (K=1 == just the final round) +ladder_rules: !include ladder/ladder_rules.yaml game: name: BattleSnake sims_per_round: 250 @@ -20,7 +18,5 @@ player: agent: !include mini/default.yaml model: !include mini/models/llama_opus_4_7.yaml push: True -prompts: - game_description: |- - BattleSnake ladder -ladder: !include ablations/ladder/rungs/battlesnake.yaml +prompts: !include ladder/ladder_prompt.yaml +ladder: !include ladder/rungs/battlesnake.yaml diff --git a/configs/ablations/ladder/battlesnake__opus_4_8.yaml b/configs/ladder/battlesnake__opus_4_8.yaml similarity index 51% rename from configs/ablations/ladder/battlesnake__opus_4_8.yaml rename to configs/ladder/battlesnake__opus_4_8.yaml index 9c4e8d76..1f6d5c35 100644 --- a/configs/ablations/ladder/battlesnake__opus_4_8.yaml +++ b/configs/ladder/battlesnake__opus_4_8.yaml @@ -1,10 +1,8 @@ # BattleSnake ladder climbed by opus-4-8. Requires LLAMA_API_KEY in .env. -# uv run codeclash ladder run configs/ablations/ladder/battlesnake__opus_4_8.yaml +# uv run codeclash ladder run configs/ladder/battlesnake__opus_4_8.yaml tournament: rounds: 5 -ladder_rules: - min_round_win_fraction: 0.5 # advance only on a strict majority of rounds - win_last_k: 1 # ...and win the last K rounds (K=1 == just the final round) +ladder_rules: !include ladder/ladder_rules.yaml game: name: BattleSnake sims_per_round: 250 @@ -20,7 +18,5 @@ player: agent: !include mini/default.yaml model: !include mini/models/llama_opus_4_8.yaml push: True -prompts: - game_description: |- - BattleSnake ladder -ladder: !include ablations/ladder/rungs/battlesnake.yaml +prompts: !include ladder/ladder_prompt.yaml +ladder: !include ladder/rungs/battlesnake.yaml diff --git a/configs/ablations/ladder/battlesnake__sonnet_5.yaml b/configs/ladder/battlesnake__sonnet_5.yaml similarity index 51% rename from configs/ablations/ladder/battlesnake__sonnet_5.yaml rename to configs/ladder/battlesnake__sonnet_5.yaml index 63c50e89..648475fe 100644 --- a/configs/ablations/ladder/battlesnake__sonnet_5.yaml +++ b/configs/ladder/battlesnake__sonnet_5.yaml @@ -1,10 +1,8 @@ # BattleSnake ladder climbed by sonnet-5. Requires LLAMA_API_KEY in .env. -# uv run codeclash ladder run configs/ablations/ladder/battlesnake__sonnet_5.yaml +# uv run codeclash ladder run configs/ladder/battlesnake__sonnet_5.yaml tournament: rounds: 5 -ladder_rules: - min_round_win_fraction: 0.5 # advance only on a strict majority of rounds - win_last_k: 1 # ...and win the last K rounds (K=1 == just the final round) +ladder_rules: !include ladder/ladder_rules.yaml game: name: BattleSnake sims_per_round: 250 @@ -20,7 +18,5 @@ player: agent: !include mini/default.yaml model: !include mini/models/llama_sonnet_5.yaml push: True -prompts: - game_description: |- - BattleSnake ladder -ladder: !include ablations/ladder/rungs/battlesnake.yaml +prompts: !include ladder/ladder_prompt.yaml +ladder: !include ladder/rungs/battlesnake.yaml diff --git a/configs/ablations/ladder/battlesnake_llama_smoke.yaml b/configs/ladder/battlesnake_llama_smoke.yaml similarity index 72% rename from configs/ablations/ladder/battlesnake_llama_smoke.yaml rename to configs/ladder/battlesnake_llama_smoke.yaml index b206b0e8..d5f9db56 100644 --- a/configs/ablations/ladder/battlesnake_llama_smoke.yaml +++ b/configs/ladder/battlesnake_llama_smoke.yaml @@ -2,12 +2,10 @@ # Opus 4.8 (native Anthropic API via AnthropicModel) climbs a 2-rung BattleSnake ladder. # 2 rounds, 10 sims — just enough to confirm the model authenticates, caches, and edits code. # Requires LLAMA_API_KEY in .env. -# uv run codeclash ladder run configs/ablations/ladder/battlesnake_llama_smoke.yaml -c +# uv run codeclash ladder run configs/ladder/battlesnake_llama_smoke.yaml -c tournament: rounds: 2 -ladder_rules: - min_round_win_fraction: 0.5 # win >= half the agent rounds (round 0 excluded) - win_last_k: 1 # ...and win the last K rounds (K=1 == the final round) +ladder_rules: !include ladder/ladder_rules.yaml game: name: BattleSnake sims_per_round: 10 @@ -25,8 +23,7 @@ player: step_limit: 10 # smoke override: stop after 10 steps (cost cap disabled in default.yaml) model: !include mini/models/llama_opus_4_8.yaml push: True -prompts: - game_description: "BattleSnake ladder smoke over the llama endpoint." +prompts: !include ladder/ladder_prompt.yaml ladder: - {agent: dummy, name: pinky, branch_init: human/moxuz/pinky-snek} # simple heuristic (port) - {agent: dummy, name: tr8r, branch_init: human/noahspriggs/tr-8r} # 2016 winner (port) diff --git a/configs/ablations/ladder/corewar.yaml b/configs/ladder/corewar.yaml similarity index 54% rename from configs/ablations/ladder/corewar.yaml rename to configs/ladder/corewar.yaml index 864e50aa..ae6760c1 100644 --- a/configs/ablations/ladder/corewar.yaml +++ b/configs/ladder/corewar.yaml @@ -1,8 +1,6 @@ tournament: rounds: 5 -ladder_rules: - min_round_win_fraction: 0.5 # advance only on a strict majority of rounds - win_last_k: 1 # ...and win the last K rounds (K=1 == just the final round) +ladder_rules: !include ladder/ladder_rules.yaml game: name: CoreWar sims_per_round: 2000 @@ -18,7 +16,5 @@ player: temperature: 0.2 max_tokens: 4096 push: True -prompts: - game_description: |- - Core War ladder -ladder: !include ablations/ladder/rungs/corewar.yaml +prompts: !include ladder/ladder_prompt.yaml +ladder: !include ladder/rungs/corewar.yaml diff --git a/configs/ladder/corewar__gemini_3_5_flash.yaml b/configs/ladder/corewar__gemini_3_5_flash.yaml new file mode 100644 index 00000000..3a53078c --- /dev/null +++ b/configs/ladder/corewar__gemini_3_5_flash.yaml @@ -0,0 +1,18 @@ +# CoreWar ladder climbed by gemini-3-5-flash. Requires LLAMA_API_KEY in .env. +# uv run codeclash ladder run configs/ladder/corewar__gemini_3_5_flash.yaml +tournament: + rounds: 5 +ladder_rules: !include ladder/ladder_rules.yaml +game: + name: CoreWar + sims_per_round: 2000 +player: + agent: mini + name: gemini-3-5-flash + branch_init: human/pspace + config: + agent: !include mini/default.yaml + model: !include mini/models/llama_gemini_3_5_flash.yaml + push: True +prompts: !include ladder/ladder_prompt.yaml +ladder: !include ladder/rungs/corewar.yaml diff --git a/configs/ladder/corewar__gpt_5_5.yaml b/configs/ladder/corewar__gpt_5_5.yaml new file mode 100644 index 00000000..673fefdc --- /dev/null +++ b/configs/ladder/corewar__gpt_5_5.yaml @@ -0,0 +1,18 @@ +# CoreWar ladder climbed by gpt-5-5. Requires LLAMA_API_KEY in .env. +# uv run codeclash ladder run configs/ladder/corewar__gpt_5_5.yaml +tournament: + rounds: 5 +ladder_rules: !include ladder/ladder_rules.yaml +game: + name: CoreWar + sims_per_round: 2000 +player: + agent: mini + name: gpt-5-5 + branch_init: human/pspace + config: + agent: !include mini/default.yaml + model: !include mini/models/llama_gpt_5_5.yaml + push: True +prompts: !include ladder/ladder_prompt.yaml +ladder: !include ladder/rungs/corewar.yaml diff --git a/configs/ladder/corewar__opus_4_7.yaml b/configs/ladder/corewar__opus_4_7.yaml new file mode 100644 index 00000000..82c362c7 --- /dev/null +++ b/configs/ladder/corewar__opus_4_7.yaml @@ -0,0 +1,18 @@ +# CoreWar ladder climbed by opus-4-7. Requires LLAMA_API_KEY in .env. +# uv run codeclash ladder run configs/ladder/corewar__opus_4_7.yaml +tournament: + rounds: 5 +ladder_rules: !include ladder/ladder_rules.yaml +game: + name: CoreWar + sims_per_round: 2000 +player: + agent: mini + name: opus-4-7 + branch_init: human/pspace + config: + agent: !include mini/default.yaml + model: !include mini/models/llama_opus_4_7.yaml + push: True +prompts: !include ladder/ladder_prompt.yaml +ladder: !include ladder/rungs/corewar.yaml diff --git a/configs/ladder/corewar__opus_4_8.yaml b/configs/ladder/corewar__opus_4_8.yaml new file mode 100644 index 00000000..3a4fc8ec --- /dev/null +++ b/configs/ladder/corewar__opus_4_8.yaml @@ -0,0 +1,18 @@ +# CoreWar ladder climbed by opus-4-8. Requires LLAMA_API_KEY in .env. +# uv run codeclash ladder run configs/ladder/corewar__opus_4_8.yaml +tournament: + rounds: 5 +ladder_rules: !include ladder/ladder_rules.yaml +game: + name: CoreWar + sims_per_round: 2000 +player: + agent: mini + name: opus-4-8 + branch_init: human/pspace + config: + agent: !include mini/default.yaml + model: !include mini/models/llama_opus_4_8.yaml + push: True +prompts: !include ladder/ladder_prompt.yaml +ladder: !include ladder/rungs/corewar.yaml diff --git a/configs/ladder/corewar__sonnet_5.yaml b/configs/ladder/corewar__sonnet_5.yaml new file mode 100644 index 00000000..30183f26 --- /dev/null +++ b/configs/ladder/corewar__sonnet_5.yaml @@ -0,0 +1,18 @@ +# CoreWar ladder climbed by sonnet-5. Requires LLAMA_API_KEY in .env. +# uv run codeclash ladder run configs/ladder/corewar__sonnet_5.yaml +tournament: + rounds: 5 +ladder_rules: !include ladder/ladder_rules.yaml +game: + name: CoreWar + sims_per_round: 2000 +player: + agent: mini + name: sonnet-5 + branch_init: human/pspace + config: + agent: !include mini/default.yaml + model: !include mini/models/llama_sonnet_5.yaml + push: True +prompts: !include ladder/ladder_prompt.yaml +ladder: !include ladder/rungs/corewar.yaml diff --git a/configs/ladder/ladder_prompt.yaml b/configs/ladder/ladder_prompt.yaml new file mode 100644 index 00000000..e1442060 --- /dev/null +++ b/configs/ladder/ladder_prompt.yaml @@ -0,0 +1,12 @@ +game_description: |- + You are a software developer ({{player_id}}) competing in a coding game. You are matched against a + single opponent, and your job is to write and improve the code for your bot so that it defeats theirs. + + {{arena_description}} + + You face this opponent over {{rounds}} rounds. Each round you edit your bot's code in {{working_dir}}; + when you submit, the two bots play a full match and the result is recorded. This is round {{round}} — + review how earlier rounds went (past match logs are in `/logs/`) and make your bot stronger. + + Your goal is to beat the opponent. The game's rules and your bot's entry point are documented in the + codebase (`docs/`). diff --git a/configs/ladder/ladder_rules.yaml b/configs/ladder/ladder_rules.yaml new file mode 100644 index 00000000..eed3f2e9 --- /dev/null +++ b/configs/ladder/ladder_rules.yaml @@ -0,0 +1,2 @@ +min_round_wins: 2 +win_last_k: 0 diff --git a/configs/ablations/ladder/make_battlesnake.yaml b/configs/ladder/make_battlesnake.yaml similarity index 97% rename from configs/ablations/ladder/make_battlesnake.yaml rename to configs/ladder/make_battlesnake.yaml index d71901ff..a8ba3b87 100644 --- a/configs/ablations/ladder/make_battlesnake.yaml +++ b/configs/ladder/make_battlesnake.yaml @@ -6,7 +6,7 @@ # 50 bots -> 50*49/2 = 1225 pairwise tournaments. # Excludes 4 compiled-language bots that can't build in-arena (snork/hettie/esproso/bobby-witt) # and bountysnake2017 (unreliable server). All bots live on CodeClash-ai/BattleSnake; Docker required. -# Run: uv run codeclash ladder make configs/ablations/ladder/make_battlesnake.yaml --workers 3 +# Run: uv run codeclash ladder make configs/ladder/make_battlesnake.yaml --workers 3 tournament: rounds: 0 diff --git a/configs/ablations/ladder/make_corewar.yaml b/configs/ladder/make_corewar.yaml similarity index 100% rename from configs/ablations/ladder/make_corewar.yaml rename to configs/ladder/make_corewar.yaml diff --git a/configs/ablations/ladder/make_robotrumble.yaml b/configs/ladder/make_robotrumble.yaml similarity index 100% rename from configs/ablations/ladder/make_robotrumble.yaml rename to configs/ladder/make_robotrumble.yaml diff --git a/configs/ablations/ladder/robotrumble.yaml b/configs/ladder/robotrumble.yaml similarity index 56% rename from configs/ablations/ladder/robotrumble.yaml rename to configs/ladder/robotrumble.yaml index 52298a69..05f5a31e 100644 --- a/configs/ablations/ladder/robotrumble.yaml +++ b/configs/ladder/robotrumble.yaml @@ -1,8 +1,6 @@ tournament: rounds: 5 -ladder_rules: - min_round_win_fraction: 0.5 # advance only on a strict majority of rounds - win_last_k: 1 # ...and win the last K rounds (K=1 == just the final round) +ladder_rules: !include ladder/ladder_rules.yaml game: name: RobotRumble sims_per_round: 250 @@ -20,7 +18,5 @@ player: temperature: 0.2 max_tokens: 4096 push: True -prompts: - game_description: |- - RobotRumble ladder -ladder: !include ablations/ladder/rungs/robotrumble.yaml +prompts: !include ladder/ladder_prompt.yaml +ladder: !include ladder/rungs/robotrumble.yaml diff --git a/configs/ladder/robotrumble__gemini_3_5_flash.yaml b/configs/ladder/robotrumble__gemini_3_5_flash.yaml new file mode 100644 index 00000000..880427bb --- /dev/null +++ b/configs/ladder/robotrumble__gemini_3_5_flash.yaml @@ -0,0 +1,20 @@ +# RobotRumble ladder climbed by gemini-3-5-flash. Requires LLAMA_API_KEY in .env. +# uv run codeclash ladder run configs/ladder/robotrumble__gemini_3_5_flash.yaml +tournament: + rounds: 5 +ladder_rules: !include ladder/ladder_rules.yaml +game: + name: RobotRumble + sims_per_round: 250 + args: + raw: false +player: + agent: mini + name: gemini-3-5-flash + branch_init: human/anton/anton3000 + config: + agent: !include mini/default.yaml + model: !include mini/models/llama_gemini_3_5_flash.yaml + push: True +prompts: !include ladder/ladder_prompt.yaml +ladder: !include ladder/rungs/robotrumble.yaml diff --git a/configs/ladder/robotrumble__gpt_5_5.yaml b/configs/ladder/robotrumble__gpt_5_5.yaml new file mode 100644 index 00000000..093412f7 --- /dev/null +++ b/configs/ladder/robotrumble__gpt_5_5.yaml @@ -0,0 +1,20 @@ +# RobotRumble ladder climbed by gpt-5-5. Requires LLAMA_API_KEY in .env. +# uv run codeclash ladder run configs/ladder/robotrumble__gpt_5_5.yaml +tournament: + rounds: 5 +ladder_rules: !include ladder/ladder_rules.yaml +game: + name: RobotRumble + sims_per_round: 250 + args: + raw: false +player: + agent: mini + name: gpt-5-5 + branch_init: human/anton/anton3000 + config: + agent: !include mini/default.yaml + model: !include mini/models/llama_gpt_5_5.yaml + push: True +prompts: !include ladder/ladder_prompt.yaml +ladder: !include ladder/rungs/robotrumble.yaml diff --git a/configs/ladder/robotrumble__opus_4_7.yaml b/configs/ladder/robotrumble__opus_4_7.yaml new file mode 100644 index 00000000..73173368 --- /dev/null +++ b/configs/ladder/robotrumble__opus_4_7.yaml @@ -0,0 +1,20 @@ +# RobotRumble ladder climbed by opus-4-7. Requires LLAMA_API_KEY in .env. +# uv run codeclash ladder run configs/ladder/robotrumble__opus_4_7.yaml +tournament: + rounds: 5 +ladder_rules: !include ladder/ladder_rules.yaml +game: + name: RobotRumble + sims_per_round: 250 + args: + raw: false +player: + agent: mini + name: opus-4-7 + branch_init: human/anton/anton3000 + config: + agent: !include mini/default.yaml + model: !include mini/models/llama_opus_4_7.yaml + push: True +prompts: !include ladder/ladder_prompt.yaml +ladder: !include ladder/rungs/robotrumble.yaml diff --git a/configs/ladder/robotrumble__opus_4_8.yaml b/configs/ladder/robotrumble__opus_4_8.yaml new file mode 100644 index 00000000..41a6e0d6 --- /dev/null +++ b/configs/ladder/robotrumble__opus_4_8.yaml @@ -0,0 +1,20 @@ +# RobotRumble ladder climbed by opus-4-8. Requires LLAMA_API_KEY in .env. +# uv run codeclash ladder run configs/ladder/robotrumble__opus_4_8.yaml +tournament: + rounds: 5 +ladder_rules: !include ladder/ladder_rules.yaml +game: + name: RobotRumble + sims_per_round: 250 + args: + raw: false +player: + agent: mini + name: opus-4-8 + branch_init: human/anton/anton3000 + config: + agent: !include mini/default.yaml + model: !include mini/models/llama_opus_4_8.yaml + push: True +prompts: !include ladder/ladder_prompt.yaml +ladder: !include ladder/rungs/robotrumble.yaml diff --git a/configs/ladder/robotrumble__sonnet_5.yaml b/configs/ladder/robotrumble__sonnet_5.yaml new file mode 100644 index 00000000..1d08a2d1 --- /dev/null +++ b/configs/ladder/robotrumble__sonnet_5.yaml @@ -0,0 +1,20 @@ +# RobotRumble ladder climbed by sonnet-5. Requires LLAMA_API_KEY in .env. +# uv run codeclash ladder run configs/ladder/robotrumble__sonnet_5.yaml +tournament: + rounds: 5 +ladder_rules: !include ladder/ladder_rules.yaml +game: + name: RobotRumble + sims_per_round: 250 + args: + raw: false +player: + agent: mini + name: sonnet-5 + branch_init: human/anton/anton3000 + config: + agent: !include mini/default.yaml + model: !include mini/models/llama_sonnet_5.yaml + push: True +prompts: !include ladder/ladder_prompt.yaml +ladder: !include ladder/rungs/robotrumble.yaml diff --git a/configs/ablations/ladder/rungs/battlesnake.yaml b/configs/ladder/rungs/battlesnake.yaml similarity index 100% rename from configs/ablations/ladder/rungs/battlesnake.yaml rename to configs/ladder/rungs/battlesnake.yaml diff --git a/configs/ablations/ladder/rungs/corewar.yaml b/configs/ladder/rungs/corewar.yaml similarity index 100% rename from configs/ablations/ladder/rungs/corewar.yaml rename to configs/ladder/rungs/corewar.yaml diff --git a/configs/ablations/ladder/rungs/robotrumble.yaml b/configs/ladder/rungs/robotrumble.yaml similarity index 100% rename from configs/ablations/ladder/rungs/robotrumble.yaml rename to configs/ladder/rungs/robotrumble.yaml diff --git a/configs/models.yaml b/configs/mini/model_roster.yaml similarity index 100% rename from configs/models.yaml rename to configs/mini/model_roster.yaml diff --git a/configs/main/BattleSnake__claude-sonnet-4-20250514__claude-sonnet-4-5-20250929__r15__s1000.yaml b/configs/pvp/BattleSnake__claude-sonnet-4-20250514__claude-sonnet-4-5-20250929__r15__s1000.yaml similarity index 100% rename from configs/main/BattleSnake__claude-sonnet-4-20250514__claude-sonnet-4-5-20250929__r15__s1000.yaml rename to configs/pvp/BattleSnake__claude-sonnet-4-20250514__claude-sonnet-4-5-20250929__r15__s1000.yaml diff --git a/configs/main/BattleSnake__claude-sonnet-4-20250514__gemini-2.5-pro__r15__s1000.yaml b/configs/pvp/BattleSnake__claude-sonnet-4-20250514__gemini-2.5-pro__r15__s1000.yaml similarity index 100% rename from configs/main/BattleSnake__claude-sonnet-4-20250514__gemini-2.5-pro__r15__s1000.yaml rename to configs/pvp/BattleSnake__claude-sonnet-4-20250514__gemini-2.5-pro__r15__s1000.yaml diff --git a/configs/main/BattleSnake__claude-sonnet-4-20250514__gpt-5-mini__r15__s1000.yaml b/configs/pvp/BattleSnake__claude-sonnet-4-20250514__gpt-5-mini__r15__s1000.yaml similarity index 100% rename from configs/main/BattleSnake__claude-sonnet-4-20250514__gpt-5-mini__r15__s1000.yaml rename to configs/pvp/BattleSnake__claude-sonnet-4-20250514__gpt-5-mini__r15__s1000.yaml diff --git a/configs/main/BattleSnake__claude-sonnet-4-20250514__gpt-5__r15__s1000.yaml b/configs/pvp/BattleSnake__claude-sonnet-4-20250514__gpt-5__r15__s1000.yaml similarity index 100% rename from configs/main/BattleSnake__claude-sonnet-4-20250514__gpt-5__r15__s1000.yaml rename to configs/pvp/BattleSnake__claude-sonnet-4-20250514__gpt-5__r15__s1000.yaml diff --git a/configs/main/BattleSnake__claude-sonnet-4-20250514__grok-code-fast-1__r15__s1000.yaml b/configs/pvp/BattleSnake__claude-sonnet-4-20250514__grok-code-fast-1__r15__s1000.yaml similarity index 100% rename from configs/main/BattleSnake__claude-sonnet-4-20250514__grok-code-fast-1__r15__s1000.yaml rename to configs/pvp/BattleSnake__claude-sonnet-4-20250514__grok-code-fast-1__r15__s1000.yaml diff --git a/configs/main/BattleSnake__claude-sonnet-4-20250514__o3__r15__s1000.yaml b/configs/pvp/BattleSnake__claude-sonnet-4-20250514__o3__r15__s1000.yaml similarity index 100% rename from configs/main/BattleSnake__claude-sonnet-4-20250514__o3__r15__s1000.yaml rename to configs/pvp/BattleSnake__claude-sonnet-4-20250514__o3__r15__s1000.yaml diff --git a/configs/main/BattleSnake__claude-sonnet-4-20250514__qwen3-coder-plus-2025-09-23__r15__s1000.yaml b/configs/pvp/BattleSnake__claude-sonnet-4-20250514__qwen3-coder-plus-2025-09-23__r15__s1000.yaml similarity index 100% rename from configs/main/BattleSnake__claude-sonnet-4-20250514__qwen3-coder-plus-2025-09-23__r15__s1000.yaml rename to configs/pvp/BattleSnake__claude-sonnet-4-20250514__qwen3-coder-plus-2025-09-23__r15__s1000.yaml diff --git a/configs/main/BattleSnake__claude-sonnet-4-5-20250929__gemini-2.5-pro__r15__s1000.yaml b/configs/pvp/BattleSnake__claude-sonnet-4-5-20250929__gemini-2.5-pro__r15__s1000.yaml similarity index 100% rename from configs/main/BattleSnake__claude-sonnet-4-5-20250929__gemini-2.5-pro__r15__s1000.yaml rename to configs/pvp/BattleSnake__claude-sonnet-4-5-20250929__gemini-2.5-pro__r15__s1000.yaml diff --git a/configs/main/BattleSnake__claude-sonnet-4-5-20250929__gpt-5-mini__r15__s1000.yaml b/configs/pvp/BattleSnake__claude-sonnet-4-5-20250929__gpt-5-mini__r15__s1000.yaml similarity index 100% rename from configs/main/BattleSnake__claude-sonnet-4-5-20250929__gpt-5-mini__r15__s1000.yaml rename to configs/pvp/BattleSnake__claude-sonnet-4-5-20250929__gpt-5-mini__r15__s1000.yaml diff --git a/configs/main/BattleSnake__claude-sonnet-4-5-20250929__gpt-5__r15__s1000.yaml b/configs/pvp/BattleSnake__claude-sonnet-4-5-20250929__gpt-5__r15__s1000.yaml similarity index 100% rename from configs/main/BattleSnake__claude-sonnet-4-5-20250929__gpt-5__r15__s1000.yaml rename to configs/pvp/BattleSnake__claude-sonnet-4-5-20250929__gpt-5__r15__s1000.yaml diff --git a/configs/main/BattleSnake__claude-sonnet-4-5-20250929__grok-code-fast-1__r15__s1000.yaml b/configs/pvp/BattleSnake__claude-sonnet-4-5-20250929__grok-code-fast-1__r15__s1000.yaml similarity index 100% rename from configs/main/BattleSnake__claude-sonnet-4-5-20250929__grok-code-fast-1__r15__s1000.yaml rename to configs/pvp/BattleSnake__claude-sonnet-4-5-20250929__grok-code-fast-1__r15__s1000.yaml diff --git a/configs/main/BattleSnake__claude-sonnet-4-5-20250929__o3__r15__s1000.yaml b/configs/pvp/BattleSnake__claude-sonnet-4-5-20250929__o3__r15__s1000.yaml similarity index 100% rename from configs/main/BattleSnake__claude-sonnet-4-5-20250929__o3__r15__s1000.yaml rename to configs/pvp/BattleSnake__claude-sonnet-4-5-20250929__o3__r15__s1000.yaml diff --git a/configs/main/BattleSnake__claude-sonnet-4-5-20250929__qwen3-coder-plus-2025-09-23__r15__s1000.yaml b/configs/pvp/BattleSnake__claude-sonnet-4-5-20250929__qwen3-coder-plus-2025-09-23__r15__s1000.yaml similarity index 100% rename from configs/main/BattleSnake__claude-sonnet-4-5-20250929__qwen3-coder-plus-2025-09-23__r15__s1000.yaml rename to configs/pvp/BattleSnake__claude-sonnet-4-5-20250929__qwen3-coder-plus-2025-09-23__r15__s1000.yaml diff --git a/configs/main/BattleSnake__gemini-2.5-pro__gpt-5-mini__r15__s1000.yaml b/configs/pvp/BattleSnake__gemini-2.5-pro__gpt-5-mini__r15__s1000.yaml similarity index 100% rename from configs/main/BattleSnake__gemini-2.5-pro__gpt-5-mini__r15__s1000.yaml rename to configs/pvp/BattleSnake__gemini-2.5-pro__gpt-5-mini__r15__s1000.yaml diff --git a/configs/main/BattleSnake__gemini-2.5-pro__gpt-5__r15__s1000.yaml b/configs/pvp/BattleSnake__gemini-2.5-pro__gpt-5__r15__s1000.yaml similarity index 100% rename from configs/main/BattleSnake__gemini-2.5-pro__gpt-5__r15__s1000.yaml rename to configs/pvp/BattleSnake__gemini-2.5-pro__gpt-5__r15__s1000.yaml diff --git a/configs/main/BattleSnake__gemini-2.5-pro__grok-code-fast-1__r15__s1000.yaml b/configs/pvp/BattleSnake__gemini-2.5-pro__grok-code-fast-1__r15__s1000.yaml similarity index 100% rename from configs/main/BattleSnake__gemini-2.5-pro__grok-code-fast-1__r15__s1000.yaml rename to configs/pvp/BattleSnake__gemini-2.5-pro__grok-code-fast-1__r15__s1000.yaml diff --git a/configs/main/BattleSnake__gemini-2.5-pro__o3__r15__s1000.yaml b/configs/pvp/BattleSnake__gemini-2.5-pro__o3__r15__s1000.yaml similarity index 100% rename from configs/main/BattleSnake__gemini-2.5-pro__o3__r15__s1000.yaml rename to configs/pvp/BattleSnake__gemini-2.5-pro__o3__r15__s1000.yaml diff --git a/configs/main/BattleSnake__gemini-2.5-pro__qwen3-coder-plus-2025-09-23__r15__s1000.yaml b/configs/pvp/BattleSnake__gemini-2.5-pro__qwen3-coder-plus-2025-09-23__r15__s1000.yaml similarity index 100% rename from configs/main/BattleSnake__gemini-2.5-pro__qwen3-coder-plus-2025-09-23__r15__s1000.yaml rename to configs/pvp/BattleSnake__gemini-2.5-pro__qwen3-coder-plus-2025-09-23__r15__s1000.yaml diff --git a/configs/main/BattleSnake__gpt-5-mini__grok-code-fast-1__r15__s1000.yaml b/configs/pvp/BattleSnake__gpt-5-mini__grok-code-fast-1__r15__s1000.yaml similarity index 100% rename from configs/main/BattleSnake__gpt-5-mini__grok-code-fast-1__r15__s1000.yaml rename to configs/pvp/BattleSnake__gpt-5-mini__grok-code-fast-1__r15__s1000.yaml diff --git a/configs/main/BattleSnake__gpt-5-mini__o3__r15__s1000.yaml b/configs/pvp/BattleSnake__gpt-5-mini__o3__r15__s1000.yaml similarity index 100% rename from configs/main/BattleSnake__gpt-5-mini__o3__r15__s1000.yaml rename to configs/pvp/BattleSnake__gpt-5-mini__o3__r15__s1000.yaml diff --git a/configs/main/BattleSnake__gpt-5-mini__qwen3-coder-plus-2025-09-23__r15__s1000.yaml b/configs/pvp/BattleSnake__gpt-5-mini__qwen3-coder-plus-2025-09-23__r15__s1000.yaml similarity index 100% rename from configs/main/BattleSnake__gpt-5-mini__qwen3-coder-plus-2025-09-23__r15__s1000.yaml rename to configs/pvp/BattleSnake__gpt-5-mini__qwen3-coder-plus-2025-09-23__r15__s1000.yaml diff --git a/configs/main/BattleSnake__gpt-5__gpt-5-mini__r15__s1000.yaml b/configs/pvp/BattleSnake__gpt-5__gpt-5-mini__r15__s1000.yaml similarity index 100% rename from configs/main/BattleSnake__gpt-5__gpt-5-mini__r15__s1000.yaml rename to configs/pvp/BattleSnake__gpt-5__gpt-5-mini__r15__s1000.yaml diff --git a/configs/main/BattleSnake__gpt-5__grok-code-fast-1__r15__s1000.yaml b/configs/pvp/BattleSnake__gpt-5__grok-code-fast-1__r15__s1000.yaml similarity index 100% rename from configs/main/BattleSnake__gpt-5__grok-code-fast-1__r15__s1000.yaml rename to configs/pvp/BattleSnake__gpt-5__grok-code-fast-1__r15__s1000.yaml diff --git a/configs/main/BattleSnake__gpt-5__o3__r15__s1000.yaml b/configs/pvp/BattleSnake__gpt-5__o3__r15__s1000.yaml similarity index 100% rename from configs/main/BattleSnake__gpt-5__o3__r15__s1000.yaml rename to configs/pvp/BattleSnake__gpt-5__o3__r15__s1000.yaml diff --git a/configs/main/BattleSnake__gpt-5__qwen3-coder-plus-2025-09-23__r15__s1000.yaml b/configs/pvp/BattleSnake__gpt-5__qwen3-coder-plus-2025-09-23__r15__s1000.yaml similarity index 100% rename from configs/main/BattleSnake__gpt-5__qwen3-coder-plus-2025-09-23__r15__s1000.yaml rename to configs/pvp/BattleSnake__gpt-5__qwen3-coder-plus-2025-09-23__r15__s1000.yaml diff --git a/configs/main/BattleSnake__grok-code-fast-1__o3__r15__s1000.yaml b/configs/pvp/BattleSnake__grok-code-fast-1__o3__r15__s1000.yaml similarity index 100% rename from configs/main/BattleSnake__grok-code-fast-1__o3__r15__s1000.yaml rename to configs/pvp/BattleSnake__grok-code-fast-1__o3__r15__s1000.yaml diff --git a/configs/main/BattleSnake__grok-code-fast-1__qwen3-coder-plus-2025-09-23__r15__s1000.yaml b/configs/pvp/BattleSnake__grok-code-fast-1__qwen3-coder-plus-2025-09-23__r15__s1000.yaml similarity index 100% rename from configs/main/BattleSnake__grok-code-fast-1__qwen3-coder-plus-2025-09-23__r15__s1000.yaml rename to configs/pvp/BattleSnake__grok-code-fast-1__qwen3-coder-plus-2025-09-23__r15__s1000.yaml diff --git a/configs/main/BattleSnake__o3__qwen3-coder-plus-2025-09-23__r15__s1000.yaml b/configs/pvp/BattleSnake__o3__qwen3-coder-plus-2025-09-23__r15__s1000.yaml similarity index 100% rename from configs/main/BattleSnake__o3__qwen3-coder-plus-2025-09-23__r15__s1000.yaml rename to configs/pvp/BattleSnake__o3__qwen3-coder-plus-2025-09-23__r15__s1000.yaml diff --git a/configs/main/CoreWar__claude-sonnet-4-20250514__claude-sonnet-4-5-20250929__r15__s1000.yaml b/configs/pvp/CoreWar__claude-sonnet-4-20250514__claude-sonnet-4-5-20250929__r15__s1000.yaml similarity index 100% rename from configs/main/CoreWar__claude-sonnet-4-20250514__claude-sonnet-4-5-20250929__r15__s1000.yaml rename to configs/pvp/CoreWar__claude-sonnet-4-20250514__claude-sonnet-4-5-20250929__r15__s1000.yaml diff --git a/configs/main/CoreWar__claude-sonnet-4-20250514__gemini-2.5-pro__r15__s1000.yaml b/configs/pvp/CoreWar__claude-sonnet-4-20250514__gemini-2.5-pro__r15__s1000.yaml similarity index 100% rename from configs/main/CoreWar__claude-sonnet-4-20250514__gemini-2.5-pro__r15__s1000.yaml rename to configs/pvp/CoreWar__claude-sonnet-4-20250514__gemini-2.5-pro__r15__s1000.yaml diff --git a/configs/main/CoreWar__claude-sonnet-4-20250514__gpt-5-mini__r15__s1000.yaml b/configs/pvp/CoreWar__claude-sonnet-4-20250514__gpt-5-mini__r15__s1000.yaml similarity index 100% rename from configs/main/CoreWar__claude-sonnet-4-20250514__gpt-5-mini__r15__s1000.yaml rename to configs/pvp/CoreWar__claude-sonnet-4-20250514__gpt-5-mini__r15__s1000.yaml diff --git a/configs/main/CoreWar__claude-sonnet-4-20250514__gpt-5__r15__s1000.yaml b/configs/pvp/CoreWar__claude-sonnet-4-20250514__gpt-5__r15__s1000.yaml similarity index 100% rename from configs/main/CoreWar__claude-sonnet-4-20250514__gpt-5__r15__s1000.yaml rename to configs/pvp/CoreWar__claude-sonnet-4-20250514__gpt-5__r15__s1000.yaml diff --git a/configs/main/CoreWar__claude-sonnet-4-20250514__grok-code-fast-1__r15__s1000.yaml b/configs/pvp/CoreWar__claude-sonnet-4-20250514__grok-code-fast-1__r15__s1000.yaml similarity index 100% rename from configs/main/CoreWar__claude-sonnet-4-20250514__grok-code-fast-1__r15__s1000.yaml rename to configs/pvp/CoreWar__claude-sonnet-4-20250514__grok-code-fast-1__r15__s1000.yaml diff --git a/configs/main/CoreWar__claude-sonnet-4-20250514__o3__r15__s1000.yaml b/configs/pvp/CoreWar__claude-sonnet-4-20250514__o3__r15__s1000.yaml similarity index 100% rename from configs/main/CoreWar__claude-sonnet-4-20250514__o3__r15__s1000.yaml rename to configs/pvp/CoreWar__claude-sonnet-4-20250514__o3__r15__s1000.yaml diff --git a/configs/main/CoreWar__claude-sonnet-4-20250514__qwen3-coder-plus-2025-09-23__r15__s1000.yaml b/configs/pvp/CoreWar__claude-sonnet-4-20250514__qwen3-coder-plus-2025-09-23__r15__s1000.yaml similarity index 100% rename from configs/main/CoreWar__claude-sonnet-4-20250514__qwen3-coder-plus-2025-09-23__r15__s1000.yaml rename to configs/pvp/CoreWar__claude-sonnet-4-20250514__qwen3-coder-plus-2025-09-23__r15__s1000.yaml diff --git a/configs/main/CoreWar__claude-sonnet-4-5-20250929__gemini-2.5-pro__r15__s1000.yaml b/configs/pvp/CoreWar__claude-sonnet-4-5-20250929__gemini-2.5-pro__r15__s1000.yaml similarity index 100% rename from configs/main/CoreWar__claude-sonnet-4-5-20250929__gemini-2.5-pro__r15__s1000.yaml rename to configs/pvp/CoreWar__claude-sonnet-4-5-20250929__gemini-2.5-pro__r15__s1000.yaml diff --git a/configs/main/CoreWar__claude-sonnet-4-5-20250929__gpt-5-mini__r15__s1000.yaml b/configs/pvp/CoreWar__claude-sonnet-4-5-20250929__gpt-5-mini__r15__s1000.yaml similarity index 100% rename from configs/main/CoreWar__claude-sonnet-4-5-20250929__gpt-5-mini__r15__s1000.yaml rename to configs/pvp/CoreWar__claude-sonnet-4-5-20250929__gpt-5-mini__r15__s1000.yaml diff --git a/configs/main/CoreWar__claude-sonnet-4-5-20250929__gpt-5__r15__s1000.yaml b/configs/pvp/CoreWar__claude-sonnet-4-5-20250929__gpt-5__r15__s1000.yaml similarity index 100% rename from configs/main/CoreWar__claude-sonnet-4-5-20250929__gpt-5__r15__s1000.yaml rename to configs/pvp/CoreWar__claude-sonnet-4-5-20250929__gpt-5__r15__s1000.yaml diff --git a/configs/main/CoreWar__claude-sonnet-4-5-20250929__grok-code-fast-1__r15__s1000.yaml b/configs/pvp/CoreWar__claude-sonnet-4-5-20250929__grok-code-fast-1__r15__s1000.yaml similarity index 100% rename from configs/main/CoreWar__claude-sonnet-4-5-20250929__grok-code-fast-1__r15__s1000.yaml rename to configs/pvp/CoreWar__claude-sonnet-4-5-20250929__grok-code-fast-1__r15__s1000.yaml diff --git a/configs/main/CoreWar__claude-sonnet-4-5-20250929__o3__r15__s1000.yaml b/configs/pvp/CoreWar__claude-sonnet-4-5-20250929__o3__r15__s1000.yaml similarity index 100% rename from configs/main/CoreWar__claude-sonnet-4-5-20250929__o3__r15__s1000.yaml rename to configs/pvp/CoreWar__claude-sonnet-4-5-20250929__o3__r15__s1000.yaml diff --git a/configs/main/CoreWar__claude-sonnet-4-5-20250929__qwen3-coder-plus-2025-09-23__r15__s1000.yaml b/configs/pvp/CoreWar__claude-sonnet-4-5-20250929__qwen3-coder-plus-2025-09-23__r15__s1000.yaml similarity index 100% rename from configs/main/CoreWar__claude-sonnet-4-5-20250929__qwen3-coder-plus-2025-09-23__r15__s1000.yaml rename to configs/pvp/CoreWar__claude-sonnet-4-5-20250929__qwen3-coder-plus-2025-09-23__r15__s1000.yaml diff --git a/configs/main/CoreWar__gemini-2.5-pro__gpt-5-mini__r15__s1000.yaml b/configs/pvp/CoreWar__gemini-2.5-pro__gpt-5-mini__r15__s1000.yaml similarity index 100% rename from configs/main/CoreWar__gemini-2.5-pro__gpt-5-mini__r15__s1000.yaml rename to configs/pvp/CoreWar__gemini-2.5-pro__gpt-5-mini__r15__s1000.yaml diff --git a/configs/main/CoreWar__gemini-2.5-pro__gpt-5__r15__s1000.yaml b/configs/pvp/CoreWar__gemini-2.5-pro__gpt-5__r15__s1000.yaml similarity index 100% rename from configs/main/CoreWar__gemini-2.5-pro__gpt-5__r15__s1000.yaml rename to configs/pvp/CoreWar__gemini-2.5-pro__gpt-5__r15__s1000.yaml diff --git a/configs/main/CoreWar__gemini-2.5-pro__grok-code-fast-1__r15__s1000.yaml b/configs/pvp/CoreWar__gemini-2.5-pro__grok-code-fast-1__r15__s1000.yaml similarity index 100% rename from configs/main/CoreWar__gemini-2.5-pro__grok-code-fast-1__r15__s1000.yaml rename to configs/pvp/CoreWar__gemini-2.5-pro__grok-code-fast-1__r15__s1000.yaml diff --git a/configs/main/CoreWar__gemini-2.5-pro__o3__r15__s1000.yaml b/configs/pvp/CoreWar__gemini-2.5-pro__o3__r15__s1000.yaml similarity index 100% rename from configs/main/CoreWar__gemini-2.5-pro__o3__r15__s1000.yaml rename to configs/pvp/CoreWar__gemini-2.5-pro__o3__r15__s1000.yaml diff --git a/configs/main/CoreWar__gemini-2.5-pro__qwen3-coder-plus-2025-09-23__r15__s1000.yaml b/configs/pvp/CoreWar__gemini-2.5-pro__qwen3-coder-plus-2025-09-23__r15__s1000.yaml similarity index 100% rename from configs/main/CoreWar__gemini-2.5-pro__qwen3-coder-plus-2025-09-23__r15__s1000.yaml rename to configs/pvp/CoreWar__gemini-2.5-pro__qwen3-coder-plus-2025-09-23__r15__s1000.yaml diff --git a/configs/main/CoreWar__gpt-5-mini__grok-code-fast-1__r15__s1000.yaml b/configs/pvp/CoreWar__gpt-5-mini__grok-code-fast-1__r15__s1000.yaml similarity index 100% rename from configs/main/CoreWar__gpt-5-mini__grok-code-fast-1__r15__s1000.yaml rename to configs/pvp/CoreWar__gpt-5-mini__grok-code-fast-1__r15__s1000.yaml diff --git a/configs/main/CoreWar__gpt-5-mini__o3__r15__s1000.yaml b/configs/pvp/CoreWar__gpt-5-mini__o3__r15__s1000.yaml similarity index 100% rename from configs/main/CoreWar__gpt-5-mini__o3__r15__s1000.yaml rename to configs/pvp/CoreWar__gpt-5-mini__o3__r15__s1000.yaml diff --git a/configs/main/CoreWar__gpt-5-mini__qwen3-coder-plus-2025-09-23__r15__s1000.yaml b/configs/pvp/CoreWar__gpt-5-mini__qwen3-coder-plus-2025-09-23__r15__s1000.yaml similarity index 100% rename from configs/main/CoreWar__gpt-5-mini__qwen3-coder-plus-2025-09-23__r15__s1000.yaml rename to configs/pvp/CoreWar__gpt-5-mini__qwen3-coder-plus-2025-09-23__r15__s1000.yaml diff --git a/configs/main/CoreWar__gpt-5__gpt-5-mini__r15__s1000.yaml b/configs/pvp/CoreWar__gpt-5__gpt-5-mini__r15__s1000.yaml similarity index 100% rename from configs/main/CoreWar__gpt-5__gpt-5-mini__r15__s1000.yaml rename to configs/pvp/CoreWar__gpt-5__gpt-5-mini__r15__s1000.yaml diff --git a/configs/main/CoreWar__gpt-5__grok-code-fast-1__r15__s1000.yaml b/configs/pvp/CoreWar__gpt-5__grok-code-fast-1__r15__s1000.yaml similarity index 100% rename from configs/main/CoreWar__gpt-5__grok-code-fast-1__r15__s1000.yaml rename to configs/pvp/CoreWar__gpt-5__grok-code-fast-1__r15__s1000.yaml diff --git a/configs/main/CoreWar__gpt-5__o3__r15__s1000.yaml b/configs/pvp/CoreWar__gpt-5__o3__r15__s1000.yaml similarity index 100% rename from configs/main/CoreWar__gpt-5__o3__r15__s1000.yaml rename to configs/pvp/CoreWar__gpt-5__o3__r15__s1000.yaml diff --git a/configs/main/CoreWar__gpt-5__qwen3-coder-plus-2025-09-23__r15__s1000.yaml b/configs/pvp/CoreWar__gpt-5__qwen3-coder-plus-2025-09-23__r15__s1000.yaml similarity index 100% rename from configs/main/CoreWar__gpt-5__qwen3-coder-plus-2025-09-23__r15__s1000.yaml rename to configs/pvp/CoreWar__gpt-5__qwen3-coder-plus-2025-09-23__r15__s1000.yaml diff --git a/configs/main/CoreWar__grok-code-fast-1__o3__r15__s1000.yaml b/configs/pvp/CoreWar__grok-code-fast-1__o3__r15__s1000.yaml similarity index 100% rename from configs/main/CoreWar__grok-code-fast-1__o3__r15__s1000.yaml rename to configs/pvp/CoreWar__grok-code-fast-1__o3__r15__s1000.yaml diff --git a/configs/main/CoreWar__grok-code-fast-1__qwen3-coder-plus-2025-09-23__r15__s1000.yaml b/configs/pvp/CoreWar__grok-code-fast-1__qwen3-coder-plus-2025-09-23__r15__s1000.yaml similarity index 100% rename from configs/main/CoreWar__grok-code-fast-1__qwen3-coder-plus-2025-09-23__r15__s1000.yaml rename to configs/pvp/CoreWar__grok-code-fast-1__qwen3-coder-plus-2025-09-23__r15__s1000.yaml diff --git a/configs/main/CoreWar__o3__qwen3-coder-plus-2025-09-23__r15__s1000.yaml b/configs/pvp/CoreWar__o3__qwen3-coder-plus-2025-09-23__r15__s1000.yaml similarity index 100% rename from configs/main/CoreWar__o3__qwen3-coder-plus-2025-09-23__r15__s1000.yaml rename to configs/pvp/CoreWar__o3__qwen3-coder-plus-2025-09-23__r15__s1000.yaml diff --git a/configs/main/Halite__claude-sonnet-4-20250514__claude-sonnet-4-5-20250929__r15__s250.yaml b/configs/pvp/Halite__claude-sonnet-4-20250514__claude-sonnet-4-5-20250929__r15__s250.yaml similarity index 100% rename from configs/main/Halite__claude-sonnet-4-20250514__claude-sonnet-4-5-20250929__r15__s250.yaml rename to configs/pvp/Halite__claude-sonnet-4-20250514__claude-sonnet-4-5-20250929__r15__s250.yaml diff --git a/configs/main/Halite__claude-sonnet-4-20250514__gemini-2.5-pro__r15__s250.yaml b/configs/pvp/Halite__claude-sonnet-4-20250514__gemini-2.5-pro__r15__s250.yaml similarity index 100% rename from configs/main/Halite__claude-sonnet-4-20250514__gemini-2.5-pro__r15__s250.yaml rename to configs/pvp/Halite__claude-sonnet-4-20250514__gemini-2.5-pro__r15__s250.yaml diff --git a/configs/main/Halite__claude-sonnet-4-20250514__gpt-5-mini__r15__s250.yaml b/configs/pvp/Halite__claude-sonnet-4-20250514__gpt-5-mini__r15__s250.yaml similarity index 100% rename from configs/main/Halite__claude-sonnet-4-20250514__gpt-5-mini__r15__s250.yaml rename to configs/pvp/Halite__claude-sonnet-4-20250514__gpt-5-mini__r15__s250.yaml diff --git a/configs/main/Halite__claude-sonnet-4-20250514__gpt-5__r15__s250.yaml b/configs/pvp/Halite__claude-sonnet-4-20250514__gpt-5__r15__s250.yaml similarity index 100% rename from configs/main/Halite__claude-sonnet-4-20250514__gpt-5__r15__s250.yaml rename to configs/pvp/Halite__claude-sonnet-4-20250514__gpt-5__r15__s250.yaml diff --git a/configs/main/Halite__claude-sonnet-4-20250514__grok-code-fast-1__r15__s250.yaml b/configs/pvp/Halite__claude-sonnet-4-20250514__grok-code-fast-1__r15__s250.yaml similarity index 100% rename from configs/main/Halite__claude-sonnet-4-20250514__grok-code-fast-1__r15__s250.yaml rename to configs/pvp/Halite__claude-sonnet-4-20250514__grok-code-fast-1__r15__s250.yaml diff --git a/configs/main/Halite__claude-sonnet-4-20250514__o3__r15__s250.yaml b/configs/pvp/Halite__claude-sonnet-4-20250514__o3__r15__s250.yaml similarity index 100% rename from configs/main/Halite__claude-sonnet-4-20250514__o3__r15__s250.yaml rename to configs/pvp/Halite__claude-sonnet-4-20250514__o3__r15__s250.yaml diff --git a/configs/main/Halite__claude-sonnet-4-20250514__qwen3-coder-plus-2025-09-23__r15__s250.yaml b/configs/pvp/Halite__claude-sonnet-4-20250514__qwen3-coder-plus-2025-09-23__r15__s250.yaml similarity index 100% rename from configs/main/Halite__claude-sonnet-4-20250514__qwen3-coder-plus-2025-09-23__r15__s250.yaml rename to configs/pvp/Halite__claude-sonnet-4-20250514__qwen3-coder-plus-2025-09-23__r15__s250.yaml diff --git a/configs/main/Halite__claude-sonnet-4-5-20250929__gemini-2.5-pro__r15__s250.yaml b/configs/pvp/Halite__claude-sonnet-4-5-20250929__gemini-2.5-pro__r15__s250.yaml similarity index 100% rename from configs/main/Halite__claude-sonnet-4-5-20250929__gemini-2.5-pro__r15__s250.yaml rename to configs/pvp/Halite__claude-sonnet-4-5-20250929__gemini-2.5-pro__r15__s250.yaml diff --git a/configs/main/Halite__claude-sonnet-4-5-20250929__gpt-5-mini__r15__s250.yaml b/configs/pvp/Halite__claude-sonnet-4-5-20250929__gpt-5-mini__r15__s250.yaml similarity index 100% rename from configs/main/Halite__claude-sonnet-4-5-20250929__gpt-5-mini__r15__s250.yaml rename to configs/pvp/Halite__claude-sonnet-4-5-20250929__gpt-5-mini__r15__s250.yaml diff --git a/configs/main/Halite__claude-sonnet-4-5-20250929__gpt-5__r15__s250.yaml b/configs/pvp/Halite__claude-sonnet-4-5-20250929__gpt-5__r15__s250.yaml similarity index 100% rename from configs/main/Halite__claude-sonnet-4-5-20250929__gpt-5__r15__s250.yaml rename to configs/pvp/Halite__claude-sonnet-4-5-20250929__gpt-5__r15__s250.yaml diff --git a/configs/main/Halite__claude-sonnet-4-5-20250929__grok-code-fast-1__r15__s250.yaml b/configs/pvp/Halite__claude-sonnet-4-5-20250929__grok-code-fast-1__r15__s250.yaml similarity index 100% rename from configs/main/Halite__claude-sonnet-4-5-20250929__grok-code-fast-1__r15__s250.yaml rename to configs/pvp/Halite__claude-sonnet-4-5-20250929__grok-code-fast-1__r15__s250.yaml diff --git a/configs/main/Halite__claude-sonnet-4-5-20250929__o3__r15__s250.yaml b/configs/pvp/Halite__claude-sonnet-4-5-20250929__o3__r15__s250.yaml similarity index 100% rename from configs/main/Halite__claude-sonnet-4-5-20250929__o3__r15__s250.yaml rename to configs/pvp/Halite__claude-sonnet-4-5-20250929__o3__r15__s250.yaml diff --git a/configs/main/Halite__claude-sonnet-4-5-20250929__qwen3-coder-plus-2025-09-23__r15__s250.yaml b/configs/pvp/Halite__claude-sonnet-4-5-20250929__qwen3-coder-plus-2025-09-23__r15__s250.yaml similarity index 100% rename from configs/main/Halite__claude-sonnet-4-5-20250929__qwen3-coder-plus-2025-09-23__r15__s250.yaml rename to configs/pvp/Halite__claude-sonnet-4-5-20250929__qwen3-coder-plus-2025-09-23__r15__s250.yaml diff --git a/configs/main/Halite__gemini-2.5-pro__gpt-5-mini__r15__s250.yaml b/configs/pvp/Halite__gemini-2.5-pro__gpt-5-mini__r15__s250.yaml similarity index 100% rename from configs/main/Halite__gemini-2.5-pro__gpt-5-mini__r15__s250.yaml rename to configs/pvp/Halite__gemini-2.5-pro__gpt-5-mini__r15__s250.yaml diff --git a/configs/main/Halite__gemini-2.5-pro__gpt-5__r15__s250.yaml b/configs/pvp/Halite__gemini-2.5-pro__gpt-5__r15__s250.yaml similarity index 100% rename from configs/main/Halite__gemini-2.5-pro__gpt-5__r15__s250.yaml rename to configs/pvp/Halite__gemini-2.5-pro__gpt-5__r15__s250.yaml diff --git a/configs/main/Halite__gemini-2.5-pro__grok-code-fast-1__r15__s250.yaml b/configs/pvp/Halite__gemini-2.5-pro__grok-code-fast-1__r15__s250.yaml similarity index 100% rename from configs/main/Halite__gemini-2.5-pro__grok-code-fast-1__r15__s250.yaml rename to configs/pvp/Halite__gemini-2.5-pro__grok-code-fast-1__r15__s250.yaml diff --git a/configs/main/Halite__gemini-2.5-pro__o3__r15__s250.yaml b/configs/pvp/Halite__gemini-2.5-pro__o3__r15__s250.yaml similarity index 100% rename from configs/main/Halite__gemini-2.5-pro__o3__r15__s250.yaml rename to configs/pvp/Halite__gemini-2.5-pro__o3__r15__s250.yaml diff --git a/configs/main/Halite__gemini-2.5-pro__qwen3-coder-plus-2025-09-23__r15__s250.yaml b/configs/pvp/Halite__gemini-2.5-pro__qwen3-coder-plus-2025-09-23__r15__s250.yaml similarity index 100% rename from configs/main/Halite__gemini-2.5-pro__qwen3-coder-plus-2025-09-23__r15__s250.yaml rename to configs/pvp/Halite__gemini-2.5-pro__qwen3-coder-plus-2025-09-23__r15__s250.yaml diff --git a/configs/main/Halite__gpt-5-mini__grok-code-fast-1__r15__s250.yaml b/configs/pvp/Halite__gpt-5-mini__grok-code-fast-1__r15__s250.yaml similarity index 100% rename from configs/main/Halite__gpt-5-mini__grok-code-fast-1__r15__s250.yaml rename to configs/pvp/Halite__gpt-5-mini__grok-code-fast-1__r15__s250.yaml diff --git a/configs/main/Halite__gpt-5-mini__o3__r15__s250.yaml b/configs/pvp/Halite__gpt-5-mini__o3__r15__s250.yaml similarity index 100% rename from configs/main/Halite__gpt-5-mini__o3__r15__s250.yaml rename to configs/pvp/Halite__gpt-5-mini__o3__r15__s250.yaml diff --git a/configs/main/Halite__gpt-5-mini__qwen3-coder-plus-2025-09-23__r15__s250.yaml b/configs/pvp/Halite__gpt-5-mini__qwen3-coder-plus-2025-09-23__r15__s250.yaml similarity index 100% rename from configs/main/Halite__gpt-5-mini__qwen3-coder-plus-2025-09-23__r15__s250.yaml rename to configs/pvp/Halite__gpt-5-mini__qwen3-coder-plus-2025-09-23__r15__s250.yaml diff --git a/configs/main/Halite__gpt-5__gpt-5-mini__r15__s250.yaml b/configs/pvp/Halite__gpt-5__gpt-5-mini__r15__s250.yaml similarity index 100% rename from configs/main/Halite__gpt-5__gpt-5-mini__r15__s250.yaml rename to configs/pvp/Halite__gpt-5__gpt-5-mini__r15__s250.yaml diff --git a/configs/main/Halite__gpt-5__grok-code-fast-1__r15__s250.yaml b/configs/pvp/Halite__gpt-5__grok-code-fast-1__r15__s250.yaml similarity index 100% rename from configs/main/Halite__gpt-5__grok-code-fast-1__r15__s250.yaml rename to configs/pvp/Halite__gpt-5__grok-code-fast-1__r15__s250.yaml diff --git a/configs/main/Halite__gpt-5__o3__r15__s250.yaml b/configs/pvp/Halite__gpt-5__o3__r15__s250.yaml similarity index 100% rename from configs/main/Halite__gpt-5__o3__r15__s250.yaml rename to configs/pvp/Halite__gpt-5__o3__r15__s250.yaml diff --git a/configs/main/Halite__gpt-5__qwen3-coder-plus-2025-09-23__r15__s250.yaml b/configs/pvp/Halite__gpt-5__qwen3-coder-plus-2025-09-23__r15__s250.yaml similarity index 100% rename from configs/main/Halite__gpt-5__qwen3-coder-plus-2025-09-23__r15__s250.yaml rename to configs/pvp/Halite__gpt-5__qwen3-coder-plus-2025-09-23__r15__s250.yaml diff --git a/configs/main/Halite__grok-code-fast-1__o3__r15__s250.yaml b/configs/pvp/Halite__grok-code-fast-1__o3__r15__s250.yaml similarity index 100% rename from configs/main/Halite__grok-code-fast-1__o3__r15__s250.yaml rename to configs/pvp/Halite__grok-code-fast-1__o3__r15__s250.yaml diff --git a/configs/main/Halite__grok-code-fast-1__qwen3-coder-plus-2025-09-23__r15__s250.yaml b/configs/pvp/Halite__grok-code-fast-1__qwen3-coder-plus-2025-09-23__r15__s250.yaml similarity index 100% rename from configs/main/Halite__grok-code-fast-1__qwen3-coder-plus-2025-09-23__r15__s250.yaml rename to configs/pvp/Halite__grok-code-fast-1__qwen3-coder-plus-2025-09-23__r15__s250.yaml diff --git a/configs/main/Halite__o3__qwen3-coder-plus-2025-09-23__r15__s250.yaml b/configs/pvp/Halite__o3__qwen3-coder-plus-2025-09-23__r15__s250.yaml similarity index 100% rename from configs/main/Halite__o3__qwen3-coder-plus-2025-09-23__r15__s250.yaml rename to configs/pvp/Halite__o3__qwen3-coder-plus-2025-09-23__r15__s250.yaml diff --git a/configs/main/HuskyBench__claude-sonnet-4-20250514__claude-sonnet-4-5-20250929__r15__s100.yaml b/configs/pvp/HuskyBench__claude-sonnet-4-20250514__claude-sonnet-4-5-20250929__r15__s100.yaml similarity index 100% rename from configs/main/HuskyBench__claude-sonnet-4-20250514__claude-sonnet-4-5-20250929__r15__s100.yaml rename to configs/pvp/HuskyBench__claude-sonnet-4-20250514__claude-sonnet-4-5-20250929__r15__s100.yaml diff --git a/configs/main/HuskyBench__claude-sonnet-4-20250514__gemini-2.5-pro__r15__s100.yaml b/configs/pvp/HuskyBench__claude-sonnet-4-20250514__gemini-2.5-pro__r15__s100.yaml similarity index 100% rename from configs/main/HuskyBench__claude-sonnet-4-20250514__gemini-2.5-pro__r15__s100.yaml rename to configs/pvp/HuskyBench__claude-sonnet-4-20250514__gemini-2.5-pro__r15__s100.yaml diff --git a/configs/main/HuskyBench__claude-sonnet-4-20250514__gpt-5-mini__r15__s100.yaml b/configs/pvp/HuskyBench__claude-sonnet-4-20250514__gpt-5-mini__r15__s100.yaml similarity index 100% rename from configs/main/HuskyBench__claude-sonnet-4-20250514__gpt-5-mini__r15__s100.yaml rename to configs/pvp/HuskyBench__claude-sonnet-4-20250514__gpt-5-mini__r15__s100.yaml diff --git a/configs/main/HuskyBench__claude-sonnet-4-20250514__gpt-5__r15__s100.yaml b/configs/pvp/HuskyBench__claude-sonnet-4-20250514__gpt-5__r15__s100.yaml similarity index 100% rename from configs/main/HuskyBench__claude-sonnet-4-20250514__gpt-5__r15__s100.yaml rename to configs/pvp/HuskyBench__claude-sonnet-4-20250514__gpt-5__r15__s100.yaml diff --git a/configs/main/HuskyBench__claude-sonnet-4-20250514__grok-code-fast-1__r15__s100.yaml b/configs/pvp/HuskyBench__claude-sonnet-4-20250514__grok-code-fast-1__r15__s100.yaml similarity index 100% rename from configs/main/HuskyBench__claude-sonnet-4-20250514__grok-code-fast-1__r15__s100.yaml rename to configs/pvp/HuskyBench__claude-sonnet-4-20250514__grok-code-fast-1__r15__s100.yaml diff --git a/configs/main/HuskyBench__claude-sonnet-4-20250514__o3__r15__s100.yaml b/configs/pvp/HuskyBench__claude-sonnet-4-20250514__o3__r15__s100.yaml similarity index 100% rename from configs/main/HuskyBench__claude-sonnet-4-20250514__o3__r15__s100.yaml rename to configs/pvp/HuskyBench__claude-sonnet-4-20250514__o3__r15__s100.yaml diff --git a/configs/main/HuskyBench__claude-sonnet-4-20250514__qwen3-coder-plus-2025-09-23__r15__s100.yaml b/configs/pvp/HuskyBench__claude-sonnet-4-20250514__qwen3-coder-plus-2025-09-23__r15__s100.yaml similarity index 100% rename from configs/main/HuskyBench__claude-sonnet-4-20250514__qwen3-coder-plus-2025-09-23__r15__s100.yaml rename to configs/pvp/HuskyBench__claude-sonnet-4-20250514__qwen3-coder-plus-2025-09-23__r15__s100.yaml diff --git a/configs/main/HuskyBench__claude-sonnet-4-5-20250929__gemini-2.5-pro__r15__s100.yaml b/configs/pvp/HuskyBench__claude-sonnet-4-5-20250929__gemini-2.5-pro__r15__s100.yaml similarity index 100% rename from configs/main/HuskyBench__claude-sonnet-4-5-20250929__gemini-2.5-pro__r15__s100.yaml rename to configs/pvp/HuskyBench__claude-sonnet-4-5-20250929__gemini-2.5-pro__r15__s100.yaml diff --git a/configs/main/HuskyBench__claude-sonnet-4-5-20250929__gpt-5-mini__r15__s100.yaml b/configs/pvp/HuskyBench__claude-sonnet-4-5-20250929__gpt-5-mini__r15__s100.yaml similarity index 100% rename from configs/main/HuskyBench__claude-sonnet-4-5-20250929__gpt-5-mini__r15__s100.yaml rename to configs/pvp/HuskyBench__claude-sonnet-4-5-20250929__gpt-5-mini__r15__s100.yaml diff --git a/configs/main/HuskyBench__claude-sonnet-4-5-20250929__gpt-5__r15__s100.yaml b/configs/pvp/HuskyBench__claude-sonnet-4-5-20250929__gpt-5__r15__s100.yaml similarity index 100% rename from configs/main/HuskyBench__claude-sonnet-4-5-20250929__gpt-5__r15__s100.yaml rename to configs/pvp/HuskyBench__claude-sonnet-4-5-20250929__gpt-5__r15__s100.yaml diff --git a/configs/main/HuskyBench__claude-sonnet-4-5-20250929__grok-code-fast-1__r15__s100.yaml b/configs/pvp/HuskyBench__claude-sonnet-4-5-20250929__grok-code-fast-1__r15__s100.yaml similarity index 100% rename from configs/main/HuskyBench__claude-sonnet-4-5-20250929__grok-code-fast-1__r15__s100.yaml rename to configs/pvp/HuskyBench__claude-sonnet-4-5-20250929__grok-code-fast-1__r15__s100.yaml diff --git a/configs/main/HuskyBench__claude-sonnet-4-5-20250929__o3__r15__s100.yaml b/configs/pvp/HuskyBench__claude-sonnet-4-5-20250929__o3__r15__s100.yaml similarity index 100% rename from configs/main/HuskyBench__claude-sonnet-4-5-20250929__o3__r15__s100.yaml rename to configs/pvp/HuskyBench__claude-sonnet-4-5-20250929__o3__r15__s100.yaml diff --git a/configs/main/HuskyBench__claude-sonnet-4-5-20250929__qwen3-coder-plus-2025-09-23__r15__s100.yaml b/configs/pvp/HuskyBench__claude-sonnet-4-5-20250929__qwen3-coder-plus-2025-09-23__r15__s100.yaml similarity index 100% rename from configs/main/HuskyBench__claude-sonnet-4-5-20250929__qwen3-coder-plus-2025-09-23__r15__s100.yaml rename to configs/pvp/HuskyBench__claude-sonnet-4-5-20250929__qwen3-coder-plus-2025-09-23__r15__s100.yaml diff --git a/configs/main/HuskyBench__gemini-2.5-pro__gpt-5-mini__r15__s100.yaml b/configs/pvp/HuskyBench__gemini-2.5-pro__gpt-5-mini__r15__s100.yaml similarity index 100% rename from configs/main/HuskyBench__gemini-2.5-pro__gpt-5-mini__r15__s100.yaml rename to configs/pvp/HuskyBench__gemini-2.5-pro__gpt-5-mini__r15__s100.yaml diff --git a/configs/main/HuskyBench__gemini-2.5-pro__gpt-5__r15__s100.yaml b/configs/pvp/HuskyBench__gemini-2.5-pro__gpt-5__r15__s100.yaml similarity index 100% rename from configs/main/HuskyBench__gemini-2.5-pro__gpt-5__r15__s100.yaml rename to configs/pvp/HuskyBench__gemini-2.5-pro__gpt-5__r15__s100.yaml diff --git a/configs/main/HuskyBench__gemini-2.5-pro__grok-code-fast-1__r15__s100.yaml b/configs/pvp/HuskyBench__gemini-2.5-pro__grok-code-fast-1__r15__s100.yaml similarity index 100% rename from configs/main/HuskyBench__gemini-2.5-pro__grok-code-fast-1__r15__s100.yaml rename to configs/pvp/HuskyBench__gemini-2.5-pro__grok-code-fast-1__r15__s100.yaml diff --git a/configs/main/HuskyBench__gemini-2.5-pro__o3__r15__s100.yaml b/configs/pvp/HuskyBench__gemini-2.5-pro__o3__r15__s100.yaml similarity index 100% rename from configs/main/HuskyBench__gemini-2.5-pro__o3__r15__s100.yaml rename to configs/pvp/HuskyBench__gemini-2.5-pro__o3__r15__s100.yaml diff --git a/configs/main/HuskyBench__gemini-2.5-pro__qwen3-coder-plus-2025-09-23__r15__s100.yaml b/configs/pvp/HuskyBench__gemini-2.5-pro__qwen3-coder-plus-2025-09-23__r15__s100.yaml similarity index 100% rename from configs/main/HuskyBench__gemini-2.5-pro__qwen3-coder-plus-2025-09-23__r15__s100.yaml rename to configs/pvp/HuskyBench__gemini-2.5-pro__qwen3-coder-plus-2025-09-23__r15__s100.yaml diff --git a/configs/main/HuskyBench__gpt-5-mini__grok-code-fast-1__r15__s100.yaml b/configs/pvp/HuskyBench__gpt-5-mini__grok-code-fast-1__r15__s100.yaml similarity index 100% rename from configs/main/HuskyBench__gpt-5-mini__grok-code-fast-1__r15__s100.yaml rename to configs/pvp/HuskyBench__gpt-5-mini__grok-code-fast-1__r15__s100.yaml diff --git a/configs/main/HuskyBench__gpt-5-mini__o3__r15__s100.yaml b/configs/pvp/HuskyBench__gpt-5-mini__o3__r15__s100.yaml similarity index 100% rename from configs/main/HuskyBench__gpt-5-mini__o3__r15__s100.yaml rename to configs/pvp/HuskyBench__gpt-5-mini__o3__r15__s100.yaml diff --git a/configs/main/HuskyBench__gpt-5-mini__qwen3-coder-plus-2025-09-23__r15__s100.yaml b/configs/pvp/HuskyBench__gpt-5-mini__qwen3-coder-plus-2025-09-23__r15__s100.yaml similarity index 100% rename from configs/main/HuskyBench__gpt-5-mini__qwen3-coder-plus-2025-09-23__r15__s100.yaml rename to configs/pvp/HuskyBench__gpt-5-mini__qwen3-coder-plus-2025-09-23__r15__s100.yaml diff --git a/configs/main/HuskyBench__gpt-5__gpt-5-mini__r15__s100.yaml b/configs/pvp/HuskyBench__gpt-5__gpt-5-mini__r15__s100.yaml similarity index 100% rename from configs/main/HuskyBench__gpt-5__gpt-5-mini__r15__s100.yaml rename to configs/pvp/HuskyBench__gpt-5__gpt-5-mini__r15__s100.yaml diff --git a/configs/main/HuskyBench__gpt-5__grok-code-fast-1__r15__s100.yaml b/configs/pvp/HuskyBench__gpt-5__grok-code-fast-1__r15__s100.yaml similarity index 100% rename from configs/main/HuskyBench__gpt-5__grok-code-fast-1__r15__s100.yaml rename to configs/pvp/HuskyBench__gpt-5__grok-code-fast-1__r15__s100.yaml diff --git a/configs/main/HuskyBench__gpt-5__o3__r15__s100.yaml b/configs/pvp/HuskyBench__gpt-5__o3__r15__s100.yaml similarity index 100% rename from configs/main/HuskyBench__gpt-5__o3__r15__s100.yaml rename to configs/pvp/HuskyBench__gpt-5__o3__r15__s100.yaml diff --git a/configs/main/HuskyBench__gpt-5__qwen3-coder-plus-2025-09-23__r15__s100.yaml b/configs/pvp/HuskyBench__gpt-5__qwen3-coder-plus-2025-09-23__r15__s100.yaml similarity index 100% rename from configs/main/HuskyBench__gpt-5__qwen3-coder-plus-2025-09-23__r15__s100.yaml rename to configs/pvp/HuskyBench__gpt-5__qwen3-coder-plus-2025-09-23__r15__s100.yaml diff --git a/configs/main/HuskyBench__grok-code-fast-1__o3__r15__s100.yaml b/configs/pvp/HuskyBench__grok-code-fast-1__o3__r15__s100.yaml similarity index 100% rename from configs/main/HuskyBench__grok-code-fast-1__o3__r15__s100.yaml rename to configs/pvp/HuskyBench__grok-code-fast-1__o3__r15__s100.yaml diff --git a/configs/main/HuskyBench__grok-code-fast-1__qwen3-coder-plus-2025-09-23__r15__s100.yaml b/configs/pvp/HuskyBench__grok-code-fast-1__qwen3-coder-plus-2025-09-23__r15__s100.yaml similarity index 100% rename from configs/main/HuskyBench__grok-code-fast-1__qwen3-coder-plus-2025-09-23__r15__s100.yaml rename to configs/pvp/HuskyBench__grok-code-fast-1__qwen3-coder-plus-2025-09-23__r15__s100.yaml diff --git a/configs/main/HuskyBench__o3__qwen3-coder-plus-2025-09-23__r15__s100.yaml b/configs/pvp/HuskyBench__o3__qwen3-coder-plus-2025-09-23__r15__s100.yaml similarity index 100% rename from configs/main/HuskyBench__o3__qwen3-coder-plus-2025-09-23__r15__s100.yaml rename to configs/pvp/HuskyBench__o3__qwen3-coder-plus-2025-09-23__r15__s100.yaml diff --git a/configs/main/RoboCode__claude-sonnet-4-20250514__claude-sonnet-4-5-20250929__r15__s250.yaml b/configs/pvp/RoboCode__claude-sonnet-4-20250514__claude-sonnet-4-5-20250929__r15__s250.yaml similarity index 100% rename from configs/main/RoboCode__claude-sonnet-4-20250514__claude-sonnet-4-5-20250929__r15__s250.yaml rename to configs/pvp/RoboCode__claude-sonnet-4-20250514__claude-sonnet-4-5-20250929__r15__s250.yaml diff --git a/configs/main/RoboCode__claude-sonnet-4-20250514__gemini-2.5-pro__r15__s250.yaml b/configs/pvp/RoboCode__claude-sonnet-4-20250514__gemini-2.5-pro__r15__s250.yaml similarity index 100% rename from configs/main/RoboCode__claude-sonnet-4-20250514__gemini-2.5-pro__r15__s250.yaml rename to configs/pvp/RoboCode__claude-sonnet-4-20250514__gemini-2.5-pro__r15__s250.yaml diff --git a/configs/main/RoboCode__claude-sonnet-4-20250514__gpt-5-mini__r15__s250.yaml b/configs/pvp/RoboCode__claude-sonnet-4-20250514__gpt-5-mini__r15__s250.yaml similarity index 100% rename from configs/main/RoboCode__claude-sonnet-4-20250514__gpt-5-mini__r15__s250.yaml rename to configs/pvp/RoboCode__claude-sonnet-4-20250514__gpt-5-mini__r15__s250.yaml diff --git a/configs/main/RoboCode__claude-sonnet-4-20250514__gpt-5__r15__s250.yaml b/configs/pvp/RoboCode__claude-sonnet-4-20250514__gpt-5__r15__s250.yaml similarity index 100% rename from configs/main/RoboCode__claude-sonnet-4-20250514__gpt-5__r15__s250.yaml rename to configs/pvp/RoboCode__claude-sonnet-4-20250514__gpt-5__r15__s250.yaml diff --git a/configs/main/RoboCode__claude-sonnet-4-20250514__grok-code-fast-1__r15__s250.yaml b/configs/pvp/RoboCode__claude-sonnet-4-20250514__grok-code-fast-1__r15__s250.yaml similarity index 100% rename from configs/main/RoboCode__claude-sonnet-4-20250514__grok-code-fast-1__r15__s250.yaml rename to configs/pvp/RoboCode__claude-sonnet-4-20250514__grok-code-fast-1__r15__s250.yaml diff --git a/configs/main/RoboCode__claude-sonnet-4-20250514__o3__r15__s250.yaml b/configs/pvp/RoboCode__claude-sonnet-4-20250514__o3__r15__s250.yaml similarity index 100% rename from configs/main/RoboCode__claude-sonnet-4-20250514__o3__r15__s250.yaml rename to configs/pvp/RoboCode__claude-sonnet-4-20250514__o3__r15__s250.yaml diff --git a/configs/main/RoboCode__claude-sonnet-4-20250514__qwen3-coder-plus-2025-09-23__r15__s250.yaml b/configs/pvp/RoboCode__claude-sonnet-4-20250514__qwen3-coder-plus-2025-09-23__r15__s250.yaml similarity index 100% rename from configs/main/RoboCode__claude-sonnet-4-20250514__qwen3-coder-plus-2025-09-23__r15__s250.yaml rename to configs/pvp/RoboCode__claude-sonnet-4-20250514__qwen3-coder-plus-2025-09-23__r15__s250.yaml diff --git a/configs/main/RoboCode__claude-sonnet-4-5-20250929__gemini-2.5-pro__r15__s250.yaml b/configs/pvp/RoboCode__claude-sonnet-4-5-20250929__gemini-2.5-pro__r15__s250.yaml similarity index 100% rename from configs/main/RoboCode__claude-sonnet-4-5-20250929__gemini-2.5-pro__r15__s250.yaml rename to configs/pvp/RoboCode__claude-sonnet-4-5-20250929__gemini-2.5-pro__r15__s250.yaml diff --git a/configs/main/RoboCode__claude-sonnet-4-5-20250929__gpt-5-mini__r15__s250.yaml b/configs/pvp/RoboCode__claude-sonnet-4-5-20250929__gpt-5-mini__r15__s250.yaml similarity index 100% rename from configs/main/RoboCode__claude-sonnet-4-5-20250929__gpt-5-mini__r15__s250.yaml rename to configs/pvp/RoboCode__claude-sonnet-4-5-20250929__gpt-5-mini__r15__s250.yaml diff --git a/configs/main/RoboCode__claude-sonnet-4-5-20250929__gpt-5__r15__s250.yaml b/configs/pvp/RoboCode__claude-sonnet-4-5-20250929__gpt-5__r15__s250.yaml similarity index 100% rename from configs/main/RoboCode__claude-sonnet-4-5-20250929__gpt-5__r15__s250.yaml rename to configs/pvp/RoboCode__claude-sonnet-4-5-20250929__gpt-5__r15__s250.yaml diff --git a/configs/main/RoboCode__claude-sonnet-4-5-20250929__grok-code-fast-1__r15__s250.yaml b/configs/pvp/RoboCode__claude-sonnet-4-5-20250929__grok-code-fast-1__r15__s250.yaml similarity index 100% rename from configs/main/RoboCode__claude-sonnet-4-5-20250929__grok-code-fast-1__r15__s250.yaml rename to configs/pvp/RoboCode__claude-sonnet-4-5-20250929__grok-code-fast-1__r15__s250.yaml diff --git a/configs/main/RoboCode__claude-sonnet-4-5-20250929__o3__r15__s250.yaml b/configs/pvp/RoboCode__claude-sonnet-4-5-20250929__o3__r15__s250.yaml similarity index 100% rename from configs/main/RoboCode__claude-sonnet-4-5-20250929__o3__r15__s250.yaml rename to configs/pvp/RoboCode__claude-sonnet-4-5-20250929__o3__r15__s250.yaml diff --git a/configs/main/RoboCode__claude-sonnet-4-5-20250929__qwen3-coder-plus-2025-09-23__r15__s250.yaml b/configs/pvp/RoboCode__claude-sonnet-4-5-20250929__qwen3-coder-plus-2025-09-23__r15__s250.yaml similarity index 100% rename from configs/main/RoboCode__claude-sonnet-4-5-20250929__qwen3-coder-plus-2025-09-23__r15__s250.yaml rename to configs/pvp/RoboCode__claude-sonnet-4-5-20250929__qwen3-coder-plus-2025-09-23__r15__s250.yaml diff --git a/configs/main/RoboCode__gemini-2.5-pro__gpt-5-mini__r15__s250.yaml b/configs/pvp/RoboCode__gemini-2.5-pro__gpt-5-mini__r15__s250.yaml similarity index 100% rename from configs/main/RoboCode__gemini-2.5-pro__gpt-5-mini__r15__s250.yaml rename to configs/pvp/RoboCode__gemini-2.5-pro__gpt-5-mini__r15__s250.yaml diff --git a/configs/main/RoboCode__gemini-2.5-pro__gpt-5__r15__s250.yaml b/configs/pvp/RoboCode__gemini-2.5-pro__gpt-5__r15__s250.yaml similarity index 100% rename from configs/main/RoboCode__gemini-2.5-pro__gpt-5__r15__s250.yaml rename to configs/pvp/RoboCode__gemini-2.5-pro__gpt-5__r15__s250.yaml diff --git a/configs/main/RoboCode__gemini-2.5-pro__grok-code-fast-1__r15__s250.yaml b/configs/pvp/RoboCode__gemini-2.5-pro__grok-code-fast-1__r15__s250.yaml similarity index 100% rename from configs/main/RoboCode__gemini-2.5-pro__grok-code-fast-1__r15__s250.yaml rename to configs/pvp/RoboCode__gemini-2.5-pro__grok-code-fast-1__r15__s250.yaml diff --git a/configs/main/RoboCode__gemini-2.5-pro__o3__r15__s250.yaml b/configs/pvp/RoboCode__gemini-2.5-pro__o3__r15__s250.yaml similarity index 100% rename from configs/main/RoboCode__gemini-2.5-pro__o3__r15__s250.yaml rename to configs/pvp/RoboCode__gemini-2.5-pro__o3__r15__s250.yaml diff --git a/configs/main/RoboCode__gemini-2.5-pro__qwen3-coder-plus-2025-09-23__r15__s250.yaml b/configs/pvp/RoboCode__gemini-2.5-pro__qwen3-coder-plus-2025-09-23__r15__s250.yaml similarity index 100% rename from configs/main/RoboCode__gemini-2.5-pro__qwen3-coder-plus-2025-09-23__r15__s250.yaml rename to configs/pvp/RoboCode__gemini-2.5-pro__qwen3-coder-plus-2025-09-23__r15__s250.yaml diff --git a/configs/main/RoboCode__gpt-5-mini__grok-code-fast-1__r15__s250.yaml b/configs/pvp/RoboCode__gpt-5-mini__grok-code-fast-1__r15__s250.yaml similarity index 100% rename from configs/main/RoboCode__gpt-5-mini__grok-code-fast-1__r15__s250.yaml rename to configs/pvp/RoboCode__gpt-5-mini__grok-code-fast-1__r15__s250.yaml diff --git a/configs/main/RoboCode__gpt-5-mini__o3__r15__s250.yaml b/configs/pvp/RoboCode__gpt-5-mini__o3__r15__s250.yaml similarity index 100% rename from configs/main/RoboCode__gpt-5-mini__o3__r15__s250.yaml rename to configs/pvp/RoboCode__gpt-5-mini__o3__r15__s250.yaml diff --git a/configs/main/RoboCode__gpt-5-mini__qwen3-coder-plus-2025-09-23__r15__s250.yaml b/configs/pvp/RoboCode__gpt-5-mini__qwen3-coder-plus-2025-09-23__r15__s250.yaml similarity index 100% rename from configs/main/RoboCode__gpt-5-mini__qwen3-coder-plus-2025-09-23__r15__s250.yaml rename to configs/pvp/RoboCode__gpt-5-mini__qwen3-coder-plus-2025-09-23__r15__s250.yaml diff --git a/configs/main/RoboCode__gpt-5__gpt-5-mini__r15__s250.yaml b/configs/pvp/RoboCode__gpt-5__gpt-5-mini__r15__s250.yaml similarity index 100% rename from configs/main/RoboCode__gpt-5__gpt-5-mini__r15__s250.yaml rename to configs/pvp/RoboCode__gpt-5__gpt-5-mini__r15__s250.yaml diff --git a/configs/main/RoboCode__gpt-5__grok-code-fast-1__r15__s250.yaml b/configs/pvp/RoboCode__gpt-5__grok-code-fast-1__r15__s250.yaml similarity index 100% rename from configs/main/RoboCode__gpt-5__grok-code-fast-1__r15__s250.yaml rename to configs/pvp/RoboCode__gpt-5__grok-code-fast-1__r15__s250.yaml diff --git a/configs/main/RoboCode__gpt-5__o3__r15__s250.yaml b/configs/pvp/RoboCode__gpt-5__o3__r15__s250.yaml similarity index 100% rename from configs/main/RoboCode__gpt-5__o3__r15__s250.yaml rename to configs/pvp/RoboCode__gpt-5__o3__r15__s250.yaml diff --git a/configs/main/RoboCode__gpt-5__qwen3-coder-plus-2025-09-23__r15__s250.yaml b/configs/pvp/RoboCode__gpt-5__qwen3-coder-plus-2025-09-23__r15__s250.yaml similarity index 100% rename from configs/main/RoboCode__gpt-5__qwen3-coder-plus-2025-09-23__r15__s250.yaml rename to configs/pvp/RoboCode__gpt-5__qwen3-coder-plus-2025-09-23__r15__s250.yaml diff --git a/configs/main/RoboCode__grok-code-fast-1__o3__r15__s250.yaml b/configs/pvp/RoboCode__grok-code-fast-1__o3__r15__s250.yaml similarity index 100% rename from configs/main/RoboCode__grok-code-fast-1__o3__r15__s250.yaml rename to configs/pvp/RoboCode__grok-code-fast-1__o3__r15__s250.yaml diff --git a/configs/main/RoboCode__grok-code-fast-1__qwen3-coder-plus-2025-09-23__r15__s250.yaml b/configs/pvp/RoboCode__grok-code-fast-1__qwen3-coder-plus-2025-09-23__r15__s250.yaml similarity index 100% rename from configs/main/RoboCode__grok-code-fast-1__qwen3-coder-plus-2025-09-23__r15__s250.yaml rename to configs/pvp/RoboCode__grok-code-fast-1__qwen3-coder-plus-2025-09-23__r15__s250.yaml diff --git a/configs/main/RoboCode__o3__qwen3-coder-plus-2025-09-23__r15__s250.yaml b/configs/pvp/RoboCode__o3__qwen3-coder-plus-2025-09-23__r15__s250.yaml similarity index 100% rename from configs/main/RoboCode__o3__qwen3-coder-plus-2025-09-23__r15__s250.yaml rename to configs/pvp/RoboCode__o3__qwen3-coder-plus-2025-09-23__r15__s250.yaml diff --git a/configs/main/RobotRumble__claude-sonnet-4-20250514__claude-sonnet-4-5-20250929__r15__s250.yaml b/configs/pvp/RobotRumble__claude-sonnet-4-20250514__claude-sonnet-4-5-20250929__r15__s250.yaml similarity index 100% rename from configs/main/RobotRumble__claude-sonnet-4-20250514__claude-sonnet-4-5-20250929__r15__s250.yaml rename to configs/pvp/RobotRumble__claude-sonnet-4-20250514__claude-sonnet-4-5-20250929__r15__s250.yaml diff --git a/configs/main/RobotRumble__claude-sonnet-4-20250514__gemini-2.5-pro__r15__s250.yaml b/configs/pvp/RobotRumble__claude-sonnet-4-20250514__gemini-2.5-pro__r15__s250.yaml similarity index 100% rename from configs/main/RobotRumble__claude-sonnet-4-20250514__gemini-2.5-pro__r15__s250.yaml rename to configs/pvp/RobotRumble__claude-sonnet-4-20250514__gemini-2.5-pro__r15__s250.yaml diff --git a/configs/main/RobotRumble__claude-sonnet-4-20250514__gpt-5-mini__r15__s250.yaml b/configs/pvp/RobotRumble__claude-sonnet-4-20250514__gpt-5-mini__r15__s250.yaml similarity index 100% rename from configs/main/RobotRumble__claude-sonnet-4-20250514__gpt-5-mini__r15__s250.yaml rename to configs/pvp/RobotRumble__claude-sonnet-4-20250514__gpt-5-mini__r15__s250.yaml diff --git a/configs/main/RobotRumble__claude-sonnet-4-20250514__gpt-5__r15__s250.yaml b/configs/pvp/RobotRumble__claude-sonnet-4-20250514__gpt-5__r15__s250.yaml similarity index 100% rename from configs/main/RobotRumble__claude-sonnet-4-20250514__gpt-5__r15__s250.yaml rename to configs/pvp/RobotRumble__claude-sonnet-4-20250514__gpt-5__r15__s250.yaml diff --git a/configs/main/RobotRumble__claude-sonnet-4-20250514__grok-code-fast-1__r15__s250.yaml b/configs/pvp/RobotRumble__claude-sonnet-4-20250514__grok-code-fast-1__r15__s250.yaml similarity index 100% rename from configs/main/RobotRumble__claude-sonnet-4-20250514__grok-code-fast-1__r15__s250.yaml rename to configs/pvp/RobotRumble__claude-sonnet-4-20250514__grok-code-fast-1__r15__s250.yaml diff --git a/configs/main/RobotRumble__claude-sonnet-4-20250514__o3__r15__s250.yaml b/configs/pvp/RobotRumble__claude-sonnet-4-20250514__o3__r15__s250.yaml similarity index 100% rename from configs/main/RobotRumble__claude-sonnet-4-20250514__o3__r15__s250.yaml rename to configs/pvp/RobotRumble__claude-sonnet-4-20250514__o3__r15__s250.yaml diff --git a/configs/main/RobotRumble__claude-sonnet-4-20250514__qwen3-coder-plus-2025-09-23__r15__s250.yaml b/configs/pvp/RobotRumble__claude-sonnet-4-20250514__qwen3-coder-plus-2025-09-23__r15__s250.yaml similarity index 100% rename from configs/main/RobotRumble__claude-sonnet-4-20250514__qwen3-coder-plus-2025-09-23__r15__s250.yaml rename to configs/pvp/RobotRumble__claude-sonnet-4-20250514__qwen3-coder-plus-2025-09-23__r15__s250.yaml diff --git a/configs/main/RobotRumble__claude-sonnet-4-5-20250929__gemini-2.5-pro__r15__s250.yaml b/configs/pvp/RobotRumble__claude-sonnet-4-5-20250929__gemini-2.5-pro__r15__s250.yaml similarity index 100% rename from configs/main/RobotRumble__claude-sonnet-4-5-20250929__gemini-2.5-pro__r15__s250.yaml rename to configs/pvp/RobotRumble__claude-sonnet-4-5-20250929__gemini-2.5-pro__r15__s250.yaml diff --git a/configs/main/RobotRumble__claude-sonnet-4-5-20250929__gpt-5-mini__r15__s250.yaml b/configs/pvp/RobotRumble__claude-sonnet-4-5-20250929__gpt-5-mini__r15__s250.yaml similarity index 100% rename from configs/main/RobotRumble__claude-sonnet-4-5-20250929__gpt-5-mini__r15__s250.yaml rename to configs/pvp/RobotRumble__claude-sonnet-4-5-20250929__gpt-5-mini__r15__s250.yaml diff --git a/configs/main/RobotRumble__claude-sonnet-4-5-20250929__gpt-5__r15__s250.yaml b/configs/pvp/RobotRumble__claude-sonnet-4-5-20250929__gpt-5__r15__s250.yaml similarity index 100% rename from configs/main/RobotRumble__claude-sonnet-4-5-20250929__gpt-5__r15__s250.yaml rename to configs/pvp/RobotRumble__claude-sonnet-4-5-20250929__gpt-5__r15__s250.yaml diff --git a/configs/main/RobotRumble__claude-sonnet-4-5-20250929__grok-code-fast-1__r15__s250.yaml b/configs/pvp/RobotRumble__claude-sonnet-4-5-20250929__grok-code-fast-1__r15__s250.yaml similarity index 100% rename from configs/main/RobotRumble__claude-sonnet-4-5-20250929__grok-code-fast-1__r15__s250.yaml rename to configs/pvp/RobotRumble__claude-sonnet-4-5-20250929__grok-code-fast-1__r15__s250.yaml diff --git a/configs/main/RobotRumble__claude-sonnet-4-5-20250929__o3__r15__s250.yaml b/configs/pvp/RobotRumble__claude-sonnet-4-5-20250929__o3__r15__s250.yaml similarity index 100% rename from configs/main/RobotRumble__claude-sonnet-4-5-20250929__o3__r15__s250.yaml rename to configs/pvp/RobotRumble__claude-sonnet-4-5-20250929__o3__r15__s250.yaml diff --git a/configs/main/RobotRumble__claude-sonnet-4-5-20250929__qwen3-coder-plus-2025-09-23__r15__s250.yaml b/configs/pvp/RobotRumble__claude-sonnet-4-5-20250929__qwen3-coder-plus-2025-09-23__r15__s250.yaml similarity index 100% rename from configs/main/RobotRumble__claude-sonnet-4-5-20250929__qwen3-coder-plus-2025-09-23__r15__s250.yaml rename to configs/pvp/RobotRumble__claude-sonnet-4-5-20250929__qwen3-coder-plus-2025-09-23__r15__s250.yaml diff --git a/configs/main/RobotRumble__gemini-2.5-pro__gpt-5-mini__r15__s250.yaml b/configs/pvp/RobotRumble__gemini-2.5-pro__gpt-5-mini__r15__s250.yaml similarity index 100% rename from configs/main/RobotRumble__gemini-2.5-pro__gpt-5-mini__r15__s250.yaml rename to configs/pvp/RobotRumble__gemini-2.5-pro__gpt-5-mini__r15__s250.yaml diff --git a/configs/main/RobotRumble__gemini-2.5-pro__gpt-5__r15__s250.yaml b/configs/pvp/RobotRumble__gemini-2.5-pro__gpt-5__r15__s250.yaml similarity index 100% rename from configs/main/RobotRumble__gemini-2.5-pro__gpt-5__r15__s250.yaml rename to configs/pvp/RobotRumble__gemini-2.5-pro__gpt-5__r15__s250.yaml diff --git a/configs/main/RobotRumble__gemini-2.5-pro__grok-code-fast-1__r15__s250.yaml b/configs/pvp/RobotRumble__gemini-2.5-pro__grok-code-fast-1__r15__s250.yaml similarity index 100% rename from configs/main/RobotRumble__gemini-2.5-pro__grok-code-fast-1__r15__s250.yaml rename to configs/pvp/RobotRumble__gemini-2.5-pro__grok-code-fast-1__r15__s250.yaml diff --git a/configs/main/RobotRumble__gemini-2.5-pro__o3__r15__s250.yaml b/configs/pvp/RobotRumble__gemini-2.5-pro__o3__r15__s250.yaml similarity index 100% rename from configs/main/RobotRumble__gemini-2.5-pro__o3__r15__s250.yaml rename to configs/pvp/RobotRumble__gemini-2.5-pro__o3__r15__s250.yaml diff --git a/configs/main/RobotRumble__gemini-2.5-pro__qwen3-coder-plus-2025-09-23__r15__s250.yaml b/configs/pvp/RobotRumble__gemini-2.5-pro__qwen3-coder-plus-2025-09-23__r15__s250.yaml similarity index 100% rename from configs/main/RobotRumble__gemini-2.5-pro__qwen3-coder-plus-2025-09-23__r15__s250.yaml rename to configs/pvp/RobotRumble__gemini-2.5-pro__qwen3-coder-plus-2025-09-23__r15__s250.yaml diff --git a/configs/main/RobotRumble__gpt-5-mini__grok-code-fast-1__r15__s250.yaml b/configs/pvp/RobotRumble__gpt-5-mini__grok-code-fast-1__r15__s250.yaml similarity index 100% rename from configs/main/RobotRumble__gpt-5-mini__grok-code-fast-1__r15__s250.yaml rename to configs/pvp/RobotRumble__gpt-5-mini__grok-code-fast-1__r15__s250.yaml diff --git a/configs/main/RobotRumble__gpt-5-mini__o3__r15__s250.yaml b/configs/pvp/RobotRumble__gpt-5-mini__o3__r15__s250.yaml similarity index 100% rename from configs/main/RobotRumble__gpt-5-mini__o3__r15__s250.yaml rename to configs/pvp/RobotRumble__gpt-5-mini__o3__r15__s250.yaml diff --git a/configs/main/RobotRumble__gpt-5-mini__qwen3-coder-plus-2025-09-23__r15__s250.yaml b/configs/pvp/RobotRumble__gpt-5-mini__qwen3-coder-plus-2025-09-23__r15__s250.yaml similarity index 100% rename from configs/main/RobotRumble__gpt-5-mini__qwen3-coder-plus-2025-09-23__r15__s250.yaml rename to configs/pvp/RobotRumble__gpt-5-mini__qwen3-coder-plus-2025-09-23__r15__s250.yaml diff --git a/configs/main/RobotRumble__gpt-5__gpt-5-mini__r15__s250.yaml b/configs/pvp/RobotRumble__gpt-5__gpt-5-mini__r15__s250.yaml similarity index 100% rename from configs/main/RobotRumble__gpt-5__gpt-5-mini__r15__s250.yaml rename to configs/pvp/RobotRumble__gpt-5__gpt-5-mini__r15__s250.yaml diff --git a/configs/main/RobotRumble__gpt-5__grok-code-fast-1__r15__s250.yaml b/configs/pvp/RobotRumble__gpt-5__grok-code-fast-1__r15__s250.yaml similarity index 100% rename from configs/main/RobotRumble__gpt-5__grok-code-fast-1__r15__s250.yaml rename to configs/pvp/RobotRumble__gpt-5__grok-code-fast-1__r15__s250.yaml diff --git a/configs/main/RobotRumble__gpt-5__o3__r15__s250.yaml b/configs/pvp/RobotRumble__gpt-5__o3__r15__s250.yaml similarity index 100% rename from configs/main/RobotRumble__gpt-5__o3__r15__s250.yaml rename to configs/pvp/RobotRumble__gpt-5__o3__r15__s250.yaml diff --git a/configs/main/RobotRumble__gpt-5__qwen3-coder-plus-2025-09-23__r15__s250.yaml b/configs/pvp/RobotRumble__gpt-5__qwen3-coder-plus-2025-09-23__r15__s250.yaml similarity index 100% rename from configs/main/RobotRumble__gpt-5__qwen3-coder-plus-2025-09-23__r15__s250.yaml rename to configs/pvp/RobotRumble__gpt-5__qwen3-coder-plus-2025-09-23__r15__s250.yaml diff --git a/configs/main/RobotRumble__grok-code-fast-1__o3__r15__s250.yaml b/configs/pvp/RobotRumble__grok-code-fast-1__o3__r15__s250.yaml similarity index 100% rename from configs/main/RobotRumble__grok-code-fast-1__o3__r15__s250.yaml rename to configs/pvp/RobotRumble__grok-code-fast-1__o3__r15__s250.yaml diff --git a/configs/main/RobotRumble__grok-code-fast-1__qwen3-coder-plus-2025-09-23__r15__s250.yaml b/configs/pvp/RobotRumble__grok-code-fast-1__qwen3-coder-plus-2025-09-23__r15__s250.yaml similarity index 100% rename from configs/main/RobotRumble__grok-code-fast-1__qwen3-coder-plus-2025-09-23__r15__s250.yaml rename to configs/pvp/RobotRumble__grok-code-fast-1__qwen3-coder-plus-2025-09-23__r15__s250.yaml diff --git a/configs/main/RobotRumble__o3__qwen3-coder-plus-2025-09-23__r15__s250.yaml b/configs/pvp/RobotRumble__o3__qwen3-coder-plus-2025-09-23__r15__s250.yaml similarity index 100% rename from configs/main/RobotRumble__o3__qwen3-coder-plus-2025-09-23__r15__s250.yaml rename to configs/pvp/RobotRumble__o3__qwen3-coder-plus-2025-09-23__r15__s250.yaml diff --git a/docs/quickstart.md b/docs/quickstart.md index 4d25859b..748ad743 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -110,8 +110,8 @@ CodeClash configs are organized into tiers: | Directory | Purpose | LLM Cost | Use When | |-----------|---------|----------|----------| | `configs/test/` | Smoke tests with dummy agents | Free | Verifying setup works | -| `configs/examples/` | Short tournaments (5 rounds) | Low | Learning, quick experiments | -| `configs/main/` | Full benchmark runs (15 rounds) | High | Reproducing paper results | +| `configs/examples/` | Single-player & minimal per-arena samples | Low | Trying one arena or mode | +| `configs/pvp/` | Full benchmark runs (15 rounds) | High | Reproducing paper results | | `configs/ablations/` | Specialized experiments | Varies | Research ablations | ### Test Configs (Free) @@ -122,31 +122,22 @@ No LLM API calls - uses dummy agents that make no changes: uv run codeclash run configs/test/battlesnake.yaml ``` -### Example Configs (Quick Experiments) +### PvP Configs (Full Benchmarks) -Short 5-round tournaments for learning and experimentation: +Full 15-round model-vs-model tournaments, as used in the paper: ```bash -# Claude Sonnet 4.5 vs o3 in BattleSnake (5 rounds) -uv run codeclash run configs/examples/BattleSnake__claude-sonnet-4-5-20250929__o3__r5__s1000.yaml +# Claude Sonnet 4.5 vs o3 in BattleSnake +uv run codeclash run configs/pvp/BattleSnake__claude-sonnet-4-5-20250929__o3__r15__s1000.yaml # Same matchup in other arenas -uv run codeclash run configs/examples/CoreWar__claude-sonnet-4-5-20250929__o3__r5__s1000.yaml -uv run codeclash run configs/examples/Halite__claude-sonnet-4-5-20250929__o3__r5__s250.yaml -uv run codeclash run configs/examples/RoboCode__claude-sonnet-4-5-20250929__o3__r5__s250.yaml -``` - -### Main Configs (Full Benchmarks) - -Full 15-round tournaments used in the paper: - -```bash -# Full BattleSnake tournament -uv run codeclash run configs/main/BattleSnake__claude-sonnet-4-5-20250929__o3__r15__s1000.yaml +uv run codeclash run configs/pvp/CoreWar__claude-sonnet-4-5-20250929__o3__r15__s1000.yaml +uv run codeclash run configs/pvp/Halite__claude-sonnet-4-5-20250929__o3__r15__s250.yaml +uv run codeclash run configs/pvp/RoboCode__claude-sonnet-4-5-20250929__o3__r15__s250.yaml ``` !!! warning "Cost Warning" - Main configs run 15 rounds with real LLM agents. Expect significant API costs depending on your model choices. + PvP configs run 15 rounds with real LLM agents. Expect significant API costs depending on your model choices. ## Viewing Results @@ -175,8 +166,8 @@ The viewer shows: ```bash # 1. Make sure you have API keys in .env -# 2. Run a short example tournament -uv run codeclash run configs/examples/BattleSnake__claude-sonnet-4-5-20250929__o3__r5__s1000.yaml +# 2. Run a tournament +uv run codeclash run configs/pvp/BattleSnake__claude-sonnet-4-5-20250929__o3__r15__s1000.yaml # 3. View results uv run python scripts/run_viewer.py @@ -186,18 +177,18 @@ uv run python scripts/run_viewer.py ```bash # CoreWar - Assembly-like programming battle -uv run codeclash run configs/examples/CoreWar__claude-sonnet-4-5-20250929__o3__r5__s1000.yaml +uv run codeclash run configs/pvp/CoreWar__claude-sonnet-4-5-20250929__o3__r15__s1000.yaml # RobotRumble - Multi-robot combat -uv run codeclash run configs/examples/RobotRumble__claude-sonnet-4-5-20250929__o3__r5__s250.yaml +uv run codeclash run configs/pvp/RobotRumble__claude-sonnet-4-5-20250929__o3__r15__s250.yaml ``` ### Create a custom matchup -Copy an example config and modify: +Copy a config and modify: ```bash -cp configs/examples/BattleSnake__claude-sonnet-4-5-20250929__o3__r5__s1000.yaml configs/my_tournament.yaml +cp configs/pvp/BattleSnake__claude-sonnet-4-5-20250929__o3__r15__s1000.yaml configs/my_tournament.yaml # Edit configs/my_tournament.yaml to change models, rounds, etc. uv run codeclash run configs/my_tournament.yaml ``` diff --git a/docs/reference/tournament/single_player.md b/docs/reference/tournament/single_player.md index 1cdeadff..d52398db 100644 --- a/docs/reference/tournament/single_player.md +++ b/docs/reference/tournament/single_player.md @@ -30,7 +30,7 @@ players: ## Running a SinglePlayer Tournament ```bash -python main_single_player.py configs/examples/battlesnake_single_player.yaml +uv run python scripts/main_single_player.py configs/examples/BattleSnake_single_player.yaml ``` ## Implementation diff --git a/docs/usage/codebase-tour.md b/docs/usage/codebase-tour.md index fe6eabfc..8d8fbada 100644 --- a/docs/usage/codebase-tour.md +++ b/docs/usage/codebase-tour.md @@ -248,7 +248,7 @@ Shared helper functions: 5. **Create example configs:** - `configs/test/myarena.yaml` (dummy agents) - - `configs/examples/MyArena__model1__model2__r5__s100.yaml` + - `configs/pvp/MyArena__model1__model2__r15__s100.yaml` ### Adding a New Agent Type diff --git a/docs/usage/tournaments.md b/docs/usage/tournaments.md index 03e10931..9f27f79f 100644 --- a/docs/usage/tournaments.md +++ b/docs/usage/tournaments.md @@ -28,18 +28,18 @@ uv run codeclash run [options] ```bash # Basic run -uv run codeclash run configs/examples/BattleSnake__claude-sonnet-4-5-20250929__o3__r5__s1000.yaml +uv run codeclash run configs/pvp/BattleSnake__claude-sonnet-4-5-20250929__o3__r15__s1000.yaml # Keep containers for debugging uv run codeclash run configs/test/battlesnake.yaml -k # Custom output directory with suffix -uv run codeclash run configs/examples/BattleSnake__claude-sonnet-4-5-20250929__o3__r5__s1000.yaml \ +uv run codeclash run configs/pvp/BattleSnake__claude-sonnet-4-5-20250929__o3__r15__s1000.yaml \ -o ./my_experiments \ -s experiment1 # Push final codebases to GitHub -uv run codeclash run configs/examples/BattleSnake__claude-sonnet-4-5-20250929__o3__r5__s1000.yaml -p +uv run codeclash run configs/pvp/BattleSnake__claude-sonnet-4-5-20250929__o3__r15__s1000.yaml -p ``` ## Configuration Anatomy @@ -260,14 +260,14 @@ Example: `PvpTournament.BattleSnake.r5.s1000.p2.claude-sonnet-4-5.o3.24121014302 ```bash # BattleSnake: Claude Sonnet 4.5 vs o3 (15 rounds) -uv run codeclash run configs/main/BattleSnake__claude-sonnet-4-5-20250929__o3__r15__s1000.yaml +uv run codeclash run configs/pvp/BattleSnake__claude-sonnet-4-5-20250929__o3__r15__s1000.yaml ``` ### Run all arenas for a matchup ```bash for arena in BattleSnake CoreWar Halite RoboCode RobotRumble; do - uv run codeclash run "configs/main/${arena}__claude-sonnet-4-5-20250929__o3__r15__s1000.yaml" + uv run codeclash run "configs/pvp/${arena}__claude-sonnet-4-5-20250929__o3__r15__s1000.yaml" done ``` @@ -299,7 +299,7 @@ uv run codeclash run configs/my_config_b.yaml -s variantB #!/bin/bash models=("claude-sonnet-4-5-20250929" "gpt-5" "gemini-2.5-pro") for model in "${models[@]}"; do - config="configs/main/BattleSnake__${model}__o3__r15__s1000.yaml" + config="configs/pvp/BattleSnake__${model}__o3__r15__s1000.yaml" if [ -f "$config" ]; then uv run codeclash run "$config" fi diff --git a/pyproject.toml b/pyproject.toml index 1a420f81..4f77404b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,6 +48,7 @@ dev = [ "Werkzeug", "frozen-flask", "anthropic", + "matplotlib", # analysis plots + elo ranking (codeclash.analysis) ] aws = [ "boto3", diff --git a/scripts/run_multiple_pvp.sh b/scripts/run_multiple_pvp.sh index 33c10165..50352f51 100755 --- a/scripts/run_multiple_pvp.sh +++ b/scripts/run_multiple_pvp.sh @@ -3,7 +3,7 @@ # Check if argument is provided if [ $# -eq 0 ]; then echo "Usage: $0 " - echo "Example: $0 configs/main/RobotRumble__gemini-2.5-pro__gpt-5-mini__r15__s1000.yaml" + echo "Example: $0 configs/pvp/RobotRumble__gemini-2.5-pro__gpt-5-mini__r15__s1000.yaml" exit 1 fi diff --git a/uv.lock b/uv.lock index c7d039ac..a84ea9e3 100644 --- a/uv.lock +++ b/uv.lock @@ -393,6 +393,7 @@ aws = [ dev = [ { name = "anthropic" }, { name = "frozen-flask" }, + { name = "matplotlib" }, { name = "pre-commit" }, { name = "pytest" }, { name = "pytest-cov" }, @@ -418,6 +419,7 @@ requires-dist = [ { name = "jinja2" }, { name = "litellm" }, { name = "markupsafe" }, + { name = "matplotlib", marker = "extra == 'dev'" }, { name = "mini-swe-agent", specifier = ">=2.4,<3" }, { name = "mkdocs-glightbox", marker = "extra == 'docs'" }, { name = "mkdocs-include-markdown-plugin", marker = "extra == 'docs'" }, @@ -447,6 +449,88 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, ] +[[package]] +name = "contourpy" +version = "1.3.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/58/01/1253e6698a07380cd31a736d248a3f2a50a7c88779a1813da27503cadc2a/contourpy-1.3.3.tar.gz", hash = "sha256:083e12155b210502d0bca491432bb04d56dc3432f95a979b429f2848c3dbe880", size = 13466174, upload-time = "2025-07-26T12:03:12.549Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/91/2e/c4390a31919d8a78b90e8ecf87cd4b4c4f05a5b48d05ec17db8e5404c6f4/contourpy-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:709a48ef9a690e1343202916450bc48b9e51c049b089c7f79a267b46cffcdaa1", size = 288773, upload-time = "2025-07-26T12:01:02.277Z" }, + { url = "https://files.pythonhosted.org/packages/0d/44/c4b0b6095fef4dc9c420e041799591e3b63e9619e3044f7f4f6c21c0ab24/contourpy-1.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:23416f38bfd74d5d28ab8429cc4d63fa67d5068bd711a85edb1c3fb0c3e2f381", size = 270149, upload-time = "2025-07-26T12:01:04.072Z" }, + { url = "https://files.pythonhosted.org/packages/30/2e/dd4ced42fefac8470661d7cb7e264808425e6c5d56d175291e93890cce09/contourpy-1.3.3-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:929ddf8c4c7f348e4c0a5a3a714b5c8542ffaa8c22954862a46ca1813b667ee7", size = 329222, upload-time = "2025-07-26T12:01:05.688Z" }, + { url = "https://files.pythonhosted.org/packages/f2/74/cc6ec2548e3d276c71389ea4802a774b7aa3558223b7bade3f25787fafc2/contourpy-1.3.3-cp311-cp311-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9e999574eddae35f1312c2b4b717b7885d4edd6cb46700e04f7f02db454e67c1", size = 377234, upload-time = "2025-07-26T12:01:07.054Z" }, + { url = "https://files.pythonhosted.org/packages/03/b3/64ef723029f917410f75c09da54254c5f9ea90ef89b143ccadb09df14c15/contourpy-1.3.3-cp311-cp311-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0bf67e0e3f482cb69779dd3061b534eb35ac9b17f163d851e2a547d56dba0a3a", size = 380555, upload-time = "2025-07-26T12:01:08.801Z" }, + { url = "https://files.pythonhosted.org/packages/5f/4b/6157f24ca425b89fe2eb7e7be642375711ab671135be21e6faa100f7448c/contourpy-1.3.3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:51e79c1f7470158e838808d4a996fa9bac72c498e93d8ebe5119bc1e6becb0db", size = 355238, upload-time = "2025-07-26T12:01:10.319Z" }, + { url = "https://files.pythonhosted.org/packages/98/56/f914f0dd678480708a04cfd2206e7c382533249bc5001eb9f58aa693e200/contourpy-1.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:598c3aaece21c503615fd59c92a3598b428b2f01bfb4b8ca9c4edeecc2438620", size = 1326218, upload-time = "2025-07-26T12:01:12.659Z" }, + { url = "https://files.pythonhosted.org/packages/fb/d7/4a972334a0c971acd5172389671113ae82aa7527073980c38d5868ff1161/contourpy-1.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:322ab1c99b008dad206d406bb61d014cf0174df491ae9d9d0fac6a6fda4f977f", size = 1392867, upload-time = "2025-07-26T12:01:15.533Z" }, + { url = "https://files.pythonhosted.org/packages/75/3e/f2cc6cd56dc8cff46b1a56232eabc6feea52720083ea71ab15523daab796/contourpy-1.3.3-cp311-cp311-win32.whl", hash = "sha256:fd907ae12cd483cd83e414b12941c632a969171bf90fc937d0c9f268a31cafff", size = 183677, upload-time = "2025-07-26T12:01:17.088Z" }, + { url = "https://files.pythonhosted.org/packages/98/4b/9bd370b004b5c9d8045c6c33cf65bae018b27aca550a3f657cdc99acdbd8/contourpy-1.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:3519428f6be58431c56581f1694ba8e50626f2dd550af225f82fb5f5814d2a42", size = 225234, upload-time = "2025-07-26T12:01:18.256Z" }, + { url = "https://files.pythonhosted.org/packages/d9/b6/71771e02c2e004450c12b1120a5f488cad2e4d5b590b1af8bad060360fe4/contourpy-1.3.3-cp311-cp311-win_arm64.whl", hash = "sha256:15ff10bfada4bf92ec8b31c62bf7c1834c244019b4a33095a68000d7075df470", size = 193123, upload-time = "2025-07-26T12:01:19.848Z" }, + { url = "https://files.pythonhosted.org/packages/be/45/adfee365d9ea3d853550b2e735f9d66366701c65db7855cd07621732ccfc/contourpy-1.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b08a32ea2f8e42cf1d4be3169a98dd4be32bafe4f22b6c4cb4ba810fa9e5d2cb", size = 293419, upload-time = "2025-07-26T12:01:21.16Z" }, + { url = "https://files.pythonhosted.org/packages/53/3e/405b59cfa13021a56bba395a6b3aca8cec012b45bf177b0eaf7a202cde2c/contourpy-1.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:556dba8fb6f5d8742f2923fe9457dbdd51e1049c4a43fd3986a0b14a1d815fc6", size = 273979, upload-time = "2025-07-26T12:01:22.448Z" }, + { url = "https://files.pythonhosted.org/packages/d4/1c/a12359b9b2ca3a845e8f7f9ac08bdf776114eb931392fcad91743e2ea17b/contourpy-1.3.3-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92d9abc807cf7d0e047b95ca5d957cf4792fcd04e920ca70d48add15c1a90ea7", size = 332653, upload-time = "2025-07-26T12:01:24.155Z" }, + { url = "https://files.pythonhosted.org/packages/63/12/897aeebfb475b7748ea67b61e045accdfcf0d971f8a588b67108ed7f5512/contourpy-1.3.3-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b2e8faa0ed68cb29af51edd8e24798bb661eac3bd9f65420c1887b6ca89987c8", size = 379536, upload-time = "2025-07-26T12:01:25.91Z" }, + { url = "https://files.pythonhosted.org/packages/43/8a/a8c584b82deb248930ce069e71576fc09bd7174bbd35183b7943fb1064fd/contourpy-1.3.3-cp312-cp312-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:626d60935cf668e70a5ce6ff184fd713e9683fb458898e4249b63be9e28286ea", size = 384397, upload-time = "2025-07-26T12:01:27.152Z" }, + { url = "https://files.pythonhosted.org/packages/cc/8f/ec6289987824b29529d0dfda0d74a07cec60e54b9c92f3c9da4c0ac732de/contourpy-1.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4d00e655fcef08aba35ec9610536bfe90267d7ab5ba944f7032549c55a146da1", size = 362601, upload-time = "2025-07-26T12:01:28.808Z" }, + { url = "https://files.pythonhosted.org/packages/05/0a/a3fe3be3ee2dceb3e615ebb4df97ae6f3828aa915d3e10549ce016302bd1/contourpy-1.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:451e71b5a7d597379ef572de31eeb909a87246974d960049a9848c3bc6c41bf7", size = 1331288, upload-time = "2025-07-26T12:01:31.198Z" }, + { url = "https://files.pythonhosted.org/packages/33/1d/acad9bd4e97f13f3e2b18a3977fe1b4a37ecf3d38d815333980c6c72e963/contourpy-1.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:459c1f020cd59fcfe6650180678a9993932d80d44ccde1fa1868977438f0b411", size = 1403386, upload-time = "2025-07-26T12:01:33.947Z" }, + { url = "https://files.pythonhosted.org/packages/cf/8f/5847f44a7fddf859704217a99a23a4f6417b10e5ab1256a179264561540e/contourpy-1.3.3-cp312-cp312-win32.whl", hash = "sha256:023b44101dfe49d7d53932be418477dba359649246075c996866106da069af69", size = 185018, upload-time = "2025-07-26T12:01:35.64Z" }, + { url = "https://files.pythonhosted.org/packages/19/e8/6026ed58a64563186a9ee3f29f41261fd1828f527dd93d33b60feca63352/contourpy-1.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:8153b8bfc11e1e4d75bcb0bff1db232f9e10b274e0929de9d608027e0d34ff8b", size = 226567, upload-time = "2025-07-26T12:01:36.804Z" }, + { url = "https://files.pythonhosted.org/packages/d1/e2/f05240d2c39a1ed228d8328a78b6f44cd695f7ef47beb3e684cf93604f86/contourpy-1.3.3-cp312-cp312-win_arm64.whl", hash = "sha256:07ce5ed73ecdc4a03ffe3e1b3e3c1166db35ae7584be76f65dbbe28a7791b0cc", size = 193655, upload-time = "2025-07-26T12:01:37.999Z" }, + { url = "https://files.pythonhosted.org/packages/68/35/0167aad910bbdb9599272bd96d01a9ec6852f36b9455cf2ca67bd4cc2d23/contourpy-1.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:177fb367556747a686509d6fef71d221a4b198a3905fe824430e5ea0fda54eb5", size = 293257, upload-time = "2025-07-26T12:01:39.367Z" }, + { url = "https://files.pythonhosted.org/packages/96/e4/7adcd9c8362745b2210728f209bfbcf7d91ba868a2c5f40d8b58f54c509b/contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d002b6f00d73d69333dac9d0b8d5e84d9724ff9ef044fd63c5986e62b7c9e1b1", size = 274034, upload-time = "2025-07-26T12:01:40.645Z" }, + { url = "https://files.pythonhosted.org/packages/73/23/90e31ceeed1de63058a02cb04b12f2de4b40e3bef5e082a7c18d9c8ae281/contourpy-1.3.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:348ac1f5d4f1d66d3322420f01d42e43122f43616e0f194fc1c9f5d830c5b286", size = 334672, upload-time = "2025-07-26T12:01:41.942Z" }, + { url = "https://files.pythonhosted.org/packages/ed/93/b43d8acbe67392e659e1d984700e79eb67e2acb2bd7f62012b583a7f1b55/contourpy-1.3.3-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:655456777ff65c2c548b7c454af9c6f33f16c8884f11083244b5819cc214f1b5", size = 381234, upload-time = "2025-07-26T12:01:43.499Z" }, + { url = "https://files.pythonhosted.org/packages/46/3b/bec82a3ea06f66711520f75a40c8fc0b113b2a75edb36aa633eb11c4f50f/contourpy-1.3.3-cp313-cp313-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:644a6853d15b2512d67881586bd03f462c7ab755db95f16f14d7e238f2852c67", size = 385169, upload-time = "2025-07-26T12:01:45.219Z" }, + { url = "https://files.pythonhosted.org/packages/4b/32/e0f13a1c5b0f8572d0ec6ae2f6c677b7991fafd95da523159c19eff0696a/contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4debd64f124ca62069f313a9cb86656ff087786016d76927ae2cf37846b006c9", size = 362859, upload-time = "2025-07-26T12:01:46.519Z" }, + { url = "https://files.pythonhosted.org/packages/33/71/e2a7945b7de4e58af42d708a219f3b2f4cff7386e6b6ab0a0fa0033c49a9/contourpy-1.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a15459b0f4615b00bbd1e91f1b9e19b7e63aea7483d03d804186f278c0af2659", size = 1332062, upload-time = "2025-07-26T12:01:48.964Z" }, + { url = "https://files.pythonhosted.org/packages/12/fc/4e87ac754220ccc0e807284f88e943d6d43b43843614f0a8afa469801db0/contourpy-1.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ca0fdcd73925568ca027e0b17ab07aad764be4706d0a925b89227e447d9737b7", size = 1403932, upload-time = "2025-07-26T12:01:51.979Z" }, + { url = "https://files.pythonhosted.org/packages/a6/2e/adc197a37443f934594112222ac1aa7dc9a98faf9c3842884df9a9d8751d/contourpy-1.3.3-cp313-cp313-win32.whl", hash = "sha256:b20c7c9a3bf701366556e1b1984ed2d0cedf999903c51311417cf5f591d8c78d", size = 185024, upload-time = "2025-07-26T12:01:53.245Z" }, + { url = "https://files.pythonhosted.org/packages/18/0b/0098c214843213759692cc638fce7de5c289200a830e5035d1791d7a2338/contourpy-1.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:1cadd8b8969f060ba45ed7c1b714fe69185812ab43bd6b86a9123fe8f99c3263", size = 226578, upload-time = "2025-07-26T12:01:54.422Z" }, + { url = "https://files.pythonhosted.org/packages/8a/9a/2f6024a0c5995243cd63afdeb3651c984f0d2bc727fd98066d40e141ad73/contourpy-1.3.3-cp313-cp313-win_arm64.whl", hash = "sha256:fd914713266421b7536de2bfa8181aa8c699432b6763a0ea64195ebe28bff6a9", size = 193524, upload-time = "2025-07-26T12:01:55.73Z" }, + { url = "https://files.pythonhosted.org/packages/c0/b3/f8a1a86bd3298513f500e5b1f5fd92b69896449f6cab6a146a5d52715479/contourpy-1.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:88df9880d507169449d434c293467418b9f6cbe82edd19284aa0409e7fdb933d", size = 306730, upload-time = "2025-07-26T12:01:57.051Z" }, + { url = "https://files.pythonhosted.org/packages/3f/11/4780db94ae62fc0c2053909b65dc3246bd7cecfc4f8a20d957ad43aa4ad8/contourpy-1.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d06bb1f751ba5d417047db62bca3c8fde202b8c11fb50742ab3ab962c81e8216", size = 287897, upload-time = "2025-07-26T12:01:58.663Z" }, + { url = "https://files.pythonhosted.org/packages/ae/15/e59f5f3ffdd6f3d4daa3e47114c53daabcb18574a26c21f03dc9e4e42ff0/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e4e6b05a45525357e382909a4c1600444e2a45b4795163d3b22669285591c1ae", size = 326751, upload-time = "2025-07-26T12:02:00.343Z" }, + { url = "https://files.pythonhosted.org/packages/0f/81/03b45cfad088e4770b1dcf72ea78d3802d04200009fb364d18a493857210/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ab3074b48c4e2cf1a960e6bbeb7f04566bf36b1861d5c9d4d8ac04b82e38ba20", size = 375486, upload-time = "2025-07-26T12:02:02.128Z" }, + { url = "https://files.pythonhosted.org/packages/0c/ba/49923366492ffbdd4486e970d421b289a670ae8cf539c1ea9a09822b371a/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6c3d53c796f8647d6deb1abe867daeb66dcc8a97e8455efa729516b997b8ed99", size = 388106, upload-time = "2025-07-26T12:02:03.615Z" }, + { url = "https://files.pythonhosted.org/packages/9f/52/5b00ea89525f8f143651f9f03a0df371d3cbd2fccd21ca9b768c7a6500c2/contourpy-1.3.3-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50ed930df7289ff2a8d7afeb9603f8289e5704755c7e5c3bbd929c90c817164b", size = 352548, upload-time = "2025-07-26T12:02:05.165Z" }, + { url = "https://files.pythonhosted.org/packages/32/1d/a209ec1a3a3452d490f6b14dd92e72280c99ae3d1e73da74f8277d4ee08f/contourpy-1.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4feffb6537d64b84877da813a5c30f1422ea5739566abf0bd18065ac040e120a", size = 1322297, upload-time = "2025-07-26T12:02:07.379Z" }, + { url = "https://files.pythonhosted.org/packages/bc/9e/46f0e8ebdd884ca0e8877e46a3f4e633f6c9c8c4f3f6e72be3fe075994aa/contourpy-1.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2b7e9480ffe2b0cd2e787e4df64270e3a0440d9db8dc823312e2c940c167df7e", size = 1391023, upload-time = "2025-07-26T12:02:10.171Z" }, + { url = "https://files.pythonhosted.org/packages/b9/70/f308384a3ae9cd2209e0849f33c913f658d3326900d0ff5d378d6a1422d2/contourpy-1.3.3-cp313-cp313t-win32.whl", hash = "sha256:283edd842a01e3dcd435b1c5116798d661378d83d36d337b8dde1d16a5fc9ba3", size = 196157, upload-time = "2025-07-26T12:02:11.488Z" }, + { url = "https://files.pythonhosted.org/packages/b2/dd/880f890a6663b84d9e34a6f88cded89d78f0091e0045a284427cb6b18521/contourpy-1.3.3-cp313-cp313t-win_amd64.whl", hash = "sha256:87acf5963fc2b34825e5b6b048f40e3635dd547f590b04d2ab317c2619ef7ae8", size = 240570, upload-time = "2025-07-26T12:02:12.754Z" }, + { url = "https://files.pythonhosted.org/packages/80/99/2adc7d8ffead633234817ef8e9a87115c8a11927a94478f6bb3d3f4d4f7d/contourpy-1.3.3-cp313-cp313t-win_arm64.whl", hash = "sha256:3c30273eb2a55024ff31ba7d052dde990d7d8e5450f4bbb6e913558b3d6c2301", size = 199713, upload-time = "2025-07-26T12:02:14.4Z" }, + { url = "https://files.pythonhosted.org/packages/72/8b/4546f3ab60f78c514ffb7d01a0bd743f90de36f0019d1be84d0a708a580a/contourpy-1.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fde6c716d51c04b1c25d0b90364d0be954624a0ee9d60e23e850e8d48353d07a", size = 292189, upload-time = "2025-07-26T12:02:16.095Z" }, + { url = "https://files.pythonhosted.org/packages/fd/e1/3542a9cb596cadd76fcef413f19c79216e002623158befe6daa03dbfa88c/contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:cbedb772ed74ff5be440fa8eee9bd49f64f6e3fc09436d9c7d8f1c287b121d77", size = 273251, upload-time = "2025-07-26T12:02:17.524Z" }, + { url = "https://files.pythonhosted.org/packages/b1/71/f93e1e9471d189f79d0ce2497007731c1e6bf9ef6d1d61b911430c3db4e5/contourpy-1.3.3-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:22e9b1bd7a9b1d652cd77388465dc358dafcd2e217d35552424aa4f996f524f5", size = 335810, upload-time = "2025-07-26T12:02:18.9Z" }, + { url = "https://files.pythonhosted.org/packages/91/f9/e35f4c1c93f9275d4e38681a80506b5510e9327350c51f8d4a5a724d178c/contourpy-1.3.3-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a22738912262aa3e254e4f3cb079a95a67132fc5a063890e224393596902f5a4", size = 382871, upload-time = "2025-07-26T12:02:20.418Z" }, + { url = "https://files.pythonhosted.org/packages/b5/71/47b512f936f66a0a900d81c396a7e60d73419868fba959c61efed7a8ab46/contourpy-1.3.3-cp314-cp314-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:afe5a512f31ee6bd7d0dda52ec9864c984ca3d66664444f2d72e0dc4eb832e36", size = 386264, upload-time = "2025-07-26T12:02:21.916Z" }, + { url = "https://files.pythonhosted.org/packages/04/5f/9ff93450ba96b09c7c2b3f81c94de31c89f92292f1380261bd7195bea4ea/contourpy-1.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f64836de09927cba6f79dcd00fdd7d5329f3fccc633468507079c829ca4db4e3", size = 363819, upload-time = "2025-07-26T12:02:23.759Z" }, + { url = "https://files.pythonhosted.org/packages/3e/a6/0b185d4cc480ee494945cde102cb0149ae830b5fa17bf855b95f2e70ad13/contourpy-1.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1fd43c3be4c8e5fd6e4f2baeae35ae18176cf2e5cced681cca908addf1cdd53b", size = 1333650, upload-time = "2025-07-26T12:02:26.181Z" }, + { url = "https://files.pythonhosted.org/packages/43/d7/afdc95580ca56f30fbcd3060250f66cedbde69b4547028863abd8aa3b47e/contourpy-1.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6afc576f7b33cf00996e5c1102dc2a8f7cc89e39c0b55df93a0b78c1bd992b36", size = 1404833, upload-time = "2025-07-26T12:02:28.782Z" }, + { url = "https://files.pythonhosted.org/packages/e2/e2/366af18a6d386f41132a48f033cbd2102e9b0cf6345d35ff0826cd984566/contourpy-1.3.3-cp314-cp314-win32.whl", hash = "sha256:66c8a43a4f7b8df8b71ee1840e4211a3c8d93b214b213f590e18a1beca458f7d", size = 189692, upload-time = "2025-07-26T12:02:30.128Z" }, + { url = "https://files.pythonhosted.org/packages/7d/c2/57f54b03d0f22d4044b8afb9ca0e184f8b1afd57b4f735c2fa70883dc601/contourpy-1.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:cf9022ef053f2694e31d630feaacb21ea24224be1c3ad0520b13d844274614fd", size = 232424, upload-time = "2025-07-26T12:02:31.395Z" }, + { url = "https://files.pythonhosted.org/packages/18/79/a9416650df9b525737ab521aa181ccc42d56016d2123ddcb7b58e926a42c/contourpy-1.3.3-cp314-cp314-win_arm64.whl", hash = "sha256:95b181891b4c71de4bb404c6621e7e2390745f887f2a026b2d99e92c17892339", size = 198300, upload-time = "2025-07-26T12:02:32.956Z" }, + { url = "https://files.pythonhosted.org/packages/1f/42/38c159a7d0f2b7b9c04c64ab317042bb6952b713ba875c1681529a2932fe/contourpy-1.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:33c82d0138c0a062380332c861387650c82e4cf1747aaa6938b9b6516762e772", size = 306769, upload-time = "2025-07-26T12:02:34.2Z" }, + { url = "https://files.pythonhosted.org/packages/c3/6c/26a8205f24bca10974e77460de68d3d7c63e282e23782f1239f226fcae6f/contourpy-1.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ea37e7b45949df430fe649e5de8351c423430046a2af20b1c1961cae3afcda77", size = 287892, upload-time = "2025-07-26T12:02:35.807Z" }, + { url = "https://files.pythonhosted.org/packages/66/06/8a475c8ab718ebfd7925661747dbb3c3ee9c82ac834ccb3570be49d129f4/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d304906ecc71672e9c89e87c4675dc5c2645e1f4269a5063b99b0bb29f232d13", size = 326748, upload-time = "2025-07-26T12:02:37.193Z" }, + { url = "https://files.pythonhosted.org/packages/b4/a3/c5ca9f010a44c223f098fccd8b158bb1cb287378a31ac141f04730dc49be/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ca658cd1a680a5c9ea96dc61cdbae1e85c8f25849843aa799dfd3cb370ad4fbe", size = 375554, upload-time = "2025-07-26T12:02:38.894Z" }, + { url = "https://files.pythonhosted.org/packages/80/5b/68bd33ae63fac658a4145088c1e894405e07584a316738710b636c6d0333/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ab2fd90904c503739a75b7c8c5c01160130ba67944a7b77bbf36ef8054576e7f", size = 388118, upload-time = "2025-07-26T12:02:40.642Z" }, + { url = "https://files.pythonhosted.org/packages/40/52/4c285a6435940ae25d7410a6c36bda5145839bc3f0beb20c707cda18b9d2/contourpy-1.3.3-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7301b89040075c30e5768810bc96a8e8d78085b47d8be6e4c3f5a0b4ed478a0", size = 352555, upload-time = "2025-07-26T12:02:42.25Z" }, + { url = "https://files.pythonhosted.org/packages/24/ee/3e81e1dd174f5c7fefe50e85d0892de05ca4e26ef1c9a59c2a57e43b865a/contourpy-1.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:2a2a8b627d5cc6b7c41a4beff6c5ad5eb848c88255fda4a8745f7e901b32d8e4", size = 1322295, upload-time = "2025-07-26T12:02:44.668Z" }, + { url = "https://files.pythonhosted.org/packages/3c/b2/6d913d4d04e14379de429057cd169e5e00f6c2af3bb13e1710bcbdb5da12/contourpy-1.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:fd6ec6be509c787f1caf6b247f0b1ca598bef13f4ddeaa126b7658215529ba0f", size = 1391027, upload-time = "2025-07-26T12:02:47.09Z" }, + { url = "https://files.pythonhosted.org/packages/93/8a/68a4ec5c55a2971213d29a9374913f7e9f18581945a7a31d1a39b5d2dfe5/contourpy-1.3.3-cp314-cp314t-win32.whl", hash = "sha256:e74a9a0f5e3fff48fb5a7f2fd2b9b70a3fe014a67522f79b7cca4c0c7e43c9ae", size = 202428, upload-time = "2025-07-26T12:02:48.691Z" }, + { url = "https://files.pythonhosted.org/packages/fa/96/fd9f641ffedc4fa3ace923af73b9d07e869496c9cc7a459103e6e978992f/contourpy-1.3.3-cp314-cp314t-win_amd64.whl", hash = "sha256:13b68d6a62db8eafaebb8039218921399baf6e47bf85006fd8529f2a08ef33fc", size = 250331, upload-time = "2025-07-26T12:02:50.137Z" }, + { url = "https://files.pythonhosted.org/packages/ae/8c/469afb6465b853afff216f9528ffda78a915ff880ed58813ba4faf4ba0b6/contourpy-1.3.3-cp314-cp314t-win_arm64.whl", hash = "sha256:b7448cb5a725bb1e35ce88771b86fba35ef418952474492cf7c764059933ff8b", size = 203831, upload-time = "2025-07-26T12:02:51.449Z" }, + { url = "https://files.pythonhosted.org/packages/a5/29/8dcfe16f0107943fa92388c23f6e05cff0ba58058c4c95b00280d4c75a14/contourpy-1.3.3-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:cd5dfcaeb10f7b7f9dc8941717c6c2ade08f587be2226222c12b25f0483ed497", size = 278809, upload-time = "2025-07-26T12:02:52.74Z" }, + { url = "https://files.pythonhosted.org/packages/85/a9/8b37ef4f7dafeb335daee3c8254645ef5725be4d9c6aa70b50ec46ef2f7e/contourpy-1.3.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:0c1fc238306b35f246d61a1d416a627348b5cf0648648a031e14bb8705fcdfe8", size = 261593, upload-time = "2025-07-26T12:02:54.037Z" }, + { url = "https://files.pythonhosted.org/packages/0a/59/ebfb8c677c75605cc27f7122c90313fd2f375ff3c8d19a1694bda74aaa63/contourpy-1.3.3-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:70f9aad7de812d6541d29d2bbf8feb22ff7e1c299523db288004e3157ff4674e", size = 302202, upload-time = "2025-07-26T12:02:55.947Z" }, + { url = "https://files.pythonhosted.org/packages/3c/37/21972a15834d90bfbfb009b9d004779bd5a07a0ec0234e5ba8f64d5736f4/contourpy-1.3.3-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5ed3657edf08512fc3fe81b510e35c2012fbd3081d2e26160f27ca28affec989", size = 329207, upload-time = "2025-07-26T12:02:57.468Z" }, + { url = "https://files.pythonhosted.org/packages/0c/58/bd257695f39d05594ca4ad60df5bcb7e32247f9951fd09a9b8edb82d1daa/contourpy-1.3.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:3d1a3799d62d45c18bafd41c5fa05120b96a28079f2393af559b843d1a966a77", size = 225315, upload-time = "2025-07-26T12:02:58.801Z" }, +] + [[package]] name = "coverage" version = "7.13.0" @@ -539,6 +623,15 @@ toml = [ { name = "tomli", marker = "python_full_version <= '3.11'" }, ] +[[package]] +name = "cycler" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a9/95/a3dbbb5028f35eafb79008e7522a75244477d2838f38cbb722248dabc2a8/cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c", size = 7615, upload-time = "2023-10-07T05:32:18.335Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321, upload-time = "2023-10-07T05:32:16.783Z" }, +] + [[package]] name = "datasets" version = "5.0.0" @@ -699,6 +792,55 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ec/f9/7f9263c5695f4bd0023734af91bedb2ff8209e8de6ead162f35d8dc762fd/flask-3.1.2-py3-none-any.whl", hash = "sha256:ca1d8112ec8a6158cc29ea4858963350011b5c846a414cdb7a954aa9e967d03c", size = 103308, upload-time = "2025-08-19T21:03:19.499Z" }, ] +[[package]] +name = "fonttools" +version = "4.63.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/84/69/c97f2c18e0db87d2c7b15da1974dace76ae938f1cfa22e2727a648b7ed43/fonttools-4.63.0.tar.gz", hash = "sha256:caeb583deeb5168e694b65cda8b4ee62abedfa66cf88488734466f2366b9c4e0", size = 3597189, upload-time = "2026-05-14T12:04:30.958Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/75/2b/a7f1545bdf5da69c4bda0cea2a5781f0ad2a6623e0277267672db43c5fe6/fonttools-4.63.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2b8ae05d9eacf6081414d759c0a352769ac28ce31280d6bb8e77b03f9e3c449f", size = 2881793, upload-time = "2026-05-14T12:02:56.645Z" }, + { url = "https://files.pythonhosted.org/packages/49/50/965308c703f085f225db2886813b27e015b8b3438c350b22dd65b52c2a2c/fonttools-4.63.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:79cdc9f567aec74a72918fd060283911406750cbc9fd28c1316023deb6ce31a9", size = 2428130, upload-time = "2026-05-14T12:02:58.891Z" }, + { url = "https://files.pythonhosted.org/packages/d8/38/6937fbd7f2dc3a6b48725851bc2c15ec949b9af14d9bbcb5fe83cdf9bdf9/fonttools-4.63.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2c14b4fd138c4bafcca294765c547914e1aa431ae1ca94ab99d8db08c958bd3b", size = 5111952, upload-time = "2026-05-14T12:03:01.263Z" }, + { url = "https://files.pythonhosted.org/packages/0b/43/a81f20050a3115b57d62c8e781446949512eac36690dc384ccea65ff4cc1/fonttools-4.63.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d76ac49f929aecaf82d83250b8347e099d7aecba0f4726c1d9b6df3b8bb5fe18", size = 5082308, upload-time = "2026-05-14T12:03:03.211Z" }, + { url = "https://files.pythonhosted.org/packages/67/00/cdd9d4944ca6ae280d01e69cc37bde3bf663630b837a6fc6d2cd65d80e0e/fonttools-4.63.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dcf076a4474fe0d7367e5bbf5b052c7284fa1feca729c04176ce513521afd8a0", size = 5087932, upload-time = "2026-05-14T12:03:05.147Z" }, + { url = "https://files.pythonhosted.org/packages/f5/f1/0aa0dbea778c75adbef223c42019fd47d22262b905974d62d829545d485f/fonttools-4.63.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7dd683fef0663e9f0f45cf541d788d24caa3ec9db50796b588e1757d8b3bc007", size = 5213271, upload-time = "2026-05-14T12:03:07.238Z" }, + { url = "https://files.pythonhosted.org/packages/a8/99/253e4056e1f0e67b9390125a154b73b5eb73ad521bece95c004858fdeec2/fonttools-4.63.0-cp311-cp311-win32.whl", hash = "sha256:afefc1ed0a59785a7fb06ea7e1678e849c193e1e387db783579bc7b3056fcfcb", size = 2304473, upload-time = "2026-05-14T12:03:09.271Z" }, + { url = "https://files.pythonhosted.org/packages/08/60/defa5e69641db890a63be281f41345f4c33b157824eaf0b9fad3e08b0dcb/fonttools-4.63.0-cp311-cp311-win_amd64.whl", hash = "sha256:063e08bd17bd5a90127a14123de0d6a952dbc847695fd98b63c043d58057f90c", size = 2356389, upload-time = "2026-05-14T12:03:11.53Z" }, + { url = "https://files.pythonhosted.org/packages/08/ef/b3c6b9b5be2f82416d73fe2ed2e96e2793cd80e7510bd6a17ca79cdd88ec/fonttools-4.63.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:37dd23e621e3b0aef1baa70a303b80aaf38449632cfc8fd2a55fb285bbccfc02", size = 2881131, upload-time = "2026-05-14T12:03:13.386Z" }, + { url = "https://files.pythonhosted.org/packages/44/a0/c815bea63117fa63e4e1c01f8a1110d2112fa003f838e6467094ec2432ce/fonttools-4.63.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a9faff9e0c1f76f9fd55899d2ce785832efebab37eb8ae13995853aef178bef0", size = 2426704, upload-time = "2026-05-14T12:03:15.801Z" }, + { url = "https://files.pythonhosted.org/packages/44/04/0b91d8e916e92ad1fac9e4624760baf0fd5ff2ead614c2f68fb21373f03f/fonttools-4.63.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ef3048ef05dbb552b89817713d9cac912e00d0fde4a3105c00d29e52e10c89af", size = 5044298, upload-time = "2026-05-14T12:03:18.085Z" }, + { url = "https://files.pythonhosted.org/packages/77/c7/2342da9830e3e9d4870305ca5d2091d2a83284f2953079b7bdd3b5e029d8/fonttools-4.63.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:58dc6bb86a78d782f00f9190ca02c119cf5bbe2807536e361e18d42019f877d8", size = 4999800, upload-time = "2026-05-14T12:03:20.161Z" }, + { url = "https://files.pythonhosted.org/packages/e6/6d/67fe16c48d7ce050979b33f47e0d28a318f02da030602e944c34f7a16ef3/fonttools-4.63.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ee08ebfa58f6e1aeff5697ab9582105bb620008c1caafb681e4c557e7483027b", size = 4982666, upload-time = "2026-05-14T12:03:22.87Z" }, + { url = "https://files.pythonhosted.org/packages/f2/00/3bbab338c07c71fa56269953845e92c951a61457bbbb0f1022551ea266d9/fonttools-4.63.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:27fdc65af8da6f88b9c6121c47a464cbe359fcfff7ff6fc2d37a1f395d755b78", size = 5133598, upload-time = "2026-05-14T12:03:25.168Z" }, + { url = "https://files.pythonhosted.org/packages/62/f2/aa27c7f98db5b064883dadcc5283947e81e034de42e22a33675878d98b54/fonttools-4.63.0-cp312-cp312-win32.whl", hash = "sha256:af2fd1664d00a397d75f806985ddb36282091c2131a73a6485c23b4a34722263", size = 2292575, upload-time = "2026-05-14T12:03:27.496Z" }, + { url = "https://files.pythonhosted.org/packages/87/36/cccb9bc2a6ab63d1b2980374f0dca72ce95ae267c9b4cfe77455bb70d0d4/fonttools-4.63.0-cp312-cp312-win_amd64.whl", hash = "sha256:59ac449f8cca9b4ffa08d2e7bbadad87ce710d69d1eda5c3c1ce579baa987272", size = 2343211, upload-time = "2026-05-14T12:03:30.057Z" }, + { url = "https://files.pythonhosted.org/packages/0f/8d/d8fec3dcde2963f8c908fb315e5ff2cd0ac34f82394bbbf73a2aa5145ce3/fonttools-4.63.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:cd7e9857e5e63738b9d9fd707bc1f59c8b09e5177726d23664db393c59bb08bd", size = 2876062, upload-time = "2026-05-14T12:03:32.554Z" }, + { url = "https://files.pythonhosted.org/packages/ef/71/d935dc54e4ff121bfdd11e08702db63a7e6f25af21d8a3d7b7212df53641/fonttools-4.63.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c2a2a42198b696a6f48fad91709afb55176e66a5e566131219dba372fb7f8c59", size = 2424594, upload-time = "2026-05-14T12:03:34.86Z" }, + { url = "https://files.pythonhosted.org/packages/8e/40/e76320afa1df918e146155ef239b1719ee266092e96f5423bfd075affba1/fonttools-4.63.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e874792a8212b44583ea02189d9e693906b2f78b261f372f95d6c563210ac1d", size = 5024840, upload-time = "2026-05-14T12:03:36.745Z" }, + { url = "https://files.pythonhosted.org/packages/ce/36/0b805d8c485f872f65a509cbe3b58a5d0d17bee855333b54a150c79d3061/fonttools-4.63.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:22135da48a348785c5e2d5d2d9d6bec5ed44adacbaeb9db12d9493bf6c6bfa68", size = 4975801, upload-time = "2026-05-14T12:03:38.833Z" }, + { url = "https://files.pythonhosted.org/packages/c8/26/2cee03d0aa083ab022da5c07aff9ed3f689da1defb81ad6917c9627896da/fonttools-4.63.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ccf41f2efdf56994d22d73bef4ced1052161958169428d06ba9724ea9e9a64be", size = 4965009, upload-time = "2026-05-14T12:03:41.494Z" }, + { url = "https://files.pythonhosted.org/packages/7e/48/cc4b66d9058c0d0982c833fad10127c4b0e9324606aafa41382295ca4102/fonttools-4.63.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9ced0bd02ac751dd6319b0da88aaef24414e3b0dbc32bb4f24944821a3741a27", size = 5105892, upload-time = "2026-05-14T12:03:43.525Z" }, + { url = "https://files.pythonhosted.org/packages/d8/1f/a98a30a814b9ddef3a2e706025f90b9e0bc94890e6cb15254bc86547d11a/fonttools-4.63.0-cp313-cp313-win32.whl", hash = "sha256:85be818f5506e8a7753153def2c9550178f0ecae6a47b5e0e8dbb23f7cc90380", size = 2291313, upload-time = "2026-05-14T12:03:45.594Z" }, + { url = "https://files.pythonhosted.org/packages/92/46/5177b01f3b4abfdd4409f31cca4ab279c9343a26efbe9ec78c97fc612e02/fonttools-4.63.0-cp313-cp313-win_amd64.whl", hash = "sha256:ba04cb5891d4c0c21b6da95eda8d7b090021508a294fff33464fc7d241e0856b", size = 2342299, upload-time = "2026-05-14T12:03:47.414Z" }, + { url = "https://files.pythonhosted.org/packages/27/d2/23d25e3f247b328be58d04a4c9f894178a0d1eda7d42867cfb388adaf416/fonttools-4.63.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:fd1e3094f42d806d3d7c79162fc59e5910fcbe3a7360c385b8da969bc4493745", size = 2875338, upload-time = "2026-05-14T12:03:50.052Z" }, + { url = "https://files.pythonhosted.org/packages/cd/58/7dfa0c761cb3b2964e2a84c4dc986c926a87de0cb9fb60d5b28ded3f2914/fonttools-4.63.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:6e528da43bc3791085f8cb6141b1d13e459226790240340fcbb4625649238b03", size = 2422661, upload-time = "2026-05-14T12:03:52.154Z" }, + { url = "https://files.pythonhosted.org/packages/dd/87/64cfa18a7a1621d17b7f4502b2b0ed8a135a90c3db51ea590ee99043e76b/fonttools-4.63.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b2248c5decb223562f7902ff6325077a073f608ee8e33e88ad88db734eb9f49", size = 5010526, upload-time = "2026-05-14T12:03:54.647Z" }, + { url = "https://files.pythonhosted.org/packages/36/e1/a8933a72c45a87177fbde2696e0d0755c8c9062f8c077a961c6215fa27b1/fonttools-4.63.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:308f957cdeaf8abe4e5f2f124902ef405448af92c90f80e302a3b771c2e6116b", size = 4923946, upload-time = "2026-05-14T12:03:56.984Z" }, + { url = "https://files.pythonhosted.org/packages/27/60/872e6e233b8c5e8b41413796ff18b7fe479661bd40147e071b450dfad7a1/fonttools-4.63.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:bf00f21eb5fb721dbaf73d1e9da6d02a1af7768f2ebcf9798be98beab8ba90f6", size = 4962489, upload-time = "2026-05-14T12:03:59.443Z" }, + { url = "https://files.pythonhosted.org/packages/30/c4/83c24f2ec38b90cfda84bf4b1a1f49df80e84a1db4e7ac6e0d41bf23bc39/fonttools-4.63.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c1aaa4b9c75798400ac043ce04d74e7830376c85095a5a6ed7cba2f17a266bf4", size = 5071870, upload-time = "2026-05-14T12:04:02.122Z" }, + { url = "https://files.pythonhosted.org/packages/de/40/3ae22b60ff1d41ce0bd044b31238cdc72cef99f28b976f1e128ebd618c9b/fonttools-4.63.0-cp314-cp314-win32.whl", hash = "sha256:22693918177bd9ceabec4736d338045f357769416fc6b0b2508eefef75b08616", size = 2295026, upload-time = "2026-05-14T12:04:04.47Z" }, + { url = "https://files.pythonhosted.org/packages/c3/d4/98078064ccc76b45cb0f6c002452011e93c4bd26f6850344f0951cc1fe89/fonttools-4.63.0-cp314-cp314-win_amd64.whl", hash = "sha256:7d782fac32985914c351556f68ac0855391572bcd87de50e05970d3cd4c96fc5", size = 2347454, upload-time = "2026-05-14T12:04:06.752Z" }, + { url = "https://files.pythonhosted.org/packages/49/4e/652d1580c5f4e39f7d103b0c793e4773129ad633dce4addd0cf4dfebde02/fonttools-4.63.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:6db5140a60a5d731d21ec076745b40a310607731b0a565b50776393188649001", size = 2958152, upload-time = "2026-05-14T12:04:08.706Z" }, + { url = "https://files.pythonhosted.org/packages/0e/55/ad864c9a9b219f552eb46b32cd7906c466e5a578ba0c3abfcc0fe7413eb6/fonttools-4.63.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7d76edbff9014094dbf03bd2d074709dfa6ec7aba13d838c937a2b33d2d6a86e", size = 2460809, upload-time = "2026-05-14T12:04:10.783Z" }, + { url = "https://files.pythonhosted.org/packages/ea/2b/0aa8db70f18cf52e49b4ed5ecec68547f981160bf5ded3b5aed6faa0a6f9/fonttools-4.63.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0eac00b9118c3c2f87d272e45341871c5b3066baa3c86897fa634a7c3fb59096", size = 5148649, upload-time = "2026-05-14T12:04:12.747Z" }, + { url = "https://files.pythonhosted.org/packages/7f/63/18e4369c25043096f1048e0c9915951adc4f842bd81c6b18155824d6fa99/fonttools-4.63.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:51394295f1a51de8b5f30bdb1e1b9a4231536c7064ef5c6e211eec19fa36036f", size = 4932147, upload-time = "2026-05-14T12:04:14.806Z" }, + { url = "https://files.pythonhosted.org/packages/a1/3f/67f3eac2ffd8a98446c5022f8ed3864eac878a5ff7af8df4c8286dba16cc/fonttools-4.63.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:9e12f105d2b6342c559c298afb674006bb2893afc7102dcf8a1b55b0486b4e40", size = 5027237, upload-time = "2026-05-14T12:04:17.675Z" }, + { url = "https://files.pythonhosted.org/packages/1a/ba/4e6214cb38a7b04779e97bb7636de9a5c7f20af7018d03dee0b64c08510a/fonttools-4.63.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:796f27556dbe094c4824f75ca85267e4df776c79036c8441469a4df37038c196", size = 5053933, upload-time = "2026-05-14T12:04:20.818Z" }, + { url = "https://files.pythonhosted.org/packages/34/3b/214dcc19ee31d3d38fb5ad2755c11ef0514e5dc300bbaf41c0b69f393799/fonttools-4.63.0-cp314-cp314t-win32.whl", hash = "sha256:948428a275741f0b64b113c955425a953314f4b9ab9997f73a72c83e68e569c8", size = 2359326, upload-time = "2026-05-14T12:04:24.22Z" }, + { url = "https://files.pythonhosted.org/packages/dd/1e/3ff1a9b523058c2eeb6a9d50f5574e2a738200d0d94107d5bc4105e8da3f/fonttools-4.63.0-cp314-cp314t-win_amd64.whl", hash = "sha256:6d4741eb179121cab9eea4cb2393d24492373a260d7945006358c08cfbf45419", size = 2425829, upload-time = "2026-05-14T12:04:26.829Z" }, + { url = "https://files.pythonhosted.org/packages/2c/47/c99d5268f354002ce80f8d029cd9d7d872969da1de8b93d32de4dc56d6f4/fonttools-4.63.0-py3-none-any.whl", hash = "sha256:445af2eab030a16b9171ea8bdda7ebf7d96bda2df88ee182a464252f6e05e20d", size = 1164562, upload-time = "2026-05-14T12:04:29.092Z" }, +] + [[package]] name = "frozen-flask" version = "1.0.2" @@ -1170,6 +1312,112 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437, upload-time = "2025-09-08T01:34:57.871Z" }, ] +[[package]] +name = "kiwisolver" +version = "1.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/67/9c61eccb13f0bdca9307614e782fec49ffdde0f7a2314935d489fa93cd9c/kiwisolver-1.5.0.tar.gz", hash = "sha256:d4193f3d9dc3f6f79aaed0e5637f45d98850ebf01f7ca20e69457f3e8946b66a", size = 103482, upload-time = "2026-03-09T13:15:53.382Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/dd/a495a9c104be1c476f0386e714252caf2b7eca883915422a64c50b88c6f5/kiwisolver-1.5.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9eed0f7edbb274413b6ee781cca50541c8c0facd3d6fd289779e494340a2b85c", size = 122798, upload-time = "2026-03-09T13:12:58.963Z" }, + { url = "https://files.pythonhosted.org/packages/11/60/37b4047a2af0cf5ef6d8b4b26e91829ae6fc6a2d1f74524bcb0e7cd28a32/kiwisolver-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c4923e404d6bcd91b6779c009542e5647fef32e4a5d75e115e3bbac6f2335eb", size = 66216, upload-time = "2026-03-09T13:13:00.155Z" }, + { url = "https://files.pythonhosted.org/packages/0a/aa/510dc933d87767584abfe03efa445889996c70c2990f6f87c3ebaa0a18c5/kiwisolver-1.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0df54df7e686afa55e6f21fb86195224a6d9beb71d637e8d7920c95cf0f89aac", size = 63911, upload-time = "2026-03-09T13:13:01.671Z" }, + { url = "https://files.pythonhosted.org/packages/80/46/bddc13df6c2a40741e0cc7865bb1c9ed4796b6760bd04ce5fae3928ef917/kiwisolver-1.5.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2517e24d7315eb51c10664cdb865195df38ab74456c677df67bb47f12d088a27", size = 1438209, upload-time = "2026-03-09T13:13:03.385Z" }, + { url = "https://files.pythonhosted.org/packages/fd/d6/76621246f5165e5372f02f5e6f3f48ea336a8f9e96e43997d45b240ed8cd/kiwisolver-1.5.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff710414307fefa903e0d9bdf300972f892c23477829f49504e59834f4195398", size = 1248888, upload-time = "2026-03-09T13:13:05.231Z" }, + { url = "https://files.pythonhosted.org/packages/b2/c1/31559ec6fb39a5b48035ce29bb63ade628f321785f38c384dee3e2c08bc1/kiwisolver-1.5.0-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6176c1811d9d5a04fa391c490cc44f451e240697a16977f11c6f722efb9041db", size = 1266304, upload-time = "2026-03-09T13:13:06.743Z" }, + { url = "https://files.pythonhosted.org/packages/5e/ef/1cb8276f2d29cc6a41e0a042f27946ca347d3a4a75acf85d0a16aa6dcc82/kiwisolver-1.5.0-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:50847dca5d197fcbd389c805aa1a1cf32f25d2e7273dc47ab181a517666b68cc", size = 1319650, upload-time = "2026-03-09T13:13:08.607Z" }, + { url = "https://files.pythonhosted.org/packages/4c/e4/5ba3cecd7ce6236ae4a80f67e5d5531287337d0e1f076ca87a5abe4cd5d0/kiwisolver-1.5.0-cp311-cp311-manylinux_2_39_riscv64.whl", hash = "sha256:01808c6d15f4c3e8559595d6d1fe6411c68e4a3822b4b9972b44473b24f4e679", size = 970949, upload-time = "2026-03-09T13:13:10.299Z" }, + { url = "https://files.pythonhosted.org/packages/5a/69/dc61f7ae9a2f071f26004ced87f078235b5507ab6e5acd78f40365655034/kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f1f9f4121ec58628c96baa3de1a55a4e3a333c5102c8e94b64e23bf7b2083309", size = 2199125, upload-time = "2026-03-09T13:13:11.841Z" }, + { url = "https://files.pythonhosted.org/packages/e5/7b/abbe0f1b5afa85f8d084b73e90e5f801c0939eba16ac2e49af7c61a6c28d/kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b7d335370ae48a780c6e6a6bbfa97342f563744c39c35562f3f367665f5c1de2", size = 2293783, upload-time = "2026-03-09T13:13:14.399Z" }, + { url = "https://files.pythonhosted.org/packages/8a/80/5908ae149d96d81580d604c7f8aefd0e98f4fd728cf172f477e9f2a81744/kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:800ee55980c18545af444d93fdd60c56b580db5cc54867d8cbf8a1dc0829938c", size = 1960726, upload-time = "2026-03-09T13:13:16.047Z" }, + { url = "https://files.pythonhosted.org/packages/84/08/a78cb776f8c085b7143142ce479859cfec086bd09ee638a317040b6ef420/kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:c438f6ca858697c9ab67eb28246c92508af972e114cac34e57a6d4ba17a3ac08", size = 2464738, upload-time = "2026-03-09T13:13:17.897Z" }, + { url = "https://files.pythonhosted.org/packages/b1/e1/65584da5356ed6cb12c63791a10b208860ac40a83de165cb6a6751a686e3/kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:8c63c91f95173f9c2a67c7c526b2cea976828a0e7fced9cdcead2802dc10f8a4", size = 2270718, upload-time = "2026-03-09T13:13:19.421Z" }, + { url = "https://files.pythonhosted.org/packages/be/6c/28f17390b62b8f2f520e2915095b3c94d88681ecf0041e75389d9667f202/kiwisolver-1.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:beb7f344487cdcb9e1efe4b7a29681b74d34c08f0043a327a74da852a6749e7b", size = 73480, upload-time = "2026-03-09T13:13:20.818Z" }, + { url = "https://files.pythonhosted.org/packages/d8/0e/2ee5debc4f77a625778fec5501ff3e8036fe361b7ee28ae402a485bb9694/kiwisolver-1.5.0-cp311-cp311-win_arm64.whl", hash = "sha256:ad4ae4ffd1ee9cd11357b4c66b612da9888f4f4daf2f36995eda64bd45370cac", size = 64930, upload-time = "2026-03-09T13:13:21.997Z" }, + { url = "https://files.pythonhosted.org/packages/4d/b2/818b74ebea34dabe6d0c51cb1c572e046730e64844da6ed646d5298c40ce/kiwisolver-1.5.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:4e9750bc21b886308024f8a54ccb9a2cc38ac9fa813bf4348434e3d54f337ff9", size = 123158, upload-time = "2026-03-09T13:13:23.127Z" }, + { url = "https://files.pythonhosted.org/packages/bf/d9/405320f8077e8e1c5c4bd6adc45e1e6edf6d727b6da7f2e2533cf58bff71/kiwisolver-1.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:72ec46b7eba5b395e0a7b63025490d3214c11013f4aacb4f5e8d6c3041829588", size = 66388, upload-time = "2026-03-09T13:13:24.765Z" }, + { url = "https://files.pythonhosted.org/packages/99/9f/795fedf35634f746151ca8839d05681ceb6287fbed6cc1c9bf235f7887c2/kiwisolver-1.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ed3a984b31da7481b103f68776f7128a89ef26ed40f4dc41a2223cda7fb24819", size = 64068, upload-time = "2026-03-09T13:13:25.878Z" }, + { url = "https://files.pythonhosted.org/packages/c4/13/680c54afe3e65767bed7ec1a15571e1a2f1257128733851ade24abcefbcc/kiwisolver-1.5.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bb5136fb5352d3f422df33f0c879a1b0c204004324150cc3b5e3c4f310c9049f", size = 1477934, upload-time = "2026-03-09T13:13:27.166Z" }, + { url = "https://files.pythonhosted.org/packages/c8/2f/cebfcdb60fd6a9b0f6b47a9337198bcbad6fbe15e68189b7011fd914911f/kiwisolver-1.5.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b2af221f268f5af85e776a73d62b0845fc8baf8ef0abfae79d29c77d0e776aaf", size = 1278537, upload-time = "2026-03-09T13:13:28.707Z" }, + { url = "https://files.pythonhosted.org/packages/f2/0d/9b782923aada3fafb1d6b84e13121954515c669b18af0c26e7d21f579855/kiwisolver-1.5.0-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b0f172dc8ffaccb8522d7c5d899de00133f2f1ca7b0a49b7da98e901de87bf2d", size = 1296685, upload-time = "2026-03-09T13:13:30.528Z" }, + { url = "https://files.pythonhosted.org/packages/27/70/83241b6634b04fe44e892688d5208332bde130f38e610c0418f9ede47ded/kiwisolver-1.5.0-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6ab8ba9152203feec73758dad83af9a0bbe05001eb4639e547207c40cfb52083", size = 1346024, upload-time = "2026-03-09T13:13:32.818Z" }, + { url = "https://files.pythonhosted.org/packages/e4/db/30ed226fb271ae1a6431fc0fe0edffb2efe23cadb01e798caeb9f2ceae8f/kiwisolver-1.5.0-cp312-cp312-manylinux_2_39_riscv64.whl", hash = "sha256:cdee07c4d7f6d72008d3f73b9bf027f4e11550224c7c50d8df1ae4a37c1402a6", size = 987241, upload-time = "2026-03-09T13:13:34.435Z" }, + { url = "https://files.pythonhosted.org/packages/ec/bd/c314595208e4c9587652d50959ead9e461995389664e490f4dce7ff0f782/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7c60d3c9b06fb23bd9c6139281ccbdc384297579ae037f08ae90c69f6845c0b1", size = 2227742, upload-time = "2026-03-09T13:13:36.4Z" }, + { url = "https://files.pythonhosted.org/packages/c1/43/0499cec932d935229b5543d073c2b87c9c22846aab48881e9d8d6e742a2d/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e315e5ec90d88e140f57696ff85b484ff68bb311e36f2c414aa4286293e6dee0", size = 2323966, upload-time = "2026-03-09T13:13:38.204Z" }, + { url = "https://files.pythonhosted.org/packages/3d/6f/79b0d760907965acfd9d61826a3d41f8f093c538f55cd2633d3f0db269f6/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:1465387ac63576c3e125e5337a6892b9e99e0627d52317f3ca79e6930d889d15", size = 1977417, upload-time = "2026-03-09T13:13:39.966Z" }, + { url = "https://files.pythonhosted.org/packages/ab/31/01d0537c41cb75a551a438c3c7a80d0c60d60b81f694dac83dd436aec0d0/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:530a3fd64c87cffa844d4b6b9768774763d9caa299e9b75d8eca6a4423b31314", size = 2491238, upload-time = "2026-03-09T13:13:41.698Z" }, + { url = "https://files.pythonhosted.org/packages/e4/34/8aefdd0be9cfd00a44509251ba864f5caf2991e36772e61c408007e7f417/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1d9daea4ea6b9be74fe2f01f7fbade8d6ffab263e781274cffca0dba9be9eec9", size = 2294947, upload-time = "2026-03-09T13:13:43.343Z" }, + { url = "https://files.pythonhosted.org/packages/ad/cf/0348374369ca588f8fe9c338fae49fa4e16eeb10ffb3d012f23a54578a9e/kiwisolver-1.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:f18c2d9782259a6dc132fdc7a63c168cbc74b35284b6d75c673958982a378384", size = 73569, upload-time = "2026-03-09T13:13:45.792Z" }, + { url = "https://files.pythonhosted.org/packages/28/26/192b26196e2316e2bd29deef67e37cdf9870d9af8e085e521afff0fed526/kiwisolver-1.5.0-cp312-cp312-win_arm64.whl", hash = "sha256:f7c7553b13f69c1b29a5bde08ddc6d9d0c8bfb84f9ed01c30db25944aeb852a7", size = 64997, upload-time = "2026-03-09T13:13:46.878Z" }, + { url = "https://files.pythonhosted.org/packages/9d/69/024d6711d5ba575aa65d5538042e99964104e97fa153a9f10bc369182bc2/kiwisolver-1.5.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:fd40bb9cd0891c4c3cb1ddf83f8bbfa15731a248fdc8162669405451e2724b09", size = 123166, upload-time = "2026-03-09T13:13:48.032Z" }, + { url = "https://files.pythonhosted.org/packages/ce/48/adbb40df306f587054a348831220812b9b1d787aff714cfbc8556e38fccd/kiwisolver-1.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c0e1403fd7c26d77c1f03e096dc58a5c726503fa0db0456678b8668f76f521e3", size = 66395, upload-time = "2026-03-09T13:13:49.365Z" }, + { url = "https://files.pythonhosted.org/packages/a8/3a/d0a972b34e1c63e2409413104216cd1caa02c5a37cb668d1687d466c1c45/kiwisolver-1.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dda366d548e89a90d88a86c692377d18d8bd64b39c1fb2b92cb31370e2896bbd", size = 64065, upload-time = "2026-03-09T13:13:50.562Z" }, + { url = "https://files.pythonhosted.org/packages/2b/0a/7b98e1e119878a27ba8618ca1e18b14f992ff1eda40f47bccccf4de44121/kiwisolver-1.5.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:332b4f0145c30b5f5ad9374881133e5aa64320428a57c2c2b61e9d891a51c2f3", size = 1477903, upload-time = "2026-03-09T13:13:52.084Z" }, + { url = "https://files.pythonhosted.org/packages/18/d8/55638d89ffd27799d5cc3d8aa28e12f4ce7a64d67b285114dbedc8ea4136/kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0c50b89ffd3e1a911c69a1dd3de7173c0cd10b130f56222e57898683841e4f96", size = 1278751, upload-time = "2026-03-09T13:13:54.673Z" }, + { url = "https://files.pythonhosted.org/packages/b8/97/b4c8d0d18421ecceba20ad8701358453b88e32414e6f6950b5a4bad54e65/kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4db576bb8c3ef9365f8b40fe0f671644de6736ae2c27a2c62d7d8a1b4329f099", size = 1296793, upload-time = "2026-03-09T13:13:56.287Z" }, + { url = "https://files.pythonhosted.org/packages/c4/10/f862f94b6389d8957448ec9df59450b81bec4abb318805375c401a1e6892/kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0b85aad90cea8ac6797a53b5d5f2e967334fa4d1149f031c4537569972596cb8", size = 1346041, upload-time = "2026-03-09T13:13:58.269Z" }, + { url = "https://files.pythonhosted.org/packages/a3/6a/f1650af35821eaf09de398ec0bc2aefc8f211f0cda50204c9f1673741ba9/kiwisolver-1.5.0-cp313-cp313-manylinux_2_39_riscv64.whl", hash = "sha256:d36ca54cb4c6c4686f7cbb7b817f66f5911c12ddb519450bbe86707155028f87", size = 987292, upload-time = "2026-03-09T13:13:59.871Z" }, + { url = "https://files.pythonhosted.org/packages/de/19/d7fb82984b9238115fe629c915007be608ebd23dc8629703d917dbfaffd4/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:38f4a703656f493b0ad185211ccfca7f0386120f022066b018eb5296d8613e23", size = 2227865, upload-time = "2026-03-09T13:14:01.401Z" }, + { url = "https://files.pythonhosted.org/packages/7f/b9/46b7f386589fd222dac9e9de9c956ce5bcefe2ee73b4e79891381dda8654/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3ac2360e93cb41be81121755c6462cff3beaa9967188c866e5fce5cf13170859", size = 2324369, upload-time = "2026-03-09T13:14:02.972Z" }, + { url = "https://files.pythonhosted.org/packages/92/8b/95e237cf3d9c642960153c769ddcbe278f182c8affb20cecc1cc983e7cc5/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c95cab08d1965db3d84a121f1c7ce7479bdd4072c9b3dafd8fecce48a2e6b902", size = 1977989, upload-time = "2026-03-09T13:14:04.503Z" }, + { url = "https://files.pythonhosted.org/packages/1b/95/980c9df53501892784997820136c01f62bc1865e31b82b9560f980c0e649/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fc20894c3d21194d8041a28b65622d5b86db786da6e3cfe73f0c762951a61167", size = 2491645, upload-time = "2026-03-09T13:14:06.106Z" }, + { url = "https://files.pythonhosted.org/packages/cb/32/900647fd0840abebe1561792c6b31e6a7c0e278fc3973d30572a965ca14c/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7a32f72973f0f950c1920475d5c5ea3d971b81b6f0ec53b8d0a956cc965f22e0", size = 2295237, upload-time = "2026-03-09T13:14:08.891Z" }, + { url = "https://files.pythonhosted.org/packages/be/8a/be60e3bbcf513cc5a50f4a3e88e1dcecebb79c1ad607a7222877becaa101/kiwisolver-1.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:0bf3acf1419fa93064a4c2189ac0b58e3be7872bf6ee6177b0d4c63dc4cea276", size = 73573, upload-time = "2026-03-09T13:14:12.327Z" }, + { url = "https://files.pythonhosted.org/packages/4d/d2/64be2e429eb4fca7f7e1c52a91b12663aeaf25de3895e5cca0f47ef2a8d0/kiwisolver-1.5.0-cp313-cp313-win_arm64.whl", hash = "sha256:fa8eb9ecdb7efb0b226acec134e0d709e87a909fa4971a54c0c4f6e88635484c", size = 64998, upload-time = "2026-03-09T13:14:13.469Z" }, + { url = "https://files.pythonhosted.org/packages/b0/69/ce68dd0c85755ae2de490bf015b62f2cea5f6b14ff00a463f9d0774449ff/kiwisolver-1.5.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:db485b3847d182b908b483b2ed133c66d88d49cacf98fd278fadafe11b4478d1", size = 125700, upload-time = "2026-03-09T13:14:14.636Z" }, + { url = "https://files.pythonhosted.org/packages/74/aa/937aac021cf9d4349990d47eb319309a51355ed1dbdc9c077cdc9224cb11/kiwisolver-1.5.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:be12f931839a3bdfe28b584db0e640a65a8bcbc24560ae3fdb025a449b3d754e", size = 67537, upload-time = "2026-03-09T13:14:15.808Z" }, + { url = "https://files.pythonhosted.org/packages/ee/20/3a87fbece2c40ad0f6f0aefa93542559159c5f99831d596050e8afae7a9f/kiwisolver-1.5.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:16b85d37c2cbb3253226d26e64663f755d88a03439a9c47df6246b35defbdfb7", size = 65514, upload-time = "2026-03-09T13:14:18.035Z" }, + { url = "https://files.pythonhosted.org/packages/f0/7f/f943879cda9007c45e1f7dba216d705c3a18d6b35830e488b6c6a4e7cdf0/kiwisolver-1.5.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4432b835675f0ea7414aab3d37d119f7226d24869b7a829caeab49ebda407b0c", size = 1584848, upload-time = "2026-03-09T13:14:19.745Z" }, + { url = "https://files.pythonhosted.org/packages/37/f8/4d4f85cc1870c127c88d950913370dd76138482161cd07eabbc450deff01/kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b0feb50971481a2cc44d94e88bdb02cdd497618252ae226b8eb1201b957e368", size = 1391542, upload-time = "2026-03-09T13:14:21.54Z" }, + { url = "https://files.pythonhosted.org/packages/04/0b/65dd2916c84d252b244bd405303220f729e7c17c9d7d33dca6feeff9ffc4/kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:56fa888f10d0f367155e76ce849fa1166fc9730d13bd2d65a2aa13b6f5424489", size = 1404447, upload-time = "2026-03-09T13:14:23.205Z" }, + { url = "https://files.pythonhosted.org/packages/39/5c/2606a373247babce9b1d056c03a04b65f3cf5290a8eac5d7bdead0a17e21/kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:940dda65d5e764406b9fb92761cbf462e4e63f712ab60ed98f70552e496f3bf1", size = 1455918, upload-time = "2026-03-09T13:14:24.74Z" }, + { url = "https://files.pythonhosted.org/packages/d5/d1/c6078b5756670658e9192a2ef11e939c92918833d2745f85cd14a6004bdf/kiwisolver-1.5.0-cp313-cp313t-manylinux_2_39_riscv64.whl", hash = "sha256:89fc958c702ee9a745e4700378f5d23fddbc46ff89e8fdbf5395c24d5c1452a3", size = 1072856, upload-time = "2026-03-09T13:14:26.597Z" }, + { url = "https://files.pythonhosted.org/packages/cb/c8/7def6ddf16eb2b3741d8b172bdaa9af882b03c78e9b0772975408801fa63/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9027d773c4ff81487181a925945743413f6069634d0b122d0b37684ccf4f1e18", size = 2333580, upload-time = "2026-03-09T13:14:28.237Z" }, + { url = "https://files.pythonhosted.org/packages/9e/87/2ac1fce0eb1e616fcd3c35caa23e665e9b1948bb984f4764790924594128/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:5b233ea3e165e43e35dba1d2b8ecc21cf070b45b65ae17dd2747d2713d942021", size = 2423018, upload-time = "2026-03-09T13:14:30.018Z" }, + { url = "https://files.pythonhosted.org/packages/67/13/c6700ccc6cc218716bfcda4935e4b2997039869b4ad8a94f364c5a3b8e63/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:ce9bf03dad3b46408c08649c6fbd6ca28a9fce0eb32fdfffa6775a13103b5310", size = 2062804, upload-time = "2026-03-09T13:14:32.888Z" }, + { url = "https://files.pythonhosted.org/packages/1b/bd/877056304626943ff0f1f44c08f584300c199b887cb3176cd7e34f1515f1/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:fc4d3f1fb9ca0ae9f97b095963bc6326f1dbfd3779d6679a1e016b9baaa153d3", size = 2597482, upload-time = "2026-03-09T13:14:34.971Z" }, + { url = "https://files.pythonhosted.org/packages/75/19/c60626c47bf0f8ac5dcf72c6c98e266d714f2fbbfd50cf6dab5ede3aaa50/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f443b4825c50a51ee68585522ab4a1d1257fac65896f282b4c6763337ac9f5d2", size = 2394328, upload-time = "2026-03-09T13:14:36.816Z" }, + { url = "https://files.pythonhosted.org/packages/47/84/6a6d5e5bb8273756c27b7d810d47f7ef2f1f9b9fd23c9ee9a3f8c75c9cef/kiwisolver-1.5.0-cp313-cp313t-win_arm64.whl", hash = "sha256:893ff3a711d1b515ba9da14ee090519bad4610ed1962fbe298a434e8c5f8db53", size = 68410, upload-time = "2026-03-09T13:14:38.695Z" }, + { url = "https://files.pythonhosted.org/packages/e4/d7/060f45052f2a01ad5762c8fdecd6d7a752b43400dc29ff75cd47225a40fd/kiwisolver-1.5.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8df31fe574b8b3993cc61764f40941111b25c2d9fea13d3ce24a49907cd2d615", size = 123231, upload-time = "2026-03-09T13:14:41.323Z" }, + { url = "https://files.pythonhosted.org/packages/c2/a7/78da680eadd06ff35edef6ef68a1ad273bad3e2a0936c9a885103230aece/kiwisolver-1.5.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:1d49a49ac4cbfb7c1375301cd1ec90169dfeae55ff84710d782260ce77a75a02", size = 66489, upload-time = "2026-03-09T13:14:42.534Z" }, + { url = "https://files.pythonhosted.org/packages/49/b2/97980f3ad4fae37dd7fe31626e2bf75fbf8bdf5d303950ec1fab39a12da8/kiwisolver-1.5.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0cbe94b69b819209a62cb27bdfa5dc2a8977d8de2f89dfd97ba4f53ed3af754e", size = 64063, upload-time = "2026-03-09T13:14:44.759Z" }, + { url = "https://files.pythonhosted.org/packages/e7/f9/b06c934a6aa8bc91f566bd2a214fd04c30506c2d9e2b6b171953216a65b6/kiwisolver-1.5.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:80aa065ffd378ff784822a6d7c3212f2d5f5e9c3589614b5c228b311fd3063ac", size = 1475913, upload-time = "2026-03-09T13:14:46.247Z" }, + { url = "https://files.pythonhosted.org/packages/6b/f0/f768ae564a710135630672981231320bc403cf9152b5596ec5289de0f106/kiwisolver-1.5.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e7f886f47ab881692f278ae901039a234e4025a68e6dfab514263a0b1c4ae05", size = 1282782, upload-time = "2026-03-09T13:14:48.458Z" }, + { url = "https://files.pythonhosted.org/packages/e2/9f/1de7aad00697325f05238a5f2eafbd487fb637cc27a558b5367a5f37fb7f/kiwisolver-1.5.0-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5060731cc3ed12ca3a8b57acd4aeca5bbc2f49216dd0bec1650a1acd89486bcd", size = 1300815, upload-time = "2026-03-09T13:14:50.721Z" }, + { url = "https://files.pythonhosted.org/packages/5a/c2/297f25141d2e468e0ce7f7a7b92e0cf8918143a0cbd3422c1ad627e85a06/kiwisolver-1.5.0-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7a4aa69609f40fce3cbc3f87b2061f042eee32f94b8f11db707b66a26461591a", size = 1347925, upload-time = "2026-03-09T13:14:52.304Z" }, + { url = "https://files.pythonhosted.org/packages/b9/d3/f4c73a02eb41520c47610207b21afa8cdd18fdbf64ffd94674ae21c4812d/kiwisolver-1.5.0-cp314-cp314-manylinux_2_39_riscv64.whl", hash = "sha256:d168fda2dbff7b9b5f38e693182d792a938c31db4dac3a80a4888de603c99554", size = 991322, upload-time = "2026-03-09T13:14:54.637Z" }, + { url = "https://files.pythonhosted.org/packages/7b/46/d3f2efef7732fcda98d22bf4ad5d3d71d545167a852ca710a494f4c15343/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:413b820229730d358efd838ecbab79902fe97094565fdc80ddb6b0a18c18a581", size = 2232857, upload-time = "2026-03-09T13:14:56.471Z" }, + { url = "https://files.pythonhosted.org/packages/3f/ec/2d9756bf2b6d26ae4349b8d3662fb3993f16d80c1f971c179ce862b9dbae/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:5124d1ea754509b09e53738ec185584cc609aae4a3b510aaf4ed6aa047ef9303", size = 2329376, upload-time = "2026-03-09T13:14:58.072Z" }, + { url = "https://files.pythonhosted.org/packages/8f/9f/876a0a0f2260f1bde92e002b3019a5fabc35e0939c7d945e0fa66185eb20/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e4415a8db000bf49a6dd1c478bf70062eaacff0f462b92b0ba68791a905861f9", size = 1982549, upload-time = "2026-03-09T13:14:59.668Z" }, + { url = "https://files.pythonhosted.org/packages/6c/4f/ba3624dfac23a64d54ac4179832860cb537c1b0af06024936e82ca4154a0/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:d618fd27420381a4f6044faa71f46d8bfd911bd077c555f7138ed88729bfbe79", size = 2494680, upload-time = "2026-03-09T13:15:01.364Z" }, + { url = "https://files.pythonhosted.org/packages/39/b7/97716b190ab98911b20d10bf92eca469121ec483b8ce0edd314f51bc85af/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5092eb5b1172947f57d6ea7d89b2f29650414e4293c47707eb499ec07a0ac796", size = 2297905, upload-time = "2026-03-09T13:15:03.925Z" }, + { url = "https://files.pythonhosted.org/packages/a3/36/4e551e8aa55c9188bca9abb5096805edbf7431072b76e2298e34fd3a3008/kiwisolver-1.5.0-cp314-cp314-win_amd64.whl", hash = "sha256:d76e2d8c75051d58177e762164d2e9ab92886534e3a12e795f103524f221dd8e", size = 75086, upload-time = "2026-03-09T13:15:07.775Z" }, + { url = "https://files.pythonhosted.org/packages/70/15/9b90f7df0e31a003c71649cf66ef61c3c1b862f48c81007fa2383c8bd8d7/kiwisolver-1.5.0-cp314-cp314-win_arm64.whl", hash = "sha256:fa6248cd194edff41d7ea9425ced8ca3a6f838bfb295f6f1d6e6bb694a8518df", size = 66577, upload-time = "2026-03-09T13:15:09.139Z" }, + { url = "https://files.pythonhosted.org/packages/17/01/7dc8c5443ff42b38e72731643ed7cf1ed9bf01691ae5cdca98501999ed83/kiwisolver-1.5.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:d1ffeb80b5676463d7a7d56acbe8e37a20ce725570e09549fe738e02ca6b7e1e", size = 125794, upload-time = "2026-03-09T13:15:10.525Z" }, + { url = "https://files.pythonhosted.org/packages/46/8a/b4ebe46ebaac6a303417fab10c2e165c557ddaff558f9699d302b256bc53/kiwisolver-1.5.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:bc4d8e252f532ab46a1de9349e2d27b91fce46736a9eedaa37beaca66f574ed4", size = 67646, upload-time = "2026-03-09T13:15:12.016Z" }, + { url = "https://files.pythonhosted.org/packages/60/35/10a844afc5f19d6f567359bf4789e26661755a2f36200d5d1ed8ad0126e5/kiwisolver-1.5.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6783e069732715ad0c3ce96dbf21dbc2235ab0593f2baf6338101f70371f4028", size = 65511, upload-time = "2026-03-09T13:15:13.311Z" }, + { url = "https://files.pythonhosted.org/packages/f8/8a/685b297052dd041dcebce8e8787b58923b6e78acc6115a0dc9189011c44b/kiwisolver-1.5.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e7c4c09a490dc4d4a7f8cbee56c606a320f9dc28cf92a7157a39d1ce7676a657", size = 1584858, upload-time = "2026-03-09T13:15:15.103Z" }, + { url = "https://files.pythonhosted.org/packages/9e/80/04865e3d4638ac5bddec28908916df4a3075b8c6cc101786a96803188b96/kiwisolver-1.5.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2a075bd7bd19c70cf67c8badfa36cf7c5d8de3c9ddb8420c51e10d9c50e94920", size = 1392539, upload-time = "2026-03-09T13:15:16.661Z" }, + { url = "https://files.pythonhosted.org/packages/ba/01/77a19cacc0893fa13fafa46d1bba06fb4dc2360b3292baf4b56d8e067b24/kiwisolver-1.5.0-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bdd3e53429ff02aa319ba59dfe4ceeec345bf46cf180ec2cf6fd5b942e7975e9", size = 1405310, upload-time = "2026-03-09T13:15:18.229Z" }, + { url = "https://files.pythonhosted.org/packages/53/39/bcaf5d0cca50e604cfa9b4e3ae1d64b50ca1ae5b754122396084599ef903/kiwisolver-1.5.0-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cdcb35dc9d807259c981a85531048ede628eabcffb3239adf3d17463518992d", size = 1456244, upload-time = "2026-03-09T13:15:20.444Z" }, + { url = "https://files.pythonhosted.org/packages/d0/7a/72c187abc6975f6978c3e39b7cf67aeb8b3c0a8f9790aa7fd412855e9e1f/kiwisolver-1.5.0-cp314-cp314t-manylinux_2_39_riscv64.whl", hash = "sha256:70d593af6a6ca332d1df73d519fddb5148edb15cd90d5f0155e3746a6d4fcc65", size = 1073154, upload-time = "2026-03-09T13:15:22.039Z" }, + { url = "https://files.pythonhosted.org/packages/c7/ca/cf5b25783ebbd59143b4371ed0c8428a278abe68d6d0104b01865b1bbd0f/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:377815a8616074cabbf3f53354e1d040c35815a134e01d7614b7692e4bf8acfa", size = 2334377, upload-time = "2026-03-09T13:15:23.741Z" }, + { url = "https://files.pythonhosted.org/packages/4a/e5/b1f492adc516796e88751282276745340e2a72dcd0d36cf7173e0daf3210/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0255a027391d52944eae1dbb5d4cc5903f57092f3674e8e544cdd2622826b3f0", size = 2425288, upload-time = "2026-03-09T13:15:25.789Z" }, + { url = "https://files.pythonhosted.org/packages/e6/e5/9b21fbe91a61b8f409d74a26498706e97a48008bfcd1864373d32a6ba31c/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:012b1eb16e28718fa782b5e61dc6f2da1f0792ca73bd05d54de6cb9561665fc9", size = 2063158, upload-time = "2026-03-09T13:15:27.63Z" }, + { url = "https://files.pythonhosted.org/packages/b1/02/83f47986138310f95ea95531f851b2a62227c11cbc3e690ae1374fe49f0f/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:0e3aafb33aed7479377e5e9a82e9d4bf87063741fc99fc7ae48b0f16e32bdd6f", size = 2597260, upload-time = "2026-03-09T13:15:29.421Z" }, + { url = "https://files.pythonhosted.org/packages/07/18/43a5f24608d8c313dd189cf838c8e68d75b115567c6279de7796197cfb6a/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e7a116ae737f0000343218c4edf5bd45893bfeaff0993c0b215d7124c9f77646", size = 2394403, upload-time = "2026-03-09T13:15:31.517Z" }, + { url = "https://files.pythonhosted.org/packages/3b/b5/98222136d839b8afabcaa943b09bd05888c2d36355b7e448550211d1fca4/kiwisolver-1.5.0-cp314-cp314t-win_amd64.whl", hash = "sha256:1dd9b0b119a350976a6d781e7278ec7aca0b201e1a9e2d23d9804afecb6ca681", size = 79687, upload-time = "2026-03-09T13:15:33.204Z" }, + { url = "https://files.pythonhosted.org/packages/99/a2/ca7dc962848040befed12732dff6acae7fb3c4f6fc4272b3f6c9a30b8713/kiwisolver-1.5.0-cp314-cp314t-win_arm64.whl", hash = "sha256:58f812017cd2985c21fbffb4864d59174d4903dd66fa23815e74bbc7a0e2dd57", size = 70032, upload-time = "2026-03-09T13:15:34.411Z" }, + { url = "https://files.pythonhosted.org/packages/1c/fa/2910df836372d8761bb6eff7d8bdcb1613b5c2e03f260efe7abe34d388a7/kiwisolver-1.5.0-graalpy312-graalpy250_312_native-macosx_10_13_x86_64.whl", hash = "sha256:5ae8e62c147495b01a0f4765c878e9bfdf843412446a247e28df59936e99e797", size = 130262, upload-time = "2026-03-09T13:15:35.629Z" }, + { url = "https://files.pythonhosted.org/packages/0f/41/c5f71f9f00aabcc71fee8b7475e3f64747282580c2fe748961ba29b18385/kiwisolver-1.5.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:f6764a4ccab3078db14a632420930f6186058750df066b8ea2a7106df91d3203", size = 138036, upload-time = "2026-03-09T13:15:36.894Z" }, + { url = "https://files.pythonhosted.org/packages/fa/06/7399a607f434119c6e1fdc8ec89a8d51ccccadf3341dee4ead6bd14caaf5/kiwisolver-1.5.0-graalpy312-graalpy250_312_native-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c31c13da98624f957b0fb1b5bae5383b2333c2c3f6793d9825dd5ce79b525cb7", size = 194295, upload-time = "2026-03-09T13:15:38.22Z" }, + { url = "https://files.pythonhosted.org/packages/b5/91/53255615acd2a1eaca307ede3c90eb550bae9c94581f8c00081b6b1c8f44/kiwisolver-1.5.0-graalpy312-graalpy250_312_native-win_amd64.whl", hash = "sha256:1f1489f769582498610e015a8ef2d36f28f505ab3096d0e16b4858a9ec214f57", size = 75987, upload-time = "2026-03-09T13:15:39.65Z" }, + { url = "https://files.pythonhosted.org/packages/e9/eb/5fcbbbf9a0e2c3a35effb88831a483345326bbc3a030a3b5b69aee647f84/kiwisolver-1.5.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ec4c85dc4b687c7f7f15f553ff26a98bfe8c58f5f7f0ac8905f0ba4c7be60232", size = 59532, upload-time = "2026-03-09T13:15:47.047Z" }, + { url = "https://files.pythonhosted.org/packages/c3/9b/e17104555bb4db148fd52327feea1e96be4b88e8e008b029002c281a21ab/kiwisolver-1.5.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:12e91c215a96e39f57989c8912ae761286ac5a9584d04030ceb3368a357f017a", size = 57420, upload-time = "2026-03-09T13:15:48.199Z" }, + { url = "https://files.pythonhosted.org/packages/48/44/2b5b95b7aa39fb2d8d9d956e0f3d5d45aef2ae1d942d4c3ffac2f9cfed1a/kiwisolver-1.5.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:be4a51a55833dc29ab5d7503e7bcb3b3af3402d266018137127450005cdfe737", size = 79892, upload-time = "2026-03-09T13:15:49.694Z" }, + { url = "https://files.pythonhosted.org/packages/52/7d/7157f9bba6b455cfb4632ed411e199fc8b8977642c2b12082e1bd9e6d173/kiwisolver-1.5.0-pp311-pypy311_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:daae526907e262de627d8f70058a0f64acc9e2641c164c99c8f594b34a799a16", size = 77603, upload-time = "2026-03-09T13:15:50.945Z" }, + { url = "https://files.pythonhosted.org/packages/0a/dd/8050c947d435c8d4bc94e3252f4d8bb8a76cfb424f043a8680be637a57f1/kiwisolver-1.5.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:59cd8683f575d96df5bb48f6add94afc055012c29e28124fcae2b63661b9efb1", size = 73558, upload-time = "2026-03-09T13:15:52.112Z" }, +] + [[package]] name = "linkify-it-py" version = "2.0.3" @@ -1306,6 +1554,70 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" }, ] +[[package]] +name = "matplotlib" +version = "3.11.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "contourpy" }, + { name = "cycler" }, + { name = "fonttools" }, + { name = "kiwisolver" }, + { name = "numpy" }, + { name = "packaging" }, + { name = "pillow" }, + { name = "pyparsing" }, + { name = "python-dateutil" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1f/24/080c99d223d158d3a8902769269ab6da5b50f7a0e6e072513907e02b7a6c/matplotlib-3.11.0.tar.gz", hash = "sha256:68c0c7be01b30dcca3638934f7f591df73401235cbdbf0d1ab1c71e7db7f8b57", size = 33251176, upload-time = "2026-06-12T02:29:15.508Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/a2/78f662f1b18968531f67d3fcde1b7ea8496920bacd4f16ddb5b79d112e46/matplotlib-3.11.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:f857524b442f0f36e641868ce2171aafa88cb0bc0644f4e1d8a5df9b32649fef", size = 9436261, upload-time = "2026-06-12T02:27:34.161Z" }, + { url = "https://files.pythonhosted.org/packages/5e/92/044f1de43901310202f4c79acf4f141be53b2ca8d8380e2fcefb3d523a75/matplotlib-3.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:57baa92fdc82948ed716eae6d2579d4d6f40965cd8d2f416755b4a72580a3233", size = 9264669, upload-time = "2026-06-12T02:27:37.413Z" }, + { url = "https://files.pythonhosted.org/packages/53/f4/f0b4f9ba7ec14a7af8151f3ad71ecfe3561e6ba38cfab1db3681ba4ca112/matplotlib-3.11.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:630eee0e67d35cce2019a0e670719f4816e3b86aff0fa72729f6c69786fceb45", size = 10021076, upload-time = "2026-06-12T02:27:39.926Z" }, + { url = "https://files.pythonhosted.org/packages/d7/33/4d679c6dcd594a156542080ac907ddccf7b09ca11655c4b28eca8e9ee5da/matplotlib-3.11.0-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5106c444d0bf966eee2853548c03772af4ab7199118e086c62fbac8ccb07c055", size = 10828999, upload-time = "2026-06-12T02:27:42.433Z" }, + { url = "https://files.pythonhosted.org/packages/07/74/0a3683802037d8cd013144d77c247219b47f2aabace6fdde74faa12bacf7/matplotlib-3.11.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4d7aea652b58e686444079be3376ef546bffa1eee9b9bb9c472b9fcf6cf410d3", size = 10913103, upload-time = "2026-06-12T02:27:44.827Z" }, + { url = "https://files.pythonhosted.org/packages/d0/9f/970fcbf381e82ec66fdf5da8ea76e2e9240f61a24011ce9fd1d42c37ac2d/matplotlib-3.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:70a5b3e9a5dab708c0f039709ae7c68d5b4d254e291ef76492cdba230c8bb5e4", size = 9310945, upload-time = "2026-06-12T02:27:46.867Z" }, + { url = "https://files.pythonhosted.org/packages/14/4e/6e7cfed23611265ded53806852343b5c59339e506e84c474a9b5afc3b249/matplotlib-3.11.0-cp311-cp311-win_arm64.whl", hash = "sha256:3d68266213e73823ac3be90615bab0cf31f88851e114cdb1dd25dacf3b01e1a7", size = 8999304, upload-time = "2026-06-12T02:27:48.798Z" }, + { url = "https://files.pythonhosted.org/packages/da/17/f5276b496c61477a6c4fc5e7401f4bfe1c2e5ef7c6cd67896f2ade3809cb/matplotlib-3.11.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:06b5872e9cf11adc8f589ded3ce11bc3e1061ad498259664fabc1f6615beb918", size = 9449976, upload-time = "2026-06-12T02:27:50.989Z" }, + { url = "https://files.pythonhosted.org/packages/82/34/bdd77418adb2178a1d59f044bd67bfebb115896e91b840b8a197eb3f4f4e/matplotlib-3.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0515d495124be3124340e59f164d901ed4484e2246a5b74cfa483cac3b80bd97", size = 9279307, upload-time = "2026-06-12T02:27:53.247Z" }, + { url = "https://files.pythonhosted.org/packages/94/95/7f522393c88313336b20d70fc849555757b2e5febc22b83b3a3f0fd4bce9/matplotlib-3.11.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:be5f93a1d21981bfb802ded0d77a0caa92d4342a47d45754fac77e314a506344", size = 10031353, upload-time = "2026-06-12T02:27:55.215Z" }, + { url = "https://files.pythonhosted.org/packages/87/ce/8f25a0e3186aefd61913e7467d1b999465bcd0d0c03ac695c1b26ca559b7/matplotlib-3.11.0-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41635d7909d19e52e924a521dde6d8f670b0f53ab1d0e8c331fa831554f681d1", size = 10839232, upload-time = "2026-06-12T02:27:57.746Z" }, + { url = "https://files.pythonhosted.org/packages/85/c2/db15da2bbdf9e3ca66df7db8e2c33a1dfed67be24a24d2c878efaaff01d6/matplotlib-3.11.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:94f5000f67ca9faa300863ea17f8bce9175cb67b88bec4bc7780502d53dd7c9e", size = 10923899, upload-time = "2026-06-12T02:28:00.223Z" }, + { url = "https://files.pythonhosted.org/packages/e5/2f/a58a4443a4d052a4ea77557478336aefc26c7981f6408d37adba763aa758/matplotlib-3.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:ac6f1ef39f3d0f9e2463303013094992cdbe0f85f43bc54155bc472b2042768e", size = 9329528, upload-time = "2026-06-12T02:28:02.27Z" }, + { url = "https://files.pythonhosted.org/packages/61/0f/4b669589d47733b97ab9df4b58d6fc1e68acb5ea42a928dc7cbdd6bf5871/matplotlib-3.11.0-cp312-cp312-win_arm64.whl", hash = "sha256:9dd11fb612ce7bc60b1de5b4fc87ff959d22317b5de42aabf392f66f97af22eb", size = 9003413, upload-time = "2026-06-12T02:28:04.49Z" }, + { url = "https://files.pythonhosted.org/packages/55/41/aa47f156b061d14c98b906f76c428507397708ec63ff94f410ae1752b426/matplotlib-3.11.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6ce3b839b34ae1f430b4616893a2945a2999debaa7e94e7e29a2a8bbf286f7b5", size = 9450532, upload-time = "2026-06-12T02:28:06.769Z" }, + { url = "https://files.pythonhosted.org/packages/8c/4f/5a9eb0375e81413953febf8af7b012a6b6357f53438a15c4f5ad86c6bbb5/matplotlib-3.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:373db8f91214e8ccaf35ac833cc1dd59dd961e148bbd55dd027141591dde1313", size = 9279760, upload-time = "2026-06-12T02:28:09.152Z" }, + { url = "https://files.pythonhosted.org/packages/a4/c0/1117d53077e3ac3152503a84e9cf7a5c239576805ee71276e80c2aaa7471/matplotlib-3.11.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:be152b7570324dc8d01574cc9474dd2d803237acf528bcbb5b211fa347461a09", size = 10031623, upload-time = "2026-06-12T02:28:11.26Z" }, + { url = "https://files.pythonhosted.org/packages/92/7e/e937138daffad65b71bf831a377809dcbc830fb4f31a31e067dc1faa2575/matplotlib-3.11.0-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:126f256df600652d7e4b394cf3164ff75210a00038f287c95a012a6f58d0e83f", size = 10839372, upload-time = "2026-06-12T02:28:14.102Z" }, + { url = "https://files.pythonhosted.org/packages/1d/c2/438ecc197ffb8023b6b9922915542f2172f5fd45b76703b0b4fc47322243/matplotlib-3.11.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:03acfeddf87b0dddb11b081ef7740ad445a3ca8bcb6b8e3011b08f2cf802b75c", size = 10924099, upload-time = "2026-06-12T02:28:16.383Z" }, + { url = "https://files.pythonhosted.org/packages/40/2e/395883da416f378b3ed2c9f3e843ac477eae1ce731b671b79adaa6f0bacd/matplotlib-3.11.0-cp313-cp313-win_amd64.whl", hash = "sha256:ab3722f04f3ff34c23b5012c5873d2894174e06c3822fcdac3610965a5ac7d06", size = 9329727, upload-time = "2026-06-12T02:28:18.581Z" }, + { url = "https://files.pythonhosted.org/packages/61/82/2c388956abf8bf392dfb5b8917c502f1082df6a941b781ab8c8e5ba2474b/matplotlib-3.11.0-cp313-cp313-win_arm64.whl", hash = "sha256:c945824670fb8915b4ac879e5e61f3c58e0913022f70a0de4c082b17372f8771", size = 9003506, upload-time = "2026-06-12T02:28:20.474Z" }, + { url = "https://files.pythonhosted.org/packages/c8/c1/34454baa44da7975ada82e9aea37105ec47059514dc967d3be14426ba8dc/matplotlib-3.11.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3489c3dc487669b4a980bc3068f87856de7a1564248d3f6c629efb2a58b03f24", size = 9499838, upload-time = "2026-06-12T02:28:22.713Z" }, + { url = "https://files.pythonhosted.org/packages/b1/c3/98fe79a398cf232219f090163a7fa7e6766e9f2e0ad26df54d6f8934d8ee/matplotlib-3.11.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:6a98f5476ce784a50ce09998f4ae1e6a9f25043cef8a480c98949902eda74620", size = 9332298, upload-time = "2026-06-12T02:28:24.796Z" }, + { url = "https://files.pythonhosted.org/packages/95/e4/b4b7c33151e74e5c802f3cde1ba807ebfc38401e329b44e215a5888dd76d/matplotlib-3.11.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:565af866fd63e4bd3f987d580afe27c44c2552a3b3305f4ecbb85133601ea6f3", size = 10045491, upload-time = "2026-06-12T02:28:27.141Z" }, + { url = "https://files.pythonhosted.org/packages/71/28/394548efd68354110c1a1be11fe6b6e559e06d1a23da35908a0e316c55a9/matplotlib-3.11.0-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e6b3e64dea5062c570f04358e2711859f3531b459f29516274fbad889079e4f3", size = 10857059, upload-time = "2026-06-12T02:28:29.222Z" }, + { url = "https://files.pythonhosted.org/packages/c8/44/e7922e6e2a4d63bdfbc9dc4a53e3850ab438d46cf42e6779bb15ec92c948/matplotlib-3.11.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:942b37c5db1899610bd1543ce8e13e4ecff9a4633e7f63bb6aa9205d2644ebd1", size = 10939576, upload-time = "2026-06-12T02:28:31.66Z" }, + { url = "https://files.pythonhosted.org/packages/3d/be/b1ca96003a441d619b727fee21d671fdff7a5ce2f1bb797b2521aa2f679a/matplotlib-3.11.0-cp313-cp313t-win_amd64.whl", hash = "sha256:c08e649a6313e1291e713623b97a38e5bb4aa580b2a100a94a3309bc6b9c8eb3", size = 9379519, upload-time = "2026-06-12T02:28:33.888Z" }, + { url = "https://files.pythonhosted.org/packages/e3/72/4bf3b91821c34596dd6a7bdac5836d94f744144c8208939ef49d8ec43f7e/matplotlib-3.11.0-cp313-cp313t-win_arm64.whl", hash = "sha256:2746cd2c113742ff6ce37a864c5ac5fd7aa644568f445e66166e457ac78e40e0", size = 9055456, upload-time = "2026-06-12T02:28:35.878Z" }, + { url = "https://files.pythonhosted.org/packages/57/52/a94102ac99eb78e2fe9b826674f9ef9ee23327110ea6ab4776c1b4eb6209/matplotlib-3.11.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:3338e3e3de128cf50d0d2fb92a122815daf9c755bd882a474343c05f8fd7ec79", size = 9452137, upload-time = "2026-06-12T02:28:37.93Z" }, + { url = "https://files.pythonhosted.org/packages/7c/03/b8cdb625a21f710dfa11bbca1f48fb4057d2c0286975f8b415bf80942c99/matplotlib-3.11.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:25c2e5455efd8d99f41fb79871a31feb7d301569642e332ec58d72cfe9282bc3", size = 9281514, upload-time = "2026-06-12T02:28:40.028Z" }, + { url = "https://files.pythonhosted.org/packages/b7/2d/4e1240ea82ee197dfb3851e71f71c87eeeb975f1753b56a0588e4e80739a/matplotlib-3.11.0-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d9695457a467ff86d23f35037a43deb6f1134dd6d3e2ac8ce1e2087cff09ffb9", size = 10843005, upload-time = "2026-06-12T02:28:42.39Z" }, + { url = "https://files.pythonhosted.org/packages/29/dc/6377ecfaa5fef79430f74a1a16638b4e2aa30d4692bae2c19f9d76fe3b01/matplotlib-3.11.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:19c16c61dea63b3582918503e6b294193961261d9daa806d4ae2151f1ad05430", size = 11127459, upload-time = "2026-06-12T02:28:44.483Z" }, + { url = "https://files.pythonhosted.org/packages/6f/41/795c405aa7560443a3b01309424cde4a1113b85c90b8a63417444a749617/matplotlib-3.11.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2d72ea8b7924f3cb955e61518d21e43b3df1e6c8a793b480a0c1214f185d30ba", size = 10925160, upload-time = "2026-06-12T02:28:46.564Z" }, + { url = "https://files.pythonhosted.org/packages/1a/f7/3a9e6389a7cfaeff76c56e40c2dabcb13110e21e82f837228c834ebe748c/matplotlib-3.11.0-cp314-cp314-win_amd64.whl", hash = "sha256:1c02da0a629dfa9debf52725ea06866b74c1fb70a895bae05e4493d34074f9f2", size = 9485186, upload-time = "2026-06-12T02:28:49.344Z" }, + { url = "https://files.pythonhosted.org/packages/8b/c0/396478ee7cf2091d182db8b4a8695f6a37f1ddb978989cf9dbb84cd5c123/matplotlib-3.11.0-cp314-cp314-win_arm64.whl", hash = "sha256:aa55d73b3117d4b07f959cd9eb6f69b375d8df3414139c479388e551aa5d999d", size = 9160349, upload-time = "2026-06-12T02:28:51.382Z" }, + { url = "https://files.pythonhosted.org/packages/c5/6f/1c3bd51bb2b34eaacdcf3c3d859dbb357f952fc8020c617dc118ad7c9e38/matplotlib-3.11.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:a9d8c6e7cd2f0ddf11d8d92e520dd1d9d2abb0cf6ac8831e338666c81e905847", size = 9500921, upload-time = "2026-06-12T02:28:53.443Z" }, + { url = "https://files.pythonhosted.org/packages/e0/0d/4d861d0121840cb1a3fd4a10deb211efd6fccd481ed23e553f31f4f4da4a/matplotlib-3.11.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:be050fcf32f729eda99f7f75a80bf67612ce16ab9ac1c23a387dcaede95cb70e", size = 9332190, upload-time = "2026-06-12T02:28:55.623Z" }, + { url = "https://files.pythonhosted.org/packages/4b/cb/22f6bc35711a0b5639a784e74e653e77c86210bd4304449dd399a482f74e/matplotlib-3.11.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dfabef0230d0697aa0d717385194dd41162e00207a68bf4abf94c2bf4c27dca0", size = 10854181, upload-time = "2026-06-12T02:28:57.856Z" }, + { url = "https://files.pythonhosted.org/packages/3f/7e/9a9eaca731a2939589da520f0ebe8fd8753d0f51fca98c7d20af6dbe261a/matplotlib-3.11.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1644db30e759199443493ac5e5caec24fdb775a8f6123021f85ba47c4133c3cb", size = 11137715, upload-time = "2026-06-12T02:29:00.555Z" }, + { url = "https://files.pythonhosted.org/packages/ef/f9/9b030b6088354acb0296871bb624b25befc1c42509d3c6cd17420c83a5b8/matplotlib-3.11.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:15b0d160079cb10699a0e98b5989c70677b2df7cacdc62af67c30f2facec46d9", size = 10939427, upload-time = "2026-06-12T02:29:02.527Z" }, + { url = "https://files.pythonhosted.org/packages/59/94/6b273eaee4ee250863567d100865da61a5c1527fa67f527b7ed22e0dd29c/matplotlib-3.11.0-cp314-cp314t-win_amd64.whl", hash = "sha256:446307e6b04b57b1f1239e228a1ec2af0d589a1008cebc3dfa3f5441d095cfb6", size = 9535809, upload-time = "2026-06-12T02:29:04.994Z" }, + { url = "https://files.pythonhosted.org/packages/60/95/1d36bddf2b7e2692c1540e78a6e5bc88bc1496b137e3e35a611f91b65ac3/matplotlib-3.11.0-cp314-cp314t-win_arm64.whl", hash = "sha256:652fb5696271d4c50f196d22a5ff4f8e4444c74f847423570d7dc0aa2bbd0159", size = 9209226, upload-time = "2026-06-12T02:29:07.033Z" }, + { url = "https://files.pythonhosted.org/packages/0f/c2/f5da6cd37ed6871f5c9b3c0507ddb69f14d6c36fac4541e4e0c60cb8cdfc/matplotlib-3.11.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:81ae77077a1e16d37a5b61096ccb07c8d90a99b518fa8256b8f21578932f2f62", size = 9434094, upload-time = "2026-06-12T02:29:09.135Z" }, + { url = "https://files.pythonhosted.org/packages/f8/07/56f66906e0f87a0c6d0d0acbd34dbc9432b1931d8f26ef618bd6f92932a9/matplotlib-3.11.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ddef37840695f5eef65f9f070fe2d2f510f584c2156203f9f622a5b0584efffd", size = 9262183, upload-time = "2026-06-12T02:29:11.283Z" }, + { url = "https://files.pythonhosted.org/packages/0c/d8/c4ecab06b7ea36a570c4f3bd2d48d1799fd5d9174470e45c2194199431e7/matplotlib-3.11.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cf662e5ac5707658cb931e19972c4bd99f7b4f8b7bf79d3c821d239fa6b71e64", size = 10015653, upload-time = "2026-06-12T02:29:13.251Z" }, +] + [[package]] name = "mdit-py-plugins" version = "0.5.0" @@ -1838,6 +2150,91 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" }, ] +[[package]] +name = "pillow" +version = "12.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1c/3d/bb7fca845737cf9d7dbde16ed1843984665ff2e0a518f5db43e77ec540b9/pillow-12.3.0.tar.gz", hash = "sha256:3b8182a766685eaa002637e28b4ec8d6b18819a0c71f579bf0dbaa5830297cce", size = 47025035, upload-time = "2026-07-01T11:56:38.965Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/c8/0a78b0e02d7ac54bc03e5321c9220da52f0c2ea83b21f7c40e7f3169c502/pillow-12.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:00808c5e14ef63ac5161091d242999076604ff74b883423a11e5d7bbb38bf756", size = 5392415, upload-time = "2026-07-01T11:53:47.162Z" }, + { url = "https://files.pythonhosted.org/packages/b2/5b/a02d30018abd97ced9f5a6c63d28597694a00d066516b9c1c6de45859fc9/pillow-12.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:37d6d0a00072fd2948eb22bce7e1475f34569d90c87c59f7a2ec59541b77f7a6", size = 4785266, upload-time = "2026-07-01T11:53:49.079Z" }, + { url = "https://files.pythonhosted.org/packages/c8/98/766667a4be768150a202836acd9fad19c06824ca86c4286d3cf6b274964e/pillow-12.3.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bcb46e2f9feff8d06323983bd83ed00c201fdcab3d74973e7072a889b3979fcd", size = 6263814, upload-time = "2026-07-01T11:53:51.32Z" }, + { url = "https://files.pythonhosted.org/packages/3b/2d/ede717bc1144f63886c21fd349bb95860b0d1a21149ff16f2bb362b612b6/pillow-12.3.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23d27a3e0307ec2244cc51e7287b919aa68d097504ebe19df4e76a98a3eea5bd", size = 6934408, upload-time = "2026-07-01T11:53:53.487Z" }, + { url = "https://files.pythonhosted.org/packages/a3/48/9c58b685e69d49c31af6c8eb9012055fab7e665785165c84796e2c73ce72/pillow-12.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4f883547d4b7f0495ebe7056b0cc2aea76094e7a4abc8e933540f3271df27d9c", size = 6337160, upload-time = "2026-07-01T11:53:55.457Z" }, + { url = "https://files.pythonhosted.org/packages/ff/fa/dc2a5c0ba6df93f67c31d34b808b7ce440b40cdbf96f0b81cde1d1e6fa93/pillow-12.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:236ff70b9312fb68943c703aa842ca6a758abfa45ac187a5e7c1452e96ef72b5", size = 7045172, upload-time = "2026-07-01T11:53:57.736Z" }, + { url = "https://files.pythonhosted.org/packages/86/a5/444817a4d4c4c2417df00513086ca196f388d8f9ef40c2e4ccd1ad1af54b/pillow-12.3.0-cp311-cp311-win32.whl", hash = "sha256:10e41f0fbf1eec8cfd234b8fe17a4caac7c9d0db4c204d3c173a8f9f6ef3232b", size = 6472232, upload-time = "2026-07-01T11:53:59.767Z" }, + { url = "https://files.pythonhosted.org/packages/63/c6/4bad1b18d132a50b27e1365e1ab163616f7a5bb56d330f66f9d1d9d4f9d4/pillow-12.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:8e95e1385e4998ae9694eeaa4730ba5457ff61185b3a55e2e7bea0880aef452a", size = 7233653, upload-time = "2026-07-01T11:54:02.066Z" }, + { url = "https://files.pythonhosted.org/packages/fd/16/00f91ab7760dc842f5aad55217e80fc4a7067a0604535249bc8a2d6d9870/pillow-12.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:ebaea975e03d3141d9d3a507df75c9b3ec90fa9d2ffd07567b3a978d9d790b26", size = 2568195, upload-time = "2026-07-01T11:54:04.622Z" }, + { url = "https://files.pythonhosted.org/packages/37/bf/fb3ebff8ddcb76aac5a01389251bbbb9519922a9b520d8247c1ca864a25d/pillow-12.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ba09209fbe443b4acccebe845d8a138b89a8f4fbaeedd44953490b5315d5e965", size = 5345969, upload-time = "2026-07-01T11:54:06.397Z" }, + { url = "https://files.pythonhosted.org/packages/d8/66/9a386a92561f402389a4fc70c18838bf6d35eb5eb5c6850b4b2dc64f5048/pillow-12.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffd0c5368496f41b0944be820fcb7a838aa6e623d250b01acf2643939c3f99d7", size = 4780323, upload-time = "2026-07-01T11:54:09.351Z" }, + { url = "https://files.pythonhosted.org/packages/25/27/ac8f99618ffd3dde21db0f4d4b1d2ab00c0880595bfd17df103f7f39fd0c/pillow-12.3.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d9c7f76c0673154f044e9d78c8655fb4213f6ca31a836df48b40fe5d187717b9", size = 6266838, upload-time = "2026-07-01T11:54:11.71Z" }, + { url = "https://files.pythonhosted.org/packages/84/21/a35af28dcc61f37ed850a2d64c65c701321dfbf25085e469d5559360cbbf/pillow-12.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:78cb2c6865a35ab8ff8b75fd122f6033b92a62c82801110e48ddd6c936a45d91", size = 6940830, upload-time = "2026-07-01T11:54:13.732Z" }, + { url = "https://files.pythonhosted.org/packages/eb/51/8b08617af3ad95e33ce6d7dd2c99ed6c8298f7fb131636303956be022e25/pillow-12.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e491916b378fba47242221bb9ead245211b70d504f495d105d17b14a24b4907c", size = 6344383, upload-time = "2026-07-01T11:54:15.756Z" }, + { url = "https://files.pythonhosted.org/packages/1d/72/cf78ac9780bb93c28328f408973845a309d4d145041665f734572ced1b52/pillow-12.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0dd2064cbc55aaec028ef5fbb60fa47bb6c3e7918e07ff17935284b227a9d2df", size = 7052934, upload-time = "2026-07-01T11:54:17.721Z" }, + { url = "https://files.pythonhosted.org/packages/20/20/25e0f4dc178a6bc0696793720055519a0de89e7661dae886992decbd2f81/pillow-12.3.0-cp312-cp312-win32.whl", hash = "sha256:dbce0b29841537a2fa4a214c2bbf14de3587c9680caa9b4e217568472490b28f", size = 6472684, upload-time = "2026-07-01T11:54:19.839Z" }, + { url = "https://files.pythonhosted.org/packages/45/89/da2f7971a317f83d807fdd4065c0af40208e59e692cc43d315a71a0e96d1/pillow-12.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:a2b55dd6b2a4c4b7d87ffa56bdb33fdc5fdb9a462173861a7bc097f17d91cb09", size = 7227137, upload-time = "2026-07-01T11:54:22.025Z" }, + { url = "https://files.pythonhosted.org/packages/de/47/4845a0a6c0dbf1db8456bd9fc791f13c5ced7ced20606d08a0aacfd25b49/pillow-12.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:331b624368d4f1d069149002f25f44bc61c8919ce8ddb3c45bdad8f6e2d89510", size = 2568267, upload-time = "2026-07-01T11:54:24.051Z" }, + { url = "https://files.pythonhosted.org/packages/9d/ac/31fb64e1e7efb5a4b50cd3d92049ba89ac6e4d8d3bb6a74e15048ca3353e/pillow-12.3.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:21900ce7ba264168cd50defae43cd75d25c833ad4ad6e73ffc5596d12e25ac89", size = 4161684, upload-time = "2026-07-01T11:54:25.934Z" }, + { url = "https://files.pythonhosted.org/packages/87/b4/9805e23d2b4d77842b468513841fda254ee42f0289d25088340e4ff46e2d/pillow-12.3.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:4e8c2a84d977f50b9daed6eeaf3baef67d00d5d74d932288f02cb94518ee3ace", size = 4255487, upload-time = "2026-07-01T11:54:27.935Z" }, + { url = "https://files.pythonhosted.org/packages/df/39/ecf519435a200c693fe053a6ee4d835b41cf963a4dfc2551c4e637cb2a71/pillow-12.3.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:ae26d61dfa7a47befdc7572b521024e8745f3d809bd95ca9505a7bba9ef849ec", size = 3696433, upload-time = "2026-07-01T11:54:29.813Z" }, + { url = "https://files.pythonhosted.org/packages/42/92/2fc3ffad878ae8dd5469ec1bc8eb83b71f48e13efdf68f02709003982a32/pillow-12.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7a743ff716f746fc19a9557f60dab1600d4613255f8a7aeb3cdde4db7eb15a66", size = 5345889, upload-time = "2026-07-01T11:54:31.97Z" }, + { url = "https://files.pythonhosted.org/packages/10/76/8803c13605b763d33d156c4678fc77f8443389c0c51c8aef707bb02015f4/pillow-12.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d69141514cc30b774ceea5e3ed3a6635c8d8a96edf664689b890f4089111fb35", size = 4780109, upload-time = "2026-07-01T11:54:34.026Z" }, + { url = "https://files.pythonhosted.org/packages/1f/01/e18aff37cb0b4aac47ac90f016d347a49aca667ef97f190b06ac2aabc928/pillow-12.3.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f7401aebd7f581d7f83a439d87d474999317ee099218e5ad25d125290990ba65", size = 6263736, upload-time = "2026-07-01T11:54:36.131Z" }, + { url = "https://files.pythonhosted.org/packages/f7/62/de5bdd77d935331f4f802edc11e4d82950f642caad6cb2f949837b8560e2/pillow-12.3.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0847a763afefb695bc912d7c131e7e0632d4edc1d8698f58ddabec8e46b8b6d3", size = 6937129, upload-time = "2026-07-01T11:54:38.216Z" }, + { url = "https://files.pythonhosted.org/packages/70/4d/105627a13300c5e0df1d174230b32fd1273062c96f7745fd552b945d1e1d/pillow-12.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:571b9fcb07b97ef3a492028fb3d2dc0993ca23a06138b0315286566d29ef718a", size = 6339562, upload-time = "2026-07-01T11:54:40.354Z" }, + { url = "https://files.pythonhosted.org/packages/6b/1d/f13de01a553988ab895ba1c722e06cf3144d4f57656fd5b81b6d881f1179/pillow-12.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:756c768d0c9c2955feb7a56c37ea24aea2e369f8d36a88da270b6a9f19e62b5e", size = 7049439, upload-time = "2026-07-01T11:54:42.489Z" }, + { url = "https://files.pythonhosted.org/packages/c9/f9/066794cca041b969964f779ee5fa66a9498bbf34248ac39c5d7954e4198f/pillow-12.3.0-cp313-cp313-win32.whl", hash = "sha256:a876864214e136f0eb367788dbd7df045f4806801518e2cfe9e13229cfe06d8f", size = 6473287, upload-time = "2026-07-01T11:54:44.9Z" }, + { url = "https://files.pythonhosted.org/packages/a6/9b/7a58e61d62be561da3a356fe2384d4059a6345fc130e23ef1c36a5b81d24/pillow-12.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:1cca606cd25738df4ed873d5ad46bbdb3d83b5cbca291f6b4ff13a4df6b0bbe8", size = 7239691, upload-time = "2026-07-01T11:54:47.141Z" }, + { url = "https://files.pythonhosted.org/packages/aa/b0/c4ed4f0ef8f8fa5ee8351537db6650bb8189f7e118842978dd6589065692/pillow-12.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:b629de27fda84b42cde7edef0d85f13b958b47f6e9bbcbba9b673c562a89bd8b", size = 2568185, upload-time = "2026-07-01T11:54:49.137Z" }, + { url = "https://files.pythonhosted.org/packages/dc/01/001f65b68192f0228cc1dbbc8d2530ab5d58b61037ba0587f946fea607cd/pillow-12.3.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:9cf95fe4d0f84c82d282745d9bb08ad9f926efa00be4697e767b814ce40d4330", size = 4161736, upload-time = "2026-07-01T11:54:51.156Z" }, + { url = "https://files.pythonhosted.org/packages/1a/d2/0219746d0fd16fc8a84498e79452375be3797d3ce4044596ce565164b84f/pillow-12.3.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:8728f216dcdb6e6d555cf971cb34076139ad74b31fc2c14da4fafc741c5f6217", size = 4255435, upload-time = "2026-07-01T11:54:53.414Z" }, + { url = "https://files.pythonhosted.org/packages/c8/02/8d0bc62ef0302318c46ff2a512822d2610e81c7aa46c9b3abe6cbaca5ad0/pillow-12.3.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:a45650e8ce7fafffd731db8550230db6b0d306d181a90b67d3e6bca2f1990930", size = 3696262, upload-time = "2026-07-01T11:54:55.739Z" }, + { url = "https://files.pythonhosted.org/packages/85/e2/73c77d218410b14f5f2d565e8a998d5317b7b9c75368d29985139f7a46f0/pillow-12.3.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:ba54cfebe86920a559a7c4d6b9050791c20513650a1952ebe3368c7dc70306f8", size = 5350344, upload-time = "2026-07-01T11:54:57.657Z" }, + { url = "https://files.pythonhosted.org/packages/c7/da/32c752228ae345f489e3a42499d817b6c3996da7e8a3bc7a04fc806b243b/pillow-12.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e158cb00350dc278f3b91551101aa7d12415a66ebf2c91d8d5ac14e56ddd3ad0", size = 4780131, upload-time = "2026-07-01T11:54:59.713Z" }, + { url = "https://files.pythonhosted.org/packages/b1/9d/8b2c807dbef61a5197c047afe99823787eb66f63daf9fb2432f91d6f0462/pillow-12.3.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e9aeb04d6aef139de265b29683e119b638208f88cf73cdd1658aa07221165321", size = 6263757, upload-time = "2026-07-01T11:55:01.778Z" }, + { url = "https://files.pythonhosted.org/packages/5c/44/c85361f65dbe00eea8576ee467c768d25129989efb76e94f205e9ca9bb46/pillow-12.3.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:251bf95b67017e27b13d82f5b326234ca62d70f9cf4c2b9032de2358a3b12c7b", size = 6936962, upload-time = "2026-07-01T11:55:03.93Z" }, + { url = "https://files.pythonhosted.org/packages/18/7e/e483414b35800b86b6f08dbbc7803fb5cd52c4d6f897f47d53ea2c7e6f65/pillow-12.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fe3cca2e4e8a592be0f269a1ca4835c25199d9f3ce815c8491048f785b0a0198", size = 6339171, upload-time = "2026-07-01T11:55:05.989Z" }, + { url = "https://files.pythonhosted.org/packages/f0/f4/68c491844841ede6bed70189546b3ee9731cf9f2cbad396faff5e1ccba45/pillow-12.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:23aceaa007d6172b02c277f0cd359c79492bbb14f7072b4ede9fbcaf20648130", size = 7048116, upload-time = "2026-07-01T11:55:08.131Z" }, + { url = "https://files.pythonhosted.org/packages/a3/34/77f3f793fed8efc7d243f21b33c5a3f0d1c97ee70346d3db855587e155ff/pillow-12.3.0-cp314-cp314-win32.whl", hash = "sha256:af8d94b0db561cf68b88a267c5c44b49e134f525d0dc2cb7ed413a66bc23559a", size = 6467209, upload-time = "2026-07-01T11:55:10.408Z" }, + { url = "https://files.pythonhosted.org/packages/f1/e0/492879f69d94f91f60fc8cd05ba03650e9520afebb2fb7aa12777d7c7f38/pillow-12.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:fdafc9cce40277e0f7a0feabce0ee50dd2fa1800f3b38015e51296b5e814048d", size = 7237707, upload-time = "2026-07-01T11:55:12.745Z" }, + { url = "https://files.pythonhosted.org/packages/c9/ac/6b11f2875f1c2ac040d84e1bbf9cf22a88038f901ca1037898b280b38365/pillow-12.3.0-cp314-cp314-win_arm64.whl", hash = "sha256:e91206ee562682b51b98ef4b26a6ef48fd84e15fd4c4bc5ec768eb641d206838", size = 2565995, upload-time = "2026-07-01T11:55:14.736Z" }, + { url = "https://files.pythonhosted.org/packages/52/69/c2208e56af9bfc1913afb24020297a691eb1d4ef688474c8a04913f65e04/pillow-12.3.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:164b31cd1a0490ab6efae01aa5df49da7061be0af1b30e035b6e9a1bfe34ee6e", size = 5352503, upload-time = "2026-07-01T11:55:17.076Z" }, + { url = "https://files.pythonhosted.org/packages/07/70/e5686d753e898a45d778ff1718dba8516ead6ab6b95d85fc8c4b70650cf2/pillow-12.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5afb51d599ea772b8365ae807ae557f18bccfe46ab261fd1c2a9ed700fc6eb17", size = 4782956, upload-time = "2026-07-01T11:55:19.448Z" }, + { url = "https://files.pythonhosted.org/packages/d5/37/25c6692f06927ee973ff18c8d9ee98ad0b4d84ee67a09610c2dd1447958e/pillow-12.3.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3edce1d53195db527e0191f84b71d02022de0540bf43a16ed734ed7537b07385", size = 6322855, upload-time = "2026-07-01T11:55:21.613Z" }, + { url = "https://files.pythonhosted.org/packages/cc/91/420637fcb8f1bc11029e403b4538e6694744428d8246118e45719f944556/pillow-12.3.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bf16ba1b4d0b6b7c8e534936632270cf70eb00dbe09005bc345b2677b726855c", size = 6989642, upload-time = "2026-07-01T11:55:24.006Z" }, + { url = "https://files.pythonhosted.org/packages/10/08/b94d7811281ccf0d143a1cf768d1c49e1e54af63e7b708ab2ee3eb87face/pillow-12.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:24870b09b224f7ae3c39ed07d10e819d06f8720bc551847b1d623832b5b0e28d", size = 6391281, upload-time = "2026-07-01T11:55:26.252Z" }, + { url = "https://files.pythonhosted.org/packages/d2/87/24233f785f55474dc02ce3e739c5528a77e3a862e9333d1dd7a25cc31f70/pillow-12.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:30f2aa603c41533cc25c05acd0da21636e84a315768feb631c937177db558931", size = 7096716, upload-time = "2026-07-01T11:55:28.318Z" }, + { url = "https://files.pythonhosted.org/packages/23/26/fcb2f6e37175b04f53570b59937867e2b80ee1685e744023153028fc14f9/pillow-12.3.0-cp314-cp314t-win32.whl", hash = "sha256:4b0a7fe987b14c31ebda6083f74f22b561fd3739bc0ac51e019622e3d72668c7", size = 6474125, upload-time = "2026-07-01T11:55:30.956Z" }, + { url = "https://files.pythonhosted.org/packages/90/de/3634abee5f1c9e13c56787b7d5517b0ba8d6de51700b95578cf338349c9f/pillow-12.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:962864dc93511324d51ddbb5b9f8731bf71675b93ca612a07441896f4688fb8c", size = 7242939, upload-time = "2026-07-01T11:55:34.044Z" }, + { url = "https://files.pythonhosted.org/packages/ce/2a/fd13f8eb24de5714a6eb444a3d67e2842c6c576e159a43793adf23051351/pillow-12.3.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0740a512dc522224c77d9aa5a8d70d8b7d73fb91f2c21125d8d025d3b8990e45", size = 2567506, upload-time = "2026-07-01T11:55:35.988Z" }, + { url = "https://files.pythonhosted.org/packages/5d/dc/8fdce34ec725a33c81c6ba122b904d6b9024e50ea9ac7bede62fab54506c/pillow-12.3.0-cp315-cp315-ios_13_0_arm64_iphoneos.whl", hash = "sha256:0feb2e9d6ad6c9e3c06effe9d00f3f1e618a6643273576b016f591e9315a7139", size = 4162063, upload-time = "2026-07-01T11:55:37.941Z" }, + { url = "https://files.pythonhosted.org/packages/76/66/2044b9a63d3b84ff048228dfcb7cd9bf0df983e8470971bf7d4c57b693de/pillow-12.3.0-cp315-cp315-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:9e881fca225083806662a5c43d627d215f258ff43c890f831966c7d7ba9c7402", size = 4255549, upload-time = "2026-07-01T11:55:40.022Z" }, + { url = "https://files.pythonhosted.org/packages/52/7e/1f67e6f4ece6b582ee4b539decbcc9f848dc245a93ed8cd7338bafef72f1/pillow-12.3.0-cp315-cp315-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:4998562bf62a445225f22e07c896bb04b35b1b1f2eb6d760584c9c51d7a5f78c", size = 3696331, upload-time = "2026-07-01T11:55:41.98Z" }, + { url = "https://files.pythonhosted.org/packages/12/40/d306fc2c8e4d45d7f175c77edca7063be7b86fe7fe6e68f4353bf71d808c/pillow-12.3.0-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:dc624f6bc473dacdf7ef7eb8678d0d08edf15cd94fad6ae5c7d6cc67a4e4902f", size = 5350370, upload-time = "2026-07-01T11:55:44.028Z" }, + { url = "https://files.pythonhosted.org/packages/dd/44/668fb1437e8ce420f62d6106eb66e44a5971602a4d794615bdf79315d82d/pillow-12.3.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:71d6097b330eea8fd15097780c8e89cb1a8ce7838669f48c5bacd6f663dd4701", size = 4780147, upload-time = "2026-07-01T11:55:46.073Z" }, + { url = "https://files.pythonhosted.org/packages/0c/08/93fa2e70e30a2d81547e481b6ee2bb9522117221fb1e0ce4b5df70967677/pillow-12.3.0-cp315-cp315-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:28ce87c5ab450a9dd970b52e5aca5fe63ed432d18a2eaddd1979a00a1ba24ace", size = 6273659, upload-time = "2026-07-01T11:55:48.264Z" }, + { url = "https://files.pythonhosted.org/packages/f8/6d/043e96ff814fc31a33077e4cba86082167db520c93632afdf2042febbb0c/pillow-12.3.0-cp315-cp315-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6b02afb9b97f65fbca5f31db6a2a3ba21aa93030225f150fa3f249717e938fb4", size = 6947439, upload-time = "2026-07-01T11:55:50.503Z" }, + { url = "https://files.pythonhosted.org/packages/af/92/ba71d2ee2ac0edf3fa33bd9d5ee9ee080da70b1766f3ca3934f9938ddac9/pillow-12.3.0-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:1182d52bc2d5e5d7d0949503aa7e36d12f42205dc287e4883f407b1988820d39", size = 6353577, upload-time = "2026-07-01T11:55:52.697Z" }, + { url = "https://files.pythonhosted.org/packages/0f/ce/e63064e2122923ff687c8ad792d0d736a7b3920a56a46982e81a7fdd25d6/pillow-12.3.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:e795b7eb908249c4e43c7c99fac7c2c75dab0c43566e37db472a355f63693d71", size = 7060394, upload-time = "2026-07-01T11:55:55.149Z" }, + { url = "https://files.pythonhosted.org/packages/54/76/a09cc3ccc8d773a7283d34c38bec1708f9e3cc932093cbc4c5e71ac4060b/pillow-12.3.0-cp315-cp315-win32.whl", hash = "sha256:57b3d78c95ba9059768b10e28b813002261d3f3dfc55cc48b0c988f625175827", size = 6467375, upload-time = "2026-07-01T11:55:57.769Z" }, + { url = "https://files.pythonhosted.org/packages/3e/03/1846c49ba3b1d5550392a4bbd06d6fb4578e1cd91a803198b5c90f5f7d53/pillow-12.3.0-cp315-cp315-win_amd64.whl", hash = "sha256:fa4ecea169a355be7a3ade2c783e2ed12f0e40d2c5621cda8b3297faf7fbb9f5", size = 7237048, upload-time = "2026-07-01T11:55:59.975Z" }, + { url = "https://files.pythonhosted.org/packages/fb/bb/89f35dcc79610423f9f195504d7def7f0d1416a711541b42867e25fe3412/pillow-12.3.0-cp315-cp315-win_arm64.whl", hash = "sha256:877c3f311ff35410f690861c4409e7ccbf0cd2f878e50628a28e5a0bb689e658", size = 2566006, upload-time = "2026-07-01T11:56:02.143Z" }, + { url = "https://files.pythonhosted.org/packages/30/88/707027ba09942dfa2c28759b5c222d769290a41c6d20ea60ec250801941f/pillow-12.3.0-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:e9871b1ffbfa9656b60aeee92ed5136a5742696006fa322b29ea3d8da0ecc9cf", size = 5352509, upload-time = "2026-07-01T11:56:04.2Z" }, + { url = "https://files.pythonhosted.org/packages/b0/6d/00352fa25332c2569cd387851f568cc5a4b75a9adbfb37ac4fbce4c02eec/pillow-12.3.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:53aa02d20d10c3d814d536aa4e5ac9b84ca0ff5a88377963b085ad6822f93e64", size = 4783167, upload-time = "2026-07-01T11:56:06.631Z" }, + { url = "https://files.pythonhosted.org/packages/13/4f/9e049dfa21af7c22427275720e2490267ba8138120add5c4c574deb69782/pillow-12.3.0-cp315-cp315t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:446c34dcc4324b084a53b705127dc15717b22c5e140ae0a3c38349d4efec071e", size = 6329237, upload-time = "2026-07-01T11:56:08.868Z" }, + { url = "https://files.pythonhosted.org/packages/36/16/cf6eeaae8d0fce8dd390a33437cf68c5d5bd73834a2bc6e2f14efda0ab45/pillow-12.3.0-cp315-cp315t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cf1845d02ad822a369a49f2bb9345b1614744267682e7a03527dc3bf6eea1777", size = 6997047, upload-time = "2026-07-01T11:56:11.379Z" }, + { url = "https://files.pythonhosted.org/packages/1e/69/dbf769bdd55f48bf5733cac28edc6364ffaa072ec9ba336266e4fe66be55/pillow-12.3.0-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:186941b6aef820ad110fb01fb06eb925374dc3a21b17e37ec9a53b250c6fe2d1", size = 6400440, upload-time = "2026-07-01T11:56:13.908Z" }, + { url = "https://files.pythonhosted.org/packages/a0/e1/ffc9cfc2eea0d178da8018e18e959301ad9d6bc9f3edb7181e748a474b97/pillow-12.3.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:f13c32a3abd6079a66d9526e18dad9b6d280384d49d7c54040cd57b6424041d9", size = 7105895, upload-time = "2026-07-01T11:56:16.575Z" }, + { url = "https://files.pythonhosted.org/packages/18/f0/a5595c1e8c3ae44b9828cb2f0fa8155e5095ef04d6327b8f61cf44a3df85/pillow-12.3.0-cp315-cp315t-win32.whl", hash = "sha256:1657923d2d45afb66526e5b933e5b3052e6bdea196c90d3abb2424e18c77dae8", size = 6474384, upload-time = "2026-07-01T11:56:18.855Z" }, + { url = "https://files.pythonhosted.org/packages/e4/04/62bcd9f844984c5938d3b05264a61d797a29d3e0812341a8204af70bbdee/pillow-12.3.0-cp315-cp315t-win_amd64.whl", hash = "sha256:8cd2f7bdda092d99c9fc2fb7391354f306d01443d22785d0cbfafa2e2c8bb418", size = 7243537, upload-time = "2026-07-01T11:56:21.214Z" }, + { url = "https://files.pythonhosted.org/packages/3d/68/1f3066acedf37673694a7141381d8f811ae97f30d34413d236abe7d489f1/pillow-12.3.0-cp315-cp315t-win_arm64.whl", hash = "sha256:06ff022112bc9cbf83b60f8e028d94ad87b60621706487e65f673de61610ab59", size = 2567491, upload-time = "2026-07-01T11:56:23.506Z" }, + { url = "https://files.pythonhosted.org/packages/75/18/2e8b40223153ccbc60df07f9e8928dc0c76202aa4e55ae9f53962b6510d6/pillow-12.3.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:b3c777e849237620b022f7f297dd67705f9f5cf1685f09f02e46f93e92725468", size = 5302510, upload-time = "2026-07-01T11:56:25.736Z" }, + { url = "https://files.pythonhosted.org/packages/46/3e/51fabf59d5ab801ceab709453d3ab6b180083496579549de4c45ced6528a/pillow-12.3.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:b343699e8308bdc51978310e1c959c584e7869cc8c40780058c87da7781a1e94", size = 4736058, upload-time = "2026-07-01T11:56:28.041Z" }, + { url = "https://files.pythonhosted.org/packages/bf/20/22fe9384b7949e25fb1293bcfc84fb82590ff4ea6b37c95b24d26d793d86/pillow-12.3.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fbd139c8447d25dd750ab79ee274cc5e1fe80fc56340ab10b18a195e1b6eca3e", size = 5237776, upload-time = "2026-07-01T11:56:30.263Z" }, + { url = "https://files.pythonhosted.org/packages/08/14/f6ba68107680ffa74b39985f3f30884e41318fbc4250caa423c79b4788bb/pillow-12.3.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e7e480451b9fa137494bccd3a7d69adbe8ac65a87d97be61e11f1b1050a5bac3", size = 5860358, upload-time = "2026-07-01T11:56:32.68Z" }, + { url = "https://files.pythonhosted.org/packages/36/54/0169bc772ec491108b62f644f8ecf1fe5d8ae5ebafde2ee2142210166903/pillow-12.3.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:04f01d28a6aaff387bf842a13be313df23ba0597a44f1a976c9feb3c6ff4711a", size = 7231786, upload-time = "2026-07-01T11:56:35.046Z" }, +] + [[package]] name = "platformdirs" version = "4.5.1" @@ -2167,6 +2564,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/46/a4/aa2bada4a2fd648f40f19affa55d2c01dc7ff5ea9cffd3dfdeb6114951db/pymdown_extensions-10.18-py3-none-any.whl", hash = "sha256:090bca72be43f7d3186374e23c782899dbef9dc153ef24c59dcd3c346f9ffcae", size = 266703, upload-time = "2025-12-07T17:22:11.22Z" }, ] +[[package]] +name = "pyparsing" +version = "3.3.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/91/9c6ee907786a473bf81c5f53cf703ba0957b23ab84c264080fb5a450416f/pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc", size = 6851574, upload-time = "2026-01-21T03:57:59.36Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", size = 122781, upload-time = "2026-01-21T03:57:55.912Z" }, +] + [[package]] name = "pytest" version = "9.0.2"