Run health checks on project memory files — broken links, orphan memories, stale entries, contradictions, oversized index lines
Run 6 health checks against a project's memory directory to catch broken references, forgotten files, stale code pointers, contradictory entries, oversized index lines, and frontmatter schema violations. Use this skill to keep memory clean and trustworthy.
The 6 checks, in order:
| # | Check | Severity | Auto-fixable |
|---|---|---|---|
| 1 | Broken Links | error | yes |
| 2 | Orphan Memories | warning | yes |
| 3 | Stale Entries | warning | no (manual review) |
| 4 | Contradictions | error | no (manual review) |
| 5 | Index Line Length | warning | yes (via scripts/slim_memory_index.py) |
| 6 | Frontmatter Schema | warning | no (manual review) |
/lint-memory — runs all 6 checkshooks/tier2/memory-triage-on-stop.sh scans for unindexed memory files and writes REVIEW_QUEUE.md (advisory, never commits). Complements lint-memory by catching orphans between manual runs.MEMORY.md)Severity: error Auto-fixable: yes
MEMORY.mdknowledge/ recursively (knowledge/**/*.md)[text](path) where path is a relative file reference (skip URLs starting with http:// or https://)[[path]] or [[path|display text]]For each link target, resolve the path relative to the memory directory and verify the target file exists on disk.
Remove the broken link from the source file:
[text](broken-path) — replace with just text (keep the display text, drop the link)[[broken-path]] — replace with broken-path (keep the text, drop the brackets)[[broken-path|display]] — replace with displayReport every removal before applying it.
Severity: warning Auto-fixable: yes
Find all *.md files at the top level of the memory directory (one level deep, not recursive). Glob ALL top-level *.md regardless of naming convention — some projects name memory files by topic slug (e.g. compose_dont_replace.md), others use feedback_* / reference_* prefixes (e.g. feedback_jwt_rotation.md). Both exist in the wild; the filter must match either.
Skip these files entirely — they are not expected to be referenced:
*.jsonl*.jsonfailure-catalog.mdprompt-variants.jsonMEMORY.mdknowledge/, episodic/, abandoned/, etc.) — compiled articles and runtime state are not orphan candidatesA file is orphaned if it is NOT referenced by any of:
MEMORY.md (as a link or plain text filename mention)sources: frontmatter field (knowledge/**/*.md)For each orphan file:
.md extension, replace underscores/hyphens with spaces. Use the full filename stem — do not strip any prefix (e.g. feedback_api_retry.md → feedback api retry, not api retry). Prefixes carry meaning; removing them silently merges distinct entries.MEMORY.md:
- **<semantic key>**: [<filename>](<filename>)
Report every addition before applying it.
Severity: warning Auto-fixable: no (manual review required)
All top-level *.md files in the memory directory (same glob as Check 2, same exclusions), plus MEMORY.md.
Backtick-wrapped code references that point to specific codebase artifacts. Use these heuristics to distinguish code references from prose:
/ or ends in a known source extension (.py, .js, .ts, .yaml, .json, .css, .html, .sh, .md). E.g. `src/utils/auth.py`, `config/settings.yaml`def or function . E.g. `def validate_token`, `function handleSubmit`class . E.g. `class UserService`, `class PaymentProcessor`Ignore backtick terms that don't match these patterns (e.g. `True`, `pip install`, `git rebase`).
def func_name or function func_name or func_name( at definition sites)class ClassName)For each stale reference, report:
This check cannot auto-fix because removing or updating code references requires human judgment about whether the memory entry itself is still relevant.
Severity: error Auto-fixable: no (manual review required)
Group entries by domain using the domain mapping defined in skills/claude-flow/references/memory-injection.md. Each memory file's semantic key or filename determines its domain.
Filter groups — only check domains with 3 or more entries. Domains with fewer entries rarely contradict.
Detect contradictions — for each qualifying domain group, use LLM judgment to identify entries that make conflicting claims. Examples:
For each contradiction found, report:
This check cannot auto-fix because resolving contradictions requires human judgment about which entry is correct or whether both need updating.
Severity: warning
Auto-fixable: yes (via skills/claude-flow/scripts/slim_memory_index.py)
MEMORY.md is loaded into context at every session start. When index entries balloon into multi-sentence summaries, the file blows past its load limit and gets silently truncated — entries near the bottom never reach the model. Index = pointer; detail belongs in the topic file.
MEMORY.md only. Skip topic files, knowledge articles, and runtime state.
Default max index-line length: 250 characters. Override per project by setting lint-memory.max_index_line in .claude/settings.json. Keep it under 300.
Any line in MEMORY.md longer than the threshold that:
- or * (list item — i.e. an actual index entry)The check is auto-fixable via scripts/slim_memory_index.py <memory_dir> --apply. The script:
- [Title](slug.md) — <one-line hook>--append-detail to overrideAfter auto-fix, re-run /lint-memory to confirm all entries are within the threshold.
For each over-long line, report:
MEMORY.mdpython3 scripts/slim_memory_index.py <memory_dir> --apply to migrate detail into topic file"Severity: warning Auto-fixable: no (manual review required)
Memory entries may optionally declare evidence (the episodes/lessons the entry builds on) and confidence (a float in [0.0, 1.0] signalling the strength of the claim). When authors add these fields, a typo or malformed value silently breaks downstream tooling that reads them. This check validates the shape of optional fields when present — it does not require them.
See docs/conventions/memory-entry-schema.md for the full schema.
All top-level *.md files in the memory directory (same glob as Check 2, same exclusions). Skip files without YAML frontmatter (no leading --- fence).
Parse the YAML frontmatter. Validate only when a field is present:
evidence — must be a YAML list. Every element must be a non-empty string. Reject evidence: "", evidence: null, evidence: [""], evidence: "ep-001" (scalar instead of list).confidence — must be a number (int or float) in the inclusive range [0.0, 1.0]. Reject confidence: "0.9" (string), confidence: 1.5, confidence: -0.1.Absence of either field is NOT a warning.
For each invalid value, report:
evidence or confidence)This check cannot auto-fix because fixing requires knowing the author's intent (e.g. was confidence: 9 meant to be 0.9?).
Produce a markdown report with this structure:
# Memory Lint Report
## Errors
<!-- Check 1 (Broken Links) and Check 4 (Contradictions) findings -->
- [broken-link] `MEMORY.md`: link to `missing-file.md` — target not found (auto-fixed: removed link)
- [contradiction] Domain "auth": `feedback_jwt_rotation.md` says "rotate every 24h" vs `feedback_token_expiry.md` says "rotate every 7d"
## Warnings
<!-- Check 2 (Orphan Memories), Check 3 (Stale Entries), Check 5 (Index Line Length) findings -->
- [orphan] `feedback_api_retry_logic.md` — not referenced anywhere (auto-fixed: added to MEMORY.md)
- [stale] `reference_db_schema.md`: references `src/models/legacy_user.py` — file not found
- [oversized-index] `MEMORY.md:64`: 1502 chars (1252 over 250-char limit) — run `scripts/slim_memory_index.py --apply` to migrate
- [frontmatter] `feedback_token_rotation.md`: `confidence: "0.9"` — expected number in [0.0, 1.0], got string
## Summary
- Errors: N (M auto-fixed)
- Warnings: N (M auto-fixed)
- Clean: yes/no
/lint-memory)Run all 6 checks in order. Produce the complete report.
Run checks 1, 2, 5, and 6 (Broken Links + Orphan Memories + Index Line Length + Frontmatter Schema). Skip checks 3-4 (codebase grep + LLM judgment) to keep compilation fast. Checks 5 and 6 are fast mechanical scans — cheap enough to run every time. Produce an abbreviated report with Errors and Warnings from those four checks.
/lint-memory to confirm./session-learnings to capture the cleanup as a session event.evidence + confidence fields validated by Check 6.