// ======================================== // FICHIER: PatternBreakingLayers.js // RESPONSABILITÉ: Stacks prédéfinis pour Pattern Breaking // Configurations optimisées par cas d'usage // ======================================== const { logSh } = require('../ErrorReporting'); /** * CONFIGURATIONS PRÉDÉFINIES PATTERN BREAKING * Optimisées pour différents niveaux et cas d'usage */ const PATTERN_BREAKING_STACKS = { // ======================================== // STACK LÉGER - Usage quotidien (✅ AMÉLIORÉ) // ======================================== lightPatternBreaking: { name: 'Light Pattern Breaking', description: 'Variations minimales préservant le style original', intensity: 0.3, config: { syntaxVariationEnabled: true, llmFingerprintReplacement: false, // Pas de remplacement mots naturalConnectorsEnabled: true, preserveReadability: true, maxModificationsPerElement: 2, qualityThreshold: 0.75, // ✅ Augmenté de 0.7 → 0.75 // ✅ Désactivations explicites aggressiveSentenceSplitting: false, aggressiveSentenceMerging: false, casualConnectors: false, casualizationIntensive: false, humanImperfections: false, questionInjection: false }, expectedReduction: '8-12%', // ✅ Réduit de 10-15% → 8-12% useCase: 'Articles standard, préservation maximale du style' }, // ======================================== // STACK STANDARD - Équilibre optimal (✅ AMÉLIORÉ) // ======================================== standardPatternBreaking: { name: 'Standard Pattern Breaking', description: 'Équilibre qualité/variations pour usage général', intensity: 0.5, config: { syntaxVariationEnabled: true, llmFingerprintReplacement: true, naturalConnectorsEnabled: true, preserveReadability: true, maxModificationsPerElement: 4, qualityThreshold: 0.65, // ✅ Augmenté de 0.6 → 0.65 // ✅ Features casual désactivées par défaut aggressiveSentenceSplitting: false, aggressiveSentenceMerging: false, casualConnectors: false, // ✅ Désactivé casualizationIntensive: false, // ✅ Désactivé humanImperfections: false, // ✅ Désactivé naturalHesitations: false, informalExpressions: false }, expectedReduction: '15-20%', // ✅ Réduit de 20-25% → 15-20% useCase: 'Usage général - articles, blogs, contenu web' }, // ======================================== // STACK INTENSIF - Anti-détection poussée (✅ CONTRÔLÉ) // ======================================== heavyPatternBreaking: { name: 'Heavy Pattern Breaking', description: 'Variations intensives avec contrôle qualité', intensity: 0.7, // ✅ Réduit de 0.8 → 0.7 config: { syntaxVariationEnabled: true, llmFingerprintReplacement: true, naturalConnectorsEnabled: true, preserveReadability: true, maxModificationsPerElement: 6, qualityThreshold: 0.6, // ✅ Augmenté de 0.5 → 0.6 // ✅ Activation sélective features aggressiveSentenceSplitting: true, // Activé en mode heavy uniquement aggressiveSentenceMerging: true, // Activé en mode heavy uniquement microSyntaxVariations: true, frenchLLMPatterns: true, // ❌ Casualisation toujours désactivée (trop risqué) casualConnectors: false, casualizationIntensive: false, humanImperfections: false }, expectedReduction: '25-30%', // ✅ Réduit de 30-35% → 25-30% useCase: 'Détection élevée, besoin variations fortes SANS casualisation' }, // ======================================== // STACK ADAPTATIF - Selon contenu (✅ AMÉLIORÉ) // ======================================== adaptivePatternBreaking: { name: 'Adaptive Pattern Breaking', description: 'Adaptation intelligente selon détection patterns', intensity: 0.6, config: { syntaxVariationEnabled: true, llmFingerprintReplacement: true, naturalConnectorsEnabled: true, preserveReadability: true, maxModificationsPerElement: 4, // ✅ 5 → 4 qualityThreshold: 0.65, // ✅ 0.6 → 0.65 adaptiveMode: true, // ✅ Pas de casualisation même en adaptatif aggressiveSentenceSplitting: false, aggressiveSentenceMerging: false, casualConnectors: false, casualizationIntensive: false, humanImperfections: false }, expectedReduction: '15-22%', // ✅ 25-30% → 15-22% useCase: 'Adaptation automatique sans casualisation' }, // ======================================== // STACK PROFESSIONNEL - Contenu B2B/Commercial // ======================================== professionalPatternBreaking: { name: 'Professional Pattern Breaking', description: 'Variations subtiles préservant le ton professionnel', intensity: 0.4, config: { syntaxVariationEnabled: true, llmFingerprintReplacement: true, naturalConnectorsEnabled: true, preserveReadability: true, maxModificationsPerElement: 3, qualityThreshold: 0.75, // DÉSACTIVATION FEATURES CASUAL aggressiveSentenceSplitting: false, aggressiveSentenceMerging: false, casualConnectors: false, // ❌ Pas de "du coup", "genre" hesitationMarkers: false, // ❌ Pas de "...", "euh" colloquialTransitions: false, // ❌ Pas de transitions colloquiales casualizationIntensive: false, // ❌ Pas de casualisation vocab naturalHesitations: false, // ❌ Pas d'hésitations informalExpressions: false, // ❌ Pas de "sympa", "pas mal" // FEATURES PROFESSIONNELLES ACTIVÉES microSyntaxVariations: true, // ✅ Micro-variations subtiles frenchLLMPatterns: true, // ✅ Patterns français (modéré) overlyFormalVocabulary: false, // ✅ Garder vocabulaire formel repetitiveStarters: true, // ✅ Varier débuts phrases perfectTransitions: true, // ✅ Casser transitions trop parfaites // CONTEXTE PROFESSIONNEL connectorTone: 'commercial', // Ton commercial/technique professionalMode: true // Mode professionnel activé }, expectedReduction: '10-15%', useCase: 'Contenu commercial B2B, signalétique, technique' }, // ======================================== // STACK SYNTAXE FOCUS - Syntaxe uniquement // ======================================== syntaxFocus: { name: 'Syntax Focus', description: 'Focus sur variations syntaxiques uniquement', intensity: 0.7, config: { syntaxVariationEnabled: true, llmFingerprintReplacement: false, naturalConnectorsEnabled: false, preserveReadability: true, maxModificationsPerElement: 6, qualityThreshold: 0.7 }, expectedReduction: '15-20%', useCase: 'Préservation vocabulaire, syntaxe variable' }, // ======================================== // STACK CONNECTEURS FOCUS - Connecteurs uniquement // ======================================== connectorsFocus: { name: 'Connectors Focus', description: 'Humanisation connecteurs et transitions', intensity: 0.8, config: { syntaxVariationEnabled: false, llmFingerprintReplacement: false, naturalConnectorsEnabled: true, preserveReadability: true, maxModificationsPerElement: 4, qualityThreshold: 0.8, connectorTone: 'casual' // casual, conversational, technical, commercial }, expectedReduction: '12-18%', useCase: 'Textes formels à humaniser' } }; /** * APPLICATION STACK PATTERN BREAKING * @param {string} stackName - Nom du stack à appliquer * @param {object} content - Contenu à traiter * @param {object} overrides - Options pour surcharger le stack * @returns {object} - { content, stats, stackUsed } */ async function applyPatternBreakingStack(stackName, content, overrides = {}) { const { applyPatternBreakingLayer } = require('./PatternBreakingCore'); logSh(`📦 Application Stack Pattern Breaking: ${stackName}`, 'INFO'); const stack = PATTERN_BREAKING_STACKS[stackName]; if (!stack) { logSh(`❌ Stack Pattern Breaking inconnu: ${stackName}`, 'WARNING'); throw new Error(`Stack Pattern Breaking inconnu: ${stackName}`); } try { // Configuration fusionnée (stack + overrides) const finalConfig = { ...stack.config, intensityLevel: stack.intensity, ...overrides }; logSh(` 🎯 Configuration: ${stack.description}`, 'DEBUG'); logSh(` ⚡ Intensité: ${finalConfig.intensityLevel} | Réduction attendue: ${stack.expectedReduction}`, 'DEBUG'); // Mode adaptatif si activé if (finalConfig.adaptiveMode) { const adaptedConfig = await adaptConfigurationToContent(content, finalConfig); Object.assign(finalConfig, adaptedConfig); logSh(` 🧠 Mode adaptatif appliqué`, 'DEBUG'); } // Application Pattern Breaking const result = await applyPatternBreakingLayer(content, finalConfig); logSh(`📦 Stack Pattern Breaking terminé: ${result.stats?.totalModifications || 0} modifications`, 'INFO'); return { content: result.content, stats: { ...result.stats, stackUsed: stackName, stackDescription: stack.description, expectedReduction: stack.expectedReduction }, modifications: result.modifications || result.stats?.totalModifications || 0, // ✅ AJOUTÉ: Propagation modifications fallback: result.fallback, stackUsed: stackName }; } catch (error) { logSh(`❌ Erreur application Stack Pattern Breaking ${stackName}: ${error.message}`, 'ERROR'); throw error; } } /** * ADAPTATION CONFIGURATION SELON CONTENU */ async function adaptConfigurationToContent(content, baseConfig) { const { detectLLMPatterns } = require('./LLMFingerprints'); const { detectFormalConnectors } = require('./NaturalConnectors'); logSh(`🧠 Adaptation configuration selon contenu...`, 'DEBUG'); const adaptations = { ...baseConfig }; try { // Analyser patterns LLM const llmDetection = detectLLMPatterns(content); const formalDetection = detectFormalConnectors(content); logSh(` 📊 Patterns LLM: ${llmDetection.count} (score: ${llmDetection.suspicionScore.toFixed(3)})`, 'DEBUG'); logSh(` 📊 Connecteurs formels: ${formalDetection.count} (score: ${formalDetection.suspicionScore.toFixed(3)})`, 'DEBUG'); // Adapter selon détection patterns LLM if (llmDetection.suspicionScore > 0.06) { adaptations.llmFingerprintReplacement = true; adaptations.intensityLevel = Math.min(1.0, baseConfig.intensityLevel + 0.2); logSh(` 🔧 Intensité augmentée pour patterns LLM élevés: ${adaptations.intensityLevel}`, 'DEBUG'); } else if (llmDetection.suspicionScore < 0.02) { adaptations.llmFingerprintReplacement = false; logSh(` 🔧 Remplacement LLM désactivé (faible détection)`, 'DEBUG'); } // Adapter selon connecteurs formels if (formalDetection.suspicionScore > 0.04) { adaptations.naturalConnectorsEnabled = true; adaptations.maxModificationsPerElement = Math.min(8, baseConfig.maxModificationsPerElement + 2); logSh(` 🔧 Focus connecteurs activé: max ${adaptations.maxModificationsPerElement} modifications`, 'DEBUG'); } // Adapter selon longueur texte const wordCount = content.split(/\s+/).length; if (wordCount > 500) { adaptations.maxModificationsPerElement = Math.min(10, baseConfig.maxModificationsPerElement + 3); logSh(` 🔧 Texte long détecté: max ${adaptations.maxModificationsPerElement} modifications`, 'DEBUG'); } } catch (error) { logSh(`⚠️ Erreur adaptation configuration: ${error.message}`, 'WARNING'); } return adaptations; } /** * DÉTECTION CONTEXTE PROFESSIONNEL * Détermine si le contenu nécessite un ton professionnel */ function detectProfessionalContext(content, context = {}) { if (!content) return false; // Indicateurs explicites dans le contexte if (context.professionalMode === true || context.tone === 'professional' || context.tone === 'commercial') { return true; } // Détection automatique via mots-clés techniques/commerciaux (liste étendue) const professionalKeywords = [ // Commerce B2B /\b(entreprise|société|solution|professionnel|commercial|clientèle|partenaire|établissement)\b/gi, // Technique industriel /\b(technique|technologie|système|processus|équipement|installation|dispositif|innovation)\b/gi, // Signalétique/production /\b(signalétique|panneau|enseigne|fabrication|production|conformité|norme|photoluminescent|luminescent)\b/gi, // Vocabulaire formel business /\b(optimiser|garantir|assurer|mettre en œuvre|respecter|propose|permettre|représent)\b/gi, // Réglementaire/qualité /\b(règlement|réglementaire|norme|exigence|sécurité|évacuation|procédure)\b/gi, // Connecteurs formels business /\b(par ailleurs|en effet|en outre|par conséquent|il convient|néanmoins|toutefois)\b/gi ]; let professionalScore = 0; const contentLower = content.toLowerCase(); professionalKeywords.forEach(pattern => { const matches = contentLower.match(pattern); if (matches) { professionalScore += matches.length; } }); const wordCount = content.split(/\s+/).length; const professionalDensity = wordCount > 0 ? professionalScore / wordCount : 0; // Seuil abaissé : >5% de mots professionnels = contexte professionnel const isProfessional = professionalDensity > 0.05; logSh(`🔍 Détection contexte: ${isProfessional ? 'PROFESSIONNEL' : 'CASUAL'} (score: ${professionalScore}, densité: ${(professionalDensity * 100).toFixed(1)}%)`, 'DEBUG'); return isProfessional; } /** * RECOMMANDATION STACK AUTOMATIQUE */ function recommendPatternBreakingStack(content, context = {}) { const { detectLLMPatterns } = require('./LLMFingerprints'); const { detectFormalConnectors } = require('./NaturalConnectors'); try { const llmDetection = detectLLMPatterns(content); const formalDetection = detectFormalConnectors(content); const wordCount = content.split(/\s+/).length; const isProfessional = detectProfessionalContext(content, context); logSh(`🤖 Recommandation Stack Pattern Breaking...`, 'DEBUG'); // Critères de recommandation const criteria = { llmPatternsHigh: llmDetection.suspicionScore > 0.05, formalConnectorsHigh: formalDetection.suspicionScore > 0.03, longContent: wordCount > 300, criticalContext: context.critical === true, preserveQuality: context.preserveQuality === true, professionalContext: isProfessional // ✅ NOUVEAU CRITÈRE }; // Logique de recommandation let recommendedStack = 'standardPatternBreaking'; let reason = 'Configuration équilibrée par défaut'; // ✅ PRIORITÉ ABSOLUE : Contexte professionnel if (criteria.professionalContext) { recommendedStack = 'professionalPatternBreaking'; reason = 'Contexte professionnel/commercial détecté'; } else if (criteria.criticalContext) { recommendedStack = 'heavyPatternBreaking'; reason = 'Contexte critique détecté'; } else if (criteria.llmPatternsHigh && criteria.formalConnectorsHigh) { recommendedStack = 'heavyPatternBreaking'; reason = 'Patterns LLM et connecteurs formels élevés'; } else if (criteria.llmPatternsHigh) { recommendedStack = 'adaptivePatternBreaking'; reason = 'Patterns LLM élevés détectés'; } else if (criteria.formalConnectorsHigh) { recommendedStack = 'connectorsFocus'; reason = 'Connecteurs formels prédominants'; } else if (criteria.preserveQuality) { recommendedStack = 'lightPatternBreaking'; reason = 'Préservation qualité prioritaire'; } else if (!criteria.llmPatternsHigh && !criteria.formalConnectorsHigh) { recommendedStack = 'syntaxFocus'; reason = 'Faible détection patterns, focus syntaxe'; } logSh(`🎯 Stack recommandé: ${recommendedStack} (${reason})`, 'DEBUG'); return { recommendedStack, reason, criteria, confidence: calculateRecommendationConfidence(criteria) }; } catch (error) { logSh(`⚠️ Erreur recommandation Stack: ${error.message}`, 'WARNING'); return { recommendedStack: 'standardPatternBreaking', reason: 'Fallback suite erreur analyse', criteria: {}, confidence: 0.5 }; } } /** * CALCUL CONFIANCE RECOMMANDATION */ function calculateRecommendationConfidence(criteria) { let confidence = 0.5; // Base // Augmenter confiance selon critères détectés if (criteria.llmPatternsHigh) confidence += 0.2; if (criteria.formalConnectorsHigh) confidence += 0.2; if (criteria.criticalContext) confidence += 0.3; if (criteria.longContent) confidence += 0.1; return Math.min(1.0, confidence); } /** * LISTE STACKS DISPONIBLES */ function listAvailableStacks() { return Object.entries(PATTERN_BREAKING_STACKS).map(([key, stack]) => ({ name: key, displayName: stack.name, description: stack.description, intensity: stack.intensity, expectedReduction: stack.expectedReduction, useCase: stack.useCase })); } /** * VALIDATION STACK */ function validateStack(stackName) { const stack = PATTERN_BREAKING_STACKS[stackName]; if (!stack) { return { valid: false, error: `Stack inconnu: ${stackName}` }; } // Vérifications configuration const config = stack.config; const checks = { hasIntensity: typeof stack.intensity === 'number', hasConfig: typeof config === 'object', hasValidThreshold: config.qualityThreshold >= 0 && config.qualityThreshold <= 1, hasValidMaxMods: config.maxModificationsPerElement > 0 }; const valid = Object.values(checks).every(Boolean); return { valid, checks, error: valid ? null : 'Configuration stack invalide' }; } // ============= EXPORTS ============= module.exports = { applyPatternBreakingStack, recommendPatternBreakingStack, detectProfessionalContext, // ✅ NOUVEAU: Export détection contexte adaptConfigurationToContent, listAvailableStacks, validateStack, PATTERN_BREAKING_STACKS };