Sleep cycle is now triggered by a system cron job (`0 3 * * *`) calling
`openclaw memory neo4j sleep` rather than an in-process 6-hour interval
timer with mutex. Simpler, more reliable, and easier to manage.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Auto-trigger sleep cycle (dedup, extraction, decay, cleanup) in the
background after agent_end when 6h+ have elapsed. Configurable via
sleepCycle.auto and sleepCycle.autoIntervalMs. Removes need for
external cron job with regular gateway usage.
Also includes: removal of Pareto promotion (replaced by manual core
promotion), entity dedup in sleep cycle, and sleep cycle pipeline
cleanup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add userPinned boolean on Memory nodes: user-stored core memories are
immune from importance recalculation, decay, and pruning. Only removable
via memory_forget. Importance locked at 1.0.
- Add listCoreForInjection(): always injects ALL userPinned core memories
plus top N non-pinned core memories by importance (no silent drop-off
for user-pinned memories regardless of maxEntries cap).
- Remove core demotion entirely: promotion is now one-way. Bad core
memories are handled manually via memory_forget.
- Add [bench] performance timing to auto-recall, auto-capture, core
memory injection, core refresh, and hybridSearch.
- Audit fixes: remove dead entity/tag methods, dead test blocks, orphaned
demoteFromCore docstring, unnecessary .slice() in graphSearch.
- Refactor attention gate into shared checks for user/assistant gates.
- Consolidate LLM client, message utils, and config helpers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Search: fix entity classification order (proper nouns before word count),
BM25 min-max normalization with floor, empty query guard.
Decay: retrieval-reinforced half-life with effective age anchored to
lastRetrievedAt, parameterized category curves (no string interpolation).
Dedup: transfer TAGGED relationships to survivor during merge.
Orphans: use EXISTS pattern instead of stale mentionCount.
Embeddings: Ollama retry with exponential backoff (2 retries, 1s base).
Config: resolve env vars in neo4j.uri, re-export MemoryCategory from schema.
Extractor: abort-aware batch delay, anonymize prompt examples.
Tests: add 80 tests for index.ts (attention gates, message extraction,
wrapper stripping). Full suite: 480 tests across 8 files, all passing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix initPromise retry: reset to null on failure so subsequent calls
retry instead of returning cached rejected promise
- Remove dead code: findPromotionCandidates, findDemotionCandidates,
calculateEffectiveImportance (~190 lines, never called)
- Add agentId filter to deleteMemory() to prevent cross-agent deletion
- Fix phase label swaps: 1b=Semantic Dedup, 1c=Conflict Detection
(CLI banner, phaseNames map, SleepCycleResult/Options type comments)
- Add autoRecallMinScore and coreMemory config to plugin JSON schema
so the UI can validate and display these options
- Add embedding LRU cache (200 entries, SHA-256 keyed) to eliminate
redundant API calls across auto-recall, auto-capture, and tools
- Add Ollama concurrency limiter (chunks of 4) to prevent thundering
herd on single-threaded embedding server
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Five high-impact improvements to the memory system:
1. Min RRF score threshold on auto-recall (default 0.25) — filters low-relevance
results before injecting into context
2. Deduplicate auto-recall against core memories already present in context
3. Capture assistant messages (decisions, recommendations, synthesized facts)
with stricter attention gating and "auto-capture-assistant" source type
4. LLM-judged importance scoring at capture time (0.1-1.0) with 5s timeout
fallback to 0.5, replacing the flat 0.5 default
5. Conflict detection in sleep cycle (Phase 1b) — finds contradictory memories
sharing entities, uses LLM to resolve, invalidates the loser
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add extraction config section (apiKey, model, baseUrl) to plugin schema
with env-var fallback and Ollama/local LLM support (no API key required)
- Add category classification to extraction prompt; update memories from
'other' to LLM-assigned category
- Reorder sleep phases: extraction before decay
- Parallelize extraction (3 concurrent via Promise.allSettled)
- Pre-compute effective scores once and reuse for promotion/demotion
- Replace O(n²) Cartesian dedup with per-memory HNSW vector index queries
- Use mentionCount for orphan entity detection instead of subquery
- Remove dead auto-capture code (evaluateAutoCapture, CaptureItem, etc.)
Add `coreMemory.refreshAtContextPercent` config option to re-inject
core memories when context usage exceeds a threshold. This counters
the "lost in the middle" phenomenon documented by Liu et al. (2023).
Implementation:
- Extend before_agent_start hook event with context usage info
- Pass contextWindowTokens and estimatedUsedTokens to hooks
- Track mid-session refresh per session to prevent over-refreshing
- Clear refresh tracking on compaction
- Add comprehensive tests
Based on research: Liu et al., "Lost in the Middle: How Language
Models Use Long Contexts" (Stanford, 2023)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>