mindnet/scripts/parse_validate_notes.py
Lars e9532e8878
All checks were successful
Deploy mindnet to llm-node / deploy (push) Successful in 4s
script_Überprüfung und Kommentarheader
2025-12-28 10:40:28 +01:00

105 lines
3.6 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
FILE: scripts/parse_validate_notes.py
VERSION: 2.1.0 (2025-12-15)
STATUS: Active
COMPATIBILITY: v2.9.1 (Post-WP14/WP-15b)
Zweck:
-------
Validiert alle Markdown-Dateien in einem Vault auf strukturelle Korrektheit.
Prüft Frontmatter-Validität und Note-Payload-Erzeugung ohne Datenbank-Upsert.
Funktionsweise:
---------------
1. Scannt rekursiv alle .md-Dateien im angegebenen Vault-Verzeichnis
2. Für jede Datei:
- Liest und parst Markdown mit Frontmatter
- Validiert erforderliche Frontmatter-Felder (id, title, type)
- Erzeugt Note-Payload (validiert durch JSON-Serialisierung)
3. Gibt Statistik aus: Anzahl valider vs. invalider Dateien
Ergebnis-Interpretation:
------------------------
- Exit-Code 0: Alle Dateien sind valide
- Exit-Code 1: Mindestens eine Datei ist invalide
- Ausgabe: "✅ Valid: X | ❌ Invalid: Y"
- Fehlerdetails werden auf stderr ausgegeben
Häufige Fehler:
--------------
- Fehlende oder ungültige Frontmatter-Felder (id, title, type)
- JSON-Serialisierungsfehler im Payload (z.B. ungültige Datentypen)
- Encoding-Probleme beim Lesen der Datei
Aufruf:
-------
python3 -m scripts.parse_validate_notes --vault ./vault
python3 -m scripts.parse_validate_notes --vault ./vault --include "**/*.md" --exclude /.obsidian/ /_imported/
Parameter:
----------
--vault PATH Pfad zum Vault-Verzeichnis (erforderlich)
--include PATTERN Glob-Pattern für Dateien (Default: "**/*.md")
--exclude PATH Pfade zum Ausschließen (Default: /.obsidian/, /_imported/)
Änderungen:
-----------
v2.1.0 (2025-12-15): Kompatibilität mit WP-14 Modularisierung
- Entfernt: app.core.note_payload (ersetzt durch ingestion_note_payload)
- Entfernt: app.core.validate_note (Validierung in make_note_payload integriert)
- Entfernt: jsonschema.ValidationError (nicht mehr benötigt)
v1.0.0: Erster Release
"""
from __future__ import annotations
import argparse
import os
import sys
import glob
from app.core.parser import read_markdown, validate_required_frontmatter, normalize_frontmatter
from app.core.ingestion.ingestion_note_payload import make_note_payload
def iter_md_files(root: str, include: str, exclude: list[str]) -> list[str]:
# include z.B. "**/*.md"
all_files = glob.glob(os.path.join(root, include), recursive=True)
def is_excluded(p: str) -> bool:
p_norm = p.replace("\\", "/")
return any(x in p_norm for x in exclude)
return [p for p in all_files if p.lower().endswith(".md") and not is_excluded(p)]
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--vault", required=True, help="Pfad zum Obsidian Vault")
ap.add_argument("--include", default="**/*.md")
ap.add_argument("--exclude", nargs="*", default=["/.obsidian/", "/_imported/"])
args = ap.parse_args()
root = os.path.abspath(args.vault)
files = iter_md_files(root, args.include, args.exclude)
if not files:
print("Keine Markdown-Dateien gefunden.", file=sys.stderr)
sys.exit(2)
ok, failed = 0, 0
for path in files:
try:
parsed = read_markdown(path)
fm = normalize_frontmatter(parsed.frontmatter)
validate_required_frontmatter(fm)
# Note-Payload wird in make_note_payload bereits validiert (JSON-Serialisierung)
payload = make_note_payload(parsed, vault_root=root, file_path=path)
ok += 1
except (ValueError, TypeError, KeyError, AttributeError) as e:
failed += 1
print(f"{os.path.relpath(path, root)} :: {e}", file=sys.stderr)
print(f"✅ Valid: {ok} | ❌ Invalid: {failed}")
if failed:
sys.exit(1)
if __name__ == "__main__":
main()