feat: self-pruning memory consolidation and on-demand rule loading#74
Conversation
Consolidation was append-only: signal-discoverer added, memory-auditor removed only on factual contradiction, and the 170-line size gate never fired — so the index grew unbounded. - memory-auditor: audit principles for SUPERSEDED/REDUNDANT/LOW-VALUE retirement, not just factual staleness - signal-discoverer: raise the bar — zero new candidates is a valid result - extract-learnings: replace the dead size gate with per-run downward pressure plus adaptive clustering (split sections past 25 entries into memory/clusters/*.md)
update-claudemd promised progressive disclosure but wrote topic files to .claude/rules/, which auto-loads every session — defeating its own purpose. Mandate paths: frontmatter (path-specific rules) on every topic file, threaded through the research/classify/approve pipeline so a backfill is visible at the approval gate rather than a silent rewrite. Apply the fix to this repo's claude-memory-architecture.md, which was loading 1.5k every session.
|
Claude finished @gupsammy's task in 5m 46s —— View job PR #74 Review
What looks goodNo Python changes. All modified files are Markdown skill/agent definitions or JSON manifests. The stdlib-only, Version sync is correct across all four locations.
---
paths:
- "plugins/claude-memory/**"
---Scoping to Must fix before mergeNothing blocking. The committed state on this branch is correct. One working-tree note (not a merge blocker): Optional suggestions
|
| 3. Apply topic file actions in this sub-order: delete orphaned topic files the user approved for removal, then write new topic files, then edit existing topic files (applying keep/update/delete/promoted-out/moved-in actions). Promoted-out sections are removed from the topic file in this step; they reappear in CLAUDE.md in step 4 | ||
| 3. Apply topic file actions in this sub-order: | ||
| - Delete orphaned topic files the user approved for removal | ||
| - Write new topic files; each must carry `paths:` YAML frontmatter scoped to the globs its subject covers (e.g. `paths: ["plugins/*/hooks/**"]`) |
There was a problem hiding this comment.
Nit: inline JSON-array form (paths: ["plugins/*/hooks/**"]) differs from the YAML block-sequence form used in the canonical example ~15 lines below. Both are valid YAML, but the block form reads more clearly and matches what the example shows. Consider:
| - Write new topic files; each must carry `paths:` YAML frontmatter scoped to the globs its subject covers (e.g. `paths: ["plugins/*/hooks/**"]`) | |
| - Write new topic files; each must carry `paths:` YAML frontmatter scoped to the globs its subject covers (e.g. `paths:\n - "plugins/*/hooks/**"`) |
Or simpler — just drop the inline form since the full example already shows the correct shape.
| - REDUNDANT: overlaps a sibling entry and adds no distinct value → REMOVE or MERGE. | ||
| - LOW-VALUE: too generic, obvious, or narrow to change future behavior → REMOVE. | ||
| Evidence here is corpus-internal (quote the competing/overlapping entry), not codebase. | ||
| Downward pressure is the goal: a consolidation that retires nothing is suspect. |
There was a problem hiding this comment.
"a consolidation that retires nothing is suspect" — deliberate, well-stated policy. Worth keeping exactly as phrased; softer wording like "should be reviewed" would dilute it.
| Steps 2-4 are required and run as parallel tool calls. | ||
|
|
||
| 2. Read MEMORY.md + list topic files (`Glob memory/*.md` from resolved path) | ||
| 2. Read MEMORY.md + list topic and cluster files (`Glob memory/**/*.md` from resolved path) |
There was a problem hiding this comment.
Pattern upgrade from memory/*.md → memory/**/*.md is correct for the new clusters/ sub-directory. Just a reminder that Glob runs relative to the cwd of the main session, not to the resolved memory directory — the "from resolved path" qualifier in the instruction is load-bearing here and should survive if this section is ever reworded.
Follow-up to 5261ef5. An audit of a live consolidation run showed the new pruning generated retirements it could not execute (no deletion tool) and reported them done anyway, and that plain-name index pointers never drove lookups. - extract-learnings: grant Bash(trash:*); Phase 4 deletes via trash then verifies absence with Glob before reporting success; enforce retire->merge->cluster order so clustering cannot mask removable entries; add condition-first Pointer Format (triggered vs always-on) - memory-auditor: merge criterion now fires on shared slug-prefix + same subject, not only >50% textual overlap - signal-discoverer: propose entries with condition-first pointers
|
Claude finished @gupsammy's task in 2m 35s —— View job PR #74 Review — updated pass (commit b5a572a)
This pass covers the single new commit added since the previous review ( What the new commit addressesThe commit message explains an operational failure: a live consolidation run produced REMOVE/MERGE proposals it couldn't execute (no deletion tool) and then reported them done anyway, and MEMORY.md index pointers written as bare filenames were never opening files. The changes fix both:
What looks goodExecution ordering is now correct and explicit. The retire → merge → cluster → add sequence prevents clustering from masking removable entries — exactly the failure mode the commit describes. The ordering guard ("Clustering never runs before retirement") is stated twice (steps 7 and Phase 4), which is the right level of emphasis for something that silently failed before.
Glob verification before marking done is a meaningful guard. Tying Phase 4 completion to Pointer Format section is well-positioned. It sits between Memory Hierarchy and Early Exit Guard, so it's loaded before any phase that writes pointers. The two-shape definition (triggered vs. always-on) with a worked example is clear enough for an agent to follow without ambiguity. Slug-prefix merge trigger is a good heuristic. A family of Version sync correct. All four locations ( Must fix before mergeNothing blocking from the new commit. Working-tree note (carried from previous review, still present): Optional suggestions
|
Phase 4 Glob verification dropped the from-resolved-path qualifier present in Phase 1, risking a glob against session cwd that reports all files absent. Marker step lost the rationale for using Bash over Write. Restore both per PR #74 review.
Drop the inline JSON-array paths example that diverged from the canonical block-sequence form shown in the full example below. Matches the YAML block-sequence convention. Per PR #74 review.
|
Claude finished @gupsammy's task in 2m 15s —— View job PR #74 Review — final pass (post-merge, all 5 commits)
What looks goodNo Python changes. All modified files are Markdown skill/agent definitions or JSON manifests. The stdlib-only, Version sync is correct — final state.
The three-bump increment on
---
paths:
- "plugins/claude-memory/**"
---The previously-flagged working-tree divergence (unstaged deletion of this frontmatter) is not present on the merged main branch. The file is clean.
The second-review suggestion about the missing qualifier in Phase 4 is resolved. Consolidation marker comment restored. Phase 3 step 7 remains dense but now self-contained. Must fix before mergeNothing — PR is already merged. Optional suggestions (not carried forward)
Both were noted in prior reviews and left as-is by choice. Neither blocks correctness. |
Summary
Two related changes to how this marketplace's tooling manages always-loaded context, unified by one principle: replace unconditional loading with trigger-activated loading.
Memory consolidation was append-only
extract-learningsis meant to manage memory, but nothing applied downward pressure.signal-discovereronly adds;memory-auditorremoved entries only on factual contradiction — explicitly exempting decisions, preferences, and principles, which are the large majority of entries; and the single size gate fired at 170 lines while real indexes sit well below it. The index grew without bound.memory-auditor: adds value-based retirement —SUPERSEDED/REDUNDANT/LOW-VALUEcategories that apply to principles, not just factually-checkable entries. Factual contradiction is no longer the only removal trigger.signal-discoverer: adds a raise-the-bar rule — zero new candidates is a valid, valuable result, not a failure.extract-learnings: replaces the dead size gate with per-run downward pressure, plus adaptive clustering — aMEMORY.mdsection past 25 entries splits intomemory/clusters/<section>.md, capping the always-loaded index while detail stays on demand.update-claudemd defeated its own progressive disclosure
The skill writes topic files to
.claude/rules/, but.claude/rules/*.mdauto-loads at SessionStart with CLAUDE.md priority unless scoped withpaths:frontmatter (per the docs). So every "load on demand" topic file actually loaded every session — the opposite of the skill's stated purpose.update-claudemd: mandatespaths:frontmatter on every topic file it writes, scoped to the globs the subject covers, and threads the backfill of existing files through the research → classify → approve pipeline so it surfaces at the approval gate instead of being a silent rewrite..claude/rules/claude-memory-architecture.md: applies the fix to this repo's own leaking file (it was loading ~1.5k every session); now scoped toplugins/claude-memory/**, so it loads only when that subsystem is touched.Commits
feat(memory)— self-pruning consolidation with adaptive clusteringfix(coding)— scope.claude/rulestopic files withpathsfrontmatterNotes
Plugin version bumps and README badge syncs in the diff are from the
auto-versionpre-commit hook, one per affected plugin.