{
  "summary": "Brancher les composants ORIGINAUX sur les données WP (parité pixel) + audit code adversarial",
  "agentCount": 15,
  "logs": [
    "Paramétrage : 6/6 familles livrées",
    "Audit : 3 bloquants, 17 mineurs"
  ],
  "result": {
    "familles": 6,
    "fichiers": 107,
    "bloquantsCorriges": 3,
    "mineurs": [
      "/opt/projects/.covalba-wp-worktrees/tom-passage-wp/src/components/origine/home.tsx: HeroAdapter passe hero.lead en chaîne brute (lead={section.lead ?? undefined}) alors que le lead original contient 3 <strong className=\"text-white font-semibold\"> ; le seed page--accueil.json fournit un lead en texte brut, donc dès que WP sert la donnée, la mise en gras blanche du hero disparaît (white/70 regular au lieu de semibold blanc). Écart visuel garanti au pixel-diff sur la section la plus visible, non signalé dans le rapport. À corriger via seed avec <strong> + parsing type withStrongClass dans l'adaptateur.",
      "/opt/projects/.covalba-wp-worktrees/tom-passage-wp/src/components/origine/home.tsx: FAQAdapter ignore le champ json_ld (true dans le seed) : le block générique actuel (src/components/blocks/Faq.tsx) injecte un schema.org FAQPage présent 2x dans le HTML servi ; la bascule vers l'adaptateur supprimera ce JSON-LD (régression SEO vs rendu WP actuel). Signalé dans le rapport comme limitation, mais l'adaptateur pourrait injecter le <script> JSON-LD lui-même sans toucher au composant original.",
      "/opt/projects/.covalba-wp-worktrees/tom-passage-wp/src/components/origine/home.tsx: SEOContentAdapter rend le contenu wysiwyg avec un <table> stylé desktop sur tous les viewports ; l'original (SEOContent.tsx HEAD, lignes ~155-204) a un tableau desktop ET une variante mobile en cards qui disparaît au rendu WP. Écart de parité mobile réel (signalé dans le rapport).",
      "/opt/projects/.covalba-wp-worktrees/tom-passage-wp/src/components/origine/home.tsx: La preuve avancée par le rapport (« Page / rendu WP : 200, sections présentes ») n'exerce aucun des 19 adaptateurs : le HTML servi sur :3083 ne contient aucun marqueur propre aux composants originaux (animate-hero-2, en-tête « Tout comprendre sur le cool roof », grid-cols-[1fr_100px_100px_100px_100px], pins 56.7% absents) car le champ origine n'est pas encore seedé en base WP (tâche #9 pendante) — BlockRenderer retombe sur les blocks génériques. Les adaptateurs ne sont validés que statiquement (tsc) ; leur exécution runtime reste à prouver lors du re-seed.",
      "/opt/projects/.covalba-wp-worktrees/tom-passage-wp/src/components/product/ProductShowcase.tsx: useState(1) remplacé par useState(variants.length > 1 ? 1 : 0) : c'est une expression dépendante de la prop, pas un strict littéral→variable-avec-défaut. Comportement identique avec defaultVariants (2 variantes → index 1) et avec le seed (2 variantes), divergence uniquement dans le cas hypothétique d'une seule variante WP (où useState(1) crasherait). Divulgué dans le rapport.",
      "/opt/projects/.covalba-wp-worktrees/tom-passage-wp/src/components/origine/produits.tsx: Adaptateurs ProductHero : tagline et accentColor sont durcis dans l'adaptateur alors que le seed WP expose fiche_produit.tagline et fiche_produit.accent_color au niveau page (vérifié dans produit--covatherm.json). Le rapport dit qu'ils 'n'existent pas dans le bloc hero' (vrai au niveau section), mais une édition BO de fiche_produit.tagline/accent_color ne se répercutera pas sur le hero. Valeurs durcies vérifiées identiques aux 4 vues d'origine.",
      "/opt/projects/.covalba-wp-worktrees/tom-passage-wp/src/components/origine/produits.tsx: makeFaq : le fallback (questions WP absentes) mappe productFaqs en texte brut, alors que les 4 vues d'origine rendaient des réponses riches avec liens (faqNodes dans CovaTherm.tsx etc.) pour certaines questions. En l'état seedé le chemin n'est pas emprunté (15/9/9/10 questions présentes, réponses HTML avec liens conformes), mais le fallback ne reproduit pas exactement le rendu des vues d'origine.",
      "/opt/projects/.covalba-wp-worktrees/tom-passage-wp/wordpress/seed/content/produit--covatherm.json: Aucun des 4 seeds produit ne porte encore le champ 'origine' sur ses sections (0 occurrence dans les 4 fichiers) : le registry origineProduits (39 clés, toutes vérifiées) n'est donc pas encore exercé de bout en bout et la parité pixel reste non démontrée en runtime. Cohérent avec la tâche #9 pendante ('seeds origine + re-seed'), hors périmètre du rapport audité — signalé pour traçabilité.",
      "/opt/projects/.covalba-wp-worktrees/tom-passage-wp/src/components/origine/industrie.tsx: DistributionCEEAdapter : retenirNote = lines[1] avec préfixe 'À retenir :' retiré donne « la prime n'est pas automatique… » (minuscule, cf. seed industrie--distribution.json texte_apres), alors que le littéral original du composant est « La prime n'est pas automatique… » (majuscule). Dès que la donnée WP alimente la section, le rendu diffère d'un caractère du site pré-CMS (parité pixel cassée sur le chemin données). L'adaptateur devrait re-capitaliser ou le seed être corrigé.",
      "/opt/projects/.covalba-wp-worktrees/tom-passage-wp/src/components/origine/industrie.tsx: LogistiqueSEOContentAdapter / DistributionSEOContentAdapter : le corps des sections SEO est injecté tel quel via dangerouslySetInnerHTML (htmlNode), or le HTML des seeds contient des <strong> et <a> NUS, sans les classes des originaux (<strong className=\"text-foreground\">, <a className=\"font-semibold text-primary underline underline-offset-4\">). Sur le chemin données WP, les strong perdront leur couleur foncée et les liens internes leur style primary/souligné par rapport au site pré-CMS ; un <span> wrapper supplémentaire est aussi introduit dans le <p>. Défauts des composants intacts (rendu sans WP identique), mais la boucle de diff pixel de la phase 3 le détectera.",
      "/opt/projects/.covalba-wp-worktrees/tom-passage-wp/wordpress/seed/content/page--estimation.json: Hors fichiers de l'agent mais impacte la famille auditée : plusieurs textes des seeds utilisent l'apostrophe typographique ’ là où les littéraux d'origine des vues utilisent l'apostrophe droite ' (page--estimation lead « d’investissement » vs « d'investissement », page--contact lead « L’équipe » et quickText « l’objectif/d’énergie », page--diagnostic item « 15 ans d’expertise »). Composant sans props = rendu inchangé (vérifié exact), mais dès que les props WP remplacent les défauts, le texte rendu différera glyphe à glyphe de l'original — la boucle de diff pixel (tâche #9) le détectera. À harmoniser côté seed.",
      "/opt/projects/.covalba-wp-worktrees/tom-passage-wp/src/lib/wp/viewProps/shared.ts: stripHtml supprime les balises sans insérer d'espace (html.replace(/<[^>]+>/g, \"\")) : deux blocs adjacents « </p><p> » seraient collés mot-à-mot. Latent uniquement — vérifié que tous les champs HTML des seeds concernés (18 réponses FAQ, leads, textes de cards) sont mono-paragraphe, donc aucun cas réel aujourd'hui ; risque si un éditeur saisit du multi-paragraphe dans le BO.",
      "/opt/projects/.covalba-wp-worktrees/tom-passage-wp/src/views/Contact.tsx: HubSpotContactForm : formId est désormais lu à l'intérieur du useEffect dont le tableau de dépendances reste [] (ligne 197). Un changement de hubspotFormId après montage ne recréerait pas le formulaire (closure figée sur la première valeur). Sans effet dans l'usage actuel (props statiques rendues une fois), et conserver [] préserve le comportement d'origine — simple dette latente.",
      "/opt/projects/.covalba-wp-worktrees/tom-passage-wp/src/lib/wp/viewProps/primeCEECoolRoof.ts: La claim du rapport « les 3 parsers fragiles testés contre le seed réel : reproduisent exactement les défauts » est inexacte pour splitSud : sudTexte parsé depuis page--bat-en-112.json donne « C’est l’inverse… c’est en zone H3… » (apostrophes typographiques U+2019 du seed) alors que le défaut de la vue est « C'est l'inverse… » (apostrophes droites, identiques à HEAD). Le mapper cible le bon champ et le défaut respecte le littéral d'origine ; l'écart vient du seed (apostrophes normalisées en ’ dans tout wordpress/seed/content/), donc le rendu WP-fed différera typographiquement de l'original sur de nombreux textes au moment de la boucle de diff pixel (tâche seeds encore pending). À traiter côté seeds, pas côté mapper.",
      "/opt/projects/.covalba-wp-worktrees/tom-passage-wp/src/views/DevenirApplicateur.tsx: renderAccentTitre : le commentaire affirme « espace précédente absorbée dans le span (comme dans le JSX d'origine) », or dans l'original l'espace est HORS du span ({' '} avant <span className=\"text-teal-vivid\">). Quand partTitre est fourni par WP, l'espace se retrouve à l'intérieur du span — DOM légèrement différent mais rendu visuel identique (un espace n'a pas de couleur visible). Le chemin par défaut (partTitre undefined) rend le markup original verbatim, donc aucune régression hors WP.",
      "/opt/projects/.covalba-wp-worktrees/tom-passage-wp/app/toitures/[slug]/page.tsx: Wrapper résiduel <div className=\"min-h-screen bg-background\"> autour de RoofPageTemplate, hérité de la route BlockRenderer : la route d'origine rendait la vue sans ce nœud DOM supplémentaire (impact visuel probablement nul, mais écart structurel vs origine).",
      "/opt/projects/.covalba-wp-worktrees/tom-passage-wp/src/lib/wp/toRoofPageData.ts: Fallback midCta = ctas.find(variante==='mid') ?? ctas[0] : si l'éditeur WP supprime le CTA mid en gardant le final, le contenu du CTA final s'affiche en position mid au lieu de retomber sur fb.midCta — contredit le contrat annoncé « champ WP absent → valeur codée » sur ce cas limite. Tout le reste du mapper (ordre des sections, split intro/afterComparison, displayCell idempotent, unescapeHtml, SITUATION_HEADERS au caractère près) est vérifié conforme aux 5 seeds et à export-data.mts ; npx tsc --noEmit passe (exit 0) ; ReferenceDetail.tsx est strictement signature-only et RoofPageTemplate.tsx est sans diff."
    ],
    "limites": [
      "Sections du seed SANS adaptateur dans la home : 'composant_react estimation' (le formulaire vit DANS le Hero original, codé en dur — le titre WP 'Estimez votre budget' de cette section n'est pas mappé) et la section 'logos' clients (le marquee logos vit dans le Hero, liste codée en dur ; TrustLogos.tsx n'est pas rendu par Index.tsx donc non paramétré, conformément à la consigne 'si rendu'). Le seed devra pointer ces deux sections vers aucune origine ou les masquer pour éviter un doublon via le block générique Logos/ComposantReact.",
      "Hero.lead : l'original met 3 <strong> dans le paragraphe ; le seed fournit un lead en texte brut — si le WP renseigne lead, les graisses disparaissent (le défaut sans props reste identique). Même logique partout : la parité pixel parfaite n'est garantie que quand la donnée WP est absente OU identique au texte d'origine.",
      "SEOContent : le corps WP est du wysiwyg sans classes Tailwind ; l'adaptateur réinjecte un styling approchant via sélecteurs [&_strong]/[&_ul]/[&_ol]/[&_table], mais le tableau comparatif mobile de l'original (cards empilées) n'est pas reproduit (le <table> HTML s'affiche aussi en mobile) et les coins arrondis du thead ne sont pas répliqués — à vérifier dans la boucle de diff pixel (tâche #9).",
      "Heuristiques d'adaptation dépendantes du FORMAT du seed : split ' — ' des entêtes de colonnes (PriceComparison/PriceVS), split de la 1re phrase de texte_apres pour l'encart PriceComparison, citation « … » — auteur dans les textes d'étapes SystemSection, lignes '-' = puces dans PriceVS. Si un éditeur WP change ces formats, le mapping dégrade proprement vers les défauts ou un rendu partiel.",
      "ExpertiseSection/RSESection/SystemSection/ProcessSection : icônes, couleurs, flags featured et numéros mappés PAR INDEX sur le skeleton original (le champ WP cards[].icone est ignoré) ; ajouter/réordonner des items côté WP au-delà de l'original ne crée pas de nouvelles cartes (Expertise/RSE/System plafonnés au nombre d'items du skeleton).",
      "PriceComparisonSection mobile : les abréviations de colonnes ('Clim', 'Membrane', 'Réfection') restent codées en dur — un renommage de colonne côté WP ne s'applique qu'au tableau desktop.",
      "Les adaptateurs ne sont pas encore exercés en conditions réelles : les sections seedées ne portent pas encore le champ `origine` (tâche #9 - seeds origine + re-seed + diff pixel). Le smoke test (page / en 200 avec les contenus) valide l'absence de régression mais pas le chemin adaptateur de bout en bout.",
      "git status du worktree contient des modifications d'autres agents (fragments wp, BlockRenderer, types.ts…) — je n'ai touché que les 20 fichiers listés (19 composants + origine/home.tsx).",
      "Les sections cta (CTASection) et texte_image 'Réseau d'applicateurs' (ApplicatorsSection) des seeds produit pointent vers des composants partagés hors src/components/product/** : adaptateurs à fournir par la famille qui possède ces composants (clé suggérée : 'CTASection', 'ApplicatorsSection').",
      "Les seeds ne portent pas encore de champ 'origine' : l'agent de la tâche #9 doit y inscrire les clés du registry listées dans le résumé (suffixe produit pour les génériques : ProductHeroCovaTherm, CompatibilityTabsCovaSeal, ProductFAQCovaMetal, RelatedProductsCovaThermLight, etc.).",
      "Champs riches (intros avec <strong>, textes de pied avec liens, contenu des showcases, corps des éditoriaux/guide) : parité pixel garantie tant que le contenu WP est identique au seed (comparaison normalisée / hash djb2 calculés sur les seeds) ; dès qu'un texte est édité dans le BO, le rendu bascule sur du texte plat ou du HTML stylé approchant (puces custom et cercles numérotés du CoolRoofGuide non reproduits à l'identique).",
      "Si WPGraphQL/ACF réécrit le HTML des wysiwyg (wpautop, entités, guillemets), les hashes des contenu_seo ne matcheront plus le seed et les éditoriaux passeront en branche HTML générique même sans édition — à vérifier lors de la boucle de diff pixel (tâche #9) et recalculer les constantes le cas échéant (564420437 / 2142459583 / 1375046801 / 2432885520 dans produits.tsx).",
      "Le tagline et l'accentColor du hero, les pills 'Recommandé'/'2-en-1'/'3-en-1'/'Laque solaire', le callout vitrage de CompatibilityTabs, le lien 'Devis gratuit' des notes de showcase et le H2 'en clair.' des éditoriaux n'ont pas de champ WP : ils restent pilotés par les défauts (non éditables côté BO).",
      "Le flag 'incompatible' (Vitrage, CovaTherm Light) n'existe pas dans le schéma compatibilite_supports : reconstruit par heuristique type === 'Vitrage' dans l'adaptateur.",
      "RelatedProducts : les cards (tag, accroche, visuel) ne sont pas dans fiche_produit ; l'adaptateur ne fait que sélectionner/ordonner le catalogue d'origine via les slugs WP.",
      "Réponses FAQ riches : rendues via dangerouslySetInnerHTML avec liens stylés [&_a] — très proche mais non strictement identique aux ReactNodes des vues (qui restent utilisés par les routes fallback).",
      "ProductShowcase : l'état initial du toggle passe à l'index 0 si une seule variante est fournie par WP (identique à l'original avec les 2 variantes par défaut).",
      "Composants 1-pour-N rows WP : IndustrieProof, LogistiqueBenefits, DistributionBenefits et DistributionProof couvrent chacun 2-3 rows du flexible (chiffres + grille_cards + references_grille/logos). L'adaptateur Benefits détecte chiffres vs cards, mais il ne faut poser `origine` que sur UNE seule row par composant sinon double rendu ; les rows references_grille et logos des blocs Proof ne sont pas adaptées (logos/références = défauts codés, props exposées pour un branchement futur).",
      "IndustrieProof rendu via adaptateur utilise sector='industrie' par défaut : sur la page logistique (qui réutilise IndustrieProof sector='logistique' en dur), la section WP ne porte pas l'info secteur — le filtre des références retomberait sur Industrie.",
      "Intros riches (strong/liens) : quand le seed fournit un intro en texte brut (LogistiqueProblem, LogistiqueSolution, DistributionCEE), l'adaptateur passe la string WP et les <strong>/<a> de l'original sont perdus si la valeur WP est renseignée ; sans valeur WP le défaut JSX riche est conservé.",
      "Reconstructions heuristiques de titres : hubHeroTitre (virgule -> <br/> + span muted), distMethodTitre (split en phrases), commaBreak, colonBreak et la métrique des cartes solution (motif « jusqu'à X ») supposent les formats exacts des seeds ; un contenu BO très différent rend un markup plus simple (une ligne) mais valide.",
      "IndustrieApplications : les liens par carte du seed (lien:#preuves) sont ignorés, le href '#preuves' reste codé en dur (identique au site actuel) ; champ `icone` WP ignoré partout (squelette d'icônes conservé, conforme au pattern home).",
      "Merge par index : si WP fournit plus d'items que le squelette par défaut (stats, cartes, étapes), les extras sont ignorés (les icônes n'existent pas côté WP) ; s'il en fournit moins, les items par défaut restants s'affichent.",
      "Images mobiles non couvertes par le schéma WP (LogistiqueHero source mobile, LogistiqueSolution mobileImage) : restent sur les assets par défaut ; l'image WP des solutions n'écrase que la carte cool roof (le seed ne fournit qu'une image).",
      "toSectorConfig : matching par layout + ordre (badged grille_cards n°1=problème, n°2=applications, texte_image avec/sans CTA, chiffres clair/sombre) — robuste pour les 4 seeds actuels mais sensible à un réordonnancement inhabituel dans le BO ; champ `origine` non discriminant faute de convention de nommage par sous-section ; hero.formFields (options des selects), proof.transition, finalCta.eyebrow, seo.eyebrow, benefits.image et reassurance band restent sur le fallback (absents du schéma WP).",
      "Footnote de DistributionSEOContent et eyebrows des dossiers SEO : non présents dans le layout contenu_seo, défauts conservés.",
      "Champs seed inutilisés — contact : grille_cards.colonnes et .theme, cards[].icone (icônes résolues par position/nom dans le mapper), composant_react.composant (la vue rend toujours HubSpotContactForm et l'iframe carte en dur, MAP_URL n'a pas de champ WP) ; l'eyebrow 'Formulaire', le pill 'Demande transmise', la mention RGPD, le label 'Localisation' et le StickyMobileCTA (label/tel) restent en dur faute de champ seed.",
      "Champs seed inutilisés — faq : faq.json_ld (la vue n'émet pas de JSON-LD), hero.variante, cta.variante ; le badge 'Une autre question ?' du CTA final reste en dur (pas de champ badge dans le layout cta).",
      "Champs seed inutilisés — references : references_grille.mode et .filtres (filtres toujours affichés, items de grille issus de src/data/references et non du CPT WP), hero.variante, cta.variante ; le badge 'Votre projet' du CTA final et le StickyMobileCTA restent en dur.",
      "Champs seed inutilisés — diagnostic : composant_react.composant (DiagnosticForm rendu en dur), logos.source='clients' (ClientLogosSlider a ses propres données internes), hero.variante.",
      "Champs seed inutilisés — estimation : composant_react.composant (formulaire d'estimation en dur, types de bâtiment/secteurs/taux €/m² non pilotables), hero.variante.",
      "Détail accent : le seed place l'espace avant le segment accent hors du span ('devis *gratuit.*') alors que l'original l'a dans le span ; le helper renderAccentTitre absorbe cette espace dans le span pour un DOM identique — rendu pixel-identique dans tous les cas.",
      "Apostrophes : certains défauts d'origine utilisent l'apostrophe droite (') alors que le seed utilise la typographique (’) ; en mode WP le texte affiché suit le seed (différence purement typographique, déjà présente dans les autres familles).",
      "Le worktree contient de nombreuses modifications parallèles d'autres agents (composants home/industrie/produits, fragments, BlockRenderer) ; le tsc --noEmit vert couvre l'ensemble mais seuls les 12 fichiers listés relèvent de cette tâche.",
      "Le découpage de texte_apres du tableau 'exemples' (splitSud) et des préfixes 'La formule : ' / 'Attention : ' est heuristique (split par phrase / premier ' : ') : si l'éditeur WP reformule ces champs, la répartition titre/texte/note peut dériver — testé OK contre le seed actuel.",
      "Les icônes lucide, eyebrows et numéros d'étapes sont mappés PAR POSITION depuis l'original : ajouter/réordonner des rows WP décale les icônes (le champ cards[].icone du seed n'est pas exploité).",
      "Le seed utilise des apostrophes typographiques (’) là où certains défauts des vues utilisent des apostrophes droites (') : avec données WP le texte rendu diffère du défaut au niveau du caractère d'apostrophe (parité pixel à vérifier par le harnais de diff).",
      "Les sections grille_cards et texte_image multiples sont matchées par position (nthLayout/byLayout) faute de champ `origine` dans les seeds de ces 5 pages.",
      "Certains micro-textes restent en dur sans champ seed correspondant (estimateur CEE, StickyMobileCTA, entête de tableau 'Barème officiel BAT-EN-112', label 'La formule') — non pilotables depuis WP en l'état.",
      "Une partie du travail audité (4 vues + 4 mappers) provenait d'une passe précédente non commitée sur la même branche ; je l'ai vérifiée mais pas réécrite.",
      "Aucune route app/ ne consomme encore ces mappers (câblage hors périmètre de cette tâche) ; npx tsc --noEmit passe mais aucun test de rendu n'a été exécuté.",
      "L'image de fiche (CustomerReference.image) vient de la featured image WP non exposée par la query GraphQL actuelle : toujours comblée par la donnée codée.",
      "Le champ surface de fiche_reference est dérivé des metrics à l'export et n'a pas de champ inverse dans CustomerReference (porté par metrics).",
      "Les en-têtes du tableau situations, le path, productName, les images/icônes des cards benefits, la vidéo méthode et l'entête FAQ sont des constantes du template/donnée codée, non pilotables depuis WP.",
      "Si WordPress (wpautop) reformate les wysiwyg au save, paragraphsOf reste tolérant (fallback stripHtml + jointure \\n\\n) mais la parité octet des textes multi-paragraphes dépend du stockage brut du seed.",
      "Parité vérifiée par revue de code + tsc ; le diff pixel automatisé (tâche #9, scripts/pixel-diff/) reste à exécuter contre l'instance WP seedée."
    ]
  }
}