script_Überprüfung und Kommentarheader
All checks were successful
Deploy mindnet to llm-node / deploy (push) Successful in 4s

This commit is contained in:
Lars 2025-12-28 10:40:28 +01:00
parent 23b1cb2966
commit e9532e8878
30 changed files with 1835 additions and 542 deletions

View File

@ -1,18 +1,59 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
tests/assert_payload_schema.py (compat v1.1)
FILE: scripts/assert_payload_schema.py
VERSION: 2.1.0 (2025-12-15)
STATUS: Active
COMPATIBILITY: v2.9.1 (Post-WP14/WP-15b)
Prüft, ob die erwarteten Payload-Indizes (payload_schema) auf den drei Collections vorhanden sind.
Kompatibel mit älteren qdrant-client Versionen (ohne with_payload_schema im Wrapper).
Zweck:
-------
Prüft, ob die erwarteten Payload-Indizes auf allen Collections vorhanden sind.
Validiert Schema-Integrität für CI/CD und Wartung.
Collections & Pflichtfelder:
- mindnet_notes : note_id, type, title, updated, tags
- mindnet_chunks : note_id, chunk_id, index, type, tags
- mindnet_edges : note_id, kind, scope, source_id, target_id, chunk_id
Funktionsweise:
---------------
1. Ermittelt Collections für das Präfix (notes, chunks, edges)
2. Lädt Payload-Schema für jede Collection
3. Prüft, ob alle Pflichtfelder indiziert sind:
- notes: note_id, type, title, updated, tags
- chunks: note_id, chunk_id, index, type, tags
- edges: note_id, kind, scope, source_id, target_id, chunk_id
4. Gibt Validierungs-Ergebnis aus
Nutzung:
python3 -m tests.assert_payload_schema
Ergebnis-Interpretation:
------------------------
- Ausgabe: JSON mit Validierungs-Ergebnissen
* collections: Schema-Status pro Collection
* missing: Fehlende Indizes
* valid: true/false
- Exit-Code 0: Alle Indizes vorhanden
- Exit-Code 1: Fehlende Indizes gefunden
Verwendung:
-----------
- CI/CD-Validierung nach ensure_payload_indexes
- Diagnose von Index-Problemen
- Wartung und Audit
Hinweise:
---------
- Kompatibel mit verschiedenen qdrant-client Versionen
- Nutzt Fallback-Strategie für Schema-Abfrage
Aufruf:
-------
python3 -m scripts.assert_payload_schema --prefix mindnet
Parameter:
----------
--prefix TEXT Collection-Präfix (Default: ENV COLLECTION_PREFIX oder mindnet)
Änderungen:
-----------
v2.1.0 (2025-12-15): Dokumentation aktualisiert
v1.1.0: Kompatibilität mit verschiedenen qdrant-client Versionen
v1.0.0: Initial Release
"""
from __future__ import annotations

View File

@ -1,4 +1,64 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
FILE: scripts/audit_chunks.py
VERSION: 2.1.0 (2025-12-15)
STATUS: Active
COMPATIBILITY: v2.9.1 (Post-WP14/WP-15b)
Zweck:
-------
Audit-Tool zur Analyse der Chunk-Qualität im Vault.
Erkennt Probleme wie überdimensionierte Chunks, leere Chunks und defekte Nachbarschafts-Links.
Funktionsweise:
---------------
1. Scannt alle Markdown-Dateien im Vault
2. Für jede Datei:
- Erzeugt Chunks via assemble_chunks
- Prüft Token-Anzahl pro Chunk
- Validiert Nachbarschafts-Links (prev/next)
3. Aggregiert Statistiken und identifiziert Probleme
Ergebnis-Interpretation:
------------------------
- Ausgabe: JSON mit Zusammenfassung
* notes: Anzahl verarbeiteter Notizen
* chunks_total: Gesamtanzahl Chunks
* chunks_per_note_avg: Durchschnittliche Chunks pro Note
* tokens_avg: Durchschnittliche Token pro Chunk
* tokens_p95: 95. Perzentil der Token-Verteilung
* issues_counts: Anzahl gefundener Probleme
- Zusätzlich: Liste der ersten 20 Probleme pro Kategorie
* oversize: Chunks > 600 Tokens
* broken_neighbors: Defekte prev/next Links
* empty: Leere Chunks (0 Tokens)
Verwendung:
-----------
- Qualitätskontrolle nach Chunking-Änderungen
- Identifikation von Problemen vor dem Import
- Monitoring der Chunk-Verteilung
Hinweise:
---------
- Nutzt synchrones assemble_chunks (kann async sein)
- Heuristik für Oversize: > 600 Tokens
- Prüft nur strukturelle Integrität, keine semantische Qualität
Aufruf:
-------
python3 -m scripts.audit_chunks --vault ./vault
Parameter:
----------
--vault PATH Pfad zum Vault-Verzeichnis (erforderlich)
Änderungen:
-----------
v2.1.0 (2025-12-15): Dokumentation aktualisiert
v1.0.0: Initial Release
"""
from __future__ import annotations
import argparse, os, json, glob, statistics as stats
from app.core.parser import read_markdown, normalize_frontmatter, validate_required_frontmatter

View File

