Skip to content

Commit cb1cc65

Browse files
fix: preserve historical graph facet evidence
1 parent ad1a549 commit cb1cc65

2 files changed

Lines changed: 52 additions & 17 deletions

File tree

engraphis/service.py

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7883,22 +7883,15 @@ def _graph_scene_rows_unlocked(self, *, workspace: str, repo: Optional[str] = No
78837883
"JOIN memories graph_memory ON graph_memory.id=graph_support.memory_id "
78847884
"WHERE graph_support.edge_id=edges.id "
78857885
"AND (graph_support.valid_from IS NULL OR graph_support.valid_from<=?) "
7886-
"AND (graph_support.valid_to IS NULL OR ?<graph_support.valid_to "
7887-
"OR (graph_support.valid_to_recorded_at IS NOT NULL "
7888-
"AND ?<graph_support.valid_to_recorded_at)) "
78897886
"AND (graph_support.ingested_at IS NULL OR graph_support.ingested_at<=?) "
7890-
"AND (graph_support.expired_at IS NULL OR ?<graph_support.expired_at) "
7887+
"AND graph_support.expired_at IS NULL "
78917888
"AND graph_memory.workspace_id=? "
78927889
"AND (graph_memory.valid_from IS NULL OR graph_memory.valid_from<=?) "
7893-
"AND (graph_memory.valid_to IS NULL OR ?<graph_memory.valid_to "
7894-
"OR (graph_memory.valid_to_recorded_at IS NOT NULL "
7895-
"AND ?<graph_memory.valid_to_recorded_at)) "
78967890
"AND (graph_memory.ingested_at IS NULL OR graph_memory.ingested_at<=?) "
7897-
"AND (graph_memory.expired_at IS NULL OR ?<graph_memory.expired_at)"
7891+
"AND graph_memory.expired_at IS NULL"
78987892
)
78997893
edge_params.extend((
7900-
t, t, known_t, known_t, known_t,
7901-
wid, t, t, known_t, known_t, known_t,
7894+
t, known_t, wid, t, known_t,
79027895
))
79037896
if restrict_sessions:
79047897
edge_sql += " AND COALESCE(graph_memory.scope, 'workspace')!='session'"
@@ -8211,14 +8204,26 @@ def _graph_scene_rows_unlocked(self, *, workspace: str, repo: Optional[str] = No
82118204
"SELECT id, mtype, COALESCE(valid_from, ingested_at, 0) AS support_time "
82128205
"FROM memories WHERE workspace_id=? AND id IN (" + marks + ") "
82138206
"AND (valid_from IS NULL OR valid_from<=?) "
8214-
"AND (valid_to IS NULL OR ?<valid_to "
8215-
"OR (valid_to_recorded_at IS NOT NULL AND ?<valid_to_recorded_at)) "
8216-
"AND (ingested_at IS NULL OR ingested_at<=?) "
8217-
"AND (expired_at IS NULL OR ?<expired_at)"
82188207
)
8219-
memory_params: list[Any] = [
8220-
wid, *chunk, t, t, known_t, known_t, known_t,
8221-
]
8208+
if include_history:
8209+
# Historical scenes may intentionally surface memories that have
8210+
# since been invalidated. The historical edge/support predicates
8211+
# already establish the valid_at/known_at anchors; applying the
8212+
# live valid_to window here would erase ghost relations whenever a
8213+
# memory facet is requested.
8214+
memory_sql += (
8215+
"AND (ingested_at IS NULL OR ingested_at<=?) "
8216+
"AND expired_at IS NULL"
8217+
)
8218+
memory_params: list[Any] = [wid, *chunk, t, known_t]
8219+
else:
8220+
memory_sql += (
8221+
"AND (valid_to IS NULL OR ?<valid_to "
8222+
"OR (valid_to_recorded_at IS NOT NULL AND ?<valid_to_recorded_at)) "
8223+
"AND (ingested_at IS NULL OR ingested_at<=?) "
8224+
"AND (expired_at IS NULL OR ?<expired_at)"
8225+
)
8226+
memory_params = [wid, *chunk, t, t, known_t, known_t, known_t]
82228227
memory_sql += " AND COALESCE(scope, 'workspace')!='session'"
82238228
if clean_memory_types:
82248229
type_marks = ",".join("?" for _ in clean_memory_types)

tests/test_graph_explorer_v2.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1776,6 +1776,36 @@ def test_graph_scene_history_binds_edge_support_to_the_edge_workspace():
17761776
assert "edge_ab" not in {edge["id"] for edge in history["edges"]}
17771777

17781778

1779+
def test_graph_scene_history_facets_keep_invalidated_supports_visible():
1780+
service, _alpha, _beta, _gamma = _seed_service()
1781+
closed_at = time.time() + 10.0
1782+
service.store.conn.execute(
1783+
"UPDATE memories SET valid_from=0, valid_to=?, valid_to_recorded_at=? "
1784+
"WHERE content='Alpha uses Beta.'",
1785+
(closed_at, closed_at),
1786+
)
1787+
service.store.conn.execute(
1788+
"UPDATE edges SET valid_from=0, valid_to=?, valid_to_recorded_at=? "
1789+
"WHERE id='edge_ab'",
1790+
(closed_at, closed_at),
1791+
)
1792+
service.store.conn.execute(
1793+
"UPDATE edge_supports SET valid_from=0, valid_to=?, valid_to_recorded_at=? "
1794+
"WHERE edge_id='edge_ab'",
1795+
(closed_at, closed_at),
1796+
)
1797+
service.store.conn.commit()
1798+
1799+
history = service.graph_scene(
1800+
workspace="acme", include_history=True, memory_types=["semantic"],
1801+
valid_at=closed_at + 1.0, known_at=closed_at + 1.0,
1802+
)
1803+
1804+
edge = next(edge for edge in history["edges"] if edge["id"] == "edge_ab")
1805+
assert edge["ghost"] is True
1806+
assert edge["support_memory_ids"]
1807+
1808+
17791809
def test_graph_scene_history_includes_closed_code_rows_and_marks_them_ghost():
17801810
service = MemoryService.create(":memory:", graph_extractor="none")
17811811
workspace_id = service.store.get_or_create_workspace("acme")

0 commit comments

Comments
 (0)