LRUCache evicts the wrong entries

Done

/home/devdi/devswarm/evals/tasks/lru_cache_recency/repo · 2026-11-09 16:17:20 UTC · took 25.7s

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

Usage by agent

Cost per agent
planner: $0.0008 planner planner, Cost: $0.0008 $0.0008 coder: $0.0010 coder coder, Cost: $0.0010 $0.0010 tester: $0.0011 tester tester, Cost: $0.0011 $0.0011
Tokens per agent
  • Cache read
  • Cache write
  • Input
  • Output
planner: 7,715 planner planner, Cache read: 5,630 planner, Cache write: 881 planner, Output: 1,196 7,715 coder: 13.0K coder coder, Cache read: 9,230 coder, Cache write: 2,515 coder, Output: 1,257 13.0K tester: 15.6K tester tester, Cache read: 11.2K tester, Cache write: 3,370 tester, Output: 1,067 15.6K
View as table
AgentCostCache readCache writeInputOutput
planner$0.00085,63088181,196
coder$0.00109,2302,51581,257
tester$0.001111,1903,37081,067

Timeline

  1. planner iteration 1 Finished 3 calls · 7,715 tokens · $0.0008 · 7.9s

    Loading…

  2. coder iteration 1 Finished 3 calls · 13.0K tokens · $0.0010 · 8.6s

    Loading…

  3. tester iteration 1 Finished 3 calls · 15.6K tokens · $0.0011 · 8.0s

    Loading…

  4. verify iteration 1 Passed 0.5s
    .......                                                                  [100%]
    7 passed in 0.02s
    

Final diff

diff --git a/lru.py b/lru.py
index 8f9595c..1cd7f0a 100644
--- a/lru.py
+++ b/lru.py
@@ -7,9 +7,16 @@ class LRUCache:
         self._data: OrderedDict = OrderedDict()
 
     def get(self, key):
-        return self._data.get(key)
+        if key not in self._data:
+            return None
+        self._data.move_to_end(key)
+        return self._data[key]
 
     def put(self, key, value) -> None:
+        if key in self._data:
+            self._data[key] = value
+            self._data.move_to_end(key)
+            return
         if len(self._data) >= self.capacity:
             self._data.popitem(last=False)
         self._data[key] = value
diff --git a/test_lru.py b/test_lru.py
index ee81494..02d9428 100644
--- a/test_lru.py
+++ b/test_lru.py
@@ -12,3 +12,49 @@ def test_evicts_when_full():
     cache.put("a", 1)
     cache.put("b", 2)
     assert cache.get("a") is None
+
+
+def test_get_refreshes_recency():
+    cache = LRUCache(2)
+    cache.put("a", 1)
+    cache.put("b", 2)
+    assert cache.get("a") == 1
+    cache.put("c", 3)
+    assert cache.get("b") is None
+    assert cache.get("a") == 1
+
+
+def test_update_refreshes_recency():
+    cache = LRUCache(2)
+    cache.put("a", 1)
+    cache.put("b", 2)
+    cache.put("a", 10)
+    cache.put("c", 3)
+    assert cache.get("b") is None
+    assert cache.get("a") == 10
+
+
+def test_update_does_not_evict():
+    cache = LRUCache(2)
+    cache.put("a", 1)
+    cache.put("b", 2)
+    cache.put("a", 5)
+    assert len(cache._data) == 2
+    assert cache.get("a") == 5
+    assert cache.get("b") == 2
+
+
+def test_get_missing_key_does_not_insert():
+    cache = LRUCache(2)
+    cache.put("a", 1)
+    assert cache.get("missing") is None
+    assert len(cache._data) == 1
+    assert list(cache._data) == ["a"]
+
+
+def test_update_at_capacity_one_keeps_entry():
+    cache = LRUCache(1)
+    cache.put("a", 1)
+    cache.put("a", 2)
+    assert len(cache._data) == 1
+    assert cache.get("a") == 2