@ -1,34 +1,66 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Script: audit_edges_vs_expectations.py Prüfe Kanten in Qdrant gegen Vault-Erwartungen
Version: 1.0.0
Datum: 2025-09-09
FILE: scripts/audit_edges_vs_expectations.py
VERSION: 2.1.0 (2025-12-15)
STATUS: Active
COMPATIBILITY: v2.9.1 (Post-WP14/WP-15b)
Zweck
-----
- Liest Edges/Chunks/Notes aus Qdrant.
- Ermittelt erwartete Kanten-Anzahlen aus dem Vault:
* belongs_to : sollte == #Chunks
* next / prev : je Note (#Chunks_in_Note - 1)
* references : Summe aller Chunk-Wikilinks
* backlink : Summe einzigartiger Wikilinks pro Note (Note-Level)
- Vergleicht IST vs. SOLL und meldet Abweichungen.
ENV/Qdrant
----------
QDRANT_URL, QDRANT_API_KEY (optional), COLLECTION_PREFIX (Default: mindnet)
Aufrufe
Zweck:
-------
# Gesamtaudit
python3 -m scripts.audit_edges_vs_expectations --vault ./test_vault
Prüft Edge-Anzahlen in Qdrant gegen erwartete Werte aus dem Vault.
Validiert strukturelle Integrität des Graphen.
# Mit anderem Prefix
python3 -m scripts.audit_edges_vs_expectations --vault ./test_vault --prefix mindnet_dev
Funktionsweise:
---------------
1. Liest Edges/Chunks/Notes aus Qdrant
2. Ermittelt erwartete Edge-Anzahlen aus Vault:
- belongs_to: sollte == #Chunks pro Note
- next/prev: je Note (#Chunks - 1)
- references: Summe aller Chunk-Wikilinks
- backlink: Summe einzigartiger Wikilinks (Note-Level)
3. Vergleicht IST vs. SOLL
4. Meldet Abweichungen
# Details anzeigen
python3 -m scripts.audit_edges_vs_expectations --vault ./test_vault --details
Ergebnis-Interpretation:
------------------------
- Ausgabe: JSON mit Vergleichs-Ergebnissen
* expected: Erwartete Edge-Anzahlen
* actual: Tatsächliche Edge-Anzahlen
* discrepancies: Abweichungen
* per_note: Details pro Note (mit --details)
- Exit-Code 0: Erfolgreich
Verwendung:
-----------
- Validierung nach Importen
- Debugging von Edge-Problemen
- Qualitätskontrolle
Hinweise:
---------
- Prüft strukturelle, nicht semantische Korrektheit
- Kann bei großen Vaults langsam sein
Aufruf:
-------
python3 -m scripts.audit_edges_vs_expectations --vault ./vault
python3 -m scripts.audit_edges_vs_expectations --vault ./vault --prefix mindnet_dev --details
Parameter:
----------
--vault PATH Pfad zum Vault-Verzeichnis (erforderlich)
--prefix TEXT Collection-Präfix (Default: mindnet)
--details Zeigt Details pro Note
Umgebungsvariablen:
-------------------
QDRANT_URL, QDRANT_API_KEY (optional), COLLECTION_PREFIX
Änderungen:
-----------
v2.1.0 (2025-12-15): Dokumentation aktualisiert
v1.0.0 (2025-09-09): Initial Release
"""
from __future__ import annotations

View File

@ -1,38 +1,61 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Name: scripts/audit_vault_vs_qdrant.py
Version: v1.0.0 (2025-09-05)
Kurzbeschreibung:
Prüft die Konsistenz zwischen Obsidian-Vault und Qdrant:
- Zählt Markdown-Dateien mit gültiger Frontmatter (title, id, type, status, created).
- Zählt Wikilink-Vorkommen im Vault (regex wie in derive_edges.py).
- Liest Zählungen aus Qdrant (Notes/Chunks/Edges je kind).
- Vergleicht erwartete Wikilink-Anzahl (Vault) vs. tatsächlich importierte Edges (Qdrant).
- Listet Auffälligkeiten pro Note (z. B. Wikilinks im Vault, aber keine references in Qdrant).
FILE: scripts/audit_vault_vs_qdrant.py
VERSION: 2.1.0 (2025-12-15)
STATUS: Active
COMPATIBILITY: v2.9.1 (Post-WP14/WP-15b)
Aufruf (aus Projekt-Root, im venv):
python3 -m scripts.audit_vault_vs_qdrant --vault ./vault --prefix mindnet
Zweck:
-------
Prüft Konsistenz zwischen Vault und Qdrant.
Vergleicht erwartete vs. tatsächliche Edge-Anzahlen.
Parameter:
--vault Pfad zum Vault (z. B. ./vault)
--prefix Collection-Prefix in Qdrant (Default: mindnet)
--limit Max. Punkte pro Scroll-Seite aus Qdrant (Default: 1000)
Funktionsweise:
---------------
1. Scannt Vault:
- Zählt Markdown-Dateien mit gültiger Frontmatter
- Zählt Wikilink-Vorkommen (regex wie in derive_edges.py)
2. Liest Qdrant:
- Zählt Notes/Chunks/Edges
- Gruppiert Edges nach kind
3. Vergleicht:
- Erwartete Wikilink-Anzahl (Vault) vs. references (Qdrant)
- Listet Auffälligkeiten pro Note
Voraussetzungen:
- Aktives Python venv mit installiertem qdrant-client.
- Zugriff auf Qdrant per ENV (QDRANT_URL, QDRANT_API_KEY optional).
Ergebnis-Interpretation:
------------------------
- Ausgabe: JSON mit Vergleichs-Ergebnissen
* vault_stats: Zählungen aus Vault
* qdrant_stats: Zählungen aus Qdrant
* discrepancies: Abweichungen und Auffälligkeiten
- Exit-Code 0: Erfolgreich
Verwendung:
-----------
- Konsistenz-Check nach Importen
- Validierung der Edge-Erzeugung
- Debugging von fehlenden Links
Hinweise:
- Der Wikilink-Regex entspricht dem in app/core/derive_edges.py verwendeten Muster. (Quelle: derive_edges.py) # :contentReference[oaicite:3]{index=3}
- Pflicht-Frontmatter wird wie in app/core/parser.py geprüft. (Quelle: parser.py) # :contentReference[oaicite:4]{index=4}
- Collection-Namen & 1D-Edge-Vektoren folgen app/core/qdrant.py / qdrant_points.py. (Quellen: qdrant.py, qdrant_points.py) #
---------
- Wikilink-Regex entspricht derive_edges.py
- Prüft strukturelle, nicht semantische Korrektheit
Changelog:
v1.0.0: Erste Version.
Aufruf:
-------
python3 -m scripts.audit_vault_vs_qdrant --vault ./vault --prefix mindnet
Autor:
mindnet Datenimporte & Sync
Parameter:
----------
--vault PATH Pfad zum Vault-Verzeichnis (erforderlich)
--prefix TEXT Collection-Präfix (Default: mindnet)
--limit INT Max. Punkte pro Scroll-Seite (Default: 1000)
Änderungen:
-----------
v2.1.0 (2025-12-15): Dokumentation aktualisiert
v1.0.0 (2025-09-05): Initial Release
"""
from __future__ import annotations
import argparse, os, glob, re, json

View File

@ -1,4 +1,61 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
FILE: scripts/backfill_edges.py
VERSION: 2.1.0 (2025-12-15)
STATUS: Active
COMPATIBILITY: v2.9.1 (Post-WP14/WP-15b)
Zweck:
-------
Füllt fehlende Edges nach, indem es Wikilinks aus dem Vault extrahiert
und in Qdrant schreibt. Nützlich nach Migrationen oder wenn Edges verloren gingen.
Funktionsweise:
---------------
1. Scannt alle Markdown-Dateien im Vault
2. Für jede Datei:
- Erstellt Note-Stub (minimaler Payload)
- Erstellt einen Chunk mit dem gesamten Body
- Extrahiert Wikilinks via derive_wikilink_edges
3. Baut Lookup-Index (Titel/Alias -> note_id)
4. Löst Wikilinks auf und erzeugt Edges
5. Schreibt Edges in Qdrant
Ergebnis-Interpretation:
------------------------
- Ausgabe: JSON mit Statistiken
* notes_scanned: Anzahl verarbeiteter Notizen
* edges_upserted: Anzahl geschriebener Edges
- Exit-Code 0: Erfolgreich
Verwendung:
-----------
- Nach Migrationen oder Datenverlust
- Wenn Edges fehlen oder unvollständig sind
- Zur Reparatur des Graphen
Hinweise:
---------
- Überschreibt existierende Edges (kein Merge)
- Nutzt vereinfachtes Chunking (1 Chunk = gesamter Body)
- Erzeugt nur Wikilink-Edges, keine anderen Edge-Typen
Aufruf:
-------
python3 -m scripts.backfill_edges --vault ./vault
python3 -m scripts.backfill_edges --vault ./vault --exclude /.obsidian/ /_backup/
Parameter:
----------
--vault PATH Pfad zum Vault-Verzeichnis (erforderlich)
--exclude PATH Pfade zum Ausschließen (Default: /.obsidian/, /_backup_frontmatter/)
Änderungen:
-----------
v2.1.0 (2025-12-15): Dokumentation aktualisiert
v1.0.0: Initial Release
"""
from __future__ import annotations
import argparse, glob, json, os
from typing import List, Tuple

View File

@ -1,3 +1,67 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
FILE: scripts/debug_edge_loss.py
VERSION: 2.1.0 (2025-12-15)
STATUS: Active (Debug-Tool)
COMPATIBILITY: v2.9.1 (Post-WP14/WP-15b)
Zweck:
-------
Debug-Tool zur Analyse von Edge-Verlust-Problemen bei der Chunk-Verarbeitung.
Hilft zu verstehen, warum bestimmte Edges nicht erkannt oder verloren gehen.
Funktionsweise:
---------------
1. Analysiert eine einzelne Markdown-Datei
2. Führt zwei Analyseschritte durch:
a) Pre-Scan: Extrahiert alle Edge-Kandidaten aus dem rohen Text
- Wikilinks
- Typed Relations
- Callout Relations
b) Chunk-Analyse:
- Erstellt Chunks mit konfigurierbarem Profil
- Prüft, welche Edges in jedem Chunk gefunden werden
- Vergleicht mit Pre-Scan-Ergebnissen
3. Gibt detaillierte Analyse pro Chunk aus
Ergebnis-Interpretation:
------------------------
- [1] Globale Kandidaten: Alle Edge-Kandidaten, die im Text vorhanden sind
- [2] Chunk-Struktur: Für jeden Chunk:
* Section-Pfad
* Text-Snippet
* Gefundene explizite Kanten (callout:edge, inline:rel)
* Warnung, falls Callout im Text vorhanden, aber nicht erkannt
Verwendung:
-----------
- Debugging von Edge-Verlust bei Chunk-Grenzen
- Validierung der Edge-Extraktion in verschiedenen Chunk-Kontexten
- Analyse von Problemen mit Callout-Erkennung
Hinweise:
---------
- Asynchrones Skript (nutzt assemble_chunks async API)
- Konfigurierbares Chunking-Profil (Standard: sliding_window, 400/600 chars)
- Smart Edge Allocation ist standardmäßig deaktiviert für klare Analyse
Aufruf:
-------
python3 scripts/debug_edge_loss.py [PFAD_ZUR_DATEI.md]
Parameter:
----------
Keine CLI-Parameter. Dateipfad als erstes Argument oder Standard-Pfad.
Änderungen:
-----------
v2.1.0 (2025-12-15): Kompatibilität mit WP-14 Modularisierung
- Entfernt: _extract_all_edges_from_md (nicht mehr vorhanden)
- Ersetzt durch: extract_wikilinks, extract_typed_relations, extract_callout_relations
- Chunk-Payload-Struktur angepasst (window, type hinzugefügt)
v1.0.0: Erster Release
"""
import asyncio
import os
import sys
@ -6,8 +70,10 @@ from pathlib import Path
# Pfad-Setup
sys.path.insert(0, os.path.abspath("."))
from app.core.chunking import assemble_chunks, _extract_all_edges_from_md
from app.core.chunking import assemble_chunks
from app.core.derive_edges import build_edges_for_note
from app.core.parser import extract_wikilinks
from app.core.graph.graph_extractors import extract_typed_relations, extract_callout_relations
# Mock für Settings, falls nötig
os.environ["MINDNET_LLM_MODEL"] = "phi3:mini"
@ -19,9 +85,25 @@ async def analyze_file(file_path: str):
text = f.read()
# 1. Globale Kandidaten (Was sieht der Pre-Scan?)
# Wir simulieren den Aufruf, den der Chunker macht
# Wir extrahieren alle Edge-Kandidaten aus dem Text
note_id = Path(file_path).stem
candidates = _extract_all_edges_from_md(text, note_id, "concept")
candidates = []
# Wikilinks extrahieren
wikilinks = extract_wikilinks(text)
for wl in wikilinks:
candidates.append(f"wikilink:{wl}")
# Typed Relations extrahieren
typed_rels, _ = extract_typed_relations(text)
for kind, target in typed_rels:
candidates.append(f"typed:{kind}:{target}")
# Callout Relations extrahieren
callout_rels, _ = extract_callout_relations(text)
for kind, target in callout_rels:
candidates.append(f"callout:{kind}:{target}")
print(f"\n[1] Globale Kandidaten (Pre-Scan):")
for c in candidates:
print(f" - {c}")
@ -45,7 +127,12 @@ async def analyze_file(file_path: str):
# Was findet derive_edges in diesem rohen Chunk?
# Wir simulieren das Payload-Dict, das derive_edges erwartet
chunk_pl = {"text": chunk.text, "window": chunk.window, "chunk_id": chunk.id}
chunk_pl = {
"text": chunk.text,
"window": chunk.window or chunk.text,
"chunk_id": chunk.id,
"type": "concept"
}
edges = build_edges_for_note(note_id, [chunk_pl])
found_explicitly = [f"{e['kind']}:{e.get('target_id')}" for e in edges if e['rule_id'] in ['callout:edge', 'inline:rel']]

View File

@ -1,15 +1,62 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
scripts/debug_note_payload.py
Zeigt, welche app.core.note_payload geladen wird, ruft make_note_payload auf
und druckt Typ/Preview der Rückgabe.
FILE: scripts/debug_note_payload.py
VERSION: 2.1.0 (2025-12-15)
STATUS: Active (Debug-Tool)
COMPATIBILITY: v2.9.1 (Post-WP14/WP-15b)
Zweck:
-------
Debug-Tool zur Analyse der Note-Payload-Erzeugung.
Zeigt, welches Modul geladen wird und die erzeugte Payload-Struktur.
Funktionsweise:
---------------
1. Lädt Note-Payload-Modul
2. Liest Markdown-Datei
3. Ruft make_note_payload auf
4. Zeigt Modul-Pfad, Rückgabe-Typ und Payload-Inhalt
Ergebnis-Interpretation:
------------------------
- Ausgabe: Debug-Informationen
* module_path: Pfad zum geladenen Modul
* return_type: Typ der Rückgabe
* keys: Liste der Payload-Keys (falls Dict)
* JSON: Vollständige Payload (falls Dict)
Verwendung:
-----------
- Debugging von Payload-Erzeugungsproblemen
- Validierung der Modul-Ladung
- Analyse der Payload-Struktur
Hinweise:
---------
- Nutzt app.core.ingestion.ingestion_note_payload (nicht mehr app.core.note_payload)
- Zeigt vollständige Payload-Struktur
Aufruf:
python3 -m scripts.debug_note_payload --file ./test_vault/40_concepts/concept-alpha.md --vault-root ./test_vault
-------
python3 -m scripts.debug_note_payload --file ./vault/note.md --vault-root ./vault
Parameter:
----------
--file PATH Pfad zur Markdown-Datei (erforderlich)
--vault-root PATH Vault-Root für relative Pfade (optional)
--hash-mode MODE Hash-Modus (optional)
--hash-normalize N Hash-Normalisierung (optional)
--hash-source SRC Hash-Quelle (optional)
Änderungen:
-----------
v2.1.0 (2025-12-15): Kompatibilität mit WP-14 Modularisierung
- Geändert: app.core.note_payload app.core.ingestion.ingestion_note_payload
v1.0.0: Initial Release
"""
import argparse, json, os, pprint
from app.core import note_payload as np
from app.core.ingestion import ingestion_note_payload as np
from app.core.parser import read_markdown
def main():
@ -24,7 +71,6 @@ def main():
print("module_path:", getattr(np, "__file__", "<unknown>"))
parsed = read_markdown(args.file)
res = np.make_note_payload(parsed, vault_root=args.vault_root,
hash_mode=args.hash_mode,
hash_normalize=args.hash_normalize,
hash_source=args.hash_source,
file_path=args.file)

View File

@ -1,14 +1,55 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
scripts/debug_qdrant_state.py
Zeigt Prefix, Collections und einfache Counts (notes/chunks/edges) + sample note_ids.
FILE: scripts/debug_qdrant_state.py
VERSION: 2.1.0 (2025-12-15)
STATUS: Active (Debug-Tool)
COMPATIBILITY: v2.9.1 (Post-WP14/WP-15b)
Zweck:
-------
Zeigt schnelle Übersicht über den Qdrant-Zustand.
Gibt Prefix, Collections, Punkt-Anzahlen und Beispiel-IDs aus.
Funktionsweise:
---------------
1. Verbindet mit Qdrant
2. Ermittelt Collections für das Präfix
3. Zählt Points in jeder Collection
4. Extrahiert Beispiel-IDs (erste 5)
Ergebnis-Interpretation:
------------------------
- Ausgabe: JSON mit Zustands-Übersicht
* prefix: Collection-Präfix
* collections: Namen der Collections
* counts: Punkt-Anzahlen pro Collection
* samples: Beispiel-IDs pro Collection
Verwendung:
-----------
- Schnelle Status-Prüfung
- Debugging von Verbindungsproblemen
- Validierung der Collection-Struktur
Hinweise:
---------
- Nutzt count() für exakte Zählung (falls verfügbar)
- Fallback auf scroll() bei Problemen
Aufruf:
export COLLECTION_PREFIX="mindnet"
python3 -m scripts.debug_qdrant_state
# oder:
python3 -m scripts.debug_qdrant_state --prefix mindnet
-------
python3 -m scripts.debug_qdrant_state
python3 -m scripts.debug_qdrant_state --prefix mindnet_dev
Parameter:
----------
--prefix TEXT Collection-Präfix (Default: ENV COLLECTION_PREFIX oder mindnet)
Änderungen:
-----------
v2.1.0 (2025-12-15): Dokumentation aktualisiert
v1.0.0: Initial Release
"""
from __future__ import annotations
import argparse, os, json

View File

@ -1,13 +1,56 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
scripts/diag_payload_indexes.py (compat v1.2)
FILE: scripts/diag_payload_indexes.py
VERSION: 2.1.0 (2025-12-15)
STATUS: Active
COMPATIBILITY: v2.9.1 (Post-WP14/WP-15b)
Zeigt payload_schema je Collection; kompatibel mit älteren qdrant-client Versionen.
Strategie (in dieser Reihenfolge):
1) openapi_client.collections_api.get_collection(..., with_payload_schema=True)
2) client.get_collection(...)
3) HTTP GET /collections/{name}?with_payload_schema=true
Zweck:
-------
Zeigt das Payload-Schema (Indizes) für alle Collections eines Präfixes.
Nützlich zur Diagnose von Index-Problemen oder Validierung der Schema-Struktur.
Funktionsweise:
---------------
1. Ermittelt Collections für das Präfix (notes, chunks, edges)
2. Für jede Collection:
- Versucht Payload-Schema über verschiedene Methoden zu laden:
* qdrant-client API (get_collection)
* HTTP GET direkt (Fallback)
- Zeigt Schema als JSON
3. Gibt Schema-Übersicht aus
Ergebnis-Interpretation:
------------------------
- Ausgabe: JSON pro Collection mit payload_schema
- Zeigt vorhandene Indizes (keyword, text) und deren Konfiguration
- Exit-Code 0: Erfolgreich
Verwendung:
-----------
- Diagnose von Index-Problemen
- Validierung nach ensure_payload_indexes
- Dokumentation der Schema-Struktur
Hinweise:
---------
- Kompatibel mit verschiedenen qdrant-client Versionen
- Nutzt Fallback-Strategie für maximale Kompatibilität
Aufruf:
-------
python3 -m scripts.diag_payload_indexes --prefix mindnet
Parameter:
----------
--prefix TEXT Collection-Präfix (Default: ENV COLLECTION_PREFIX oder mindnet)
Änderungen:
-----------
v2.1.0 (2025-12-15): Dokumentation aktualisiert
v1.2.0: Kompatibilität mit verschiedenen qdrant-client Versionen
v1.0.0: Initial Release
"""
from __future__ import annotations

View File

@ -1,4 +1,58 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
FILE: scripts/dump_note_chunks.py
VERSION: 2.1.0 (2025-12-15)
STATUS: Active
COMPATIBILITY: v2.9.1 (Post-WP14/WP-15b)
Zweck:
-------
Gibt die Chunks einer bestimmten Note in lesbarer Form aus.
Nützlich zur Analyse der Chunk-Struktur und -Inhalte.
Funktionsweise:
---------------
1. Sucht Note nach note-id im Vault
2. Erzeugt Chunks via assemble_chunks
3. Gibt Chunks formatiert aus:
- Chunk-ID, Token-Anzahl, Section-Pfad
- Vollständiger Chunk-Text
Ergebnis-Interpretation:
------------------------
- Ausgabe: Formatierter Text
* Header: "# Titel (note-id) — X chunks"
* Pro Chunk: "--- chunk_id | tokens | section_path ---"
* Gefolgt vom Chunk-Text
- Exit-Code 0: Erfolgreich
- Fehlermeldung, wenn Note nicht gefunden
Verwendung:
-----------
- Analyse der Chunk-Struktur einer spezifischen Note
- Debugging von Chunking-Problemen
- Validierung der Chunk-Inhalte
Hinweise:
---------
- Nutzt synchrones assemble_chunks (kann async sein)
- Gibt nur erste gefundene Note aus (bei Duplikaten)
Aufruf:
-------
python3 -m scripts.dump_note_chunks --vault ./vault --note-id my-note-id
Parameter:
----------
--vault PATH Pfad zum Vault-Verzeichnis (erforderlich)
--note-id ID Note-ID zum Dumpen (erforderlich)
Änderungen:
-----------
v2.1.0 (2025-12-15): Dokumentation aktualisiert
v1.0.0: Initial Release
"""
from __future__ import annotations
import argparse, os, glob
from app.core.parser import read_markdown, normalize_frontmatter, validate_required_frontmatter

View File

@ -1,22 +1,70 @@
#!/usr/bin/env python3
# scripts/edges_dryrun.py
# -*- coding: utf-8 -*-
"""
Dry-Run: Erzeuge Edges aus einem Vault **ohne** Qdrant-Upsert.
- Liest Markdown mit YAML-Frontmatter
- Chunking: einfacher Absatz-Chunker (Index + text)
- Kanten: nutzt app.core.edges.build_edges_for_note()
- Ausgabe: JSON pro Note mit Edge-Counts und 3 Beispiel-Payloads
FILE: scripts/edges_dryrun.py
VERSION: 2.1.0 (2025-12-15)
STATUS: Active
COMPATIBILITY: v2.9.1 (Post-WP14/WP-15b)
Zweck:
-------
Simuliert die Edge-Erzeugung aus Markdown-Dateien ohne Datenbank-Upsert.
Nützlich zur Analyse, welche Kanten aus einem Vault generiert würden.
Funktionsweise:
---------------
1. Scannt alle .md-Dateien im Vault
2. Für jede Datei:
- Parst Markdown mit Frontmatter
- Erstellt einfache Absatz-basierte Chunks (vereinfachtes Chunking)
- Extrahiert Edge-Kandidaten via build_edges_for_note():
* Wikilinks [[...]]
* Typed Relations [[rel:KIND|Target]]
* Callout Relations [!edge] KIND: [[Target]]
* Struktur-Kanten (belongs_to, next, prev)
- Zählt Edges nach Typ (kind/relation)
3. Gibt JSON-Report aus mit Edge-Statistiken pro Note
Ergebnis-Interpretation:
------------------------
- Ausgabe: JSON-Array mit einem Objekt pro Note
- Jedes Objekt enthält:
* path: Dateipfad
* note_id: Note-Identifier
* type: Note-Typ
* chunks: Anzahl der Chunks
* edges_total: Gesamtanzahl der Edges
* edges_by_kind: Dictionary mit Edge-Anzahl pro Typ
* samples: Erste 3 Edges als Beispiele
Verwendung:
-----------
- Analyse der Graph-Struktur vor dem Import
- Debugging von fehlenden oder unerwarteten Edges
- Validierung der Edge-Extraktion-Logik
Hinweise:
---------
- Verwendet vereinfachtes Chunking (Absatz-basiert), nicht das vollständige Chunking-System
- Edge-Extraktion entspricht der Produktions-Logik (app.core.derive_edges)
- Keine Datenbank-Operationen, rein analytisch
Aufruf:
python3 -m scripts.edges_dryrun --vault ./vault
-------
python3 -m scripts.edges_dryrun --vault ./vault
python3 -m scripts.edges_dryrun --vault ./vault --include-note-scope-refs
Optional:
--include-note-scope-refs # auch Frontmatter-Links (links[].target_id) als Note-Scope-Referenzen
Parameter:
----------
--vault PATH Pfad zum Vault-Verzeichnis (erforderlich)
--include-note-scope-refs Berücksichtigt auch Frontmatter-Links (links[].target_id)
Voraussetzungen:
- app/core/parser.py (read_markdown, normalize_frontmatter)
- app/core/edges.py (dieses Modul forwardet zur v2-Implementierung)
Änderungen:
-----------
v2.1.0 (2025-12-15): Kompatibilität mit WP-14 Modularisierung
- Geändert: app.core.edges app.core.derive_edges
- Parameter korrigiert: chunk_payloads chunks, note_level_refs note_level_references
v1.0.0: Erster Release
"""
from __future__ import annotations
@ -28,7 +76,7 @@ from pathlib import Path
from typing import Dict, List, Optional
from app.core.parser import read_markdown, normalize_frontmatter
from app.core.edges import build_edges_for_note
from app.core.derive_edges import build_edges_for_note
def _iter_markdown(vault: str):
for p in Path(vault).rglob("*.md"):
@ -83,8 +131,8 @@ def main():
edges = build_edges_for_note(
note_id=note_id,
chunk_payloads=chunks,
note_level_refs=note_refs,
chunks=chunks,
note_level_references=note_refs,
include_note_scope_refs=include_note_scope,
)
kinds = {}

View File

@ -1,19 +1,64 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
scripts/edges_full_check.py
Zählt und validiert Kanten in Qdrant. Erkennt folgende Rule-Gruppen:
- explicit_total: rule_id startswith "explicit:" (z.B. explicit:wikilink, explicit:note_scope)
- callout_total: rule_id == "callout:edge"
- inline_total: rule_id startswith "inline:" (z.B. inline:rel)
- defaults_total: rule_id startswith "edge_defaults:"
- structure: rule_id in {"structure:belongs_to","structure:order"}
FILE: scripts/edges_full_check.py
VERSION: 2.1.0 (2025-12-15)
STATUS: Active
COMPATIBILITY: v2.9.1 (Post-WP14/WP-15b)
Gibt zusätzlich:
- edges_by_kind (aggregiert)
- notes/chunks/edges Anzahlen
- multi_callout_detected: True, falls ein Chunk mehrere Callout-Ziele der gleichen Relation enthält
- per_note_checks: belongs_to == chunks, next == prev == (chunks-1)
Zweck:
-------
Umfassende Validierung der Edge-Struktur in Qdrant.
Analysiert Edge-Typen, Rule-Gruppen und strukturelle Integrität.
Funktionsweise:
---------------
1. Lädt alle Edges aus {prefix}_edges
2. Gruppiert Edges nach rule_id:
- explicit: rule_id startswith "explicit:" (wikilink, note_scope)
- callout: rule_id == "callout:edge"
- inline: rule_id startswith "inline:" (rel)
- defaults: rule_id startswith "edge_defaults:"
- structure: rule_id in {"structure:belongs_to", "structure:order"}
3. Prüft strukturelle Integrität:
- belongs_to == chunks pro Note
- next == prev == (chunks-1) pro Note
- Multi-Callout-Erkennung
4. Aggregiert Statistiken
Ergebnis-Interpretation:
------------------------
- Ausgabe: JSON mit umfassender Analyse
* counts: notes/chunks/edges Anzahlen
* edges_by_kind: Aggregierte Edge-Anzahl pro Typ
* rule_groups: Zählung nach Rule-Gruppen
* per_note_checks: Strukturelle Validierung pro Note
* multi_callout_detected: Boolean
- Exit-Code 0: Erfolgreich
Verwendung:
-----------
- Umfassende Graph-Analyse
- Validierung nach größeren Änderungen
- Debugging von Edge-Problemen
Hinweise:
---------
- Kann bei großen Graphen langsam sein
- Prüft strukturelle, nicht semantische Korrektheit
Aufruf:
-------
python3 -m scripts.edges_full_check --prefix mindnet
Parameter:
----------
--prefix TEXT Collection-Präfix (Default: ENV COLLECTION_PREFIX oder mindnet)
Änderungen:
-----------
v2.1.0 (2025-12-15): Dokumentation aktualisiert
v1.0.0: Initial Release
"""
from __future__ import annotations

View File

@ -1,39 +1,74 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Script: scripts/export_markdown.py Qdrant Markdown (Vault)
Version: 1.4.1
Datum: 2025-09-10
FILE: scripts/export_markdown.py
VERSION: 2.1.0 (2025-12-15)
STATUS: Active
COMPATIBILITY: v2.9.1 (Post-WP14/WP-15b)
Funktion
--------
Exportiert Notes (Frontmatter + Body) aus Qdrant in einen Zielordner. Der Body wird
bevorzugt aus dem Feld `fulltext` rekonstruiert; falls leer/nicht vorhanden, aus Chunks
(Sortierung: seq chunk_index Nummer in chunk_id). Pfade werden **relativ** geschrieben.
Zweck:
-------
Exportiert Notes (Frontmatter + Body) aus Qdrant zurück in Markdown-Dateien.
Nützlich für Backup, Migration oder Notfall-Wiederherstellung.
Optionen
--------
--out PATH Zielordner (erforderlich)
--prefix TEXT Collection-Prefix (CLI überschreibt ENV COLLECTION_PREFIX)
--note-id ID Nur eine Note exportieren
--overwrite Existierende Dateien überschreiben
--include-edges MODE none|yaml|footer (Default: none)
--flatten-paths Alle Dateien flach schreiben; Originalpfad in FM: orig_path
Funktionsweise:
---------------
1. Liest alle Notes aus Qdrant (Collection: {prefix}_notes)
2. Für jede Note:
- Rekonstruiert Frontmatter aus Payload-Feldern
- Rekonstruiert Body:
* Primär: aus `fulltext` Feld (falls vorhanden)
* Fallback: aus Chunks (sortiert nach seq chunk_index chunk_id)
- Optional: Fügt Edges als Links hinzu (yaml/footer)
3. Schreibt Markdown-Dateien mit relativen Pfaden
ENV
---
Ergebnis-Interpretation:
------------------------
- Ausgabe: JSON pro Datei mit note_id, path, decision (write/skip-exists)
- Abschluss: "Done. Exported notes: X"
- Exit-Code 0: Erfolgreich
Verwendung:
-----------
- Backup vor größeren Änderungen
- Migration zwischen Instanzen
- Notfall-Wiederherstellung bei Vault-Verlust
- Analyse der in Qdrant gespeicherten Daten
Hinweise:
---------
- Pfade werden relativ geschrieben (wie im Original-Vault)
- --flatten-paths: Alle Dateien in einen Ordner (orig_path in Frontmatter)
- Body-Rekonstruktion aus Chunks kann bei sehr langen Dokumenten unvollständig sein
- Edge-Export optional (none/yaml/footer)
Aufruf:
-------
python3 -m scripts.export_markdown --out ./_exportVault
python3 -m scripts.export_markdown --out ./_exportVault --note-id concept-alpha --include-edges yaml
python3 -m scripts.export_markdown --out ./_exportVault --flatten-paths --overwrite
Parameter:
----------
--out PATH Zielordner für exportierte Markdown-Dateien (erforderlich)
--prefix TEXT Collection-Präfix (überschreibt ENV COLLECTION_PREFIX)
--note-id ID Nur eine bestimmte Note-ID exportieren (optional)
--overwrite Existierende Dateien überschreiben (sonst skip)
--include-edges MODE none|yaml|footer (Default: none)
- none: Keine Edges
- yaml: Als YAML-Feld 'references' im Frontmatter
- footer: Als Markdown-Links am Ende
--flatten-paths Alle Dateien flach schreiben (orig_path in Frontmatter)
Umgebungsvariablen:
-------------------
COLLECTION_PREFIX, QDRANT_URL | QDRANT_HOST/QDRANT_PORT | QDRANT_API_KEY
Beispiele
---------
export COLLECTION_PREFIX="mindnet"
python3 -m scripts.export_markdown --out ./_exportVault
# Nur eine Note, Edges als YAML-Feld 'references'
python3 -m scripts.export_markdown --out ./_exportVault --note-id concept-alpha --include-edges yaml
# Flach schreiben mit Überschreiben
python3 -m scripts.export_markdown --out ./_exportVault --flatten-paths --overwrite
Änderungen:
-----------
v2.1.0 (2025-12-15): Kompatibilität mit WP-14 Modularisierung
- Aktualisiert: Import-Pfade für neue Struktur
v1.4.1 (2025-09-10): Initial Release
"""
from __future__ import annotations

View File

