vault validate
Prüft einen Vault gegen die Apparat-Spezifikation und gibt einen Report aus. Pflichtfelder werden hart geprüft, Konventionsbrüche erzeugen Warnungen. Das Kommando ändert nichts — es liest nur und berichtet.
Einfachster Fall
apparat vault validate
Wenn alles sauber ist:
Vault "recherche" is clean — 42 file(s) scanned, no findings.
Wenn es etwas zu berichten gibt:
Vault "recherche" — validation findings: content/2026-04-19--maria-beispiel--V1StGXRa.md ERROR id.filename_mismatch Field `id` "Bx7tYu3v" does not match the NanoId suffix "V1StGXRa" in the filename. WARN type.case Type value "Person" should be lowercase. content/2026-04-20--wcag--BbBbBbBb.md WARN key.case Frontmatter key "birthDate" is not snake_case. assets/stray-file.pdf ERROR asset.schema Asset filename "stray-file.pdf" does not match the schema YYYY-MM-DD--slug--nanoid.ext. Summary: 2 errors, 2 warnings across 44 file(s) scanned, 41 clean (errors).
Jede Zeile: Severity (ERROR oder WARN), Rule-ID (maschinenlesbar, z.B. id.missing, type.case), Beschreibung.
Exit-Codes
| Code | Bedeutung |
|---|---|
| 0 | Sauber — keine Fehler, keine Warnungen |
| 1 | Mindestens ein harter Fehler |
| 2 | Nur Warnungen, keine harten Fehler |
So kann ein CI-Skript zwischen „blockend" und „kosmetisch" unterscheiden:
apparat vault validate case $? in 0) echo "clean" ;; 1) echo "errors — do not ship"; exit 1 ;; 2) echo "warnings only — proceeding, but clean up soon" ;; esac
Maschinenlesbare Ausgabe: --json
apparat vault validate --json
Gibt ein einzelnes JSON-Objekt auf stdout aus, das den vollständigen Report enthält:
{ "vault": { "name": "recherche", "url": "https://apparat.example.com/vaults/recherche", "path": "/home/max/vaults/recherche" }, "summary": { "errors": 2, "warnings": 2, "files_scanned": 44, "files_clean": 41 }, "findings": [ { "severity": "error", "file": "content/2026-04-19--maria-beispiel--V1StGXRa.md", "rule": "id.filename_mismatch", "message": "Field `id` \"Bx7tYu3v\" does not match the NanoId suffix \"V1StGXRa\" in the filename." }, ... ] }
Der Exit-Code ist derselbe wie im Textmodus. Praktisch für:
- Pre-Commit-Hook mit
jq, der bestimmte Regeln hart nimmt und andere tolerant behandelt. - Integrationen in Editoren oder Dashboards, die die Fehler strukturiert darstellen.
Vault-Auswahl
Wie bei allen Read-Kommandos: ohne --vault greift die übliche Auto-Lokalisierung (CWD-Erkennung, einziger registrierter Vault, interaktive Auswahl). Explizit:
apparat vault validate --vault=arbeit apparat vault validate --vault=/home/max/vaults/recherche apparat vault validate --vault=https://apparat.example.com/vaults/recherche
Was geprüft wird
Harte Fehler (Exit-Code 1)
Das sind Zustände, die verhindern, dass die Datei als reguläre Entität behandelt werden kann. Dieselben Dateien erscheinen als irregulär in vault irregular und lassen sich mit entity import in den regulären Bestand überführen.
| Rule-ID | Bedeutung |
|---|---|
file.schema |
Content-Dateiname folgt nicht YYYY-MM-DD--slug--nanoid.md |
frontmatter.missing |
Datei hat kein YAML-Frontmatter-Block |
frontmatter.parse |
Frontmatter ist syntaktisch kaputt |
id.missing |
Pflichtfeld id fehlt oder ist leer |
id.format |
id entspricht nicht dem NanoID-Format [A-Za-z0-9]{8} |
id.filename_mismatch |
id im Frontmatter und NanoID im Dateinamen stimmen nicht überein |
type.missing |
Pflichtfeld type fehlt oder ist leer |
created.missing |
Pflichtfeld created fehlt |
created.format |
created ist kein ISO-Datum (YYYY-MM-DD) |
language.missing |
Pflichtfeld language fehlt oder ist leer |
language.format |
language entspricht nicht dem BCP-47-Subset ^[a-z]{2,3}(-[A-Z]{2})?$ |
asset.schema |
Asset-Dateiname folgt nicht YYYY-MM-DD--slug--nanoid.ext |
Warnungen (Exit-Code 2)
Konventionsbrüche, die nichts kaputt machen, aber eine aufräumwürdige Drift signalisieren.
| Rule-ID | Bedeutung |
|---|---|
key.case |
Frontmatter-Schlüssel ist nicht snake_case (z.B. birthDate statt birth_date) |
key.charset |
Schlüssel enthält Bindestrich, Leerzeichen oder Umlaut |
key.language |
Schlüssel sieht deutsch aus (titel, autor, datum, Umlaute) |
type.case |
type-Wert enthält Großbuchstaben (Person statt person) |
string.length |
Einzelner String-Wert ist länger als 500 Zeichen (klingt nach Fließtext im falschen Feld) |
link.orphan |
Ein Fließtext-Link zeigt auf eine NanoID, die weder als Entität noch als Asset im Vault existiert. |
relation.broken |
Ein Frontmatter-Beziehungseintrag (works_at: Xxx, knows: [...]) zeigt auf eine NanoID, die es im Vault nicht gibt. |
asset.orphan |
Ein Asset unter assets/ wird weder im Fließtext eingebettet noch in einer representations:-Liste referenziert — es gehört zu keiner Entität. |
journal.stale |
Eine Datei unter .apparat/journal/ ist älter als 24 Stunden. Hinweis auf eine steckengebliebene Multi-Datei-Operation, die keine automatische Recovery einsammeln konnte (z. B. weil das Kommando, das sie startete, heute einen anderen Operations-Namen kennt). |
journal.malformed |
Das Journal-Verzeichnis oder eine einzelne Journal-Datei lässt sich nicht lesen bzw. dekodieren — etwa weil die Datei kein gültiges JSON enthält oder ihr Startzeitpunkt kein lesbares Datum ist. |
asset.sidecar_missing |
Ein Asset unter assets/ hat keine <dateiname>.sha256-Datei. Apparat nutzt diese Sidecar-Datei, um Duplikate beim Import zu erkennen. Heilung: apparat graph rebuild schreibt fehlende Sidecars nach. |
asset.sidecar_orphan |
Eine .sha256-Datei liegt im assets/-Verzeichnis, ohne dass die zugehörige Asset-Datei existiert. Heilung: die verwaiste Sidecar-Datei manuell löschen. |
asset.sidecar_drift |
Der in der Sidecar-Datei gespeicherte Hash stimmt nicht mehr mit dem aktuellen Asset-Inhalt überein. Hinweis auf Bit-Rot oder einen externen Eingriff in die Datei. Heilung: Asset-Inhalt prüfen, danach Sidecar löschen und apparat graph rebuild lassen. |
asset.sidecar_malformed |
Eine .sha256-Datei existiert, enthält aber keinen gültigen SHA-256-Wert. Heilung: Sidecar löschen, apparat graph rebuild schreibt sie korrekt nach. |
Was außerhalb des Validators liegt
Drei Klassen von Befunden werden vom Validator bewusst nicht angefasst:
- Plural-Formen bei
type(personsstattperson) — eine zuverlässige Singular-Erkennung braucht Wortlisten-Wissen und ist im Validator nicht vorgesehen. - Konsistenz von Beziehungsnamen über den Vault hinweg (
works_atvs.employed_at) — diese Drift fängt die Vokabular-Konsolidierung ab. - Cross-Vault-Links. Referenzen auf andere Vaults werden nicht als verwaist markiert, solange der Ziel-Vault registriert ist —
link.orphanmeldet nur Ziele, die innerhalb dieses Vaults fehlen.
Abgrenzung zu anderen Kommandos
vault validate arbeitet rein lesend — der Vault wird nicht verändert, weder Inhalte noch Zeitstempel. Für gezielte Sanierung gibt es vault irregular und entity import. Der Trash hat seine eigene Listing-Ansicht (vault trash list) und wird vom Validator nicht mitgeprüft.
Verwandte Themen
- Grundbegriffe — Entität: welche Pflichtfelder eine Entität haben muss.
- Grundbegriffe — Tags und Typen: Konventionen für Typ- und Tag-Werte.