From 2cab42355f58dd0ce8bda84caf0d6f72acc26f00 Mon Sep 17 00:00:00 2001 From: Apunkt Date: Fri, 12 Jun 2026 18:07:24 +0200 Subject: [PATCH] Fix CLS clustering: include temporal_next edges in cluster building _build_hebbian_clusters() only used hebbian edges, but 97% of hebbian edges are self-loops from reinforce_record(). Only 7 are cross-record. temporal_next edges (140) provide the cross-record connectivity needed to form clusters >= CLUSTER_MIN_SIZE. Without them, consolidation never creates summaries, no consolidated_from edges exist, and the graph remains fragmented with 514 isolated nodes and max CC=58. --- src/iai_mcp/sleep.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/iai_mcp/sleep.py b/src/iai_mcp/sleep.py index e3e6c5b..f2d9b1c 100644 --- a/src/iai_mcp/sleep.py +++ b/src/iai_mcp/sleep.py @@ -296,16 +296,22 @@ def run_light_consolidation( def _build_hebbian_clusters(store: MemoryStore) -> list[list[UUID]]: - """Find connected components in the hebbian edge graph with size >= CLUSTER_MIN_SIZE.""" + """Find connected components in the hebbian+temporal_next edge graph + with size >= CLUSTER_MIN_SIZE. + + Hebbian edges capture semantic similarity (dedup/reinforce); + temporal_next edges capture sequential proximity (same-session inserts + within 5 minutes). Both are valid signals for CLS clustering. + """ edges_df = store.db.open_table(EDGES_TABLE).to_pandas() if edges_df.empty: return [] - hebbian = edges_df[edges_df["edge_type"] == "hebbian"] - if hebbian.empty: + relevant = edges_df[edges_df["edge_type"].isin(("hebbian", "temporal_next"))] + if relevant.empty: return [] adj: dict[UUID, set[UUID]] = {} - for _, row in hebbian.iterrows(): + for _, row in relevant.iterrows(): src = UUID(row["src"]) dst = UUID(row["dst"]) adj.setdefault(src, set()).add(dst)