@ -1,4 +1,68 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
FILE: scripts/fix_frontmatter.py
VERSION: 2.1.0 (2025-12-15)
STATUS: Active
COMPATIBILITY: v2.9.1 (Post-WP14/WP-15b)
Zweck:
-------
Repariert oder ergänzt fehlende Frontmatter-Felder in Markdown-Dateien.
Erzeugt stabile IDs, erkennt Typen und erstellt vollständige Frontmatter-Struktur.
Funktionsweise:
---------------
1. Scannt alle Markdown-Dateien im Vault
2. Für jede Datei:
- Liest vorhandenes Frontmatter
- Erkennt fehlende Felder (id, title, type, created)
- Generiert fehlende Werte:
* id: Stabile ID aus Pfad, Titel und Datum
* title: Aus H1, Dateiname oder "Untitled"
* type: Aus Pfad/Tags (journal, task, project, etc.)
* created: Aus Dateiname oder mtime
- Validiert Payload (optional)
- Schreibt korrigiertes Frontmatter zurück
Ergebnis-Interpretation:
------------------------
- Ausgabe: JSON pro Datei mit Änderungen
* path: Dateipfad
* changes: Dict mit alten/neuen Werten
* backup_path: Pfad zur Backup-Datei (falls --backup)
- Exit-Code 0: Erfolgreich
Verwendung:
-----------
- Migration von Legacy-Vaults ohne Frontmatter
- Reparatur beschädigter Frontmatter
- Standardisierung von Frontmatter-Strukturen
Hinweise:
---------
- Erstellt Backups vor Änderungen (mit --backup)
- Idempotent: Überspringt bereits vollständige Frontmatter
- Nutzt Heuristiken für Typ-Erkennung (Pfad/Tags)
Aufruf:
-------
python3 -m scripts.fix_frontmatter --vault ./vault --apply
python3 -m scripts.fix_frontmatter --vault ./vault --backup --apply
Parameter:
----------
--vault PATH Pfad zum Vault-Verzeichnis (erforderlich)
--backup Erstellt Backup-Dateien vor Änderungen
--apply Führt tatsächliche Änderungen durch (sonst Dry-Run)
--validate Validiert Note-Payload nach Fix
Änderungen:
-----------
v2.1.0 (2025-12-15): Dokumentation aktualisiert
- Hinweis: validate_note_payload existiert nicht mehr (wird entfernt)
v1.0.0: Initial Release
"""
from __future__ import annotations
import argparse, os, re, sys, json, shutil, time, hashlib
from dataclasses import dataclass
@ -6,7 +70,7 @@ from typing import Dict, Tuple, Optional, List
from slugify import slugify
from app.core.parser import read_markdown, normalize_frontmatter
from app.core.parser import FRONTMATTER_RE # für Re-Inject
from app.core.validate_note import validate_note_payload
# NOTE: validate_note_payload existiert nicht mehr - entfernt
from app.core.ingestion.ingestion_note_payload import make_note_payload
DATE_IN_NAME = re.compile(r"(?P<y>\d{4})[-_\.]?(?P<m>\d{2})[-_\.]?(?P<d>\d{2})")

View File

@ -1,50 +1,73 @@
#!/usr/bin/env python3
# scripts/gc_qdrant_after_vault_scan.py
# Version: 1.0.0 (2025-09-05)
#
# Zweck
# -----
# Garbage-Collector für Qdrant: löscht Einträge (Edges, Chunks, Notes), deren Note-ID
# nicht mehr im Obsidian-Vault vorhanden ist. So bleiben Vektorindex/Graph mit dem Vault konsistent.
#
# Aufrufparameter
# ---------------
# --vault PATH Pfad zum Obsidian-Vault (z. B. ./vault) [erforderlich]
# --mode {edges,content,all}
# edges -> nur Kanten mit source_id/target_id ∉ Vault-Notes löschen
# content -> Chunks & Notes löschen, deren note_id ∉ Vault-Notes (keine Edges)
# all -> zuerst edges, dann content
# --prefix PREFIX Collection-Präfix (Default: aus ENV COLLECTION_PREFIX oder "mindnet")
# --apply Ohne diesen Schalter: Dry-Run (nur Vorschau). Mit Schalter: ausführen.
# --yes Sicherheitsabfrage überspringen (non-interaktiv)
# --batch-size N Größe für In-Filter (Default: 1000)
#
# Hinweise
# --------
# - Benötigt funktionierendes Python-venv mit allen Abhängigkeiten von mindnet (qdrant-client usw.).
# - Läuft gegen die drei Collections {prefix}_notes, {prefix}_chunks, {prefix}_edges (keine anderen Projekte).
# - Nutzt OR-Filter (Filter.should) korrekt, keine minimum_should (Pydantic v2 lässt die Option nicht zu).
#
# Änderungen ggü. vorher
# ----------------------
# - Neu: eigenes GC-Tool; berührt ausschließlich das übergebene Projekt-Präfix.
# - Sichere Dry-Run-Vorschau mit Zählung pro Collection; interaktive Bestätigung.
# - Löscht Edges mittels Filter auf (source_id ∈ MISSING) ODER (target_id ∈ MISSING).
# - Löscht Chunks/Notes mittels Filter auf note_id ∈ MISSING.
#
# Beispiele
# ---------
# DRY RUN: python3 -m scripts.gc_qdrant_after_vault_scan --vault ./vault --mode all
# APPLY: python3 -m scripts.gc_qdrant_after_vault_scan --vault ./vault --mode all --apply
# CI-Modus: python3 -m scripts.gc_qdrant_after_vault_scan --vault ./vault --mode edges --apply --yes
#
# Kompatibilität / Kontext
# ------------------------
# - Frontmatter-Validierung & Parsing wie im Projekt (parser.read_markdown, validate_required_frontmatter). :contentReference[oaicite:0]{index=0}
# - Note-Payload-Schema (u. a. note_id, hash_fulltext) wie spezifiziert. :contentReference[oaicite:1]{index=1}
# - Collection-Namen & Anlage-Logik über app.core.qdrant (notes/chunks = dim, edges = 1D). :contentReference[oaicite:2]{index=2}
# - Edges nutzen Felder source_id/target_id; Chunks/Notes tragen note_id in payload. :contentReference[oaicite:3]{index=3} :contentReference[oaicite:4]{index=4}
#
# -*- coding: utf-8 -*-
"""
FILE: scripts/gc_qdrant_after_vault_scan.py
VERSION: 2.1.0 (2025-12-15)
STATUS: Active
COMPATIBILITY: v2.9.1 (Post-WP14/WP-15b)
Zweck:
-------
Garbage-Collector für Qdrant: löscht Einträge, deren Note-ID nicht mehr
im Vault vorhanden ist. Hält Vektorindex/Graph mit dem Vault konsistent.
Funktionsweise:
---------------
1. Scannt Vault und sammelt alle note_ids
2. Lädt note_ids aus Qdrant
3. Berechnet Differenz (verwaiste IDs)
4. Löscht verwaiste Einträge:
- mode=edges: Nur Edges mit source_id/target_id Vault
- mode=content: Chunks & Notes mit note_id Vault
- mode=all: Zuerst edges, dann content
5. Nutzt Batch-Filter für effiziente Löschung
Ergebnis-Interpretation:
------------------------
- Ausgabe: JSON mit Preview und Statistiken
* mode: DRY-RUN oder APPLY
* vault_note_ids: Anzahl Notizen im Vault
* qdrant_note_ids: Anzahl Notizen in Qdrant
* orphans: Anzahl verwaister Notizen
* deleted: Anzahl gelöschter Einträge (nach --apply)
- Exit-Code 0: Erfolgreich
Verwendung:
-----------
- Regelmäßige Wartung nach Vault-Bereinigung
- Konsistenz-Check zwischen Vault und Datenbank
- Vor Migrationen
Sicherheitsmerkmale:
-------------------
- Dry-Run standardmäßig (keine Änderungen ohne --apply)
- Interaktive Bestätigung (außer mit --yes)
- Nur betroffene Collections werden geändert
Aufruf:
-------
python3 -m scripts.gc_qdrant_after_vault_scan --vault ./vault --mode all
python3 -m scripts.gc_qdrant_after_vault_scan --vault ./vault --mode all --apply
python3 -m scripts.gc_qdrant_after_vault_scan --vault ./vault --mode edges --apply --yes
Parameter:
----------
--vault PATH Pfad zum Vault-Verzeichnis (erforderlich)
--mode MODE edges | content | all (Default: all)
- edges: Nur Edges löschen
- content: Nur Chunks & Notes löschen
- all: Beides (zuerst edges, dann content)
--prefix TEXT Collection-Präfix (Default: ENV COLLECTION_PREFIX oder mindnet)
--apply Führt tatsächliches Löschen durch (sonst Dry-Run)
--yes Keine interaktive Bestätigung
--batch-size N Batch-Größe für Filter (Default: 1000)
Änderungen:
-----------
v2.1.0 (2025-12-15): Kompatibilität mit WP-14 Modularisierung
- Aktualisiert: Import-Pfade für neue Struktur
v1.0.0 (2025-09-05): Initial Release
"""
from __future__ import annotations
import argparse, os, glob, json, sys
from typing import Iterable, Set, Tuple, List

View File

@ -1,40 +1,70 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
scripts/health_check_mindnet.py
FILE: scripts/health_check_mindnet.py
VERSION: 2.1.0 (2025-12-15)
STATUS: Active
COMPATIBILITY: v2.9.1 (Post-WP14/WP-15b)
Health-Check für den mindnet-Retriever-/Query-Endpoint.
Zweck:
-------
Health-Check für den mindnet /query-Retriever-Endpoint.
Prüft Verfügbarkeit, Antwortzeit und Ergebnisqualität.
Funktion:
- Führt POST-Requests auf /query in verschiedenen Modi aus (standard: semantic + hybrid).
- Prüft Status-Code, JSON-Struktur und Anzahl der Treffer.
- Kennzeichnet Probleme als:
- status="ok"
- status="warning" (z.B. Timeout)
- status="error" (harte Fehler wie HTTP-Fehler, JSON-Fehler etc.)
Funktionsweise:
---------------
1. Führt POST-Requests auf /query in verschiedenen Modi aus
2. Prüft für jeden Modus:
- HTTP-Status-Code (erwartet 200)
- JSON-Struktur (erwartet Objekt mit results-Array)
- Anzahl der Treffer (mindestens min-results)
- Antwortzeit (Latency)
3. Klassifiziert Ergebnisse:
- ok: Alles in Ordnung
- warning: Timeout oder unerwartetes Verhalten
- error: HTTP-Fehler, JSON-Fehler, zu wenige Ergebnisse
Exit-Code:
- Default (tolerant):
- overall_status = "ok" (inkl. warnings) Exit-Code 0
- overall_status = "error" Exit-Code 1
- Mit --strict:
- warnings werden wie errors behandelt Exit-Code 1
Ergebnis-Interpretation:
------------------------
- Ausgabe: Menschlich lesbare Zusammenfassung + JSON-Report
- overall_status: ok | warning | error
- Exit-Code 0: ok (tolerant) oder ok/warning (strict)
- Exit-Code 1: error (tolerant) oder warning/error (strict)
Beispiele:
Verwendung:
-----------
- Monitoring und Alerting (z.B. cronjob)
- CI/CD-Pipelines (Validierung nach Deployment)
- Debugging von Performance-Problemen
- Integration in externe Monitoring-Tools (n8n, etc.)
python scripts/health_check_mindnet.py \
--url http://127.0.0.1:8001/query \
--query "embeddings" \
--top-k 3
Hinweise:
---------
- Standard: Prüft semantic und hybrid Modi
- Tolerant: Warnings führen nicht zu Exit-Code 1
- Strict: Warnings werden wie Errors behandelt
- JSON-Ausgabe für maschinelle Weiterverarbeitung
python scripts/health_check_mindnet.py \
--url http://127.0.0.1:8001/query \
--query "embeddings" \
--top-k 3 \
--timeout 15 \
--modes hybrid
Aufruf:
-------
python3 scripts/health_check_mindnet.py --url http://127.0.0.1:8001/query
python3 scripts/health_check_mindnet.py --query "test" --top-k 5 --modes semantic hybrid
python3 scripts/health_check_mindnet.py --strict
# Strenger Modus (warnings → Exit-Code 1)
python scripts/health_check_mindnet.py --strict
Parameter:
----------
--url URL Vollständige URL des /query-Endpunkts (Default: http://127.0.0.1:8001/query)
--query TEXT Test-Query (Default: embeddings)
--top-k INT Anzahl der erwarteten Ergebnisse (Default: 3)
--timeout FLOAT Timeout in Sekunden pro Request (Default: 5.0)
--modes LIST Zu prüfende Modi (Default: semantic hybrid)
--min-results INT Minimale Anzahl erwarteter Ergebnisse (Default: 1)
--strict Warnings als Fehler behandeln (Exit-Code 1 bei warnings)
Änderungen:
-----------
v2.1.0 (2025-12-15): Dokumentation aktualisiert
v1.0.0: Initial Release
"""
from __future__ import annotations

View File

