{
  "name": "hard-multi-file-bug",
  "description": "Debug a multi-file Python application with interacting bugs",
  "dataset": "terminal-bench-local",
  "difficulty": "hard",
  "instruction": "There is a small Python application with three files: models.py, service.py, and main.py. The application is a simple inventory management system. Running main.py should produce correct output but currently it has bugs across multiple files. Find and fix all the bugs so that running python3 main.py produces the expected output. Do not change the overall structure or add new files.",
  "setup_files": {
    "models.py": "class Product:\n    def __init__(self, name, price, quantity):\n        self.name = name\n        self.price = price\n        self.quantity = quantity\n\n    def total_value(self):\n        return self.price + self.quantity  # Bug: should be multiplication\n\n    def __repr__(self):\n        return f\"Product({self.name}, ${self.price}, qty={self.quantity})\"\n\n\nclass Inventory:\n    def __init__(self):\n        self.products = []\n\n    def add_product(self, product):\n        # Bug: doesn't check if product already exists, should update quantity\n        self.products.append(product)\n\n    def get_product(self, name):\n        for p in self.products:\n            if p.name == name:\n                return p\n        return None\n\n    def total_inventory_value(self):\n        total = 0\n        for p in self.products:\n            total += p.total_value()\n        return total\n\n    def remove_product(self, name):\n        self.products = [p for p in self.products if p.name != name]  # This is correct\n",
    "service.py": "from models import Inventory, Product\n\n\ndef process_orders(inventory, orders):\n    results = []\n    for order in orders:\n        name = order['product']\n        qty = order['quantity']\n        product = inventory.get_product(name)\n\n        if product is None:\n            results.append(f\"REJECT {name}: not found\")\n            continue\n\n        if product.quantity < qty:\n            results.append(f\"REJECT {name}: insufficient stock ({product.quantity} < {qty})\")\n            continue\n\n        product.quantity += qty  # Bug: should subtract, not add\n        total = product.price * qty\n        results.append(f\"OK {name}: {qty} units, ${total:.2f}\")\n\n    return results\n\n\ndef restock(inventory, restock_list):\n    for item in restock_list:\n        product = inventory.get_product(item['product'])\n        if product:\n            product.quantity += item['quantity']\n        else:\n            # Bug: price and quantity args are swapped\n            inventory.add_product(Product(item['product'], item['quantity'], item['price']))\n",
    "main.py": "from models import Inventory, Product\nfrom service import process_orders, restock\n\ndef main():\n    inv = Inventory()\n    inv.add_product(Product(\"Widget\", 9.99, 100))\n    inv.add_product(Product(\"Gadget\", 24.99, 50))\n    inv.add_product(Product(\"Doohickey\", 4.99, 200))\n\n    orders = [\n        {\"product\": \"Widget\", \"quantity\": 10},\n        {\"product\": \"Gadget\", \"quantity\": 60},   # Should be rejected: insufficient stock\n        {\"product\": \"Doohickey\", \"quantity\": 5},\n        {\"product\": \"Thingamajig\", \"quantity\": 1},  # Should be rejected: not found\n    ]\n\n    results = process_orders(inv, orders)\n    for r in results:\n        print(r)\n\n    print(f\"Inventory value: ${inv.total_inventory_value():.2f}\")\n\n    restock(inv, [{\"product\": \"Widget\", \"quantity\": 50}, {\"product\": \"Sprocket\", \"price\": 14.99, \"quantity\": 30}])\n    print(f\"After restock value: ${inv.total_inventory_value():.2f}\")\n\nif __name__ == \"__main__\":\n    main()\n",
    "test_multi_file.py": "import subprocess\nimport sys\n\nresult = subprocess.run([sys.executable, 'main.py'], capture_output=True, text=True, timeout=10)\noutput = result.stdout.strip()\n\nexpected_lines = [\n    \"OK Widget: 10 units, $99.90\",\n    \"REJECT Gadget: insufficient stock (50 < 60)\",\n    \"OK Doohickey: 5 units, $24.95\",\n    \"REJECT Thingamajig: not found\",\n    \"Inventory value: $3121.65\",\n    \"After restock value: $4070.85\"\n]\n\nlines = output.split('\\n')\npassed = 0\nfailed = 0\n\nfor i, expected in enumerate(expected_lines):\n    if i < len(lines) and lines[i].strip() == expected:\n        passed += 1\n    else:\n        got = lines[i].strip() if i < len(lines) else '<missing>'\n        print(f\"FAIL line {i+1}: expected '{expected}', got '{got}'\")\n        failed += 1\n\nprint(f\"{passed}/{passed+failed} tests passed\")\nif failed > 0:\n    sys.exit(1)\n"
  },
  "verify": "cd $BENCH_WORK_DIR && python3 test_multi_file.py",
  "timeout": 240000,
  "tags": ["hard", "debugging", "multi-file", "python"]
}
