mindnet/docs/Handbuch.md
Lars 66adc6a354
All checks were successful
Deploy mindnet to llm-node / deploy (push) Successful in 2s
docs/Handbuch.md aktualisiert
2025-10-06 14:22:47 +02:00

350 lines
14 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 📘 Mindnet Skript-Handbuch (aktualisiert)
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.
---
## 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**
- `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
source .venv/bin/activate
**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**.
---
## 1) Vault anlegen (für Tests)
### `scripts/make_test_vault.py`
**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
- `--with-missing` : Optional auch die `missing-note` gleich anlegen
**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.
**Kompatibilität:**
- `note.schema.json`: `created`/`updated` sind Strings.
**Beispiele:**
python3 -m scripts.make_test_vault --out ./test_vault --force
python3 -m scripts.make_test_vault --out ./test_vault --force --with-missing
---
## 2) Import in Qdrant
### `scripts/import_markdown.py`
**Zweck:**
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)
- optional: Purge der alten Chunks/Edges pro Note
**Parameter:**
- `--vault PATH` : (Pflicht) Vault-Verzeichnis
- `--apply` : Änderungen wirklich durchführen (ohne: Dry-Run)
- `--purge-before-upsert` : Vor Upsert alte Chunks/Edges **nur der geänderten Notes** löschen
- `--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.
**Beispiele:**
# 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.
---
## 3) Konsistenzprüfungen
### `scripts/audit_vault_vs_qdrant.py`
**Zweck:**
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)
**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
### `scripts/validate_edges.py`
**Zweck:**
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
**Parameter:**
- `--prefix STR` : Prefix für Qdrant-Collections
- `--details` : Detailausgabe mit Beispielen
**Beispiel:**
python3 -m scripts.validate_edges --prefix mindnet --details
---
## 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
### `scripts/reset_qdrant.py`
**Zweck:**
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`
**Parameter:**
- `--mode {wipe,truncate,truncate-edges}`
- `--prefix STR` : Prefix der Collections (Default: `mindnet`)
- `--yes` : Automatische Bestätigung
- `--dry-run` : Nur anzeigen, nicht ausführen
**Beispiele:**
python3 -m scripts.reset_qdrant --mode truncate-edges --prefix mindnet
python3 -m scripts.reset_qdrant --mode truncate --prefix mindnet --yes
python3 -m scripts.reset_qdrant --mode wipe --prefix mindnet --yes
---
## 6) Diagnose & Tools
### `scripts/diagnose_changed.py`
**Zweck:**
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.
**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
### `scripts/resolve_unresolved_references.py`
**Zweck:**
Prüft offene Wikilinks (`status=unresolved`) und fügt Edges nach, wenn inzwischen passende Notizen existieren.
Ersetzt `unresolved` durch gültige `references`/`backlink`.
**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
---
## 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)
- **`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).
---
## 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
python3 -m scripts.reset_qdrant --mode truncate --prefix mindnet --yes
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
**B) Änderungs-Propagation & Idempotenz**
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
**C) Unresolved Links lösen**
python3 -m scripts.import_markdown --vault ./test_vault --apply --prefix mindnet
python3 -m scripts.resolve_unresolved_references --prefix mindnet --apply
python3 -m scripts.validate_edges --prefix mindnet --details
**D) Export & Roundtrip (Produkt-Vault)**
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