feat(tools): add check-metadata.py - validates frontmatter fields
This commit is contained in:
parent
d79f0a4b0f
commit
74293b5949
1 changed files with 102 additions and 0 deletions
102
tools/coherence/check-metadata.py
Normal file
102
tools/coherence/check-metadata.py
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
check-metadata.py - Validates required frontmatter fields
|
||||
|
||||
One thing: Check if frontmatter has required fields.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import yaml
|
||||
from pathlib import Path
|
||||
|
||||
# Required fields for fieldnotes
|
||||
REQUIRED_FIELDS = [
|
||||
"title",
|
||||
"date",
|
||||
]
|
||||
|
||||
# Optional but recommended fields
|
||||
RECOMMENDED_FIELDS = [
|
||||
"author",
|
||||
"type",
|
||||
"status",
|
||||
]
|
||||
|
||||
def parse_frontmatter(filepath):
|
||||
"""Parse frontmatter from markdown file."""
|
||||
try:
|
||||
with open(filepath, "r", encoding="utf-8") as f:
|
||||
content = f.read()
|
||||
if content.startswith("---"):
|
||||
parts = content.split("---", 3)
|
||||
if len(parts) >= 3:
|
||||
return yaml.safe_load(parts[1])
|
||||
except Exception as e:
|
||||
print(f"Error parsing {filepath}: {e}")
|
||||
return {}
|
||||
|
||||
def check_metadata(filepath):
|
||||
"""Check if file has required frontmatter fields."""
|
||||
fm = parse_frontmatter(filepath)
|
||||
|
||||
if not fm:
|
||||
return {"error": "No frontmatter found"}
|
||||
|
||||
issues = []
|
||||
|
||||
# Check required
|
||||
for field in REQUIRED_FIELDS:
|
||||
if field not in fm or not fm[field]:
|
||||
issues.append(f"Missing required: {field}")
|
||||
|
||||
# Check recommended
|
||||
for field in RECOMMENDED_FIELDS:
|
||||
if field not in fm or not fm[field]:
|
||||
issues.append(f"Missing recommended: {field}")
|
||||
|
||||
return {
|
||||
"required_ok": all(f in fm and fm[f] for f in REQUIRED_FIELDS),
|
||||
"recommended_ok": all(f in fm and fm[f] for f in RECOMMENDED_FIELDS),
|
||||
"issues": issues,
|
||||
}
|
||||
|
||||
def main():
|
||||
"""Check metadata in markdown files."""
|
||||
path_arg = sys.argv[1] if len(sys.argv) > 1 else "."
|
||||
|
||||
issues = []
|
||||
checked = 0
|
||||
path = Path(path_arg)
|
||||
|
||||
if path.is_file() and path.suffix == ".md":
|
||||
checked = 1
|
||||
result = check_metadata(path)
|
||||
if result.get("issues"):
|
||||
issues.append((str(path), result["issues"]))
|
||||
elif path.is_dir():
|
||||
for filepath in path.rglob("*.md"):
|
||||
checked += 1
|
||||
result = check_metadata(filepath)
|
||||
if result.get("issues"):
|
||||
issues.append((str(filepath), result["issues"]))
|
||||
else:
|
||||
print(f"Error: {path_arg} is not a file or directory")
|
||||
sys.exit(2)
|
||||
|
||||
# Output
|
||||
print(f"Checked: {checked}")
|
||||
print(f"Files with issues: {len(issues)}")
|
||||
|
||||
if issues:
|
||||
print("\nIssues found:")
|
||||
for filepath, file_issues in issues:
|
||||
print(f" {filepath}")
|
||||
for issue in file_issues:
|
||||
print(f" - {issue}")
|
||||
sys.exit(1)
|
||||
else:
|
||||
print("All files have required metadata. OK")
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue