Available stock counts drift from reality

Done

/home/devdi/devswarm/evals/tasks/hard_inventory_orders/repo · 2026-11-09 17:07:55 UTC · took 38.1s

  1. Plan (done)
  2. Code (done)
  3. Test (done)
  4. Review (done)
  5. Finish (done)
Cost
$0.0053
Tests
Passed
Iterations
1
Re-plans
0
LLM calls
11
Prompt read from cache
76%

Usage by agent

Cost per agent
planner: $0.0013 planner planner, Cost: $0.0013 $0.0013 coder: $0.0021 coder coder, Cost: $0.0021 $0.0021 tester: $0.0019 tester tester, Cost: $0.0019 $0.0019
Tokens per agent
  • Cache read
  • Cache write
  • Input
  • Output
planner: 13.3K planner planner, Cache read: 9,449 planner, Cache write: 1,854 planner, Output: 1,979 13.3K coder: 23.3K coder coder, Cache read: 15.9K coder, Cache write: 4,710 coder, Output: 2,708 23.3K tester: 23.3K tester tester, Cache read: 14.9K tester, Cache write: 6,463 tester, Output: 1,862 23.3K
View as table
AgentCostCache readCache writeInputOutput
planner$0.00139,4491,854101,979
coder$0.002115,9084,710102,708
tester$0.001914,9476,46381,862

Timeline

  1. planner iteration 1 Finished 4 calls · 13.3K tokens · $0.0013 · 13.3s

    Loading…

  2. coder iteration 1 Finished 4 calls · 23.3K tokens · $0.0021 · 12.8s

    Loading…

  3. tester iteration 1 Finished 3 calls · 23.3K tokens · $0.0019 · 10.9s

    Loading…

  4. verify iteration 1 Passed 0.6s
    .............                                                            [100%]
    13 passed in 0.03s
    

Final diff

diff --git a/orders.py b/orders.py
index 3c6e298..6a5f045 100644
--- a/orders.py
+++ b/orders.py
@@ -1,4 +1,4 @@
-from stock import Stock
+from stock import OutOfStock, Stock
 
 
 class OrderError(Exception):
@@ -11,19 +11,39 @@ class Orders:
         self._orders: dict[int, dict] = {}
         self._next_id = 1
 
+    def _get(self, order_id: int) -> dict:
+        try:
+            return self._orders[order_id]
+        except KeyError:
+            raise OrderError(f"unknown order id {order_id}") from None
+
     def place(self, lines: dict[str, int]) -> int:
-        for sku, qty in lines.items():
-            self.stock.reserve(sku, qty)
+        reserved: list[tuple[str, int]] = []
+        try:
+            for sku, qty in lines.items():
+                self.stock.reserve(sku, qty)
+                reserved.append((sku, qty))
+        except OutOfStock:
+            for sku, qty in reserved:
+                self.stock.release(sku, qty)
+            raise
         order_id = self._next_id
         self._next_id += 1
         self._orders[order_id] = {"lines": dict(lines), "status": "open"}
         return order_id
 
     def ship(self, order_id: int) -> None:
-        self._orders[order_id]["status"] = "shipped"
+        order = self._get(order_id)
+        if order["status"] == "cancelled":
+            raise OrderError(f"order {order_id} is cancelled and cannot be shipped")
+        order["status"] = "shipped"
 
     def cancel(self, order_id: int) -> None:
-        order = self._orders[order_id]
+        order = self._get(order_id)
+        if order["status"] == "cancelled":
+            return
+        if order["status"] == "shipped":
+            raise OrderError(f"order {order_id} has shipped and cannot be cancelled")
         for sku, qty in order["lines"].items():
             self.stock.release(sku, qty)
         order["status"] = "cancelled"
diff --git a/test_orders.py b/test_orders.py
index 149497c..51a8275 100644
--- a/test_orders.py
+++ b/test_orders.py
@@ -1,5 +1,7 @@
-from orders import Orders
-from stock import Stock
+import pytest
+
+from orders import OrderError, Orders
+from stock import OutOfStock, Stock
 
 
 def test_place_reserves():
