mindnet/docs/03_Technical_References/AUDIT_SYSTEM_INTEGRITY_V4.5.8.md
Lars 742792770c Implement Phase 3 Agentic Edge Validation in ingestion_processor.py and related documentation updates
Introduce a new method for persisting rejected edges for audit purposes, enhancing traceability and validation logic. Update the decision engine to utilize a generic fallback template for improved error handling during LLM validation. Revise documentation across multiple files to reflect the new versioning, context, and features related to Phase 3 validation, including automatic mirror edges and note-scope zones. This update ensures better graph integrity and validation accuracy in the ingestion process.
2026-01-12 07:45:54 +01:00

20 KiB

System-Integrity & Regression-Audit (v4.5.8)

Datum: 2026-01-XX
Version: v4.5.8
Status: Audit abgeschlossen
Auditor: AI Assistant (Auto)

Kontext

Nach umfangreichen Änderungen in WP24c (insbesondere v4.5.7/8) wurde ein vollständiges System-Integrity & Regression-Audit durchgeführt, um sicherzustellen, dass keine unbeabsichtigten Beeinträchtigungen oder "Logic-Drift" eingeführt wurden.

Audit-Scope

  1. WP-22 Scoring Integrität: Prüfung der mathematischen Berechnung des total_score
  2. WP-25a/b MoE & Prompts: Verifizierung der Profil-Ladung und MoE-Kaskade
  3. Deduplizierungs-Logik: Prüfung der De-Duplizierung von Kanten
  4. Phase 3 Validierungs-Gate: Verifizierung der neuen Validierungs-Logik
  5. Note-Scope Kontext-Optimierung: Prüfung der Kontext-Optimierung

1. WP-22 Scoring Integrität

Prüfpunkt: Hat die Einführung von candidate: oder verified Status Auswirkungen auf die mathematische Berechnung des total_score?

Status: KEIN PROBLEM

Ergebnis:

  • candidate: und verified sind KEINE Status-Werte für die Scoring-Funktion
  • Sie sind Präfixe in rule_id und provenance für Kanten (Edge-Metadaten)
  • Die get_status_multiplier() Funktion in retriever_scoring.py behandelt ausschließlich:
    • stable: 1.2 (Multiplikator)
    • active: 1.0 (Standard)
    • draft: 0.5 (Dämpfung)
  • Die mathematische Formel in compute_wp22_score() bleibt vollständig unangetastet

Code-Referenz:

  • app/core/retrieval/retriever_scoring.py Zeile 49-63: get_status_multiplier()
  • app/core/retrieval/retriever_scoring.py Zeile 65-128: compute_wp22_score()

Bewertung: Die Scoring-Mathematik ist vollständig isoliert von den Edge-Metadaten (candidate:, verified). Keine Regression festgestellt.


2. WP-25a/b MoE & Prompts

Prüfpunkt 2a: Werden die korrekten Profile aus llm_profiles.yaml geladen?

Status: FUNKTIONIERT KORREKT

Ergebnis:

  • LLMService._load_llm_profiles() lädt Profile aus llm_profiles.yaml (nicht prompts.yaml)
  • Pfad wird korrekt aus Settings geladen: LLM_PROFILES_PATH (Default: config/llm_profiles.yaml)
  • Profile werden im __init__ geladen und im Instanz-Attribut self.profiles gespeichert
  • Fehlerbehandlung vorhanden: Bei fehlender Datei wird leeres Dict zurückgegeben mit Warnung

Code-Referenz:

  • app/services/llm_service.py Zeile 87-100: _load_llm_profiles()
  • app/services/llm_service.py Zeile 36: Initialisierung in __init__

Bewertung: Profil-Ladung funktioniert korrekt. Keine Regression.

Prüfpunkt 2b: Nutzt die neue Validierungs-Logik in Phase 3 die bestehende MoE-Kaskade?

Status: FUNKTIONIERT KORREKT

