Loading...
Loading...
Nightly memory consolidation — prunes stale entries, merges duplicates, resolves contradictions, rebuilds MEMORY.md index. Use when memory files have accumulated over many sessions and need cleanup. Do NOT use for storing new decisions (use remember) or searching memory (use memory).
npx skill4agent add yonatangross/orchestkit dreamDRY_RUN = "--dry-run" in "$ARGUMENTS" # Preview changes without writing# Find the memory directory (agent-specific or project-level)
# Agent memory lives in: .claude/agent-memory/<agent-id>/
# Project memory lives in: .claude/projects/<hash>/memory/
# Also check: .claude/memory/
memory_dirs = []
Glob(pattern=".claude/agent-memory/*/MEMORY.md")
Glob(pattern=".claude/projects/*/memory/MEMORY.md")
Glob(pattern=".claude/memory/MEMORY.md")
# For each discovered MEMORY.md, glob all *.md files in that directory
for dir in memory_dirs:
Glob(pattern=f"{dir}/../*.md") # All memory files alongside MEMORY.mdnamedescriptiontypeinventory = [{
"path": "/abs/path/to/file.md",
"name": frontmatter.name,
"type": frontmatter.type, # user, feedback, project, reference
"description": frontmatter.description,
"body": body_text,
"file_refs": [], # extracted file paths
"symbol_refs": [], # extracted function/class names
"topics": [], # key phrases for duplicate detection
}]/# Regex-like extraction from body text:
# - Paths containing / with common extensions: .py, .ts, .tsx, .js, .json, .md, .yaml, .yml, .sh
# - Backtick-wrapped paths: `src/something/file.ts`
# - Quoted paths in frontmatter descriptions
for ref in file_refs:
Glob(pattern=ref) # Check if file exists
# If no match → mark as STALE_FILE_REFfunction_name()ClassNamedef function_namefor symbol in symbol_refs:
Grep(pattern=symbol, path=".", output_mode="files_with_matches", head_limit=1)
# If no match → mark as STALE_SYMBOL_REF| Finding | Classification | Action |
|---|---|---|
| All file refs valid, all symbols found | FRESH | Keep |
| Some file refs missing | PARTIALLY_STALE | Flag for review |
| All file refs missing AND all symbols missing | FULLY_STALE | Prune candidate |
| No external refs (pure decision/preference) | EVERGREEN | Keep |
feedbackprojectnamedescriptionstopwords = {"the", "a", "an", "is", "are", "was", "were", "be", "been",
"have", "has", "had", "do", "does", "did", "will", "would",
"could", "should", "may", "might", "can", "shall", "to", "of",
"in", "for", "on", "with", "at", "by", "from", "as", "into",
"through", "during", "before", "after", "this", "that", "it",
"not", "no", "but", "or", "and", "if", "then", "than", "so"}
def significant_words(text):
words = set(text.lower().split()) - stopwords
return {w for w in words if len(w) > 2}
def overlap_ratio(words_a, words_b):
if not words_a or not words_b:
return 0.0
intersection = words_a & words_b
smaller = min(len(words_a), len(words_b))
return len(intersection) / smaller if smaller > 0 else 0.0
# For each pair with same type:
# if overlap_ratio >= 0.6 → DUPLICATE pair
# Keep the NEWER file (by filesystem mtime), prune the oldernegation_pairs = [
("do ", "do not "), ("do ", "don't "),
("use ", "avoid "), ("use ", "stop using "),
("prefer ", "don't prefer "), ("always ", "never "),
]
# For each pair flagged as contradictory:
# Keep the NEWER file (more recent decision supersedes)
# Prune the older file--dry-run--dry-run[DRY RUN][DRY RUN] Would delete: .claude/agent-memory/foo/stale_old_path.md (FULLY_STALE)
[DRY RUN] Would delete: .claude/agent-memory/foo/duplicate_auth.md (DUPLICATE of auth_patterns.md)
[DRY RUN] Would delete: .claude/agent-memory/foo/old_preference.md (CONTRADICTED by new_preference.md)
[DRY RUN] Would rebuild: .claude/agent-memory/foo/MEMORY.md (3 entries removed, 12 remaining)# 1. Delete FULLY_STALE files
for stale in fully_stale_files:
Bash(command=f"rm '{stale['path']}'")
# 2. Delete DUPLICATE files (keep newer)
for dup in duplicate_pairs:
older = dup["older"]
Bash(command=f"rm '{older['path']}'")
# 3. Delete CONTRADICTED files (keep newer)
for contradiction in contradiction_pairs:
older = contradiction["older"]
Bash(command=f"rm '{older['path']}'")
# 4. Rebuild MEMORY.md index from surviving files.md# <Directory Name> Memory
- [Name](filename.md) -- one-line description from frontmatter# Write the rebuilt MEMORY.md
Write(path="<memory_dir>/MEMORY.md", content=rebuilt_index)## Dream Consolidation Report
| Metric | Count |
|--------|-------|
| Memory directories scanned | N |
| Total memory files scanned | N |
| Stale entries pruned | N |
| Duplicates merged | N |
| Contradictions resolved | N |
| Partially stale (kept, flagged) | N |
| Evergreen (no external refs) | N |
| Surviving memories | N |
| MEMORY.md indexes rebuilt | N |
### Changes Made
| File | Action | Reason |
|------|--------|--------|
| `path/to/file.md` | DELETED | Fully stale: all referenced files removed |
| `path/to/old.md` | DELETED | Duplicate of `path/to/new.md` |
| `path/to/outdated.md` | DELETED | Contradicted by `path/to/current.md` |
### Flagged for Review (PARTIALLY_STALE)
| File | Missing References |
|------|-------------------|
| `path/to/file.md` | `src/old/path.ts` no longer exists |--dry-run[DRY RUN] No files were modified. Run without --dry-run to apply changes.| Condition | Response |
|---|---|
| No memory directories found | Report "No memory directories found" and exit |
| No memory files in directory | Report "Directory empty, nothing to consolidate" |
| All memories are FRESH | Report "All N memories are current, nothing to prune" |
| MEMORY.md exceeds 200 lines after rebuild | Warn user, do not auto-truncate |
| File deletion fails | Report error, continue with remaining files |
| Memory file has no frontmatter | Treat as EVERGREEN (cannot verify refs without metadata) |
/ork:remember/ork:memory search/ork:memory loadork:rememberork:memory