feat: Dreaming engine for periodic memory consolidation#592
feat: Dreaming engine for periodic memory consolidation#592helal-muneer wants to merge 1 commit intoCortexReach:masterfrom
Conversation
rwmjhb
left a comment
There was a problem hiding this comment.
Interesting feature with a sound architecture (bridging existing tier-manager and decay-engine). Branch needs a rebase and one scope isolation issue needs fixing before merge.
Please rebase onto current main — stale_base=true and index.ts has had significant recent activity. Rebase needed to surface any conflicts before this can land.
Must fix
MR1 — Dreaming ignores scope isolation and synthesizes cross-scope memories into global
The engine fetches memories across all scopes, then stores REM reflections with a hardcoded scope: 'global'. In multi-user or multi-workspace deployments this leaks content between isolated memory spaces — a user's private memories can influence another user's global reflection entries.
Fix: filter store.list() by the active scope in each phase, and tag REM reflections with the same scope as the source memories.
Non-blocking
- F1 —
resolveEnvVarsnow returns''instead of throwing for unset env vars. This silently propagates an empty API key throughresolveFirstApiKey'sif (!key)guard (which only checks the raw config string, before resolution). Users with"${JINA_API_KEY}"configured but the env var unset will get opaque HTTP 401 failures instead of a clear startup error. - F2 — REM stores reflection with
vector: []. LanceDB uses fixed-dimension Arrow columns — a 0-dimension vector will throw an Arrow schema mismatch on every cycle. The error is caught and logged as⚠️ REM failed, so the REM phase silently never creates any reflection memories. - F3 —
config.phases.light(and.deep,.rem) accessed without null guard. A minimal config like{ "dreaming": { "enabled": true } }crashes withTypeError: Cannot read properties of undefinedon first cycle. Add aDEFAULT_DREAMING_CONFIGand deep-merge it at parse time. - F6 —
storageMode('separate'/'both') andcronfields are exposed inconfigSchemaand UI hints but never read at runtime. Users selecting these options silently getinlinebehavior and 6-hour fixed intervals. Remove from schema until implemented, or log a warning when set.
- MR1: Add scope isolation to dreaming engine — all phases now filter by active scope, REM reflections tagged with source scope instead of hardcoded 'global' - F1: resolveFirstApiKey now validates resolved env var value, throws clear error if env var is unset instead of silently propagating empty API key - F2: REM phase no longer stores vector:[] (Arrow schema mismatch). Accepts optional embedFn; if unavailable, logs patterns without creating a memory entry - F3: Add DEFAULT_DREAMING_CONFIG + mergeDreamingConfig() for safe deep-merge of partial user configs over defaults - F6: Remove unimplemented cron/timezone/storageMode/separateReports from DreamingConfig interface and openclaw.plugin.json schema
a240a8a to
705da9a
Compare
705da9a to
82f710c
Compare
- H: Cross-agent shared memory scope (shared:) - I: Entity relationship layer (entity-graph.ts) - J: Memory confidence scoring (confidence-tracker.ts) - K: Proactive memory injection (proactive-injector.ts) New tools: memory_entities, memory_boost, memory_shared Config: scopes.shared, entityGraph.enabled, proactive.enabled
82f710c to
62e44a6
Compare
rwmjhb
left a comment
There was a problem hiding this comment.
The three-phase dreaming concept is interesting, but there are several correctness blockers that need to be resolved before this is mergeable.
Must fix before merge:
-
MR1: Scope isolation violated. The dreaming engine can synthesize cross-scope memories into
global, defeating the per-user/per-agent isolation guarantees the rest of the plugin provides. Dreaming should only consolidate within the originating scope. -
MR2: REM output re-enters the consolidation pool. REM reflections are stored as generic legacy working memories, so subsequent dreaming cycles can reprocess their own output — unbounded feedback loop.
-
F2: REM phase stores reflection with
vector: []. LanceDB enforces a fixed vector dimension. An empty vector will crash every REM cycle against the schema constraint. -
F3:
config.phasesaccessed without null guard. A minimal dreaming config (omittingphases) throws a TypeError at startup. -
F6:
storageModeandcronfields are schema-advertised but entirely unimplemented. Shipping config knobs that silently do nothing is a user-trust issue. Either implement or remove from schema before merge.
Nice to have (non-blocking):
- F1:
resolveEnvVarssilently returns''for unset env vars — a missing embedding API key becomes an empty string with no warning. - F4: Initial
setTimeouthandle is discarded — the first cycle can fire afterstop()if the plugin restarts within 5 minutes. - EF1: The 319-line dreaming engine has zero automated test coverage across all three phases.
Address the must-fix items and this is ready for a proper review.
|
The schema gap causing UI validation errors is a real problem, and bridging tier-manager + decay-engine is the right architectural approach. However there are several correctness issues that need to land before this is safe to enable. Must fix
High priority
Other
Question for author: Was Strategy B (bridge mode) explicitly endorsed by a maintainer? Issue #577 describes three strategies but shows no maintainer response before implementation started — want to make sure the approach was aligned. |
Summary
Closes #577
Implements Dreaming functionality — periodic memory consolidation and tier promotion that bridges LanceDB Pro's existing , , and into OpenClaw's dreaming lifecycle.
Three-Phase Dreaming Cycle
💤 Light Sleep — Decay + Tier Re-evaluation
decayEngine.scoreAll()tierManager.evaluateAll()store.patchMetadata()🧠 Deep Sleep — Working → Core Promotion
patchMetadata()💫 REM — Pattern Detection & Reflection
category: "reflection") with discovered patternsChanges
src/dreaming-engine.tsopenclaw.plugin.jsondreamingconfig schema + UI hintsindex.tsBug Fix Included
resolveEnvVars()now returns empty string instead of throwing when env var is missing (prevents plugin startup failure whenJINA_API_KEYetc. are unset)Configuration
{ "dreaming": { "enabled": true, "timezone": "UTC", "storageMode": "inline", "verboseLogging": false, "phases": { "light": { "lookbackDays": 7, "limit": 50 }, "deep": { "limit": 20, "minScore": 0.5, "minRecallCount": 2 }, "rem": { "lookbackDays": 30, "limit": 10, "minPatternStrength": 0.6 } } } }Testing