Ergebnis:

  • Phase 3 Validierung nutzt profile_name="ingest_validator" (siehe ingestion_processor.py Zeile 345)
  • LLMService.generate_raw_response() unterstützt vollständig die MoE-Kaskade:
    • Profil-Auflösung aus llm_profiles.yaml (Zeile 151-161)
    • Fallback-Kaskade via fallback_profile (Zeile 214-227)
    • visited_profiles Schutz verhindert Endlosschleifen (Zeile 214)
    • Rekursiver Aufruf mit visited_profiles Parameter (Zeile 226)
  • Die Kaskade wird nicht umgangen, sondern vollständig genutzt

Code-Referenz:

  • app/core/ingestion/ingestion_processor.py Zeile 340-346: Phase 3 Validierung
  • app/services/llm_service.py Zeile 150-227: MoE-Kaskade Implementierung
  • config/llm_profiles.yaml: Profil-Definitionen mit fallback_profile

Bewertung: MoE-Kaskade wird korrekt genutzt. Keine Regression.

Prüfpunkt 2c: Werden Prompts korrekt aus prompts.yaml geladen?

Status: FUNKTIONIERT KORREKT

Ergebnis:

  • LLMService._load_prompts() lädt Prompts aus prompts.yaml (Zeile 76-85)
  • DecisionEngine nutzt prompt_key und variables für Lazy-Loading (Zeile 108-113, 309-315)
  • LLMService.get_prompt() unterstützt Hierarchie: Model-ID → Provider → Default (Zeile 102-123)
  • Prompt-Formatierung erfolgt via template.format(**(variables or {})) (Zeile 179)

Code-Referenz:

  • app/services/llm_service.py Zeile 76-85: _load_prompts()
  • app/services/llm_service.py Zeile 102-123: get_prompt() mit Hierarchie
  • app/core/retrieval/decision_engine.py Zeile 107-113: Intent-Routing mit prompt_key
  • app/core/retrieval/decision_engine.py Zeile 309-315: Finale Synthese mit prompt_key

Bewertung: Prompt-Ladung funktioniert korrekt. Keine Regression.


3. Deduplizierungs-Logik

Prüfpunkt: Gefährden die Änderungen an all_chunk_callout_keys in v4.5.7/8 die gewollte De-Duplizierung von Kanten (WP-24c)?

Status: FUNKTIONIERT KORREKT

Ergebnis:

  • all_chunk_callout_keys wird VOR jeder Verwendung initialisiert (Zeile 531-533)
  • Initialisierung erfolgt VOR Phase 1 (Sammeln aus candidate_pool) und VOR Phase 2 (Chunk-Verarbeitung)
  • Die De-Duplizierungs-Logik ist vollständig intakt:
    • Phase 1: Sammeln aller explicit:callout Keys aus candidate_pool (Zeile 657-697)
    • Phase 2: Prüfung gegen all_chunk_callout_keys vor Erstellung neuer Callout-Kanten (Zeile 768)
    • Globaler Scan: Nutzung von all_chunk_callout_keys als Ausschlusskriterium (Zeile 855)
  • LLM-Validierungs-Zonen: Callouts werden korrekt zu all_chunk_callout_keys hinzugefügt (Zeile 615)

Code-Referenz:

  • app/core/graph/graph_derive_edges.py Zeile 531-533: Initialisierung
  • app/core/graph/graph_derive_edges.py Zeile 657-697: Phase 1 (Sammeln)
  • app/core/graph/graph_derive_edges.py Zeile 768: Phase 2 (Prüfung)
  • app/core/graph/graph_derive_edges.py Zeile 855: Globaler Scan (Ausschluss)

Bewertung: De-Duplizierungs-Logik ist intakt. Keine Regression.


4. Phase 3 Validierungs-Gate

Prüfpunkt: Ist das Phase 3 Validierungs-Gate korrekt implementiert und nutzt es die MoE-Kaskade?

Status: GEWOLLTE ÄNDERUNG (v4.5.8)

Ergebnis:

  • Phase 3 Validierung ist korrekt implementiert in ingestion_processor.py (Zeile 274-371)
  • Trigger-Kriterium: Kanten mit rule_id ODER provenance beginnend mit "candidate:" (Zeile 292)
  • Validierung: Nutzt validate_edge_candidate() mit profile_name="ingest_validator" (Zeile 340-346)
  • Erfolg: Entfernt candidate: Präfix aus rule_id und provenance (Zeile 349-357)
  • Ablehnung: Kanten werden zu rejected_edges hinzugefügt und nicht weiterverarbeitet (Zeile 362-363)
  • MoE-Kaskade: Wird vollständig genutzt via llm_service.generate_raw_response() (siehe Prüfpunkt 2b)

