seo-generator-server/lib/human-simulation/HumanSimulationLayers.js
StillHammer 9a2ef7da2b feat(human-simulation): Système d'erreurs graduées procédurales + anti-répétition complet
## 🎯 Nouveau système d'erreurs graduées (architecture SmartTouch)

### Architecture procédurale intelligente :
- **3 niveaux de gravité** : Légère (50%) → Moyenne (30%) → Grave (10%)
- **14 types d'erreurs** réalistes et subtiles
- **Sélection procédurale** selon contexte (longueur, technique, heure)
- **Distribution contrôlée** : max 1 grave, 2 moyennes, 3 légères par article

### 1. Erreurs GRAVES (10% articles max) :
- Accord sujet-verbe : "ils sont" → "ils est"
- Mot manquant : "pour garantir la qualité" → "pour garantir qualité"
- Double mot : "pour garantir" → "pour pour garantir"
- Négation oubliée : "n'est pas" → "est pas"

### 2. Erreurs MOYENNES (30% articles) :
- Accord pluriel : "plaques résistantes" → "plaques résistant"
- Virgule manquante : "Ainsi, il" → "Ainsi il"
- Registre inapproprié : "Par conséquent" → "Du coup"
- Préposition incorrecte : "résistant aux" → "résistant des"
- Connecteur illogique : "cependant" → "donc"

### 3. Erreurs LÉGÈRES (50% articles) :
- Double espace : "de votre" → "de  votre"
- Trait d'union : "c'est-à-dire" → "c'est à dire"
- Espace ponctuation : "qualité ?" → "qualité?"
- Majuscule : "Toutenplaque" → "toutenplaque"
- Apostrophe droite : "l'article" → "l'article"

##  Système anti-répétition complet :

### Corrections critiques :
- **HumanSimulationTracker.js** : Tracker centralisé global
- **Word boundaries (\b)** sur TOUS les regex → FIX "maison" → "néanmoinson"
- **Protection 30+ expressions idiomatiques** françaises
- **Anti-répétition** : max 2× même mot, jamais 2× même développement
- **Diversification** : 48 variantes (hésitations, développements, connecteurs)

### Nouvelle structure (comme SmartTouch) :
```
lib/human-simulation/
├── error-profiles/                (NOUVEAU)
│   ├── ErrorProfiles.js          (définitions + probabilités)
│   ├── ErrorGrave.js             (10% articles)
│   ├── ErrorMoyenne.js           (30% articles)
│   ├── ErrorLegere.js            (50% articles)
│   └── ErrorSelector.js          (sélection procédurale)
├── HumanSimulationCore.js         (orchestrateur)
├── HumanSimulationTracker.js      (anti-répétition)
└── [autres modules]
```

## 🔄 Remplace ancien système :
-  SpellingErrors.js (basique, répétitif, "et" → "." × 8)
-  error-profiles/ (gradué, procédural, intelligent, diversifié)

## 🎲 Fonctionnalités procédurales :
- Analyse contexte : longueur texte, complexité technique, heure rédaction
- Multiplicateurs adaptatifs selon contexte
- Conditions application intelligentes
- Tracking global par batch (respecte limites 10%/30%/50%)

## 📊 Résultats validation :
Sur 100 articles → ~40-50 avec erreurs subtiles et diverses (plus de spam répétitif)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-14 01:06:28 +08:00

456 lines
16 KiB
JavaScript

