The mnemonic-validate tool validates memory files against the MIF Level 3 schema.
# Validate all memories (default paths)
./tools/mnemonic-validate
# Validate specific directory
./tools/mnemonic-validate ${MNEMONIC_ROOT}
# JSON output for CI/CD
./tools/mnemonic-validate --format json
# Using make targets
make validate-memories
make validate-memories-ciThe validation tool is included with the mnemonic plugin. No additional installation required.
Dependencies: Python 3.9+ with PyYAML (included in most Python installations).
mnemonic-validate [options] [path...]
Options:
--format json|markdown Output format (default: markdown)
--check TYPE Only validate: code_refs|citations|links|schema
--skip-http Skip HTTP checks (offline mode)
--fast-fail Stop on first error
--changed Only validate git-modified files
--capture Capture validation run as episodic memory
-v, --verbose Verbose output
-h, --help Show this helpIf no path is specified, the tool searches:
${MNEMONIC_ROOT}/(global memories)${MNEMONIC_ROOT}/(project memories)
Validates MIF Level 3 required fields and formats:
| Field | Validation |
|---|---|
id |
Must be valid UUID v4 format (lowercase) |
type |
Must be semantic, episodic, or procedural |
namespace |
Should follow pattern {namespace}/{scope} |
created |
Must be valid ISO 8601 timestamp |
title |
Must be non-empty string |
Additional checks:
provenance.confidenceshould be between 0.0 and 1.0provenance.sourceTypeshould be a MIF 1.4.2 value (user_explicit,user_implicit,agent_inferred,external_import,system_generated)compressedAt, if present, must be an ISO 8601 timestamptagsshould be lowercase with hyphenstemporal.validFromshould be before or equal totemporal.recordedAt
Memories written by earlier mnemonic releases are still valid. These forms produce warnings, never errors, each naming the MIF 1.4.2 replacement:
- snake_case frontmatter keys (
valid_from,source_type,compressed_at,code_refs, ...) - legacy
sourceTypevalues (inferred,conversation) - relationship types not in kebab-case (
relates_to,RelatesTo) - relationship
labeloutsidemetadata - frontmatter relationships with no body
## Relationshipslink [[uuid]]wiki-link relationship lines- citations using
typeinstead ofcitationType, or missingcitationRole
tools/mnemonic-migrate-mif rewrites these in place on request (dry run by
default).
For memories with codeRefs (legacy: code_refs):
typeshould be one of:function,class,method,variable,type,modulefilepath should exist (relative to git root)linenumber should be within file length
For memories with citations:
citationType(required; legacy spellingtypeaccepted) should be a MIF 1.4.2 value (article,book,paper,website,documentation,repository,video,podcast,specification,dataset,tool,other) or a legacy mnemonic value (blog,github,stackoverflow)citationRoleshould be present (warning if missing)title(required) must be non-emptyurl(required) must be valid URL formatrelevance(optional) should be between 0.0 and 1.0
Validates relationship links:
- every frontmatter
relationshipsentry should be mirrored as a Markdown link under## Relationships(MIF 1.4.2 section 5.3); a legacy[[uuid]]line counts as a mirror but is itself warned about - legacy
[[uuid]]patterns in the body must have a valid UUID format - (Future: referenced memory should exist)
# Mnemonic Validation Report
**Date:** 2026-01-24T10:30:00Z
## Summary
- **Memories validated:** 145
- **Valid:** 142
- **Errors:** 3
- **Warnings:** 5
## Errors
### abc123-example.memory.md
- **type**: Missing required field: type
- **id** (line 2): Invalid UUID format: not-a-uuid
## Warnings
### def456-other.memory.md
- **tags**: Tag should be lowercase with hyphens: CamelCase{
"timestamp": "2026-01-24T10:30:00Z",
"summary": {
"total": 145,
"valid": 142,
"errors": 3,
"warnings": 5
},
"results": [
{
"file": "abc123-example.memory.md",
"valid": false,
"errors": [
{
"file": "abc123-example.memory.md",
"field": "type",
"message": "Missing required field: type",
"line": null,
"severity": "error"
}
],
"warnings": []
}
]
}0: All validations passed1: One or more errors found
name: Validate Memories
on:
push:
paths:
- '**/*.memory.md'
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Validate memories
run: ./tools/mnemonic-validate --format json
- name: Validate changed only
if: github.event_name == 'pull_request'
run: ./tools/mnemonic-validate --changed --format jsonAdd to .pre-commit-config.yaml:
repos:
- repo: local
hooks:
- id: validate-memories
name: Validate memory files
entry: ./tools/mnemonic-validate --changed --fast-fail
language: python
types: [markdown]
files: \.memory\.md$Use --capture to save validation results as an episodic memory:
./tools/mnemonic-validate --captureThis creates a memory in:
blockers/projectif errors were foundepisodic/projectif validation passed
The captured memory includes:
- Summary statistics
- List of errors and warnings
- Timestamp and provenance
This enables tracking validation history over time via mnemonic search.
# Validate with markdown output
make validate-memories
# Validate with JSON output (for CI)
make validate-memories-ci
# Validate only changed files
make validate-memories-changedEnsure you're running from the mnemonic plugin directory or have set up paths correctly.
Check that:
- Memory files end with
.memory.md - The search paths contain memory files
- For
--changed, files are tracked by git
If frontmatter fails to parse:
- Check for invalid YAML syntax
- Ensure the file starts with
--- - Verify closing
---exists
The validation rules are parsed from skills/format/SKILL.md, ensuring a single source of truth between documentation and validation (see ADR-004).