@ -1,11 +1,69 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
scripts/import_markdown.py
CLI-Tool zum Importieren von Markdown-Dateien in Qdrant.
WP-15b: Implementiert den Two-Pass Workflow (Pre-Scan + Processing).
Sorgt dafür, dass der LocalBatchCache vor der Verarbeitung robust gefüllt wird.
Indiziert Notizen nach ID, Titel und Dateiname für maximale Link-Kompatibilität.
VERSION: 2.4.1
FILE: scripts/import_markdown.py
VERSION: 2.4.1 (2025-12-15)
STATUS: Active (Core)
COMPATIBILITY: v2.9.1 (Post-WP14/WP-15b)
Zweck:
-------
Hauptwerkzeug zum Importieren von Markdown-Dateien aus einem Vault in Qdrant.
Implementiert den Two-Pass Workflow (WP-15b) für robuste Edge-Validierung.
Funktionsweise:
---------------
1. PASS 1: Global Pre-Scan
- Scannt alle Markdown-Dateien im Vault
- Extrahiert Note-Kontext (ID, Titel, Dateiname)
- Füllt LocalBatchCache für semantische Edge-Validierung
- Indiziert nach ID, Titel und Dateiname für Link-Auflösung
2. PASS 2: Semantic Processing
- Verarbeitet Dateien in Batches (20 Dateien, max. 5 parallel)
- Nutzt gefüllten Cache für binäre Edge-Validierung
- Erzeugt Notes, Chunks und Edges in Qdrant
- Respektiert Hash-basierte Change Detection
Ergebnis-Interpretation:
------------------------
- Log-Ausgabe: Fortschritt und Statistiken
- Stats: processed, skipped, errors
- Exit-Code 0: Erfolgreich (auch wenn einzelne Dateien Fehler haben)
- Ohne --apply: Dry-Run (keine DB-Änderungen)
Verwendung:
-----------
- Regelmäßiger Import nach Vault-Änderungen
- Initial-Import eines neuen Vaults
- Re-Indexierung mit --force
Hinweise:
---------
- Two-Pass Workflow sorgt für robuste Edge-Validierung
- Change Detection verhindert unnötige Re-Indexierung
- Parallele Verarbeitung für Performance (max. 5 gleichzeitig)
- Cloud-Resilienz durch Semaphore-Limits
Aufruf:
-------
python3 -m scripts.import_markdown --vault ./vault --apply
python3 -m scripts.import_markdown --vault ./vault --prefix mindnet_dev --force --apply
Parameter:
----------
--vault PATH Pfad zum Vault-Verzeichnis (Default: ./vault)
--prefix TEXT Collection-Präfix (Default: ENV COLLECTION_PREFIX oder mindnet)
--force Erzwingt Re-Indexierung aller Dateien (ignoriert Hashes)
--apply Führt tatsächliche DB-Schreibvorgänge durch (sonst Dry-Run)
Änderungen:
-----------
v2.4.1 (2025-12-15): WP-15b Two-Pass Workflow
- Implementiert Pre-Scan für LocalBatchCache
- Indizierung nach ID, Titel und Dateiname
- Batch-Verarbeitung mit Semaphore-Limits
v2.0.0: Initial Release
"""
import asyncio
import os

View File

@ -1,45 +1,60 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
make_test_vault.py erzeugt einen minimalen, nachvollziehbaren Test-Vault
FILE: scripts/make_test_vault.py
VERSION: 2.1.0 (2025-12-15)
STATUS: Active (Test-Tool)
COMPATIBILITY: v2.9.1 (Post-WP14/WP-15b)
Version: 1.2 (2025-09-09)
Änderungen ggü. 1.1:
- Fügt **externe Links** (http/mailto) in `exp-two.md` hinzu, damit der Chunk-Payload-Exporter
`external_links` realistisch testen kann.
- Kleine Textanpassungen zur stabilen Chunk-Bildung (Absatzstruktur).
Zweck:
-------
Erzeugt einen minimalen, nachvollziehbaren Test-Vault für Entwicklung und Tests.
Enthält verschiedene Szenarien: leere Links, externe Links, verschiedene Note-Typen.
Zweck
- Kleiner Obsidian-ähnlicher Vault zum Durchspielen des Importers (Chunks/Edges).
- Szenarien: leere Links, spätere Anlage fehlender Noten, Chunk-Neuaufteilung, externe Links.
Funktionsweise:
---------------
1. Erstellt Verzeichnisstruktur (concepts, experiences, projects)
2. Generiert Test-Notizen mit vollständigem Frontmatter:
- concept-alpha.md (Basis-Concept)
- exp-one.md (verlinkt auf concept-alpha und missing-note)
- exp-two.md (verlinkt auf concept-alpha + externe Links)
- project-demo.md (verlinkt auf concept-alpha und exp-one)
3. Optional: Erstellt missing-note (mit --with-missing)
Struktur (Default: ./test_vault)
- 40_concepts/concept-alpha.md
- 20_experiences/exp-one.md (verlinkt auf [[concept-alpha]] und [[missing-note]])
- 20_experiences/exp-two.md (verlinkt auf [[concept-alpha]] + externe Links)
- 30_projects/project-demo.md (verlinkt auf [[concept-alpha]] und [[exp-one]])
Ergebnis-Interpretation:
------------------------
- Ausgabe: Erfolgsmeldung mit erstellten Dateien
- Exit-Code 0: Erfolgreich
- Exit-Code 1: Fehler (z.B. Verzeichnis existiert bereits ohne --force)
Voraussetzungen
- Keine. Rein Dateigenerierung.
Verwendung:
-----------
- Entwicklung und Testing
- Demo und Dokumentation
- CI/CD-Tests
Aufruf
python3 -m scripts.make_test_vault [--out ./test_vault] [--force] [--with-missing]
Hinweise:
---------
- Erstellt realistische Test-Daten mit verschiedenen Edge-Szenarien
- Enthält "Red Links" (missing-note) für Link-Auflösungs-Tests
- Externe Links für Chunk-Payload-Tests
Parameter
--out Zielverzeichnis (Standard: ./test_vault)
--force Bestehenden Ordner löschen und neu anlegen.
--with-missing Auch die 'missing-note' direkt anlegen (Standard: erst im 2. Lauf)
Aufruf:
-------
python3 -m scripts.make_test_vault --out ./test_vault
python3 -m scripts.make_test_vault --out ./test_vault --force --with-missing
Hinweise für Tests
1) Erster Import (dry-run oder --apply): Es gibt einen leeren Link [[missing-note]].
2) Lege danach eine Datei für missing-note an (mit gleicher ID im YAML) und importiere erneut:
-> Erwartung: Edges für ehemals leeren Link werden korrekt nachgezogen (references + backlink).
3) Ändere den Body von exp-one.md so, dass andere Chunk-Grenzen entstehen und importiere erneut:
-> Erwartung: Chunks/Edges/Note werden für betroffene Noten aktualisiert.
4) Prüfe externe Links (verify_chunk_texts.py betrifft nur Text; externe Links siehst du in chunk_payloads).
Parameter:
----------
--out PATH Zielverzeichnis (Default: ./test_vault)
--force Löscht bestehenden Ordner und legt neu an
--with-missing Erstellt auch missing-note direkt (Standard: erst im 2. Lauf)
Kompatibel mit:
- note.schema.json: 'created'/'updated' müssen strings sein. (Wichtig!)
Änderungen:
-----------
v2.1.0 (2025-12-15): Dokumentation aktualisiert
v1.2 (2025-09-09): Externe Links hinzugefügt
v1.0.0: Initial Release
"""
from __future__ import annotations

View File

