feat(memory): Add opt-in temporal decay for hybrid search scoring

Exponential decay (half-life configurable, default 30 days) applied
before MMR re-ranking. Dated daily files (memory/YYYY-MM-DD.md) use
filename date; evergreen files (MEMORY.md, topic files) are not
decayed; other sources fall back to file mtime.

Config: memorySearch.query.hybrid.temporalDecay.{enabled, halfLifeDays}
Default: disabled (backwards compatible, opt-in).
This commit is contained in:
Rodrigo Uroz
2026-02-10 08:42:22 -03:00
committed by Peter Steinberger
parent fa9420069a
commit 6b3e0710f4
13 changed files with 1372 additions and 35 deletions

View File

@@ -278,11 +278,13 @@ export class MemoryIndexManager implements MemorySearchManager {
return vectorResults.filter((entry) => entry.score >= minScore).slice(0, maxResults);
}
const merged = this.mergeHybridResults({
const merged = await this.mergeHybridResults({
vector: vectorResults,
keyword: keywordResults,
vectorWeight: hybrid.vectorWeight,
textWeight: hybrid.textWeight,
mmr: hybrid.mmr,
temporalDecay: hybrid.temporalDecay,
});
return merged.filter((entry) => entry.score >= minScore).slice(0, maxResults);
@@ -343,8 +345,10 @@ export class MemoryIndexManager implements MemorySearchManager {
keyword: Array<MemorySearchResult & { id: string; textScore: number }>;
vectorWeight: number;
textWeight: number;
}): MemorySearchResult[] {
const merged = mergeHybridResults({
mmr?: { enabled: boolean; lambda: number };
temporalDecay?: { enabled: boolean; halfLifeDays: number };
}): Promise<MemorySearchResult[]> {
return mergeHybridResults({
vector: params.vector.map((r) => ({
id: r.id,
path: r.path,
@@ -365,8 +369,10 @@ export class MemoryIndexManager implements MemorySearchManager {
})),
vectorWeight: params.vectorWeight,
textWeight: params.textWeight,
});
return merged.map((entry) => entry as MemorySearchResult);
mmr: params.mmr,
temporalDecay: params.temporalDecay,
workspaceDir: this.workspaceDir,
}).then((entries) => entries.map((entry) => entry as MemorySearchResult));
}
async sync(params?: {