Die Ingestion transformiert Markdown in den Graphen. Entrypoint: `scripts/import_markdown.py` (CLI) oder `routers/ingest.py` (API). Seit v2.9 nutzt dieser Prozess ein hocheffizientes **Two-Pass-Verfahren**, um globale Kontext-Informationen für die semantische Validierung bereitzustellen, ohne die Idempotenz oder die Change-Detection zu verletzen.
Der Prozess ist **asynchron**, **idempotent** und wird nun in zwei logische Durchläufe (Passes) unterteilt, um die semantische Genauigkeit zu maximieren.
* **Hard Skip Rule:** Wenn `status` in `['system', 'template', 'archive', 'hidden']` ist, wird die Datei für das Deep-Processing übersprungen, ihre Metadaten werden jedoch für den Kontext-Cache erfasst.
* **Traffic Control:** Nutzung der neutralen `clean_llm_text` Funktion zur Bereinigung von Steuerzeichen (<s>, [OUT]).
* **Deep Fallback (v2.11.14):** Erkennt "Silent Refusals". Liefert die Cloud keine verwertbaren Kanten, wird ein lokaler Fallback via Ollama erzwungen.
12.**Inline-Kanten finden:** Parsing von `[[rel:...]]` und Callouts.
13.**Alias-Auflösung & Kanonisierung (WP-22):**
* Jede Kante wird via `EdgeRegistry` normalisiert (z.B. `basiert_auf` -> `based_on`).
> Das Flag `--purge-before-upsert` nutzt nun `ingestion_db.purge_artifacts`. Es ist kritisch, um "Geister-Chunks" (verwaiste Daten nach Textlöschung) konsistent aus den spezialisierten Collections zu entfernen.
Die Strategie `by_heading` implementiert seit v3.9.9 das **"Pack-and-Carry-Over"** Verfahren (Regel 1-3), um Sektions-Überschriften und deren Inhalte atomar in Chunks zu halten.
* Jede Überschrift (`<= split_level`) erzwingt einen neuen Chunk.
* *Merge-Check:* Wenn der vorherige Chunk leer war (nur Überschriften), wird gemergt.
* *Safety Net:* Wird ein Abschnitt zu lang (> `max` Token), wird auch ohne Überschrift getrennt.
**Modus "Soft" (`strict_heading_split: false`):**
* **Hierarchie-Check:** Überschriften *oberhalb* des Split-Levels erzwingen **immer** einen Split.
* **Füll-Logik:** Überschriften *auf* dem Split-Level lösen nur dann einen neuen Chunk aus, wenn der aktuelle Chunk die `target`-Größe erreicht hat.
* **Pack-and-Carry-Over:** Wenn ein Abschnitt zu groß ist, wird er intelligent zerlegt, wobei der Rest (mit Überschrift) zurück in die Queue gelegt wird.
* *Safety Net:* Auch hier greift das `max` Token Limit.
### 3.3 Registry-First Profiling (v2.13.12)
Seit v2.13.12 nutzt der `IngestionService` die korrekte Hierarchie zur Ermittlung des Chunking-Profils:
2.**`types.yaml` Typ-Config** - Profil basierend auf `type`
3.**Global Defaults** - Fallback auf `sliding_standard`
**Wichtig:** Ein Hard-Fallback auf `sliding_standard` erfolgt nur noch, wenn keine Konfiguration existiert. Dies stellt sicher, dass Note-Typen wie `value` automatisch das korrekte Profil (z.B. `structured_smart_edges_strict`) erhalten.
### 3.4 Deterministic Hashing (v2.13.12)
Der `full`-Hash inkludiert nun alle strategischen Parameter (z.B. `split_level`, `strict_heading_split`), sodass Konfigurationsänderungen im Frontmatter zwingend einen Re-Import auslösen.
**Impact:** Änderungen an Chunking-Parametern werden zuverlässig erkannt, auch wenn der Text unverändert bleibt.
**1. Registry Review (WP-14):** Prüfung der `data/logs/unknown_edges.jsonl`. Die zentrale Auflösung via `registry.py` verhindert Inkonsistenzen zwischen Import und Retrieval.
**2. Mistral-safe Parsing:** Automatisierte Bereinigung von LLM-Antworten in `ingestion_validation.py`. Stellt sicher, dass semantische Entscheidungen ("YES"/"NO") nicht durch technische Header verfälscht werden.
**3. Profilgesteuerte Validierung (WP-25a):** Die semantische Kanten-Validierung erfolgt zwingend über das MoE-Profil `ingest_validator` (Temperature 0.0 für Determinismus). Dies gewährleistet konsistente binäre Entscheidungen (YES/NO) unabhängig von der globalen Provider-Konfiguration.
**3. Purge Integrity:** Validierung, dass vor jedem Upsert alle assoziierten Artefakte in den Collections `{prefix}_chunks` und `{prefix}_edges` gelöscht wurden, um Daten-Duplikate zu vermeiden.