Code-Referenz:

  • app/core/ingestion/ingestion_processor.py Zeile 274-371: Phase 3 Implementierung
  • app/core/ingestion/ingestion_validation.py Zeile 24-91: validate_edge_candidate()

Bewertung: Phase 3 Validierungs-Gate ist korrekt implementiert. Gewollte Änderung, keine Regression.


5. Note-Scope Kontext-Optimierung

Prüfpunkt: Ist die Note-Scope Kontext-Optimierung korrekt implementiert?

Status: GEWOLLTE ÄNDERUNG (v4.5.8)

Ergebnis:

  • Kontext-Optimierung ist korrekt implementiert in Phase 3 Validierung (Zeile 311-326)
  • Note-Scope: Verwendet note_summary oder note_text (aggregierter Kontext) (Zeile 314-316)
  • Chunk-Scope: Versucht spezifischen Chunk-Text zu finden, sonst Note-Text (Zeile 318-326)
  • Note-Summary: Wird aus Top 5 Chunks erstellt (Zeile 282)
  • Note-Text: Wird aus markdown_body oder aggregiert aus allen Chunks erstellt (Zeile 280)

Code-Referenz:

  • app/core/ingestion/ingestion_processor.py Zeile 278-282: Note-Summary/Text Erstellung
  • app/core/ingestion/ingestion_processor.py Zeile 311-326: Kontext-Optimierung

Bewertung: Note-Scope Kontext-Optimierung ist korrekt implementiert. Gewollte Änderung, keine Regression.


6. Weitere Prüfungen

6.1 Edge-Registry Integration

Status: FUNKTIONIERT KORREKT

Ergebnis:

  • Edge-Registry wird korrekt für Typ-Auflösung genutzt (Zeile 383 in ingestion_processor.py)
  • Symmetrie-Generierung nutzt edge_registry.get_inverse() (Zeile 397)
  • Keine Regression festgestellt

6.2 Context-Reuse Logik

Status: FUNKTIONIERT KORREKT

Ergebnis:

  • Context-Reuse ist in decision_engine.py implementiert (Zeile 154-196)
  • Bei Kompressions-Fehlern wird Original-Content zurückgegeben (Zeile 232-235)
  • Bei Synthese-Fehlern wird Fallback mit vorhandenem Context genutzt (Zeile 328-365)
  • Keine Regression festgestellt

6.3 Prompt-Template Validierung

Status: FUNKTIONIERT KORREKT

Ergebnis:

  • Prompt-Validierung in llm_service.py prüft auf leere Templates (Zeile 172-175)
  • Fehlerbehandlung vorhanden: ValueError bei fehlendem oder leerem prompt_key
  • Keine Regression festgestellt

Zusammenfassung

Keine Regressionen festgestellt

Alle geprüften Funktionen arbeiten korrekt und entsprechen den ursprünglichen WP-Spezifikationen:

  1. WP-22 Scoring: Mathematik bleibt unangetastet
  2. WP-25a/b MoE & Prompts: Profile und Prompts werden korrekt geladen, MoE-Kaskade funktioniert
  3. Deduplizierungs-Logik: all_chunk_callout_keys funktioniert korrekt
  4. Phase 3 Validierung: Korrekt implementiert, nutzt MoE-Kaskade
  5. Note-Scope Kontext-Optimierung: Korrekt implementiert

📋 Gewollte Änderungen (v4.5.8)

Die folgenden Änderungen sind explizit gewollt und stellen keine Regressionen dar:

  1. Phase 3 Validierungs-Gate: Neue Validierungs-Logik für candidate: Kanten
  2. Note-Scope Kontext-Optimierung: Optimierte Kontext-Auswahl für Note-Scope vs. Chunk-Scope Kanten

🔍 Empfehlungen

Keine kritischen Probleme gefunden. Das System ist in einem stabilen Zustand.

