Skip to content

Commit 41b97a1

Browse files
Fix current_state.latest_observation sort to use true recency
Fourth dogfood-surfaced bug. Within a single runtime session, multiple record_observation calls inherit the same episode's event_at, so the previous step_index-only sort collapsed their order to insertion order and returned the *oldest* write as "latest_observation" — the opposite of what the field promises. Sort now uses (event_at, created_at, step_index) with reverse=True: - event_at is the primary semantic signal (when the observed event happened) and wins when it genuinely differs across observations. - created_at varies per write regardless of episode reuse, so it breaks event_at ties correctly within a session. - step_index remains the final tiebreak so trajectory-based ingestion (where step_index IS the authoritative ordering) keeps working. Regression test seeds three record_observation calls with 10ms spacing and asserts the third one surfaces as latest_observation. 14 tests pass (was 13) — the full pass now covers all four dogfood findings. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent f38d43b commit 41b97a1

2 files changed

Lines changed: 37 additions & 2 deletions

File tree

state_trace/memory.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -345,9 +345,20 @@ def _step(node: Node) -> int:
345345
value = node.metadata.get("step_index")
346346
return int(value) if value is not None else -1
347347

348+
def _recency_key(node: Node) -> tuple:
349+
# Most-recent-first. Primary sort: event_at (the semantic "when
350+
# did the thing happen"). Tiebreak on created_at — dogfood
351+
# finding: within one runtime session, multiple record_observation
352+
# calls share an episode's event_at stamp, so event_at alone ties
353+
# and falls back to insertion order. created_at varies per write
354+
# and breaks those ties correctly. Final tiebreak on step_index
355+
# so trajectory-based ingestion preserves step ordering.
356+
event_at = node.event_at or node.created_at
357+
return (event_at, node.created_at, _step(node))
358+
348359
task_nodes.sort(key=lambda node: (node.importance, _step(node)), reverse=True)
349-
observation_nodes.sort(key=_step, reverse=True)
350-
decision_nodes.sort(key=_step, reverse=True)
360+
observation_nodes.sort(key=_recency_key, reverse=True)
361+
decision_nodes.sort(key=_recency_key, reverse=True)
351362

352363
active_files = sorted(
353364
file_nodes.values(),

tests/test_temporal_memory.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,30 @@ def test_retrieve_brief_preserves_load_bearing_detail_in_top_evidence() -> None:
326326
)
327327

328328

329+
def test_current_state_latest_observation_is_truly_most_recent() -> None:
330+
"""Dogfood regression: within one runtime session, multiple record_observation
331+
calls share step_index=0. Before the fix, current_state sorted observations
332+
by step_index only and returned insertion order as 'latest', so the newest
333+
write wasn't the one surfaced. Now sort is by event_at -> most recent wins."""
334+
import time
335+
engine = MemoryEngine(capacity_limit=128.0)
336+
ctx = {"session": "recency-session", "goal": "verify recency"}
337+
engine.store("Verify ordering", {"type": "task", "importance": 0.9, **ctx})
338+
engine.record_observation("First observation", {**ctx, "status": "info"})
339+
time.sleep(0.01) # ensure event_at differs
340+
engine.record_observation("Second observation", {**ctx, "status": "info"})
341+
time.sleep(0.01)
342+
engine.record_observation("Third observation — newest", {**ctx, "status": "info"})
343+
344+
state = engine.current_state(session="recency-session")
345+
346+
assert state["latest_observation"] is not None
347+
assert state["latest_observation"]["content"] == "Third observation — newest", (
348+
f"latest_observation should be the most recent write, not the first; "
349+
f"got: {state['latest_observation']['content']!r}"
350+
)
351+
352+
329353
def test_failed_hypotheses_surfaces_rejected_angle_observations() -> None:
330354
"""Dogfood regression: concluded dead-ends recorded as status=info with
331355
rejected_angle=True should surface from failed_hypotheses with reason

0 commit comments

Comments
 (0)