// ========================================
// FICHIER: HumanSimulationLayers.js
// RESPONSABILITÉ: Stacks prédéfinis Human Simulation
// Compatible avec architecture modulaire existante
// ========================================
const { logSh } = require('../ErrorReporting');
const { tracer } = require('../trace');
const { applyHumanSimulationLayer } = require('./HumanSimulationCore');
/**
* STACKS PRÉDÉFINIS HUMAN SIMULATION
* Configuration par niveau d'intensité
*/
const HUMAN_SIMULATION_STACKS = {
// ========================================
// SIMULATION LÉGÈRE - Pour tests et développement
// ========================================
lightSimulation: {
name: 'lightSimulation',
description: 'Simulation humaine légère - développement et tests',
layersCount: 3,
config: {
fatigueEnabled: true,
personalityErrorsEnabled: true,
temporalStyleEnabled: false, // Désactivé en mode light
graduatedErrorsEnabled: true, // ✅ Erreurs graduées procédurales
imperfectionIntensity: 0.3,
naturalRepetitions: true,
qualityThreshold: 0, // ✅ VALIDATION DÉSACTIVÉE
maxModificationsPerElement: 2
},
expectedImpact: {
modificationsPerElement: '1-2',
qualityPreservation: '95%',
detectionReduction: '10-15%',
executionTime: '+20%'
}
},
// ========================================
// SIMULATION STANDARD - Usage production normal
// ========================================
standardSimulation: {
name: 'standardSimulation',
description: 'Simulation humaine standard - équilibre performance/qualité',
layersCount: 3,
config: {
fatigueEnabled: true,
personalityErrorsEnabled: true,
temporalStyleEnabled: true,
graduatedErrorsEnabled: true, // ✅ Erreurs graduées procédurales
imperfectionIntensity: 0.5,
naturalRepetitions: true,
qualityThreshold: 0, // ✅ VALIDATION DÉSACTIVÉE
maxModificationsPerElement: 3
},
expectedImpact: {
modificationsPerElement: '2-3',
qualityPreservation: '85%',
detectionReduction: '25-35%',
executionTime: '+40%'
}
},
// ========================================
// SIMULATION INTENSIVE - Maximum anti-détection
// ========================================
heavySimulation: {
name: 'heavySimulation',
description: 'Simulation humaine intensive - anti-détection maximale',
layersCount: 3,
config: {
fatigueEnabled: true,
personalityErrorsEnabled: true,
temporalStyleEnabled: true,
spellingErrorsEnabled: true, // ✅ NOUVEAU
imperfectionIntensity: 0.7,
naturalRepetitions: true,
qualityThreshold: 0, // ✅ VALIDATION DÉSACTIVÉE
maxModificationsPerElement: 4
},
expectedImpact: {
modificationsPerElement: '3-5',
qualityPreservation: '75%',
detectionReduction: '40-50%',
executionTime: '+60%'
}
},
// ========================================
// SIMULATION ADAPTIVE - Intelligence contextuelle
// ========================================
adaptiveSimulation: {
name: 'adaptiveSimulation',
description: 'Simulation humaine adaptive - ajustement intelligent selon contexte',
layersCount: 3,
config: {
fatigueEnabled: true,
personalityErrorsEnabled: true,
temporalStyleEnabled: true,
imperfectionIntensity: 'adaptive', // Calculé dynamiquement
naturalRepetitions: true,
qualityThreshold: 'adaptive', // Ajusté selon complexité
maxModificationsPerElement: 'adaptive', // Variable
adaptiveLogic: true // Flag pour logique adaptive
},
expectedImpact: {
modificationsPerElement: '1-4',
qualityPreservation: '80-90%',
detectionReduction: '30-45%',
executionTime: '+45%'
}
},
// ========================================
// SIMULATION PERSONNALISÉE - Focus personnalité
// ========================================
personalityFocus: {
name: 'personalityFocus',
description: 'Focus erreurs personnalité - cohérence maximale',
layersCount: 2,
config: {
fatigueEnabled: false, // Désactivé
personalityErrorsEnabled: true,
temporalStyleEnabled: false, // Désactivé
imperfectionIntensity: 1.0, // Focus sur personnalité
naturalRepetitions: true,
qualityThreshold: 0.75,
maxModificationsPerElement: 3
},
expectedImpact: {
modificationsPerElement: '2-3',
qualityPreservation: '85%',
detectionReduction: '20-30%',
executionTime: '+25%'
}
},
// ========================================
// SIMULATION TEMPORELLE - Focus variations horaires
// ========================================
temporalFocus: {
name: 'temporalFocus',
description: 'Focus style temporel - variations selon heure',
layersCount: 2,
config: {
fatigueEnabled: false,
personalityErrorsEnabled: false,
temporalStyleEnabled: true, // Focus principal
imperfectionIntensity: 0.8,
naturalRepetitions: true,
qualityThreshold: 0.75,
maxModificationsPerElement: 3
},
expectedImpact: {
modificationsPerElement: '1-3',
qualityPreservation: '85%',
detectionReduction: '15-25%',
executionTime: '+20%'
}
}
};
/**
* APPLICATION STACK PRÉDÉFINI
* @param {object} content - Contenu à simuler
* @param {string} stackName - Nom du stack
* @param {object} options - Options additionnelles
* @returns {object} - Résultat simulation
*/
async function applyPredefinedSimulation(content, stackName, options = {}) {
return await tracer.run(`HumanSimulationLayers.applyPredefinedSimulation(${stackName})`, async () => {
const stack = HUMAN_SIMULATION_STACKS[stackName];
if (!stack) {
throw new Error(`Stack Human Simulation non trouvé: ${stackName}`);
}
await tracer.annotate({
stackName,
stackDescription: stack.description,
layersCount: stack.layersCount,
contentElements: Object.keys(content).length
});
logSh(`🧠 APPLICATION STACK: ${stack.name}`, 'INFO');
logSh(` 📝 ${stack.description}`, 'DEBUG');
logSh(` ⚙️ ${stack.layersCount} couches actives`, 'DEBUG');
try {
// Configuration fusionnée
let finalConfig = { ...stack.config, ...options };
// ========================================
// LOGIQUE ADAPTIVE (si applicable)
// ========================================
if (stack.config.adaptiveLogic) {
finalConfig = await applyAdaptiveLogic(content, finalConfig, options);
logSh(` 🧠 Logique adaptive appliquée`, 'DEBUG');
}
// ========================================
// APPLICATION SIMULATION PRINCIPALE
// ========================================
const simulationOptions = {
...finalConfig,
elementIndex: options.elementIndex || 0,
totalElements: options.totalElements || Object.keys(content).length,
currentHour: options.currentHour || new Date().getHours(),
csvData: options.csvData,
stackName: stack.name
};
const result = await applyHumanSimulationLayer(content, simulationOptions);
// ========================================
// ENRICHISSEMENT RÉSULTAT
// ========================================
const enrichedResult = {
...result,
stackInfo: {
name: stack.name,
description: stack.description,
layersCount: stack.layersCount,
expectedImpact: stack.expectedImpact,
configUsed: finalConfig
}
};
logSh(`✅ STACK ${stack.name} terminé: ${result.stats.totalModifications} modifications`, 'INFO');
await tracer.event('Stack Human Simulation terminé', {
stackName,
success: !result.fallback,
modifications: result.stats.totalModifications,
qualityScore: result.qualityScore
});
return enrichedResult;
} catch (error) {
logSh(`❌ ERREUR STACK ${stack.name}: ${error.message}`, 'ERROR');
await tracer.event('Stack Human Simulation échoué', {
stackName,
error: error.message
});
// Fallback gracieux
return {
content,
stats: { fallbackUsed: true, error: error.message },
modifications: 0, // ✅ AJOUTÉ: Mapping pour PipelineExecutor (fallback = 0 modifs)
fallback: true,
stackInfo: { name: stack.name, error: error.message }
};
}
}, { stackName, contentElements: Object.keys(content).length });
}
/**
* LOGIQUE ADAPTIVE INTELLIGENTE
* Ajuste la configuration selon le contexte
*/
async function applyAdaptiveLogic(content, config, options) {
logSh('🧠 Application logique adaptive', 'DEBUG');
const adaptedConfig = { ...config };
// ========================================
// 1. ANALYSE COMPLEXITÉ CONTENU
// ========================================
const totalText = Object.values(content).join(' ');
const wordCount = totalText.split(/\s+/).length;
const avgElementLength = wordCount / Object.keys(content).length;
// ========================================
// 2. AJUSTEMENT INTENSITÉ SELON COMPLEXITÉ
// ========================================
if (avgElementLength > 200) {
// Contenu long = intensité réduite pour préserver qualité
adaptedConfig.imperfectionIntensity = 0.5;
adaptedConfig.qualityThreshold = 0.8;
logSh(' 📏 Contenu long détecté: intensité réduite', 'DEBUG');
} else if (avgElementLength < 50) {
// Contenu court = intensité augmentée
adaptedConfig.imperfectionIntensity = 1.0;
adaptedConfig.qualityThreshold = 0.6;
logSh(' 📏 Contenu court détecté: intensité augmentée', 'DEBUG');
} else {
// Contenu moyen = intensité équilibrée
adaptedConfig.imperfectionIntensity = 0.7;
adaptedConfig.qualityThreshold = 0.7;
}
// ========================================
// 3. AJUSTEMENT SELON PERSONNALITÉ
// ========================================
const personality = options.csvData?.personality;
if (personality) {
const personalityName = personality.nom.toLowerCase();
// Personnalités techniques = moins d'erreurs de personnalité
if (['marc', 'amara', 'fabrice'].includes(personalityName)) {
adaptedConfig.imperfectionIntensity *= 0.8;
logSh(' 🎭 Personnalité technique: intensité erreurs réduite', 'DEBUG');
}
// Personnalités créatives = plus d'erreurs stylistiques
if (['sophie', 'émilie', 'chloé'].includes(personalityName)) {
adaptedConfig.imperfectionIntensity *= 1.2;
logSh(' 🎭 Personnalité créative: intensité erreurs augmentée', 'DEBUG');
}
}
// ========================================
// 4. AJUSTEMENT SELON HEURE
// ========================================
const currentHour = options.currentHour || new Date().getHours();
if (currentHour >= 22 || currentHour <= 6) {
// Nuit = plus de fatigue, moins de complexité
adaptedConfig.fatigueEnabled = true;
adaptedConfig.temporalStyleEnabled = true;
adaptedConfig.imperfectionIntensity *= 1.3;
logSh(' 🌙 Période nocturne: simulation fatigue renforcée', 'DEBUG');
} else if (currentHour >= 6 && currentHour <= 10) {
// Matin = énergie, moins d'erreurs
adaptedConfig.imperfectionIntensity *= 0.7;
logSh(' 🌅 Période matinale: intensité réduite', 'DEBUG');
}
// ========================================
// 5. LIMITATION SÉCURITÉ
// ========================================
adaptedConfig.imperfectionIntensity = Math.max(0.2, Math.min(1.5, adaptedConfig.imperfectionIntensity));
adaptedConfig.qualityThreshold = Math.max(0.5, Math.min(0.9, adaptedConfig.qualityThreshold));
// Modifs max adaptées à la taille du contenu
adaptedConfig.maxModificationsPerElement = Math.min(6, Math.max(1, Math.ceil(avgElementLength / 50)));
logSh(` 🎯 Config adaptée: intensité=${adaptedConfig.imperfectionIntensity.toFixed(2)}, seuil=${adaptedConfig.qualityThreshold.toFixed(2)}`, 'DEBUG');
return adaptedConfig;
}
/**
* OBTENIR STACKS DISPONIBLES
* @returns {array} - Liste des stacks avec métadonnées
*/
function getAvailableSimulationStacks() {
return Object.values(HUMAN_SIMULATION_STACKS).map(stack => ({
name: stack.name,
description: stack.description,
layersCount: stack.layersCount,
expectedImpact: stack.expectedImpact,
configPreview: {
fatigueEnabled: stack.config.fatigueEnabled,
personalityErrorsEnabled: stack.config.personalityErrorsEnabled,
temporalStyleEnabled: stack.config.temporalStyleEnabled,
intensity: stack.config.imperfectionIntensity
}
}));
}
/**
* VALIDATION STACK
* @param {string} stackName - Nom du stack à valider
* @returns {object} - Résultat validation
*/
function validateSimulationStack(stackName) {
const stack = HUMAN_SIMULATION_STACKS[stackName];
if (!stack) {
return {
valid: false,
error: `Stack '${stackName}' non trouvé`,
availableStacks: Object.keys(HUMAN_SIMULATION_STACKS)
};
}
// Validation configuration
const configIssues = [];
if (typeof stack.config.imperfectionIntensity === 'number' &&
(stack.config.imperfectionIntensity < 0 || stack.config.imperfectionIntensity > 2)) {
configIssues.push('intensité hors limites (0-2)');
}
if (typeof stack.config.qualityThreshold === 'number' &&
(stack.config.qualityThreshold < 0.3 || stack.config.qualityThreshold > 1)) {
configIssues.push('seuil qualité hors limites (0.3-1)');
}
return {
valid: configIssues.length === 0,
stack,
issues: configIssues,
recommendation: configIssues.length > 0 ?
'Corriger la configuration avant utilisation' :
'Stack prêt à utiliser'
};
}
/**
* RECOMMANDATION STACK AUTOMATIQUE
* @param {object} context - Contexte { contentLength, personality, hour, goal }
* @returns {string} - Nom du stack recommandé
*/
function recommendSimulationStack(context = {}) {
const { contentLength, personality, hour, goal } = context;
logSh('🤖 Recommandation stack automatique', 'DEBUG');
// Priorité 1: Objectif spécifique
if (goal === 'development') return 'lightSimulation';
if (goal === 'maximum_stealth') return 'heavySimulation';
if (goal === 'personality_focus') return 'personalityFocus';
if (goal === 'temporal_focus') return 'temporalFocus';
// Priorité 2: Complexité contenu
if (contentLength > 2000) return 'lightSimulation'; // Contenu long = prudent
if (contentLength < 300) return 'heavySimulation'; // Contenu court = intensif
// Priorité 3: Personnalité
if (personality) {
const personalityName = personality.toLowerCase();
if (['marc', 'amara', 'fabrice'].includes(personalityName)) {
return 'standardSimulation'; // Techniques = équilibré
}
if (['sophie', 'chloé', 'émilie'].includes(personalityName)) {
return 'personalityFocus'; // Créatives = focus personnalité
}
}
// Priorité 4: Heure
if (hour >= 22 || hour <= 6) return 'temporalFocus'; // Nuit = focus temporel
if (hour >= 6 && hour <= 10) return 'lightSimulation'; // Matin = léger
// Par défaut: adaptive pour intelligence contextuelle
logSh(' 🎯 Recommandation: adaptiveSimulation (par défaut)', 'DEBUG');
return 'adaptiveSimulation';
}
// ============= EXPORTS =============
module.exports = {
applyPredefinedSimulation,
getAvailableSimulationStacks,
validateSimulationStack,
recommendSimulationStack,
applyAdaptiveLogic,
HUMAN_SIMULATION_STACKS
};