Optional (nicht kritisch):

  • Erwägen Sie zusätzliche Unit-Tests für Phase 3 Validierung
  • Dokumentation der candidate:verified Transformation könnte erweitert werden

Audit-Methodik

  1. Code-Analyse: Vollständige Analyse der relevanten Dateien
  2. Semantic Search: Suche nach Verwendungen von candidate:, verified, all_chunk_callout_keys
  3. Grep-Suche: Exakte String-Suche nach kritischen Patterns
  4. Dokumentations-Review: Prüfung der technischen Dokumentation

Geprüfte Dateien:

  • app/core/retrieval/retriever_scoring.py
  • app/services/llm_service.py
  • app/core/retrieval/decision_engine.py
  • app/core/graph/graph_derive_edges.py
  • app/core/ingestion/ingestion_processor.py
  • app/core/ingestion/ingestion_validation.py
  • config/prompts.yaml
  • config/llm_profiles.yaml

7. Zusätzliche Prüfungen & Bekannte Schwachstellen

7.1 Callout-Extraktion aus Edge-Zonen (aus AUDIT_CLEAN_CONTEXT_V4.2.0)

Status: ⚠️ POTENZIELL BEHOBEN (verifizieren erforderlich)

Hintergrund:

  • AUDIT_CLEAN_CONTEXT_V4.2.0 identifizierte ein kritisches Problem: Callouts in Edge-Zonen wurden nicht extrahiert
  • Problem: Callouts wurden nur aus gefilterten Chunks extrahiert, nicht aus Original-Markdown

Aktueller Status:

  • Funktion extract_callouts_from_markdown() existiert in graph_derive_edges.py (Zeile 263-501)
  • Funktion wird in build_edges_for_note() aufgerufen (Zeile 852-864)
  • ⚠️ VERIFIZIERUNG ERFORDERLICH: Prüfen, ob Callouts in LLM-Validierungs-Zonen korrekt extrahiert werden

Code-Referenz:

  • app/core/graph/graph_derive_edges.py Zeile 263-501: extract_callouts_from_markdown()
  • app/core/graph/graph_derive_edges.py Zeile 852-864: Aufruf in build_edges_for_note()

Empfehlung:

  • Test mit Callout in LLM-Validierungs-Zone durchführen
  • Verifizieren, dass Edge in Qdrant _edges Collection existiert
  • Prüfen, ob candidate: Präfix korrekt gesetzt wird

7.2 Rejected Edges Tracking & Monitoring

Status: ⚠️ POTENZIELLE SCHWACHSTELLE

Problem:

  • Phase 3 Validierung lehnt Kanten ab und fügt sie zu rejected_edges hinzu (Zeile 363)
  • rejected_edges werden geloggt, aber nicht persistiert oder analysiert
  • Keine Möglichkeit, abgelehnte Kanten zu überprüfen oder zu debuggen

Konsequenz:

  • Fehlende Transparenz: Keine Nachvollziehbarkeit, warum Kanten abgelehnt wurden
  • Keine Metriken: Keine Statistiken über Ablehnungsrate
  • Schwieriges Debugging: Bei Problemen keine Möglichkeit, abgelehnte Kanten zu analysieren

Code-Referenz:

  • app/core/ingestion/ingestion_processor.py Zeile 363: rejected_edges.append(e)
  • app/core/ingestion/ingestion_processor.py Zeile 370-371: Logging, aber keine Persistierung

Empfehlung:

  • Optional: Persistierung von rejected_edges in Log-Datei oder separater Collection
  • Metriken: Tracking der Ablehnungsrate pro Note/Typ
  • Debug-Modus: Detailliertes Logging der Ablehnungsgründe

7.3 Transiente vs. Permanente Fehler in Phase 3 Validierung

Status: FUNKTIONIERT KORREKT

Ergebnis:

  • validate_edge_candidate() unterscheidet korrekt zwischen transienten und permanenten Fehlern (Zeile 79-91)
  • Transiente Fehler (Netzwerk) → Kante wird erlaubt (Integrität vor Präzision)
  • Permanente Fehler → Kante wird abgelehnt (Graph-Qualität schützen)

Code-Referenz:

  • app/core/ingestion/ingestion_validation.py Zeile 79-91: Fehlerbehandlung

