v4.9.0 — Agent Memory vault cleanup audit (V4 #33)
MINOR. A read-only lint over the MemoryVault + a one-time audit pass. As the vault grew across the V4 arc (~150 agent entries), entries drift off-spec — broken [[wikilinks]], malformed frontmatter, dangling supersede references, unsanctioned keys. vault_lint.py surfaces all of it with a suggested fix per finding, and never touches the vault — it reports; the operator applies (A3, locked DC-1). Auto-repair stays deferred to V5-5. Single-repo release; crickets untouched.
Added
harness/skills/memory/scripts/vault_lint.py— read-only vault lint. A registry of 9 checks over agent-shaped entries (those carrying thekind+status+createdfrontmatter trio; the operator's intermixed free-form notes are skipped):required-field,kebab-case,field-order,slug-filename,date-format,placeholder-value(an unfilleda | b | coption-list left in frontmatter),schema-drift(unknown keys),wikilink-resolution,supersede-integrity. Wikilinks resolve against the whole Obsidian vault root (the dir with.obsidian/), not justAgentMemory/, so cross-vault references (e.g.[[Ideas]]) don't false-positive. CLI:--format json|text,--scope.--auditreport mode. Runs all checks and writes a grouped operator-review report (to--outor<vault>/_meta/vault-lint-<date>.md) — findings collapse by severity → check → identical message, so a key likedomainacross 8 entries is one line + an entry list, not 8 repeats. The report file is the only write the lint ever makes; it never mutates an entry.
Changed
save.pyis the lint's schema source of truth (DC-2). AddedFRONTMATTER_FIELD_ORDER/REQUIRED_FRONTMATTER_FIELDSconstants the lint reuses (a test pins_build_frontmatterto the order), and widened thegroupregex from a single optional sub-segment to any depth (^[a-z0-9-]+(/[a-z0-9-]+)*$) — the live vault had outgrown it with deep groups likeprojects/<slug>/decisions. Backward-compatible.
Internal
- Live-dogfood calibration. Running the lint against the real vault drove three fixes that took findings from 131 → 39 (no false-positive floods): Obsidian-root wikilink resolution, normalizing markdown-escaped
\]]brackets, and exempting_index/_summaryanchor slugs from the kebab check. An adversarial review then caught a contained false-negative (the supersede "still active" warn not resolving a stem reference) — fixed + regression-tested. - +26 tests (
scripts/test_vault_lint.py; the lint lives in the skill dir but its tests live inscripts/so CI'sunittest discoverruns them). 380 → 406.
Cross-references
- agentm v4.8.0 — prior release.
- ROADMAP-V4 item #33. Deferred follow-ups: auto-fix / self-healing (→ V5-5); idea-incubator
_summary.md+Ideas.mdbespoke-shape lint; scheduled/unattended runs (→ V6); and a personal-notes link-discovery audit (→ V4 #43).