fix(memory-core): use all dreaming signals for light confidence

This commit is contained in:
Vincent Koc
2026-04-12 18:30:35 +01:00
parent a24af49100
commit 8a4a63ca07
3 changed files with 31 additions and 1 deletions

View File

@@ -32,6 +32,7 @@ Docs: https://docs.openclaw.ai
- Gateway/cron: preserve requested isolated-agent config across runtime reloads so subagent jobs and heartbeat overrides keep the right workspace and heartbeat settings when the hot-loaded snapshot is stale. Thanks @l0cka and @vincentkoc.
- Gateway/plugins: always send a non-empty `idempotencyKey` for plugin subagent runs, so dreaming narrative jobs stop failing gateway schema validation. (#65354) Thanks @CodeForgeNet and @vincentkoc.
- Dreaming/promotion: raise phase reinforcement enough for repeated dreaming-only revisits to clear the default durable-memory gate after multiple days, instead of stalling just below the score threshold. Thanks @vincentkoc.
- Dreaming/light-sleep: compute staged candidate confidence from all recorded short-term signals instead of recall-only counts, so dreaming-only entries stop rendering as `confidence: 0.00`. Thanks @vincentkoc.
- CLI/plugins: honor `memory-wiki` when `plugins.allow` is set for `openclaw wiki`, and register `wiki` as the plugin-owned command alias so doctor/config stop treating it as stale. (#64779) Thanks @feiskyer and @vincentkoc.
- Cron/isolated sessions: persist the right transcript path for each isolated run, including fresh session rollovers, so cron runs stop appending to stale session files. Thanks @samrusani and @vincentkoc.
- CLI/memory-wiki: pass the active app config into the metadata registrar so built `openclaw wiki` commands resolve the live wiki plugin config instead of silently falling back to defaults. (#65012) Thanks @leonardsellem and @vincentkoc.

View File

@@ -406,6 +406,29 @@ describe("memory-core dreaming phases", () => {
expect(after[0]?.snippet).toContain("Keep retention at 365 days.");
});
it("renders non-zero light-sleep confidence for dreaming-ingested candidates", async () => {
const workspaceDir = await createDreamingWorkspace();
await withDreamingTestClock(async () => {
await writeDailyNote(workspaceDir, [
`# ${DREAMING_TEST_DAY}`,
"",
"- Move backups to S3 Glacier.",
"- Keep retention at 365 days.",
]);
const { beforeAgentReply } = createLightDreamingHarness(workspaceDir);
await triggerLightDreaming(beforeAgentReply, workspaceDir, 5);
const dailyContent = await fs.readFile(
path.join(workspaceDir, "memory", `${DREAMING_TEST_DAY}.md`),
"utf-8",
);
expect(dailyContent).toContain("## Light Sleep");
expect(dailyContent).toContain("confidence: 0.62");
expect(dailyContent).not.toContain("confidence: 0.00");
});
});
it("checkpoints session transcript ingestion and skips unchanged transcripts", async () => {
const workspaceDir = await createDreamingWorkspace();
vi.stubEnv("OPENCLAW_TEST_FAST", "1");

View File

@@ -1241,7 +1241,13 @@ export async function seedHistoricalDailyMemorySignals(params: {
}
function entryAverageScore(entry: ShortTermRecallEntry): number {
return entry.recallCount > 0 ? Math.max(0, Math.min(1, entry.totalScore / entry.recallCount)) : 0;
const signalCount = Math.max(
0,
Math.floor(entry.recallCount ?? 0) +
Math.floor(entry.dailyCount ?? 0) +
Math.floor(entry.groundedCount ?? 0),
);
return signalCount > 0 ? Math.max(0, Math.min(1, entry.totalScore / signalCount)) : 0;
}
function tokenizeSnippet(snippet: string): Set<string> {