From 1b71ddd178c75962bf80283fb81ee71396a62fbb Mon Sep 17 00:00:00 2001 From: Mikael Hugo Date: Sat, 2 May 2026 23:21:57 +0200 Subject: [PATCH] fix(sf): drop embedding row when memory is superseded MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit supersedeMemory soft-deleted via superseded_by but left the memory_embeddings row in place. loadAllEmbeddings already filters by superseded_by IS NULL, so the orphaned row is harmless functionally — but it wastes storage, complicates manual SQL audits, and is inconsistent with updateMemoryContent (which already invalidates the embedding via 7bec2dc2d). Best-effort delete; supersede still succeeds even if the embedding delete raises. Symmetric with the update path. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/resources/extensions/sf/memory-store.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/resources/extensions/sf/memory-store.ts b/src/resources/extensions/sf/memory-store.ts index 90dd31611..4951b0a21 100644 --- a/src/resources/extensions/sf/memory-store.ts +++ b/src/resources/extensions/sf/memory-store.ts @@ -343,12 +343,22 @@ export function reinforceMemory(id: string): boolean { /** * Mark a memory as superseded by another. + * + * Drops the superseded memory's embedding row too: loadAllEmbeddings() + * already filters by superseded_by IS NULL, so the row was dead weight + * — keeping it would just waste storage and confuse manual SQL audits. + * Best-effort: a missing/failed delete doesn't block the supersede. */ export function supersedeMemory(oldId: string, newId: string): boolean { if (!isDbAvailable()) return false; try { supersedeMemoryRow(oldId, newId, new Date().toISOString()); + try { + deleteMemoryEmbedding(oldId); + } catch { + // Orphaned embedding rows are harmless; supersede still succeeded. + } return true; } catch { return false;