consolidate · diff
git:20260917.07153d0 to git:20260917.8a9009d
46 added, 0 removed. Audit A to A.
---
name: consolidate
description: Periodically merge the memory index, long-tier memory files, and the habit file — deduplicate, resolve contradictions to the current truth, absolutize dates, bring HABITS.md back under budget — and propose the result for your confirmation before any write. Use when MEMORY.md grows large (~120+ lines), when the habit file is over budget, or when memories accumulate duplicates, contradictions, or stale facts.
---
# memory-loop: consolidate
Capture and expiry keep memory *flowing*; nothing keeps it *coherent*. Over many
sessions the index bloats, two files describe the same thing, an old fact
survives next to the newer one that disproved it, and "yesterday" is frozen in a
note whose yesterday is long gone. This skill is the operate-stage cleanup: a
reflective pass that merges long-tier memory into durable, well-organized form —
and, like `remember`, **never writes without your confirmation**.
> Adapted from xai-org/grok-build's "dream" consolidation pass (Apache-2.0),
> reframed around memory-loop's save gate and tier model.
## When to run
It is a manual skill — there is no forced trigger. Run it when:
- `MEMORY.md` has grown large (~120+ lines).
- A learning-review nudge surfaced duplicate or contradictory notes.
- A big piece of work finished and left several related memories behind.
- The learning-nudge hook reported HABITS.md over budget, or a write to it was
denied by `habits-budget-guard.sh`.
+ - The SessionStart upkeep check (`memory-staleness-check.sh`) listed
+ re-verification candidates, index drift, orphans or broken index links — it
+ is the closest thing this skill has to a trigger, and it only ever reports.
## Scope — what it may touch
Read `MEMORY.md`, the `tier: long` memory files beside it, and the habit file
(`habitsPath`, default `~/.claude/groundwork/HABITS.md`). **Exclude:**
| Excluded | Why |
|----------|-----|
| Files without a `tier` key | Outside the lifecycle (the compatibility contract) — never touch them |
| `tier: short` memories | The expiry sweep owns these; consolidation leaves them alone |
| Identity files (the user/assistant names from `setup`) | Continuity anchors — changed only through the `identity` skill, never here |
| Anything already under `archived/` | Already retired |
## The five verbs
Review each memory or group through five lenses (the consolidation prompt):
1. **Merge** — fold related information into one coherent, self-contained topic.
2. **Resolve** — on a contradiction, keep only the current truth; a recent
session that disproves an older fact wins (note the superseded one as
background if it still explains a decision).
3. **Convert** — turn relative dates ("yesterday", "last week") into absolute
dates.
4. **Discard** — drop ephemera: greetings, meta-commentary, tool-output noise,
consumed "current state / next steps", and preferences already in global
memory. **Discard means move to `archived/`, not delete** — nothing is lost.
5. **Preserve** — keep decisions and their rationale, architecture, preferences,
and problem/solution pairs.
+ ## The index pass
+
+ The index is a separate artifact from the memories it points at, so it drifts
+ on its own. All four checks are mechanical:
+
+ - **Broken links** — an index line naming a file that is not there.
+ - **Orphans** — a memory file no line points at; it is invisible to recall.
+ - **Drift** — a file newer than `MEMORY.md`: its one-line summary may describe
+ a version of the body that no longer exists. Re-read the body and rewrite the
+ line from it, never from the old summary.
+ - **Size** — past `memoryIndexMaxLines` (default 120) the index is itself the
+ thing to consolidate.
+
+ ## The staleness pass
+
+ Age is not wrongness. A memory past `memoryReviewDays` is a **candidate for
+ re-verification**, never a candidate for deletion:
+
+ 1. Re-verify it the way it was verified originally — run the command, read the
+ source. "It still sounds right" is not verification.
+ 2. Still true → set `reviewed: <today>` and change nothing else. That is the
+ whole repair, and it is what stops the same file being reported forever.
+ 3. Partly wrong → correct it, set `modified: <today>`, and fix its index line.
+ 4. Wholly superseded → archive it (never delete) and remove the index line.
+
+ Two buckets the check reports are **out of scope here** (see the exclusion
+ table above) — route both through `remember`: untiered files, and `tier: short`
+ memories whose expiry is conditional or missing, which no sweep will ever
+ archive and which are retired by their event, not by their age.
+
## The habit pass
HABITS.md is consolidated by the same five verbs, with one extra constraint: it
has a hard budget (`habitsBudgetBytes`, default 8000; `habitsMaxRules`, default
24) that a PreToolUse guard enforces at the write. Capture has an automatic
trigger and pruning does not, so without this pass the file only ever grows.
- **Merge by trigger, not by wording.** Two rules that fire in the same moment
are one rule however differently they are phrased. A cluster of rules that all
say "check the real artifact before claiming it" in the vocabulary of
different incidents is the single most common way the file fills up.
- **Re-apply the three gates** (damage / recurrence / generality) to every
existing rule, not just to new ones. A rule that names one script, one flag,
or one repo's layout fails generality now even if it passed when it was
written — route it to that repo's `CLAUDE.md` or the wiki.
- **Discard means archive**, exactly as for memories: move the rule to
`HABITS-ARCHIVE.md` beside HABITS.md, keeping its `[Cnn]` pointer so the case
record still resolves. Never touch HABITS-CASES.md itself — the cases outlive
the rules that cited them.
- **Never reword a rule while relocating it.** Moving and editing in the same
step is the hardest kind of change to review afterwards.
- Report the before/after of both numbers: bytes and rule count.
🛑 hard lines are consolidated, never dropped for budget: merge overlapping
prohibitions and compress their inline background to one sentence, but a
prohibition leaves this file only when it is promoted to a hook that enforces it.
## Procedure
1. **Read** (read-only) `MEMORY.md`, the in-scope long-tier files, and — when
this run includes the habit pass — all of HABITS.md.
2. **Apply the five verbs** and draft a **per-file action table** — no writing yet:
```
| File | Action | Basis (one line) |
|-----------------|---------------------------|----------------------------------------|
| a.md + b.md | merge → topic-x.md | same topic X in both; b is newer |
| c.md | evolve (edit in place) | 3 relative dates → absolute; 1 Resolve |
| d.md | archive | consumed project note; gist now global |
| e.md | keep | still valid, unchanged |
```
Include the before/after of each `MEMORY.md` index line that changes.
3. **Refuse the degenerate case.** If the table is empty — nothing genuinely
merges, contradicts, or staled — report "nothing to consolidate" honestly.
Never invent consolidation to look productive.
4. **Confirm before writing.** Present the table and ask the user to approve
all / pick items / reject. Flag any uncertain call (especially *which side of
a contradiction is current*) as a question, not a decision. **No `Write`/`Edit`
before this confirmation.**
5. **Apply only what was approved.** For each merge: create the merged file, move
the originals to `archived/`, update the `MEMORY.md` index line, and fix any
`[[wikilink]]` references to renamed files (grep to confirm none dangle).
Preserve every frontmatter key (`tier`, `salience`, `expires`, …) on the
surviving file.
6. **Report** what changed: N actions applied, index N → N lines.
+ 7. **Record the run** so the upkeep check stops asking:
+ ```bash
+ mkdir -p ~/.claude/groundwork/memory-loop
+ date +%Y-%m-%d > ~/.claude/groundwork/memory-loop/last-consolidate
+ ```
+
+ Write it after step 5 applied something, or after an honest "nothing to
+ consolidate" in step 3 — never as a way to silence the check without
+ looking.
+
## Safety contract
- Propose, then write — the confirmation in step 4 is the only path to a write.
- Never delete; archive instead (restore is a `mv` plus a save-gate re-save).
- Never bulk-add `tier` to untiered files here; that is the `remember` gate's job.
- An unverified inference is not consolidated — the same rule the save gate
applies at the entrance, applied again when reorganizing.
+ - Age alone never justifies removing a memory. If you cannot re-verify it now,
+ leave it and say so — an unverified old memory is a known risk, while a
+ deleted one is a silent gap.