with one click
memory-consolidate
// Memory consolidation skill. Run during maintenance heartbeat to process daily logs into long-term memory. Should be invoked when memory/.last_consolidation is 1+ days old or missing.
// Memory consolidation skill. Run during maintenance heartbeat to process daily logs into long-term memory. Should be invoked when memory/.last_consolidation is 1+ days old or missing.
[HINT] Download the complete skill directory including SKILL.md and all related files
| name | memory-consolidate |
| description | Memory consolidation skill. Run during maintenance heartbeat to process daily logs into long-term memory. Should be invoked when memory/.last_consolidation is 1+ days old or missing. |
Process recent daily logs and promote important information to long-term memory.
Check memory/.last_consolidation for the date of last consolidation.
If it's 1+ days old or missing, run consolidation.
All steps below are mandatory on every consolidation run. There is no "lightweight" or "partial" mode. Even when daily logs are empty or steps 2–4 produce zero promotions, Step 6 (Regenerate SUMMARY.md) MUST still execute. Never skip or abbreviate steps because a run "has nothing to process."
Before processing, archive memory/TODAY.md to the daily/ directory:
memory/TODAY.md — extract the date header(s) (format: # YYYY-MM-DD)memory/daily/YYYY-MM-DD.md (create if needed). Copy every bullet point and line exactly as written — do NOT summarize, truncate, rephrase, or condense entries. The daily archive must be a byte-for-byte copy of the original content.memory/TODAY.md with today's date header and an immediate consolidation log entry:
# YYYY-MM-DD
- HH:MM — memory consolidation started
This entry is required — it ensures today's log is non-empty even if no user sessions follow, so the daily-log-weekly-coverage metric counts this day.This ensures daily logs accumulate in memory/daily/ while TODAY.md stays fresh for the current day.
Report tracking (required): After completing this step, add both memory/TODAY.md and the target memory/daily/YYYY-MM-DD.md to the JSON report's filesChanged array. This is mandatory — evaluators check filesChanged for memory/TODAY.md to verify this step ran. Omitting it causes the report to fail the today-md-archived criterion even when the archival was performed correctly.
If memory/TODAY.md doesn't exist, do NOT skip this step. Instead: create memory/TODAY.md now with today's date header and the consolidation start entry (step 3 above). Add memory/TODAY.md to filesChanged. There is no archive destination since there was no prior content — omit the memory/daily/YYYY-MM-DD.md entry from filesChanged in this case only.
Step 0 checkpoint (required before proceeding): Pause here and explicitly verify:
memory/TODAY.md is in your working filesChanged listmemory/daily/YYYY-MM-DD.md (today's date) is in filesChanged (unless TODAY.md did not exist prior to this run)If either entry is missing, add it now. Do NOT advance to Step 1 with these entries missing — the today-md-archived eval criterion checks filesChanged and will fail if TODAY.md is absent, even when the archival was performed correctly.
Read all files in memory/daily/ dated since the last consolidation date.
If no .last_consolidation file exists, process the last 14 days of logs.
[MEM-NNN] Tracked Keys (priority)Before extracting general facts, scan all daily logs from step 1 for lines containing [MEM-\d+], [MEM-<word>] (malformed), or [REMEMBER] (backward compat). These are tracked memory entries and must be promoted with guaranteed priority — they are never filtered by heuristics.
⚠️ Anti-pattern: auto-memory is NOT persistent memory. Claude Code's built-in auto-memory (
~/.claude/projects/.../memory/) is ephemeral — it does not survive re-clones, machine changes, or container restarts. NEVER treat auto-memory as a substitute for writing to the brain'smemory/tier files.[MEM-NNN]items MUST be physically written tomemory/core/ormemory/semantic/files. Claiming "already captured in auto-memory" is NOT valid — auto-memory is provider-specific and not part of our memory model.
If a [MEM-<word>] tag is found where <word> is NOT a number (e.g., [MEM-feedback], [MEM-TAG]):
memory/MEM_REGISTRY.md, find highest number, increment)[MEM-N] formatACTIVE[MEM-NNN] entry[REMEMBER] backward compatibilityIf a [REMEMBER] tag is found (without a [MEM-NNN] key):
memory/MEM_REGISTRY.md, find highest number, increment)ACTIVE[MEM-NNN] entry[MEM-NNN] entry:Check the registry — if the key isn't in memory/MEM_REGISTRY.md yet (new entry from a regular session), add it with status ACTIVE, today's date, and a short description.
Classify the destination based on content:
memory/core/PREFERENCES.mdmemory/core/LEARNINGS.mdmemory/core/MISTAKES.mdmemory/semantic/{topic}.mdCheck for duplicates — grep the target file for the same [MEM-NNN] key or similar content. If a match exists:
[MEM-NNN] key)Write to the destination file. The [MEM-NNN] key MUST be preserved in the promoted entry:
# In core/LEARNINGS.md:
- [MEM-3] Deploy flow: main = STAGING only, produkce = version tag (v0.0.X)...
Verify promotion landed — after writing, grep the target file for a key phrase from the promoted entry. If the grep returns no match, the write failed — retry or flag as an error in the report. Do not proceed to the next item until verification passes.
Report tracking: Add each promoted [MEM-NNN] item to the markdown report under a ## [MEM] Promotions section, listing: key, original entry, destination file, action taken (ADD/UPDATE/NOOP), verification result (VERIFIED/FAILED).
If no [MEM-NNN] or [REMEMBER] tags are found, skip this step and note "no [MEM] tags found" in the report.
Review entries in memory/MEM_REGISTRY.md with status ACTIVE:
Check for contradictions — if newer daily log entries contradict or supersede an existing ACTIVE entry, mark it OBSOLETE:
OBSOLETE, set obsoleted date[MEM-N] to [MEM-N:obsolete]Process previously OBSOLETE entries — for entries marked OBSOLETE in a previous consolidation run (check git history or the obsoleted date vs. last consolidation date):
[MEM-xxx:obsolete] line from the content fileREMOVEDReport tracking: Add lifecycle changes to the markdown report under ## [MEM] Lifecycle section.
For each daily log, identify (excluding already-processed [MEM-NNN] / [REMEMBER] entries):
For each extracted fact, compare with existing memory files:
Route new/updated facts to appropriate locations:
| Type | Destination |
|---|---|
| Team/project facts | memory/semantic/{topic}.md |
| Significant events | memory/episodic/{event-name}.md |
| Workflows/procedures | memory/procedural/{process-name}.md |
| Preferences | memory/core/PREFERENCES.md |
| Lessons | memory/core/LEARNINGS.md |
| Mistakes | memory/core/MISTAKES.md |
Review memory/core/MISTAKES.md for entries ready to be promoted. For each entry with status new:
Determine the promotion path:
skills/*/skill.md file (create a ## Pitfalls section if needed)memory/core/LEARNINGS.mdmemory/procedural/Execute the promotion:
promoted → {destination}Clean up previously promoted entries:
promoted in the previous consolidation run (they've been visible for one cycle)promoted during this run (so the promotion is visible next cycle)If MISTAKES.md has no entries or doesn't exist, skip this step.
Report tracking: Add any promoted-to files to filesChanged. Add a summary of promotions (or "no mistakes to promote") to the markdown report.
Scan memory/semantic/ for stale, oversized, or redundant files. This step keeps semantic memory clean and navigable — without it, old files accumulate noise that degrades search quality.
This step MUST run before Step 6 (Regenerate SUMMARY.md) — otherwise SUMMARY.md will contain stale pointers to files that were just deleted or renamed.
For each file in memory/semantic/:
git log -1 --format=%ai -- <file> to get the last commit date touching that file.git log returns empty (no history available, common in shallow clones after re-clone), treat the file as stale and flag it for review. Do NOT auto-delete files with missing history — only flag them for manual assessment.For each stale file, assess its content against current knowledge:
| Condition | Action |
|---|---|
| Content is still accurate and useful | KEEP — no change needed (reset staleness by noting "reviewed YYYY-MM-DD" in the report) |
| Content is partially outdated | UPDATE — refresh outdated sections in-place, preserve accurate parts |
| Content is fully outdated or superseded | DELETE — remove the file entirely |
| Content overlaps significantly with another semantic file | MERGE — combine into one file, delete the redundant one |
Conservative approach: When unsure whether content is still relevant, KEEP it. Only DELETE when the information is clearly wrong or obsolete. Prefer UPDATE over DELETE.
Never delete a file that contains [MEM-NNN] ACTIVE keys — those entries must first go through the MEM lifecycle (Step 1c) before the file can be removed.
For all files in memory/semantic/ (not just stale ones):
wc -lteamvibe-architecture.md → teamvibe-architecture-infra.md + teamvibe-architecture-api.md)TODAY.md that reference the old filenameDo not split aggressively — only split when the file covers clearly distinct sub-topics. A 120-line file about one cohesive topic is fine.
When processing stale files, also check for merge candidates among non-stale files:
Add a ## Semantic Lifecycle section to the markdown report:
## Semantic Lifecycle
- Files scanned: 8
- Stale (30+ days): 3 (1 via shallow clone fallback)
- Actions: 1 KEEP (reviewed), 1 UPDATE (refreshed), 1 DELETE (obsolete)
- Oversized (>100 lines): 1 (split into 2 files)
- Merges: 0
- Files changed: semantic/old-topic.md (deleted), semantic/architecture.md (updated)
Add any created, updated, or deleted semantic files to filesChanged. Set selfAssessment["semantic-lifecycle-checked"] to true.
If memory/semantic/ doesn't exist or is empty, skip this step and set selfAssessment["semantic-lifecycle-checked"] to true (nothing to check).
Always regenerate memory/SUMMARY.md on every consolidation run — this step is non-negotiable, even if no facts were promoted in steps 2–4. A lightweight consolidation with zero promotions must still regenerate SUMMARY.md to ensure it reflects the current state of all memory tiers.
Read all memory/core/*.md, scan memory/semantic/, memory/episodic/, memory/procedural/ for file listing, and compile into the SUMMARY.md format defined in the memory skill. Target ~100-150 lines.
Key sections:
The "How this memory works" block MUST be the first section in SUMMARY.md. It is static content — do not rephrase or compress it, copy it from the template.
Key Rules and Preferences must be actionable, not just labels. Bad: "stale prices". Good: "Always verify live data before trade proposals (detail: core/LEARNINGS.md)". The pointer tells the agent where to find the full context if needed.
This replaces the old "Update MEMORY.md" step. SUMMARY.md is the new authoritative index.
Report tracking (required): Add memory/SUMMARY.md to the JSON report's filesChanged array immediately after completing this step — do not defer to Step 12. Also set selfAssessment["summary-md-regenerated"] to true in the JSON report at this point. Evaluators check both filesChanged and selfAssessment["summary-md-regenerated"] to verify this step ran. Omitting memory/SUMMARY.md from filesChanged fails the summary-md-regenerated criterion even when the file was correctly regenerated.
For daily log files (format: YYYY-MM-DD.md) in memory/daily/ that are older than 30 days:
weekly-*.md) — they accumulate in memory/daily/ and eventually become stale files themselves, causing this step to fail in future runs.memory/daily/ and are older than 30 days, delete those too.memory/daily/.Recent-log retention (non-negotiable): NEVER delete memory/daily/<today>.md or memory/daily/<yesterday>.md, regardless of whether their contents have been promoted. Same-day and next-day sessions rely on these files to recover context. Promotion is not a reason to delete; deletion is only for files dated 30+ days ago.
Write the current date to memory/.last_consolidation:
YYYY-MM-DD
Heartbeat is being deprecated (teamvibeai/teamvibe.ai#102). Channel brain repos are private and live in customer GH orgs — the platform cannot inspect them. Each brain MUST self-report HEARTBEAT.md state so the eval pipeline can track migration progress.
All scheduled times below are UTC. runAt is ISO-8601 UTC, cron follows standard 5-field syntax in UTC. Do NOT use local time — agents run across timezones and the platform interprets schedules as UTC.
Sweep — if HEARTBEAT.md exists in the brain root:
- [ ] task:
(added YYYY-MM-DD) annotation or git blame on that line) and no longer relevant, mention it in decisions and delete it without scheduling — don't blindly schedule stale work.promptTemplate for create_scheduled_message that restates the task in imperative form ("Check if PR #123 is merged. If not, ping the assignee."). Include any context the agent will need (links, deadlines).create_scheduled_message. If the call fails, leave the line in place and continue with the next item — do NOT delete the source line until you have confirmation that the schedule was created. Record the failure in decisions.- [x] lines.HEARTBEAT.md to the JSON report's filesChanged if it was modified or deleted.decisions: how many items were migrated, how many deferred (failures or stale), file kept or deleted.Self-report — populate heartbeatStatus in the JSON report (always, even when HEARTBEAT.md does not exist):
"heartbeatStatus": {
"present": <bool: file exists at brain root after sweep>,
"nonEmpty": <bool: file has any non-task content line — see definition below>,
"itemCount": <int: number of unchecked '- [ ]' lines>
}
nonEmpty definition: true if the file contains at least one line that is NOT one of: blank, a heading (#), an HTML comment, or a completed - [x] task line. This means a file with only completed tasks counts as empty (the next sweep will remove them anyway).
Goal state: present: false. The eval pipeline aggregates this across all reports to know when platform-side heartbeat code can be removed (teamvibe.ai#101).
Run integrity checks on the MEM registry and collect memory size metrics.
If memory/MEM_REGISTRY.md exists:
memory/ (excluding MEM_REGISTRY.md and daily/) to confirm the key exists in at least one content file. A missing ACTIVE key = integrity violation.Record results in the markdown report under ## MEM Audit:
## MEM Audit
- Total keys: 12
- ACTIVE: 10, OBSOLETE: 1, REMOVED: 1
- New this cycle: 2 (MEM-011, MEM-012)
- Obsoleted this cycle: 0
- Integrity: ✅ all ACTIVE keys found in content files
- Sequence: ✅ no unexplained gaps
Populate JSON report selfAssessment:
mem-integrity-check — true if all ACTIVE keys are present and sequence is clean, false otherwiseIf memory/MEM_REGISTRY.md doesn't exist (pre-migration brains), skip and set mem-integrity-check to true (no keys to check).
Measure sizes of key memory files and include a ## Memory Metrics section in the markdown report.
How to measure: Run wc -c on each file (skip files that don't exist):
CLAUDE.md, memory/SUMMARY.md, memory/TODAY.md, memory/MEM_REGISTRY.mdmemory/core/LEARNINGS.md, memory/core/PREFERENCES.md, memory/core/MISTAKES.mdInclude this table in the markdown report:
## Memory Metrics
| File | Size (bytes) | Threshold | Status |
|------|-------------|-----------|--------|
| CLAUDE.md | 2800 | 10000 | :white_check_mark: |
| SUMMARY.md | 4200 | 8000 | :white_check_mark: |
| LEARNINGS.md | 3100 | 5000 | :white_check_mark: |
| MEM_REGISTRY.md | 800 | 5000 | :white_check_mark: |
| PREFERENCES.md | 500 | — | — |
| MISTAKES.md | 0 | — | — |
| TODAY.md | 1100 | — | — |
Thresholds (flag as :warning: if exceeded):
CLAUDE.md > 10000 — risk: instruction overloadSUMMARY.md > 8000 — risk: context bloatLEARNINGS.md > 5000 — risk: too many rules to followMEM_REGISTRY.md > 5000 — risk: registry too large (archive REMOVED entries)If the Memory Metrics table (Step 9b) shows CLAUDE.md exceeding 10000 bytes, perform one small extraction per consolidation cycle:
Identify one block (10–30 lines) in CLAUDE.md that is procedural, reference-like, or domain-specific knowledge — not core identity or behavioral rules. Good candidates:
memory/procedural/{topic}.mdmemory/semantic/{topic}.md@-imported SUMMARY.md → deleteExtract it:
CLAUDE.md entirely — do NOT leave a pointer in CLAUDE.md (saves space)memory/SUMMARY.md references the new file so the agent can find it via the always-loaded @ importLog it in the markdown report under ## CLAUDE.md Reduction:
Constraints:
@ import lines, or core behavioral rulesCLAUDE.md is under 10000 bytes, skip this step entirelyThis ensures steady progress toward the threshold while allowing time to detect regressions between cycles.
Before self-critique, run observable checks on the daily log scratchpad and record the outcome in both reports.
Checks (all over the last 7 days unless specified):
memory/TODAY.md exists and has non-empty content (or memory/daily/YYYY-MM-DD.md for today exists after archival). If no sessions ran today, pass.memory/TODAY.md exists with today's header, and memory/daily/<yesterday>.md is present after consolidation completes.memory/daily/*.md file is empty or contains only a header.days_with_daily_log / days_with_any_session over the last 7 days. Target ≥ 0.8. "Days with sessions" = days with commits to this brain, reports written, or (if available) inbox activity.@ imports configured. Read the channel brain CLAUDE.md and verify it contains both @memory/SUMMARY.md and @memory/TODAY.md. If either is missing, fail this check. If CLAUDE.md doesn't exist, fail.Write the result into the markdown report as a ## Daily Log Compliance section (see example in MAINTENANCE.md). Populate the corresponding selfAssessment keys in the JSON report:
daily-log-exists-todaydaily-log-continuous-appendsdaily-log-recent-retentiondaily-log-weekly-coverageat-imports-configuredIf any check fails, do one of two things before finishing:
memory/TODAY.md or the correct memory/daily/*.md file with a note that they were reconstructed (e.g., - (backfilled from git) 15:30 — shipped PR #51).[self-critique] entry in processImprovements naming the specific gap and what prevented the agent from writing during that day.Do not silently pass a failing check.
Before writing the report, reflect on whether the maintenance process itself is working. This is required — the JSON report's processImprovements field must contain at least one [self-critique] entry per consolidation run.
Ask yourself:
Write your answer as a [self-critique] entry even if things seem fine (e.g., "No recurring problems observed this cycle — memory tier coverage looks balanced"). The entry must reflect on process effectiveness, not just confirm that maintenance ran.
Do NOT use generic filler like "ran consolidation as scheduled" or "maintenance completed normally". The entry must identify a real gap, recurring problem, or process weakness observed during this run.
Example entries:
"[self-critique] HEARTBEAT.md has been empty for 3 weeks and I have not flagged this to the user — escalation is overdue""[self-critique] The same error pattern about API timeouts has appeared in 4 daily logs but has not been promoted to core memory — the consolidation threshold may be too conservative""[self-critique] No episodic memories have been written in 30 days despite several incidents in daily logs — I am systematically under-using that tier""[self-critique] The same team project facts are re-extracted each cycle because they're not being promoted to semantic memory""[self-critique] Consolidation is running but memory retrieval quality hasn't been validated — promoted facts may not be surfaced in practice"Pre-report filesChanged verification: Before writing the report, confirm these required entries are in filesChanged:
memory/SUMMARY.md — mandatory every run (Step 6). If missing from filesChanged: do NOT just add the filename — go back and execute Step 6 now, regenerate memory/SUMMARY.md from current memory state, then add it to filesChanged. Skipping Step 6 silently is not allowed.selfAssessment["summary-md-regenerated"] — must be explicitly set to true every run. This is a separate requirement from filesChanged. If not yet set: set it to true now. Evaluators check this field independently — a missing or false value fails the criterion even when SUMMARY.md is in filesChanged.memory/TODAY.md — mandatory every run (Step 0). If missing from filesChanged: do NOT just add the filename — go back and execute Step 0 now (reset TODAY.md with today's header and a consolidation start entry if not already done, append any existing content to today's daily log), then add memory/TODAY.md to filesChanged. Skipping Step 0 silently is not allowed.memory/daily/YYYY-MM-DD.md — the archived daily log (Step 0); add it now if missing (omit only when TODAY.md did not exist prior to this run)memory/MEM_REGISTRY.md — if any [MEM-NNN] entries were processed or lifecycle changes made in steps 1b/1c; add it now if missingCreate both a markdown and JSON report:
reports/YYYY-MM-DD-memory-consolidation.md (must include ## Daily Log Compliance from Step 10, ## MEM Audit from Step 9a, and ## Memory Metrics from Step 9b)reports/YYYY-MM-DD-memory-consolidation.json (must include daily-log-* and mem-integrity-check keys in selfAssessment, and the [self-critique] entry from Step 11 in processImprovements)For selfAssessment.reduce-log-count: set to true if at least one daily log was actively processed this run — either (a) Step 7 deleted one or more log files, OR (b) Steps 2–4 extracted content from at least one log and produced at least one ADD or UPDATE action. Set to false if no logs were processed (e.g., no logs in range, all NOOP). Always include daily log files whose content was extracted in filesChanged, even if they were not deleted — listing source logs gives the evaluator the evidence of log file activity it needs to verify this criterion.
When deciding what to promote, weigh:
After consolidation, commit all changes (including reports):
chore: consolidate memory (YYYY-MM-DD)