fix(sf): enforceMemoryCap sweeps orphaned embeddings too
Same orphan-cleanup as 1b71ddd17 but for the batch path. enforceMemoryCap
calls supersedeLowestRankedMemories, which marks N lowest memories
superseded in one UPDATE — bypassing the per-memory supersede embedding
cleanup. The result was that capping a project at 50 memories left dead
embedding rows for everything that got demoted.
Now: a single DELETE-IN-SUBQUERY removes embedding rows for any memory
that no longer has superseded_by IS NULL — covers both the cap path
and any historical orphans from before the per-row cleanup landed.
Best-effort; cap enforcement is load-bearing, embedding cleanup is not.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
1b71ddd178
commit
05a326a294
1 changed files with 21 additions and 0 deletions
|
|
@ -434,6 +434,12 @@ export function decayStaleMemories(thresholdUnits = 20): void {
|
|||
|
||||
/**
|
||||
* Supersede lowest-ranked memories when count exceeds cap.
|
||||
*
|
||||
* After superseding, sweeps memory_embeddings for rows whose memory is now
|
||||
* superseded — keeps the embeddings table aligned with active memories so
|
||||
* loadAllEmbeddings doesn't carry dead vectors and storage doesn't grow
|
||||
* unbounded. Best-effort cleanup; the cap enforcement is the load-bearing
|
||||
* step.
|
||||
*/
|
||||
export function enforceMemoryCap(max = 50): void {
|
||||
if (!isDbAvailable()) return;
|
||||
|
|
@ -451,6 +457,21 @@ export function enforceMemoryCap(max = 50): void {
|
|||
|
||||
const excess = count - max;
|
||||
supersedeLowestRankedMemories(excess, new Date().toISOString());
|
||||
|
||||
// Sweep orphaned embeddings for newly-superseded memories.
|
||||
try {
|
||||
adapter
|
||||
.prepare(
|
||||
`DELETE FROM memory_embeddings WHERE memory_id IN (
|
||||
SELECT id FROM memories WHERE superseded_by IS NOT NULL
|
||||
)`,
|
||||
)
|
||||
.run();
|
||||
} catch {
|
||||
// Orphaned rows are harmless to queries (loadAllEmbeddings filters
|
||||
// by superseded_by IS NULL); skip-on-error keeps cap enforcement
|
||||
// load-bearing without coupling to embedding cleanup.
|
||||
}
|
||||
} catch {
|
||||
// non-fatal
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue