mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-09 03:22:40 +00:00
fix(memory-core): filter stale recall entries in REM harness preview
This commit is contained in:
@@ -45,6 +45,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Release/CI/E2E: Docker E2E and live Docker harness runs now apply default memory, CPU, and process ceilings while preserving explicit per-lane overrides.
|
||||
- Release/CI/E2E: plugin lifecycle matrix resource sampling now fails phases that exceed RSS, wall-clock, or CPU ceilings instead of only logging the measurements.
|
||||
- Release/CI/E2E: Codex npm plugin live assertions now cap transcript discovery and diagnostic log reads so failure proof stays bounded.
|
||||
- Memory: keep doctor REM harness previews aligned with live REM by dropping short-term recall snippets whose source files disappeared before rendering preview output. Thanks @samzong and @frankekn.
|
||||
- Tests/state isolation: QA Lab valid-tool-call metrics now require runtime tool-call evidence when runtime parity data is available instead of counting tool-backed scenario pass status alone.
|
||||
- Tests/state isolation: QA Lab runtime parity now fails planned-only tool-call rows without matching tool results instead of treating matching mock plans as real tool evidence.
|
||||
- Tests/state isolation: provider, media, auth, cron, task, session, sandbox, Gateway, and Codex timeout fixtures now scope more home/state/env data per test, reducing cross-test leakage and making release validation failures less noisy. (#90027, #89974)
|
||||
|
||||
@@ -2916,6 +2916,75 @@ describe("previewRemHarness", () => {
|
||||
expect(preview.grounded).toBeNull();
|
||||
});
|
||||
|
||||
it("skips REM short-term candidates whose source file disappeared", async () => {
|
||||
const workspaceDir = await createDreamingWorkspace();
|
||||
const nowMs = new Date("2026-04-15T12:00:00.000Z").getTime();
|
||||
await fs.writeFile(
|
||||
path.join(workspaceDir, "memory", "2026-04-14.md"),
|
||||
"Move backups to S3 Glacier.\n",
|
||||
"utf-8",
|
||||
);
|
||||
await recordShortTermRecalls({
|
||||
workspaceDir,
|
||||
query: "live backup",
|
||||
nowMs,
|
||||
results: [
|
||||
{
|
||||
path: "memory/2026-04-14.md",
|
||||
startLine: 1,
|
||||
endLine: 1,
|
||||
score: 0.91,
|
||||
snippet: "Move backups to S3 Glacier.",
|
||||
source: "memory",
|
||||
},
|
||||
],
|
||||
});
|
||||
await recordShortTermRecalls({
|
||||
workspaceDir,
|
||||
query: "stale provider setup",
|
||||
nowMs,
|
||||
results: [
|
||||
{
|
||||
path: "memory/.dreams/session-corpus/2026-04-16.txt",
|
||||
startLine: 2,
|
||||
endLine: 2,
|
||||
score: 0.88,
|
||||
snippet: "Assistant: Documented Ollama provider setup.",
|
||||
source: "memory",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const preview = await previewRemHarness({
|
||||
workspaceDir,
|
||||
nowMs,
|
||||
pluginConfig: {
|
||||
dreaming: {
|
||||
enabled: true,
|
||||
phases: {
|
||||
rem: {
|
||||
enabled: true,
|
||||
lookbackDays: 7,
|
||||
limit: 10,
|
||||
minPatternStrength: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const candidateTruthSnippets = preview.rem.candidateTruths
|
||||
.map((entry) => entry.snippet)
|
||||
.join("\n");
|
||||
const bodyText = preview.rem.bodyLines.join("\n");
|
||||
expect(preview.recallEntryCount).toBe(1);
|
||||
expect(preview.rem.sourceEntryCount).toBe(1);
|
||||
expect(candidateTruthSnippets).toContain("Move backups to S3 Glacier.");
|
||||
expect(candidateTruthSnippets).not.toContain("Documented Ollama provider setup");
|
||||
expect(bodyText).toContain("Move backups to S3 Glacier.");
|
||||
expect(bodyText).not.toContain("Documented Ollama provider setup");
|
||||
});
|
||||
|
||||
it("skips REM preview when rem.limit=0 while still ranking deep candidates", async () => {
|
||||
const workspaceDir = await createDreamingWorkspace();
|
||||
const nowMs = new Date("2026-04-15T12:00:00.000Z").getTime();
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
} from "./dreaming-phases.js";
|
||||
import { previewGroundedRemMarkdown, type GroundedRemPreviewResult } from "./rem-evidence.js";
|
||||
import {
|
||||
filterLiveShortTermRecallEntries,
|
||||
rankShortTermPromotionCandidates,
|
||||
readShortTermRecallEntries,
|
||||
type PromotionCandidate,
|
||||
@@ -131,10 +132,13 @@ export async function previewRemHarness(
|
||||
workspaceDir: params.workspaceDir,
|
||||
nowMs,
|
||||
});
|
||||
const recallEntries = filterRecallEntriesWithinLookback({
|
||||
entries: allRecallEntries,
|
||||
nowMs,
|
||||
lookbackDays: remConfig.lookbackDays,
|
||||
const recallEntries = await filterLiveShortTermRecallEntries({
|
||||
workspaceDir: params.workspaceDir,
|
||||
entries: filterRecallEntriesWithinLookback({
|
||||
entries: allRecallEntries,
|
||||
nowMs,
|
||||
lookbackDays: remConfig.lookbackDays,
|
||||
}),
|
||||
});
|
||||
const remPreviewLimit = resolveRemPreviewLimit(remConfig.limit, params.remPreviewLimit);
|
||||
const remSkipped = remConfig.limit <= 0 || remPreviewLimit <= 0;
|
||||
|
||||
Reference in New Issue
Block a user