CorpusConsolidationService
Defined in: packages/memory-ltm/src/corpus-consolidation.service.ts:84
Periodic corpus consolidation (G3-T2): clusters NEAR-duplicate long-term
memories in the [mergeThreshold, duplicateThreshold) similarity band —
the band write-time dedup deliberately leaves alone, which otherwise
accumulates unbounded — keeps one canonical per cluster, and supersedes the
rest.
NOT the STM→LTM promotion pass: consolidate_memories /
ConsolidationService (apps/mcp-server) is a different, unrelated job.
Merge semantics (pinned Decisions 8/9 + WRAPUP-PLAN §2 B5):
- canonical = highest
metadata.importance, tie-break most recentcreatedAt; - the union of every cluster member’s tags is CAS-written onto the canonical;
- each loser gets EXACTLY the write-time supersede markers
(ContradictionDetectionService.annotateSuperseded:
status,supersededBy,supersededReason,supersededAtin metadata JSON — zero schema changes), a derivedduplicate-ofMemoryLink to the canonical, and a system-actor audit row (corpus_consolidation), so the G3-T1 recall exclusion andget_memoryretrieval Just Work; - every mutation rides the G3-T3 CAS path
(MemoryLtmService.casMetadataUpdate): retry ONCE from a fresh
read, then skip and count
skippedConcurrentEdit— a background merge never clobbers a concurrent user edit.
Exclusions: rows already superseded, contradiction-flagged pairs
(status='contradicted' / contradictionWith — deliberately kept by
G3-T4), embeddingExcluded rows, and rows without a stored vector are
skipped as seeds AND filtered out of candidate sets. Losers stay in the
vector index (like write-time supersede) — recall filters them post-
hydration, and Postgres remains the source of truth.
Idempotent: a re-run finds nothing new because losers are now superseded.
Cursor-resumable using the applyDecayPolicy pattern. REVIEW-GATED
(pinned Decision 3): run() defaults to dryRun: true and mutates nothing
unless the caller passes dryRun: false explicitly.
Constructors
Section titled “Constructors”Constructor
Section titled “Constructor”new CorpusConsolidationService(
prisma,ltmService,contradictionDetection,vectorStore?):CorpusConsolidationService
Defined in: packages/memory-ltm/src/corpus-consolidation.service.ts:89
Parameters
Section titled “Parameters”prisma
Section titled “prisma”ltmService
Section titled “ltmService”contradictionDetection
Section titled “contradictionDetection”vectorStore?
Section titled “vectorStore?”Returns
Section titled “Returns”CorpusConsolidationService
Methods
Section titled “Methods”getDuplicateThreshold()
Section titled “getDuplicateThreshold()”getDuplicateThreshold():
number
Defined in: packages/memory-ltm/src/corpus-consolidation.service.ts:114
Returns
Section titled “Returns”number
getMergeThreshold()
Section titled “getMergeThreshold()”getMergeThreshold():
number
Defined in: packages/memory-ltm/src/corpus-consolidation.service.ts:110
Returns
Section titled “Returns”number
run(
options?):Promise<CorpusConsolidationResult>
Defined in: packages/memory-ltm/src/corpus-consolidation.service.ts:123
Run one (resumable slice of a) consolidation pass. See the class doc for
semantics. Defaults to dryRun: true — the review gate — so calling this
without options NEVER mutates.
Parameters
Section titled “Parameters”options?
Section titled “options?”CorpusConsolidationOptions = {}
Returns
Section titled “Returns”Promise<CorpusConsolidationResult>