feat: memory decay — move old archives to cold storage (v3.3)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-31 15:12:20 +10:00
co-authored by Claude Sonnet 4.6
parent a7aeb673b7
commit 85bb1be946
2 changed files with 56 additions and 1 deletions
+46
View File
@@ -589,6 +589,51 @@ function findRelevantHistory(workspaceDir, objective, maxItems = 3) {
return lines.join("\n");
}
/**
* Move archives older than `decayDays` to a cold/ subdirectory.
* Files are preserved, not deleted — they just leave the active index.
*/
function decayOldArchives(workspaceDir, config = {}) {
const decayDays = config.archiveDecayDays ?? 30;
if (decayDays <= 0) return; // Disabled
const archiveDir = path.join(workspaceDir, "memory", "session_archive");
const coldDir = path.join(archiveDir, "cold");
let files;
try { files = fs.readdirSync(archiveDir).filter(f => f.endsWith(".md")); }
catch { return; }
const cutoff = Date.now() - (decayDays * 86400000);
let movedCount = 0;
for (const f of files) {
// Parse date from filename: YYYY-MM-DD_HH-MM.md
const dateMatch = f.match(/^(\d{4})-(\d{2})-(\d{2})/);
if (!dateMatch) continue;
const fileDate = new Date(
parseInt(dateMatch[1]),
parseInt(dateMatch[2]) - 1,
parseInt(dateMatch[3])
).getTime();
if (fileDate < cutoff) {
fs.mkdirSync(coldDir, { recursive: true });
const src = path.join(archiveDir, f);
const dst = path.join(coldDir, f);
try {
// Move: copy then delete
fs.copyFileSync(src, dst);
fs.unlinkSync(src);
movedCount++;
} catch {}
}
}
return movedCount;
}
function extractStateFromMessages(messages) {
if (!messages || messages.length === 0) return null;
@@ -819,6 +864,7 @@ const plugin = {
// Generate daily summary for previous day if needed
generateDailySummary(ws, config);
generateWeeklySummary(ws, config);
decayOldArchives(ws, config);
const existing = readFile(statePath);
const newState = extractStateFromMessages(messages);