learning_ai_common_plat/packages/palace/src/decay.ts
saravanakumardb1 d1c6cf47c8 feat(palace): add @bytelyst/palace shared package — MemPalace primitives (91 tests)
New shared package: packages/palace/ (@bytelyst/palace)

Modules:
- types.ts — BasePalaceWingDoc, RoomDoc, MemoryDoc, TunnelDoc, KGTripleDoc, DiaryDoc
- halls.ts — HallType union, HALL_PRESETS (notelett/mindlyst/coding), hallFromLabel()
- cosine.ts — cosineSimilarity(), topKByCosine(), normalizeVector()
- dedup.ts — isContentDuplicate(), isExactDuplicate(), findClosestMatch()
- decay.ts — computeDecayedRelevance(), boostRelevance()
- extraction.ts — buildExtractionPrompt(), parseExtractionResponse(), regexFallbackExtraction()
- kg.ts — findContradictions(), mergeTriples(), isTripleCurrent()
- wakeup.ts — buildWakeUpLayers(), truncateToTokenBudget(), WAKEUP_PRESETS
- config.ts — palaceConfigSchema (Zod)

7 test files, 91 tests passing.
Consumed by NoteLett, MindLyst, and future palace-enabled products.
2026-04-10 00:57:00 -07:00

53 lines
1.8 KiB
TypeScript

/**
* Relevance decay for palace memories.
*
* Uses exponential half-life decay: relevance halves every N days.
* Memories that are accessed/referenced get their relevance boosted.
*/
const MS_PER_DAY = 86_400_000;
/**
* Compute decayed relevance using exponential half-life.
*
* @param originalRelevance - Initial relevance score (0-1)
* @param createdAt - ISO date string or Date when the memory was created/last accessed
* @param halfLifeDays - Number of days for relevance to halve (default: 30)
* @param asOf - Reference time for decay calculation (default: now)
* @returns Decayed relevance score (0-1)
*/
export function computeDecayedRelevance(
originalRelevance: number,
createdAt: string | Date,
halfLifeDays = 30,
asOf: Date = new Date()
): number {
if (halfLifeDays <= 0) return originalRelevance;
if (originalRelevance <= 0) return 0;
const created = typeof createdAt === 'string' ? new Date(createdAt) : createdAt;
const elapsedMs = asOf.getTime() - created.getTime();
if (elapsedMs <= 0) return Math.min(originalRelevance, 1);
const elapsedDays = elapsedMs / MS_PER_DAY;
const decayFactor = Math.pow(0.5, elapsedDays / halfLifeDays);
return Math.max(0, Math.min(1, originalRelevance * decayFactor));
}
/**
* Compute a boosted relevance for a memory that was accessed/referenced.
*
* Boost formula: new = old + (1 - old) * boostFactor
* This asymptotically approaches 1.0 without exceeding it.
*
* @param currentRelevance - Current relevance score (0-1)
* @param boostFactor - How much of the remaining gap to close (default: 0.3)
* @returns Boosted relevance score (0-1)
*/
export function boostRelevance(currentRelevance: number, boostFactor = 0.3): number {
const boosted = currentRelevance + (1 - currentRelevance) * boostFactor;
return Math.min(1, Math.max(0, boosted));
}