@@ -13,3 +15,109 @@ def test_cancel_releases():
     orders = Orders(stock)
     orders.cancel(orders.place({"a": 2}))
     assert stock.available("a") == 5
+
+
+def test_double_cancel_restores_stock_once():
+    stock = Stock({"a": 5})
+    orders = Orders(stock)
+    order_id = orders.place({"a": 2})
+    orders.cancel(order_id)
+    orders.cancel(order_id)
+    assert stock.available("a") == 5
+
+
+def test_failed_multiline_place_leaves_stock_unchanged():
+    stock = Stock({"a": 5, "b": 1})
+    orders = Orders(stock)
+    with pytest.raises(OutOfStock):
+        orders.place({"a": 2, "b": 3})
+    assert stock.available("a") == 5
+    assert stock.available("b") == 1
+    assert orders._orders == {}
+
+
+def test_cancel_shipped_order_raises_and_changes_nothing():
+    stock = Stock({"a": 5})
+    orders = Orders(stock)
+    order_id = orders.place({"a": 2})
+    orders.ship(order_id)
+    with pytest.raises(OrderError):
+        orders.cancel(order_id)
+    assert stock.available("a") == 3
+    assert orders._orders[order_id]["status"] == "shipped"
+
+
+def test_ship_cancelled_order_raises_and_stays_cancelled():
+    stock = Stock({"a": 5})
+    orders = Orders(stock)
+    order_id = orders.place({"a": 2})
+    orders.cancel(order_id)
+    with pytest.raises(OrderError):
+        orders.ship(order_id)
+    assert orders._orders[order_id]["status"] == "cancelled"
+
+
+def test_unknown_order_id_raises_order_error():
+    orders = Orders(Stock({"a": 5}))
+    with pytest.raises(OrderError):
+        orders.ship(999)
+    with pytest.raises(OrderError):
+        orders.cancel(999)
+
+
+def test_failed_place_with_first_line_out_of_stock_leaves_stock_unchanged():
+    stock = Stock({"a": 1, "b": 5})
+    orders = Orders(stock)
+    with pytest.raises(OutOfStock):
+        orders.place({"a": 2, "b": 3})
+    assert stock.available("a") == 1
+    assert stock.available("b") == 5
+    assert orders._orders == {}
+
+
+def test_failed_place_with_unknown_sku_leaves_stock_unchanged():
+    stock = Stock({"a": 5})
+    orders = Orders(stock)
+    with pytest.raises(OutOfStock):
+        orders.place({"a": 2, "missing": 1})
+    assert stock.available("a") == 5
+    assert stock.available("missing") == 0
+
+
+def test_failed_place_does_not_consume_order_id():
+    stock = Stock({"a": 5, "b": 1})
+    orders = Orders(stock)
+    with pytest.raises(OutOfStock):
+        orders.place({"a": 1, "b": 2})
+    assert orders.place({"a": 1}) == 1
+
+
+def test_ship_unknown_id_changes_nothing():
+    stock = Stock({"a": 5})
+    orders = Orders(stock)
+    order_id = orders.place({"a": 2})
+    with pytest.raises(OrderError):
+        orders.ship(999)
+    assert orders._orders[order_id]["status"] == "open"
+    assert stock.available("a") == 3
+
+
+def test_cancel_unknown_id_changes_nothing():
+    stock = Stock({"a": 5})
+    orders = Orders(stock)
+    order_id = orders.place({"a": 2})
+    with pytest.raises(OrderError):
+        orders.cancel(999)
+    assert orders._orders[order_id]["status"] == "open"
+    assert stock.available("a") == 3
+
+
+def test_cancel_after_double_cancel_stays_cancelled_and_no_raise():
+    stock = Stock({"a": 5})
+    orders = Orders(stock)
+    order_id = orders.place({"a": 2})
+    orders.cancel(order_id)
+    orders.cancel(order_id)
+    orders.cancel(order_id)
+    assert stock.available("a") == 5
+    assert orders._orders[order_id]["status"] == "cancelled"