Bewertung: Korrekt implementiert. Keine Regression.


7.4 Note-Scope Kontext-Optimierung: Chunk-Text Fallback

Status: ⚠️ POTENZIELLE SCHWACHSTELLE

Problem:

  • Bei Chunk-Scope Kanten wird versucht, spezifischen Chunk-Text zu finden (Zeile 319-325)
  • Fallback auf note_text, wenn Chunk-Text nicht gefunden wird
  • Risiko: Bei fehlendem Chunk-Text wird Note-Text verwendet, was weniger präzise ist

Code-Referenz:

  • app/core/ingestion/ingestion_processor.py Zeile 318-326: Chunk-Text Suche

Empfehlung:

  • Prüfen, ob Chunk-Text immer verfügbar ist
  • Bei fehlendem Chunk-Text: Warnung loggen
  • Optional: Bessere Fehlerbehandlung für fehlende Chunk-IDs

7.5 LLM-Validierungs-Zonen: Callout-Key Tracking

Status: FUNKTIONIERT KORREKT

Ergebnis:

  • Callouts aus LLM-Validierungs-Zonen werden korrekt zu all_chunk_callout_keys hinzugefügt (Zeile 615)
  • Verhindert Duplikate im globalen Scan
  • Korrekte candidate: Präfix-Setzung

Code-Referenz:

  • app/core/graph/graph_derive_edges.py Zeile 604-616: LLM-Validierungs-Zone Callout-Tracking

Bewertung: Korrekt implementiert. Keine Regression.


7.6 Scope-Aware Edge Retrieval (aus AUDIT_RETRIEVER_V4.1.0)

Status: ⚠️ POTENZIELL BEHOBEN (verifizieren erforderlich)

Hintergrund:

  • AUDIT_RETRIEVER_V4.1.0 identifizierte ein Problem: Retriever suchte nur nach Note-Level Edges, nicht Chunk-Level
  • Problem: Chunk-Scope Edges wurden nicht explizit berücksichtigt

Aktueller Status:

  • ⚠️ VERIFIZIERUNG ERFORDERLICH: Prüfen, ob fetch_edges_from_qdrant Chunk-Level Edges korrekt lädt
  • Dokumentation besagt, dass Optimierungen implementiert wurden

Empfehlung:

  • Test mit Chunk-Scope Edge durchführen
  • Verifizieren, dass Edge im Retrieval-Ergebnis enthalten ist
  • Prüfen, ob chunk_id Filter korrekt funktioniert

7.7 Section-Filtering im Retrieval (aus AUDIT_RETRIEVER_V4.1.0)

Status: ⚠️ POTENZIELL BEHOBEN (verifizieren erforderlich)