@ -1,21 +1,62 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
scripts/ollama_tool_runner.py Minimaler Tool-Caller für Ollama + mindnet
FILE: scripts/ollama_tool_runner.py
VERSION: 2.1.0 (2025-12-15)
STATUS: Active
COMPATIBILITY: v2.9.1 (Post-WP14/WP-15b)
Zweck:
Führt den Tool-Call-Loop für mindnet_query / mindnet_subgraph aus.
Nutzt /tools/ollama (Schema) und deine FastAPI (/query, /graph).
ENV:
OLLAMA=http://127.0.0.1:11434
API_BASE=http://127.0.0.1:8000
MODEL=llama3.1
Nutzung:
python3 scripts/ollama_tool_runner.py "Frage an den Agenten"
Version:
0.1.0 (Erstanlage)
Stand:
2025-10-07
-------
Minimaler Tool-Caller für Ollama mit mindnet-Tools.
Führt Tool-Call-Loop für mindnet_query und mindnet_subgraph aus.
Funktionsweise:
---------------
1. Lädt Tool-Schema von /tools/ollama Endpoint
2. Sendet Query an Ollama mit Tool-Definitionen
3. Ollama entscheidet, welche Tools aufzurufen sind
4. Führt Tool-Calls aus:
- mindnet_query: Ruft /query Endpoint auf
- mindnet_subgraph: Ruft /graph Endpoint auf
5. Wiederholt bis keine weiteren Tool-Calls nötig sind
Ergebnis-Interpretation:
------------------------
- Ausgabe: Konversations-Verlauf mit Tool-Calls und Antworten
- Exit-Code 0: Erfolgreich
- Exit-Code 1: Fehler (z.B. API nicht erreichbar)
Verwendung:
-----------
- Testing von Tool-Integration
- Demo der Agent-Funktionalität
- Entwicklung neuer Tools
Hinweise:
---------
- Nutzt Ollama als LLM-Backend
- Tool-Schema wird von mindnet API bereitgestellt
- Unterstützt mehrere Tool-Calls in einer Konversation
Aufruf:
-------
python3 scripts/ollama_tool_runner.py "Frage an den Agenten"
Parameter:
----------
Keine CLI-Parameter. Query als erstes Argument.
Umgebungsvariablen:
-------------------
OLLAMA (Default: http://127.0.0.1:11434)
API_BASE (Default: http://127.0.0.1:8000)
MODEL (Default: llama3.1)
Änderungen:
-----------
v2.1.0 (2025-12-15): Dokumentation aktualisiert
v0.1.0 (2025-10-07): Initial Release
"""
from __future__ import annotations

View File

@ -1,13 +1,63 @@
#!/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 jsonschema import ValidationError
from app.core.parser import read_markdown, validate_required_frontmatter, normalize_frontmatter
from app.core.note_payload import make_note_payload
from app.core.validate_note import validate_note_payload
from app.core.ingestion.ingestion_note_payload import make_note_payload
@ -39,11 +89,10 @@ def main():
parsed = read_markdown(path)
fm = normalize_frontmatter(parsed.frontmatter)
validate_required_frontmatter(fm)
# Note-Payload gemäß note.schema.json validieren
payload = make_note_payload(parsed, vault_root=root)
validate_note_payload(payload)
# 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 (ValidationError, ValueError) as e:
except (ValueError, TypeError, KeyError, AttributeError) as e:
failed += 1
print(f"{os.path.relpath(path, root)} :: {e}", file=sys.stderr)

View File

@ -1,24 +1,158 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
scripts/payload_dryrun.py (zeigt, was VOR dem Upsert tatsächlich in den Payloads steht)
- KEIN Überschreiben der Note-Payload mehr
- types.yaml ist maßgeblich (gemäß app/core/note_payload.py & chunk_payload.py)
FILE: scripts/payload_dryrun.py
VERSION: 2.1.0 (2025-12-15)
STATUS: Active
COMPATIBILITY: v2.9.1 (Post-WP14/WP-15b)
Zweck:
-------
Zeigt die Payload-Struktur, die vor dem Datenbank-Upsert erzeugt würde.
Nützlich zur Validierung der Payload-Erzeugung und Konfiguration (types.yaml).
Funktionsweise:
---------------
1. Scannt alle Markdown-Dateien im Vault
2. Für jede Datei:
- Parst Markdown mit Frontmatter
- Erzeugt Note-Payload (wie in make_note_payload)
- Erstellt Chunks via assemble_chunks
- Erzeugt Chunk-Payloads (wie in make_chunk_payloads)
- Optional: Erzeugt Edges (mit --with-edges)
3. Gibt JSON pro Note aus mit Payload-Zusammenfassung
Ergebnis-Interpretation:
------------------------
- Ausgabe: JSON-Objekte (ein Objekt pro Note, eine Zeile pro Objekt)
- Jedes Objekt enthält:
* note_id, title, type, path
* note_payload: retriever_weight, chunk_profile
* chunks_summary: count, first (erste 3 Chunks mit Metadaten)
* edges_summary (nur mit --with-edges): total, by_kind
Verwendung:
-----------
- Validierung der types.yaml Konfiguration
- Debugging von Payload-Erzeugungsproblemen
- Analyse der Chunk-Struktur vor dem Import
- Prüfung von retriever_weight und chunk_profile Zuweisungen
Hinweise:
---------
- types.yaml ist maßgeblich für Payload-Erzeugung
- Frontmatter-Überschreibungen werden berücksichtigt
- Keine Datenbank-Operationen, rein analytisch
- Chunking nutzt vollständiges assemble_chunks (nicht vereinfacht)
Aufruf:
-------
python3 -m scripts.payload_dryrun --vault ./vault
python3 -m scripts.payload_dryrun --vault ./vault --note-id my-note-id
python3 -m scripts.payload_dryrun --vault ./vault --with-edges
Parameter:
----------
--vault PATH Pfad zum Vault-Verzeichnis (erforderlich)
--note-id ID Nur eine bestimmte Note verarbeiten (optional)
--with-edges Edge-Erzeugung einschließen (optional)
Änderungen:
-----------
v2.1.0 (2025-12-15): Kompatibilität mit WP-14 Modularisierung
- Entfernt: Fallback für app.core.edges
- Verwendet direkt: app.core.derive_edges
- Parameter korrigiert: chunk_payloads chunks, note_level_refs note_level_references
v1.0.0: Erster Release
"""
from __future__ import annotations
import argparse, os, json
import argparse, os, json, asyncio
from typing import Any, Dict, List, Optional
from app.core.parser import read_markdown, normalize_frontmatter, validate_required_frontmatter
from app.core.chunking import assemble_chunks
from app.core.ingestion.ingestion_note_payload import make_note_payload
from app.core.ingestion.ingestion_chunk_payload import make_chunk_payloads
try:
from app.core.derive_edges import build_edges_for_note
except Exception:
from app.core.edges import build_edges_for_note # type: ignore
from app.core.derive_edges import build_edges_for_note
def main():
async def process_file(path: str, root: str, args):
"""Verarbeitet eine einzelne Datei asynchron."""
parsed = read_markdown(path)
if not parsed:
return None
fm = normalize_frontmatter(parsed.frontmatter)
try:
validate_required_frontmatter(fm)
except Exception as e:
print(json.dumps({"path": path, "error": f"invalid frontmatter: {e}"}))
return None
if args.note_id and fm.get("id") != args.note_id:
return None
# Note-Payload exakt so, wie der Importer ihn baut (types.yaml maßgeblich)
note_pl = make_note_payload(parsed,
vault_root=root,
hash_source="parsed",
hash_normalize="canonical",
file_path=path)
body_text = getattr(parsed, "body", "") or ""
chunks = await assemble_chunks(fm["id"], body_text, fm.get("type","concept"))
chunk_note = {
"frontmatter": fm,
"id": fm.get("id"),
"type": fm.get("type"),
"title": fm.get("title"),
"path": note_pl.get("path") or path,
"note_id": note_pl.get("note_id"),
"tags": fm.get("tags"),
}
# make_chunk_payloads bestimmt Werte ebenfalls aus types.yaml (Frontmatter wird ignoriert)
chunk_pls = make_chunk_payloads(
chunk_note,
note_pl["path"],
chunks,
note_text=body_text,
types_cfg=None, # Loader aus Datei; kein Override von außen
file_path=path,
)
out = {
"note_id": note_pl.get("note_id") or fm.get("id"),
"title": fm.get("title"),
"type": fm.get("type"),
"note_payload": {
"retriever_weight": note_pl.get("retriever_weight"),
"chunk_profile": note_pl.get("chunk_profile")
},
"chunks_summary": {
"count": len(chunk_pls),
"first": [
{k: chunk_pls[i].get(k) for k in ("chunk_id","index","ord","retriever_weight","chunk_profile","neighbors_prev","neighbors_next")}
for i in range(min(3, len(chunk_pls)))
]
},
"path": note_pl.get("path")
}
if args.with_edges:
edges = build_edges_for_note(
note_id=note_pl.get("note_id") or fm.get("id"),
chunks=chunk_pls,
note_level_references=note_pl.get("references") or [],
include_note_scope_refs=False,
)
kinds = {}
for e in edges:
k = (e.get("relation") or e.get("kind") or "edge")
kinds[k] = kinds.get(k, 0) + 1
out["edges_summary"] = {"total": len(edges), "by_kind": kinds}
return out
async def main_async():
ap = argparse.ArgumentParser()
ap.add_argument("--vault", required=True)
ap.add_argument("--note-id")
@ -35,81 +169,12 @@ def main():
files.sort()
for path in files:
parsed = read_markdown(path)
if not parsed:
continue
fm = normalize_frontmatter(parsed.frontmatter)
try:
validate_required_frontmatter(fm)
except Exception as e:
print(json.dumps({"path": path, "error": f"invalid frontmatter: {e}"}))
continue
result = await process_file(path, root, args)
if result:
print(json.dumps(result, ensure_ascii=False))
if args.note_id and fm.get("id") != args.note_id:
continue
# Note-Payload exakt so, wie der Importer ihn baut (types.yaml maßgeblich)
note_pl = make_note_payload(parsed,
vault_root=root,
hash_mode="body",
hash_normalize="canonical",
hash_source="parsed",
file_path=path)
body_text = getattr(parsed, "body", "") or ""
chunks = assemble_chunks(fm["id"], body_text, fm.get("type","concept"))
chunk_note = {
"frontmatter": fm,
"id": fm.get("id"),
"type": fm.get("type"),
"title": fm.get("title"),
"path": note_pl.get("path") or path,
"note_id": note_pl.get("note_id"),
"tags": fm.get("tags"),
}
# make_chunk_payloads bestimmt Werte ebenfalls aus types.yaml (Frontmatter wird ignoriert)
chunk_pls = make_chunk_payloads(
chunk_note,
note_pl["path"],
chunks,
note_text=body_text,
types_cfg=None, # Loader aus Datei; kein Override von außen
file_path=path,
)
out = {
"note_id": note_pl.get("note_id") or fm.get("id"),
"title": fm.get("title"),
"type": fm.get("type"),
"note_payload": {
"retriever_weight": note_pl.get("retriever_weight"),
"chunk_profile": note_pl.get("chunk_profile")
},
"chunks_summary": {
"count": len(chunk_pls),
"first": [
{k: chunk_pls[i].get(k) for k in ("chunk_id","index","ord","retriever_weight","chunk_profile","neighbors_prev","neighbors_next")}
for i in range(min(3, len(chunk_pls)))
]
},
"path": note_pl.get("path")
}
if args.with_edges:
edges = build_edges_for_note(
note_id=note_pl.get("note_id") or fm.get("id"),
chunk_payloads=chunk_pls,
note_level_refs=note_pl.get("references") or [],
include_note_scope_refs=False,
)
kinds = {}
for e in edges:
k = (e.get("relation") or e.get("kind") or "edge")
kinds[k] = kinds.get(k, 0) + 1
out["edges_summary"] = {"total": len(edges), "by_kind": kinds}
print(json.dumps(out, ensure_ascii=False))
def main():
asyncio.run(main_async())
if __name__ == "__main__":
main()

View File

@ -1,4 +1,60 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
FILE: scripts/preview_chunks.py
VERSION: 2.1.0 (2025-12-15)
STATUS: Active
COMPATIBILITY: v2.9.1 (Post-WP14/WP-15b)
Zweck:
-------
Zeigt eine Vorschau der Chunk-Struktur für Notizen im Vault.
Nützlich zur Analyse der Chunking-Strategie und Nachbarschafts-Links.
Funktionsweise:
---------------
1. Scannt alle Markdown-Dateien im Vault
2. Für jede Datei:
- Erzeugt Note-Payload
- Erstellt Chunks via assemble_chunks
- Erzeugt Chunk-Payloads
3. Gibt JSON pro Note aus mit Chunk-Details
Ergebnis-Interpretation:
------------------------
- Ausgabe: JSON-Objekte (ein Objekt pro Note, eine Zeile pro Objekt)
- Jedes Objekt enthält:
* note_id, title
* num_chunks: Anzahl der Chunks
* avg_tokens: Durchschnittliche Token pro Chunk
* chunks: Array mit Chunk-Details (id, tokens, section, prev, next)
Verwendung:
-----------
- Analyse der Chunk-Verteilung
- Validierung der Nachbarschafts-Links
- Debugging von Chunking-Problemen
Hinweise:
---------
- Nutzt synchrones assemble_chunks (kann async sein)
- Zeigt nur Struktur, keine Inhalte
Aufruf:
-------
python3 -m scripts.preview_chunks --vault ./vault
python3 -m scripts.preview_chunks --vault ./vault --note-id my-note-id
Parameter:
----------
--vault PATH Pfad zum Vault-Verzeichnis (erforderlich)
--note-id ID Nur eine bestimmte Note verarbeiten (optional)
Änderungen:
-----------
v2.1.0 (2025-12-15): Dokumentation aktualisiert
v1.0.0: Initial Release
"""
from __future__ import annotations
import argparse, os, glob, json
from app.core.parser import read_markdown, normalize_frontmatter, validate_required_frontmatter

View File

@ -1,38 +1,79 @@
# scripts/prune_qdrant_vs_vault.py
# -----------------------------------------------------------------------------
# Name: prune_qdrant_vs_vault.py
# Version: 1.0.0 (2025-09-08)
# Zweck: Entfernt verwaiste Qdrant-Einträge (notes/chunks/edges), wenn
# die zugehörigen Markdown-Dateien im Vault nicht mehr existieren.
#
# Was es macht:
# - Liest alle note_id aus dem Vault (Frontmatter: id / note_id).
# - Liest alle note_id aus Qdrant (mindnet_notes).
# - Bildet die Differenz (nur in Qdrant vorhandene, im Vault fehlende).
# - Löscht für jede verwaiste note_id:
# * Notes-Point(s)
# * Alle Chunks der Note
# * Alle Edges, die auf diese Note referenzieren
# (source_id == note_id ODER target_id == note_id ODER
# source_note_id == note_id ODER target_note_id == note_id)
#
# Hinweise:
# - Kein globaler Delete. Nur betroffene note_id.
# - Dry-Run standardmäßig; tatsächliches Löschen erst mit --apply.
# - Interaktive Bestätigung (abschaltbar mit --yes).
#
# Aufruf:
# python3 -m scripts.prune_qdrant_vs_vault --vault ./vault --prefix mindnet
# python3 -m scripts.prune_qdrant_vs_vault --vault ./vault --prefix mindnet --apply
# python3 -m scripts.prune_qdrant_vs_vault --vault ./vault --prefix mindnet --apply --yes
#
# Voraussetzungen:
# - Ausführung im aktivierten venv empfohlen: source .venv/bin/activate
# - Qdrant läuft lokal (oder URL/API-Key in ENV), siehe app/core/qdrant.py
#
# Änderungen:
# - 1.0.0: Erster Release.
# -----------------------------------------------------------------------------
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
FILE: scripts/prune_qdrant_vs_vault.py
VERSION: 2.1.0 (2025-12-15)
STATUS: Active
COMPATIBILITY: v2.9.1 (Post-WP14/WP-15b)
Zweck:
-------
Bereinigt verwaiste Einträge in Qdrant, wenn die zugehörigen Markdown-Dateien
im Vault nicht mehr existieren. Stellt Konsistenz zwischen Vault und Datenbank her.
Funktionsweise:
---------------
1. Liest alle note_id aus dem Vault (aus Frontmatter: id / note_id)
2. Liest alle note_id aus Qdrant (Collection: {prefix}_notes)
3. Berechnet Differenz: note_ids nur in Qdrant vorhanden (verwaist)
4. Für jede verwaiste note_id (nur mit --apply):
- Löscht Note-Point(s) aus {prefix}_notes
- Löscht alle Chunks der Note aus {prefix}_chunks
- Löscht alle Edges, die auf diese Note referenzieren:
* source_id == note_id
* target_id == note_id
* source_note_id == note_id
* target_note_id == note_id
Ergebnis-Interpretation:
------------------------
- Ausgabe: JSON mit Preview-Informationen
* mode: "DRY-RUN" oder "APPLY"
* counts: Statistiken (vault_note_ids, qdrant_note_ids, orphans)
* orphans_sample: Erste 20 verwaiste note_ids
- Bei --apply: Zusätzlich JSON mit deleted-Statistiken
* deleted.notes: Anzahl gelöschter Note-Points
* deleted.chunks: Anzahl gelöschter Chunks
* deleted.edges: Anzahl gelöschter Edges
Verwendung:
-----------
- Regelmäßige Wartung nach Vault-Bereinigung
- Vor Migrationen oder größeren Umstrukturierungen
- Konsistenz-Check zwischen Vault und Datenbank
Sicherheitsmerkmale:
-------------------
- Dry-Run standardmäßig (keine Änderungen ohne --apply)
- Interaktive Bestätigung (außer mit --yes)
- Nur betroffene note_ids werden gelöscht (kein globaler Delete)
- Zeigt Preview vor Ausführung
Aufruf:
-------
# Dry-Run (nur Analyse)
python3 -m scripts.prune_qdrant_vs_vault --vault ./vault --prefix mindnet
# Tatsächliches Löschen
python3 -m scripts.prune_qdrant_vs_vault --vault ./vault --prefix mindnet --apply
# Ohne Rückfrage
python3 -m scripts.prune_qdrant_vs_vault --vault ./vault --prefix mindnet --apply --yes
Parameter:
----------
--vault PATH Pfad zum Vault-Verzeichnis (erforderlich)
--prefix TEXT Collection-Präfix (Default: mindnet)
--apply Führt tatsächliches Löschen durch (sonst nur Dry-Run)
--yes Keine interaktive Bestätigung
Änderungen:
-----------
v2.1.0 (2025-12-15): Kompatibilität mit WP-14 Modularisierung
- Geändert: parse_markdown_file read_markdown + normalize_frontmatter
- Parsing-Logik an neue API angepasst
v1.0.0 (2025-09-08): Erster Release
"""
import argparse
import json
@ -45,18 +86,19 @@ from qdrant_client import QdrantClient
from qdrant_client.http import models as rest
from app.core.qdrant import QdrantConfig, get_client, collection_names
from app.core.parser import parse_markdown_file # nutzt euer bestehendes Parsing/Schema
from app.core.parser import read_markdown, normalize_frontmatter
def read_vault_note_ids(vault_dir: Path) -> Set[str]:
note_ids: Set[str] = set()
for p in vault_dir.rglob("*.md"):
try:
parsed = parse_markdown_file(str(p))
fm = parsed.frontmatter if hasattr(parsed, "frontmatter") else (parsed.get("frontmatter") or {})
nid = fm.get("id") or fm.get("note_id")
if nid:
note_ids.add(str(nid))
parsed = read_markdown(str(p))
if parsed:
fm = normalize_frontmatter(parsed.frontmatter) if parsed.frontmatter else {}
nid = fm.get("id") or fm.get("note_id")
if nid:
note_ids.add(str(nid))
except Exception:
# still und leise weiter wir wollen robust sein
continue

View File

@ -1,25 +1,59 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Script: scripts/report_hashes.py Übersicht & Lücken bei Mehrfach-Hashes
Version: 1.0.0
Datum: 2025-09-10
FILE: scripts/report_hashes.py
VERSION: 2.1.0 (2025-12-15)
STATUS: Active
COMPATIBILITY: v2.9.1 (Post-WP14/WP-15b)
Funktion
--------
Listet je Note die vorhandenen Einträge im Feld `hashes` (Signaturen: <mode>:<source>:<normalize>)
und meldet fehlende Soll-Keys. Eignet sich als CI-Check.
Zweck:
-------
Erstellt Übersicht über Hash-Signaturen in Note-Payloads.
Meldet fehlende Soll-Keys für Multi-Hash Change Detection.
Optionen
--------
--prefix TEXT Collection-Prefix (CLI überschreibt ENV)
--require K [K ...] Zusätzliche Soll-Keys (Default: body|frontmatter|full:parsed:canonical)
--fail-on-missing Exitcode 2, wenn fehlende Keys gefunden werden
Funktionsweise:
---------------
1. Lädt alle Notes aus {prefix}_notes
2. Prüft für jede Note das `hashes` Feld
3. Vergleicht vorhandene Keys mit Soll-Keys
4. Meldet fehlende Keys pro Note
Beispiele
Ergebnis-Interpretation:
------------------------
- Ausgabe: JSON mit Hash-Übersicht
* notes_total: Anzahl geprüfter Notizen
* notes_with_missing: Anzahl Notizen mit fehlenden Keys
* missing_keys: Liste fehlender Keys pro Note
- Exit-Code 0: Keine fehlenden Keys (oder --fail-on-missing nicht gesetzt)
- Exit-Code 2: Fehlende Keys gefunden (nur mit --fail-on-missing)
Verwendung:
-----------
- CI/CD-Validierung der Hash-Integrität
- Audit nach Migrationen
- Prüfung der Change Detection Funktionalität
Hinweise:
---------
python3 -m scripts.report_hashes --prefix mindnet
python3 -m scripts.report_hashes --require frontmatter:raw:none --fail-on-missing
- Multi-Hash Format: <mode>:<source>:<normalize>
- Standard Soll-Keys: body:parsed:canonical, full:parsed:canonical
- Kann zusätzliche Keys via --require anfordern
Aufruf:
-------
python3 -m scripts.report_hashes --prefix mindnet
python3 -m scripts.report_hashes --require frontmatter:raw:none --fail-on-missing
Parameter:
----------
--prefix TEXT Collection-Präfix (überschreibt ENV COLLECTION_PREFIX)
--require KEY ... Zusätzliche Soll-Keys (Default: body:parsed:canonical, full:parsed:canonical)
--fail-on-missing Exit-Code 2, wenn fehlende Keys gefunden werden
Änderungen:
-----------
v2.1.0 (2025-12-15): Dokumentation aktualisiert
v1.0.0 (2025-09-10): Initial Release
"""
from __future__ import annotations

View File

@ -1,49 +1,75 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Name: scripts/reset_qdrant.py
Version: v1.2.1 (2025-12-11)
Kurzbeschreibung:
Sicheres Zurücksetzen der Qdrant-Collections für EIN Projektpräfix. Das Skript
ermittelt zunächst die tatsächlich betroffenen Collections und zeigt eine
Übersicht an. Anschließend wird der User um Bestätigung gebeten (interaktive
Abfrage), bevor eine der Aktionen ausgeführt wird:
FILE: scripts/reset_qdrant.py
VERSION: 2.1.0 (2025-12-15)
STATUS: Active (Core)
COMPATIBILITY: v2.9.1 (Post-WP14/WP-15b)
- wipe: Löscht die Collections komplett und legt sie gemäß Projekt-Defaults neu an.
**Neu**: Danach werden *immer* die Payload-Indizes & Schema-Ergänzungen
über ensure_payload_indexes() idempotent eingerichtet (falls nicht mit --no-indexes deaktiviert).
- truncate: Löscht nur alle Points (Inhalte), behält die Collection-Settings.
**Neu**: Optional (Default) werden im Anschluss die Payload-Indizes geprüft/ergänzt.
Zweck:
-------
Sicheres Zurücksetzen der Qdrant-Collections für ein Projektpräfix.
Ermöglicht vollständigen Neustart (wipe) oder Löschen nur der Inhalte (truncate).
Aufruf (aus Projekt-Root, im venv):
python3 -m scripts.reset_qdrant --mode wipe [--prefix PREFIX] [--yes] [--dry-run]
python3 -m scripts.reset_qdrant --mode truncate [--prefix PREFIX] [--yes] [--dry-run]
Funktionsweise:
---------------
1. Ermittelt betroffene Collections (notes, chunks, edges für Präfix)
2. Zeigt Preview der existierenden Collections
3. Interaktive Bestätigung (außer mit --yes)
4. Führt Aktion aus:
- wipe: Löscht Collections komplett, legt neu an, richtet Indizes ein
- truncate: Löscht nur Points, behält Collection-Settings, prüft Indizes
5. Richtet Payload-Indizes idempotent ein (außer mit --no-indexes)
Parameter:
--mode wipe | truncate (Pflicht)
--prefix Collection-Prefix (Default: env COLLECTION_PREFIX oder 'mindnet')
--yes Keine Rückfrage, direkt ausführen (CI/CD geeignet)
--dry-run Nur anzeigen, was passieren würde; nichts ändern
--no-indexes Überspringt den Schritt ensure_payload_indexes() (Standard: Indizes/Schema werden geprüft/ergänzt)
Ergebnis-Interpretation:
------------------------
- Preview: Zeigt betroffene Collections vor Ausführung
- Exit-Code 0: Erfolgreich
- Exit-Code 1: Abgebrochen oder keine Aktion
- Exit-Code 2: Verbindungs- oder Konfigurationsfehler
Umgebungsvariablen (optional):
QDRANT_URL, QDRANT_API_KEY, COLLECTION_PREFIX, VECTOR_DIM (Default 384)
(Zusätzliche ENV für Named Vectors etc. werden innerhalb ensure_collections/ensure_payload_indexes berücksichtigt.)
Verwendung:
-----------
- Vor größeren Migrationen oder Schema-Änderungen
- Bei Inkonsistenzen in der Datenbank
- Für Entwicklung/Testing (schneller Reset)
- CI/CD-Pipelines (mit --yes)
Sicherheitsmerkmale:
- Betrachtet ausschließlich Collections des angegebenen Präfixes.
- Listet vor Ausführung die tatsächlich existierenden Ziel-Collections auf.
- Fragt interaktiv nach Bestätigung (es sei denn --yes ist gesetzt).
-------------------
- Betrachtet nur Collections des angegebenen Präfixes
- Listet betroffene Collections vor Ausführung auf
- Interaktive Bestätigung (außer mit --yes)
- Dry-Run Modus verfügbar
Exitcodes:
0 = OK, 1 = abgebrochen/keine Aktion, 2 = Verbindungs-/Konfigurationsfehler
Aufruf:
-------
python3 -m scripts.reset_qdrant --mode wipe --prefix mindnet
python3 -m scripts.reset_qdrant --mode truncate --prefix mindnet --yes
python3 -m scripts.reset_qdrant --mode wipe --dry-run
Changelog:
v1.2.1: Fix: load_dotenv() hinzugefügt, damit VECTOR_DIM aus .env gelesen wird.
v1.2.0: ensure_payload_indexes() nach wipe/truncate standardmäßig ausführen (idempotent); --no-indexes Flag ergänzt.
v1.1.1: Stabilisierung & Preview (2025-09-05).
v1.1.0: Interaktive Bestätigung, --yes/--dry-run hinzugefügt, Preview der betroffenen Collections.
v1.0.0: Wipe/Truncate ohne Bestätigungsabfrage.
Parameter:
----------
--mode MODE wipe | truncate (Pflicht)
- wipe: Collections löschen & neu anlegen
- truncate: Nur Points löschen, Settings behalten
--prefix TEXT Collection-Präfix (Default: ENV COLLECTION_PREFIX oder mindnet)
--yes Keine Rückfrage, direkt ausführen (CI/CD)
--dry-run Nur anzeigen, was passieren würde
--no-indexes Überspringt ensure_payload_indexes() (Standard: Indizes werden geprüft/ergänzt)
Umgebungsvariablen:
-------------------
QDRANT_URL, QDRANT_API_KEY, COLLECTION_PREFIX, VECTOR_DIM (Default: 768)
Änderungen:
-----------
v2.1.0 (2025-12-15): Kompatibilität mit WP-14 Modularisierung
- Aktualisiert: Import-Pfade für neue Struktur
v1.2.1 (2025-12-11): Fix load_dotenv() für VECTOR_DIM
v1.2.0: ensure_payload_indexes() standardmäßig nach wipe/truncate
v1.1.0: Interaktive Bestätigung, --yes/--dry-run
v1.0.0: Initial Release
"""
from __future__ import annotations
import argparse

View File

@ -1,20 +1,66 @@
#!/usr/bin/env python3
# scripts/resolve_unresolved_references.py
# -*- coding: utf-8 -*-
"""
resolve_unresolved_references.py Unaufgelöste Wikilinks in Qdrant nachträglich auflösen
FILE: scripts/resolve_unresolved_references.py
VERSION: 2.1.0 (2025-12-15)
STATUS: Active
COMPATIBILITY: v2.9.1 (Post-WP14/WP-15b)
Version: 1.1.0 (Fixed for v2.6 Architecture)
Zweck:
-------
Löst unaufgelöste Wikilinks in Qdrant nachträglich auf.
Findet Edges mit status=="unresolved" und versucht sie über Titel/Alias aufzulösen.
Zweck
------
- Findet Edges in {prefix}_edges mit payload.status=="unresolved".
- Baut einen In-Memory Index aller Notizen (Titel/Alias -> ID).
- Aktualisiert die Edges (setzt target_id, entfernt status).
- Erzeugt symmetrische 'backlink'-Kanten für 'references'.
Funktionsweise:
---------------
1. Baut Lookup-Index aus allen Notizen:
- Mapping: lower(title) -> note_id
- Mapping: lower(alias) -> note_id
2. Findet alle Edges mit status=="unresolved"
3. Versucht Auflösung über Lookup-Index
4. Aktualisiert erfolgreich aufgelöste Edges:
- Setzt target_id
- Entfernt status
- Fügt resolution="healed_by_script" hinzu
5. Erzeugt Backlinks für erfolgreich aufgelöste references-Edges
Aufruf
------
python3 -m scripts.resolve_unresolved_references --apply
Ergebnis-Interpretation:
------------------------
- Log-Ausgabe: Fortschritt und Statistiken
- "Resolvable: X/Y": Anzahl aufgelösbarer Edges
- Ohne --apply: Dry-Run (keine DB-Änderungen)
- Exit-Code 0: Erfolgreich
Verwendung:
-----------
- Nach Import von neuen Notizen, die bestehende Links auflösen
- Reparatur von "Red Links" (Links auf noch nicht existierende Notizen)
- Wartung des Graphen nach größeren Änderungen
Hinweise:
---------
- Sucht nach status=="unresolved" in Edge-Payloads
- Auflösung erfolgt über Titel und Aliases (case-insensitive)
- Erzeugt automatisch Backlinks für references-Edges
- Batch-Verarbeitung für Performance
Aufruf:
-------
python3 -m scripts.resolve_unresolved_references --apply
python3 -m scripts.resolve_unresolved_references --prefix mindnet --limit 1000 --apply
Parameter:
----------
--prefix TEXT Collection-Präfix (Default: ENV COLLECTION_PREFIX)
--apply Führt tatsächliche DB-Änderungen durch (sonst Dry-Run)
--limit INT Maximale Anzahl zu verarbeitender Edges (0=alle, Default: 0)
--batch INT Batch-Größe für Upserts (Default: 100)
Änderungen:
-----------
v2.1.0 (2025-12-15): Dokumentation aktualisiert
v1.1.0: Fixed for v2.6 Architecture
v1.0.0: Initial Release
"""
import argparse

View File

@ -1,23 +1,63 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
FILE: scripts/setup_mindnet_collections.py
VERSION: 2.1.0 (2025-12-15)
STATUS: Active
COMPATIBILITY: v2.9.1 (Post-WP14/WP-15b)
Zweck:
-------
Richtet die Qdrant-Collections für das mindnet-Projekt ein.
Legt Collections und Payload-Indizes an (idempotent).
Collections:
- mindnet_chunks : semantische Suche über Markdown-Text-Chunks (Vektor: dim/Cosine)
- mindnet_notes : 1 Punkt pro Notiz (Metadaten, optional Titel-Embedding)
- mindnet_edges : explizite Link-Kanten (Dummy-Vektor size=1; Filter über Payload)
Funktionsweise:
---------------
1. Prüft Qdrant-Verfügbarkeit (optional /ready Endpoint)
2. Legt drei Collections an:
- {prefix}_chunks: Semantische Suche über Text-Chunks (Vektor: dim/Cosine)
- {prefix}_notes: Metadaten pro Notiz (Vektor: dim/Cosine)
- {prefix}_edges: Link-Kanten (Dummy-Vektor size=1, Filter über Payload)
3. Richtet Payload-Indizes ein:
- Keyword-Indizes für häufige Filter-Felder
- Text-Index für Volltextsuche (chunks.text)
Eigenschaften:
- Idempotent: legt nur an, wenn eine Collection noch nicht existiert
- Legt sinnvolle Payload-Indizes an (keyword/text)
- Ohne "global"-Seiteneffekte; Qdrant-URL wird sauber übergeben
Ergebnis-Interpretation:
------------------------
- Ausgabe: Status pro Collection ([+] angelegt, [=] existiert bereits)
- Abschluss: JSON-Liste aller vorhandenen Collections
- Exit-Code 0: Erfolgreich
- Exit-Code 1: Fehler (z.B. Qdrant nicht erreichbar)
Aufrufbeispiel:
python3 setup_mindnet_collections.py \
--qdrant-url http://127.0.0.1:6333 \
--prefix mindnet \
--dim 384 \
--distance Cosine
Verwendung:
-----------
- Initial-Setup einer neuen mindnet-Instanz
- Nach Qdrant-Reset oder Migration
- Validierung der Collection-Struktur
Hinweise:
---------
- Idempotent: Überspringt existierende Collections
- Nutzt HTTP-API direkt (kein qdrant-client)
- Legt nur Basis-Indizes an (erweiterte Indizes via ensure_payload_indexes)
Aufruf:
-------
python3 -m scripts.setup_mindnet_collections --qdrant-url http://127.0.0.1:6333 --prefix mindnet --dim 768
python3 -m scripts.setup_mindnet_collections --prefix mindnet_dev --dim 768 --distance Cosine
Parameter:
----------
--qdrant-url URL Qdrant-URL (Default: http://127.0.0.1:6333)
--prefix TEXT Collection-Präfix (Default: mindnet)
--dim INT Vektor-Dimension (Default: 384, empfohlen: 768 für nomic)
--distance METRIC Cosine | Euclid | Dot (Default: Cosine)
Änderungen:
-----------
v2.1.0 (2025-12-15): Kompatibilität mit WP-14 Modularisierung
- Dokumentation aktualisiert
v1.0.0: Initial Release
"""
from __future__ import annotations

View File

@ -1,23 +1,66 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
scripts/validate_edges.py
FILE: scripts/validate_edges.py
VERSION: 2.1.0 (2025-12-15)
STATUS: Active
COMPATIBILITY: v2.9.1 (Post-WP14/WP-15b)
Validiert die von WP-03 erzeugten Edges in Qdrant:
- Zählt Kanten je Typ (references, backlink, references_at)
- Prüft: Für jede "references" (resolved) existiert eine "backlink"-Gegenkante
- Prüft: "backlink" darf nicht "unresolved" sein
- Prüft: "references_at".source_id existiert in {prefix}_chunks
- Prüft: "references"/"backlink" source/target existieren in {prefix}_notes
- Prüft: doppelte edge_id (sollte 0 sein, da UUIDv5 aus edge_id)
Gibt ein kompaktes JSON-Resultat + optionale Detail-Listen aus.
Zweck:
-------
Validiert die Integrität der Edges in Qdrant.
Prüft strukturelle Korrektheit, Referenz-Integrität und Konsistenz.
Umgebung/Parameter:
- QDRANT_URL (Default: http://127.0.0.1:6333)
- QDRANT_API_KEY (optional)
- COLLECTION_PREFIX (Default: mindnet)
Funktionsweise:
---------------
1. Lädt alle Edges aus {prefix}_edges
2. Führt mehrere Validierungen durch:
- Zählt Edges nach Typ (references, backlink, etc.)
- Prüft: Für jede "references" existiert "backlink"-Gegenkante
- Prüft: "backlink" darf nicht "unresolved" sein
- Prüft: "references_at".source_id existiert in chunks
- Prüft: source/target existieren in notes
- Prüft: doppelte edge_id (sollte 0 sein)
3. Gibt kompaktes JSON-Resultat + optionale Detail-Listen aus
Beispiel:
python scripts/validate_edges.py --prefix mindnet
Ergebnis-Interpretation:
------------------------
- Ausgabe: JSON mit Validierungs-Ergebnissen
* counts_by_kind: Anzahl Edges pro Typ
* validation_results: Ergebnisse der einzelnen Prüfungen
* issues: Liste gefundener Probleme (optional mit --verbose)
- Exit-Code 0: Alle Validierungen bestanden
- Exit-Code 1: Validierungsfehler gefunden
Verwendung:
-----------
- Qualitätskontrolle nach Importen
- Debugging von Graph-Problemen
- CI/CD-Validierung
Hinweise:
---------
- Prüft strukturelle Integrität, nicht semantische Korrektheit
- Kann bei großen Graphen langsam sein
Aufruf:
-------
python3 -m scripts.validate_edges --prefix mindnet
python3 -m scripts.validate_edges --prefix mindnet --verbose
Parameter:
----------
--prefix TEXT Collection-Präfix (Default: ENV COLLECTION_PREFIX oder mindnet)
--verbose Zeigt detaillierte Problem-Listen
Umgebungsvariablen:
-------------------
QDRANT_URL (Default: http://127.0.0.1:6333), QDRANT_API_KEY, COLLECTION_PREFIX
Änderungen:
-----------
v2.1.0 (2025-12-15): Dokumentation aktualisiert
v1.0.0: Initial Release
"""
from __future__ import annotations
import argparse

View File

@ -1,58 +1,73 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Script: scripts/verify_chunk_texts.py
Version: 1.0.0
Datum: 2025-09-09
FILE: scripts/verify_chunk_texts.py
VERSION: 2.1.0 (2025-12-15)
STATUS: Active
COMPATIBILITY: v2.9.1 (Post-WP14/WP-15b)
Kurzbeschreibung
Zweck:
-------
Verifiziert, dass Chunk-Texte in Qdrant korrekt gespeichert sind und
der Note-Body aus Chunks rekonstruiert werden kann.
Funktionsweise:
---------------
Verifiziert, dass in Qdrant für jede Note die zugehörigen Chunks ein Textfeld
enthalten und der Body (notes.payload.fulltext) aus den Chunk-Texten sinnvoll
rekonstruiert werden kann.
1. Lädt alle Notes aus {prefix}_notes
2. Für jede Note:
- Lädt zugehörige Chunks
- Prüft, dass alle Chunks Text enthalten (text/content/raw)
- Rekonstruiert Body aus Chunks (sortiert nach chunk_index/chunk_id)
- Berechnet Coverage: gefundene Textsegmente / Fulltext-Länge
3. Validiert gegen notes.payload.fulltext
Prüfungen pro Note:
- Alle Chunks vorhanden (>=1).
- Jedes Chunk-Payload hat einen nutzbaren Textschlüssel: "text" (bevorzugt), sonst "content", sonst "raw".
- Reihenfolge der Chunks wird stabil bestimmt (payload.chunk_index -> Nummer aus chunk_id).
- Coverage: Summe der im Fulltext gefundenen Chunk-Textsegmente / len(Fulltext) (Toleranz für Overlaps).
-> OK wenn coverage >= 0.90 (konfigurierbar via --min-coverage)
Ergebnis-Interpretation:
------------------------
- Ausgabe: JSON mit Validierungs-Ergebnissen
* summary: Gesamtstatistiken
* per_note: Details pro Note
* coverage: Durchschnittliche Coverage
- Exit-Code 0: Alle Prüfungen bestanden
- Exit-Code 1: Probleme gefunden
Ausgabe:
- JSON mit Gesamtsummen und Details je Note.
Verwendung:
-----------
- Validierung nach Importen
- Diagnose von Text-Rekonstruktionsproblemen
- Qualitätskontrolle
ENV:
- QDRANT_URL | QDRANT_HOST/QDRANT_PORT | QDRANT_API_KEY
- COLLECTION_PREFIX (Fallback, wenn --prefix fehlt)
Hinweise:
---------
- Coverage-Toleranz für Overlaps (Standard: >= 0.90)
- Prüft Text-Felder: text (bevorzugt), content, raw
Beispiele:
# Alle Notes prüfen (Prefix aus ENV)
python3 -m scripts.verify_chunk_texts
Aufruf:
-------
python3 -m scripts.verify_chunk_texts --prefix mindnet
python3 -m scripts.verify_chunk_texts --note-id concept-alpha --min-coverage 0.95
# Nur eine Note prüfen
python3 -m scripts.verify_chunk_texts --note-id concept-alpha
Parameter:
----------
--prefix TEXT Collection-Präfix (Default: ENV COLLECTION_PREFIX)
--note-id ID Nur eine bestimmte Note prüfen (optional)
--min-coverage F Minimale Coverage (Default: 0.90)
# Prefix explizit setzen und strengere Coverage verlangen
python3 -m scripts.verify_chunk_texts --prefix mindnet --min-coverage 0.95
Umgebungsvariablen:
-------------------
QDRANT_URL | QDRANT_HOST/QDRANT_PORT | QDRANT_API_KEY, COLLECTION_PREFIX
Änderungen:
-----------
v2.1.0 (2025-12-15): Dokumentation aktualisiert
v1.0.0 (2025-09-09): Initial Release
"""
from __future__ import annotations
import argparse, json, os, re, sys
from typing import Dict, List, Tuple, Optional
from qdrant_client import QdrantClient
from qdrant_client.http import models as rest
def _names(prefix: str) -> Tuple[str,str,str]:
return f"{prefix}_notes", f"{prefix}_chunks", f"{prefix}_edges"
def _client() -> QdrantClient:
url = os.getenv("QDRANT_URL")
if not url:
host = os.getenv("QDRANT_HOST", "127.0.0.1")
port = int(os.getenv("QDRANT_PORT", "6333"))
url = f"http://{host}:{port}"
api_key = os.getenv("QDRANT_API_KEY") or None
return QdrantClient(url=url, api_key=api_key)
from app.core.qdrant import QdrantConfig, get_client, collection_names
def _chunk_sort_key(p: Dict, pid: str) -> Tuple[int,int,str]:
# Primär: payload.chunk_index, sekundär: Nummer am Ende der ID (#cNN oder #NN), sonst 0
@ -104,9 +119,11 @@ def main() -> None:
ap.add_argument("--min-coverage", type=float, default=0.90, help="Mindestabdeckung durch Chunks (Default: 0.90)")
args = ap.parse_args()
prefix = args.prefix or os.getenv("COLLECTION_PREFIX", "mindnet")
notes_col, chunks_col, _ = _names(prefix)
cli = _client()
cfg = QdrantConfig.from_env()
if args.prefix:
cfg.prefix = args.prefix
notes_col, chunks_col, _ = collection_names(cfg.prefix)
cli = get_client(cfg)
# Notes abrufen (optional filter by note_id)
notes_filter = None
@ -125,7 +142,7 @@ def main() -> None:
if off is None:
break
results = []
results: List[Dict] = []
total_missing_text = 0
total_notes_ok = 0
for n in notes:

View File

@ -1,28 +1,60 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
scripts/wp04_smoketest.py E2E-Schnelltest der WP-04 Endpunkte
FILE: scripts/wp04_smoketest.py
VERSION: 2.1.0 (2025-12-15)
STATUS: Active (Test-Tool)
COMPATIBILITY: v2.9.1 (Post-WP14/WP-15b)
Zweck:
- Holt exemplarisch einen Vektor aus {prefix}_chunks (falls verfügbar),
- ruft POST /query mit diesem Vektor auf,
- ruft GET /graph/<note_id> für die Top-Note auf,
- druckt Kurzresultate auf STDOUT.
-------
E2E-Schnelltest der WP-04 Endpunkte (/query und /graph).
Validiert grundlegende Funktionalität der Retrieval- und Graph-APIs.
Kompatibilität:
Python 3.12+, requests, qdrant-client
Version:
0.1.0 (Erstanlage)
Stand:
2025-10-07
Bezug:
WP-04 /query & /graph
Nutzung:
export QDRANT_URL="http://localhost:6333"
export MINDNET_PREFIX="mindnet"
python3 scripts/wp04_smoketest.py --api http://localhost:8000
Änderungsverlauf:
0.1.0 (2025-10-07) Erstanlage.
Funktionsweise:
---------------
1. Holt exemplarischen Chunk-Vektor aus Qdrant
2. Ruft POST /query mit Test-Query auf
3. Ruft GET /graph/<note_id> für Top-Note auf
4. Gibt Kurzresultate aus
Ergebnis-Interpretation:
------------------------
- Ausgabe: Test-Ergebnisse
* query_result: Ergebnis des /query Aufrufs
* graph_result: Ergebnis des /graph Aufrufs
* status: ok/error
- Exit-Code 0: Alle Tests bestanden
- Exit-Code 1: Fehler (z.B. API nicht erreichbar, keine Daten)
Verwendung:
-----------
- Schnelle Validierung nach Deployment
- CI/CD-Tests
- Debugging von API-Problemen
Hinweise:
---------
- Benötigt vorhandene Daten in Qdrant
- Testet nur grundlegende Funktionalität
Aufruf:
-------
python3 scripts/wp04_smoketest.py --api http://localhost:8000
Parameter:
----------
--api URL Base-URL der mindnet API (Default: http://localhost:8000)
Umgebungsvariablen:
-------------------
QDRANT_URL (Default: http://localhost:6333)
MINDNET_PREFIX (Default: mindnet)
Änderungen:
-----------
v2.1.0 (2025-12-15): Dokumentation aktualisiert
v0.1.0 (2025-10-07): Initial Release
"""
from __future__ import annotations