Skip to content

Commit 68dcc3a

Browse files
fix(core): apply system-time snapshot to history when known_at is omitted
why()/timeline() only ran the ingested_at/expired_at post-filter when the caller passed an explicit known_at. On the default call path (known_at=None) retention-expired and future-dated records leaked into public history output. Normalize to now_ts() when known_at is omitted, matching RecallEngine.recall. Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
1 parent 1ce18cf commit 68dcc3a

2 files changed

Lines changed: 42 additions & 3 deletions

File tree

‎engraphis/core/engine.py‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2783,13 +2783,16 @@ def _relatedness(self, query: str, flt: SearchFilter, *,
27832783
records = self.store.list_memories(
27842784
flt, include_invalid=include_invalid, limit=500, prompt_only=prompt_only,
27852785
)
2786-
if include_invalid and flt.known_at is not None:
2786+
if include_invalid:
27872787
# History must retain closed valid-time intervals, but cannot expose a
27882788
# record that was not known at the requested system-time snapshot.
2789+
# Default to the current snapshot when the caller omitted known_at —
2790+
# same normalization RecallEngine.recall applies (core/recall.py).
2791+
system_time = flt.known_at if flt.known_at is not None else now_ts()
27892792
records = [
27902793
rec for rec in records
2791-
if (rec.ingested_at is None or rec.ingested_at <= flt.known_at)
2792-
and (rec.expired_at is None or flt.known_at < rec.expired_at)
2794+
if (rec.ingested_at is None or rec.ingested_at <= system_time)
2795+
and (rec.expired_at is None or system_time < rec.expired_at)
27932796
]
27942797
for rec in records:
27952798
# Public history is model-adjacent just like ordinary recall: tool output

‎tests/test_engine.py‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,6 +1110,42 @@ def test_why_and_timeline_history_respect_known_time_but_keep_closed_records():
11101110
]
11111111

11121112

1113+
def test_why_and_timeline_default_snapshot_hides_expired_and_future_records():
1114+
eng = MemoryEngine.create(":memory:")
1115+
wid = eng.store.get_or_create_workspace("w")
1116+
rid = eng.store.get_or_create_repo(wid, "r")
1117+
far_past = time.time() - 10 * 86_400
1118+
future = time.time() + 10 * 86_400
1119+
records = (
1120+
MemoryRecord(
1121+
id="", workspace_id=wid, repo_id=rid, scope=Scope.REPO,
1122+
content="Default snapshot retention-expired record",
1123+
valid_from=far_past - 1.0, valid_to=far_past + 1.0,
1124+
ingested_at=far_past, expired_at=far_past + 2.0,
1125+
),
1126+
MemoryRecord(
1127+
id="", workspace_id=wid, repo_id=rid, scope=Scope.REPO,
1128+
content="Default snapshot future-dated record",
1129+
valid_from=future, ingested_at=future,
1130+
),
1131+
MemoryRecord(
1132+
id="", workspace_id=wid, repo_id=rid, scope=Scope.REPO,
1133+
content="Default snapshot live closed-interval record",
1134+
valid_from=1.0, valid_to=time.time() + 3_600.0, ingested_at=1.0,
1135+
),
1136+
)
1137+
for record in records:
1138+
eng.store.add_memory(record)
1139+
1140+
timeline = eng.timeline("default snapshot", workspace_id=wid, repo_id=rid)
1141+
why = eng.why("default snapshot", workspace_id=wid, repo_id=rid)
1142+
1143+
assert [record.content for record in timeline] == [
1144+
"Default snapshot live closed-interval record",
1145+
]
1146+
assert why["supersedes"] == []
1147+
1148+
11131149
def test_temporal_supersession_closes_at_effective_time_and_keeps_vectors():
11141150
eng = MemoryEngine.create(":memory:")
11151151
wid = eng.store.get_or_create_workspace("w")

0 commit comments

Comments
 (0)