import json from scripts.dynamic_dispatch_optimizer import generate_plan, write_plan def test_generate_plan_rebalances_offline_host_tasks_to_online_capacity(): spec = { "hosts": [ {"name": "ezra", "capacity": 2, "lanes": ["research", "general"]}, {"name": "bezalel", "capacity": 2, "lanes": ["build", "general"]}, {"name": "local", "capacity": 1, "lanes": ["general"], "always_available": True}, ], "tasks": [ {"id": "ISSUE-1", "lane": "build", "priority": 100}, {"id": "ISSUE-2", "lane": "general", "priority": 80}, {"id": "ISSUE-3", "lane": "research", "priority": 60}, ], } failover_status = {"fleet": {"ezra": "ONLINE", "bezalel": "OFFLINE"}} plan = generate_plan(spec, failover_status) assignments = {item["task_id"]: item["host"] for item in plan["assignments"]} assert assignments == { "ISSUE-1": "local", "ISSUE-2": "ezra", "ISSUE-3": "ezra", } assert plan["offline_hosts"] == ["bezalel"] assert plan["unassigned"] == [] def test_generate_plan_prefers_preferred_host_when_online(): spec = { "hosts": [ {"name": "ezra", "capacity": 2, "lanes": ["general"]}, {"name": "bezalel", "capacity": 2, "lanes": ["general"]}, ], "tasks": [ {"id": "ISSUE-9", "lane": "general", "priority": 100, "preferred_hosts": ["bezalel", "ezra"]}, ], } plan = generate_plan(spec, {"fleet": {"ezra": "ONLINE", "bezalel": "ONLINE"}}) assert plan["assignments"] == [ {"task_id": "ISSUE-9", "host": "bezalel", "lane": "general", "priority": 100} ] def test_generate_plan_reports_unassigned_when_no_host_matches_lane(): spec = { "hosts": [ {"name": "ezra", "capacity": 1, "lanes": ["research"]}, ], "tasks": [ {"id": "ISSUE-5", "lane": "build", "priority": 50}, ], } plan = generate_plan(spec, {"fleet": {"ezra": "ONLINE"}}) assert plan["assignments"] == [] assert plan["unassigned"] == [ {"task_id": "ISSUE-5", "reason": "no_online_host_for_lane:build"} ] def test_write_plan_persists_json(tmp_path): plan = { "assignments": [{"task_id": "ISSUE-1", "host": "ezra", "lane": "general", "priority": 10}], "offline_hosts": [], "unassigned": [], } output_path = tmp_path / "dispatch-plan.json" write_plan(plan, output_path) assert json.loads(output_path.read_text()) == plan