Hintergrund:

  • AUDIT_RETRIEVER_V4.1.0 identifizierte fehlende Filterung nach target_section
  • Problem: Section-Links ([[Note#Section]]) wurden nicht präzise gefiltert

Aktueller Status:

  • ⚠️ VERIFIZIERUNG ERFORDERLICH: Prüfen, ob target_section Filter im Retrieval funktioniert
  • Dokumentation besagt, dass Optimierungen implementiert wurden

Empfehlung:

  • Test mit Section-Link durchführen
  • Verifizieren, dass nur relevante Chunks zurückgegeben werden
  • Prüfen, ob QueryRequest.target_section korrekt verwendet wird

7.8 Prompt-Integration: Explanation Layer

Status: ⚠️ UNKLAR (aus AUDIT_CLEAN_CONTEXT_V4.2.0)

Problem:

  • Unklar, ob explanation.related_edges im LLM-Prompt verwendet werden
  • Keine explizite Dokumentation der Prompt-Struktur für RAG-Kontext

Code-Referenz:

  • app/core/retrieval/retriever.py Zeile 150-252: _build_explanation()
  • app/routers/chat.py: Prompt-Verwendung

Empfehlung:

  • Prüfen Sie config/prompts.yaml für interview_template und andere Templates
  • Stellen Sie sicher, dass {related_edges} oder ähnliche Variablen im Prompt verwendet werden
  • Dokumentieren Sie die Prompt-Struktur für RAG-Kontext

7.9 Fallback-Synthese: Hardcodierter Prompt (aus AUDIT_WP25B_CODE_REVIEW)

Status: ⚠️ ARCHITEKTONISCHE INKONSISTENZ

Problem:

  • Fallback-Synthese in decision_engine.py verwendet prompt= statt prompt_key= (Zeile 361)
  • Inkonsistent mit WP25b-Architektur (Lazy-Loading)
  • Keine modell-spezifischen Prompts im Fallback

Code-Referenz:

  • app/core/retrieval/decision_engine.py Zeile 360-363: Hardcodierter Prompt

Empfehlung:

  • Umstellen auf prompt_key="fallback_synthesis" mit variables
  • Konsistenz mit WP25b-Architektur
  • Modell-spezifische Optimierungen auch im Fallback

Schweregrad: 🟡 Mittel (funktional, aber architektonisch inkonsistent)


7.10 Edge-Registry: Unbekannte Kanten

Status: FUNKTIONIERT KORREKT

Ergebnis:

  • Unbekannte Kanten-Typen werden in unknown_edges.jsonl protokolliert
  • Edge-Registry normalisiert Kanten-Typen korrekt
  • Keine Regression festgestellt

Code-Referenz:

  • app/services/edge_registry.py: Edge-Registry Implementierung

Bewertung: Korrekt implementiert. Keine Regression.


8. Zusammenfassung der zusätzlichen Prüfungen

Bestätigt funktionierend:

  1. Transiente vs. Permanente Fehler: Korrekte Unterscheidung
  2. LLM-Validierungs-Zonen Callout-Tracking: Korrekt implementiert
  3. Edge-Registry: Funktioniert korrekt

⚠️ Verifizierung erforderlich:

  1. Callout-Extraktion aus Edge-Zonen: Funktion existiert, aber Verifizierung erforderlich
  2. Scope-Aware Edge Retrieval: Potenziell behoben, Verifizierung erforderlich
  3. Section-Filtering: Potenziell behoben, Verifizierung erforderlich

⚠️ Potenzielle Schwachstellen:

  1. Rejected Edges Tracking: Keine Persistierung oder Metriken
  2. Note-Scope Kontext-Optimierung: Chunk-Text Fallback könnte verbessert werden
  3. Prompt-Integration: Unklar, ob explanation.related_edges verwendet werden
  4. Fallback-Synthese: Architektonische Inkonsistenz (hardcodierter Prompt)

9. Empfohlene Follow-up Prüfungen

9.1 Funktionale Tests

  1. Callout in LLM-Validierungs-Zone:

    • Erstellen Sie eine Notiz mit Callout in ### Unzugeordnete Kanten
    • Verifizieren: Edge existiert in Qdrant mit candidate: Präfix
    • Verifizieren: Edge wird in Phase 3 validiert
  2. Chunk-Scope Edge Retrieval:

    • Erstellen Sie eine Note mit Chunk-Scope Edge
    • Query mit explain=True
    • Verifizieren: Edge erscheint in explanation.related_edges
  3. Section-Link Retrieval:

    • Erstellen Sie einen Section-Link ([[Note#Section]])
    • Query mit target_section="Section"
    • Verifizieren: Nur relevante Chunks werden zurückgegeben

9.2 Metriken & Monitoring

  1. Phase 3 Validierung Metriken:

    • Tracking der Validierungsrate (verified/rejected)
    • Tracking der Ablehnungsgründe
    • Monitoring der LLM-Validierungs-Performance
  2. Edge-Statistiken:

    • Anzahl der candidate: Kanten pro Note
    • Anzahl der verifizierten Kanten pro Note
    • Anzahl der abgelehnten Kanten pro Note

9.3 Dokumentation

  1. Prompt-Struktur:

    • Dokumentieren Sie die Verwendung von explanation.related_edges in Prompts
    • Erstellen Sie Beispiele für RAG-Kontext-Integration
  2. Phase 3 Validierung:

    • Dokumentieren Sie den Validierungs-Prozess
    • Erstellen Sie Troubleshooting-Guide für abgelehnte Kanten

Audit abgeschlossen: System-Integrität bestätigt mit zusätzlichen Prüfungen