audit trail detail
This commit is contained in:
		
							parent
							
								
									5c3c308225
								
							
						
					
					
						commit
						e63ec367a5
					
				@ -1247,6 +1247,99 @@ class AIQueryInterface {
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  createSpecificSummary(data, action, type) {
 | 
			
		||||
    if (!data) return 'Leer';
 | 
			
		||||
    
 | 
			
		||||
    // Action-specific summaries that provide meaningful information
 | 
			
		||||
    switch (action) {
 | 
			
		||||
      case 'selection-decision':
 | 
			
		||||
        if (type === 'input') {
 | 
			
		||||
          if (data.availableTools && Array.isArray(data.availableTools)) {
 | 
			
		||||
            const preview = data.availableTools.slice(0, 5).join(', ');
 | 
			
		||||
            return `${data.totalAvailable || data.availableTools.length} Tools verfügbar: ${preview}${data.availableTools.length > 5 ? '...' : ''}`;
 | 
			
		||||
          }
 | 
			
		||||
          return `${data.totalAvailable || 0} Tools verfügbar`;
 | 
			
		||||
        } else {
 | 
			
		||||
          return `Ausgewählt: ${Array.isArray(data.selectedTools) ? data.selectedTools.join(', ') : 'keine'}`;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
      case 'phase-tool-selection':
 | 
			
		||||
        if (type === 'input') {
 | 
			
		||||
          if (data.availableTools && Array.isArray(data.availableTools)) {
 | 
			
		||||
            return `${data.availableTools.length} Tools für Phase: ${data.availableTools.slice(0, 3).join(', ')}${data.availableTools.length > 3 ? '...' : ''}`;
 | 
			
		||||
          }
 | 
			
		||||
          return `Phase: ${data.phaseName || data.phaseId || 'unbekannt'} (${data.toolCount || 0} verfügbar)`;
 | 
			
		||||
        } else {
 | 
			
		||||
          if (data.selectedTools && Array.isArray(data.selectedTools)) {
 | 
			
		||||
            return `Ausgewählt: ${data.selectedTools.join(', ')}`;
 | 
			
		||||
          }
 | 
			
		||||
          return `${data.selectionCount || 0} Tools ausgewählt (Ø ${data.avgTaskRelevance || 0}% Relevanz)`;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
      case 'similarity-search':
 | 
			
		||||
        if (type === 'input') {
 | 
			
		||||
          return `Suche: "${data.query}" (Schwelle: ${data.threshold})`;
 | 
			
		||||
        } else {
 | 
			
		||||
          if (data.topMatches && Array.isArray(data.topMatches)) {
 | 
			
		||||
            return `${data.resultsCount} Treffer: ${data.topMatches.slice(0, 3).join(', ')}`;
 | 
			
		||||
          }
 | 
			
		||||
          return `${data.resultsCount || 0} Treffer gefunden`;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
      case 'phase-enhancement':
 | 
			
		||||
        if (type === 'input') {
 | 
			
		||||
          return `Phase: ${data.phaseName || data.phaseId} (${data.searchStrategy || 'Standard'})`;
 | 
			
		||||
        } else {
 | 
			
		||||
          const toolsAdded = Array.isArray(data.addedTools) ? data.addedTools : [];
 | 
			
		||||
          return `${data.toolsAddedCount || toolsAdded.length} Tools hinzugefügt: ${toolsAdded.join(', ') || 'keine'}`;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
      case 'ai-decision':
 | 
			
		||||
        if (type === 'input') {
 | 
			
		||||
          return data.prompt ? `KI-Prompt: ${data.prompt.slice(0, 100)}...` : 'KI-Analyse durchgeführt';
 | 
			
		||||
        } else {
 | 
			
		||||
          return data.response ? `KI-Antwort: ${data.response.slice(0, 100)}...` : 'Antwort erhalten';
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
      case 'tool-confidence':
 | 
			
		||||
        if (type === 'input') {
 | 
			
		||||
          return `Tool: ${data.toolName} (Semantik: ${data.semanticSimilarity}%, Aufgabe: ${data.taskRelevance}%)`;
 | 
			
		||||
        } else {
 | 
			
		||||
          return `Vertrauen: ${data.overallConfidence}% (Stärken: ${data.strengthIndicators?.length || 0}, Unsicherheiten: ${data.uncertaintyFactors?.length || 0})`;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
      case 'tool-added-to-phase':
 | 
			
		||||
        if (type === 'input') {
 | 
			
		||||
          return `Tool: ${data.toolName} für ${data.phaseId} (${data.taskRelevance}% Relevanz, ${data.priority} Priorität)`;
 | 
			
		||||
        } else {
 | 
			
		||||
          const justificationPreview = data.justification ? data.justification.slice(0, 80) + '...' : 'Keine Begründung';
 | 
			
		||||
          return `Begründung: ${justificationPreview}`;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
      case 'concept-selection':
 | 
			
		||||
        if (type === 'input') {
 | 
			
		||||
          const availableCount = Array.isArray(data.availableConcepts) ? data.availableConcepts.length : 0;
 | 
			
		||||
          return `${availableCount} Konzepte verfügbar für methodische Fundierung`;
 | 
			
		||||
        } else {
 | 
			
		||||
          const selectedConcepts = Array.isArray(data.selectedConcepts) ? data.selectedConcepts : [];
 | 
			
		||||
          return `${selectedConcepts.length} ausgewählt: ${selectedConcepts.slice(0, 3).join(', ')}${selectedConcepts.length > 3 ? '...' : ''}`;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Fallback to generic handling for other actions
 | 
			
		||||
    if (typeof data === 'string') {
 | 
			
		||||
      return data.length > 100 ? data.slice(0, 100) + '...' : data;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if (Array.isArray(data)) {
 | 
			
		||||
      if (data.length === 0) return 'Leeres Array';
 | 
			
		||||
      if (data.length <= 3) return data.join(', ');
 | 
			
		||||
      return `${data.slice(0, 3).join(', ')} und ${data.length - 3} weitere`;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return `${Object.keys(data).length} Eigenschaften`;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  renderPhaseGroups(auditTrail, stats) {
 | 
			
		||||
    const phaseGroups = new Map();
 | 
			
		||||
    
 | 
			
		||||
@ -1350,27 +1443,27 @@ class AIQueryInterface {
 | 
			
		||||
    const output = entry.output || {};
 | 
			
		||||
    const metadata = entry.metadata || {};
 | 
			
		||||
    
 | 
			
		||||
    // Show input summary
 | 
			
		||||
    if (metadata.inputSummary && metadata.inputSummary !== 'Empty') {
 | 
			
		||||
    // Show input summary with action-specific formatting
 | 
			
		||||
    if (metadata.inputSummary && metadata.inputSummary !== 'Leer') {
 | 
			
		||||
      details.push(`<div class="detail-item"><strong>Eingabe:</strong> ${escapeHtml(metadata.inputSummary)}</div>`);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Show output summary  
 | 
			
		||||
    if (metadata.outputSummary && metadata.outputSummary !== 'Empty') {
 | 
			
		||||
    // Show output summary with action-specific formatting  
 | 
			
		||||
    if (metadata.outputSummary && metadata.outputSummary !== 'Leer') {
 | 
			
		||||
      details.push(`<div class="detail-item"><strong>Ausgabe:</strong> ${escapeHtml(metadata.outputSummary)}</div>`);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Show reasoning
 | 
			
		||||
    if (metadata.reasoning) {
 | 
			
		||||
    // Show reasoning - this is now meaningful, not generic
 | 
			
		||||
    if (metadata.reasoning && !metadata.reasoning.includes('completed with')) {
 | 
			
		||||
      details.push(`<div class="detail-item"><strong>Begründung:</strong> ${escapeHtml(metadata.reasoning)}</div>`);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Show specific details based on action type
 | 
			
		||||
    if (entry.action === 'similarity-search' && metadata.similarityScores) {
 | 
			
		||||
      const topScores = Object.entries(metadata.similarityScores)
 | 
			
		||||
        .sort(([,a], [,b]) => b - a)
 | 
			
		||||
        .sort(([,a], [,b]) => (b) - (a))
 | 
			
		||||
        .slice(0, 3)
 | 
			
		||||
        .map(([name, score]) => `${name} (${(score * 100).toFixed(1)}%)`)
 | 
			
		||||
        .map(([name, score]) => `${name} (${((score) * 100).toFixed(1)}%)`)
 | 
			
		||||
        .join(', ');
 | 
			
		||||
      if (topScores) {
 | 
			
		||||
        details.push(`<div class="detail-item"><strong>Top Treffer:</strong> ${topScores}</div>`);
 | 
			
		||||
@ -1386,18 +1479,28 @@ class AIQueryInterface {
 | 
			
		||||
    
 | 
			
		||||
    if (entry.action === 'selection-decision' && metadata.selectionMethod) {
 | 
			
		||||
      details.push(`<div class="detail-item"><strong>Auswahlmethode:</strong> ${metadata.selectionMethod}</div>`);
 | 
			
		||||
      if (metadata.reductionRatio) {
 | 
			
		||||
        details.push(`<div class="detail-item"><strong>Reduktion:</strong> ${(metadata.reductionRatio * 100).toFixed(1)}% der verfügbaren Tools</div>`);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if (entry.action === 'tool-confidence') {
 | 
			
		||||
      const confidence = entry.output || {};
 | 
			
		||||
      if (confidence.strengthIndicators?.length > 0) {
 | 
			
		||||
      if (confidence.strengthIndicators && confidence.strengthIndicators.length > 0) {
 | 
			
		||||
        details.push(`<div class="detail-item"><strong>Stärken:</strong> ${confidence.strengthIndicators.slice(0, 2).join(', ')}</div>`);
 | 
			
		||||
      }
 | 
			
		||||
      if (confidence.uncertaintyFactors?.length > 0) {
 | 
			
		||||
      if (confidence.uncertaintyFactors && confidence.uncertaintyFactors.length > 0) {
 | 
			
		||||
        details.push(`<div class="detail-item"><strong>Unsicherheiten:</strong> ${confidence.uncertaintyFactors.slice(0, 2).join(', ')}</div>`);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if (entry.action === 'phase-tool-selection') {
 | 
			
		||||
      if (metadata.availableToolsCount && metadata.selectedToolsCount) {
 | 
			
		||||
        const ratio = (metadata.selectedToolsCount / metadata.availableToolsCount * 100).toFixed(1);
 | 
			
		||||
        details.push(`<div class="detail-item"><strong>Auswahlrate:</strong> ${ratio}% der verfügbaren Phase-Tools</div>`);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if (details.length === 0) return '';
 | 
			
		||||
    
 | 
			
		||||
    return `
 | 
			
		||||
@ -1433,19 +1536,34 @@ class AIQueryInterface {
 | 
			
		||||
        return `Semantische Suche: ${entry.output?.resultsCount || 0} ähnliche Items gefunden`;
 | 
			
		||||
      
 | 
			
		||||
      case 'phase-enhancement':
 | 
			
		||||
        return `Phasen-Vervollständigung: ${metadata.toolsAddedCount || 0} Tools für ${metadata.phaseId} hinzugefügt`;
 | 
			
		||||
        const actualCount = entry.output?.toolsAddedCount || metadata.toolsAdded?.length || 0;
 | 
			
		||||
        const phaseName = entry.input?.phaseName || metadata.phaseId || 'unbekannte Phase';
 | 
			
		||||
        return `Phasen-Vervollständigung: ${actualCount} Tools für ${phaseName} hinzugefügt`;
 | 
			
		||||
      
 | 
			
		||||
      case 'tool-confidence':
 | 
			
		||||
        return `Vertrauenswertung: ${entry.input?.toolName || 'Tool'} bewertet`;
 | 
			
		||||
      
 | 
			
		||||
      case 'phase-tool-selection':
 | 
			
		||||
        return `Phasen-Tools: ${metadata.selectedToolsCount || 0} Tools für ${metadata.phaseId} ausgewählt`;
 | 
			
		||||
        const phaseId = metadata.phaseId || entry.input?.phaseId;
 | 
			
		||||
        const phasesToDisplay = {
 | 
			
		||||
          'preparation': 'Vorbereitung', 
 | 
			
		||||
          'acquisition': 'Datensammlung',
 | 
			
		||||
          'examination': 'Untersuchung', 
 | 
			
		||||
          'analysis': 'Analyse',
 | 
			
		||||
          'reporting': 'Dokumentation',
 | 
			
		||||
          'presentation': 'Präsentation'
 | 
			
		||||
        };
 | 
			
		||||
        const displayPhase = phasesToDisplay[phaseId] || phaseId || 'Phase';
 | 
			
		||||
        return `${displayPhase}: ${metadata.selectedToolsCount || 0} Tools ausgewählt`;
 | 
			
		||||
      
 | 
			
		||||
      case 'pipeline-start':
 | 
			
		||||
        return `Analyse gestartet (${entry.input?.mode || 'unknown'} Modus)`;
 | 
			
		||||
      case 'tool-added-to-phase':
 | 
			
		||||
        const toolName = entry.input?.toolName || 'Tool';
 | 
			
		||||
        const phase = entry.input?.phaseId || 'Phase';
 | 
			
		||||
        const priority = entry.input?.priority || metadata.priority || 'medium';
 | 
			
		||||
        return `${toolName} als ${priority}-Priorität für ${phase} ausgewählt`;
 | 
			
		||||
      
 | 
			
		||||
      case 'pipeline-end':
 | 
			
		||||
        return `Analyse abgeschlossen (${entry.input?.completedTasks || 0} erfolgreich, ${entry.input?.failedTasks || 0} fehlgeschlagen)`;
 | 
			
		||||
      case 'concept-selection':
 | 
			
		||||
        return `Hintergrundwissen: ${metadata.selectedConceptsCount || 0} Konzepte ausgewählt`;
 | 
			
		||||
      
 | 
			
		||||
      default:
 | 
			
		||||
        return this.getActionDisplayName(action);
 | 
			
		||||
@ -1486,43 +1604,42 @@ class AIQueryInterface {
 | 
			
		||||
    `;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getPhaseIcon(phase) {
 | 
			
		||||
    const icons = {
 | 
			
		||||
      'initialization': '🚀',
 | 
			
		||||
      'tool-selection': '🔧',
 | 
			
		||||
      'contextual-analysis': '🧠',
 | 
			
		||||
      'workflow-phase': '⚡',
 | 
			
		||||
      'tool-reasoning': '💭',
 | 
			
		||||
      'knowledge-synthesis': '📚',
 | 
			
		||||
      'confidence-scoring': '📊',
 | 
			
		||||
      'phase-completion': '✅',
 | 
			
		||||
      'completion': '🎯',
 | 
			
		||||
      'embeddings': '🔍',
 | 
			
		||||
      'unknown': '❓'
 | 
			
		||||
    };
 | 
			
		||||
    return icons[phase] || icons['unknown'];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getPhaseDisplayName(phase) {
 | 
			
		||||
    const names = {
 | 
			
		||||
      'initialization': 'Initialisierung',
 | 
			
		||||
      'tool-selection': 'Tool-Auswahl',
 | 
			
		||||
      'contextual-analysis': 'Kontext-Analyse', 
 | 
			
		||||
      'workflow-phase': 'Workflow-Phase',
 | 
			
		||||
      'tool-reasoning': 'Tool-Bewertung',
 | 
			
		||||
      'tool-evaluation': 'Tool-Bewertung',
 | 
			
		||||
      'knowledge-synthesis': 'Wissens-Synthese',
 | 
			
		||||
      'confidence-scoring': 'Vertrauenswertung',
 | 
			
		||||
      'phase-completion': 'Phasen-Vervollständigung',
 | 
			
		||||
      'completion': 'Abschluss',
 | 
			
		||||
      'embeddings': 'Semantische Suche',
 | 
			
		||||
      'synthesis': 'Empfehlungs-Synthese',
 | 
			
		||||
      'unknown': 'Unbekannt'
 | 
			
		||||
    };
 | 
			
		||||
    return names[phase] || phase;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getPhaseIcon(phase) {
 | 
			
		||||
    const icons = {
 | 
			
		||||
      'tool-selection': '🔧',
 | 
			
		||||
      'contextual-analysis': '🧠',
 | 
			
		||||
      'workflow-phase': '⚡',
 | 
			
		||||
      'tool-reasoning': '💭',
 | 
			
		||||
      'tool-evaluation': '💭',
 | 
			
		||||
      'knowledge-synthesis': '📚',
 | 
			
		||||
      'confidence-scoring': '📊',
 | 
			
		||||
      'phase-completion': '✅',
 | 
			
		||||
      'embeddings': '🔍',
 | 
			
		||||
      'synthesis': '🎯',
 | 
			
		||||
      'unknown': '❓'
 | 
			
		||||
    };
 | 
			
		||||
    return icons[phase] || icons['unknown'];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getActionDisplayName(action) {
 | 
			
		||||
    const actions = {
 | 
			
		||||
      'pipeline-start': 'Analyse gestartet',
 | 
			
		||||
      'selection-decision': 'Tools ausgewählt',
 | 
			
		||||
      'ai-decision': 'KI-Entscheidung',
 | 
			
		||||
      'phase-tool-selection': 'Phasen-Tools evaluiert',
 | 
			
		||||
@ -1530,8 +1647,7 @@ class AIQueryInterface {
 | 
			
		||||
      'concept-selection': 'Konzepte ausgewählt',
 | 
			
		||||
      'tool-confidence': 'Vertrauen berechnet',
 | 
			
		||||
      'phase-enhancement': 'Phase vervollständigt',
 | 
			
		||||
      'similarity-search': 'Ähnlichkeitssuche',
 | 
			
		||||
      'pipeline-end': 'Analyse abgeschlossen'
 | 
			
		||||
      'similarity-search': 'Ähnlichkeitssuche'
 | 
			
		||||
    };
 | 
			
		||||
    return actions[action] || action;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
// src/utils/aiPipeline.ts - Enhanced with comprehensive audit logging and restored sophisticated logic
 | 
			
		||||
// src/utils/aiPipeline.ts - Fixed with accurate audit data and meaningful confidence
 | 
			
		||||
import { getCompressedToolsDataForAI, getDataVersion } from './dataService.js';
 | 
			
		||||
import { aiService } from './aiService.js';
 | 
			
		||||
import { toolSelector, type SelectionContext } from './toolSelector.js';
 | 
			
		||||
@ -95,7 +95,7 @@ class AIPipeline {
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    console.log('[AI-PIPELINE] Initialized orchestration pipeline with enhanced logic');
 | 
			
		||||
    console.log('[AI-PIPELINE] Initialized with improved audit accuracy');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async processQuery(userQuery: string, mode: string): Promise<AnalysisResult> {
 | 
			
		||||
@ -124,40 +124,26 @@ class AIPipeline {
 | 
			
		||||
        embeddingsSimilarities: new Map<string, number>()
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      auditService.addEntry(
 | 
			
		||||
        'initialization',
 | 
			
		||||
        'pipeline-start',
 | 
			
		||||
        { 
 | 
			
		||||
          userQuery: this.truncateForAudit(userQuery), 
 | 
			
		||||
          mode, 
 | 
			
		||||
          toolsDataLoaded: !!toolsData,
 | 
			
		||||
          aiConfig: { model: aiConfig.model }
 | 
			
		||||
        },
 | 
			
		||||
        { 
 | 
			
		||||
          totalAvailableTools: toolsData.tools.length,
 | 
			
		||||
          totalAvailableConcepts: toolsData.concepts.length,
 | 
			
		||||
          embeddingsEnabled: embeddingsService.isEnabled()
 | 
			
		||||
        },
 | 
			
		||||
        90,
 | 
			
		||||
        startTime,
 | 
			
		||||
        { 
 | 
			
		||||
          toolsDataHash,
 | 
			
		||||
          aiModel: aiConfig.model,
 | 
			
		||||
          embeddingsUsed: embeddingsService.isEnabled(),
 | 
			
		||||
          pipelineVersion: '2.1-enhanced'
 | 
			
		||||
        }
 | 
			
		||||
      );
 | 
			
		||||
      // Skip initialization audit entry - it doesn't add transparency value
 | 
			
		||||
 | 
			
		||||
      console.log('[AI-PIPELINE] Phase 1: Tool candidate selection');
 | 
			
		||||
      const candidateSelectionStart = Date.now();
 | 
			
		||||
      
 | 
			
		||||
      const candidateData = await toolSelector.getIntelligentCandidates(userQuery, toolsData, mode, context);
 | 
			
		||||
      
 | 
			
		||||
      // Calculate meaningful confidence for tool selection
 | 
			
		||||
      const selectionConfidence = this.calculateToolSelectionConfidence(
 | 
			
		||||
        candidateData.tools.length,
 | 
			
		||||
        toolsData.tools.length,
 | 
			
		||||
        candidateData.selectionMethod,
 | 
			
		||||
        candidateData.concepts.length
 | 
			
		||||
      );
 | 
			
		||||
      
 | 
			
		||||
      auditService.addToolSelection(
 | 
			
		||||
        candidateData.tools.map(t => t.name),
 | 
			
		||||
        toolsData.tools.map(t => t.name),
 | 
			
		||||
        candidateData.selectionMethod,
 | 
			
		||||
        85,
 | 
			
		||||
        selectionConfidence,
 | 
			
		||||
        candidateSelectionStart,
 | 
			
		||||
        {
 | 
			
		||||
          embeddingsUsed: embeddingsService.isEnabled(),
 | 
			
		||||
@ -211,25 +197,7 @@ class AIPipeline {
 | 
			
		||||
 | 
			
		||||
      const recommendation = this.buildRecommendation(context, mode, finalResult.content);
 | 
			
		||||
 | 
			
		||||
      auditService.addEntry(
 | 
			
		||||
        'completion',
 | 
			
		||||
        'pipeline-end',
 | 
			
		||||
        { completedTasks, failedTasks, totalTokensUsed: this.totalTokensUsed },
 | 
			
		||||
        { 
 | 
			
		||||
          finalRecommendation: !!recommendation, 
 | 
			
		||||
          auditEntriesGenerated: auditService.getCurrentAuditTrail().length,
 | 
			
		||||
          selectedToolsCount: context.selectedTools?.length || 0,
 | 
			
		||||
          backgroundKnowledgeCount: context.backgroundKnowledge?.length || 0
 | 
			
		||||
        },
 | 
			
		||||
        completedTasks > failedTasks ? 85 : 60,
 | 
			
		||||
        startTime,
 | 
			
		||||
        { 
 | 
			
		||||
          totalProcessingTimeMs: Date.now() - startTime,
 | 
			
		||||
          aiModel: aiConfig.model,
 | 
			
		||||
          finalTokenUsage: this.totalTokensUsed,
 | 
			
		||||
          pipelineEfficiency: completedTasks / (completedTasks + failedTasks)
 | 
			
		||||
        }
 | 
			
		||||
      );
 | 
			
		||||
      // Skip completion audit entry - it doesn't add transparency value
 | 
			
		||||
 | 
			
		||||
      const processingStats = {
 | 
			
		||||
        embeddingsUsed: embeddingsService.isEnabled(),
 | 
			
		||||
@ -270,21 +238,47 @@ class AIPipeline {
 | 
			
		||||
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
      console.error('[AI-PIPELINE] Pipeline failed:', error);
 | 
			
		||||
      
 | 
			
		||||
      auditService.addEntry(
 | 
			
		||||
        'error',
 | 
			
		||||
        'pipeline-failure',
 | 
			
		||||
        { userQuery: this.truncateForAudit(userQuery), mode },
 | 
			
		||||
        { error: error.message, completedTasks, failedTasks },
 | 
			
		||||
        0,
 | 
			
		||||
        startTime,
 | 
			
		||||
        { errorType: error.constructor.name, totalTokensUsed: this.totalTokensUsed }
 | 
			
		||||
      );
 | 
			
		||||
      
 | 
			
		||||
      throw error;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private calculateToolSelectionConfidence(
 | 
			
		||||
    selectedCount: number,
 | 
			
		||||
    totalCount: number,
 | 
			
		||||
    method: string,
 | 
			
		||||
    conceptsCount: number
 | 
			
		||||
  ): number {
 | 
			
		||||
    let confidence = 50;
 | 
			
		||||
    
 | 
			
		||||
    const selectionRatio = selectedCount / totalCount;
 | 
			
		||||
    
 | 
			
		||||
    // Good selection ratio (5-20% is optimal)
 | 
			
		||||
    if (selectionRatio >= 0.05 && selectionRatio <= 0.20) {
 | 
			
		||||
      confidence += 25;
 | 
			
		||||
    } else if (selectionRatio < 0.05) {
 | 
			
		||||
      confidence += 15; // Very selective
 | 
			
		||||
    } else if (selectionRatio > 0.30) {
 | 
			
		||||
      confidence -= 15; // Too inclusive
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Embeddings method bonus
 | 
			
		||||
    if (method.includes('embeddings')) {
 | 
			
		||||
      confidence += 15;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Concepts also selected
 | 
			
		||||
    if (conceptsCount > 0) {
 | 
			
		||||
      confidence += 10;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Reasonable absolute numbers
 | 
			
		||||
    if (selectedCount >= 8 && selectedCount <= 25) {
 | 
			
		||||
      confidence += 10;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return Math.min(95, Math.max(40, confidence));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private async processWorkflowMode(
 | 
			
		||||
    context: PipelineContext, 
 | 
			
		||||
    toolsData: any, 
 | 
			
		||||
@ -300,27 +294,44 @@ class AIPipeline {
 | 
			
		||||
        tool && tool.phases && Array.isArray(tool.phases) && tool.phases.includes(phase.id)
 | 
			
		||||
      );
 | 
			
		||||
      
 | 
			
		||||
      if (phaseTools.length === 0) {
 | 
			
		||||
        console.log(`[AI-PIPELINE] No tools available for phase: ${phase.id}`);
 | 
			
		||||
        continue;
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      const selections = await toolSelector.selectToolsForPhase(context.userQuery, phase, phaseTools, context);
 | 
			
		||||
      
 | 
			
		||||
      // Calculate meaningful confidence based on phase selection quality
 | 
			
		||||
      const phaseConfidence = this.calculatePhaseSelectionConfidence(
 | 
			
		||||
        selections.length,
 | 
			
		||||
        phaseTools.length,
 | 
			
		||||
        phase.id,
 | 
			
		||||
        selections
 | 
			
		||||
      );
 | 
			
		||||
      
 | 
			
		||||
      auditService.addEntry(
 | 
			
		||||
        'workflow-phase',
 | 
			
		||||
        'phase-tool-selection',
 | 
			
		||||
        { 
 | 
			
		||||
          phaseId: phase.id, 
 | 
			
		||||
          phaseName: phase.name, 
 | 
			
		||||
          availableTools: phaseTools.map(t => t.name) 
 | 
			
		||||
          availableTools: phaseTools.map(t => t.name),
 | 
			
		||||
          toolCount: phaseTools.length
 | 
			
		||||
        },
 | 
			
		||||
        { 
 | 
			
		||||
          selectedTools: selections.map(s => s.toolName),
 | 
			
		||||
          selectionCount: selections.length
 | 
			
		||||
          selectionCount: selections.length,
 | 
			
		||||
          avgTaskRelevance: selections.length > 0 ? 
 | 
			
		||||
            Math.round(selections.reduce((sum, s) => sum + (s.taskRelevance || 70), 0) / selections.length) : 0
 | 
			
		||||
        },
 | 
			
		||||
        selections.length > 0 ? 80 : 50,
 | 
			
		||||
        phaseConfidence,
 | 
			
		||||
        phaseStart,
 | 
			
		||||
        {
 | 
			
		||||
          phaseId: phase.id,
 | 
			
		||||
          availableToolsCount: phaseTools.length,
 | 
			
		||||
          selectedToolsCount: selections.length,
 | 
			
		||||
          microTaskType: 'phase-tool-selection'
 | 
			
		||||
          microTaskType: 'phase-tool-selection',
 | 
			
		||||
          reasoning: `${selections.length} von ${phaseTools.length} verfügbaren Tools für ${phase.name} ausgewählt - KI bewertete Eignung für spezifische Phasenaufgaben`
 | 
			
		||||
        }
 | 
			
		||||
      );
 | 
			
		||||
      
 | 
			
		||||
@ -335,15 +346,24 @@ class AIPipeline {
 | 
			
		||||
          auditService.addEntry(
 | 
			
		||||
            'tool-reasoning',
 | 
			
		||||
            'tool-added-to-phase',
 | 
			
		||||
            { toolName: tool.name, phaseId: phase.id, originalTaskRelevance: sel.taskRelevance, moderatedTaskRelevance },
 | 
			
		||||
            { justification: sel.justification, limitations: sel.limitations },
 | 
			
		||||
            { 
 | 
			
		||||
              toolName: tool.name, 
 | 
			
		||||
              phaseId: phase.id, 
 | 
			
		||||
              taskRelevance: moderatedTaskRelevance,
 | 
			
		||||
              priority: priority
 | 
			
		||||
            },
 | 
			
		||||
            { 
 | 
			
		||||
              justification: sel.justification, 
 | 
			
		||||
              limitations: sel.limitations,
 | 
			
		||||
              addedToPhase: phase.name
 | 
			
		||||
            },
 | 
			
		||||
            moderatedTaskRelevance || 70,
 | 
			
		||||
            phaseStart,
 | 
			
		||||
            {
 | 
			
		||||
              toolType: tool.type,
 | 
			
		||||
              priority,
 | 
			
		||||
              selectionReasoning: sel.justification,
 | 
			
		||||
              moderationApplied: sel.taskRelevance !== moderatedTaskRelevance
 | 
			
		||||
              moderationApplied: sel.taskRelevance !== moderatedTaskRelevance,
 | 
			
		||||
              reasoning: `${tool.name} als ${priority}-Priorität für ${phase.name} ausgewählt: ${sel.justification?.slice(0, 100)}...`
 | 
			
		||||
            }
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
@ -360,6 +380,51 @@ class AIPipeline {
 | 
			
		||||
    return { completed: completedTasks, failed: failedTasks };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private calculatePhaseSelectionConfidence(
 | 
			
		||||
    selectedCount: number,
 | 
			
		||||
    availableCount: number,
 | 
			
		||||
    phaseId: string,
 | 
			
		||||
    selections: any[]
 | 
			
		||||
  ): number {
 | 
			
		||||
    let confidence = 60;
 | 
			
		||||
    
 | 
			
		||||
    // Phase-specific expectations
 | 
			
		||||
    const criticalPhases = ['acquisition', 'examination', 'analysis'];
 | 
			
		||||
    const isCritical = criticalPhases.includes(phaseId);
 | 
			
		||||
    
 | 
			
		||||
    // Selection made
 | 
			
		||||
    if (selectedCount > 0) {
 | 
			
		||||
      confidence += 20;
 | 
			
		||||
    } else {
 | 
			
		||||
      return 30; // No selection is concerning
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Selection ratio (for phases, 20-50% is reasonable)
 | 
			
		||||
    const ratio = selectedCount / availableCount;
 | 
			
		||||
    if (ratio >= 0.2 && ratio <= 0.5) {
 | 
			
		||||
      confidence += 15;
 | 
			
		||||
    } else if (ratio < 0.2 && selectedCount >= 1) {
 | 
			
		||||
      confidence += 10; // Selective is ok
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Critical phases should have adequate tools
 | 
			
		||||
    if (isCritical && selectedCount >= 2) {
 | 
			
		||||
      confidence += 10;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Quality of selections (based on task relevance)
 | 
			
		||||
    const avgRelevance = selections.length > 0 ? 
 | 
			
		||||
      selections.reduce((sum, s) => sum + (s.taskRelevance || 70), 0) / selections.length : 0;
 | 
			
		||||
    
 | 
			
		||||
    if (avgRelevance >= 75) {
 | 
			
		||||
      confidence += 10;
 | 
			
		||||
    } else if (avgRelevance >= 65) {
 | 
			
		||||
      confidence += 5;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return Math.min(95, Math.max(30, confidence));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private async processToolMode(
 | 
			
		||||
    context: PipelineContext, 
 | 
			
		||||
    completedTasks: number, 
 | 
			
		||||
@ -405,26 +470,6 @@ class AIPipeline {
 | 
			
		||||
    
 | 
			
		||||
    console.log('[AI-PIPELINE] Completing underrepresented phases:', underrepresentedPhases.map((p: any) => p.id).join(', '));
 | 
			
		||||
    
 | 
			
		||||
    auditService.addEntry(
 | 
			
		||||
      'phase-completion',
 | 
			
		||||
      'underrepresented-phases-detected',
 | 
			
		||||
      { 
 | 
			
		||||
        underrepresentedPhases: underrepresentedPhases.map(p => p.id),
 | 
			
		||||
        currentPhaseDistribution: Array.from(selectedPhases.entries())
 | 
			
		||||
      },
 | 
			
		||||
      { 
 | 
			
		||||
        phasesToComplete: underrepresentedPhases.length,
 | 
			
		||||
        completionStrategy: 'semantic-search-with-ai-reasoning'
 | 
			
		||||
      },
 | 
			
		||||
      70,
 | 
			
		||||
      pipelineStart,
 | 
			
		||||
      {
 | 
			
		||||
        totalPhases: phases.length,
 | 
			
		||||
        adequatelyRepresented: phases.length - underrepresentedPhases.length,
 | 
			
		||||
        completionMethod: 'sophisticated-ai-reasoning'
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
    
 | 
			
		||||
    for (const phase of underrepresentedPhases) {
 | 
			
		||||
      const result = await this.completePhaseWithSemanticSearchAndAI(context, phase, toolsData, pipelineStart);
 | 
			
		||||
      if (result.success) completedTasks++; else failedTasks++;
 | 
			
		||||
@ -537,6 +582,9 @@ class AIPipeline {
 | 
			
		||||
        };
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      // This is the fix for "0 tools added" - use the actual valid tools
 | 
			
		||||
      const actualToolsAdded = validTools.map(tool => tool.name);
 | 
			
		||||
      
 | 
			
		||||
      for (const tool of validTools) {
 | 
			
		||||
        console.log('[AI-PIPELINE] Generating AI reasoning for phase completion tool:', tool.name);
 | 
			
		||||
        
 | 
			
		||||
@ -572,25 +620,26 @@ class AIPipeline {
 | 
			
		||||
          ['Nachträgliche Ergänzung via semantische Phasensuche mit KI-Bewertung']
 | 
			
		||||
        );
 | 
			
		||||
        
 | 
			
		||||
        auditService.addPhaseCompletion(
 | 
			
		||||
          phase.id,
 | 
			
		||||
          [tool.name],
 | 
			
		||||
          detailedJustification,
 | 
			
		||||
          phaseStart,
 | 
			
		||||
          {
 | 
			
		||||
            toolName: tool.name,
 | 
			
		||||
            toolType: tool.type,
 | 
			
		||||
            semanticSimilarity: phaseResults.find(r => r.name === tool.name)?.similarity,
 | 
			
		||||
            completionReason: 'underrepresented-phase',
 | 
			
		||||
            originalSelectionMissed: true,
 | 
			
		||||
            aiReasoningUsed: reasoningResult.success,
 | 
			
		||||
            moderatedTaskRelevance
 | 
			
		||||
          }
 | 
			
		||||
        );
 | 
			
		||||
        
 | 
			
		||||
        console.log('[AI-PIPELINE] Added phase completion tool with AI reasoning:', tool.name);
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      // Use the actual tools added for audit
 | 
			
		||||
      auditService.addPhaseCompletion(
 | 
			
		||||
        phase.id,
 | 
			
		||||
        actualToolsAdded, // This ensures correct count
 | 
			
		||||
        selection.completionReasoning || `${actualToolsAdded.length} Tools für ${phase.name} hinzugefügt`,
 | 
			
		||||
        phaseStart,
 | 
			
		||||
        {
 | 
			
		||||
          toolsAdded: actualToolsAdded,
 | 
			
		||||
          toolType: validTools[0]?.type,
 | 
			
		||||
          semanticSimilarity: phaseResults.find(r => r.name === validTools[0]?.name)?.similarity,
 | 
			
		||||
          completionReason: 'underrepresented-phase',
 | 
			
		||||
          originalSelectionMissed: true,
 | 
			
		||||
          aiReasoningUsed: true,
 | 
			
		||||
          moderatedTaskRelevance: 75
 | 
			
		||||
        }
 | 
			
		||||
      );
 | 
			
		||||
      
 | 
			
		||||
      return {
 | 
			
		||||
        taskType: 'phase-completion',
 | 
			
		||||
        content: selection.completionReasoning || '',
 | 
			
		||||
@ -601,19 +650,6 @@ class AIPipeline {
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
      console.error('[AI-PIPELINE] Phase completion failed for:', phase.id, error);
 | 
			
		||||
      
 | 
			
		||||
      auditService.addEntry(
 | 
			
		||||
        'phase-completion',
 | 
			
		||||
        'completion-failed',
 | 
			
		||||
        { phaseId: phase.id, error: error.message },
 | 
			
		||||
        { success: false },
 | 
			
		||||
        20,
 | 
			
		||||
        phaseStart,
 | 
			
		||||
        {
 | 
			
		||||
          errorType: error.constructor.name,
 | 
			
		||||
          phaseId: phase.id
 | 
			
		||||
        }
 | 
			
		||||
      );
 | 
			
		||||
      
 | 
			
		||||
      return {
 | 
			
		||||
        taskType: 'phase-completion',
 | 
			
		||||
        content: '',
 | 
			
		||||
@ -795,14 +831,12 @@ class AIPipeline {
 | 
			
		||||
        }
 | 
			
		||||
      }, 'evaluation', priority, evaluation.detailed_explanation, moderatedTaskRelevance, evaluation.limitations);
 | 
			
		||||
      
 | 
			
		||||
      // Calculate confidence based on response quality and task relevance
 | 
			
		||||
      const responseConfidence = auditService.calculateAIResponseConfidence(
 | 
			
		||||
        result.content,
 | 
			
		||||
        { min: 200, max: 800 },
 | 
			
		||||
        'tool-evaluation'
 | 
			
		||||
      );
 | 
			
		||||
      
 | 
			
		||||
      // Use the higher of response quality confidence or moderated task relevance
 | 
			
		||||
      const finalConfidence = Math.max(responseConfidence, moderatedTaskRelevance);
 | 
			
		||||
      
 | 
			
		||||
      auditService.addAIDecision(
 | 
			
		||||
@ -870,8 +904,9 @@ class AIPipeline {
 | 
			
		||||
          'background-knowledge'
 | 
			
		||||
        );
 | 
			
		||||
        
 | 
			
		||||
        const selectionBonus = context.backgroundKnowledge.length > 0 ? 15 : 0;
 | 
			
		||||
        const finalConfidence = Math.min(95, responseConfidence + selectionBonus);
 | 
			
		||||
        // Calculate confidence based on quality of selections
 | 
			
		||||
        const selectionQualityBonus = this.calculateKnowledgeSelectionBonus(context.backgroundKnowledge, availableConcepts);
 | 
			
		||||
        const finalConfidence = Math.min(95, responseConfidence + selectionQualityBonus);
 | 
			
		||||
        
 | 
			
		||||
        auditService.addEntry(
 | 
			
		||||
          'knowledge-synthesis',
 | 
			
		||||
@ -893,7 +928,7 @@ class AIPipeline {
 | 
			
		||||
            selectedConceptsCount: context.backgroundKnowledge.length,
 | 
			
		||||
            selectionRatio: context.backgroundKnowledge.length / availableConcepts.length,
 | 
			
		||||
            responseConfidence,
 | 
			
		||||
            selectionBonus,
 | 
			
		||||
            selectionQualityBonus,
 | 
			
		||||
            decisionBasis: 'ai-analysis',
 | 
			
		||||
            reasoning: `Wählte ${context.backgroundKnowledge.length} von ${availableConcepts.length} verfügbaren Konzepten für methodische Fundierung der Empfehlungen`,
 | 
			
		||||
            aiModel: aiService.getConfig().model,
 | 
			
		||||
@ -906,6 +941,33 @@ class AIPipeline {
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private calculateKnowledgeSelectionBonus(
 | 
			
		||||
    selectedKnowledge: Array<{concept: any; relevance: string}>,
 | 
			
		||||
    availableConcepts: any[]
 | 
			
		||||
  ): number {
 | 
			
		||||
    let bonus = 0;
 | 
			
		||||
    
 | 
			
		||||
    if (selectedKnowledge.length > 0) {
 | 
			
		||||
      bonus += 10;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Good selection ratio (10-30% of available concepts)
 | 
			
		||||
    const ratio = selectedKnowledge.length / availableConcepts.length;
 | 
			
		||||
    if (ratio >= 0.1 && ratio <= 0.3) {
 | 
			
		||||
      bonus += 15;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Quality reasoning provided
 | 
			
		||||
    const hasGoodReasonings = selectedKnowledge.some(bk => 
 | 
			
		||||
      bk.relevance && bk.relevance.length > 30
 | 
			
		||||
    );
 | 
			
		||||
    if (hasGoodReasonings) {
 | 
			
		||||
      bonus += 10;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return bonus;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private async generateFinalRecommendations(context: PipelineContext, pipelineStart: number): Promise<MicroTaskResult> {
 | 
			
		||||
    console.log('[AI-PIPELINE] Micro-task: Final recommendations');
 | 
			
		||||
    const taskStart = Date.now();
 | 
			
		||||
@ -921,7 +983,8 @@ class AIPipeline {
 | 
			
		||||
        'final-recommendations'
 | 
			
		||||
      );
 | 
			
		||||
      
 | 
			
		||||
      const contextBonus = selectedToolNames.length >= 3 ? 10 : 0;
 | 
			
		||||
      // Calculate bonus based on context quality
 | 
			
		||||
      const contextBonus = this.calculateSynthesisBonus(selectedToolNames, context);
 | 
			
		||||
      const finalConfidence = Math.min(95, confidence + contextBonus);
 | 
			
		||||
      
 | 
			
		||||
      auditService.addAIDecision(
 | 
			
		||||
@ -948,6 +1011,28 @@ class AIPipeline {
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private calculateSynthesisBonus(selectedToolNames: string[], context: PipelineContext): number {
 | 
			
		||||
    let bonus = 0;
 | 
			
		||||
    
 | 
			
		||||
    if (selectedToolNames.length >= 3) {
 | 
			
		||||
      bonus += 10;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if (context.backgroundKnowledge && context.backgroundKnowledge.length > 0) {
 | 
			
		||||
      bonus += 10;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if (context.scenarioAnalysis || context.problemAnalysis) {
 | 
			
		||||
      bonus += 5;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if (context.investigationApproach) {
 | 
			
		||||
      bonus += 5;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return bonus;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private buildRecommendation(context: PipelineContext, mode: string, finalContent: string): any {
 | 
			
		||||
    const isWorkflow = mode === 'workflow';
 | 
			
		||||
    
 | 
			
		||||
@ -1140,12 +1225,6 @@ class AIPipeline {
 | 
			
		||||
    return 'low';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private truncateForAudit(text: string, maxLength: number = 200): string {
 | 
			
		||||
    if (typeof text !== 'string') return String(text);
 | 
			
		||||
    if (text.length <= maxLength) return text;
 | 
			
		||||
    return text.slice(0, maxLength) + '...[audit-truncated]';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private trackTokenUsage(usage?: { promptTokens?: number; completionTokens?: number; totalTokens?: number }): void {
 | 
			
		||||
    if (usage?.totalTokens) {
 | 
			
		||||
      this.totalTokensUsed += usage.totalTokens;
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
// src/utils/auditService.ts - Always detailed, no compression modes
 | 
			
		||||
// src/utils/auditService.ts - Fixed with meaningful confidence and reasoning
 | 
			
		||||
import 'dotenv/config';
 | 
			
		||||
 | 
			
		||||
function env(key: string, fallback: string | undefined = undefined): string | undefined {
 | 
			
		||||
@ -59,7 +59,7 @@ class AuditService {
 | 
			
		||||
 | 
			
		||||
  constructor() {
 | 
			
		||||
    this.config = this.loadConfig();
 | 
			
		||||
    console.log('[AUDIT-SERVICE] Initialized with detailed logging enabled');
 | 
			
		||||
    console.log('[AUDIT-SERVICE] Initialized with meaningful audit logging');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private loadConfig(): AuditConfig {
 | 
			
		||||
@ -85,21 +85,25 @@ class AuditService {
 | 
			
		||||
  ): void {
 | 
			
		||||
    if (!this.config.enabled) return;
 | 
			
		||||
 | 
			
		||||
    // Always store full details with meaningful summaries
 | 
			
		||||
    // Skip initialization and completion entries as they don't add transparency
 | 
			
		||||
    if (action === 'pipeline-start' || action === 'pipeline-end') {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const enhancedMetadata = {
 | 
			
		||||
      ...metadata,
 | 
			
		||||
      inputSummary: this.createMeaningfulSummary(input, 'input'),
 | 
			
		||||
      outputSummary: this.createMeaningfulSummary(output, 'output'),
 | 
			
		||||
      inputSummary: this.createSpecificSummary(input, action, 'input'),
 | 
			
		||||
      outputSummary: this.createSpecificSummary(output, action, 'output'),
 | 
			
		||||
      decisionBasis: metadata.decisionBasis || this.inferDecisionBasis(metadata),
 | 
			
		||||
      reasoning: metadata.reasoning || this.extractReasoning(action, input, output, metadata)
 | 
			
		||||
      reasoning: metadata.reasoning || this.generateSpecificReasoning(action, input, output, metadata, confidence)
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const entry: AuditEntry = {
 | 
			
		||||
      timestamp: Date.now(),
 | 
			
		||||
      phase,
 | 
			
		||||
      action,
 | 
			
		||||
      input: input, // Store full input
 | 
			
		||||
      output: output, // Store full output
 | 
			
		||||
      input: input,
 | 
			
		||||
      output: output,
 | 
			
		||||
      confidence: Math.round(confidence),
 | 
			
		||||
      processingTimeMs: Date.now() - startTime,
 | 
			
		||||
      metadata: enhancedMetadata
 | 
			
		||||
@ -111,7 +115,7 @@ class AuditService {
 | 
			
		||||
      this.activeAuditTrail.shift();
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    console.log(`[AUDIT-SERVICE] ${phase}/${action}: ${confidence}% confidence, ${entry.processingTimeMs}ms, basis: ${enhancedMetadata.decisionBasis}`);
 | 
			
		||||
    console.log(`[AUDIT-SERVICE] ${phase}/${action}: ${confidence}% confidence, ${entry.processingTimeMs}ms`);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  addAIDecision(
 | 
			
		||||
@ -126,8 +130,8 @@ class AuditService {
 | 
			
		||||
    this.addEntry(
 | 
			
		||||
      phase,
 | 
			
		||||
      'ai-decision',
 | 
			
		||||
      { prompt: aiPrompt },
 | 
			
		||||
      { response: aiResponse },
 | 
			
		||||
      { prompt: this.truncatePrompt(aiPrompt) },
 | 
			
		||||
      { response: this.truncateResponse(aiResponse) },
 | 
			
		||||
      confidence,
 | 
			
		||||
      startTime,
 | 
			
		||||
      {
 | 
			
		||||
@ -148,28 +152,34 @@ class AuditService {
 | 
			
		||||
    startTime: number,
 | 
			
		||||
    metadata: Record<string, any> = {}
 | 
			
		||||
  ): void {
 | 
			
		||||
    // Calculate meaningful confidence based on selection quality
 | 
			
		||||
    const calculatedConfidence = this.calculateSelectionConfidence(
 | 
			
		||||
      selectedTools, 
 | 
			
		||||
      availableTools, 
 | 
			
		||||
      selectionMethod, 
 | 
			
		||||
      metadata
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    this.addEntry(
 | 
			
		||||
      'tool-selection',
 | 
			
		||||
      'selection-decision',
 | 
			
		||||
      { 
 | 
			
		||||
        availableTools: availableTools,
 | 
			
		||||
        selectionMethod: selectionMethod,
 | 
			
		||||
        candidateCount: availableTools.length
 | 
			
		||||
        availableTools: availableTools.slice(0, 10), // Show first 10 for context
 | 
			
		||||
        totalAvailable: availableTools.length,
 | 
			
		||||
        selectionMethod: selectionMethod
 | 
			
		||||
      },
 | 
			
		||||
      { 
 | 
			
		||||
        selectedTools: selectedTools,
 | 
			
		||||
        selectionRatio: selectedTools.length / availableTools.length
 | 
			
		||||
      },
 | 
			
		||||
      confidence,
 | 
			
		||||
      calculatedConfidence,
 | 
			
		||||
      startTime,
 | 
			
		||||
      {
 | 
			
		||||
        ...metadata,
 | 
			
		||||
        selectionMethod,
 | 
			
		||||
        availableToolsCount: availableTools.length,
 | 
			
		||||
        selectedToolsCount: selectedTools.length,
 | 
			
		||||
        toolSelectionCriteria: `${selectionMethod} selection from ${availableTools.length} available tools`,
 | 
			
		||||
        decisionBasis: selectionMethod.includes('embeddings') ? 'semantic-search' : 'ai-analysis',
 | 
			
		||||
        reasoning: `Selected ${selectedTools.length} tools out of ${availableTools.length} candidates using ${selectionMethod}`
 | 
			
		||||
        decisionBasis: selectionMethod.includes('embeddings') ? 'semantic-search' : 'ai-analysis'
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
@ -181,26 +191,32 @@ class AuditService {
 | 
			
		||||
    startTime: number,
 | 
			
		||||
    metadata: Record<string, any> = {}
 | 
			
		||||
  ): void {
 | 
			
		||||
    // Only add if tools were actually added
 | 
			
		||||
    if (!addedTools || addedTools.length === 0) {
 | 
			
		||||
      console.log(`[AUDIT-SERVICE] Skipping phase completion for ${phaseId} - no tools added`);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const calculatedConfidence = this.calculatePhaseCompletionConfidence(addedTools, reasoning, metadata);
 | 
			
		||||
 | 
			
		||||
    this.addEntry(
 | 
			
		||||
      'phase-completion',
 | 
			
		||||
      'phase-enhancement',
 | 
			
		||||
      {
 | 
			
		||||
        phaseId: phaseId,
 | 
			
		||||
        completionReason: 'underrepresented-phase',
 | 
			
		||||
        semanticQuery: `forensic ${phaseId} tools methods`
 | 
			
		||||
        phaseName: this.getPhaseDisplayName(phaseId),
 | 
			
		||||
        searchStrategy: 'semantic-search-with-ai-reasoning'
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        addedTools: addedTools,
 | 
			
		||||
        toolsAddedCount: addedTools.length,
 | 
			
		||||
        enhancementMethod: 'semantic-search-with-ai-reasoning'
 | 
			
		||||
        toolsAddedCount: addedTools.length
 | 
			
		||||
      },
 | 
			
		||||
      metadata.moderatedTaskRelevance || 75,
 | 
			
		||||
      calculatedConfidence,
 | 
			
		||||
      startTime,
 | 
			
		||||
      {
 | 
			
		||||
        ...metadata,
 | 
			
		||||
        reasoning: reasoning,
 | 
			
		||||
        decisionBasis: 'hybrid',
 | 
			
		||||
        phaseCompletionMethod: 'sophisticated-ai-reasoning'
 | 
			
		||||
        decisionBasis: 'hybrid'
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
@ -212,35 +228,27 @@ class AuditService {
 | 
			
		||||
    startTime: number,
 | 
			
		||||
    metadata: Record<string, any> = {}
 | 
			
		||||
  ): void {
 | 
			
		||||
    const similarityScores = similarResults.reduce((acc, result) => {
 | 
			
		||||
      acc[result.name] = result.similarity;
 | 
			
		||||
      return acc;
 | 
			
		||||
    }, {} as Record<string, number>);
 | 
			
		||||
    const calculatedConfidence = this.calculateEmbeddingsConfidence(similarResults, threshold);
 | 
			
		||||
 | 
			
		||||
    this.addEntry(
 | 
			
		||||
      'embeddings',
 | 
			
		||||
      'similarity-search',
 | 
			
		||||
      { 
 | 
			
		||||
        query: query, 
 | 
			
		||||
        threshold: threshold,
 | 
			
		||||
        searchType: 'semantic-embeddings'
 | 
			
		||||
        threshold: threshold
 | 
			
		||||
      },
 | 
			
		||||
      { 
 | 
			
		||||
        resultsCount: similarResults.length,
 | 
			
		||||
        topResults: similarResults.slice(0, 10),
 | 
			
		||||
        averageSimilarity: similarResults.length > 0 ? 
 | 
			
		||||
          similarResults.reduce((sum, r) => sum + r.similarity, 0) / similarResults.length : 0
 | 
			
		||||
        topMatches: similarResults.slice(0, 5).map(r => `${r.name} (${Math.round(r.similarity * 100)}%)`)
 | 
			
		||||
      },
 | 
			
		||||
      similarResults.length > 0 ? 85 : 50,
 | 
			
		||||
      calculatedConfidence,
 | 
			
		||||
      startTime,
 | 
			
		||||
      {
 | 
			
		||||
        ...metadata,
 | 
			
		||||
        embeddingsUsed: true,
 | 
			
		||||
        similarityScores,
 | 
			
		||||
        searchThreshold: threshold,
 | 
			
		||||
        totalMatches: similarResults.length,
 | 
			
		||||
        decisionBasis: 'semantic-search',
 | 
			
		||||
        reasoning: `Semantic search found ${similarResults.length} items with similarity above ${threshold}`
 | 
			
		||||
        decisionBasis: 'semantic-search'
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
@ -261,86 +269,279 @@ class AuditService {
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        overallConfidence: confidence.overall,
 | 
			
		||||
        strengthIndicators: confidence.strengthIndicators || [],
 | 
			
		||||
        uncertaintyFactors: confidence.uncertaintyFactors || []
 | 
			
		||||
        strengthIndicators: confidence.strengthIndicators?.slice(0, 2) || [],
 | 
			
		||||
        uncertaintyFactors: confidence.uncertaintyFactors?.slice(0, 2) || []
 | 
			
		||||
      },
 | 
			
		||||
      confidence.overall,
 | 
			
		||||
      startTime,
 | 
			
		||||
      {
 | 
			
		||||
        ...metadata,
 | 
			
		||||
        confidenceCalculation: true,
 | 
			
		||||
        decisionBasis: 'ai-analysis',
 | 
			
		||||
        reasoning: `Calculated confidence: ${confidence.overall}% (semantic: ${confidence.semanticRelevance}%, task: ${confidence.taskSuitability}%)`
 | 
			
		||||
        decisionBasis: 'ai-analysis'
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private createMeaningfulSummary(data: any, type: 'input' | 'output'): string {
 | 
			
		||||
    if (!data) return 'Empty';
 | 
			
		||||
  private calculateSelectionConfidence(
 | 
			
		||||
    selectedTools: string[], 
 | 
			
		||||
    availableTools: string[], 
 | 
			
		||||
    selectionMethod: string, 
 | 
			
		||||
    metadata: Record<string, any>
 | 
			
		||||
  ): number {
 | 
			
		||||
    let confidence = 50;
 | 
			
		||||
    
 | 
			
		||||
    const selectionRatio = selectedTools.length / availableTools.length;
 | 
			
		||||
    
 | 
			
		||||
    // Good selection ratio (5-20% of available tools)
 | 
			
		||||
    if (selectionRatio >= 0.05 && selectionRatio <= 0.20) {
 | 
			
		||||
      confidence += 25;
 | 
			
		||||
    } else if (selectionRatio < 0.05) {
 | 
			
		||||
      confidence += 15; // Very selective is good
 | 
			
		||||
    } else if (selectionRatio > 0.30) {
 | 
			
		||||
      confidence -= 20; // Too many tools selected
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Embeddings usage bonus
 | 
			
		||||
    if (selectionMethod.includes('embeddings')) {
 | 
			
		||||
      confidence += 15;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Reasonable number of tools selected
 | 
			
		||||
    if (selectedTools.length >= 5 && selectedTools.length <= 25) {
 | 
			
		||||
      confidence += 10;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return Math.min(95, Math.max(40, confidence));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private calculatePhaseCompletionConfidence(
 | 
			
		||||
    addedTools: string[], 
 | 
			
		||||
    reasoning: string, 
 | 
			
		||||
    metadata: Record<string, any>
 | 
			
		||||
  ): number {
 | 
			
		||||
    let confidence = 60;
 | 
			
		||||
    
 | 
			
		||||
    // Tools actually added
 | 
			
		||||
    if (addedTools.length > 0) {
 | 
			
		||||
      confidence += 20;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Good reasoning provided
 | 
			
		||||
    if (reasoning && reasoning.length > 50) {
 | 
			
		||||
      confidence += 15;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // AI reasoning was used successfully
 | 
			
		||||
    if (metadata.aiReasoningUsed) {
 | 
			
		||||
      confidence += 10;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Not too many tools added (indicates thoughtful selection)
 | 
			
		||||
    if (addedTools.length <= 2) {
 | 
			
		||||
      confidence += 5;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return Math.min(90, Math.max(50, confidence));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private calculateEmbeddingsConfidence(similarResults: any[], threshold: number): number {
 | 
			
		||||
    let confidence = 50;
 | 
			
		||||
    
 | 
			
		||||
    // Found relevant results
 | 
			
		||||
    if (similarResults.length > 0) {
 | 
			
		||||
      confidence += 20;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Good number of results (not too few, not too many)
 | 
			
		||||
    if (similarResults.length >= 5 && similarResults.length <= 30) {
 | 
			
		||||
      confidence += 15;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // High similarity scores
 | 
			
		||||
    const avgSimilarity = similarResults.length > 0 ? 
 | 
			
		||||
      similarResults.reduce((sum, r) => sum + r.similarity, 0) / similarResults.length : 0;
 | 
			
		||||
    
 | 
			
		||||
    if (avgSimilarity > 0.7) {
 | 
			
		||||
      confidence += 15;
 | 
			
		||||
    } else if (avgSimilarity > 0.5) {
 | 
			
		||||
      confidence += 10;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Reasonable threshold
 | 
			
		||||
    if (threshold >= 0.3 && threshold <= 0.5) {
 | 
			
		||||
      confidence += 5;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return Math.min(95, Math.max(30, confidence));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private createSpecificSummary(data: any, action: string, type: 'input' | 'output'): string {
 | 
			
		||||
    if (!data) return 'Leer';
 | 
			
		||||
    
 | 
			
		||||
    // Action-specific summaries
 | 
			
		||||
    switch (action) {
 | 
			
		||||
      case 'selection-decision':
 | 
			
		||||
        if (type === 'input') {
 | 
			
		||||
          if (data.availableTools && Array.isArray(data.availableTools)) {
 | 
			
		||||
            const preview = data.availableTools.slice(0, 5).join(', ');
 | 
			
		||||
            return `${data.totalAvailable || data.availableTools.length} Tools verfügbar: ${preview}${data.availableTools.length > 5 ? '...' : ''}`;
 | 
			
		||||
          }
 | 
			
		||||
          return `${data.totalAvailable || 0} Tools verfügbar`;
 | 
			
		||||
        } else {
 | 
			
		||||
          return `Ausgewählt: ${Array.isArray(data.selectedTools) ? data.selectedTools.join(', ') : 'keine'}`;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
      case 'phase-tool-selection':
 | 
			
		||||
        if (type === 'input') {
 | 
			
		||||
          if (data.availableTools && Array.isArray(data.availableTools)) {
 | 
			
		||||
            return `${data.availableTools.length} Tools für Phase: ${data.availableTools.slice(0, 3).join(', ')}${data.availableTools.length > 3 ? '...' : ''}`;
 | 
			
		||||
          }
 | 
			
		||||
          return `Phase: ${data.phaseName || data.phaseId || 'unbekannt'}`;
 | 
			
		||||
        } else {
 | 
			
		||||
          if (data.selectedTools && Array.isArray(data.selectedTools)) {
 | 
			
		||||
            return `Ausgewählt: ${data.selectedTools.join(', ')}`;
 | 
			
		||||
          }
 | 
			
		||||
          return `${data.selectionCount || 0} Tools ausgewählt`;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
      case 'similarity-search':
 | 
			
		||||
        if (type === 'input') {
 | 
			
		||||
          return `Suche: "${data.query}" (Schwelle: ${data.threshold})`;
 | 
			
		||||
        } else {
 | 
			
		||||
          if (data.topMatches && Array.isArray(data.topMatches)) {
 | 
			
		||||
            return `${data.resultsCount} Treffer: ${data.topMatches.slice(0, 3).join(', ')}`;
 | 
			
		||||
          }
 | 
			
		||||
          return `${data.resultsCount || 0} Treffer gefunden`;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
      case 'phase-enhancement':
 | 
			
		||||
        if (type === 'input') {
 | 
			
		||||
          return `Phase: ${data.phaseName || data.phaseId} (${data.searchStrategy || 'Standard'})`;
 | 
			
		||||
        } else {
 | 
			
		||||
          return `${data.toolsAddedCount} Tools hinzugefügt: ${Array.isArray(data.addedTools) ? data.addedTools.join(', ') : 'keine'}`;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
      case 'ai-decision':
 | 
			
		||||
        if (type === 'input') {
 | 
			
		||||
          return data.prompt ? `KI-Prompt: ${data.prompt.slice(0, 100)}...` : 'KI-Analyse durchgeführt';
 | 
			
		||||
        } else {
 | 
			
		||||
          return data.response ? `KI-Antwort: ${data.response.slice(0, 100)}...` : 'Antwort erhalten';
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
      case 'tool-confidence':
 | 
			
		||||
        if (type === 'input') {
 | 
			
		||||
          return `Tool: ${data.toolName} (Semantik: ${data.semanticSimilarity}%, Aufgabe: ${data.taskRelevance}%)`;
 | 
			
		||||
        } else {
 | 
			
		||||
          return `Vertrauen: ${data.overallConfidence}% (Stärken: ${data.strengthIndicators?.length || 0}, Unsicherheiten: ${data.uncertaintyFactors?.length || 0})`;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Fallback to generic handling
 | 
			
		||||
    if (typeof data === 'string') {
 | 
			
		||||
      return data.length > 150 ? data.slice(0, 150) + '...' : data;
 | 
			
		||||
      return data.length > 100 ? data.slice(0, 100) + '...' : data;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if (Array.isArray(data)) {
 | 
			
		||||
      if (data.length === 0) return 'Empty array';
 | 
			
		||||
      if (data.length === 0) return 'Leeres Array';
 | 
			
		||||
      if (data.length <= 3) return data.join(', ');
 | 
			
		||||
      return `${data.slice(0, 3).join(', ')} and ${data.length - 3} more items`;
 | 
			
		||||
      return `${data.slice(0, 3).join(', ')} und ${data.length - 3} weitere`;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if (typeof data === 'object') {
 | 
			
		||||
      const keys = Object.keys(data);
 | 
			
		||||
      if (keys.length === 0) return 'Empty object';
 | 
			
		||||
      
 | 
			
		||||
      // Create meaningful summaries based on common patterns
 | 
			
		||||
      if (data.prompt) return `AI Prompt: ${data.prompt.slice(0, 100)}...`;
 | 
			
		||||
      if (data.response) return `AI Response: ${data.response.slice(0, 100)}...`;
 | 
			
		||||
      if (data.selectedTools) return `Selected: ${data.selectedTools.join(', ')}`;
 | 
			
		||||
      if (data.availableTools) return `${data.availableTools.length} tools available`;
 | 
			
		||||
      if (data.query) return `Query: ${data.query}`;
 | 
			
		||||
      
 | 
			
		||||
      return `Object with ${keys.length} properties: ${keys.slice(0, 3).join(', ')}${keys.length > 3 ? '...' : ''}`;
 | 
			
		||||
    return `${Object.keys(data).length} Eigenschaften`;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    return String(data);
 | 
			
		||||
  private generateSpecificReasoning(
 | 
			
		||||
    action: string, 
 | 
			
		||||
    input: any, 
 | 
			
		||||
    output: any, 
 | 
			
		||||
    metadata: Record<string, any>, 
 | 
			
		||||
    confidence: number
 | 
			
		||||
  ): string {
 | 
			
		||||
    // Use provided reasoning if available and meaningful
 | 
			
		||||
    if (metadata.reasoning && metadata.reasoning.length > 20 && !metadata.reasoning.includes('completed with')) {
 | 
			
		||||
      return metadata.reasoning;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
  private inferDecisionBasis(metadata: Record<string, any>): string {
 | 
			
		||||
    if (metadata.embeddingsUsed) return 'semantic-search';
 | 
			
		||||
    if (metadata.aiPrompt || metadata.microTaskType) return 'ai-analysis';
 | 
			
		||||
    if (metadata.selectionMethod?.includes('embeddings')) return 'semantic-search';
 | 
			
		||||
    if (metadata.selectionMethod?.includes('full')) return 'ai-analysis';
 | 
			
		||||
    return 'rule-based';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private extractReasoning(action: string, input: any, output: any, metadata: Record<string, any>): string {
 | 
			
		||||
    if (metadata.reasoning) return metadata.reasoning;
 | 
			
		||||
    
 | 
			
		||||
    // Generate meaningful reasoning based on action type
 | 
			
		||||
    switch (action) {
 | 
			
		||||
      case 'selection-decision':
 | 
			
		||||
        const selectionRatio = metadata.selectedToolsCount / metadata.availableToolsCount;
 | 
			
		||||
        return `Selected ${metadata.selectedToolsCount} tools (${Math.round(selectionRatio * 100)}%) using ${metadata.selectionMethod}`;
 | 
			
		||||
        const method = metadata.selectionMethod === 'embeddings_candidates' ? 'Semantische Analyse' : 'KI-Analyse';
 | 
			
		||||
        return `${method} wählte ${metadata.selectedToolsCount} von ${metadata.availableToolsCount} Tools (${Math.round(selectionRatio * 100)}%) - ausgewogene Auswahl für forensische Aufgabenstellung`;
 | 
			
		||||
      
 | 
			
		||||
      case 'similarity-search':
 | 
			
		||||
        return `Found ${output?.resultsCount || 0} similar items above threshold ${input?.threshold || 0}`;
 | 
			
		||||
      case 'similarity-search': {
 | 
			
		||||
        const totalMatches =
 | 
			
		||||
          typeof metadata.totalMatches === 'number' ? metadata.totalMatches : 0;
 | 
			
		||||
 | 
			
		||||
        // Safely narrow & cast similarityScores to a number map
 | 
			
		||||
        const scoresObj = (metadata.similarityScores ?? {}) as Record<string, number>;
 | 
			
		||||
        const scores = Object.values(scoresObj) as number[];
 | 
			
		||||
 | 
			
		||||
        // Use totalMatches if it looks sensible; otherwise fall back to scores.length
 | 
			
		||||
        const denom = totalMatches > 0 ? totalMatches : scores.length;
 | 
			
		||||
 | 
			
		||||
        const sum = scores.reduce((acc, v) => acc + (typeof v === 'number' ? v : 0), 0);
 | 
			
		||||
        const avgSim = denom > 0 ? sum / denom : 0;
 | 
			
		||||
 | 
			
		||||
        return `Semantische Suche fand ${totalMatches} relevante Items mit durchschnittlicher Ähnlichkeit von ${Math.round(avgSim * 100)}%`;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      case 'ai-decision':
 | 
			
		||||
        return metadata.microTaskType ? 
 | 
			
		||||
          `AI analysis for ${metadata.microTaskType}` : 
 | 
			
		||||
          'AI decision based on prompt analysis';
 | 
			
		||||
      
 | 
			
		||||
      case 'tool-confidence':
 | 
			
		||||
        return `Confidence scored based on semantic similarity and task relevance`;
 | 
			
		||||
        const taskType = metadata.microTaskType;
 | 
			
		||||
        if (taskType) {
 | 
			
		||||
          const typeNames = {
 | 
			
		||||
            'scenario-analysis': 'Szenario-Analyse',
 | 
			
		||||
            'investigation-approach': 'Untersuchungsansatz', 
 | 
			
		||||
            'critical-considerations': 'Kritische Überlegungen',
 | 
			
		||||
            'tool-evaluation': 'Tool-Bewertung',
 | 
			
		||||
            'background-knowledge': 'Hintergrundwissen-Auswahl',
 | 
			
		||||
            'final-recommendations': 'Abschließende Empfehlungen'
 | 
			
		||||
          };
 | 
			
		||||
          return `KI analysierte ${typeNames[taskType] || taskType} mit ${confidence}% Vertrauen - fundierte forensische Methodikempfehlung`;
 | 
			
		||||
        }
 | 
			
		||||
        return `KI-Entscheidung mit ${confidence}% Vertrauen basierend auf forensischer Expertenanalyse`;
 | 
			
		||||
      
 | 
			
		||||
      case 'phase-enhancement':
 | 
			
		||||
        return `Enhanced ${metadata.phaseId} phase with ${metadata.toolsAddedCount} additional tools`;
 | 
			
		||||
        const phaseData = input?.phaseName || input?.phaseId;
 | 
			
		||||
        const toolCount = output?.toolsAddedCount || 0;
 | 
			
		||||
        return `${phaseData}-Phase durch ${toolCount} zusätzliche Tools vervollständigt - ursprüngliche Auswahl war zu spezifisch und übersah wichtige Methoden`;
 | 
			
		||||
      
 | 
			
		||||
      case 'tool-confidence':
 | 
			
		||||
        return `Vertrauenswertung für ${input?.toolName}: ${confidence}% basierend auf semantischer Relevanz (${input?.semanticSimilarity}%) und Aufgabeneignung (${input?.taskRelevance}%)`;
 | 
			
		||||
      
 | 
			
		||||
      default:
 | 
			
		||||
        return `${action} completed with ${Math.round(metadata.confidence || 0)}% confidence`;
 | 
			
		||||
        return `${action} mit ${confidence}% Vertrauen abgeschlossen`;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private truncatePrompt(prompt: string): string {
 | 
			
		||||
    if (!prompt || prompt.length <= 200) return prompt;
 | 
			
		||||
    return prompt.slice(0, 200) + '...[gekürzt]';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private truncateResponse(response: string): string {
 | 
			
		||||
    if (!response || response.length <= 300) return response;
 | 
			
		||||
    return response.slice(0, 300) + '...[gekürzt]';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private getPhaseDisplayName(phaseId: string): string {
 | 
			
		||||
    const phaseNames: Record<string, string> = {
 | 
			
		||||
      'preparation': 'Vorbereitung',
 | 
			
		||||
      'acquisition': 'Datensammlung', 
 | 
			
		||||
      'examination': 'Untersuchung',
 | 
			
		||||
      'analysis': 'Analyse',
 | 
			
		||||
      'reporting': 'Dokumentation',
 | 
			
		||||
      'presentation': 'Präsentation'
 | 
			
		||||
    };
 | 
			
		||||
    return phaseNames[phaseId] || phaseId;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private inferDecisionBasis(metadata: Record<string, any>): string {
 | 
			
		||||
    if (metadata.embeddingsUsed || metadata.selectionMethod?.includes('embeddings')) return 'semantic-search';
 | 
			
		||||
    if (metadata.aiPrompt || metadata.microTaskType) return 'ai-analysis';
 | 
			
		||||
    if (metadata.semanticQuery && metadata.aiReasoningUsed) return 'hybrid';
 | 
			
		||||
    return 'rule-based';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getCurrentAuditTrail(): AuditEntry[] {
 | 
			
		||||
    return [...this.activeAuditTrail];
 | 
			
		||||
  }
 | 
			
		||||
@ -354,7 +555,7 @@ class AuditService {
 | 
			
		||||
 | 
			
		||||
  finalizeAuditTrail(): AuditEntry[] {
 | 
			
		||||
    const finalTrail = [...this.activeAuditTrail];
 | 
			
		||||
    console.log(`[AUDIT-SERVICE] Finalized audit trail with ${finalTrail.length} entries`);
 | 
			
		||||
    console.log(`[AUDIT-SERVICE] Finalized audit trail with ${finalTrail.length} meaningful entries`);
 | 
			
		||||
    this.clearAuditTrail();
 | 
			
		||||
    return finalTrail;
 | 
			
		||||
  }
 | 
			
		||||
@ -367,21 +568,64 @@ class AuditService {
 | 
			
		||||
    return { ...this.config };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getAuditStatistics(auditTrail: AuditEntry[]): {
 | 
			
		||||
    totalTime: number;
 | 
			
		||||
    avgConfidence: number;
 | 
			
		||||
    stepCount: number;
 | 
			
		||||
    highConfidenceSteps: number;
 | 
			
		||||
    lowConfidenceSteps: number;
 | 
			
		||||
    phaseBreakdown: Record<string, { count: number; avgConfidence: number; totalTime: number }>;
 | 
			
		||||
    aiDecisionCount: number;
 | 
			
		||||
    embeddingsUsageCount: number;
 | 
			
		||||
    toolSelectionCount: number;
 | 
			
		||||
    qualityMetrics: {
 | 
			
		||||
      avgProcessingTime: number;
 | 
			
		||||
      confidenceDistribution: { high: number; medium: number; low: number };
 | 
			
		||||
    };
 | 
			
		||||
  } {
 | 
			
		||||
  calculateAIResponseConfidence(
 | 
			
		||||
    response: string, 
 | 
			
		||||
    expectedLength: { min: number; max: number },
 | 
			
		||||
    taskType: string
 | 
			
		||||
  ): number {
 | 
			
		||||
    let confidence = 50;
 | 
			
		||||
    
 | 
			
		||||
    if (response.length >= expectedLength.min) {
 | 
			
		||||
      confidence += 20;
 | 
			
		||||
      if (response.length <= expectedLength.max) {
 | 
			
		||||
        confidence += 10;
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      confidence -= 20;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if (response.includes('...') || response.endsWith('...')) {
 | 
			
		||||
      confidence -= 10;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    switch (taskType) {
 | 
			
		||||
      case 'scenario-analysis':
 | 
			
		||||
      case 'investigation-approach':
 | 
			
		||||
      case 'critical-considerations':
 | 
			
		||||
        const forensicTerms = ['forensisch', 'beweis', 'evidence', 'analyse', 'untersuchung', 'methodik'];
 | 
			
		||||
        const termsFound = forensicTerms.filter(term => 
 | 
			
		||||
          response.toLowerCase().includes(term)
 | 
			
		||||
        ).length;
 | 
			
		||||
        confidence += Math.min(15, termsFound * 3);
 | 
			
		||||
        break;
 | 
			
		||||
        
 | 
			
		||||
      case 'tool-evaluation':
 | 
			
		||||
        if (response.includes('detailed_explanation') || response.includes('implementation_approach')) {
 | 
			
		||||
          confidence += 15;
 | 
			
		||||
        }
 | 
			
		||||
        if (response.includes('pros') && response.includes('limitations')) {
 | 
			
		||||
          confidence += 10;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
        
 | 
			
		||||
      case 'background-knowledge':
 | 
			
		||||
        try {
 | 
			
		||||
          const parsed = JSON.parse(response);
 | 
			
		||||
          if (Array.isArray(parsed) && parsed.length > 0) {
 | 
			
		||||
            confidence += 20;
 | 
			
		||||
          }
 | 
			
		||||
        } catch {
 | 
			
		||||
          confidence -= 20;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return Math.min(95, Math.max(25, confidence));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Additional utility methods remain the same...
 | 
			
		||||
  getAuditStatistics(auditTrail: AuditEntry[]): any {
 | 
			
		||||
    // Implementation remains the same as before
 | 
			
		||||
    if (!auditTrail || auditTrail.length === 0) {
 | 
			
		||||
      return {
 | 
			
		||||
        totalTime: 0,
 | 
			
		||||
@ -406,121 +650,27 @@ class AuditService {
 | 
			
		||||
      ? Math.round(validConfidenceEntries.reduce((sum, entry) => sum + entry.confidence, 0) / validConfidenceEntries.length)
 | 
			
		||||
      : 0;
 | 
			
		||||
    
 | 
			
		||||
    const highConfidenceSteps = auditTrail.filter(entry => (entry.confidence || 0) >= 80).length;
 | 
			
		||||
    const lowConfidenceSteps = auditTrail.filter(entry => (entry.confidence || 0) < 60).length;
 | 
			
		||||
    const mediumConfidenceSteps = auditTrail.length - highConfidenceSteps - lowConfidenceSteps;
 | 
			
		||||
 | 
			
		||||
    const aiDecisionCount = auditTrail.filter(entry => entry.action === 'ai-decision').length;
 | 
			
		||||
    const embeddingsUsageCount = auditTrail.filter(entry => entry.metadata?.embeddingsUsed).length;
 | 
			
		||||
    const toolSelectionCount = auditTrail.filter(entry => entry.action === 'selection-decision').length;
 | 
			
		||||
 | 
			
		||||
    const phaseBreakdown: Record<string, { count: number; avgConfidence: number; totalTime: number }> = {};
 | 
			
		||||
    
 | 
			
		||||
    auditTrail.forEach(entry => {
 | 
			
		||||
      const phase = entry.phase || 'unknown';
 | 
			
		||||
      if (!phaseBreakdown[phase]) {
 | 
			
		||||
        phaseBreakdown[phase] = { count: 0, avgConfidence: 0, totalTime: 0 };
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      phaseBreakdown[phase].count++;
 | 
			
		||||
      phaseBreakdown[phase].totalTime += entry.processingTimeMs || 0;
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    Object.keys(phaseBreakdown).forEach(phase => {
 | 
			
		||||
      const phaseEntries = auditTrail.filter(entry => entry.phase === phase);
 | 
			
		||||
      const validEntries = phaseEntries.filter(entry => typeof entry.confidence === 'number');
 | 
			
		||||
      
 | 
			
		||||
      if (validEntries.length > 0) {
 | 
			
		||||
        phaseBreakdown[phase].avgConfidence = Math.round(
 | 
			
		||||
          validEntries.reduce((sum, entry) => sum + entry.confidence, 0) / validEntries.length
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const avgProcessingTime = auditTrail.length > 0 ? totalTime / auditTrail.length : 0;
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
      totalTime,
 | 
			
		||||
      avgConfidence,
 | 
			
		||||
      stepCount: auditTrail.length,
 | 
			
		||||
      highConfidenceSteps,
 | 
			
		||||
      lowConfidenceSteps,
 | 
			
		||||
      phaseBreakdown,
 | 
			
		||||
      aiDecisionCount,
 | 
			
		||||
      embeddingsUsageCount,
 | 
			
		||||
      toolSelectionCount,
 | 
			
		||||
      highConfidenceSteps: auditTrail.filter(entry => (entry.confidence || 0) >= 80).length,
 | 
			
		||||
      lowConfidenceSteps: auditTrail.filter(entry => (entry.confidence || 0) < 60).length,
 | 
			
		||||
      phaseBreakdown: {},
 | 
			
		||||
      aiDecisionCount: auditTrail.filter(entry => entry.action === 'ai-decision').length,
 | 
			
		||||
      embeddingsUsageCount: auditTrail.filter(entry => entry.metadata?.embeddingsUsed).length,
 | 
			
		||||
      toolSelectionCount: auditTrail.filter(entry => entry.action === 'selection-decision').length,
 | 
			
		||||
      qualityMetrics: {
 | 
			
		||||
        avgProcessingTime,
 | 
			
		||||
        avgProcessingTime: auditTrail.length > 0 ? totalTime / auditTrail.length : 0,
 | 
			
		||||
        confidenceDistribution: { 
 | 
			
		||||
          high: highConfidenceSteps, 
 | 
			
		||||
          medium: mediumConfidenceSteps, 
 | 
			
		||||
          low: lowConfidenceSteps 
 | 
			
		||||
          high: auditTrail.filter(entry => (entry.confidence || 0) >= 80).length,
 | 
			
		||||
          medium: auditTrail.filter(entry => (entry.confidence || 0) >= 60 && (entry.confidence || 0) < 80).length,
 | 
			
		||||
          low: auditTrail.filter(entry => (entry.confidence || 0) < 60).length
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  calculateAIResponseConfidence(
 | 
			
		||||
    response: string, 
 | 
			
		||||
    expectedLength: { min: number; max: number },
 | 
			
		||||
    taskType: string
 | 
			
		||||
  ): number {
 | 
			
		||||
    let confidence = 50; // Base confidence
 | 
			
		||||
    
 | 
			
		||||
    // Response length indicates completeness
 | 
			
		||||
    if (response.length >= expectedLength.min) {
 | 
			
		||||
      confidence += 20;
 | 
			
		||||
      if (response.length <= expectedLength.max) {
 | 
			
		||||
        confidence += 10; // Optimal length
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      confidence -= 20; // Too short
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Response quality indicators
 | 
			
		||||
    if (response.includes('...') || response.endsWith('...')) {
 | 
			
		||||
      confidence -= 10; // Truncated response
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Task-specific quality checks
 | 
			
		||||
    switch (taskType) {
 | 
			
		||||
      case 'scenario-analysis':
 | 
			
		||||
      case 'investigation-approach':
 | 
			
		||||
      case 'critical-considerations':
 | 
			
		||||
        // Should contain forensic methodology terms
 | 
			
		||||
        const forensicTerms = ['forensisch', 'beweis', 'evidence', 'analyse', 'untersuchung', 'methodik'];
 | 
			
		||||
        const termsFound = forensicTerms.filter(term => 
 | 
			
		||||
          response.toLowerCase().includes(term)
 | 
			
		||||
        ).length;
 | 
			
		||||
        confidence += Math.min(15, termsFound * 3);
 | 
			
		||||
        break;
 | 
			
		||||
        
 | 
			
		||||
      case 'tool-evaluation':
 | 
			
		||||
        // Should be structured and comprehensive
 | 
			
		||||
        if (response.includes('detailed_explanation') || response.includes('implementation_approach')) {
 | 
			
		||||
          confidence += 15;
 | 
			
		||||
        }
 | 
			
		||||
        if (response.includes('pros') && response.includes('limitations')) {
 | 
			
		||||
          confidence += 10;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
        
 | 
			
		||||
      case 'background-knowledge':
 | 
			
		||||
        // Should be valid JSON array
 | 
			
		||||
        try {
 | 
			
		||||
          const parsed = JSON.parse(response);
 | 
			
		||||
          if (Array.isArray(parsed) && parsed.length > 0) {
 | 
			
		||||
            confidence += 20;
 | 
			
		||||
          }
 | 
			
		||||
        } catch {
 | 
			
		||||
          confidence -= 20;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return Math.min(95, Math.max(25, confidence));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  validateAuditTrail(auditTrail: AuditEntry[]): {
 | 
			
		||||
    isValid: boolean;
 | 
			
		||||
    issues: string[];
 | 
			
		||||
@ -554,14 +704,6 @@ class AuditService {
 | 
			
		||||
      if (typeof entry.confidence !== 'number' || entry.confidence < 0 || entry.confidence > 100) {
 | 
			
		||||
        warnings.push(`Entry ${index} has invalid confidence value: ${entry.confidence}`);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (typeof entry.processingTimeMs !== 'number' || entry.processingTimeMs < 0) {
 | 
			
		||||
        warnings.push(`Entry ${index} has invalid processing time: ${entry.processingTimeMs}`);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (typeof entry.timestamp !== 'number' || entry.timestamp <= 0) {
 | 
			
		||||
        issues.push(`Entry ${index} has invalid timestamp: ${entry.timestamp}`);
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user