## 🎯 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>
220 lines
6.6 KiB
JavaScript
220 lines
6.6 KiB
JavaScript
// ========================================
|
|
// FICHIER: ErrorGrave.js
|
|
// RESPONSABILITÉ: Erreurs GRAVES (10% articles max)
|
|
// Visibles mais crédibles - faute de frappe sérieuse ou distraction
|
|
// ========================================
|
|
|
|
const { logSh } = require('../../ErrorReporting');
|
|
|
|
/**
|
|
* DÉFINITIONS ERREURS GRAVES
|
|
* Probabilité globale: 10% des articles
|
|
* Maximum: 1 erreur grave par article
|
|
*/
|
|
const ERREURS_GRAVES = {
|
|
|
|
// ========================================
|
|
// ACCORD SUJET-VERBE INCORRECT
|
|
// ========================================
|
|
accord_sujet_verbe: {
|
|
name: 'Accord sujet-verbe incorrect',
|
|
probability: 0.3, // 30% si erreur grave sélectionnée
|
|
examples: [
|
|
{ pattern: /\bils (est|a)\b/gi, correction: 'ils sont/ont' },
|
|
{ pattern: /\bnous (est|a)\b/gi, correction: 'nous sommes/avons' },
|
|
{ pattern: /\belles (est|a)\b/gi, correction: 'elles sont/ont' }
|
|
],
|
|
apply: (content) => {
|
|
let modified = content;
|
|
let applied = false;
|
|
|
|
// Chercher "ils sont" ou "ils ont" et les remplacer
|
|
if (!applied && Math.random() < 0.5) {
|
|
const regex = /\bils sont\b/gi;
|
|
if (modified.match(regex)) {
|
|
modified = modified.replace(regex, 'ils est');
|
|
applied = true;
|
|
logSh(` ❌ Erreur grave: "ils sont" → "ils est"`, 'DEBUG');
|
|
}
|
|
}
|
|
|
|
if (!applied && Math.random() < 0.5) {
|
|
const regex = /\bils ont\b/gi;
|
|
if (modified.match(regex)) {
|
|
modified = modified.replace(regex, 'ils a');
|
|
applied = true;
|
|
logSh(` ❌ Erreur grave: "ils ont" → "ils a"`, 'DEBUG');
|
|
}
|
|
}
|
|
|
|
return { content: modified, applied };
|
|
}
|
|
},
|
|
|
|
// ========================================
|
|
// MOT MANQUANT (omission)
|
|
// ========================================
|
|
mot_manquant: {
|
|
name: 'Mot manquant (omission)',
|
|
probability: 0.25, // 25% si erreur grave
|
|
examples: [
|
|
{ pattern: 'pour garantir la qualité', error: 'pour garantir qualité' },
|
|
{ pattern: 'dans le but de', error: 'dans but de' },
|
|
{ pattern: 'il est important de', error: 'il important de' }
|
|
],
|
|
apply: (content) => {
|
|
let modified = content;
|
|
let applied = false;
|
|
|
|
// Supprimer article défini aléatoirement
|
|
const patterns = [
|
|
{ from: /\bpour garantir la qualité\b/gi, to: 'pour garantir qualité' },
|
|
{ from: /\bdans le but de\b/gi, to: 'dans but de' },
|
|
{ from: /\bil est important de\b/gi, to: 'il important de' },
|
|
{ from: /\bpour la durabilité\b/gi, to: 'pour durabilité' }
|
|
];
|
|
|
|
for (const pattern of patterns) {
|
|
if (applied) break;
|
|
if (modified.match(pattern.from) && Math.random() < 0.5) {
|
|
modified = modified.replace(pattern.from, pattern.to);
|
|
applied = true;
|
|
logSh(` ❌ Erreur grave: mot manquant`, 'DEBUG');
|
|
break;
|
|
}
|
|
}
|
|
|
|
return { content: modified, applied };
|
|
}
|
|
},
|
|
|
|
// ========================================
|
|
// DOUBLE MOT (copier-coller raté)
|
|
// ========================================
|
|
double_mot: {
|
|
name: 'Double mot (répétition)',
|
|
probability: 0.25, // 25% si erreur grave
|
|
examples: [
|
|
{ pattern: 'pour garantir', error: 'pour pour garantir' },
|
|
{ pattern: 'de la qualité', error: 'de de la qualité' }
|
|
],
|
|
apply: (content) => {
|
|
let modified = content;
|
|
let applied = false;
|
|
|
|
// Insérer doublon sur mots courants
|
|
const words = content.split(' ');
|
|
const targetWords = ['pour', 'de', 'la', 'le', 'et', 'dans'];
|
|
|
|
for (let i = 0; i < words.length && !applied; i++) {
|
|
const word = words[i].toLowerCase();
|
|
if (targetWords.includes(word) && Math.random() < 0.3) {
|
|
words.splice(i, 0, words[i]); // Dupliquer le mot
|
|
applied = true;
|
|
logSh(` ❌ Erreur grave: "${word}" dupliqué`, 'DEBUG');
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (applied) {
|
|
modified = words.join(' ');
|
|
}
|
|
|
|
return { content: modified, applied };
|
|
}
|
|
},
|
|
|
|
// ========================================
|
|
// NÉGATION OUBLIÉE
|
|
// ========================================
|
|
negation_oubliee: {
|
|
name: 'Négation oubliée',
|
|
probability: 0.20, // 20% si erreur grave
|
|
examples: [
|
|
{ pattern: "n'est pas nécessaire", error: "est pas nécessaire" },
|
|
{ pattern: "ne sont pas", error: "sont pas" }
|
|
],
|
|
apply: (content) => {
|
|
let modified = content;
|
|
let applied = false;
|
|
|
|
// Supprimer "ne" ou "n'" dans négations
|
|
const patterns = [
|
|
{ from: /\bn'est pas\b/gi, to: 'est pas' },
|
|
{ from: /\bne sont pas\b/gi, to: 'sont pas' },
|
|
{ from: /\bn'ont pas\b/gi, to: 'ont pas' }
|
|
];
|
|
|
|
for (const pattern of patterns) {
|
|
if (applied) break;
|
|
if (modified.match(pattern.from) && Math.random() < 0.5) {
|
|
modified = modified.replace(pattern.from, pattern.to);
|
|
applied = true;
|
|
logSh(` ❌ Erreur grave: négation oubliée`, 'DEBUG');
|
|
break;
|
|
}
|
|
}
|
|
|
|
return { content: modified, applied };
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* APPLIQUER UNE ERREUR GRAVE
|
|
* @param {string} content - Contenu à modifier
|
|
* @param {object} tracker - HumanSimulationTracker instance
|
|
* @returns {object} - { content, applied, errorType }
|
|
*/
|
|
function applyErrorGrave(content, tracker = null) {
|
|
// Vérifier avec tracker si erreur grave déjà appliquée
|
|
if (tracker && tracker.graveErrorApplied) {
|
|
logSh(`🚫 Erreur grave bloquée: déjà 1 erreur grave dans cet article`, 'DEBUG');
|
|
return { content, applied: false, errorType: null };
|
|
}
|
|
|
|
// Sélectionner type d'erreur aléatoirement selon probabilités
|
|
const errorTypes = Object.keys(ERREURS_GRAVES);
|
|
const selectedType = errorTypes[Math.floor(Math.random() * errorTypes.length)];
|
|
const errorDefinition = ERREURS_GRAVES[selectedType];
|
|
|
|
logSh(`🎲 Tentative erreur grave: ${errorDefinition.name}`, 'DEBUG');
|
|
|
|
// Appliquer l'erreur
|
|
const result = errorDefinition.apply(content);
|
|
|
|
if (result.applied) {
|
|
logSh(`✅ Erreur grave appliquée: ${errorDefinition.name}`, 'DEBUG');
|
|
|
|
// Marquer dans tracker
|
|
if (tracker) {
|
|
tracker.graveErrorApplied = true;
|
|
}
|
|
}
|
|
|
|
return {
|
|
content: result.content,
|
|
applied: result.applied,
|
|
errorType: result.applied ? selectedType : null
|
|
};
|
|
}
|
|
|
|
/**
|
|
* OBTENIR STATISTIQUES ERREURS GRAVES
|
|
*/
|
|
function getErrorGraveStats() {
|
|
return {
|
|
totalTypes: Object.keys(ERREURS_GRAVES).length,
|
|
types: Object.keys(ERREURS_GRAVES),
|
|
globalProbability: '10%',
|
|
maxPerArticle: 1
|
|
};
|
|
}
|
|
|
|
// ============= EXPORTS =============
|
|
module.exports = {
|
|
ERREURS_GRAVES,
|
|
applyErrorGrave,
|
|
getErrorGraveStats
|
|
};
|