restore old after-confidence-scoring
This commit is contained in:
		
							parent
							
								
									8bba0eefa9
								
							
						
					
					
						commit
						afbd8d2cd3
					
				@ -50,7 +50,7 @@ const domainAgnosticSoftware = data['domain-agnostic-software'] || [];
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      <!-- Input Layout -->
 | 
					      <!-- Input Layout -->
 | 
				
			||||||
      <div class="ai-input-layout">
 | 
					      <div class="ai-input-layout">
 | 
				
			||||||
        <div class="ai-textarea-section">
 | 
					        <div class="ai-textarea-section" style="height: 200px">
 | 
				
			||||||
          <textarea 
 | 
					          <textarea 
 | 
				
			||||||
            id="ai-query-input" 
 | 
					            id="ai-query-input" 
 | 
				
			||||||
            placeholder="Beschreiben Sie Ihr forensisches Szenario..."
 | 
					            placeholder="Beschreiben Sie Ihr forensisches Szenario..."
 | 
				
			||||||
@ -1158,12 +1158,10 @@ class AIQueryInterface {
 | 
				
			|||||||
    const lowConfidenceSteps = auditTrail.filter(entry => (entry.confidence || 0) < 60).length;
 | 
					    const lowConfidenceSteps = auditTrail.filter(entry => (entry.confidence || 0) < 60).length;
 | 
				
			||||||
    const mediumConfidenceSteps = auditTrail.length - highConfidenceSteps - lowConfidenceSteps;
 | 
					    const mediumConfidenceSteps = auditTrail.length - highConfidenceSteps - lowConfidenceSteps;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Enhanced metrics
 | 
					 | 
				
			||||||
    const aiDecisionCount = auditTrail.filter(entry => entry.action === 'ai-decision').length;
 | 
					    const aiDecisionCount = auditTrail.filter(entry => entry.action === 'ai-decision').length;
 | 
				
			||||||
    const embeddingsUsageCount = auditTrail.filter(entry => entry.metadata?.embeddingsUsed).length;
 | 
					    const embeddingsUsageCount = auditTrail.filter(entry => entry.metadata?.embeddingsUsed).length;
 | 
				
			||||||
    const toolSelectionCount = auditTrail.filter(entry => entry.action === 'selection-decision').length;
 | 
					    const toolSelectionCount = auditTrail.filter(entry => entry.action === 'selection-decision').length;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Phase breakdown
 | 
					 | 
				
			||||||
    const phaseBreakdown = {};
 | 
					    const phaseBreakdown = {};
 | 
				
			||||||
    auditTrail.forEach(entry => {
 | 
					    auditTrail.forEach(entry => {
 | 
				
			||||||
      const phase = entry.phase || 'unknown';
 | 
					      const phase = entry.phase || 'unknown';
 | 
				
			||||||
@ -1175,7 +1173,6 @@ class AIQueryInterface {
 | 
				
			|||||||
      phaseBreakdown[phase].totalTime += entry.processingTimeMs || 0;
 | 
					      phaseBreakdown[phase].totalTime += entry.processingTimeMs || 0;
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Calculate average confidence per phase
 | 
					 | 
				
			||||||
    Object.keys(phaseBreakdown).forEach(phase => {
 | 
					    Object.keys(phaseBreakdown).forEach(phase => {
 | 
				
			||||||
      const phaseEntries = auditTrail.filter(entry => entry.phase === phase);
 | 
					      const phaseEntries = auditTrail.filter(entry => entry.phase === phase);
 | 
				
			||||||
      const validEntries = phaseEntries.filter(entry => typeof entry.confidence === 'number');
 | 
					      const validEntries = phaseEntries.filter(entry => typeof entry.confidence === 'number');
 | 
				
			||||||
@ -1191,7 +1188,6 @@ class AIQueryInterface {
 | 
				
			|||||||
    const aiTransparency = auditTrail.length > 0 ? 
 | 
					    const aiTransparency = auditTrail.length > 0 ? 
 | 
				
			||||||
      (auditTrail.filter(entry => entry.metadata?.aiPrompt || entry.metadata?.reasoning).length / auditTrail.length) * 100 : 0;
 | 
					      (auditTrail.filter(entry => entry.metadata?.aiPrompt || entry.metadata?.reasoning).length / auditTrail.length) * 100 : 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // RESTORED: Intelligent Analysis Quality Assessment
 | 
					 | 
				
			||||||
    let analysisQuality;
 | 
					    let analysisQuality;
 | 
				
			||||||
    if (avgConfidence >= 85 && lowConfidenceSteps === 0) {
 | 
					    if (avgConfidence >= 85 && lowConfidenceSteps === 0) {
 | 
				
			||||||
      analysisQuality = 'excellent';
 | 
					      analysisQuality = 'excellent';
 | 
				
			||||||
@ -1203,7 +1199,6 @@ class AIQueryInterface {
 | 
				
			|||||||
      analysisQuality = 'poor';
 | 
					      analysisQuality = 'poor';
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // RESTORED: Intelligent Insights Generation
 | 
					 | 
				
			||||||
    const keyInsights = [];
 | 
					    const keyInsights = [];
 | 
				
			||||||
    const embeddingsUsed = auditTrail.some(e => e.metadata?.embeddingsUsed);
 | 
					    const embeddingsUsed = auditTrail.some(e => e.metadata?.embeddingsUsed);
 | 
				
			||||||
    if (embeddingsUsed) {
 | 
					    if (embeddingsUsed) {
 | 
				
			||||||
@ -1226,7 +1221,6 @@ class AIQueryInterface {
 | 
				
			|||||||
      keyInsights.push('Mehrheit der Analyseschritte mit hoher Sicherheit');
 | 
					      keyInsights.push('Mehrheit der Analyseschritte mit hoher Sicherheit');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // RESTORED: Automatic Issue Detection (excluding processing time warnings)
 | 
					 | 
				
			||||||
    const potentialIssues = [];
 | 
					    const potentialIssues = [];
 | 
				
			||||||
    if (lowConfidenceSteps > 2) {
 | 
					    if (lowConfidenceSteps > 2) {
 | 
				
			||||||
      potentialIssues.push(`${lowConfidenceSteps} Analyseschritte mit niedriger Konfidenz`);
 | 
					      potentialIssues.push(`${lowConfidenceSteps} Analyseschritte mit niedriger Konfidenz`);
 | 
				
			||||||
 | 
				
			|||||||
@ -36,6 +36,11 @@ AUSWAHLSTRATEGIE:
 | 
				
			|||||||
  - Lieber weniger perfekte Items als viele mittelmäßige
 | 
					  - Lieber weniger perfekte Items als viele mittelmäßige
 | 
				
			||||||
  - Jedes Item muss begründbar sein
 | 
					  - Jedes Item muss begründbar sein
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					4. **TASK RELEVANCE REALISM**
 | 
				
			||||||
 | 
					  - Gib realistische Bewertungen (50-85% typisch)
 | 
				
			||||||
 | 
					  - Vermeide übertriebene 90-100% Scores
 | 
				
			||||||
 | 
					  - Nur bei perfekter Übereinstimmung >85%
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AUSWAHLREGELN:
 | 
					AUSWAHLREGELN:
 | 
				
			||||||
- Wähle ${mode === 'workflow' ? '15-25' : '4-10'} Items total, max ${maxSelectedItems}
 | 
					- Wähle ${mode === 'workflow' ? '15-25' : '4-10'} Items total, max ${maxSelectedItems}
 | 
				
			||||||
- BEIDE Arrays füllen: selectedTools UND selectedConcepts
 | 
					- BEIDE Arrays füllen: selectedTools UND selectedConcepts
 | 
				
			||||||
@ -59,7 +64,13 @@ ${JSON.stringify(toolsToSend, null, 2)}
 | 
				
			|||||||
VERFÜGBARE KONZEPTE (${conceptsToSend.length} Items - theoretisches Wissen):
 | 
					VERFÜGBARE KONZEPTE (${conceptsToSend.length} Items - theoretisches Wissen):
 | 
				
			||||||
${JSON.stringify(conceptsToSend, null, 2)}
 | 
					${JSON.stringify(conceptsToSend, null, 2)}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
WICHTIGER HINWEIS: Wähle sowohl aus TOOLS als auch aus KONZEPTEN aus! Konzepte sind essentiell für methodische Fundierung.`;
 | 
					WICHTIGER HINWEIS: Wähle sowohl aus TOOLS als auch aus KONZEPTEN aus! Konzepte sind essentiell für methodische Fundierung.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TASK RELEVANCE GUIDELINES:
 | 
				
			||||||
 | 
					- 50-65%: Grundlegend relevant, aber nicht optimal
 | 
				
			||||||
 | 
					- 66-75%: Gut geeignet für die Aufgabe
 | 
				
			||||||
 | 
					- 76-85%: Sehr gut geeignet, klare Vorteile
 | 
				
			||||||
 | 
					- 86-100%: NUR für perfekte Übereinstimmung verwenden`;
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  scenarioAnalysis: (isWorkflow: boolean, userQuery: string) => {
 | 
					  scenarioAnalysis: (isWorkflow: boolean, userQuery: string) => {
 | 
				
			||||||
@ -148,13 +159,19 @@ AUSWAHLREGELN FÜR PHASE "${phase.name}":
 | 
				
			|||||||
3. Mindestens 1 Methode wenn verfügbar, Rest Software-Tools
 | 
					3. Mindestens 1 Methode wenn verfügbar, Rest Software-Tools
 | 
				
			||||||
4. Begründe WARUM jedes Item für diese Phase optimal ist
 | 
					4. Begründe WARUM jedes Item für diese Phase optimal ist
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TASK RELEVANCE GUIDELINES:
 | 
				
			||||||
 | 
					- 60-70%: Grundlegend für diese Phase geeignet
 | 
				
			||||||
 | 
					- 71-80%: Gut geeignet, klare Phasenrelevanz
 | 
				
			||||||
 | 
					- 81-90%: Sehr gut geeignet, optimal für Phase
 | 
				
			||||||
 | 
					- 91-100%: NUR für perfekte Phasenübereinstimmung
 | 
				
			||||||
 | 
					
 | 
				
			||||||
WICHTIG: Verwende EXAKT die Namen wie oben aufgelistet (ohne Präfixe wie M1./T2.)!
 | 
					WICHTIG: Verwende EXAKT die Namen wie oben aufgelistet (ohne Präfixe wie M1./T2.)!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ANTWORT AUSSCHLIESSLICH IM JSON-FORMAT OHNE JEGLICHEN TEXT AUSSERHALB:
 | 
					ANTWORT AUSSCHLIESSLICH IM JSON-FORMAT OHNE JEGLICHEN TEXT AUSSERHALB:
 | 
				
			||||||
[
 | 
					[
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    "toolName": "Exakter Name aus der Liste oben",
 | 
					    "toolName": "Exakter Name aus der Liste oben",
 | 
				
			||||||
    "taskRelevance": 85,
 | 
					    "taskRelevance": 75,
 | 
				
			||||||
    "justification": "Detaillierte Begründung (60-80 Wörter) warum optimal für ${phase.name} - erkläre Anwendung, Vorteile und spezifische Relevanz",
 | 
					    "justification": "Detaillierte Begründung (60-80 Wörter) warum optimal für ${phase.name} - erkläre Anwendung, Vorteile und spezifische Relevanz",
 | 
				
			||||||
    "limitations": ["Mögliche Einschränkung für diese Phase"]
 | 
					    "limitations": ["Mögliche Einschränkung für diese Phase"]
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -266,6 +283,7 @@ AUSWAHLREGELN FÜR NACHERGÄNZUNG:
 | 
				
			|||||||
1. Wähle 1-2 BESTE Methoden/Tools die die ${phase.name}-Phase optimal ergänzen
 | 
					1. Wähle 1-2 BESTE Methoden/Tools die die ${phase.name}-Phase optimal ergänzen
 | 
				
			||||||
2. Methoden/Tools müssen für die ursprüngliche Anfrage relevant sein
 | 
					2. Methoden/Tools müssen für die ursprüngliche Anfrage relevant sein
 | 
				
			||||||
3. Ergänzen, nicht ersetzen - erweitere die zu spezifische Erstauswahl
 | 
					3. Ergänzen, nicht ersetzen - erweitere die zu spezifische Erstauswahl
 | 
				
			||||||
 | 
					4. Realistische Task Relevance (70-85% typisch für Nachergänzungen)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ANTWORT AUSSCHLIESSLICH IM JSON-FORMAT:
 | 
					ANTWORT AUSSCHLIESSLICH IM JSON-FORMAT:
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
				
			|||||||
@ -1,11 +1,11 @@
 | 
				
			|||||||
// src/utils/aiPipeline.ts - Enhanced with comprehensive audit logging
 | 
					// src/utils/aiPipeline.ts - Enhanced with comprehensive audit logging and restored sophisticated logic
 | 
				
			||||||
import { getCompressedToolsDataForAI, getDataVersion } from './dataService.js';
 | 
					import { getCompressedToolsDataForAI, getDataVersion } from './dataService.js';
 | 
				
			||||||
import { aiService } from './aiService.js';
 | 
					import { aiService } from './aiService.js';
 | 
				
			||||||
import { toolSelector, type SelectionContext } from './toolSelector.js';
 | 
					import { toolSelector, type SelectionContext } from './toolSelector.js';
 | 
				
			||||||
import { confidenceScoring, type AnalysisContext } from './confidenceScoring.js';
 | 
					import { confidenceScoring, type AnalysisContext } from './confidenceScoring.js';
 | 
				
			||||||
import { embeddingsService } from './embeddings.js';
 | 
					import { embeddingsService } from './embeddings.js';
 | 
				
			||||||
import { auditService, type AuditEntry } from './auditService.js';
 | 
					import { auditService, type AuditEntry } from './auditService.js';
 | 
				
			||||||
import { JSONParser } from './jsonUtils.js'; // FIXED: Use centralized JSON parsing
 | 
					import { JSONParser } from './jsonUtils.js';
 | 
				
			||||||
import { getPrompt } from '../config/prompts.js';
 | 
					import { getPrompt } from '../config/prompts.js';
 | 
				
			||||||
import 'dotenv/config';
 | 
					import 'dotenv/config';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -13,6 +13,11 @@ interface PipelineConfig {
 | 
				
			|||||||
  microTaskDelay: number;
 | 
					  microTaskDelay: number;
 | 
				
			||||||
  maxContextTokens: number;
 | 
					  maxContextTokens: number;
 | 
				
			||||||
  maxPromptTokens: number;
 | 
					  maxPromptTokens: number;
 | 
				
			||||||
 | 
					  taskRelevanceModeration: {
 | 
				
			||||||
 | 
					    maxInitialScore: number;
 | 
				
			||||||
 | 
					    maxWithPhaseBonus: number;
 | 
				
			||||||
 | 
					    moderationThreshold: number;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface MicroTaskResult {
 | 
					interface MicroTaskResult {
 | 
				
			||||||
@ -40,6 +45,10 @@ interface AnalysisResult {
 | 
				
			|||||||
    contextContinuityUsed: boolean;
 | 
					    contextContinuityUsed: boolean;
 | 
				
			||||||
    totalAITokensUsed: number;
 | 
					    totalAITokensUsed: number;
 | 
				
			||||||
    auditEntriesGenerated: number;
 | 
					    auditEntriesGenerated: number;
 | 
				
			||||||
 | 
					    aiModel: string;
 | 
				
			||||||
 | 
					    toolsDataHash: string;
 | 
				
			||||||
 | 
					    temperature: number;
 | 
				
			||||||
 | 
					    maxTokensUsed: number;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -78,10 +87,15 @@ class AIPipeline {
 | 
				
			|||||||
    this.config = {
 | 
					    this.config = {
 | 
				
			||||||
      microTaskDelay: parseInt(process.env.AI_MICRO_TASK_DELAY_MS || '500', 10),
 | 
					      microTaskDelay: parseInt(process.env.AI_MICRO_TASK_DELAY_MS || '500', 10),
 | 
				
			||||||
      maxContextTokens: parseInt(process.env.AI_MAX_CONTEXT_TOKENS || '4000', 10),
 | 
					      maxContextTokens: parseInt(process.env.AI_MAX_CONTEXT_TOKENS || '4000', 10),
 | 
				
			||||||
      maxPromptTokens: parseInt(process.env.AI_MAX_PROMPT_TOKENS || '1500', 10)
 | 
					      maxPromptTokens: parseInt(process.env.AI_MAX_PROMPT_TOKENS || '1500', 10),
 | 
				
			||||||
 | 
					      taskRelevanceModeration: {
 | 
				
			||||||
 | 
					        maxInitialScore: 85,
 | 
				
			||||||
 | 
					        maxWithPhaseBonus: 95,
 | 
				
			||||||
 | 
					        moderationThreshold: 80
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    console.log('[AI-PIPELINE] Initialized orchestration pipeline');
 | 
					    console.log('[AI-PIPELINE] Initialized orchestration pipeline with enhanced logic');
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async processQuery(userQuery: string, mode: string): Promise<AnalysisResult> {
 | 
					  async processQuery(userQuery: string, mode: string): Promise<AnalysisResult> {
 | 
				
			||||||
@ -92,7 +106,6 @@ class AIPipeline {
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    console.log('[AI-PIPELINE] Starting', mode, 'analysis pipeline');
 | 
					    console.log('[AI-PIPELINE] Starting', mode, 'analysis pipeline');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Initialize audit trail
 | 
					 | 
				
			||||||
    auditService.clearAuditTrail();
 | 
					    auditService.clearAuditTrail();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
@ -111,7 +124,6 @@ class AIPipeline {
 | 
				
			|||||||
        embeddingsSimilarities: new Map<string, number>()
 | 
					        embeddingsSimilarities: new Map<string, number>()
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // AUDIT: Pipeline initialization
 | 
					 | 
				
			||||||
      auditService.addEntry(
 | 
					      auditService.addEntry(
 | 
				
			||||||
        'initialization',
 | 
					        'initialization',
 | 
				
			||||||
        'pipeline-start',
 | 
					        'pipeline-start',
 | 
				
			||||||
@ -132,17 +144,15 @@ class AIPipeline {
 | 
				
			|||||||
          toolsDataHash,
 | 
					          toolsDataHash,
 | 
				
			||||||
          aiModel: aiConfig.model,
 | 
					          aiModel: aiConfig.model,
 | 
				
			||||||
          embeddingsUsed: embeddingsService.isEnabled(),
 | 
					          embeddingsUsed: embeddingsService.isEnabled(),
 | 
				
			||||||
          pipelineVersion: '2.0-enhanced'
 | 
					          pipelineVersion: '2.1-enhanced'
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Phase 1: Get intelligent tool candidates with enhanced logging
 | 
					 | 
				
			||||||
      console.log('[AI-PIPELINE] Phase 1: Tool candidate selection');
 | 
					      console.log('[AI-PIPELINE] Phase 1: Tool candidate selection');
 | 
				
			||||||
      const candidateSelectionStart = Date.now();
 | 
					      const candidateSelectionStart = Date.now();
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      const candidateData = await toolSelector.getIntelligentCandidates(userQuery, toolsData, mode, context);
 | 
					      const candidateData = await toolSelector.getIntelligentCandidates(userQuery, toolsData, mode, context);
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      // AUDIT: Tool candidate selection
 | 
					 | 
				
			||||||
      auditService.addToolSelection(
 | 
					      auditService.addToolSelection(
 | 
				
			||||||
        candidateData.tools.map(t => t.name),
 | 
					        candidateData.tools.map(t => t.name),
 | 
				
			||||||
        toolsData.tools.map(t => t.name),
 | 
					        toolsData.tools.map(t => t.name),
 | 
				
			||||||
@ -159,7 +169,6 @@ class AIPipeline {
 | 
				
			|||||||
      
 | 
					      
 | 
				
			||||||
      context.filteredData = candidateData;
 | 
					      context.filteredData = candidateData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Phase 2: Contextual analysis micro-tasks with enhanced logging
 | 
					 | 
				
			||||||
      console.log('[AI-PIPELINE] Phase 2: Contextual analysis');
 | 
					      console.log('[AI-PIPELINE] Phase 2: Contextual analysis');
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      const analysisResult = await this.analyzeScenario(context, startTime);
 | 
					      const analysisResult = await this.analyzeScenario(context, startTime);
 | 
				
			||||||
@ -177,7 +186,6 @@ class AIPipeline {
 | 
				
			|||||||
      this.trackTokenUsage(considerationsResult.aiUsage);
 | 
					      this.trackTokenUsage(considerationsResult.aiUsage);
 | 
				
			||||||
      await this.delay(this.config.microTaskDelay);
 | 
					      await this.delay(this.config.microTaskDelay);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Phase 3: Tool-specific analysis with enhanced logging
 | 
					 | 
				
			||||||
      console.log('[AI-PIPELINE] Phase 3: Tool-specific analysis');
 | 
					      console.log('[AI-PIPELINE] Phase 3: Tool-specific analysis');
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      if (mode === 'workflow') {
 | 
					      if (mode === 'workflow') {
 | 
				
			||||||
@ -190,7 +198,6 @@ class AIPipeline {
 | 
				
			|||||||
        failedTasks = toolResults.failed;
 | 
					        failedTasks = toolResults.failed;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Phase 4: Knowledge and finalization with enhanced logging
 | 
					 | 
				
			||||||
      console.log('[AI-PIPELINE] Phase 4: Knowledge synthesis');
 | 
					      console.log('[AI-PIPELINE] Phase 4: Knowledge synthesis');
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      const knowledgeResult = await this.selectBackgroundKnowledge(context, startTime);
 | 
					      const knowledgeResult = await this.selectBackgroundKnowledge(context, startTime);
 | 
				
			||||||
@ -202,10 +209,8 @@ class AIPipeline {
 | 
				
			|||||||
      if (finalResult.success) completedTasks++; else failedTasks++;
 | 
					      if (finalResult.success) completedTasks++; else failedTasks++;
 | 
				
			||||||
      this.trackTokenUsage(finalResult.aiUsage);
 | 
					      this.trackTokenUsage(finalResult.aiUsage);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Build final recommendation
 | 
					 | 
				
			||||||
      const recommendation = this.buildRecommendation(context, mode, finalResult.content);
 | 
					      const recommendation = this.buildRecommendation(context, mode, finalResult.content);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // AUDIT: Pipeline completion
 | 
					 | 
				
			||||||
      auditService.addEntry(
 | 
					      auditService.addEntry(
 | 
				
			||||||
        'completion',
 | 
					        'completion',
 | 
				
			||||||
        'pipeline-end',
 | 
					        'pipeline-end',
 | 
				
			||||||
@ -235,7 +240,11 @@ class AIPipeline {
 | 
				
			|||||||
        microTasksFailed: failedTasks,
 | 
					        microTasksFailed: failedTasks,
 | 
				
			||||||
        contextContinuityUsed: true,
 | 
					        contextContinuityUsed: true,
 | 
				
			||||||
        totalAITokensUsed: this.totalTokensUsed,
 | 
					        totalAITokensUsed: this.totalTokensUsed,
 | 
				
			||||||
        auditEntriesGenerated: auditService.getCurrentAuditTrail().length
 | 
					        auditEntriesGenerated: auditService.getCurrentAuditTrail().length,
 | 
				
			||||||
 | 
					        aiModel: aiConfig.model,
 | 
				
			||||||
 | 
					        toolsDataHash,
 | 
				
			||||||
 | 
					        temperature: 0.3,
 | 
				
			||||||
 | 
					        maxTokensUsed: 2500
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      console.log('[AI-PIPELINE] Pipeline completed successfully:', {
 | 
					      console.log('[AI-PIPELINE] Pipeline completed successfully:', {
 | 
				
			||||||
@ -248,13 +257,13 @@ class AIPipeline {
 | 
				
			|||||||
        auditEntries: processingStats.auditEntriesGenerated
 | 
					        auditEntries: processingStats.auditEntriesGenerated
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Finalize audit trail
 | 
					 | 
				
			||||||
      const finalAuditTrail = auditService.finalizeAuditTrail();
 | 
					      const finalAuditTrail = auditService.finalizeAuditTrail();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      return {
 | 
					      return {
 | 
				
			||||||
        recommendation: {
 | 
					        recommendation: {
 | 
				
			||||||
          ...recommendation,
 | 
					          ...recommendation,
 | 
				
			||||||
          auditTrail: auditService.isEnabled() ? finalAuditTrail : undefined
 | 
					          auditTrail: auditService.isEnabled() ? finalAuditTrail : undefined,
 | 
				
			||||||
 | 
					          processingStats
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        processingStats
 | 
					        processingStats
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
@ -262,7 +271,6 @@ class AIPipeline {
 | 
				
			|||||||
    } catch (error) {
 | 
					    } catch (error) {
 | 
				
			||||||
      console.error('[AI-PIPELINE] Pipeline failed:', error);
 | 
					      console.error('[AI-PIPELINE] Pipeline failed:', error);
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      // AUDIT: Pipeline failure
 | 
					 | 
				
			||||||
      auditService.addEntry(
 | 
					      auditService.addEntry(
 | 
				
			||||||
        'error',
 | 
					        'error',
 | 
				
			||||||
        'pipeline-failure',
 | 
					        'pipeline-failure',
 | 
				
			||||||
@ -286,7 +294,6 @@ class AIPipeline {
 | 
				
			|||||||
  ): Promise<{ completed: number; failed: number }> {
 | 
					  ): Promise<{ completed: number; failed: number }> {
 | 
				
			||||||
    const phases = toolsData.phases || [];
 | 
					    const phases = toolsData.phases || [];
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Select tools for each phase with enhanced logging
 | 
					 | 
				
			||||||
    for (const phase of phases) {
 | 
					    for (const phase of phases) {
 | 
				
			||||||
      const phaseStart = Date.now();
 | 
					      const phaseStart = Date.now();
 | 
				
			||||||
      const phaseTools = context.filteredData.tools.filter((tool: any) =>
 | 
					      const phaseTools = context.filteredData.tools.filter((tool: any) =>
 | 
				
			||||||
@ -295,7 +302,6 @@ class AIPipeline {
 | 
				
			|||||||
      
 | 
					      
 | 
				
			||||||
      const selections = await toolSelector.selectToolsForPhase(context.userQuery, phase, phaseTools, context);
 | 
					      const selections = await toolSelector.selectToolsForPhase(context.userQuery, phase, phaseTools, context);
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      // AUDIT: Phase tool selection
 | 
					 | 
				
			||||||
      auditService.addEntry(
 | 
					      auditService.addEntry(
 | 
				
			||||||
        'workflow-phase',
 | 
					        'workflow-phase',
 | 
				
			||||||
        'phase-tool-selection',
 | 
					        'phase-tool-selection',
 | 
				
			||||||
@ -321,21 +327,23 @@ class AIPipeline {
 | 
				
			|||||||
      selections.forEach((sel: any) => {
 | 
					      selections.forEach((sel: any) => {
 | 
				
			||||||
        const tool = phaseTools.find((t: any) => t && t.name === sel.toolName);
 | 
					        const tool = phaseTools.find((t: any) => t && t.name === sel.toolName);
 | 
				
			||||||
        if (tool) {
 | 
					        if (tool) {
 | 
				
			||||||
          const priority = this.derivePriorityFromScore(sel.taskRelevance);
 | 
					          const moderatedTaskRelevance = this.moderateTaskRelevance(sel.taskRelevance);
 | 
				
			||||||
          this.addToolToSelection(context, tool, phase.id, priority, sel.justification, sel.taskRelevance, sel.limitations);
 | 
					          const priority = this.derivePriorityFromScore(moderatedTaskRelevance);
 | 
				
			||||||
 | 
					          
 | 
				
			||||||
 | 
					          this.addToolToSelection(context, tool, phase.id, priority, sel.justification, moderatedTaskRelevance, sel.limitations);
 | 
				
			||||||
          
 | 
					          
 | 
				
			||||||
          // AUDIT: Individual tool selection reasoning
 | 
					 | 
				
			||||||
          auditService.addEntry(
 | 
					          auditService.addEntry(
 | 
				
			||||||
            'tool-reasoning',
 | 
					            'tool-reasoning',
 | 
				
			||||||
            'tool-added-to-phase',
 | 
					            'tool-added-to-phase',
 | 
				
			||||||
            { toolName: tool.name, phaseId: phase.id, taskRelevance: sel.taskRelevance },
 | 
					            { toolName: tool.name, phaseId: phase.id, originalTaskRelevance: sel.taskRelevance, moderatedTaskRelevance },
 | 
				
			||||||
            { justification: sel.justification, limitations: sel.limitations },
 | 
					            { justification: sel.justification, limitations: sel.limitations },
 | 
				
			||||||
            sel.taskRelevance || 70,
 | 
					            moderatedTaskRelevance || 70,
 | 
				
			||||||
            phaseStart,
 | 
					            phaseStart,
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
              toolType: tool.type,
 | 
					              toolType: tool.type,
 | 
				
			||||||
              priority,
 | 
					              priority,
 | 
				
			||||||
              selectionReasoning: sel.justification
 | 
					              selectionReasoning: sel.justification,
 | 
				
			||||||
 | 
					              moderationApplied: sel.taskRelevance !== moderatedTaskRelevance
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
          );
 | 
					          );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -345,8 +353,9 @@ class AIPipeline {
 | 
				
			|||||||
      await this.delay(this.config.microTaskDelay);
 | 
					      await this.delay(this.config.microTaskDelay);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Complete underrepresented phases with enhanced logging
 | 
					 | 
				
			||||||
    const completionResult = await this.completeUnderrepresentedPhases(context, toolsData, pipelineStart);
 | 
					    const completionResult = await this.completeUnderrepresentedPhases(context, toolsData, pipelineStart);
 | 
				
			||||||
 | 
					    completedTasks += completionResult.completed;
 | 
				
			||||||
 | 
					    failedTasks += completionResult.failed;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    return { completed: completedTasks, failed: failedTasks };
 | 
					    return { completed: completedTasks, failed: failedTasks };
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -369,6 +378,267 @@ class AIPipeline {
 | 
				
			|||||||
    return { completed: completedTasks, failed: failedTasks };
 | 
					    return { completed: completedTasks, failed: failedTasks };
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private async completeUnderrepresentedPhases(
 | 
				
			||||||
 | 
					    context: PipelineContext, 
 | 
				
			||||||
 | 
					    toolsData: any, 
 | 
				
			||||||
 | 
					    pipelineStart: number
 | 
				
			||||||
 | 
					  ): Promise<{ completed: number; failed: number }> {
 | 
				
			||||||
 | 
					    const phases = toolsData.phases || [];
 | 
				
			||||||
 | 
					    const selectedPhases = new Map<string, number>();
 | 
				
			||||||
 | 
					    let completedTasks = 0;
 | 
				
			||||||
 | 
					    let failedTasks = 0;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    context.selectedTools?.forEach((st: any) => {
 | 
				
			||||||
 | 
					      const count = selectedPhases.get(st.phase) || 0;
 | 
				
			||||||
 | 
					      selectedPhases.set(st.phase, count + 1);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    const underrepresentedPhases = phases.filter((phase: any) => {
 | 
				
			||||||
 | 
					      const count = selectedPhases.get(phase.id) || 0;
 | 
				
			||||||
 | 
					      return count <= 1;
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if (underrepresentedPhases.length === 0) {
 | 
				
			||||||
 | 
					      console.log('[AI-PIPELINE] All phases adequately represented');
 | 
				
			||||||
 | 
					      return { completed: 0, failed: 0 };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    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++;
 | 
				
			||||||
 | 
					      await this.delay(this.config.microTaskDelay);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    return { completed: completedTasks, failed: failedTasks };
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private async completePhaseWithSemanticSearchAndAI(
 | 
				
			||||||
 | 
					    context: PipelineContext, 
 | 
				
			||||||
 | 
					    phase: any, 
 | 
				
			||||||
 | 
					    toolsData: any, 
 | 
				
			||||||
 | 
					    pipelineStart: number
 | 
				
			||||||
 | 
					  ): Promise<MicroTaskResult> {
 | 
				
			||||||
 | 
					    const phaseStart = Date.now();
 | 
				
			||||||
 | 
					    const phaseQuery = `forensic ${phase.name.toLowerCase()} tools methods`;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    console.log('[AI-PIPELINE] Phase completion for:', phase.id);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      const phaseResults = await embeddingsService.findSimilar(phaseQuery, 20, 0.2);
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      auditService.addEmbeddingsSearch(
 | 
				
			||||||
 | 
					        phaseQuery,
 | 
				
			||||||
 | 
					        phaseResults,
 | 
				
			||||||
 | 
					        0.2,
 | 
				
			||||||
 | 
					        phaseStart,
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          phaseId: phase.id,
 | 
				
			||||||
 | 
					          phaseName: phase.name,
 | 
				
			||||||
 | 
					          completionPurpose: 'underrepresented-phase-enhancement'
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      if (phaseResults.length === 0) {
 | 
				
			||||||
 | 
					        console.log('[AI-PIPELINE] No semantic results for phase:', phase.id);
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					          taskType: 'phase-completion',
 | 
				
			||||||
 | 
					          content: '',
 | 
				
			||||||
 | 
					          processingTimeMs: Date.now() - phaseStart,
 | 
				
			||||||
 | 
					          success: true
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      const toolsMap = new Map(toolsData.tools.map((tool: any) => [tool.name, tool]));
 | 
				
			||||||
 | 
					      const conceptsMap = new Map(toolsData.concepts.map((concept: any) => [concept.name, concept]));
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      const phaseTools = phaseResults
 | 
				
			||||||
 | 
					        .filter((result: any) => result.type === 'tool')
 | 
				
			||||||
 | 
					        .map((result: any) => toolsMap.get(result.name))
 | 
				
			||||||
 | 
					        .filter((tool: any): tool is NonNullable<any> =>
 | 
				
			||||||
 | 
					          tool !== undefined &&
 | 
				
			||||||
 | 
					          tool !== null &&
 | 
				
			||||||
 | 
					          tool.phases &&
 | 
				
			||||||
 | 
					          Array.isArray(tool.phases) &&
 | 
				
			||||||
 | 
					          tool.phases.includes(phase.id) &&
 | 
				
			||||||
 | 
					          !context.seenToolNames.has(tool.name)
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        .slice(0, 5);
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      const phaseConcepts = phaseResults
 | 
				
			||||||
 | 
					        .filter((result: any) => result.type === 'concept')
 | 
				
			||||||
 | 
					        .map((result: any) => conceptsMap.get(result.name))
 | 
				
			||||||
 | 
					        .filter((concept: any): concept is NonNullable<any> => concept !== undefined && concept !== null)
 | 
				
			||||||
 | 
					        .slice(0, 2);
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      if (phaseTools.length === 0) {
 | 
				
			||||||
 | 
					        console.log('[AI-PIPELINE] No suitable tools for phase completion:', phase.id);
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					          taskType: 'phase-completion',
 | 
				
			||||||
 | 
					          content: '',
 | 
				
			||||||
 | 
					          processingTimeMs: Date.now() - phaseStart,
 | 
				
			||||||
 | 
					          success: true
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      const selectionPrompt = getPrompt('generatePhaseCompletionPrompt', context.userQuery, phase, phaseTools, phaseConcepts);
 | 
				
			||||||
 | 
					      const selectionResult = await this.callMicroTaskAI(selectionPrompt, context, 800, 'phase-completion-selection');
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      if (!selectionResult.success) {
 | 
				
			||||||
 | 
					        console.error('[AI-PIPELINE] Phase completion selection failed for:', phase.id);
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					          taskType: 'phase-completion',
 | 
				
			||||||
 | 
					          content: '',
 | 
				
			||||||
 | 
					          processingTimeMs: Date.now() - phaseStart,
 | 
				
			||||||
 | 
					          success: false,
 | 
				
			||||||
 | 
					          error: 'Selection micro-task failed'
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      const selection = JSONParser.safeParseJSON(selectionResult.content, { 
 | 
				
			||||||
 | 
					        selectedTools: [], 
 | 
				
			||||||
 | 
					        selectedConcepts: [],
 | 
				
			||||||
 | 
					        completionReasoning: ''
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      const validTools = selection.selectedTools
 | 
				
			||||||
 | 
					        .map((name: string) => phaseTools.find((t: any) => t && t.name === name))
 | 
				
			||||||
 | 
					        .filter((tool: any): tool is NonNullable<any> => tool !== undefined && tool !== null)
 | 
				
			||||||
 | 
					        .slice(0, 2);
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      if (validTools.length === 0) {
 | 
				
			||||||
 | 
					        console.log('[AI-PIPELINE] No valid tools selected for phase completion:', phase.id);
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					          taskType: 'phase-completion',
 | 
				
			||||||
 | 
					          content: selection.completionReasoning || '',
 | 
				
			||||||
 | 
					          processingTimeMs: Date.now() - phaseStart,
 | 
				
			||||||
 | 
					          success: true
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      for (const tool of validTools) {
 | 
				
			||||||
 | 
					        console.log('[AI-PIPELINE] Generating AI reasoning for phase completion tool:', tool.name);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        const reasoningPrompt = getPrompt(
 | 
				
			||||||
 | 
					          'phaseCompletionReasoning',
 | 
				
			||||||
 | 
					          context.userQuery,
 | 
				
			||||||
 | 
					          phase,
 | 
				
			||||||
 | 
					          tool.name,
 | 
				
			||||||
 | 
					          tool,
 | 
				
			||||||
 | 
					          selection.completionReasoning || 'Nachergänzung zur Vervollständigung der Phasenabdeckung'
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        const reasoningResult = await this.callMicroTaskAI(reasoningPrompt, context, 400, 'phase-completion-reasoning');
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        let detailedJustification: string;
 | 
				
			||||||
 | 
					        let moderatedTaskRelevance = 75;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if (reasoningResult.success && reasoningResult.content.trim()) {
 | 
				
			||||||
 | 
					          detailedJustification = reasoningResult.content.trim();
 | 
				
			||||||
 | 
					          moderatedTaskRelevance = this.moderateTaskRelevance(80);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          detailedJustification = `Nachträglich hinzugefügt zur Vervollständigung der ${phase.name}-Phase. Die ursprüngliche KI-Auswahl war zu spezifisch und hat wichtige Tools für diese Phase übersehen.`;
 | 
				
			||||||
 | 
					          moderatedTaskRelevance = this.moderateTaskRelevance(75);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        this.addToolToSelection(
 | 
				
			||||||
 | 
					          context,
 | 
				
			||||||
 | 
					          tool,
 | 
				
			||||||
 | 
					          phase.id,
 | 
				
			||||||
 | 
					          'medium',
 | 
				
			||||||
 | 
					          detailedJustification,
 | 
				
			||||||
 | 
					          moderatedTaskRelevance,
 | 
				
			||||||
 | 
					          ['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);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      return {
 | 
				
			||||||
 | 
					        taskType: 'phase-completion',
 | 
				
			||||||
 | 
					        content: selection.completionReasoning || '',
 | 
				
			||||||
 | 
					        processingTimeMs: Date.now() - phaseStart,
 | 
				
			||||||
 | 
					        success: true
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					    } 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: '',
 | 
				
			||||||
 | 
					        processingTimeMs: Date.now() - phaseStart,
 | 
				
			||||||
 | 
					        success: false,
 | 
				
			||||||
 | 
					        error: error.message
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private moderateTaskRelevance(taskRelevance: number): number {
 | 
				
			||||||
 | 
					    if (typeof taskRelevance !== 'number') {
 | 
				
			||||||
 | 
					      return 70;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    let moderated = Math.min(taskRelevance, this.config.taskRelevanceModeration.maxInitialScore);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if (moderated > this.config.taskRelevanceModeration.moderationThreshold) {
 | 
				
			||||||
 | 
					      const excess = moderated - this.config.taskRelevanceModeration.moderationThreshold;
 | 
				
			||||||
 | 
					      moderated = this.config.taskRelevanceModeration.moderationThreshold + (excess * 0.7);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    return Math.round(Math.min(moderated, this.config.taskRelevanceModeration.maxInitialScore));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private async analyzeScenario(context: PipelineContext, pipelineStart: number): Promise<MicroTaskResult> {
 | 
					  private async analyzeScenario(context: PipelineContext, pipelineStart: number): Promise<MicroTaskResult> {
 | 
				
			||||||
    console.log('[AI-PIPELINE] Micro-task: Scenario analysis');
 | 
					    console.log('[AI-PIPELINE] Micro-task: Scenario analysis');
 | 
				
			||||||
    const taskStart = Date.now();
 | 
					    const taskStart = Date.now();
 | 
				
			||||||
@ -386,7 +656,6 @@ class AIPipeline {
 | 
				
			|||||||
      
 | 
					      
 | 
				
			||||||
      this.addToContextHistory(context, `${isWorkflow ? 'Szenario' : 'Problem'}-Analyse: ${result.content.slice(0, 200)}...`);
 | 
					      this.addToContextHistory(context, `${isWorkflow ? 'Szenario' : 'Problem'}-Analyse: ${result.content.slice(0, 200)}...`);
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      // AUDIT: Scenario analysis
 | 
					 | 
				
			||||||
      auditService.addAIDecision(
 | 
					      auditService.addAIDecision(
 | 
				
			||||||
        'contextual-analysis',
 | 
					        'contextual-analysis',
 | 
				
			||||||
        prompt,
 | 
					        prompt,
 | 
				
			||||||
@ -418,7 +687,6 @@ class AIPipeline {
 | 
				
			|||||||
      context.investigationApproach = result.content;
 | 
					      context.investigationApproach = result.content;
 | 
				
			||||||
      this.addToContextHistory(context, `${isWorkflow ? 'Untersuchungs' : 'Lösungs'}ansatz: ${result.content.slice(0, 200)}...`);
 | 
					      this.addToContextHistory(context, `${isWorkflow ? 'Untersuchungs' : 'Lösungs'}ansatz: ${result.content.slice(0, 200)}...`);
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      // AUDIT: Investigation approach
 | 
					 | 
				
			||||||
      auditService.addAIDecision(
 | 
					      auditService.addAIDecision(
 | 
				
			||||||
        'contextual-analysis',
 | 
					        'contextual-analysis',
 | 
				
			||||||
        prompt,
 | 
					        prompt,
 | 
				
			||||||
@ -451,7 +719,6 @@ class AIPipeline {
 | 
				
			|||||||
      context.criticalConsiderations = result.content;
 | 
					      context.criticalConsiderations = result.content;
 | 
				
			||||||
      this.addToContextHistory(context, `Kritische Überlegungen: ${result.content.slice(0, 200)}...`);
 | 
					      this.addToContextHistory(context, `Kritische Überlegungen: ${result.content.slice(0, 200)}...`);
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      // AUDIT: Critical considerations
 | 
					 | 
				
			||||||
      auditService.addAIDecision(
 | 
					      auditService.addAIDecision(
 | 
				
			||||||
        'contextual-analysis',
 | 
					        'contextual-analysis',
 | 
				
			||||||
        prompt,
 | 
					        prompt,
 | 
				
			||||||
@ -479,14 +746,14 @@ class AIPipeline {
 | 
				
			|||||||
    console.log('[AI-PIPELINE] Micro-task: Tool evaluation for:', tool.name);
 | 
					    console.log('[AI-PIPELINE] Micro-task: Tool evaluation for:', tool.name);
 | 
				
			||||||
    const taskStart = Date.now();
 | 
					    const taskStart = Date.now();
 | 
				
			||||||
    const existingSelection = context.selectedTools?.find((st: any) => st.tool && st.tool.name === tool.name);
 | 
					    const existingSelection = context.selectedTools?.find((st: any) => st.tool && st.tool.name === tool.name);
 | 
				
			||||||
    const taskRelevance = existingSelection?.taskRelevance || 70;
 | 
					    const originalTaskRelevance = existingSelection?.taskRelevance || 70;
 | 
				
			||||||
    const priority = this.derivePriorityFromScore(taskRelevance);
 | 
					    const moderatedTaskRelevance = this.moderateTaskRelevance(originalTaskRelevance);
 | 
				
			||||||
 | 
					    const priority = this.derivePriorityFromScore(moderatedTaskRelevance);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    const prompt = getPrompt('toolEvaluation', context.userQuery, tool, rank, taskRelevance);
 | 
					    const prompt = getPrompt('toolEvaluation', context.userQuery, tool, rank, moderatedTaskRelevance);
 | 
				
			||||||
    const result = await this.callMicroTaskAI(prompt, context, 1000, 'tool-evaluation');
 | 
					    const result = await this.callMicroTaskAI(prompt, context, 1000, 'tool-evaluation');
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    if (result.success) {
 | 
					    if (result.success) {
 | 
				
			||||||
      // FIXED: Use centralized JSON parsing
 | 
					 | 
				
			||||||
      const evaluation = JSONParser.safeParseJSON(result.content, {
 | 
					      const evaluation = JSONParser.safeParseJSON(result.content, {
 | 
				
			||||||
        detailed_explanation: 'Evaluation failed',
 | 
					        detailed_explanation: 'Evaluation failed',
 | 
				
			||||||
        implementation_approach: '',
 | 
					        implementation_approach: '',
 | 
				
			||||||
@ -500,16 +767,15 @@ class AIPipeline {
 | 
				
			|||||||
        evaluation: {
 | 
					        evaluation: {
 | 
				
			||||||
          ...evaluation,
 | 
					          ...evaluation,
 | 
				
			||||||
          rank,
 | 
					          rank,
 | 
				
			||||||
          task_relevance: taskRelevance
 | 
					          task_relevance: moderatedTaskRelevance
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }, 'evaluation', priority, evaluation.detailed_explanation, taskRelevance, evaluation.limitations);
 | 
					      }, 'evaluation', priority, evaluation.detailed_explanation, moderatedTaskRelevance, evaluation.limitations);
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      // AUDIT: Tool evaluation
 | 
					 | 
				
			||||||
      auditService.addAIDecision(
 | 
					      auditService.addAIDecision(
 | 
				
			||||||
        'tool-evaluation',
 | 
					        'tool-evaluation',
 | 
				
			||||||
        prompt,
 | 
					        prompt,
 | 
				
			||||||
        result.content,
 | 
					        result.content,
 | 
				
			||||||
        taskRelevance,
 | 
					        moderatedTaskRelevance,
 | 
				
			||||||
        `Evaluated tool ${tool.name} for ${context.mode} mode`,
 | 
					        `Evaluated tool ${tool.name} for ${context.mode} mode`,
 | 
				
			||||||
        taskStart,
 | 
					        taskStart,
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@ -517,7 +783,9 @@ class AIPipeline {
 | 
				
			|||||||
          toolName: tool.name,
 | 
					          toolName: tool.name,
 | 
				
			||||||
          toolType: tool.type,
 | 
					          toolType: tool.type,
 | 
				
			||||||
          rank,
 | 
					          rank,
 | 
				
			||||||
          taskRelevance,
 | 
					          originalTaskRelevance,
 | 
				
			||||||
 | 
					          moderatedTaskRelevance,
 | 
				
			||||||
 | 
					          moderationApplied: originalTaskRelevance !== moderatedTaskRelevance,
 | 
				
			||||||
          evaluationParsed: !!evaluation.detailed_explanation,
 | 
					          evaluationParsed: !!evaluation.detailed_explanation,
 | 
				
			||||||
          prosCount: evaluation.pros?.length || 0,
 | 
					          prosCount: evaluation.pros?.length || 0,
 | 
				
			||||||
          limitationsCount: evaluation.limitations?.length || 0,
 | 
					          limitationsCount: evaluation.limitations?.length || 0,
 | 
				
			||||||
@ -548,7 +816,6 @@ class AIPipeline {
 | 
				
			|||||||
    const result = await this.callMicroTaskAI(prompt, context, 700, 'background-knowledge');
 | 
					    const result = await this.callMicroTaskAI(prompt, context, 700, 'background-knowledge');
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    if (result.success) {
 | 
					    if (result.success) {
 | 
				
			||||||
      // FIXED: Use centralized JSON parsing
 | 
					 | 
				
			||||||
      const selections = JSONParser.safeParseJSON(result.content, []);
 | 
					      const selections = JSONParser.safeParseJSON(result.content, []);
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      if (Array.isArray(selections)) {
 | 
					      if (Array.isArray(selections)) {
 | 
				
			||||||
@ -559,7 +826,6 @@ class AIPipeline {
 | 
				
			|||||||
          relevance: sel.relevance
 | 
					          relevance: sel.relevance
 | 
				
			||||||
        }));
 | 
					        }));
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // AUDIT: Background knowledge selection
 | 
					 | 
				
			||||||
        auditService.addEntry(
 | 
					        auditService.addEntry(
 | 
				
			||||||
          'knowledge-synthesis',
 | 
					          'knowledge-synthesis',
 | 
				
			||||||
          'concept-selection',
 | 
					          'concept-selection',
 | 
				
			||||||
@ -596,7 +862,6 @@ class AIPipeline {
 | 
				
			|||||||
    const result = await this.callMicroTaskAI(prompt, context, 350, 'final-recommendations');
 | 
					    const result = await this.callMicroTaskAI(prompt, context, 350, 'final-recommendations');
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    if (result.success) {
 | 
					    if (result.success) {
 | 
				
			||||||
      // AUDIT: Final recommendations
 | 
					 | 
				
			||||||
      auditService.addAIDecision(
 | 
					      auditService.addAIDecision(
 | 
				
			||||||
        'synthesis',
 | 
					        'synthesis',
 | 
				
			||||||
        prompt,
 | 
					        prompt,
 | 
				
			||||||
@ -617,152 +882,6 @@ class AIPipeline {
 | 
				
			|||||||
    return result;
 | 
					    return result;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private async completeUnderrepresentedPhases(context: PipelineContext, toolsData: any, pipelineStart: number): Promise<void> {
 | 
					 | 
				
			||||||
    const phases = toolsData.phases || [];
 | 
					 | 
				
			||||||
    const selectedPhases = new Map<string, number>();
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    context.selectedTools?.forEach((st: any) => {
 | 
					 | 
				
			||||||
      const count = selectedPhases.get(st.phase) || 0;
 | 
					 | 
				
			||||||
      selectedPhases.set(st.phase, count + 1);
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    const underrepresentedPhases = phases.filter((phase: any) => {
 | 
					 | 
				
			||||||
      const count = selectedPhases.get(phase.id) || 0;
 | 
					 | 
				
			||||||
      return count <= 1;
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    if (underrepresentedPhases.length === 0) {
 | 
					 | 
				
			||||||
      console.log('[AI-PIPELINE] All phases adequately represented');
 | 
					 | 
				
			||||||
      return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    console.log('[AI-PIPELINE] Completing underrepresented phases:', underrepresentedPhases.map((p: any) => p.id).join(', '));
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    // AUDIT: Phase completion start
 | 
					 | 
				
			||||||
    auditService.addEntry(
 | 
					 | 
				
			||||||
      'phase-completion',
 | 
					 | 
				
			||||||
      'underrepresented-phases-detected',
 | 
					 | 
				
			||||||
      { 
 | 
					 | 
				
			||||||
        underrepresentedPhases: underrepresentedPhases.map(p => p.id),
 | 
					 | 
				
			||||||
        currentPhaseDistribution: Array.from(selectedPhases.entries())
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      { 
 | 
					 | 
				
			||||||
        phasesToComplete: underrepresentedPhases.length,
 | 
					 | 
				
			||||||
        completionStrategy: 'semantic-search'
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      70,
 | 
					 | 
				
			||||||
      pipelineStart,
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        totalPhases: phases.length,
 | 
					 | 
				
			||||||
        adequatelyRepresented: phases.length - underrepresentedPhases.length,
 | 
					 | 
				
			||||||
        completionMethod: 'semantic-phase-search'
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    for (const phase of underrepresentedPhases) {
 | 
					 | 
				
			||||||
      await this.completePhaseWithSemanticSearch(context, phase, toolsData, pipelineStart);
 | 
					 | 
				
			||||||
      await this.delay(this.config.microTaskDelay);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  private async completePhaseWithSemanticSearch(context: PipelineContext, phase: any, toolsData: any, pipelineStart: number): Promise<void> {
 | 
					 | 
				
			||||||
    const phaseStart = Date.now();
 | 
					 | 
				
			||||||
    const phaseQuery = `forensic ${phase.name.toLowerCase()} tools methods`;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    console.log('[AI-PIPELINE] Phase completion for:', phase.id);
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    try {
 | 
					 | 
				
			||||||
      const phaseResults = await embeddingsService.findSimilar(phaseQuery, 20, 0.2);
 | 
					 | 
				
			||||||
      
 | 
					 | 
				
			||||||
      // AUDIT: Embeddings search for phase completion
 | 
					 | 
				
			||||||
      auditService.addEmbeddingsSearch(
 | 
					 | 
				
			||||||
        phaseQuery,
 | 
					 | 
				
			||||||
        phaseResults,
 | 
					 | 
				
			||||||
        0.2,
 | 
					 | 
				
			||||||
        phaseStart,
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
          phaseId: phase.id,
 | 
					 | 
				
			||||||
          phaseName: phase.name,
 | 
					 | 
				
			||||||
          completionPurpose: 'underrepresented-phase-enhancement'
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      );
 | 
					 | 
				
			||||||
      
 | 
					 | 
				
			||||||
      if (phaseResults.length === 0) {
 | 
					 | 
				
			||||||
        console.log('[AI-PIPELINE] No semantic results for phase:', phase.id);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      
 | 
					 | 
				
			||||||
      const toolsMap = new Map(toolsData.tools.map((tool: any) => [tool.name, tool]));
 | 
					 | 
				
			||||||
      
 | 
					 | 
				
			||||||
      const phaseTools = phaseResults
 | 
					 | 
				
			||||||
        .filter((result: any) => result.type === 'tool')
 | 
					 | 
				
			||||||
        .map((result: any) => toolsMap.get(result.name))
 | 
					 | 
				
			||||||
        .filter((tool: any): tool is NonNullable<any> =>
 | 
					 | 
				
			||||||
          tool !== undefined &&
 | 
					 | 
				
			||||||
          tool !== null &&
 | 
					 | 
				
			||||||
          tool.phases &&
 | 
					 | 
				
			||||||
          Array.isArray(tool.phases) &&
 | 
					 | 
				
			||||||
          tool.phases.includes(phase.id) &&
 | 
					 | 
				
			||||||
          !context.seenToolNames.has(tool.name)
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        .slice(0, 2);
 | 
					 | 
				
			||||||
      
 | 
					 | 
				
			||||||
      if (phaseTools.length === 0) {
 | 
					 | 
				
			||||||
        console.log('[AI-PIPELINE] No suitable tools for phase completion:', phase.id);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      
 | 
					 | 
				
			||||||
      // Add tools with justification and audit each addition
 | 
					 | 
				
			||||||
      for (const tool of phaseTools) {
 | 
					 | 
				
			||||||
        const justification = `Nachträglich hinzugefügt zur Vervollständigung der ${phase.name}-Phase. Die ursprüngliche KI-Auswahl war zu spezifisch und hat wichtige Tools für diese Phase übersehen.`;
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        this.addToolToSelection(
 | 
					 | 
				
			||||||
          context,
 | 
					 | 
				
			||||||
          tool,
 | 
					 | 
				
			||||||
          phase.id,
 | 
					 | 
				
			||||||
          'medium',
 | 
					 | 
				
			||||||
          justification,
 | 
					 | 
				
			||||||
          75,
 | 
					 | 
				
			||||||
          ['Nachträgliche Ergänzung via semantische Phasensuche']
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // AUDIT: Phase completion tool addition
 | 
					 | 
				
			||||||
        auditService.addPhaseCompletion(
 | 
					 | 
				
			||||||
          phase.id,
 | 
					 | 
				
			||||||
          [tool.name],
 | 
					 | 
				
			||||||
          justification,
 | 
					 | 
				
			||||||
          phaseStart,
 | 
					 | 
				
			||||||
          {
 | 
					 | 
				
			||||||
            toolName: tool.name,
 | 
					 | 
				
			||||||
            toolType: tool.type,
 | 
					 | 
				
			||||||
            semanticSimilarity: phaseResults.find(r => r.name === tool.name)?.similarity,
 | 
					 | 
				
			||||||
            completionReason: 'underrepresented-phase',
 | 
					 | 
				
			||||||
            originalSelectionMissed: true
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        console.log('[AI-PIPELINE] Added phase completion tool:', tool.name);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      
 | 
					 | 
				
			||||||
    } catch (error) {
 | 
					 | 
				
			||||||
      console.error('[AI-PIPELINE] Phase completion failed for:', phase.id, error);
 | 
					 | 
				
			||||||
      
 | 
					 | 
				
			||||||
      // AUDIT: Phase completion failure
 | 
					 | 
				
			||||||
      auditService.addEntry(
 | 
					 | 
				
			||||||
        'phase-completion',
 | 
					 | 
				
			||||||
        'completion-failed',
 | 
					 | 
				
			||||||
        { phaseId: phase.id, error: error.message },
 | 
					 | 
				
			||||||
        { success: false },
 | 
					 | 
				
			||||||
        20,
 | 
					 | 
				
			||||||
        phaseStart,
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
          errorType: error.constructor.name,
 | 
					 | 
				
			||||||
          phaseId: phase.id
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  private buildRecommendation(context: PipelineContext, mode: string, finalContent: string): any {
 | 
					  private buildRecommendation(context: PipelineContext, mode: string, finalContent: string): any {
 | 
				
			||||||
    const isWorkflow = mode === 'workflow';
 | 
					    const isWorkflow = mode === 'workflow';
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@ -795,7 +914,6 @@ class AIPipeline {
 | 
				
			|||||||
          st.limitations || []
 | 
					          st.limitations || []
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // AUDIT: Confidence calculation for each tool
 | 
					 | 
				
			||||||
        auditService.addConfidenceCalculation(
 | 
					        auditService.addConfidenceCalculation(
 | 
				
			||||||
          st.tool.name,
 | 
					          st.tool.name,
 | 
				
			||||||
          confidence,
 | 
					          confidence,
 | 
				
			||||||
@ -803,7 +921,8 @@ class AIPipeline {
 | 
				
			|||||||
          {
 | 
					          {
 | 
				
			||||||
            phase: st.phase,
 | 
					            phase: st.phase,
 | 
				
			||||||
            priority: st.priority,
 | 
					            priority: st.priority,
 | 
				
			||||||
            toolType: st.tool.type
 | 
					            toolType: st.tool.type,
 | 
				
			||||||
 | 
					            moderatedTaskRelevance: st.taskRelevance
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -839,14 +958,14 @@ class AIPipeline {
 | 
				
			|||||||
          st.limitations || []
 | 
					          st.limitations || []
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // AUDIT: Confidence calculation for each tool
 | 
					 | 
				
			||||||
        auditService.addConfidenceCalculation(
 | 
					        auditService.addConfidenceCalculation(
 | 
				
			||||||
          st.tool.name,
 | 
					          st.tool.name,
 | 
				
			||||||
          confidence,
 | 
					          confidence,
 | 
				
			||||||
          Date.now(),
 | 
					          Date.now(),
 | 
				
			||||||
          {
 | 
					          {
 | 
				
			||||||
            rank: st.tool.evaluation?.rank || 1,
 | 
					            rank: st.tool.evaluation?.rank || 1,
 | 
				
			||||||
            toolType: st.tool.type
 | 
					            toolType: st.tool.type,
 | 
				
			||||||
 | 
					            moderatedTaskRelevance: st.taskRelevance
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -873,7 +992,6 @@ class AIPipeline {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Helper methods
 | 
					 | 
				
			||||||
  private async callMicroTaskAI(
 | 
					  private async callMicroTaskAI(
 | 
				
			||||||
    prompt: string, 
 | 
					    prompt: string, 
 | 
				
			||||||
    context: PipelineContext, 
 | 
					    context: PipelineContext, 
 | 
				
			||||||
 | 
				
			|||||||
@ -83,26 +83,21 @@ export const apiServerError = {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const apiSpecial = {
 | 
					export const apiSpecial = {
 | 
				
			||||||
  // JSON parsing error
 | 
					 | 
				
			||||||
  invalidJSON: (): Response => 
 | 
					  invalidJSON: (): Response => 
 | 
				
			||||||
    apiError.badRequest('Invalid JSON in request body'),
 | 
					    apiError.badRequest('Invalid JSON in request body'),
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  // Missing required fields
 | 
					 | 
				
			||||||
  missingRequired: (fields: string[]): Response => 
 | 
					  missingRequired: (fields: string[]): Response => 
 | 
				
			||||||
    apiError.badRequest(`Missing required fields: ${fields.join(', ')}`),
 | 
					    apiError.badRequest(`Missing required fields: ${fields.join(', ')}`),
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  // Empty request body
 | 
					 | 
				
			||||||
  emptyBody: (): Response => 
 | 
					  emptyBody: (): Response => 
 | 
				
			||||||
    apiError.badRequest('Request body cannot be empty'),
 | 
					    apiError.badRequest('Request body cannot be empty'),
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  // File upload responses
 | 
					 | 
				
			||||||
  uploadSuccess: (data: { url: string; filename: string; size: number; storage: string }): Response => 
 | 
					  uploadSuccess: (data: { url: string; filename: string; size: number; storage: string }): Response => 
 | 
				
			||||||
    apiResponse.created(data),
 | 
					    apiResponse.created(data),
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  uploadFailed: (error: string): Response => 
 | 
					  uploadFailed: (error: string): Response => 
 | 
				
			||||||
    apiServerError.internal(`Upload failed: ${error}`),
 | 
					    apiServerError.internal(`Upload failed: ${error}`),
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  // Contribution responses
 | 
					 | 
				
			||||||
  contributionSuccess: (data: { prUrl?: string; branchName?: string; message: string }): Response => 
 | 
					  contributionSuccess: (data: { prUrl?: string; branchName?: string; message: string }): Response => 
 | 
				
			||||||
    apiResponse.created({ success: true, ...data }),
 | 
					    apiResponse.created({ success: true, ...data }),
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
@ -114,7 +109,6 @@ export const apiWithHeaders = {
 | 
				
			|||||||
  successWithHeaders: (data: any, headers: Record<string, string>): Response => 
 | 
					  successWithHeaders: (data: any, headers: Record<string, string>): Response => 
 | 
				
			||||||
    createAPIResponse(data, 200, headers),
 | 
					    createAPIResponse(data, 200, headers),
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  // Redirect response
 | 
					 | 
				
			||||||
  redirect: (location: string, temporary: boolean = true): Response => 
 | 
					  redirect: (location: string, temporary: boolean = true): Response => 
 | 
				
			||||||
    new Response(null, {
 | 
					    new Response(null, {
 | 
				
			||||||
      status: temporary ? 302 : 301,
 | 
					      status: temporary ? 302 : 301,
 | 
				
			||||||
 | 
				
			|||||||
@ -101,7 +101,6 @@ class AuditService {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    this.activeAuditTrail.push(entry);
 | 
					    this.activeAuditTrail.push(entry);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Enforce max entries limit
 | 
					 | 
				
			||||||
    if (this.activeAuditTrail.length > this.config.maxEntries) {
 | 
					    if (this.activeAuditTrail.length > this.config.maxEntries) {
 | 
				
			||||||
      this.activeAuditTrail.shift();
 | 
					      this.activeAuditTrail.shift();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -109,7 +108,6 @@ class AuditService {
 | 
				
			|||||||
    console.log(`[AUDIT-SERVICE] ${phase}/${action}: ${confidence}% confidence, ${entry.processingTimeMs}ms`);
 | 
					    console.log(`[AUDIT-SERVICE] ${phase}/${action}: ${confidence}% confidence, ${entry.processingTimeMs}ms`);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // NEW: Specialized audit methods for forensic transparency
 | 
					 | 
				
			||||||
  addAIDecision(
 | 
					  addAIDecision(
 | 
				
			||||||
    phase: string,
 | 
					    phase: string,
 | 
				
			||||||
    aiPrompt: string,
 | 
					    aiPrompt: string,
 | 
				
			||||||
@ -162,24 +160,28 @@ class AuditService {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  addPhaseCompletion(
 | 
					  addPhaseCompletion(
 | 
				
			||||||
    phaseId: string,
 | 
					    phaseId: string,
 | 
				
			||||||
    toolsAdded: string[],
 | 
					    addedTools: string[],
 | 
				
			||||||
    completionReasoning: string,
 | 
					    reasoning: string,
 | 
				
			||||||
    startTime: number,
 | 
					    startTime: number,
 | 
				
			||||||
    metadata: Record<string, any> = {}
 | 
					    metadata: Record<string, any> = {}
 | 
				
			||||||
  ): void {
 | 
					  ): void {
 | 
				
			||||||
    this.addEntry(
 | 
					    this.addEntry(
 | 
				
			||||||
      'phase-completion',
 | 
					      'phase-completion',
 | 
				
			||||||
      'phase-enhancement',
 | 
					      'phase-enhancement',
 | 
				
			||||||
      { phaseId, underrepresentedPhase: true },
 | 
					      {
 | 
				
			||||||
      { toolsAdded },
 | 
					        phaseId,
 | 
				
			||||||
      75, // Default confidence for phase completion
 | 
					        addedTools,
 | 
				
			||||||
 | 
					        reasoning: reasoning.slice(0, 200)
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        toolsAddedCount: addedTools.length,
 | 
				
			||||||
 | 
					        enhancementMethod: 'semantic-search-with-ai-reasoning'
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      metadata.moderatedTaskRelevance || 75,
 | 
				
			||||||
      startTime,
 | 
					      startTime,
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        ...metadata,
 | 
					        ...metadata,
 | 
				
			||||||
        phaseId,
 | 
					        phaseCompletionMethod: 'sophisticated-ai-reasoning'
 | 
				
			||||||
        toolsAdded,
 | 
					 | 
				
			||||||
        completionReasoning,
 | 
					 | 
				
			||||||
        enhancementType: 'semantic-phase-completion'
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -215,25 +217,30 @@ class AuditService {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  addConfidenceCalculation(
 | 
					  addConfidenceCalculation(
 | 
				
			||||||
    toolName: string,
 | 
					    toolName: string,
 | 
				
			||||||
    confidenceBreakdown: any,
 | 
					    confidence: any,
 | 
				
			||||||
    startTime: number,
 | 
					    startTime: number,
 | 
				
			||||||
    metadata: Record<string, any> = {}
 | 
					    metadata: Record<string, any> = {}
 | 
				
			||||||
  ): void {
 | 
					  ): void {
 | 
				
			||||||
    this.addEntry(
 | 
					    this.addEntry(
 | 
				
			||||||
      'confidence-scoring',
 | 
					      'confidence-scoring',
 | 
				
			||||||
      'tool-confidence',
 | 
					      'tool-confidence',
 | 
				
			||||||
      { toolName },
 | 
					      {
 | 
				
			||||||
      { confidenceBreakdown },
 | 
					        toolName,
 | 
				
			||||||
      confidenceBreakdown.overall || 50,
 | 
					        confidence: {
 | 
				
			||||||
 | 
					          overall: confidence.overall,
 | 
				
			||||||
 | 
					          semantic: confidence.semanticRelevance,
 | 
				
			||||||
 | 
					          task: confidence.taskSuitability
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        uncertaintyFactorsCount: confidence.uncertaintyFactors?.length || 0,
 | 
				
			||||||
 | 
					        strengthIndicatorsCount: confidence.strengthIndicators?.length || 0
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      confidence.overall,
 | 
				
			||||||
      startTime,
 | 
					      startTime,
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        ...metadata,
 | 
					        ...metadata,
 | 
				
			||||||
        confidenceFactors: [
 | 
					        confidenceCalculation: true
 | 
				
			||||||
          ...(confidenceBreakdown.strengthIndicators || []),
 | 
					 | 
				
			||||||
          ...(confidenceBreakdown.uncertaintyFactors || [])
 | 
					 | 
				
			||||||
        ],
 | 
					 | 
				
			||||||
        semanticRelevance: confidenceBreakdown.semanticRelevance,
 | 
					 | 
				
			||||||
        taskSuitability: confidenceBreakdown.taskSuitability
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -300,7 +307,6 @@ class AuditService {
 | 
				
			|||||||
    return { ...this.config };
 | 
					    return { ...this.config };
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Statistics and analysis methods (enhanced)
 | 
					 | 
				
			||||||
  getAuditStatistics(auditTrail: AuditEntry[]): {
 | 
					  getAuditStatistics(auditTrail: AuditEntry[]): {
 | 
				
			||||||
    totalTime: number;
 | 
					    totalTime: number;
 | 
				
			||||||
    avgConfidence: number;
 | 
					    avgConfidence: number;
 | 
				
			||||||
@ -346,12 +352,10 @@ class AuditService {
 | 
				
			|||||||
    const lowConfidenceSteps = auditTrail.filter(entry => (entry.confidence || 0) < 60).length;
 | 
					    const lowConfidenceSteps = auditTrail.filter(entry => (entry.confidence || 0) < 60).length;
 | 
				
			||||||
    const mediumConfidenceSteps = auditTrail.length - highConfidenceSteps - lowConfidenceSteps;
 | 
					    const mediumConfidenceSteps = auditTrail.length - highConfidenceSteps - lowConfidenceSteps;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Enhanced metrics
 | 
					 | 
				
			||||||
    const aiDecisionCount = auditTrail.filter(entry => entry.action === 'ai-decision').length;
 | 
					    const aiDecisionCount = auditTrail.filter(entry => entry.action === 'ai-decision').length;
 | 
				
			||||||
    const embeddingsUsageCount = auditTrail.filter(entry => entry.metadata?.embeddingsUsed).length;
 | 
					    const embeddingsUsageCount = auditTrail.filter(entry => entry.metadata?.embeddingsUsed).length;
 | 
				
			||||||
    const toolSelectionCount = auditTrail.filter(entry => entry.action === 'selection-decision').length;
 | 
					    const toolSelectionCount = auditTrail.filter(entry => entry.action === 'selection-decision').length;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Phase breakdown
 | 
					 | 
				
			||||||
    const phaseBreakdown: Record<string, { count: number; avgConfidence: number; totalTime: number }> = {};
 | 
					    const phaseBreakdown: Record<string, { count: number; avgConfidence: number; totalTime: number }> = {};
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    auditTrail.forEach(entry => {
 | 
					    auditTrail.forEach(entry => {
 | 
				
			||||||
@ -364,7 +368,6 @@ class AuditService {
 | 
				
			|||||||
      phaseBreakdown[phase].totalTime += entry.processingTimeMs || 0;
 | 
					      phaseBreakdown[phase].totalTime += entry.processingTimeMs || 0;
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Calculate average confidence per phase
 | 
					 | 
				
			||||||
    Object.keys(phaseBreakdown).forEach(phase => {
 | 
					    Object.keys(phaseBreakdown).forEach(phase => {
 | 
				
			||||||
      const phaseEntries = auditTrail.filter(entry => entry.phase === phase);
 | 
					      const phaseEntries = auditTrail.filter(entry => entry.phase === phase);
 | 
				
			||||||
      const validEntries = phaseEntries.filter(entry => typeof entry.confidence === 'number');
 | 
					      const validEntries = phaseEntries.filter(entry => typeof entry.confidence === 'number');
 | 
				
			||||||
@ -425,7 +428,6 @@ class AuditService {
 | 
				
			|||||||
        return;
 | 
					        return;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Required fields validation
 | 
					 | 
				
			||||||
      const requiredFields = ['timestamp', 'phase', 'action'];
 | 
					      const requiredFields = ['timestamp', 'phase', 'action'];
 | 
				
			||||||
      requiredFields.forEach(field => {
 | 
					      requiredFields.forEach(field => {
 | 
				
			||||||
        if (!(field in entry)) {
 | 
					        if (!(field in entry)) {
 | 
				
			||||||
@ -433,7 +435,6 @@ class AuditService {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Enhanced validation for audit quality
 | 
					 | 
				
			||||||
      if (entry.action === 'ai-decision' && !entry.metadata?.aiPrompt && !entry.metadata?.reasoning) {
 | 
					      if (entry.action === 'ai-decision' && !entry.metadata?.aiPrompt && !entry.metadata?.reasoning) {
 | 
				
			||||||
        warnings.push(`Entry ${index}: AI decision lacks transparency (no prompt or reasoning)`);
 | 
					        warnings.push(`Entry ${index}: AI decision lacks transparency (no prompt or reasoning)`);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@ -442,7 +443,6 @@ class AuditService {
 | 
				
			|||||||
        warnings.push(`Entry ${index}: Tool selection lacks methodology info`);
 | 
					        warnings.push(`Entry ${index}: Tool selection lacks methodology info`);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Data type validation
 | 
					 | 
				
			||||||
      if (typeof entry.confidence !== 'number' || entry.confidence < 0 || entry.confidence > 100) {
 | 
					      if (typeof entry.confidence !== 'number' || entry.confidence < 0 || entry.confidence > 100) {
 | 
				
			||||||
        warnings.push(`Entry ${index} has invalid confidence value: ${entry.confidence}`);
 | 
					        warnings.push(`Entry ${index} has invalid confidence value: ${entry.confidence}`);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,5 @@
 | 
				
			|||||||
// src/utils/clientUtils.ts - Consolidated (removes duplicates from toolHelpers.ts)
 | 
					// src/utils/clientUtils.ts
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Tool helper functions (moved here to avoid circular imports)
 | 
					 | 
				
			||||||
export function createToolSlug(toolName: string): string {
 | 
					export function createToolSlug(toolName: string): string {
 | 
				
			||||||
  if (!toolName || typeof toolName !== 'string') {
 | 
					  if (!toolName || typeof toolName !== 'string') {
 | 
				
			||||||
    console.warn('[CLIENT-UTILS] Invalid toolName provided to createToolSlug:', toolName);
 | 
					    console.warn('[CLIENT-UTILS] Invalid toolName provided to createToolSlug:', toolName);
 | 
				
			||||||
@ -30,7 +29,6 @@ export function isToolHosted(tool: any): boolean {
 | 
				
			|||||||
         tool.projectUrl.trim() !== "";
 | 
					         tool.projectUrl.trim() !== "";
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Text and display utilities
 | 
					 | 
				
			||||||
export function sanitizeText(text: string): string {
 | 
					export function sanitizeText(text: string): string {
 | 
				
			||||||
  if (typeof text !== 'string') return '';
 | 
					  if (typeof text !== 'string') return '';
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
@ -60,7 +58,6 @@ export function truncateText(text: string, maxLength: number): string {
 | 
				
			|||||||
  return text.slice(0, maxLength) + '...';
 | 
					  return text.slice(0, maxLength) + '...';
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Data summarization utilities
 | 
					 | 
				
			||||||
export function summarizeData(data: any): string {
 | 
					export function summarizeData(data: any): string {
 | 
				
			||||||
  if (data === null || data === undefined) return 'null';
 | 
					  if (data === null || data === undefined) return 'null';
 | 
				
			||||||
  if (typeof data === 'string') {
 | 
					  if (typeof data === 'string') {
 | 
				
			||||||
@ -85,7 +82,6 @@ export function summarizeData(data: any): string {
 | 
				
			|||||||
  return String(data);
 | 
					  return String(data);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Time formatting utilities
 | 
					 | 
				
			||||||
export function formatDuration(ms: number): string {
 | 
					export function formatDuration(ms: number): string {
 | 
				
			||||||
  if (ms < 1000) return '< 1s';
 | 
					  if (ms < 1000) return '< 1s';
 | 
				
			||||||
  if (ms < 60000) return `${Math.ceil(ms / 1000)}s`;
 | 
					  if (ms < 60000) return `${Math.ceil(ms / 1000)}s`;
 | 
				
			||||||
@ -94,7 +90,6 @@ export function formatDuration(ms: number): string {
 | 
				
			|||||||
  return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;
 | 
					  return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DOM utilities
 | 
					 | 
				
			||||||
export function showElement(element: HTMLElement | null): void {
 | 
					export function showElement(element: HTMLElement | null): void {
 | 
				
			||||||
  if (element) {
 | 
					  if (element) {
 | 
				
			||||||
    element.style.display = 'block';
 | 
					    element.style.display = 'block';
 | 
				
			||||||
@ -109,7 +104,6 @@ export function hideElement(element: HTMLElement | null): void {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Autocomplete functionality (kept from original clientUtils.ts as it's UI-specific)
 | 
					 | 
				
			||||||
interface AutocompleteOptions {
 | 
					interface AutocompleteOptions {
 | 
				
			||||||
  minLength?: number;
 | 
					  minLength?: number;
 | 
				
			||||||
  maxResults?: number;
 | 
					  maxResults?: number;
 | 
				
			||||||
 | 
				
			|||||||
@ -44,7 +44,7 @@ class ConfidenceScoring {
 | 
				
			|||||||
      highThreshold: this.getEnvInt('CONFIDENCE_HIGH_THRESHOLD', 80)
 | 
					      highThreshold: this.getEnvInt('CONFIDENCE_HIGH_THRESHOLD', 80)
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    console.log('[CONFIDENCE-SCORING] Initialized with config:', this.config);
 | 
					    console.log('[CONFIDENCE-SCORING] Initialized with restored config:', this.config);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private getEnvFloat(key: string, defaultValue: number): number {
 | 
					  private getEnvFloat(key: string, defaultValue: number): number {
 | 
				
			||||||
@ -70,7 +70,6 @@ class ConfidenceScoring {
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    let enhancedTaskSuitability = taskRelevance;
 | 
					    let enhancedTaskSuitability = taskRelevance;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Phase alignment bonus for workflow mode
 | 
					 | 
				
			||||||
    if (context.mode === 'workflow') {
 | 
					    if (context.mode === 'workflow') {
 | 
				
			||||||
      const toolSelection = context.selectedTools?.find((st: any) => st.tool && st.tool.name === tool.name);
 | 
					      const toolSelection = context.selectedTools?.find((st: any) => st.tool && st.tool.name === tool.name);
 | 
				
			||||||
      if (toolSelection && tool.phases && Array.isArray(tool.phases) && tool.phases.includes(toolSelection.phase)) {
 | 
					      if (toolSelection && tool.phases && Array.isArray(tool.phases) && tool.phases.includes(toolSelection.phase)) {
 | 
				
			||||||
@ -116,18 +115,15 @@ class ConfidenceScoring {
 | 
				
			|||||||
  ): string[] {
 | 
					  ): string[] {
 | 
				
			||||||
    const factors: string[] = [];
 | 
					    const factors: string[] = [];
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Add explicit limitations
 | 
					 | 
				
			||||||
    if (limitations?.length > 0) {
 | 
					    if (limitations?.length > 0) {
 | 
				
			||||||
      factors.push(...limitations.slice(0, 2));
 | 
					      factors.push(...limitations.slice(0, 2));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Semantic similarity concerns
 | 
					 | 
				
			||||||
    const similarity = context.embeddingsSimilarities.get(tool.name) || 0.5;
 | 
					    const similarity = context.embeddingsSimilarities.get(tool.name) || 0.5;
 | 
				
			||||||
    if (similarity < 0.7) {
 | 
					    if (similarity < 0.7) {
 | 
				
			||||||
      factors.push('Geringe semantische Ähnlichkeit zur Anfrage');
 | 
					      factors.push('Geringe semantische Ähnlichkeit zur Anfrage');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Skill level vs query complexity mismatches
 | 
					 | 
				
			||||||
    if (tool.skillLevel === 'expert' && /schnell|rapid|triage|urgent|sofort/i.test(context.userQuery)) {
 | 
					    if (tool.skillLevel === 'expert' && /schnell|rapid|triage|urgent|sofort/i.test(context.userQuery)) {
 | 
				
			||||||
      factors.push('Experten-Tool für zeitkritisches Szenario');
 | 
					      factors.push('Experten-Tool für zeitkritisches Szenario');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -136,17 +132,14 @@ class ConfidenceScoring {
 | 
				
			|||||||
      factors.push('Einsteiger-Tool für komplexe Analyse');
 | 
					      factors.push('Einsteiger-Tool für komplexe Analyse');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Technical accessibility concerns
 | 
					 | 
				
			||||||
    if (tool.type === 'software' && !isToolHosted(tool) && tool.accessType === 'download') {
 | 
					    if (tool.type === 'software' && !isToolHosted(tool) && tool.accessType === 'download') {
 | 
				
			||||||
      factors.push('Installation und Setup erforderlich');
 | 
					      factors.push('Installation und Setup erforderlich');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Licensing concerns
 | 
					 | 
				
			||||||
    if (tool.license === 'Proprietary') {
 | 
					    if (tool.license === 'Proprietary') {
 | 
				
			||||||
      factors.push('Kommerzielle Software - Lizenzkosten zu beachten');
 | 
					      factors.push('Kommerzielle Software - Lizenzkosten zu beachten');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Overall confidence concerns
 | 
					 | 
				
			||||||
    if (confidence < 60) {
 | 
					    if (confidence < 60) {
 | 
				
			||||||
      factors.push('Moderate Gesamtbewertung - alternative Ansätze empfohlen');
 | 
					      factors.push('Moderate Gesamtbewertung - alternative Ansätze empfohlen');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -157,28 +150,23 @@ class ConfidenceScoring {
 | 
				
			|||||||
  private identifyStrengthIndicators(tool: any, context: AnalysisContext, confidence: number): string[] {
 | 
					  private identifyStrengthIndicators(tool: any, context: AnalysisContext, confidence: number): string[] {
 | 
				
			||||||
    const indicators: string[] = [];
 | 
					    const indicators: string[] = [];
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // High semantic relevance
 | 
					 | 
				
			||||||
    const similarity = context.embeddingsSimilarities.get(tool.name) || 0.5;
 | 
					    const similarity = context.embeddingsSimilarities.get(tool.name) || 0.5;
 | 
				
			||||||
    if (similarity >= 0.7) {
 | 
					    if (similarity >= 0.7) {
 | 
				
			||||||
      indicators.push('Sehr gute semantische Übereinstimmung mit Ihrer Anfrage');
 | 
					      indicators.push('Sehr gute semantische Übereinstimmung mit Ihrer Anfrage');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Documentation availability
 | 
					 | 
				
			||||||
    if (tool.knowledgebase === true) {
 | 
					    if (tool.knowledgebase === true) {
 | 
				
			||||||
      indicators.push('Umfassende Dokumentation und Wissensbasis verfügbar');
 | 
					      indicators.push('Umfassende Dokumentation und Wissensbasis verfügbar');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Immediate availability
 | 
					 | 
				
			||||||
    if (isToolHosted(tool)) {
 | 
					    if (isToolHosted(tool)) {
 | 
				
			||||||
      indicators.push('Sofort verfügbar über gehostete Lösung');
 | 
					      indicators.push('Sofort verfügbar über gehostete Lösung');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Balanced skill requirements
 | 
					 | 
				
			||||||
    if (tool.skillLevel === 'intermediate' || tool.skillLevel === 'advanced') {
 | 
					    if (tool.skillLevel === 'intermediate' || tool.skillLevel === 'advanced') {
 | 
				
			||||||
      indicators.push('Ausgewogenes Verhältnis zwischen Funktionalität und Benutzerfreundlichkeit');
 | 
					      indicators.push('Ausgewogenes Verhältnis zwischen Funktionalität und Benutzerfreundlichkeit');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Method-query alignment
 | 
					 | 
				
			||||||
    if (tool.type === 'method' && /methodik|vorgehen|prozess|ansatz/i.test(context.userQuery)) {
 | 
					    if (tool.type === 'method' && /methodik|vorgehen|prozess|ansatz/i.test(context.userQuery)) {
 | 
				
			||||||
      indicators.push('Methodischer Ansatz passt zu Ihrer prozeduralen Anfrage');
 | 
					      indicators.push('Methodischer Ansatz passt zu Ihrer prozeduralen Anfrage');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -197,12 +185,10 @@ class ConfidenceScoring {
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    let confidence = 60;
 | 
					    let confidence = 60;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Selection ratio scoring
 | 
					 | 
				
			||||||
    if (selectionRatio > 0.05 && selectionRatio < 0.3) confidence += 20;
 | 
					    if (selectionRatio > 0.05 && selectionRatio < 0.3) confidence += 20;
 | 
				
			||||||
    else if (selectionRatio <= 0.05) confidence -= 10;
 | 
					    else if (selectionRatio <= 0.05) confidence -= 10;
 | 
				
			||||||
    else confidence -= 15;
 | 
					    else confidence -= 15;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Quality indicators
 | 
					 | 
				
			||||||
    if (hasReasoning) confidence += 15;
 | 
					    if (hasReasoning) confidence += 15;
 | 
				
			||||||
    if (result.selectedConcepts?.length > 0) confidence += 5;
 | 
					    if (result.selectedConcepts?.length > 0) confidence += 5;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
				
			|||||||
@ -1,10 +1,9 @@
 | 
				
			|||||||
// src/utils/jsonUtils.ts - Centralized JSON parsing and utilities
 | 
					// src/utils/jsonUtils.ts
 | 
				
			||||||
export class JSONParser {
 | 
					export class JSONParser {
 | 
				
			||||||
  static safeParseJSON(jsonString: string, fallback: any = null): any {
 | 
					  static safeParseJSON(jsonString: string, fallback: any = null): any {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      let cleaned = jsonString.trim();
 | 
					      let cleaned = jsonString.trim();
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      // Remove code block markers
 | 
					 | 
				
			||||||
      const jsonBlockPatterns = [
 | 
					      const jsonBlockPatterns = [
 | 
				
			||||||
        /```json\s*([\s\S]*?)\s*```/i,
 | 
					        /```json\s*([\s\S]*?)\s*```/i,
 | 
				
			||||||
        /```\s*([\s\S]*?)\s*```/i,
 | 
					        /```\s*([\s\S]*?)\s*```/i,
 | 
				
			||||||
@ -19,7 +18,6 @@ export class JSONParser {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      // Handle truncated JSON
 | 
					 | 
				
			||||||
      if (!cleaned.endsWith('}') && !cleaned.endsWith(']')) {
 | 
					      if (!cleaned.endsWith('}') && !cleaned.endsWith(']')) {
 | 
				
			||||||
        console.warn('[JSON-PARSER] JSON appears truncated, attempting recovery');
 | 
					        console.warn('[JSON-PARSER] JSON appears truncated, attempting recovery');
 | 
				
			||||||
        cleaned = this.repairTruncatedJSON(cleaned);
 | 
					        cleaned = this.repairTruncatedJSON(cleaned);
 | 
				
			||||||
@ -27,7 +25,6 @@ export class JSONParser {
 | 
				
			|||||||
      
 | 
					      
 | 
				
			||||||
      const parsed = JSON.parse(cleaned);
 | 
					      const parsed = JSON.parse(cleaned);
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      // Ensure proper structure for tool selection responses
 | 
					 | 
				
			||||||
      if (parsed && typeof parsed === 'object') {
 | 
					      if (parsed && typeof parsed === 'object') {
 | 
				
			||||||
        if (!parsed.selectedTools) parsed.selectedTools = [];
 | 
					        if (!parsed.selectedTools) parsed.selectedTools = [];
 | 
				
			||||||
        if (!parsed.selectedConcepts) parsed.selectedConcepts = [];
 | 
					        if (!parsed.selectedConcepts) parsed.selectedConcepts = [];
 | 
				
			||||||
@ -109,7 +106,6 @@ export class JSONParser {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Fallback: extract any quoted strings that look like tool names
 | 
					 | 
				
			||||||
    if (selectedTools.length === 0 && selectedConcepts.length === 0) {
 | 
					    if (selectedTools.length === 0 && selectedConcepts.length === 0) {
 | 
				
			||||||
      const allMatches = jsonString.match(/"([^"]+)"/g);
 | 
					      const allMatches = jsonString.match(/"([^"]+)"/g);
 | 
				
			||||||
      if (allMatches) {
 | 
					      if (allMatches) {
 | 
				
			||||||
@ -139,7 +135,6 @@ export class JSONParser {
 | 
				
			|||||||
      throw new Error(`JSON string too large (${jsonString.length} bytes, max ${maxSize})`);
 | 
					      throw new Error(`JSON string too large (${jsonString.length} bytes, max ${maxSize})`);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Security checks for potentially malicious content
 | 
					 | 
				
			||||||
    const suspiciousPatterns = [
 | 
					    const suspiciousPatterns = [
 | 
				
			||||||
      /<script/i,
 | 
					      /<script/i,
 | 
				
			||||||
      /javascript:/i,
 | 
					      /javascript:/i,
 | 
				
			||||||
@ -158,7 +153,6 @@ export class JSONParser {
 | 
				
			|||||||
    try {
 | 
					    try {
 | 
				
			||||||
      const parsed = JSON.parse(jsonString);
 | 
					      const parsed = JSON.parse(jsonString);
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      // Validate basic structure
 | 
					 | 
				
			||||||
      if (typeof parsed !== 'object' || parsed === null) {
 | 
					      if (typeof parsed !== 'object' || parsed === null) {
 | 
				
			||||||
        throw new Error('JSON must be an object');
 | 
					        throw new Error('JSON must be an object');
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@ -182,11 +176,9 @@ export class JSONParser {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (typeof obj === 'string') {
 | 
					    if (typeof obj === 'string') {
 | 
				
			||||||
      // Sanitize strings that might contain sensitive data
 | 
					 | 
				
			||||||
      if (obj.length > 500) {
 | 
					      if (obj.length > 500) {
 | 
				
			||||||
        return obj.slice(0, 500) + '...[truncated]';
 | 
					        return obj.slice(0, 500) + '...[truncated]';
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      // Remove potential code injection patterns
 | 
					 | 
				
			||||||
      return obj.replace(/<script[\s\S]*?<\/script>/gi, '[script removed]');
 | 
					      return obj.replace(/<script[\s\S]*?<\/script>/gi, '[script removed]');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -217,7 +209,6 @@ export class JSONParser {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      const sanitized: any = {};
 | 
					      const sanitized: any = {};
 | 
				
			||||||
      keys.forEach(key => {
 | 
					      keys.forEach(key => {
 | 
				
			||||||
        // Skip potential dangerous properties
 | 
					 | 
				
			||||||
        if (['__proto__', 'constructor', 'prototype'].includes(key)) {
 | 
					        if (['__proto__', 'constructor', 'prototype'].includes(key)) {
 | 
				
			||||||
          return;
 | 
					          return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -237,7 +228,6 @@ export class JSONParser {
 | 
				
			|||||||
      return { isValid: false, errors };
 | 
					      return { isValid: false, errors };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Check required top-level properties
 | 
					 | 
				
			||||||
    const requiredProps = ['metadata', 'recommendation', 'auditTrail'];
 | 
					    const requiredProps = ['metadata', 'recommendation', 'auditTrail'];
 | 
				
			||||||
    for (const prop of requiredProps) {
 | 
					    for (const prop of requiredProps) {
 | 
				
			||||||
      if (!(prop in data)) {
 | 
					      if (!(prop in data)) {
 | 
				
			||||||
@ -245,7 +235,6 @@ export class JSONParser {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Validate metadata
 | 
					 | 
				
			||||||
    if (data.metadata && typeof data.metadata === 'object') {
 | 
					    if (data.metadata && typeof data.metadata === 'object') {
 | 
				
			||||||
      const requiredMetadataProps = ['timestamp', 'version', 'userQuery', 'mode'];
 | 
					      const requiredMetadataProps = ['timestamp', 'version', 'userQuery', 'mode'];
 | 
				
			||||||
      for (const prop of requiredMetadataProps) {
 | 
					      for (const prop of requiredMetadataProps) {
 | 
				
			||||||
@ -257,7 +246,6 @@ export class JSONParser {
 | 
				
			|||||||
      errors.push('Invalid metadata structure');
 | 
					      errors.push('Invalid metadata structure');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Validate audit trail
 | 
					 | 
				
			||||||
    if (!Array.isArray(data.auditTrail)) {
 | 
					    if (!Array.isArray(data.auditTrail)) {
 | 
				
			||||||
      errors.push('auditTrail must be an array');
 | 
					      errors.push('auditTrail must be an array');
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
@ -293,7 +281,7 @@ export class JSONParser {
 | 
				
			|||||||
      metadata: {
 | 
					      metadata: {
 | 
				
			||||||
        timestamp: new Date().toISOString(),
 | 
					        timestamp: new Date().toISOString(),
 | 
				
			||||||
        version: "1.0",
 | 
					        version: "1.0",
 | 
				
			||||||
        userQuery: userQuery.slice(0, 1000), // Truncate for security
 | 
					        userQuery: userQuery.slice(0, 1000),
 | 
				
			||||||
        mode,
 | 
					        mode,
 | 
				
			||||||
        exportedBy: 'ForensicPathways',
 | 
					        exportedBy: 'ForensicPathways',
 | 
				
			||||||
        toolsDataHash: additionalMetadata.toolsDataHash || 'unknown',
 | 
					        toolsDataHash: additionalMetadata.toolsDataHash || 'unknown',
 | 
				
			||||||
@ -316,16 +304,13 @@ export class JSONParser {
 | 
				
			|||||||
    const issues: string[] = [];
 | 
					    const issues: string[] = [];
 | 
				
			||||||
    const warnings: string[] = [];
 | 
					    const warnings: string[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Basic structure validation
 | 
					 | 
				
			||||||
    const structureValidation = this.validateAuditExportStructure(data);
 | 
					    const structureValidation = this.validateAuditExportStructure(data);
 | 
				
			||||||
    if (!structureValidation.isValid) {
 | 
					    if (!structureValidation.isValid) {
 | 
				
			||||||
      issues.push(...structureValidation.errors);
 | 
					      issues.push(...structureValidation.errors);
 | 
				
			||||||
      return { isValid: false, issues, warnings };
 | 
					      return { isValid: false, issues, warnings };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Additional validation for uploaded content
 | 
					 | 
				
			||||||
    if (data.metadata) {
 | 
					    if (data.metadata) {
 | 
				
			||||||
      // Check timestamp validity
 | 
					 | 
				
			||||||
      const timestamp = new Date(data.metadata.timestamp);
 | 
					      const timestamp = new Date(data.metadata.timestamp);
 | 
				
			||||||
      if (isNaN(timestamp.getTime())) {
 | 
					      if (isNaN(timestamp.getTime())) {
 | 
				
			||||||
        warnings.push('Invalid timestamp in metadata');
 | 
					        warnings.push('Invalid timestamp in metadata');
 | 
				
			||||||
@ -337,13 +322,11 @@ export class JSONParser {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Validate mode
 | 
					 | 
				
			||||||
      if (!['workflow', 'tool'].includes(data.metadata.mode)) {
 | 
					      if (!['workflow', 'tool'].includes(data.metadata.mode)) {
 | 
				
			||||||
        warnings.push(`Unknown analysis mode: ${data.metadata.mode}`);
 | 
					        warnings.push(`Unknown analysis mode: ${data.metadata.mode}`);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Validate audit trail quality
 | 
					 | 
				
			||||||
    if (Array.isArray(data.auditTrail)) {
 | 
					    if (Array.isArray(data.auditTrail)) {
 | 
				
			||||||
      const aiDecisions = data.auditTrail.filter(e => e.action === 'ai-decision').length;
 | 
					      const aiDecisions = data.auditTrail.filter(e => e.action === 'ai-decision').length;
 | 
				
			||||||
      const toolSelections = data.auditTrail.filter(e => e.action === 'selection-decision').length;
 | 
					      const toolSelections = data.auditTrail.filter(e => e.action === 'selection-decision').length;
 | 
				
			||||||
@ -356,7 +339,6 @@ export class JSONParser {
 | 
				
			|||||||
        warnings.push('No tool selections found in audit trail');
 | 
					        warnings.push('No tool selections found in audit trail');
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Check for confidence values
 | 
					 | 
				
			||||||
      const entriesWithConfidence = data.auditTrail.filter(e => typeof e.confidence === 'number').length;
 | 
					      const entriesWithConfidence = data.auditTrail.filter(e => typeof e.confidence === 'number').length;
 | 
				
			||||||
      const confidenceRatio = entriesWithConfidence / data.auditTrail.length;
 | 
					      const confidenceRatio = entriesWithConfidence / data.auditTrail.length;
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,7 @@
 | 
				
			|||||||
import { aiService } from './aiService.js';
 | 
					import { aiService } from './aiService.js';
 | 
				
			||||||
import { embeddingsService, type SimilarityResult } from './embeddings.js';
 | 
					import { embeddingsService, type SimilarityResult } from './embeddings.js';
 | 
				
			||||||
import { confidenceScoring } from './confidenceScoring.js';
 | 
					import { confidenceScoring } from './confidenceScoring.js';
 | 
				
			||||||
import { JSONParser } from './jsonUtils.js'; // FIXED: Use centralized JSON parsing
 | 
					import { JSONParser } from './jsonUtils.js';
 | 
				
			||||||
import { getPrompt } from '../config/prompts.js';
 | 
					import { getPrompt } from '../config/prompts.js';
 | 
				
			||||||
import 'dotenv/config';
 | 
					import 'dotenv/config';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -111,7 +111,6 @@ class ToolSelector {
 | 
				
			|||||||
      
 | 
					      
 | 
				
			||||||
      console.log('[TOOL-SELECTOR] Embeddings found', similarItems.length, 'similar items');
 | 
					      console.log('[TOOL-SELECTOR] Embeddings found', similarItems.length, 'similar items');
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      // Store similarities for confidence calculation
 | 
					 | 
				
			||||||
      similarItems.forEach(item => {
 | 
					      similarItems.forEach(item => {
 | 
				
			||||||
        context.embeddingsSimilarities.set(item.name, item.similarity);
 | 
					        context.embeddingsSimilarities.set(item.name, item.similarity);
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
@ -238,7 +237,6 @@ class ToolSelector {
 | 
				
			|||||||
    const basePrompt = getPrompt('toolSelection', mode, userQuery, selectionMethod, this.config.maxSelectedItems);
 | 
					    const basePrompt = getPrompt('toolSelection', mode, userQuery, selectionMethod, this.config.maxSelectedItems);
 | 
				
			||||||
    const prompt = getPrompt('toolSelectionWithData', basePrompt, toolsToSend, conceptsToSend);
 | 
					    const prompt = getPrompt('toolSelectionWithData', basePrompt, toolsToSend, conceptsToSend);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Validate prompt length
 | 
					 | 
				
			||||||
    aiService.validatePromptLength(prompt);
 | 
					    aiService.validatePromptLength(prompt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    console.log('[TOOL-SELECTOR] Sending to AI:', 
 | 
					    console.log('[TOOL-SELECTOR] Sending to AI:', 
 | 
				
			||||||
@ -249,7 +247,6 @@ class ToolSelector {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      const response = await aiService.callAI(prompt, { maxTokens: 2500 });
 | 
					      const response = await aiService.callAI(prompt, { maxTokens: 2500 });
 | 
				
			||||||
      // FIXED: Use centralized JSON parsing
 | 
					 | 
				
			||||||
      const result = JSONParser.safeParseJSON(response.content, null);
 | 
					      const result = JSONParser.safeParseJSON(response.content, null);
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      if (!result || !Array.isArray(result.selectedTools) || !Array.isArray(result.selectedConcepts)) {
 | 
					      if (!result || !Array.isArray(result.selectedTools) || !Array.isArray(result.selectedConcepts)) {
 | 
				
			||||||
@ -315,7 +312,6 @@ class ToolSelector {
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      const response = await aiService.callMicroTaskAI(prompt, 1000);
 | 
					      const response = await aiService.callMicroTaskAI(prompt, 1000);
 | 
				
			||||||
      // FIXED: Use centralized JSON parsing
 | 
					 | 
				
			||||||
      const selections = JSONParser.safeParseJSON(response.content, []);
 | 
					      const selections = JSONParser.safeParseJSON(response.content, []);
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      if (Array.isArray(selections)) {
 | 
					      if (Array.isArray(selections)) {
 | 
				
			||||||
@ -368,8 +364,6 @@ class ToolSelector {
 | 
				
			|||||||
    related_software: concept.related_software || []
 | 
					    related_software: concept.related_software || []
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // REMOVED: safeParseJSON method - now using centralized version from jsonUtils.ts
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  getConfig(): ToolSelectionConfig {
 | 
					  getConfig(): ToolSelectionConfig {
 | 
				
			||||||
    return { ...this.config };
 | 
					    return { ...this.config };
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user