Skip to content

Commit ac2d994

Browse files
Close final review gaps
1 parent 01787cd commit ac2d994

4 files changed

Lines changed: 90 additions & 2 deletions

File tree

‎engraphis/core/engine.py‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1078,7 +1078,16 @@ def _relatedness(self, query: str, flt: SearchFilter, *,
10781078
sem[mid] = float(np.dot(qn, vec))
10791079
q_tokens = tokenize(query)
10801080
out: list[tuple[float, MemoryRecord]] = []
1081-
for rec in self.store.list_memories(flt, include_invalid=include_invalid, limit=500):
1081+
records = self.store.list_memories(flt, include_invalid=include_invalid, limit=500)
1082+
if include_invalid and flt.known_at is not None:
1083+
# History must retain closed valid-time intervals, but cannot expose a
1084+
# record that was not known at the requested system-time snapshot.
1085+
records = [
1086+
rec for rec in records
1087+
if (rec.ingested_at is None or rec.ingested_at <= flt.known_at)
1088+
and (rec.expired_at is None or flt.known_at < rec.expired_at)
1089+
]
1090+
for rec in records:
10821091
lex = jaccard(q_tokens, tokenize(f"{rec.title} {rec.content}"))
10831092
score = max(sem.get(rec.id, 0.0), lex)
10841093
if score > 0.05:

‎engraphis/routes/v2_api.py‎

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -977,8 +977,34 @@ def recall(q: str = Query(...), workspace: Optional[str] = None, k: int = 8,
977977
mems = _keyword_search(
978978
ws, q, k, as_of=as_of, valid_at=valid_at, known_at=known_at,
979979
)
980+
if response_mode == "compact":
981+
# Preserve the public compact-response contract even when semantic recall
982+
# degrades to the keyword path during an embedding migration.
983+
mems = [
984+
{
985+
key: memory.get(key)
986+
for key in (
987+
"id", "document_id", "title", "memory_type", "scope", "pinned",
988+
"importance", "valid_from", "valid_to", "valid_to_recorded_at",
989+
"ingested_at", "expired_at", "subject_key", "claim_kind", "provenance",
990+
)
991+
}
992+
for memory in mems
993+
]
994+
historical = valid_at is not None or known_at is not None or as_of is not None
995+
effective_budget = (
996+
token_budget if token_budget is not None else service().engine.recall_engine.token_budget
997+
)
980998
return {"query": q, "workspace": ws, "count": len(mems), "context": "",
981-
"memories": mems, "mode": "keyword",
999+
"memories": mems, "mode": "keyword", "response_mode": response_mode,
1000+
"retrieval_profile": retrieval_profile,
1001+
"valid_at": valid_at if valid_at is not None else as_of,
1002+
"known_at": known_at, "historical": historical,
1003+
"packed_sources": [],
1004+
"usage": {"budget_tokens": effective_budget, "context_tokens": 0,
1005+
"source_tokens": 0, "saved_tokens": 0, "savings_ratio": 0.0,
1006+
"packed_count": 0, "omitted_count": len(mems),
1007+
"token_counter": "engraphis.regex.v1"},
9821008
"note": "Keyword match — install sentence-transformers for semantic search."}
9831009
payload = dict(out)
9841010
payload.update({

‎tests/test_dashboard_v2.py‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,21 @@ def incompatible_embedder(*_args, **_kwargs):
400400
assert fallback.json()["mode"] == "keyword"
401401
assert [item["id"] for item in fallback.json()["memories"]] == [old["id"]]
402402

403+
compact_fallback = client.get(
404+
"/api/recall",
405+
params={
406+
"workspace": "demo", "q": "fallback retention", "response_mode": "compact",
407+
"token_budget": 0,
408+
},
409+
)
410+
payload = compact_fallback.json()
411+
assert compact_fallback.status_code == 200
412+
assert payload["mode"] == "keyword"
413+
assert payload["response_mode"] == "compact"
414+
assert payload["usage"]["budget_tokens"] == 0
415+
assert payload["usage"]["context_tokens"] == 0
416+
assert payload["memories"] and "content" not in payload["memories"][0]
417+
403418

404419
def test_http_memory_api_rejects_backdated_supersession_without_partial_write(
405420
monkeypatch, tmp_path

‎tests/test_engine.py‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,44 @@ def test_timeline_orders_history_chronologically():
466466
assert hist[0].valid_from < hist[1].valid_from
467467

468468

469+
def test_why_and_timeline_history_respect_known_time_but_keep_closed_records():
470+
eng = MemoryEngine.create(":memory:")
471+
wid = eng.store.get_or_create_workspace("w")
472+
rid = eng.store.get_or_create_repo(wid, "r")
473+
records = (
474+
MemoryRecord(
475+
id="", workspace_id=wid, repo_id=rid, scope=Scope.REPO,
476+
content="Launch history current policy", valid_from=1.0, ingested_at=1.0,
477+
),
478+
MemoryRecord(
479+
id="", workspace_id=wid, repo_id=rid, scope=Scope.REPO,
480+
content="Launch history closed policy", valid_from=2.0, valid_to=3.0,
481+
ingested_at=2.0,
482+
),
483+
MemoryRecord(
484+
id="", workspace_id=wid, repo_id=rid, scope=Scope.REPO,
485+
content="Launch history learned later", valid_from=4.0, valid_to=5.0,
486+
ingested_at=200.0,
487+
),
488+
)
489+
for record in records:
490+
eng.store.add_memory(record)
491+
492+
timeline = eng.timeline(
493+
"launch history", workspace_id=wid, repo_id=rid, known_at=100.0,
494+
)
495+
why = eng.why(
496+
"launch history", workspace_id=wid, repo_id=rid, known_at=100.0,
497+
)
498+
499+
assert {record.content for record in timeline} == {
500+
"Launch history current policy", "Launch history closed policy",
501+
}
502+
assert [record.content for record in why["supersedes"]] == [
503+
"Launch history closed policy",
504+
]
505+
506+
469507
def test_temporal_supersession_closes_at_effective_time_and_keeps_vectors():
470508
eng = MemoryEngine.create(":memory:")
471509
wid = eng.store.get_or_create_workspace("w")

0 commit comments

Comments
 (0)