mindnet/docs/Handbuch.md

350 lines
14 KiB
Markdown
Raw Permalink Normal View History

2025-10-06 14:22:47 +02:00
# 📘 Mindnet Skript-Handbuch (aktualisiert)
2025-09-07 07:46:39 +02:00
2025-10-06 14:22:47 +02:00
Dieses Handbuch dokumentiert die Skripte und Tests für das Projekt **mindnet Wissensnetzwerk**.
Es beschreibt Zweck, Parameter, typische Aufrufe sowie aktuelle Verhaltensweisen (Hash-Modi, Parser-Robustheit, `window`/`text`-Trennung in Chunks, Export-Fixes).
Alle Beispiele sind so formatiert, dass sie direkt kopierbar sind. **Code/CLI-Beispiele sind eingerückt**, damit die Markdown-Darstellung nicht abbricht.
2025-09-07 07:46:39 +02:00
2025-10-06 14:22:47 +02:00
---
## 0) Umgebung & Konfiguration
**Wichtige ENV-Variablen**
- `QDRANT_URL` – z. B. `http://localhost:6333`
- `QDRANT_API_KEY` – API-Key (falls aktiviert)
- `COLLECTION_PREFIX` – Prefix der drei Collections, Standard: `mindnet` → `mindnet_notes`, `mindnet_chunks`, `mindnet_edges`
- `VECTOR_DIM` – Embedding-Dimension (Chunks), Standard: `384`
**Hash-Vergleich & Änderungs­erkennung**
2025-09-07 07:46:39 +02:00
2025-10-06 14:22:47 +02:00
- `MINDNET_HASH_COMPARE` – steuert, **welcher Anteil** für „changed“ verglichen wird
Werte: `Body` (Standard), `Frontmatter`, `Full`
- `MINDNET_HASH_SOURCE` – Quelle: `parsed` (Standard), `raw`, `file`
- `MINDNET_HASH_NORMALIZE` – Normalisierung: `canonical` (Standard) oder `none`
**Beispiel (nur Body berücksichtigen, kanonisch, geparst):**
export MINDNET_HASH_COMPARE=Body
export MINDNET_HASH_SOURCE=parsed
export MINDNET_HASH_NORMALIZE=canonical
2025-09-07 07:46:39 +02:00
source .venv/bin/activate
2025-10-06 14:22:47 +02:00
**Baseline-Signaturen (mehrere Modi):**
Der Importer kann **Signaturen aller Modi** (Body/Frontmatter/Full) vorhalten, damit spätere Moduswechsel deterministisch sind (keine „Mass-Changes“). Siehe `--baseline-modes` unter **Importer**.
2025-09-07 07:46:39 +02:00
---
2025-10-06 14:22:47 +02:00
## 1) Vault anlegen (für Tests)
2025-09-07 07:46:39 +02:00
2025-10-06 14:22:47 +02:00
### `scripts/make_test_vault.py`
2025-09-07 07:46:39 +02:00
**Zweck:**
Erstellt einen kleinen, nachvollziehbaren Test-Vault mit Markdown-Dateien.
Szenarien: offene Links, nachträgliche Anlage fehlender Notes, geänderte Chunk-Grenzen.
**Parameter:**
- `--out PATH` : Zielverzeichnis (Default: `./test_vault`)
- `--force` : Existierenden Ordner löschen und neu anlegen
2025-10-06 14:22:47 +02:00
- `--with-missing` : Optional – auch die `missing-note` gleich anlegen
2025-09-07 07:46:39 +02:00
2025-09-07 07:48:59 +02:00
**Hinweise für Tests**
2025-10-06 14:22:47 +02:00
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.
2025-09-07 07:48:59 +02:00
2025-10-06 14:22:47 +02:00
**Kompatibilität:**
- `note.schema.json`: `created`/`updated` sind Strings.
2025-09-07 07:48:59 +02:00
2025-09-07 07:46:39 +02:00
**Beispiele:**
python3 -m scripts.make_test_vault --out ./test_vault --force
python3 -m scripts.make_test_vault --out ./test_vault --force --with-missing
---
2025-10-06 14:22:47 +02:00
## 2) Import in Qdrant
2025-09-07 07:46:39 +02:00
2025-10-06 14:22:47 +02:00
### `scripts/import_markdown.py`
2025-09-07 07:46:39 +02:00
**Zweck:**
2025-10-06 14:22:47 +02:00
Importiert Notes/Chunks/Edges aus einem Vault nach Qdrant.
- validiert Frontmatter
- chunked Inhalte + Embeddings
- erzeugt Edges (`references`, `references_at`, `backlink`, `next`, `prev`, `belongs_to`)
- erkennt geänderte Dateien **modusgesteuert** (Body/Frontmatter/Full)
2025-09-07 07:46:39 +02:00
- optional: Purge der alten Chunks/Edges pro Note
**Parameter:**
- `--vault PATH` : (Pflicht) Vault-Verzeichnis
2025-10-06 14:22:47 +02:00
- `--apply` : Änderungen wirklich durchführen (ohne: Dry-Run)
2025-09-07 07:46:39 +02:00
- `--purge-before-upsert` : Vor Upsert alte Chunks/Edges **nur der geänderten Notes** löschen
2025-10-06 14:22:47 +02:00
- `--prefix STR` : überschreibt `COLLECTION_PREFIX`
- `--note-id ID` : nur eine bestimmte Note importieren
- `--note-scope-refs` : zusätzlich **note-weite** `references` erzeugen (nicht nur chunk-weise)
- `--baseline-modes` : berechne & speichere Hash-Signaturen für **alle** Modi (`Body`, `Frontmatter`, `Full`) als Baseline
**Erwartetes Verhalten:**
- Unveränderte Notes → `"changed": false`, Entscheidung: `apply-skip-unchanged` (bei `--apply`)
- Geänderte Notes → `"changed": true` (abhängig von `MINDNET_HASH_COMPARE`)
- Idempotenz: mehrfacher Lauf ohne Änderungen erzeugt **keine** neuen Punkte
- Baseline: Bei `--baseline-modes` erscheinen Felder wie `hash_signature`, `hash_fulltext`, ggf. `hash_frontmatter` und `needs_baseline_for_mode: false` bei Folgeläufen.
2025-09-07 07:46:39 +02:00
**Beispiele:**
2025-10-06 14:22:47 +02:00
# Dry-Run (zeigt Änderungen, schreibt NICHT)
python3 -m scripts.import_markdown --vault ./vault --prefix mindnet
# Apply + gezielte Vorreinigung pro geänderter Note
python3 -m scripts.import_markdown --vault ./vault --prefix mindnet --apply --purge-before-upsert
# Baseline-Signaturen aller Modi vorhalten
python3 -m scripts.import_markdown --vault ./vault --apply --baseline-modes
**Hash-Modi in der Praxis:**
- `MINDNET_HASH_COMPARE=Body` → Änderungen im Body werden erkannt; reine Frontmatter-Änderungen bleiben **ohne Effekt**.
- `MINDNET_HASH_COMPARE=Frontmatter` → nur Frontmatter maßgeblich.
- `MINDNET_HASH_COMPARE=Full` → beide Anteile zählen.
2025-09-07 07:46:39 +02:00
---
2025-10-06 14:22:47 +02:00
## 3) Konsistenzprüfungen
2025-09-07 07:46:39 +02:00
2025-10-06 14:22:47 +02:00
### `scripts/audit_vault_vs_qdrant.py`
2025-09-07 07:46:39 +02:00
**Zweck:**
2025-10-06 14:22:47 +02:00
Vergleicht Vault-Inhalte mit Qdrant.
- Zählt Notes/Chunks/Edges
- Verifiziert Anzahl Wikilinks vs. Edges
- Meldet Deltas (z. B. `references` im Vault vs. in Qdrant)
2025-09-07 07:46:39 +02:00
**Parameter:**
- `--vault PATH` : Vault-Verzeichnis
- `--prefix STR` : Prefix für Qdrant-Collections (Default: `mindnet`)
**Beispiel:**
python3 -m scripts.audit_vault_vs_qdrant --vault ./vault --prefix mindnet
2025-10-06 14:22:47 +02:00
### `scripts/validate_edges.py`
2025-09-07 07:46:39 +02:00
**Zweck:**
2025-10-06 14:22:47 +02:00
Prüft die Edges-Collection in Qdrant.
- Zählt Edges pro Typ (`references`, `references_at`, `backlink`, `next`, `prev`, `belongs_to`)
- Kontrolliert Invarianten (z. B. jede `references` hat einen `backlink`)
- Listet `unresolved` Edges auf
2025-09-07 07:46:39 +02:00
**Parameter:**
- `--prefix STR` : Prefix für Qdrant-Collections
- `--details` : Detailausgabe mit Beispielen
**Beispiel:**
python3 -m scripts.validate_edges --prefix mindnet --details
---
2025-10-06 14:22:47 +02:00
## 4) Export Qdrant → Markdown (Vault)
### `scripts/export_markdown.py`
**Zweck:**
Exportiert Notes + rekonstruierten Body in einen Zielordner.
- Pfade werden **relativ** aus `note.payload.path` abgeleitet (führende `/` entfernt, Backslashes → Slashes; Unicode-NFC empfohlen)
- **Body-Rekonstruktion** priorisiert:
1. `fulltext` (falls in Note-Payload vorhanden)
2. sonst **Chunks**: Sortierung `seq` → `chunk_index` → Nummer in `chunk_id`; **nur `text`** (Overlap bereits entfernt)
- `--prefix` (CLI) wird unterstützt (oder ENV `COLLECTION_PREFIX`)
**Parameter:**
- `--out PATH` : Ziel-Root (muss existieren)
- `--overwrite` : vorhandene Dateien überschreiben
- `--note-id ID` : nur eine bestimmte Note exportieren
- `--prefix STR` : überschreibt `COLLECTION_PREFIX`
- `--include-edges {none,footer,yaml}` *(optional, falls aktiviert)*: Edges als YAML-Liste im Frontmatter oder im Footer beilegen
**Beispiele:**
export COLLECTION_PREFIX="mindnet"
python3 -m scripts.export_markdown --out ./_exportVault
# Nur eine bestimmte Note:
python3 -m scripts.export_markdown --out ./_exportVault --note-id 20250821-architektur-ki-trainerassistent-761cfe
# Existierende Dateien überschreiben:
python3 -m scripts.export_markdown --out ./_exportVault --overwrite
---
## 5) Qdrant zurücksetzen
2025-09-07 07:46:39 +02:00
2025-10-06 14:22:47 +02:00
### `scripts/reset_qdrant.py`
2025-09-07 07:46:39 +02:00
**Zweck:**
2025-10-06 14:22:47 +02:00
Setzt die Qdrant-Collections zurück.
- `wipe`: löscht Collections komplett (inkl. Schema)
- `truncate`: löscht nur Inhalte, behält Collections
- `truncate-edges`: löscht nur Punkte in `*_edges`
2025-09-07 07:46:39 +02:00
**Parameter:**
2025-10-06 14:22:47 +02:00
- `--mode {wipe,truncate,truncate-edges}`
- `--prefix STR` : Prefix der Collections (Default: `mindnet`)
- `--yes` : Automatische Bestätigung
- `--dry-run` : Nur anzeigen, nicht ausführen
2025-09-07 07:46:39 +02:00
**Beispiele:**
2025-10-06 14:22:47 +02:00
python3 -m scripts.reset_qdrant --mode truncate-edges --prefix mindnet
2025-09-07 07:46:39 +02:00
python3 -m scripts.reset_qdrant --mode truncate --prefix mindnet --yes
python3 -m scripts.reset_qdrant --mode wipe --prefix mindnet --yes
---
2025-10-06 14:22:47 +02:00
## 6) Diagnose & Tools
2025-09-07 07:46:39 +02:00
2025-10-06 14:22:47 +02:00
### `scripts/diagnose_changed.py`
2025-09-07 07:46:39 +02:00
**Zweck:**
2025-10-06 14:22:47 +02:00
Prüft, ob Datei-Hashes (`sha256`) mit gespeicherten `hash_*` in Qdrant übereinstimmen.
Hilft, wenn der Importer zu viele Dateien als „changed“ erkennt oder Moduswechsel geplant sind.
2025-09-07 07:46:39 +02:00
**Parameter:**
- `--vault PATH` : Vault-Verzeichnis
- `--prefix STR` : Prefix (Default: `mindnet`)
- `--note-id ID` : Nur bestimmte Note prüfen
- `--all` : Alle Notes prüfen
**Beispiel:**
python3 -m scripts.diagnose_changed --vault ./vault --prefix mindnet --all
2025-10-06 14:22:47 +02:00
### `scripts/resolve_unresolved_references.py`
2025-09-07 07:46:39 +02:00
**Zweck:**
2025-10-06 14:22:47 +02:00
Prüft offene Wikilinks (`status=unresolved`) und fügt Edges nach, wenn inzwischen passende Notizen existieren.
Ersetzt `unresolved` durch gültige `references`/`backlink`.
2025-09-07 07:46:39 +02:00
**Parameter:**
- `--prefix STR` : Prefix für Qdrant-Collections
- `--apply` : Änderungen wirklich ausführen (sonst nur Vorschau)
**Beispiele:**
python3 -m scripts.resolve_unresolved_references --prefix mindnet
python3 -m scripts.resolve_unresolved_references --prefix mindnet --apply
---
2025-10-06 14:22:47 +02:00
## 7) Parser-Verhalten (robust & abwärtskompatibel)
- Der Parser liest Markdown **fehlertolerant** (UTF-8 mit Fallbacks), extrahiert YAML-Frontmatter und Body.
- Keine harten Abhängigkeiten von alten Regex-Symbolen (`FRONTMATTER_RE` entfällt zugunsten interner Marker).
- `read_markdown(path)` gibt `(frontmatter_dict, body_str)` zurück.
- **Sonderfälle aus Fremd-Tools** (z. B. Silverbullet-Dateien wie `CONFIG.md`, `index.md`) werden **nicht importiert**, sofern sie nicht zum Vault gehören.
---
## 8) Chunk-Payload (Fenster vs. Kern)
2025-09-07 07:46:39 +02:00
2025-10-06 14:22:47 +02:00
- **`window`** = kontextualisierter Fenster-Text (mit linkem Overlap)
- **`text`** = **Kerntext** ohne das vom vorherigen Chunk übernommene Overlap
- Felder: `start`, `end`, `overlap_left`, `overlap_right`, `chunk_index`, `seq`, `path`, `section_title`, `section_path`, `token_count` (falls vorhanden)
- **Fallback (synthetisch):** Falls der Chunker **keinen** Overlap-Fenstertext liefert, erzeugt die Payload-Schicht Fenster mit typgerechtem Overlap aus `chunk_config.get_sizes(type)['overlap']` (unterer Wert).
- **Edges** werden aus `window` abgeleitet (um Links an Chunk-Grenzen nicht zu verlieren); der **Export** rekonstruiert den Body aus `text` (Overlap-frei).
2025-09-07 07:46:39 +02:00
2025-10-06 14:22:47 +02:00
---
## 9) Edge-Modell & IDs
- Collections:
`*_notes` (optional Vektor / Nullvektor), `*_chunks` (384-d Embeddings), `*_edges` (1-d Dummy-Vektor)
- **Deterministische IDs** (UUIDv5 / stabile Keys):
- `note_id` stabil aus Frontmatter/Slug
- `chunk_id` i. d. R. `note_id#<n>`
- `edge_id` stabil aus `(kind, source_id, target_id, seq)`
- Kantenarten: `references`, `references_at`, `backlink`, `next`, `prev`, `belongs_to`
- `unresolved` wird gekennzeichnet und kann per Resolver später aufgelöst werden.
---
## 10) Tests & Qualitätssicherung
**Tests unter `tests/`**
- `check_chunks_window_vs_text.py` – vergleicht je Chunk `window` vs. `text`, schätzt Overlap
- `compare_vaults.py` – rekursiver Vault-Vergleich (Body/Frontmatter/All, Key: auto/id/title/filename), Unicode-NFC-robust
- `verify_chunks_integrity.py` – prüft, ob Rekonstruktion aus Chunks (`text`) zu `fulltext` bzw. zum Vault-Body passt
- `list_md_seen_by_importer.py` – zeigt, welche `.md` der Importer sieht (inkl. Gründe/Filter)
- `inspect_one_note.py` – Parser-Diagnose für eine konkrete Datei
- `run_e2e_roundtrip.sh` – End-to-End: Reset → Import → Audit → (optional) Hash-Reporter → Export → Vergleich
**Typische Aufrufe:**
# Overlap-Qualität (Fenster vs. Kern)
python3 tests/check_chunks_window_vs_text.py --prefix "$COLLECTION_PREFIX"
# Roundtrip-Vergleich (rekursiv)
python3 tests/compare_vaults.py --src ./vault --dst ./_exportVault --focus body
# Chunks-Rekonstruktion (gegen Vault-Body)
python3 tests/verify_chunks_integrity.py --prefix "$COLLECTION_PREFIX" --vault ./vault
---
## 11) Typische Workflows
**A) Clean-Start mit Test-Vault**
python3 -m scripts.make_test_vault --out ./test_vault --force
2025-09-07 07:46:39 +02:00
python3 -m scripts.reset_qdrant --mode truncate --prefix mindnet --yes
2025-10-06 14:22:47 +02:00
python3 -m scripts.import_markdown --vault ./test_vault --prefix mindnet
python3 -m scripts.import_markdown --vault ./test_vault --prefix mindnet --apply --purge-before-upsert
python3 -m scripts.audit_vault_vs_qdrant --vault ./test_vault --prefix mindnet
python3 -m scripts.validate_edges --prefix mindnet --details
export COLLECTION_PREFIX="mindnet"
python3 -m scripts.export_markdown --out ./_exportVault
2025-09-07 07:46:39 +02:00
2025-10-06 14:22:47 +02:00
**B) Änderungs-Propagation & Idempotenz**
2025-09-07 07:46:39 +02:00
2025-10-06 14:22:47 +02:00
python3 -m scripts.import_markdown --vault ./test_vault --prefix mindnet
python3 -m scripts.import_markdown --vault ./test_vault --prefix mindnet --apply --purge-before-upsert
python3 -m scripts.audit_vault_vs_qdrant --vault ./test_vault --prefix mindnet
python3 -m scripts.validate_edges --prefix mindnet --details
python3 -m scripts.import_markdown --vault ./test_vault --prefix mindnet
2025-09-07 07:46:39 +02:00
2025-10-06 14:22:47 +02:00
**C) Unresolved Links lösen**
2025-09-07 07:46:39 +02:00
2025-10-06 14:22:47 +02:00
python3 -m scripts.import_markdown --vault ./test_vault --apply --prefix mindnet
2025-09-07 07:46:39 +02:00
python3 -m scripts.resolve_unresolved_references --prefix mindnet --apply
python3 -m scripts.validate_edges --prefix mindnet --details
2025-10-06 14:22:47 +02:00
**D) Export & Roundtrip (Produkt-Vault)**
2025-09-07 07:46:39 +02:00
2025-10-06 14:22:47 +02:00
export COLLECTION_PREFIX="mindnet"
python3 -m scripts.import_markdown --vault ./vault --apply --purge-before-upsert --prefix "$COLLECTION_PREFIX"
python3 -m scripts.export_markdown --out ./_exportVault --prefix "$COLLECTION_PREFIX"
python3 tests/compare_vaults.py --src ./vault --dst ./_exportVault --focus body
---
## 12) Troubleshooting (kurz)
- **Importer markiert alle als changed (Moduswechsel):**
→ `--baseline-modes` einmalig laufen lassen; sicherstellen: `MINDNET_HASH_COMPARE` passt zum Ziel.
- **Edges verschwinden / nur 1 Edge sichtbar:**
→ `app/core/qdrant_points.py` muss Edge-Payload normalisieren (Schema Alt/Neu) und `edge_id` eindeutig bilden.
- **Export ohne Body / falsches Zielverzeichnis:**
→ Exporter nutzt relativierte Pfade und rekonstruiert Body aus `fulltext` oder Chunks (`text`). ENV/CLI `--prefix` beachten.
- **Parser-Fehler (UTF-8):**
→ Neuer Parser arbeitet mit Fallbacks; mit `tests/inspect_one_note.py` prüfen, was ankommt.
- **„Fehlende“ Dateien im Vergleich:**
→ Prüfe, ob Dateien **wirklich zum Vault gehören** (z. B. Silverbullet-Artefakte `CONFIG.md`, `index.md` ausblenden).
---
## 13) Hinweise zu Silverbullet-Dateien
- Dateien wie `CONFIG.md` oder `index.md`, die **nicht** zum inhaltlichen Vault gehören, werden **nicht importiert** und erscheinen daher nicht im Export-Roundtrip.
- Diese Dateien bitte vom produktiven Vault trennen oder im Vergleich (`tests/compare_vaults.py