fix(memory): correct dormant formula, remove hard prune, integrate reinforcement

P0.1 - Fix dormant effective age formula:
- Use overlap logic: only apply dormancy to entry's lifetime
- Formula: activeDays + dormantOverlapDays * 0.25
- calculateDormantDays now returns total days (not excess past grace)
- Test: 28 dormant days → 17.5 effective days

P0.2 - Remove hard stale pruning:
- Remove isPrunableByAge from enforcement
- Remove rejected_stale from accounting reasons
- Elimination now by cap competition only

P0.3 - Integrate reinforcement:
- Call reinforceMemory in dedupe absorption path
- Call reinforceMemory in promotion duplicate path
- Update retentionClock on reinforcement

A1 - Retention clock reset on reinforcement

A4 - Fix tests to encode correct formula
This commit is contained in:
Ralph Chang
2026-04-29 14:55:25 +08:00
parent ffb612226c
commit 04233f8452
6 changed files with 191 additions and 95 deletions
+22 -7
View File
@@ -36,6 +36,7 @@ import {
updateWorkspaceMemory,
updateWorkspaceMemoryWithAccounting,
renderWorkspaceMemory,
reinforceMemory,
} from "./workspace-memory.ts";
import {
appendPendingMemories,
@@ -311,21 +312,35 @@ export const MemoryV2Plugin: Plugin = async (input) => {
const updateResult = await updateWorkspaceMemoryWithAccounting(directory, workspaceMemory => {
beforeEntries = [...workspaceMemory.entries];
const existingKeys = new Set(
workspaceMemory.entries
.filter(memory => memory.status !== "superseded")
.map(memory => memoryKey(memory)),
);
const existingByKey = new Map<string, { memory: typeof workspaceMemory.entries[number]; index: number }>();
workspaceMemory.entries.forEach((memory, index) => {
if (memory.status === "superseded") return;
existingByKey.set(memoryKey(memory), { memory, index });
});
const promotedAt = Date.now();
for (const memory of pending) {
const key = memoryKey(memory);
if (!existingKeys.has(key)) {
const existing = existingByKey.get(key);
if (existing) {
const reinforced = reinforceMemory(
existing.memory,
sessionID ?? memory.pendingOwnerSessionID ?? "workspace-promotion",
promotedAt,
);
if (reinforced !== existing.memory) {
workspaceMemory.entries[existing.index] = reinforced;
existingByKey.set(key, { memory: reinforced, index: existing.index });
}
} else {
workspaceMemory.entries.push({
...memory,
retentionClock: memory.retentionClock ?? promotedAt,
});
existingKeys.add(key);
existingByKey.set(key, {
memory: workspaceMemory.entries[workspaceMemory.entries.length - 1],
index: workspaceMemory.entries.length - 1,
});
}
}