[{"data":1,"prerenderedAt":4398},["ShallowReactive",2],{"search-api":-1,"listing-tag-Qualité-page-1":3},[4,949,1767,2403,3904],{"_path":5,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":9,"description":10,"id":11,"date":12,"listed":13,"nocomments":7,"hidden":7,"categories":14,"tags":15,"cover":20,"readingTime":21,"body":26,"_type":943,"_id":944,"_source":945,"_file":946,"_stem":947,"_extension":948},"\u002Ffr\u002Fintelligence-artificielle\u002Fia-code-review-retour-experience","intelligence-artificielle",false,"","IA en code review : retour d'expérience après 6 mois avec Claude","Après 6 mois à utiliser Claude pour reviewer mes propres PR sur crmcoaching : ce qu'il trouve bien, ce qu'il rate, et comment l'intégrer dans une boucle de review solo sans perdre en rigueur.",37,"2026-03-20",true,[6],[16,17,18,19],"Code Review","IA","Retour d'expérience","Qualité","covers\u002Farticles\u002Fia-code-review-retour-experience.jpg",{"text":22,"minutes":23,"time":24,"words":25},"11 min read",10.31,618600,2062,{"type":27,"children":28,"toc":934},"root",[29,37,42,51,55,62,67,75,80,88,93,101,106,389,418,421,427,435,440,448,462,470,475,483,488,491,497,502,510,515,523,528,536,541,549,554,562,567,580,583,589,594,604,614,624,627,633,739,752,755,761,771,781,791,801,804,816,819,825,848,861,874,887,900,913,916,928],{"type":30,"tag":31,"props":32,"children":33},"element","p",{},[34],{"type":35,"value":36},"text","Je développe seul crmcoaching (un CRM pour coachs professionnels) sur une stack NestJS 11, Prisma 7, PostgreSQL, Next.js 16 et architecture hexagonale. Pas d'équipe. Pas de reviewer humain disponible à chaque PR. Et pourtant, la qualité ne peut pas régresser : c'est un SaaS en production.",{"type":30,"tag":31,"props":38,"children":39},{},[40],{"type":35,"value":41},"Depuis décembre 2025, Claude est dans ma boucle de review systématique. Le bilan après 6 mois : le temps de review que je passe moi-même a baissé d'environ 40% sur les aspects mécaniques (sécurité, conventions, couverture de tests), et j'ai attrapé plusieurs bugs avant de les pousser en staging. Mais Claude rate aussi des choses de façon prévisible, et comprendre ces angles morts change tout à la façon dont on l'utilise.",{"type":30,"tag":31,"props":43,"children":44},{},[45],{"type":30,"tag":46,"props":47,"children":48},"strong",{},[49],{"type":35,"value":50},"Ce qui fait la différence, ce n'est pas l'outil. C'est la méthode d'intégration.",{"type":30,"tag":52,"props":53,"children":54},"hr",{},[],{"type":30,"tag":56,"props":57,"children":59},"h2",{"id":58},"les-trois-façons-dutiliser-claude-en-review",[60],{"type":35,"value":61},"Les trois façons d'utiliser Claude en review",{"type":30,"tag":31,"props":63,"children":64},{},[65],{"type":35,"value":66},"Avant d'entrer dans ce que Claude trouve ou rate, il faut clarifier le mode d'utilisation : les résultats varient significativement selon la façon dont on l'intègre.",{"type":30,"tag":31,"props":68,"children":69},{},[70],{"type":30,"tag":46,"props":71,"children":72},{},[73],{"type":35,"value":74},"Claude Code en local (mode interactif)",{"type":30,"tag":31,"props":76,"children":77},{},[78],{"type":35,"value":79},"C'est le mode que j'utilise le plus souvent. Après avoir implémenté une feature dans un worktree isolé, je demande à Claude Code de reviewer le diff avant de créer la PR. L'avantage : Claude a accès au repo complet, aux fichiers de contexte (CLAUDE.md, conventions hexagonales, règles biome), et peut naviguer dans le code adjacent pour vérifier la cohérence. Le coût est inclus dans l'abonnement Claude Pro : pas de calcul à la PR.",{"type":30,"tag":31,"props":81,"children":82},{},[83],{"type":30,"tag":46,"props":84,"children":85},{},[86],{"type":35,"value":87},"Claude via API avec le diff + contexte projet",{"type":30,"tag":31,"props":89,"children":90},{},[91],{"type":35,"value":92},"Pour les PR plus complexes ou quand je veux un avis \"extérieur\" sans contexte de session accumulé, j'envoie le diff complet avec un prompt système qui embarque les conventions crmcoaching. Le coût est environ 0,10 à 0,40 € par PR selon la taille du diff (claude-sonnet-4, ~800 tokens en input pour une PR moyenne + diff). Sur 20 PR par mois, c'est inférieur à 8 €.",{"type":30,"tag":31,"props":94,"children":95},{},[96],{"type":30,"tag":46,"props":97,"children":98},{},[99],{"type":35,"value":100},"Prompt système avec conventions intégrées (CI review automatique)",{"type":30,"tag":31,"props":102,"children":103},{},[104],{"type":35,"value":105},"Le mode le plus scalable si on veut une review systématique sans action manuelle. Un workflow GitHub Actions envoie le diff à l'API Claude dès l'ouverture d'une PR, avec le prompt système suivant :",{"type":30,"tag":107,"props":108,"children":112},"pre",{"className":109,"code":110,"language":111,"meta":8,"style":8},"language-typescript shiki shiki-themes catppuccin-frappe github-dark","\u002F\u002F apps\u002Fapi\u002Fsrc\u002Finfrastructure\u002Fclaude\u002Freview-prompt.ts\n\nexport const REVIEW_SYSTEM_PROMPT = `\nTu es un reviewer senior sur le projet crmcoaching.\n\nStack : NestJS 11, Prisma 7, PostgreSQL, Zod 4, architecture hexagonale, Vitest.\nFrontend : Next.js 16 App Router, React 19, Tailwind v4, TanStack Query.\n\nConventions obligatoires :\n- Architecture hexagonale stricte : domain\u002F ne dépend de rien, application\u002F dépend de domain\u002F, infrastructure\u002F implémente les ports\n- Pas de non-null assertion (!) sans justification explicite en commentaire\n- Fonctions > 50 lignes : extraire un helper avant de merger\n- Complexité cognitive > 15 : bloquant (biome noExcessiveCognitiveComplexity)\n- Conventional Commits : feat:, fix:, refactor:, test:, chore:\n- Tests obligatoires par couche : unit sur domain\u002F et application\u002F, integration sur infrastructure\u002F (vraie DB), Playwright sur les pages\n\nPour chaque finding, utilise le format :\n- [sécurité] pour les injections, secrets, vulnérabilités\n- [architecture] pour les violations hexagonales, couplage\n- [qualité] pour la complexité, les fonctions trop longues\n- [tests] pour la couverture manquante\n- [convention] pour le style et le nommage\n\nFaux positifs à éviter : ne signale pas les biome-ignore avec justification explicite.\n`.trim();\n","typescript",[113],{"type":30,"tag":114,"props":115,"children":116},"code",{"__ignoreMap":8},[117,129,138,171,180,188,197,206,214,223,232,241,250,259,268,277,285,294,303,312,321,330,339,347,356],{"type":30,"tag":118,"props":119,"children":122},"span",{"class":120,"line":121},"line",1,[123],{"type":30,"tag":118,"props":124,"children":126},{"style":125},"--shiki-default:#737994;--shiki-default-font-style:italic;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit",[127],{"type":35,"value":128},"\u002F\u002F apps\u002Fapi\u002Fsrc\u002Finfrastructure\u002Fclaude\u002Freview-prompt.ts\n",{"type":30,"tag":118,"props":130,"children":132},{"class":120,"line":131},2,[133],{"type":30,"tag":118,"props":134,"children":135},{"emptyLinePlaceholder":13},[136],{"type":35,"value":137},"\n",{"type":30,"tag":118,"props":139,"children":141},{"class":120,"line":140},3,[142,148,153,159,165],{"type":30,"tag":118,"props":143,"children":145},{"style":144},"--shiki-default:#CA9EE6;--shiki-dark:#F97583",[146],{"type":35,"value":147},"export",{"type":30,"tag":118,"props":149,"children":150},{"style":144},[151],{"type":35,"value":152}," const",{"type":30,"tag":118,"props":154,"children":156},{"style":155},"--shiki-default:#C6D0F5;--shiki-dark:#79B8FF",[157],{"type":35,"value":158}," REVIEW_SYSTEM_PROMPT",{"type":30,"tag":118,"props":160,"children":162},{"style":161},"--shiki-default:#81C8BE;--shiki-dark:#F97583",[163],{"type":35,"value":164}," =",{"type":30,"tag":118,"props":166,"children":168},{"style":167},"--shiki-default:#A6D189;--shiki-dark:#9ECBFF",[169],{"type":35,"value":170}," `\n",{"type":30,"tag":118,"props":172,"children":174},{"class":120,"line":173},4,[175],{"type":30,"tag":118,"props":176,"children":177},{"style":167},[178],{"type":35,"value":179},"Tu es un reviewer senior sur le projet crmcoaching.\n",{"type":30,"tag":118,"props":181,"children":183},{"class":120,"line":182},5,[184],{"type":30,"tag":118,"props":185,"children":186},{"emptyLinePlaceholder":13},[187],{"type":35,"value":137},{"type":30,"tag":118,"props":189,"children":191},{"class":120,"line":190},6,[192],{"type":30,"tag":118,"props":193,"children":194},{"style":167},[195],{"type":35,"value":196},"Stack : NestJS 11, Prisma 7, PostgreSQL, Zod 4, architecture hexagonale, Vitest.\n",{"type":30,"tag":118,"props":198,"children":200},{"class":120,"line":199},7,[201],{"type":30,"tag":118,"props":202,"children":203},{"style":167},[204],{"type":35,"value":205},"Frontend : Next.js 16 App Router, React 19, Tailwind v4, TanStack Query.\n",{"type":30,"tag":118,"props":207,"children":209},{"class":120,"line":208},8,[210],{"type":30,"tag":118,"props":211,"children":212},{"emptyLinePlaceholder":13},[213],{"type":35,"value":137},{"type":30,"tag":118,"props":215,"children":217},{"class":120,"line":216},9,[218],{"type":30,"tag":118,"props":219,"children":220},{"style":167},[221],{"type":35,"value":222},"Conventions obligatoires :\n",{"type":30,"tag":118,"props":224,"children":226},{"class":120,"line":225},10,[227],{"type":30,"tag":118,"props":228,"children":229},{"style":167},[230],{"type":35,"value":231},"- Architecture hexagonale stricte : domain\u002F ne dépend de rien, application\u002F dépend de domain\u002F, infrastructure\u002F implémente les ports\n",{"type":30,"tag":118,"props":233,"children":235},{"class":120,"line":234},11,[236],{"type":30,"tag":118,"props":237,"children":238},{"style":167},[239],{"type":35,"value":240},"- Pas de non-null assertion (!) sans justification explicite en commentaire\n",{"type":30,"tag":118,"props":242,"children":244},{"class":120,"line":243},12,[245],{"type":30,"tag":118,"props":246,"children":247},{"style":167},[248],{"type":35,"value":249},"- Fonctions > 50 lignes : extraire un helper avant de merger\n",{"type":30,"tag":118,"props":251,"children":253},{"class":120,"line":252},13,[254],{"type":30,"tag":118,"props":255,"children":256},{"style":167},[257],{"type":35,"value":258},"- Complexité cognitive > 15 : bloquant (biome noExcessiveCognitiveComplexity)\n",{"type":30,"tag":118,"props":260,"children":262},{"class":120,"line":261},14,[263],{"type":30,"tag":118,"props":264,"children":265},{"style":167},[266],{"type":35,"value":267},"- Conventional Commits : feat:, fix:, refactor:, test:, chore:\n",{"type":30,"tag":118,"props":269,"children":271},{"class":120,"line":270},15,[272],{"type":30,"tag":118,"props":273,"children":274},{"style":167},[275],{"type":35,"value":276},"- Tests obligatoires par couche : unit sur domain\u002F et application\u002F, integration sur infrastructure\u002F (vraie DB), Playwright sur les pages\n",{"type":30,"tag":118,"props":278,"children":280},{"class":120,"line":279},16,[281],{"type":30,"tag":118,"props":282,"children":283},{"emptyLinePlaceholder":13},[284],{"type":35,"value":137},{"type":30,"tag":118,"props":286,"children":288},{"class":120,"line":287},17,[289],{"type":30,"tag":118,"props":290,"children":291},{"style":167},[292],{"type":35,"value":293},"Pour chaque finding, utilise le format :\n",{"type":30,"tag":118,"props":295,"children":297},{"class":120,"line":296},18,[298],{"type":30,"tag":118,"props":299,"children":300},{"style":167},[301],{"type":35,"value":302},"- [sécurité] pour les injections, secrets, vulnérabilités\n",{"type":30,"tag":118,"props":304,"children":306},{"class":120,"line":305},19,[307],{"type":30,"tag":118,"props":308,"children":309},{"style":167},[310],{"type":35,"value":311},"- [architecture] pour les violations hexagonales, couplage\n",{"type":30,"tag":118,"props":313,"children":315},{"class":120,"line":314},20,[316],{"type":30,"tag":118,"props":317,"children":318},{"style":167},[319],{"type":35,"value":320},"- [qualité] pour la complexité, les fonctions trop longues\n",{"type":30,"tag":118,"props":322,"children":324},{"class":120,"line":323},21,[325],{"type":30,"tag":118,"props":326,"children":327},{"style":167},[328],{"type":35,"value":329},"- [tests] pour la couverture manquante\n",{"type":30,"tag":118,"props":331,"children":333},{"class":120,"line":332},22,[334],{"type":30,"tag":118,"props":335,"children":336},{"style":167},[337],{"type":35,"value":338},"- [convention] pour le style et le nommage\n",{"type":30,"tag":118,"props":340,"children":342},{"class":120,"line":341},23,[343],{"type":30,"tag":118,"props":344,"children":345},{"emptyLinePlaceholder":13},[346],{"type":35,"value":137},{"type":30,"tag":118,"props":348,"children":350},{"class":120,"line":349},24,[351],{"type":30,"tag":118,"props":352,"children":353},{"style":167},[354],{"type":35,"value":355},"Faux positifs à éviter : ne signale pas les biome-ignore avec justification explicite.\n",{"type":30,"tag":118,"props":357,"children":359},{"class":120,"line":358},25,[360,365,371,377,383],{"type":30,"tag":118,"props":361,"children":362},{"style":167},[363],{"type":35,"value":364},"`",{"type":30,"tag":118,"props":366,"children":368},{"style":367},"--shiki-default:#81C8BE;--shiki-dark:#E1E4E8",[369],{"type":35,"value":370},".",{"type":30,"tag":118,"props":372,"children":374},{"style":373},"--shiki-default:#8CAAEE;--shiki-default-font-style:italic;--shiki-dark:#B392F0;--shiki-dark-font-style:inherit",[375],{"type":35,"value":376},"trim",{"type":30,"tag":118,"props":378,"children":380},{"style":379},"--shiki-default:#C6D0F5;--shiki-dark:#E1E4E8",[381],{"type":35,"value":382},"()",{"type":30,"tag":118,"props":384,"children":386},{"style":385},"--shiki-default:#949CBB;--shiki-dark:#E1E4E8",[387],{"type":35,"value":388},";\n",{"type":30,"tag":31,"props":390,"children":391},{},[392,394,400,402,408,410,416],{"type":35,"value":393},"Ce prompt injecte directement les règles de ",{"type":30,"tag":114,"props":395,"children":397},{"className":396},[],[398],{"type":35,"value":399},".claude\u002Frules\u002F",{"type":35,"value":401}," dans le contexte de review. Le résultat : Claude signale les violations hexagonales (une couche ",{"type":30,"tag":114,"props":403,"children":405},{"className":404},[],[406],{"type":35,"value":407},"application\u002F",{"type":35,"value":409}," qui importe directement depuis ",{"type":30,"tag":114,"props":411,"children":413},{"className":412},[],[414],{"type":35,"value":415},"infrastructure\u002F",{"type":35,"value":417},"), les non-null assertions sans justification, et les fonctions qui dépassent le seuil biome, avec une précision que je n'aurais pas trouvé moi-même en relecture rapide.",{"type":30,"tag":52,"props":419,"children":420},{},[],{"type":30,"tag":56,"props":422,"children":424},{"id":423},"ce-que-claude-trouve-bien",[425],{"type":35,"value":426},"Ce que Claude trouve bien",{"type":30,"tag":31,"props":428,"children":429},{},[430],{"type":30,"tag":46,"props":431,"children":432},{},[433],{"type":35,"value":434},"Violations de l'architecture hexagonale",{"type":30,"tag":31,"props":436,"children":437},{},[438],{"type":35,"value":439},"C'est le finding le plus utile sur crmcoaching. Quand une use-case importe directement un service Prisma au lieu de passer par le Port, Claude le détecte fiablement si les conventions hexagonales sont dans le prompt système. Sur les 6 derniers mois, 7 violations de ce type ont été attrapées avant merge, dont 2 qui auraient créé des couplages difficiles à défaire ensuite.",{"type":30,"tag":31,"props":441,"children":442},{},[443],{"type":30,"tag":46,"props":444,"children":445},{},[446],{"type":35,"value":447},"Sécurité évidente",{"type":30,"tag":31,"props":449,"children":450},{},[451,453,460],{"type":35,"value":452},"Secrets hardcodés, logique d'autorisation absente sur un endpoint, JWT validé sans vérification de l'audience. Claude détecte ces patterns mieux que ma relecture humaine, non pas parce qu'il est plus intelligent, mais parce qu'il ne fatigue pas et applique le pattern systématiquement. Une ",{"type":30,"tag":454,"props":455,"children":457},"a",{"href":456},"\u002Ffr\u002Fintelligence-artificielle\u002Fllm-securite-code-vulnerabilites",[458],{"type":35,"value":459},"étude Stanford (2023)",{"type":35,"value":461}," documentait que 40% du code IA-généré contenait des vulnérabilités dans des contextes de sécurité spécifiques : Claude en review détecte précisément ces patterns dans le code qu'il a lui-même généré.",{"type":30,"tag":31,"props":463,"children":464},{},[465],{"type":30,"tag":46,"props":466,"children":467},{},[468],{"type":35,"value":469},"Couverture de tests manquante",{"type":30,"tag":31,"props":471,"children":472},{},[473],{"type":35,"value":474},"\"Ce use-case n'a pas de test pour le cas d'erreur quand le lead n'existe pas\" : ce type de finding revient régulièrement et me fait gagner du temps sur la lecture des specs de test. Claude identifie les branches non couvertes avec une précision correcte, surtout quand les conventions de test par couche sont dans le prompt.",{"type":30,"tag":31,"props":476,"children":477},{},[478],{"type":30,"tag":46,"props":479,"children":480},{},[481],{"type":35,"value":482},"Style et conventions mécaniques",{"type":30,"tag":31,"props":484,"children":485},{},[486],{"type":35,"value":487},"Nommage incohérent avec les conventions du projet, fonction trop longue sans extraction de helper, complexité cyclomatique élevée. Claude commente ces points avec une régularité que ma propre relecture n'a pas quand je suis dans le contexte de l'implémentation.",{"type":30,"tag":52,"props":489,"children":490},{},[],{"type":30,"tag":56,"props":492,"children":494},{"id":493},"ce-que-claude-rate-systématiquement",[495],{"type":35,"value":496},"Ce que Claude rate systématiquement",{"type":30,"tag":31,"props":498,"children":499},{},[500],{"type":35,"value":501},"Après 6 mois, j'ai identifié 5 angles morts récurrents.",{"type":30,"tag":31,"props":503,"children":504},{},[505],{"type":30,"tag":46,"props":506,"children":507},{},[508],{"type":35,"value":509},"La cohérence avec le reste du codebase quand le contexte est insuffisant",{"type":30,"tag":31,"props":511,"children":512},{},[513],{"type":35,"value":514},"Claude revoit le diff. Si le projet utilise un pattern de gestion d'erreur spécifique que je n'ai pas mis dans le prompt système, Claude peut suggérer un pattern différent, techniquement correct mais incohérent avec le reste. La solution : enrichir progressivement le prompt système avec les patterns qui reviennent. C'est un travail itératif, pas une config one-shot.",{"type":30,"tag":31,"props":516,"children":517},{},[518],{"type":30,"tag":46,"props":519,"children":520},{},[521],{"type":35,"value":522},"La logique métier incorrecte",{"type":30,"tag":31,"props":524,"children":525},{},[526],{"type":35,"value":527},"Un calcul de remise selon des règles coaching spécifiques à crmcoaching : si le code est techniquement correct mais que la règle métier est fausse, Claude ne voit pas le problème. Aucun outil IA ne peut combler ce gap : seule ma connaissance du domaine le peut. C'est le point le plus important à ne pas déléguer.",{"type":30,"tag":31,"props":529,"children":530},{},[531],{"type":30,"tag":46,"props":532,"children":533},{},[534],{"type":35,"value":535},"L'impact architectural à long terme",{"type":30,"tag":31,"props":537,"children":538},{},[539],{"type":35,"value":540},"Un changement qui respecte tous les patterns peut introduire un couplage problématique que je ne verrai que 3 mois plus tard. Claude analyse local. Il ne voit pas les implications systémiques d'un changement de modèle de données sur les 8 use-cases qui utilisent l'entité concernée.",{"type":30,"tag":31,"props":542,"children":543},{},[544],{"type":30,"tag":46,"props":545,"children":546},{},[547],{"type":35,"value":548},"La duplication de logique métier cross-domaines",{"type":30,"tag":31,"props":550,"children":551},{},[552],{"type":35,"value":553},"Deux modules qui implémentent la même règle de validation légèrement différemment. Claude revoit chaque diff en isolation et ne peut pas détecter la duplication sans contexte étendu du repo. Claude Code en mode local s'en sort mieux que l'API, parce qu'il peut naviguer activement dans le codebase.",{"type":30,"tag":31,"props":555,"children":556},{},[557],{"type":30,"tag":46,"props":558,"children":559},{},[560],{"type":35,"value":561},"L'intention derrière une constante ou une valeur",{"type":30,"tag":31,"props":563,"children":564},{},[565],{"type":35,"value":566},"Une PR qui modifie un timeout de 5000ms à 3000ms. Claude commente éventuellement sur le style. Il ne sait pas que ce timeout avait été calibré pour contourner un bug de l'API Brevo en production. Cette connaissance implicite ne peut pas être injectée dans un prompt système : elle n'existe que dans les ADRs ou la mémoire du développeur.",{"type":30,"tag":568,"props":569,"children":574},"cta",{"cta":570,"href":571,"title":572,"type":573},"Coder comme un senior →","https:\u002F\u002Fapp.kamanga.fr\u002Fforms\u002Fmentoring","Tu veux affûter ton œil de reviewer sur le code que l'IA te génère ?","call",[575],{"type":30,"tag":31,"props":576,"children":577},{},[578],{"type":35,"value":579},"Savoir ce que tu peux déléguer à Claude et ce que tu dois garder, ça se construit avec l'expérience, ou avec quelqu'un qui l'a déjà construite. En mentoring 1:1, on revoit tes vraies PR ensemble, je te montre où je coupe la délégation et pourquoi, et tu repars avec une boucle de review solo qui ne sacrifie rien à la rigueur.",{"type":30,"tag":52,"props":581,"children":582},{},[],{"type":30,"tag":56,"props":584,"children":586},{"id":585},"limpact-sur-ma-façon-de-travailler-en-solo",[587],{"type":35,"value":588},"L'impact sur ma façon de travailler en solo",{"type":30,"tag":31,"props":590,"children":591},{},[592],{"type":35,"value":593},"Ce que Claude change concrètement dans une boucle solo :",{"type":30,"tag":31,"props":595,"children":596},{},[597,602],{"type":30,"tag":46,"props":598,"children":599},{},[600],{"type":35,"value":601},"Ce qui s'améliore :",{"type":35,"value":603}," ma relecture humaine porte maintenant sur le fond (logique métier, impact architectural, cohérence avec les décisions passées) plutôt que sur la forme (conventions, sécurité mécanique, couverture de tests). Claude filtre ce bruit. Le \"time to first review\" passe à moins de 2 minutes en mode API, ce qui casse le cycle \"j'ai fini la feature, j'attends le feedback, je suis passé à autre chose\".",{"type":30,"tag":31,"props":605,"children":606},{},[607,612],{"type":30,"tag":46,"props":608,"children":609},{},[610],{"type":35,"value":611},"Le risque principal :",{"type":35,"value":613}," la délégation de responsabilité. \"Claude a reviewé, donc c'est bon.\" Ce pattern crée une fausse sécurité dangereuse sur les bugs de logique métier. Je l'ai vécu sur une PR de scoring Brevo en mars 2026 : Claude avait validé la structure, mais la règle de scoring était inversée. Bug détecté en staging, pas en production, mais le risque était réel.",{"type":30,"tag":31,"props":615,"children":616},{},[617,622],{"type":30,"tag":46,"props":618,"children":619},{},[620],{"type":35,"value":621},"La règle que j'applique :",{"type":35,"value":623}," Claude revoit les patterns connus (sécurité, conventions, architecture, tests). Moi je revois la logique métier, l'intention du changement, et les impacts cross-domaines. Cette séparation est explicite, pas implicite.",{"type":30,"tag":52,"props":625,"children":626},{},[],{"type":30,"tag":56,"props":628,"children":630},{"id":629},"la-séparation-des-responsabilités",[631],{"type":35,"value":632},"La séparation des responsabilités",{"type":30,"tag":634,"props":635,"children":636},"table",{},[637,656],{"type":30,"tag":638,"props":639,"children":640},"thead",{},[641],{"type":30,"tag":642,"props":643,"children":644},"tr",{},[645,651],{"type":30,"tag":646,"props":647,"children":648},"th",{},[649],{"type":35,"value":650},"Claude revoit",{"type":30,"tag":646,"props":652,"children":653},{},[654],{"type":35,"value":655},"Je revois moi-même",{"type":30,"tag":657,"props":658,"children":659},"tbody",{},[660,674,687,700,713,726],{"type":30,"tag":642,"props":661,"children":662},{},[663,669],{"type":30,"tag":664,"props":665,"children":666},"td",{},[667],{"type":35,"value":668},"Sécurité (injections, secrets, autorisations manquantes)",{"type":30,"tag":664,"props":670,"children":671},{},[672],{"type":35,"value":673},"Logique métier",{"type":30,"tag":642,"props":675,"children":676},{},[677,682],{"type":30,"tag":664,"props":678,"children":679},{},[680],{"type":35,"value":681},"Style et conventions crmcoaching",{"type":30,"tag":664,"props":683,"children":684},{},[685],{"type":35,"value":686},"Impact architectural",{"type":30,"tag":642,"props":688,"children":689},{},[690,695],{"type":30,"tag":664,"props":691,"children":692},{},[693],{"type":35,"value":694},"Tests manquants par couche",{"type":30,"tag":664,"props":696,"children":697},{},[698],{"type":35,"value":699},"Cohérence avec le codebase",{"type":30,"tag":642,"props":701,"children":702},{},[703,708],{"type":30,"tag":664,"props":704,"children":705},{},[706],{"type":35,"value":707},"Complexité excessive (biome)",{"type":30,"tag":664,"props":709,"children":710},{},[711],{"type":35,"value":712},"Intention du changement",{"type":30,"tag":642,"props":714,"children":715},{},[716,721],{"type":30,"tag":664,"props":717,"children":718},{},[719],{"type":35,"value":720},"Violations hexagonales",{"type":30,"tag":664,"props":722,"children":723},{},[724],{"type":35,"value":725},"Trade-offs de design",{"type":30,"tag":642,"props":727,"children":728},{},[729,734],{"type":30,"tag":664,"props":730,"children":731},{},[732],{"type":35,"value":733},"Documentation manquante",{"type":30,"tag":664,"props":735,"children":736},{},[737],{"type":35,"value":738},"Décisions implicites non documentées",{"type":30,"tag":31,"props":740,"children":741},{},[742,744,750],{"type":35,"value":743},"Complétez cette séparation avec la ",{"type":30,"tag":454,"props":745,"children":747},{"href":746},"\u002Ffr\u002Fintelligence-artificielle\u002Ftester-code-genere-ia-checklist",[748],{"type":35,"value":749},"checklist de validation du code IA",{"type":35,"value":751}," pour les PRs à fort contenu généré.",{"type":30,"tag":52,"props":753,"children":754},{},[],{"type":30,"tag":56,"props":756,"children":758},{"id":757},"les-métriques-que-je-suis",[759],{"type":35,"value":760},"Les métriques que je suis",{"type":30,"tag":31,"props":762,"children":763},{},[764,769],{"type":30,"tag":46,"props":765,"children":766},{},[767],{"type":35,"value":768},"Time to first review :",{"type":35,"value":770}," avec Claude en mode API, ce metric est inférieur à 2 minutes. C'est un gain réel pour rester dans le flux.",{"type":30,"tag":31,"props":772,"children":773},{},[774,779],{"type":30,"tag":46,"props":775,"children":776},{},[777],{"type":35,"value":778},"Taux de faux positifs :",{"type":35,"value":780}," le pourcentage de commentaires Claude que je rejette comme non-pertinents. Actuellement autour de 20% (en baisse depuis que j'ai enrichi le prompt système avec les patterns crmcoaching). Au-dessus de 30%, il faut retravailler le prompt ou les conventions injectées.",{"type":30,"tag":31,"props":782,"children":783},{},[784,789],{"type":30,"tag":46,"props":785,"children":786},{},[787],{"type":35,"value":788},"Bug escape rate :",{"type":35,"value":790}," bugs détectés en production divisé par bugs détectés en review. Si ce ratio se dégrade malgré Claude, l'IA crée une fausse sécurité. Sur les 6 mois, le ratio s'est amélioré sur les bugs de sécurité et d'architecture, pas sur les bugs de logique métier (cohérent avec les angles morts identifiés).",{"type":30,"tag":31,"props":792,"children":793},{},[794,799],{"type":30,"tag":46,"props":795,"children":796},{},[797],{"type":35,"value":798},"Coût API :",{"type":35,"value":800}," moins de 8 € par mois sur le volume actuel de PRs crmcoaching. Marginal par rapport au coût du temps de review humaine.",{"type":30,"tag":52,"props":802,"children":803},{},[],{"type":30,"tag":568,"props":805,"children":810},{"cta":806,"href":807,"title":808,"type":809},"Les 100 pratiques que l'IA n'enseigne pas →","https:\u002F\u002Fkamanga.fr\u002Freferentiel-craft","La séparation des responsabilités n'est qu'une des 100 pratiques craft","product",[811],{"type":30,"tag":31,"props":812,"children":813},{},[814],{"type":35,"value":815},"Savoir ce que l'IA revoit et ce qu'elle rate, c'est un réflexe craft parmi d'autres. Le Craft Bundle réunit les 100 pratiques que j'applique sur crmcoaching pour coder propre et garder la main sur la qualité : les jugements de senior que l'IA ne te transmettra jamais, parce qu'elle ne les a jamais appris.",{"type":30,"tag":52,"props":817,"children":818},{},[],{"type":30,"tag":56,"props":820,"children":822},{"id":821},"faq-sur-lia-en-code-review",[823],{"type":35,"value":824},"FAQ sur l'IA en code review",{"type":30,"tag":826,"props":827,"children":828},"details",{},[829,835],{"type":30,"tag":830,"props":831,"children":832},"summary",{},[833],{"type":35,"value":834},"1. Quelle est la différence entre un linter et Claude en review ?",{"type":30,"tag":31,"props":836,"children":837},{},[838,840,846],{"type":35,"value":839},"Un ",{"type":30,"tag":454,"props":841,"children":843},{"href":842},"\u002Ffr\u002Fdette-technique\u002Foutils-analyse-statique-2026",[844],{"type":35,"value":845},"linter",{"type":35,"value":847}," applique des règles déterministes prédéfinies : syntaxe, style, patterns interdits. Il est rapide, sans faux positifs sur ce qu'il est configuré à détecter. Claude applique un raisonnement contextuel : il peut détecter des problèmes que le linter ne peut pas formaliser en règles (ex : \"cette use-case viole le principe de responsabilité unique\"). La complémentarité est optimale : linter (biome dans mon cas) pour les règles déterministes, Claude pour les jugements contextuels qui nécessitent de comprendre l'intention.",{"type":30,"tag":826,"props":849,"children":850},{},[851,856],{"type":30,"tag":830,"props":852,"children":853},{},[854],{"type":35,"value":855},"2. Claude peut-il reviewer du code dans des langages ou frameworks peu courants ?",{"type":30,"tag":31,"props":857,"children":858},{},[859],{"type":35,"value":860},"Claude est entraîné sur TypeScript, NestJS, Prisma, React et toute la stack crmcoaching : pas de problème sur ce scope. Pour des langages peu courants ou des DSLs internes, la qualité du review se dégrade. Dans ce cas, utiliser Claude uniquement pour les aspects génériques (sécurité, documentation) et garder les aspects spécifiques au langage pour une review humaine ou outillée.",{"type":30,"tag":826,"props":862,"children":863},{},[864,869],{"type":30,"tag":830,"props":865,"children":866},{},[867],{"type":35,"value":868},"3. Comment gérer le coût des reviews Claude sur un volume important de PRs ?",{"type":30,"tag":31,"props":870,"children":871},{},[872],{"type":35,"value":873},"En mode Claude Code Pro, les reviews interactives sont incluses dans l'abonnement. En mode API (review automatique en CI), le coût est environ 0,10 à 0,40 € par PR selon la taille du diff avec claude-sonnet-4. Sur 50 PRs par semaine (volume équipe), c'est 5 à 20 € par semaine. Marginal par rapport au coût d'un développeur, et positif dès qu'une review prévient un seul bug en production.",{"type":30,"tag":826,"props":875,"children":876},{},[877,882],{"type":30,"tag":830,"props":878,"children":879},{},[880],{"type":35,"value":881},"4. Comment éviter que Claude donne des faux positifs qui créent du bruit ?",{"type":30,"tag":31,"props":883,"children":884},{},[885],{"type":35,"value":886},"En enrichissant progressivement le prompt système avec les conventions réelles du projet. Les faux positifs viennent quasi systématiquement d'une convention que Claude ne connaît pas : il signale un pattern valide génériquement mais incohérent avec le projet. Ajouter cette convention dans le prompt réduit le bruit de façon immédiate. Sur crmcoaching, le taux de faux positifs est passé de 32% à 20% en 3 mois d'enrichissement du prompt.",{"type":30,"tag":826,"props":888,"children":889},{},[890,895],{"type":30,"tag":830,"props":891,"children":892},{},[893],{"type":35,"value":894},"5. Claude peut-il nuire à l'apprentissage si on lui délègue trop ?",{"type":30,"tag":31,"props":896,"children":897},{},[898],{"type":35,"value":899},"Risque réel en solo ou en petite équipe. Si on laisse Claude décider sans challenger ses suggestions, on apprend les patterns que Claude connaît, pas les jugements contextuels qu'un senior aurait partagés. La règle : utiliser Claude comme premier filtre mécanique, mais prendre soi-même la décision finale sur chaque finding. Rejeter activement un faux positif en comprenant pourquoi il est faux est un apprentissage, pas une perte de temps.",{"type":30,"tag":826,"props":901,"children":902},{},[903,908],{"type":30,"tag":830,"props":904,"children":905},{},[906],{"type":35,"value":907},"6. Comment mesurer si Claude améliore réellement la qualité sur la durée ?",{"type":30,"tag":31,"props":909,"children":910},{},[911],{"type":35,"value":912},"Deux métriques combinées : le bug escape rate (bugs détectés en production \u002F bugs détectés en review) et la densité de défauts par KLOC sur le code produit depuis l'adoption. Si le bug escape rate diminue et que la densité de défauts diminue, Claude améliore la qualité. Si seulement le bug escape rate diminue, Claude détecte mieux mais ne change pas les pratiques : il faut renforcer la qualité des conventions injectées dans le prompt.",{"type":30,"tag":52,"props":914,"children":915},{},[],{"type":30,"tag":568,"props":917,"children":922},{"cta":918,"href":919,"title":920,"type":921},"Testez la readiness IA de votre équipe →","\u002Fmes-ressources","Ressource gratuite : AI-Ready Engineering Team Checklist","resource",[923],{"type":30,"tag":31,"props":924,"children":925},{},[926],{"type":35,"value":927},"La checklist AI-Ready inclut une section dédiée à l'adoption des outils IA en code review : critères d'intégration, règles de séparation des responsabilités, et métriques de suivi à 30 et 90 jours.",{"type":30,"tag":929,"props":930,"children":931},"style",{},[932],{"type":35,"value":933},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":8,"searchDepth":131,"depth":131,"links":935},[936,937,938,939,940,941,942],{"id":58,"depth":131,"text":61},{"id":423,"depth":131,"text":426},{"id":493,"depth":131,"text":496},{"id":585,"depth":131,"text":588},{"id":629,"depth":131,"text":632},{"id":757,"depth":131,"text":760},{"id":821,"depth":131,"text":824},"markdown","content:fr:intelligence-artificielle:ia-code-review-retour-experience.md","content","fr\u002Fintelligence-artificielle\u002Fia-code-review-retour-experience.md","fr\u002Fintelligence-artificielle\u002Fia-code-review-retour-experience","md",{"_path":950,"_dir":951,"_draft":7,"_partial":7,"_locale":8,"title":952,"description":953,"id":954,"date":955,"listed":13,"nocomments":7,"hidden":7,"categories":956,"tags":957,"cover":961,"readingTime":962,"body":967,"_type":943,"_id":1764,"_source":945,"_file":1765,"_stem":1766,"_extension":948},"\u002Ffr\u002Fpratiques-agiles\u002Fcontinuous-integration-fondamentaux","pratiques-agiles","Continuous Integration : les 5 fondamentaux non-négociables","Avoir Jenkins ou GitHub Actions n'est pas faire de la CI. La vraie CI implique des pratiques humaines que l'outil seul ne peut pas imposer.",27,"2026-03-06",[951],[958,959,960,19],"Continuous Integration","CI\u002FCD","Pipeline","covers\u002Farticles\u002Fcontinuous-integration-fondamentaux.jpg",{"text":963,"minutes":964,"time":965,"words":966},"9 min read",8.29,497400,1658,{"type":27,"children":968,"toc":1754},[969,974,979,984,989,994,997,1003,1008,1018,1028,1038,1043,1046,1052,1057,1062,1067,1196,1201,1204,1210,1215,1220,1225,1496,1507,1510,1516,1521,1526,1531,1536,1539,1545,1550,1555,1560,1563,1569,1582,1587,1626,1631,1634,1640,1645,1650,1663,1666,1672,1685,1698,1711,1724,1737,1740,1750],{"type":30,"tag":31,"props":970,"children":971},{},[972],{"type":35,"value":973},"Dans un client dans le secteur bancaire que j'accompagnais (15 développeurs, produit financier B2B), le pipeline CI durait 28 minutes. Les branches vivaient en moyenne 4 jours avant d'être mergées. L'équipe avait GitHub Actions configuré depuis 18 mois. Elle pensait pratiquer la Continuous Integration.",{"type":30,"tag":31,"props":975,"children":976},{},[977],{"type":35,"value":978},"Elle pratiquait le contraire.",{"type":30,"tag":31,"props":980,"children":981},{},[982],{"type":35,"value":983},"Les merges de longues branches généraient des conflits quotidiens. Les builds rouges duraient parfois 6 heures avant d'être corrigés. Et les développeurs avaient arrêté de regarder les alertes du pipeline depuis longtemps : trop de faux positifs, trop de délai entre le commit et le feedback.",{"type":30,"tag":31,"props":985,"children":986},{},[987],{"type":35,"value":988},"La Continuous Integration est une discipline humaine autant qu'une infrastructure technique. La plupart des équipes ont l'outil, et pratiquent le contraire de la CI sans le savoir.",{"type":30,"tag":31,"props":990,"children":991},{},[992],{"type":35,"value":993},"La définition originale vient de Kent Beck (Extreme Programming, 1999) et Martin Fowler : intégrer ses changements dans la branche principale plusieurs fois par jour. Pas une fois par semaine lors de la \"merge PR\". Plusieurs fois par jour. Selon les recherches DORA, les équipes qui pratiquent la vraie CI ont un lead time 4 fois inférieur et un taux d'échec de déploiement 3 fois plus bas. Ce n'est pas l'outil qui fait la différence : c'est la discipline.",{"type":30,"tag":52,"props":995,"children":996},{},[],{"type":30,"tag":56,"props":998,"children":1000},{"id":999},"ce-que-la-ci-nest-pas",[1001],{"type":35,"value":1002},"Ce que la CI n'est pas",{"type":30,"tag":31,"props":1004,"children":1005},{},[1006],{"type":35,"value":1007},"Trois confusions fréquentes méritent d'être clarifiées avant d'aller plus loin.",{"type":30,"tag":31,"props":1009,"children":1010},{},[1011,1016],{"type":30,"tag":46,"props":1012,"children":1013},{},[1014],{"type":35,"value":1015},"La CI n'est pas un pipeline de build automatisé.",{"type":35,"value":1017}," Lancer des tests automatiquement à chaque push n'est pas de la CI si les branches durent 2 semaines avant d'être mergées. L'automatisation sans intégration fréquente, c'est du quality assurance sur des changements isolés.",{"type":30,"tag":31,"props":1019,"children":1020},{},[1021,1026],{"type":30,"tag":46,"props":1022,"children":1023},{},[1024],{"type":35,"value":1025},"La CI n'est pas un gating de qualité.",{"type":35,"value":1027}," Utiliser le pipeline pour bloquer les PRs avec des tests qui échouent est utile, mais c'est de l'assurance qualité, pas de la CI au sens strict.",{"type":30,"tag":31,"props":1029,"children":1030},{},[1031,1036],{"type":30,"tag":46,"props":1032,"children":1033},{},[1034],{"type":35,"value":1035},"La CI n'est pas une histoire de fréquence de déploiement.",{"type":35,"value":1037}," Déployer souvent (CD) est différent d'intégrer souvent (CI). On peut déployer une fois par jour depuis une branche de longue durée : ce n'est pas de la CI.",{"type":30,"tag":31,"props":1039,"children":1040},{},[1041],{"type":35,"value":1042},"La définition précise de Martin Fowler : \"Continuous Integration is a practice where members of a team merge their work frequently, usually each person merges at least daily.\" L'accent est sur la fréquence d'intégration, pas sur l'automatisation.",{"type":30,"tag":52,"props":1044,"children":1045},{},[],{"type":30,"tag":56,"props":1047,"children":1049},{"id":1048},"fondamental-1-intégrer-dans-le-trunk-au-moins-une-fois-par-jour",[1050],{"type":35,"value":1051},"Fondamental 1 : Intégrer dans le trunk au moins une fois par jour",{"type":30,"tag":31,"props":1053,"children":1054},{},[1055],{"type":35,"value":1056},"Chaque développeur intègre son code dans la branche principale (main, master, trunk) au moins une fois toutes les 24 heures.",{"type":30,"tag":31,"props":1058,"children":1059},{},[1060],{"type":35,"value":1061},"Ce qui rend cela difficile : ça suppose que chaque commit soit dans un état qui ne casse pas la branche principale. Ce qui implique des feature flags pour les fonctionnalités incomplètes, et une culture de \"never break the trunk\".",{"type":30,"tag":31,"props":1063,"children":1064},{},[1065],{"type":35,"value":1066},"Les feature flags permettent d'intégrer du code incomplet sans l'exposer aux utilisateurs. C'est le mécanisme qui rend la CI viable pour des fonctionnalités qui prennent plus d'une journée :",{"type":30,"tag":107,"props":1068,"children":1072},{"className":1069,"code":1070,"language":1071,"meta":8,"style":8},"language-python shiki shiki-themes catppuccin-frappe github-dark","# La fonctionnalité n'est pas terminée mais le code est intégré\nif feature_flags.is_enabled('new_checkout_flow', user):\n    return new_checkout_flow(request)\nelse:\n    return legacy_checkout_flow(request)\n","python",[1073],{"type":30,"tag":114,"props":1074,"children":1075},{"__ignoreMap":8},[1076,1084,1132,1159,1172],{"type":30,"tag":118,"props":1077,"children":1078},{"class":120,"line":121},[1079],{"type":30,"tag":118,"props":1080,"children":1081},{"style":125},[1082],{"type":35,"value":1083},"# La fonctionnalité n'est pas terminée mais le code est intégré\n",{"type":30,"tag":118,"props":1085,"children":1086},{"class":120,"line":131},[1087,1092,1097,1101,1107,1112,1117,1122,1127],{"type":30,"tag":118,"props":1088,"children":1089},{"style":144},[1090],{"type":35,"value":1091},"if",{"type":30,"tag":118,"props":1093,"children":1094},{"style":379},[1095],{"type":35,"value":1096}," feature_flags",{"type":30,"tag":118,"props":1098,"children":1099},{"style":385},[1100],{"type":35,"value":370},{"type":30,"tag":118,"props":1102,"children":1104},{"style":1103},"--shiki-default:#8CAAEE;--shiki-dark:#E1E4E8",[1105],{"type":35,"value":1106},"is_enabled",{"type":30,"tag":118,"props":1108,"children":1109},{"style":385},[1110],{"type":35,"value":1111},"(",{"type":30,"tag":118,"props":1113,"children":1114},{"style":167},[1115],{"type":35,"value":1116},"'new_checkout_flow'",{"type":30,"tag":118,"props":1118,"children":1119},{"style":385},[1120],{"type":35,"value":1121},",",{"type":30,"tag":118,"props":1123,"children":1124},{"style":379},[1125],{"type":35,"value":1126}," user",{"type":30,"tag":118,"props":1128,"children":1129},{"style":385},[1130],{"type":35,"value":1131},"):\n",{"type":30,"tag":118,"props":1133,"children":1134},{"class":120,"line":140},[1135,1140,1145,1149,1154],{"type":30,"tag":118,"props":1136,"children":1137},{"style":144},[1138],{"type":35,"value":1139},"    return",{"type":30,"tag":118,"props":1141,"children":1142},{"style":1103},[1143],{"type":35,"value":1144}," new_checkout_flow",{"type":30,"tag":118,"props":1146,"children":1147},{"style":385},[1148],{"type":35,"value":1111},{"type":30,"tag":118,"props":1150,"children":1151},{"style":379},[1152],{"type":35,"value":1153},"request",{"type":30,"tag":118,"props":1155,"children":1156},{"style":385},[1157],{"type":35,"value":1158},")\n",{"type":30,"tag":118,"props":1160,"children":1161},{"class":120,"line":173},[1162,1167],{"type":30,"tag":118,"props":1163,"children":1164},{"style":144},[1165],{"type":35,"value":1166},"else",{"type":30,"tag":118,"props":1168,"children":1169},{"style":385},[1170],{"type":35,"value":1171},":\n",{"type":30,"tag":118,"props":1173,"children":1174},{"class":120,"line":182},[1175,1179,1184,1188,1192],{"type":30,"tag":118,"props":1176,"children":1177},{"style":144},[1178],{"type":35,"value":1139},{"type":30,"tag":118,"props":1180,"children":1181},{"style":1103},[1182],{"type":35,"value":1183}," legacy_checkout_flow",{"type":30,"tag":118,"props":1185,"children":1186},{"style":385},[1187],{"type":35,"value":1111},{"type":30,"tag":118,"props":1189,"children":1190},{"style":379},[1191],{"type":35,"value":1153},{"type":30,"tag":118,"props":1193,"children":1194},{"style":385},[1195],{"type":35,"value":1158},{"type":30,"tag":31,"props":1197,"children":1198},{},[1199],{"type":35,"value":1200},"Le signal d'alerte est simple : si vos branches vivent plus de 2 jours, vous ne pratiquez pas la CI : vous faites du \"integrate when done.\"",{"type":30,"tag":52,"props":1202,"children":1203},{},[],{"type":30,"tag":56,"props":1205,"children":1207},{"id":1206},"fondamental-2-le-pipeline-de-build-doit-passer-en-moins-de-10-minutes",[1208],{"type":35,"value":1209},"Fondamental 2 : Le pipeline de build doit passer en moins de 10 minutes",{"type":30,"tag":31,"props":1211,"children":1212},{},[1213],{"type":35,"value":1214},"Si le feedback du pipeline prend plus de 10 minutes, les développeurs arrêtent d'attendre le résultat avant de passer à la tâche suivante. Le feedback loop se rompt.",{"type":30,"tag":31,"props":1216,"children":1217},{},[1218],{"type":35,"value":1219},"Cette règle vient des recherches sur la productivité des développeurs : au-delà de 10 minutes, le développeur a changé de contexte mental. Quand le pipeline échoue 15 minutes plus tard, le coût de retour au contexte est élevé.",{"type":30,"tag":31,"props":1221,"children":1222},{},[1223],{"type":35,"value":1224},"Pour maintenir un pipeline sous 10 minutes : tests unitaires en parallèle, tests d'intégration sélectifs basés sur les changements, cache agressif des dépendances, et séparation en stages, avec un fast feedback en moins de 5 minutes et un slow feedback déclenché séparément.",{"type":30,"tag":107,"props":1226,"children":1230},{"className":1227,"code":1228,"language":1229,"meta":8,"style":8},"language-yaml shiki shiki-themes catppuccin-frappe github-dark","# GitHub Actions - jobs parallèles\njobs:\n  unit-tests:\n    runs-on: ubuntu-latest\n    steps:\n      - run: npm run test:unit    # \u003C 3 min\n\n  lint-typecheck:\n    runs-on: ubuntu-latest\n    steps:\n      - run: npm run lint && npm run typecheck    # \u003C 2 min\n\n  integration-tests:\n    needs: [unit-tests]    # Seulement si les unit tests passent\n    runs-on: ubuntu-latest\n    steps:\n      - run: npm run test:integration    # \u003C 10 min\n","yaml",[1231],{"type":30,"tag":114,"props":1232,"children":1233},{"__ignoreMap":8},[1234,1242,1255,1267,1285,1297,1324,1331,1343,1358,1369,1394,1401,1413,1445,1460,1471],{"type":30,"tag":118,"props":1235,"children":1236},{"class":120,"line":121},[1237],{"type":30,"tag":118,"props":1238,"children":1239},{"style":125},[1240],{"type":35,"value":1241},"# GitHub Actions - jobs parallèles\n",{"type":30,"tag":118,"props":1243,"children":1244},{"class":120,"line":131},[1245,1251],{"type":30,"tag":118,"props":1246,"children":1248},{"style":1247},"--shiki-default:#8CAAEE;--shiki-dark:#85E89D",[1249],{"type":35,"value":1250},"jobs",{"type":30,"tag":118,"props":1252,"children":1253},{"style":367},[1254],{"type":35,"value":1171},{"type":30,"tag":118,"props":1256,"children":1257},{"class":120,"line":140},[1258,1263],{"type":30,"tag":118,"props":1259,"children":1260},{"style":1247},[1261],{"type":35,"value":1262},"  unit-tests",{"type":30,"tag":118,"props":1264,"children":1265},{"style":367},[1266],{"type":35,"value":1171},{"type":30,"tag":118,"props":1268,"children":1269},{"class":120,"line":173},[1270,1275,1280],{"type":30,"tag":118,"props":1271,"children":1272},{"style":1247},[1273],{"type":35,"value":1274},"    runs-on",{"type":30,"tag":118,"props":1276,"children":1277},{"style":367},[1278],{"type":35,"value":1279},":",{"type":30,"tag":118,"props":1281,"children":1282},{"style":167},[1283],{"type":35,"value":1284}," ubuntu-latest\n",{"type":30,"tag":118,"props":1286,"children":1287},{"class":120,"line":182},[1288,1293],{"type":30,"tag":118,"props":1289,"children":1290},{"style":1247},[1291],{"type":35,"value":1292},"    steps",{"type":30,"tag":118,"props":1294,"children":1295},{"style":367},[1296],{"type":35,"value":1171},{"type":30,"tag":118,"props":1298,"children":1299},{"class":120,"line":190},[1300,1305,1310,1314,1319],{"type":30,"tag":118,"props":1301,"children":1302},{"style":385},[1303],{"type":35,"value":1304},"      -",{"type":30,"tag":118,"props":1306,"children":1307},{"style":1247},[1308],{"type":35,"value":1309}," run",{"type":30,"tag":118,"props":1311,"children":1312},{"style":367},[1313],{"type":35,"value":1279},{"type":30,"tag":118,"props":1315,"children":1316},{"style":167},[1317],{"type":35,"value":1318}," npm run test:unit",{"type":30,"tag":118,"props":1320,"children":1321},{"style":125},[1322],{"type":35,"value":1323},"    # \u003C 3 min\n",{"type":30,"tag":118,"props":1325,"children":1326},{"class":120,"line":199},[1327],{"type":30,"tag":118,"props":1328,"children":1329},{"emptyLinePlaceholder":13},[1330],{"type":35,"value":137},{"type":30,"tag":118,"props":1332,"children":1333},{"class":120,"line":208},[1334,1339],{"type":30,"tag":118,"props":1335,"children":1336},{"style":1247},[1337],{"type":35,"value":1338},"  lint-typecheck",{"type":30,"tag":118,"props":1340,"children":1341},{"style":367},[1342],{"type":35,"value":1171},{"type":30,"tag":118,"props":1344,"children":1345},{"class":120,"line":216},[1346,1350,1354],{"type":30,"tag":118,"props":1347,"children":1348},{"style":1247},[1349],{"type":35,"value":1274},{"type":30,"tag":118,"props":1351,"children":1352},{"style":367},[1353],{"type":35,"value":1279},{"type":30,"tag":118,"props":1355,"children":1356},{"style":167},[1357],{"type":35,"value":1284},{"type":30,"tag":118,"props":1359,"children":1360},{"class":120,"line":225},[1361,1365],{"type":30,"tag":118,"props":1362,"children":1363},{"style":1247},[1364],{"type":35,"value":1292},{"type":30,"tag":118,"props":1366,"children":1367},{"style":367},[1368],{"type":35,"value":1171},{"type":30,"tag":118,"props":1370,"children":1371},{"class":120,"line":234},[1372,1376,1380,1384,1389],{"type":30,"tag":118,"props":1373,"children":1374},{"style":385},[1375],{"type":35,"value":1304},{"type":30,"tag":118,"props":1377,"children":1378},{"style":1247},[1379],{"type":35,"value":1309},{"type":30,"tag":118,"props":1381,"children":1382},{"style":367},[1383],{"type":35,"value":1279},{"type":30,"tag":118,"props":1385,"children":1386},{"style":167},[1387],{"type":35,"value":1388}," npm run lint && npm run typecheck",{"type":30,"tag":118,"props":1390,"children":1391},{"style":125},[1392],{"type":35,"value":1393},"    # \u003C 2 min\n",{"type":30,"tag":118,"props":1395,"children":1396},{"class":120,"line":243},[1397],{"type":30,"tag":118,"props":1398,"children":1399},{"emptyLinePlaceholder":13},[1400],{"type":35,"value":137},{"type":30,"tag":118,"props":1402,"children":1403},{"class":120,"line":252},[1404,1409],{"type":30,"tag":118,"props":1405,"children":1406},{"style":1247},[1407],{"type":35,"value":1408},"  integration-tests",{"type":30,"tag":118,"props":1410,"children":1411},{"style":367},[1412],{"type":35,"value":1171},{"type":30,"tag":118,"props":1414,"children":1415},{"class":120,"line":261},[1416,1421,1425,1430,1435,1440],{"type":30,"tag":118,"props":1417,"children":1418},{"style":1247},[1419],{"type":35,"value":1420},"    needs",{"type":30,"tag":118,"props":1422,"children":1423},{"style":367},[1424],{"type":35,"value":1279},{"type":30,"tag":118,"props":1426,"children":1427},{"style":385},[1428],{"type":35,"value":1429}," [",{"type":30,"tag":118,"props":1431,"children":1432},{"style":167},[1433],{"type":35,"value":1434},"unit-tests",{"type":30,"tag":118,"props":1436,"children":1437},{"style":385},[1438],{"type":35,"value":1439},"]",{"type":30,"tag":118,"props":1441,"children":1442},{"style":125},[1443],{"type":35,"value":1444},"    # Seulement si les unit tests passent\n",{"type":30,"tag":118,"props":1446,"children":1447},{"class":120,"line":270},[1448,1452,1456],{"type":30,"tag":118,"props":1449,"children":1450},{"style":1247},[1451],{"type":35,"value":1274},{"type":30,"tag":118,"props":1453,"children":1454},{"style":367},[1455],{"type":35,"value":1279},{"type":30,"tag":118,"props":1457,"children":1458},{"style":167},[1459],{"type":35,"value":1284},{"type":30,"tag":118,"props":1461,"children":1462},{"class":120,"line":279},[1463,1467],{"type":30,"tag":118,"props":1464,"children":1465},{"style":1247},[1466],{"type":35,"value":1292},{"type":30,"tag":118,"props":1468,"children":1469},{"style":367},[1470],{"type":35,"value":1171},{"type":30,"tag":118,"props":1472,"children":1473},{"class":120,"line":287},[1474,1478,1482,1486,1491],{"type":30,"tag":118,"props":1475,"children":1476},{"style":385},[1477],{"type":35,"value":1304},{"type":30,"tag":118,"props":1479,"children":1480},{"style":1247},[1481],{"type":35,"value":1309},{"type":30,"tag":118,"props":1483,"children":1484},{"style":367},[1485],{"type":35,"value":1279},{"type":30,"tag":118,"props":1487,"children":1488},{"style":167},[1489],{"type":35,"value":1490}," npm run test:integration",{"type":30,"tag":118,"props":1492,"children":1493},{"style":125},[1494],{"type":35,"value":1495},"    # \u003C 10 min\n",{"type":30,"tag":568,"props":1497,"children":1501},{"cta":1498,"href":1499,"title":1500,"type":573},"Révéler les angles morts de mon équipe →","https:\u002F\u002Fapp.kamanga.fr\u002Fforms\u002Fdiscovery-call","Votre CI est verte, mais votre équipe intègre-t-elle vraiment plusieurs fois par jour ?",[1502],{"type":30,"tag":31,"props":1503,"children":1504},{},[1505],{"type":35,"value":1506},"La vraie maturité CI ne se lit pas dans le statut du pipeline : elle se cache dans la durée de vie des branches, les builds rouges qu'on ignore et les rituels qui ont décroché. En 30 minutes de diagnostic centré sur votre équipe, je vous aide à voir ce que vos métriques de delivery ne capturent pas et à prioriser les 2-3 leviers qui rapprocheront votre flux d'une intégration vraiment continue.",{"type":30,"tag":52,"props":1508,"children":1509},{},[],{"type":30,"tag":56,"props":1511,"children":1513},{"id":1512},"fondamental-3-les-tests-cassés-sont-la-priorité-absolue",[1514],{"type":35,"value":1515},"Fondamental 3 : Les tests cassés sont la priorité absolue",{"type":30,"tag":31,"props":1517,"children":1518},{},[1519],{"type":35,"value":1520},"Quand le pipeline est rouge, réparer le trunk est la priorité numéro un de toute l'équipe, avant les nouvelles features, avant les code reviews en attente, avant les réunions.",{"type":30,"tag":31,"props":1522,"children":1523},{},[1524],{"type":35,"value":1525},"Cette règle s'appelle le \"stop the line\", empruntée au Toyota Production System (Jidoka). Dans le TPS, quand un problème est détecté sur la ligne de production, la ligne s'arrête jusqu'à ce que le problème soit résolu. En CI, le trunk cassé est la ligne arrêtée.",{"type":30,"tag":31,"props":1527,"children":1528},{},[1529],{"type":35,"value":1530},"En pratique : pipeline rouge → alerte immédiate à toute l'équipe via Slack et dashboard. La personne qui a cassé le trunk a 10 minutes pour proposer un fix ou reverter. Si pas de fix en 10 minutes : revert automatique ou manuel. Pas de nouveaux commits sur trunk tant qu'il est rouge.",{"type":30,"tag":31,"props":1532,"children":1533},{},[1534],{"type":35,"value":1535},"Ce qui arrive sans cette règle : les builds cassés s'accumulent, les développeurs ignorent les alertes, et le pipeline devient du décor plutôt qu'un signal utile. J'ai vu des équipes avec un pipeline rouge depuis 3 semaines : tout le monde avait arrêté de regarder.",{"type":30,"tag":52,"props":1537,"children":1538},{},[],{"type":30,"tag":56,"props":1540,"children":1542},{"id":1541},"fondamental-4-tout-le-monde-voit-létat-du-pipeline",[1543],{"type":35,"value":1544},"Fondamental 4 : Tout le monde voit l'état du pipeline",{"type":30,"tag":31,"props":1546,"children":1547},{},[1548],{"type":35,"value":1549},"L'état du pipeline doit être visible passivement par toute l'équipe, pas seulement quand quelqu'un pense à aller le vérifier.",{"type":30,"tag":31,"props":1551,"children":1552},{},[1553],{"type":35,"value":1554},"Les mécanismes de visibilité : dashboard de build sur un écran visible dans l'espace de travail, notification Slack dans le canal de l'équipe (pas seulement à la personne qui a pushé), badge de statut sur le README du repo, statut visible dans l'IDE.",{"type":30,"tag":31,"props":1556,"children":1557},{},[1558],{"type":35,"value":1559},"La différence entre \"notification opt-in\" et \"visibilité passive\" est fondamentale : si le développeur doit aller chercher l'information, il ne le fera pas systématiquement. La visibilité passive crée une conscience collective de l'état de la CI sans effort individuel.",{"type":30,"tag":52,"props":1561,"children":1562},{},[],{"type":30,"tag":56,"props":1564,"children":1566},{"id":1565},"fondamental-5-les-tests-sont-la-définition-de-trunk-en-bonne-santé",[1567],{"type":35,"value":1568},"Fondamental 5 : Les tests sont la définition de \"trunk en bonne santé\"",{"type":30,"tag":31,"props":1570,"children":1571},{},[1572,1574,1580],{"type":35,"value":1573},"Les tests automatisés définissent ce que \"trunk en bonne santé\" signifie : intégrez ce critère dans votre ",{"type":30,"tag":454,"props":1575,"children":1577},{"href":1576},"\u002Ffr\u002Fdette-technique\u002Fdefinition-of-done-qualite",[1578],{"type":35,"value":1579},"Definition of Done",{"type":35,"value":1581},". Si un comportement n'est pas testé, la CI ne peut pas le protéger.",{"type":30,"tag":31,"props":1583,"children":1584},{},[1585],{"type":35,"value":1586},"La pyramide de tests en CI définit la structure optimale :",{"type":30,"tag":1588,"props":1589,"children":1590},"ul",{},[1591,1602,1616],{"type":30,"tag":1592,"props":1593,"children":1594},"li",{},[1595,1600],{"type":30,"tag":46,"props":1596,"children":1597},{},[1598],{"type":35,"value":1599},"Tests unitaires",{"type":35,"value":1601}," (70-80% des tests) : rapides, sans dépendances externes. Feedback en moins de 2 minutes.",{"type":30,"tag":1592,"props":1603,"children":1604},{},[1605,1614],{"type":30,"tag":46,"props":1606,"children":1607},{},[1608],{"type":30,"tag":454,"props":1609,"children":1611},{"href":1610},"\u002Ffr\u002Fdette-technique\u002Ftests-integration-legacy-pieges",[1612],{"type":35,"value":1613},"Tests d'intégration",{"type":35,"value":1615}," (15-20% des tests) : avec base de données ou services externes. Feedback en moins de 8 minutes.",{"type":30,"tag":1592,"props":1617,"children":1618},{},[1619,1624],{"type":30,"tag":46,"props":1620,"children":1621},{},[1622],{"type":35,"value":1623},"Tests end-to-end",{"type":35,"value":1625}," (5-10% des tests) : sur les flux critiques uniquement. Déclenchés moins fréquemment.",{"type":30,"tag":31,"props":1627,"children":1628},{},[1629],{"type":35,"value":1630},"Un pipeline vert ne garantit pas que le logiciel est correct : il garantit qu'il est cohérent avec ses tests. La qualité des tests détermine la qualité du signal.",{"type":30,"tag":52,"props":1632,"children":1633},{},[],{"type":30,"tag":56,"props":1635,"children":1637},{"id":1636},"ce-que-ça-change-concrètement",[1638],{"type":35,"value":1639},"Ce que ça change concrètement",{"type":30,"tag":31,"props":1641,"children":1642},{},[1643],{"type":35,"value":1644},"Dans l'équipe mentionnée en introduction, après 6 semaines de travail sur les 5 fondamentaux (parallélisation des tests, feature flags systématiques, règle du stop the line, dashboard visible, refonte de la pyramide de tests), le résultat était mesurable. Le pipeline est passé de 28 minutes à 8 minutes. La durée des branches est passée de 4 jours à 18 heures. Le lead time de delivery a baissé de 40%.",{"type":30,"tag":31,"props":1646,"children":1647},{},[1648],{"type":35,"value":1649},"Aucun recrutement. Aucun changement de framework. Seulement des pratiques humaines appliquées avec discipline.",{"type":30,"tag":31,"props":1651,"children":1652},{},[1653,1655,1661],{"type":35,"value":1654},"Les métriques de maturité CI à suivre (ces indicateurs font partie des ",{"type":30,"tag":454,"props":1656,"children":1658},{"href":1657},"\u002Ffr\u002Fmanagement\u002Fmetriques-management-developpeurs-motivation",[1659],{"type":35,"value":1660},"4 métriques DORA",{"type":35,"value":1662},") : fréquence d'intégration par développeur (cible : plus de 2 fois par jour), MTTR du pipeline en cas de rupture (cible : moins de 30 minutes), durée du pipeline en p95 (cible : moins de 10 minutes), taux de flakiness des tests (cible : moins de 5%).",{"type":30,"tag":52,"props":1664,"children":1665},{},[],{"type":30,"tag":56,"props":1667,"children":1669},{"id":1668},"faq-sur-la-continuous-integration",[1670],{"type":35,"value":1671},"FAQ sur la Continuous Integration",{"type":30,"tag":826,"props":1673,"children":1674},{},[1675,1680],{"type":30,"tag":830,"props":1676,"children":1677},{},[1678],{"type":35,"value":1679},"1. Quelle est la différence entre CI et CD (Continuous Delivery \u002F Deployment) ?",{"type":30,"tag":31,"props":1681,"children":1682},{},[1683],{"type":35,"value":1684},"La CI est l'intégration fréquente du code dans le trunk avec vérification automatique. La CD (Delivery) est la capacité à déployer n'importe quel commit en production de façon fiable à tout moment. La CD (Deployment) est le déploiement automatique de chaque commit qui passe la CI. La CI est un prérequis à la CD. On peut pratiquer la CI sans CD, mais pas l'inverse de façon viable.",{"type":30,"tag":826,"props":1686,"children":1687},{},[1688,1693],{"type":30,"tag":830,"props":1689,"children":1690},{},[1691],{"type":35,"value":1692},"2. Comment convaincre une équipe de passer des feature branches longues aux intégrations quotidiennes ?",{"type":30,"tag":31,"props":1694,"children":1695},{},[1696],{"type":35,"value":1697},"Par la data. Calculer le temps moyen passé à résoudre les conflits de merge sur les 3 derniers mois. Dans la plupart des équipes avec des branches de 1-2 semaines, les merge conflicts représentent 10 à 15% du temps de développement. Proposer un pilote de 4 sprints avec des branches courtes et feature flags, et mesurer. Le résultat parle de lui-même.",{"type":30,"tag":826,"props":1699,"children":1700},{},[1701,1706],{"type":30,"tag":830,"props":1702,"children":1703},{},[1704],{"type":35,"value":1705},"3. Les feature flags créent-ils une dette technique ?",{"type":30,"tag":31,"props":1707,"children":1708},{},[1709],{"type":35,"value":1710},"Oui, si mal gérés. Un feature flag non supprimé après le lancement de la feature est de la dette. La règle : chaque feature flag a une date d'expiration définie au moment de sa création. Un linter ou un test automatique vérifie que les flags expirés sont supprimés. En pratique, un backlog dédié à la suppression des flags (2 à 3 par sprint) suffit pour maintenir le stock sous contrôle.",{"type":30,"tag":826,"props":1712,"children":1713},{},[1714,1719],{"type":30,"tag":830,"props":1715,"children":1716},{},[1717],{"type":35,"value":1718},"4. Comment gérer la CI dans un monorepo avec de nombreux services ?",{"type":30,"tag":31,"props":1720,"children":1721},{},[1722],{"type":35,"value":1723},"Avec des pipelines sélectifs basés sur les changements. Les outils comme Nx pour JavaScript\u002FTypeScript, Bazel pour les environnements multi-langages, ou les \"path filters\" dans GitHub Actions permettent de ne lancer que les tests des services impactés par les changements. Cela maintient un pipeline sous 10 minutes même dans un monorepo de 20 services.",{"type":30,"tag":826,"props":1725,"children":1726},{},[1727,1732],{"type":30,"tag":830,"props":1728,"children":1729},{},[1730],{"type":35,"value":1731},"5. Que faire quand les tests sont trop lents pour permettre une intégration quotidienne ?",{"type":30,"tag":31,"props":1733,"children":1734},{},[1735],{"type":35,"value":1736},"C'est le signal pour revoir la pyramide de tests. Audit en 3 étapes : identifier les 20% de tests les plus lents qui représentent 80% du temps, évaluer si ces tests d'intégration pourraient être remplacés par des tests unitaires avec mocks, puis déplacer les tests lents dans un stage séparé déclenché toutes les 2 heures. Le pipeline fast feedback reste sous 10 minutes, le reste se vérifie en continu.",{"type":30,"tag":52,"props":1738,"children":1739},{},[],{"type":30,"tag":568,"props":1741,"children":1744},{"cta":1742,"href":919,"title":1743,"type":921},"Télécharger le guide gratuit →","Ressource gratuite : Guide Lead Time -50% en 90 jours",[1745],{"type":30,"tag":31,"props":1746,"children":1747},{},[1748],{"type":35,"value":1749},"Le guide complet pour réduire votre lead time en 90 jours inclut un chapitre sur l'optimisation du pipeline CI\u002FCD et les pratiques d'intégration qui font la différence sur la fréquence de delivery, avec les métriques DORA à suivre.",{"type":30,"tag":929,"props":1751,"children":1752},{},[1753],{"type":35,"value":933},{"title":8,"searchDepth":131,"depth":131,"links":1755},[1756,1757,1758,1759,1760,1761,1762,1763],{"id":999,"depth":131,"text":1002},{"id":1048,"depth":131,"text":1051},{"id":1206,"depth":131,"text":1209},{"id":1512,"depth":131,"text":1515},{"id":1541,"depth":131,"text":1544},{"id":1565,"depth":131,"text":1568},{"id":1636,"depth":131,"text":1639},{"id":1668,"depth":131,"text":1671},"content:fr:pratiques-agiles:continuous-integration-fondamentaux.md","fr\u002Fpratiques-agiles\u002Fcontinuous-integration-fondamentaux.md","fr\u002Fpratiques-agiles\u002Fcontinuous-integration-fondamentaux",{"_path":1576,"_dir":1768,"_draft":7,"_partial":7,"_locale":8,"title":1769,"description":1770,"id":1771,"date":1772,"listed":13,"nocomments":7,"hidden":7,"categories":1773,"tags":1774,"cover":1776,"readingTime":1777,"body":1782,"_type":943,"_id":2400,"_source":945,"_file":2401,"_stem":2402,"_extension":948},"dette-technique","Définir une Definition of Done qui améliore vraiment la qualité","Une DoD vague produit une qualité vague. Comment construire une Definition of Done qui tient ses promesses et s'améliore dans le temps.",26,"2026-03-04",[1768],[1579,19,1775],"Agile","covers\u002Farticles\u002Fdefinition-of-done-qualite.jpg",{"text":1778,"minutes":1779,"time":1780,"words":1781},"8 min read",7.71,462600,1542,{"type":27,"children":1783,"toc":2390},[1784,1789,1797,1802,1805,1811,1829,1832,1838,1855,1860,1870,1888,1893,1903,1906,1912,1927,1932,1942,1952,1969,1979,1989,1999,2009,2018,2021,2030,2033,2039,2044,2054,2064,2074,2084,2093,2096,2102,2107,2117,2135,2148,2157,2160,2166,2175,2178,2184,2283,2286,2295,2298,2304,2317,2330,2351,2364,2377,2380],{"type":30,"tag":31,"props":1785,"children":1786},{},[1787],{"type":35,"value":1788},"Je me souviens d'une équipe dans une grande organisation de retraite complémentaire. Ils avaient une DoD, une vraie, écrite, affichée dans la salle. Je leur ai demandé comment elle était utilisée. Le Scrum Master a répondu avec un sourire gêné : \"En théorie, elle est vérifiée avant chaque merge. En pratique, en fin de sprint, on coche tout et on merge pour tenir le sprint.\" J'ai vérifié les métriques : 38% des bugs de prod de l'année précédente étaient apparus dans des stories \"Done\" selon la DoD de l'équipe. Ce n'était pas un problème de personnes. C'était un problème de contrat.",{"type":30,"tag":31,"props":1790,"children":1791},{},[1792],{"type":30,"tag":46,"props":1793,"children":1794},{},[1795],{"type":35,"value":1796},"La DoD la plus fréquente que je rencontre dans les équipes : \"Le code est mergé et testé.\" C'est une description, pas une Definition of Done. Et cette ambiguïté est directement responsable de 30 à 40% des bugs qui atteignent la production.",{"type":30,"tag":31,"props":1798,"children":1799},{},[1800],{"type":35,"value":1801},"La Definition of Done est le contrat de qualité de l'équipe. Quand elle est vague, chaque développeur l'interprète différemment. Quand elle est absente, la qualité dépend de la conscience professionnelle individuelle, ce qui est insuffisant pour garantir la cohérence.",{"type":30,"tag":52,"props":1803,"children":1804},{},[],{"type":30,"tag":56,"props":1806,"children":1808},{"id":1807},"avant-de-commencer-les-prérequis",[1809],{"type":35,"value":1810},"Avant de commencer : les prérequis",{"type":30,"tag":1588,"props":1812,"children":1813},{},[1814,1819,1824],{"type":30,"tag":1592,"props":1815,"children":1816},{},[1817],{"type":35,"value":1818},"L'équipe a déjà une DoD existante (même minimale ou informelle) à partir de laquelle progresser",{"type":30,"tag":1592,"props":1820,"children":1821},{},[1822],{"type":35,"value":1823},"Le Product Owner et le Tech Lead sont impliqués dans la redéfinition",{"type":30,"tag":1592,"props":1825,"children":1826},{},[1827],{"type":35,"value":1828},"L'équipe a accès aux métriques de base : taux de bugs de prod, lead time, incidents récents",{"type":30,"tag":52,"props":1830,"children":1831},{},[],{"type":30,"tag":56,"props":1833,"children":1835},{"id":1834},"étape-1-auditer-la-dod-actuelle-ou-son-absence",[1836],{"type":35,"value":1837},"Étape 1 : Auditer la DoD actuelle (ou son absence)",{"type":30,"tag":31,"props":1839,"children":1840},{},[1841,1846,1848,1853],{"type":30,"tag":46,"props":1842,"children":1843},{},[1844],{"type":35,"value":1845},"Durée estimée",{"type":35,"value":1847}," : 2 heures en atelier équipe\n",{"type":30,"tag":46,"props":1849,"children":1850},{},[1851],{"type":35,"value":1852},"Qui",{"type":35,"value":1854}," : Toute l'équipe de développement + PO + Scrum Master",{"type":30,"tag":31,"props":1856,"children":1857},{},[1858],{"type":35,"value":1859},"Avant de construire une nouvelle DoD, comprendre pourquoi l'actuelle ne fonctionne pas.",{"type":30,"tag":31,"props":1861,"children":1862},{},[1863,1868],{"type":30,"tag":46,"props":1864,"children":1865},{},[1866],{"type":35,"value":1867},"Questions à poser en atelier",{"type":35,"value":1869}," :",{"type":30,"tag":1588,"props":1871,"children":1872},{},[1873,1878,1883],{"type":30,"tag":1592,"props":1874,"children":1875},{},[1876],{"type":35,"value":1877},"\"Quand considérez-vous qu'une story est vraiment terminée ?\" Recueillir les réponses individuelles avant la discussion.",{"type":30,"tag":1592,"props":1879,"children":1880},{},[1881],{"type":35,"value":1882},"\"Citez un bug récent de prod : quelle étape de la DoD aurait dû le détecter ?\"",{"type":30,"tag":1592,"props":1884,"children":1885},{},[1886],{"type":35,"value":1887},"\"Y a-t-il des items de notre DoD actuelle que personne ne vérifie vraiment ?\"",{"type":30,"tag":31,"props":1889,"children":1890},{},[1891],{"type":35,"value":1892},"Le dernier exercice est le plus révélateur. Dans 80% des équipes que j'accompagne, il existe des items \"fantômes\" dans la DoD : des critères formellement présents mais systématiquement contournés, généralement par manque de temps en fin de sprint.",{"type":30,"tag":31,"props":1894,"children":1895},{},[1896,1901],{"type":30,"tag":46,"props":1897,"children":1898},{},[1899],{"type":35,"value":1900},"Résultat attendu",{"type":35,"value":1902}," : une liste de ce qui fonctionne, ce qui est contourné, et ce qui manque.",{"type":30,"tag":52,"props":1904,"children":1905},{},[],{"type":30,"tag":56,"props":1907,"children":1909},{"id":1908},"étape-2-les-7-critères-non-négociables-dune-dod-solide",[1910],{"type":35,"value":1911},"Étape 2 : Les 7 critères non-négociables d'une DoD solide",{"type":30,"tag":31,"props":1913,"children":1914},{},[1915,1919,1921,1925],{"type":30,"tag":46,"props":1916,"children":1917},{},[1918],{"type":35,"value":1845},{"type":35,"value":1920}," : 1 heure de discussion\n",{"type":30,"tag":46,"props":1922,"children":1923},{},[1924],{"type":35,"value":1852},{"type":35,"value":1926}," : Tech Lead + PO",{"type":30,"tag":31,"props":1928,"children":1929},{},[1930],{"type":35,"value":1931},"Ces 7 critères sont le minimum pour une DoD qui protège réellement la qualité. Adaptez le wording à votre contexte, mais ne supprimez pas les catégories.",{"type":30,"tag":31,"props":1933,"children":1934},{},[1935,1940],{"type":30,"tag":46,"props":1936,"children":1937},{},[1938],{"type":35,"value":1939},"1. Code reviewé par au moins un pair",{"type":35,"value":1941},"\nPas \"par le Tech Lead si disponible\". Par n'importe quel pair, avec un retour documenté dans la PR. Spécifier le délai maximum : aucune PR ne reste sans review plus de 24 heures ouvrées.",{"type":30,"tag":31,"props":1943,"children":1944},{},[1945,1950],{"type":30,"tag":46,"props":1946,"children":1947},{},[1948],{"type":35,"value":1949},"2. Tests automatisés écrits ou mis à jour",{"type":35,"value":1951},"\nSpécifier le type : tests unitaires pour la logique, tests d'intégration pour les interactions avec les dépendances. Spécifier le seuil : la couverture du module ne descend pas en dessous du seuil de l'équipe.",{"type":30,"tag":31,"props":1953,"children":1954},{},[1955,1967],{"type":30,"tag":46,"props":1956,"children":1957},{},[1958,1960,1965],{"type":35,"value":1959},"3. ",{"type":30,"tag":454,"props":1961,"children":1962},{"href":950},[1963],{"type":35,"value":1964},"Build CI",{"type":35,"value":1966}," vert sur la branche",{"type":35,"value":1968},"\nÉvident mais souvent contourné \"pour gagner du temps\". Un build rouge = story non terminée, sans exception.",{"type":30,"tag":31,"props":1970,"children":1971},{},[1972,1977],{"type":30,"tag":46,"props":1973,"children":1974},{},[1975],{"type":35,"value":1976},"4. Critères d'acceptation vérifiés et documentés",{"type":35,"value":1978},"\nChaque critère d'acceptation de la story doit avoir été testé manuellement ou automatiquement. Le résultat est documenté dans le ticket.",{"type":30,"tag":31,"props":1980,"children":1981},{},[1982,1987],{"type":30,"tag":46,"props":1983,"children":1984},{},[1985],{"type":35,"value":1986},"5. Pas de régression identifiée sur les scénarios existants",{"type":35,"value":1988},"\nUne suite de tests de régression tourne sur chaque PR. Si elle n'existe pas, c'est un déficit à combler progressivement, mais c'est un objectif de la DoD.",{"type":30,"tag":31,"props":1990,"children":1991},{},[1992,1997],{"type":30,"tag":46,"props":1993,"children":1994},{},[1995],{"type":35,"value":1996},"6. Documentation mise à jour si applicable",{"type":35,"value":1998},"\nPas de documentation pour chaque story. Mais si la story modifie une API publique, un flux d'intégration, ou une règle métier documentée, la documentation est mise à jour dans la même PR.",{"type":30,"tag":31,"props":2000,"children":2001},{},[2002,2007],{"type":30,"tag":46,"props":2003,"children":2004},{},[2005],{"type":35,"value":2006},"7. Déployable en environnement de staging sans intervention manuelle",{"type":35,"value":2008},"\nLa story doit pouvoir être déployée en staging en appuyant sur un bouton. Si un déploiement nécessite des étapes manuelles, c'est une dette technique à documenter et traiter.",{"type":30,"tag":31,"props":2010,"children":2011},{},[2012,2016],{"type":30,"tag":46,"props":2013,"children":2014},{},[2015],{"type":35,"value":1900},{"type":35,"value":2017}," : une DoD de 7 items précis et actionnables.",{"type":30,"tag":52,"props":2019,"children":2020},{},[],{"type":30,"tag":568,"props":2022,"children":2024},{"cta":570,"href":571,"title":2023,"type":573},"Vous voulez savoir reconnaître le code qui n'est pas vraiment terminé, avant de le merger ?",[2025],{"type":30,"tag":31,"props":2026,"children":2027},{},[2028],{"type":35,"value":2029},"Juger si une PR est réellement \"Done\", ça ne se déduit pas d'une checklist : ça s'apprend à l'oeil, sur du vrai code. En mentoring 1:1, je relis vos PR avec vous et je vous montre ce qui manque (tests qui ne testent rien, cas limites oubliés, régressions silencieuses). Vous repartez avec le réflexe de voir ce qu'une DoD ne capture pas.",{"type":30,"tag":52,"props":2031,"children":2032},{},[],{"type":30,"tag":56,"props":2034,"children":2036},{"id":2035},"étape-3-lintégrer-dans-le-workflow-sans-friction",[2037],{"type":35,"value":2038},"Étape 3 : L'intégrer dans le workflow sans friction",{"type":30,"tag":31,"props":2040,"children":2041},{},[2042],{"type":35,"value":2043},"Une DoD que personne ne consulte n'existe pas. Elle doit être au bon endroit, au bon moment.",{"type":30,"tag":31,"props":2045,"children":2046},{},[2047,2052],{"type":30,"tag":46,"props":2048,"children":2049},{},[2050],{"type":35,"value":2051},"Dans Jira\u002FLinear",{"type":35,"value":2053}," : ajouter la DoD comme checklist dans le template de story. Chaque item est coché (et non supprimé) avant de passer au statut \"Done\". L'outil garde une trace.",{"type":30,"tag":31,"props":2055,"children":2056},{},[2057,2062],{"type":30,"tag":46,"props":2058,"children":2059},{},[2060],{"type":35,"value":2061},"Dans GitHub\u002FGitLab",{"type":35,"value":2063}," : créer un template de PR avec les items de la DoD comme checklist. Le développeur les coche au moment de la PR, pas après coup.",{"type":30,"tag":31,"props":2065,"children":2066},{},[2067,2072],{"type":30,"tag":46,"props":2068,"children":2069},{},[2070],{"type":35,"value":2071},"Dans le sprint review",{"type":35,"value":2073}," : le PO valide que les items de la DoD ont été respectés avant d'accepter la story. C'est le moment de fermeture du cycle qualité.",{"type":30,"tag":31,"props":2075,"children":2076},{},[2077,2082],{"type":30,"tag":46,"props":2078,"children":2079},{},[2080],{"type":35,"value":2081},"L'erreur à éviter",{"type":35,"value":2083}," : transformer la DoD en checklist bureaucratique que tout le monde coche sans vérifier. Pour éviter ça, j'inclus des items vérifiables de façon objective (build vert, coverage seuil) plutôt que subjectifs (\"le code est de qualité\").",{"type":30,"tag":31,"props":2085,"children":2086},{},[2087,2091],{"type":30,"tag":46,"props":2088,"children":2089},{},[2090],{"type":35,"value":1900},{"type":35,"value":2092}," : la DoD est intégrée dans les templates Jira et GitHub. Elle est visible au bon moment dans le workflow.",{"type":30,"tag":52,"props":2094,"children":2095},{},[],{"type":30,"tag":56,"props":2097,"children":2099},{"id":2098},"étape-4-la-faire-évoluer-chaque-trimestre",[2100],{"type":35,"value":2101},"Étape 4 : La faire évoluer chaque trimestre",{"type":30,"tag":31,"props":2103,"children":2104},{},[2105],{"type":35,"value":2106},"Une DoD figée devient rapidement soit trop laxiste (l'équipe a progressé et la DoD ne reflète plus ses standards actuels) soit trop contraignante (les outils ont changé et certains items ne s'appliquent plus).",{"type":30,"tag":31,"props":2108,"children":2109},{},[2110,2115],{"type":30,"tag":46,"props":2111,"children":2112},{},[2113],{"type":35,"value":2114},"Rituel recommandé",{"type":35,"value":2116}," : une session de 1 heure par trimestre, en même temps que le trimestrial planning, pour réviser la DoD :",{"type":30,"tag":1588,"props":2118,"children":2119},{},[2120,2125,2130],{"type":30,"tag":1592,"props":2121,"children":2122},{},[2123],{"type":35,"value":2124},"Quels items sont systématiquement respectés ? (→ potentiellement automatisables dans la CI)",{"type":30,"tag":1592,"props":2126,"children":2127},{},[2128],{"type":35,"value":2129},"Quels items sont régulièrement contournés ? (→ soit les supprimer, soit identifier pourquoi et lever le blocage)",{"type":30,"tag":1592,"props":2131,"children":2132},{},[2133],{"type":35,"value":2134},"Quels items manquent compte tenu des problèmes rencontrés ce trimestre ?",{"type":30,"tag":31,"props":2136,"children":2137},{},[2138,2140,2146],{"type":35,"value":2139},"L'objectif à 12-18 mois : une DoD qui contient des items d'un ",{"type":30,"tag":454,"props":2141,"children":2143},{"href":2142},"\u002Ffr\u002Fdette-technique\u002Fintroduction-maturite-engineering-5-niveaux",[2144],{"type":35,"value":2145},"niveau 3 de maturité engineering",{"type":35,"value":2147}," : les standards de qualité sont ancrés dans les pratiques de l'équipe, pas seulement dans un document.",{"type":30,"tag":31,"props":2149,"children":2150},{},[2151,2155],{"type":30,"tag":46,"props":2152,"children":2153},{},[2154],{"type":35,"value":1900},{"type":35,"value":2156}," : une DoD vivante, révisée trimestriellement, qui progresse avec le niveau de maturité de l'équipe.",{"type":30,"tag":52,"props":2158,"children":2159},{},[],{"type":30,"tag":56,"props":2161,"children":2163},{"id":2162},"le-piège-à-éviter",[2164],{"type":35,"value":2165},"Le piège à éviter",{"type":30,"tag":2167,"props":2168,"children":2169},"blockquote",{},[2170],{"type":30,"tag":31,"props":2171,"children":2172},{},[2173],{"type":35,"value":2174},"Ne jamais créer deux niveaux de DoD \"selon le temps disponible\". J'ai vu des équipes définir une \"DoD normale\" et une \"DoD express\" pour les sprints surchargés. Résultat : la DoD express devient la norme, et la DoD normale n'est jamais appliquée. Une seule DoD : si elle n'est pas atteignable, réduire le scope du sprint, pas les standards. C'est la discipline fondamentale d'un système agile sain.",{"type":30,"tag":52,"props":2176,"children":2177},{},[],{"type":30,"tag":56,"props":2179,"children":2181},{"id":2180},"en-résumé",[2182],{"type":35,"value":2183},"En résumé",{"type":30,"tag":634,"props":2185,"children":2186},{},[2187,2208],{"type":30,"tag":638,"props":2188,"children":2189},{},[2190],{"type":30,"tag":642,"props":2191,"children":2192},{},[2193,2198,2203],{"type":30,"tag":646,"props":2194,"children":2195},{},[2196],{"type":35,"value":2197},"Étape",{"type":30,"tag":646,"props":2199,"children":2200},{},[2201],{"type":35,"value":2202},"Action",{"type":30,"tag":646,"props":2204,"children":2205},{},[2206],{"type":35,"value":2207},"Résultat",{"type":30,"tag":657,"props":2209,"children":2210},{},[2211,2229,2247,2265],{"type":30,"tag":642,"props":2212,"children":2213},{},[2214,2219,2224],{"type":30,"tag":664,"props":2215,"children":2216},{},[2217],{"type":35,"value":2218},"1",{"type":30,"tag":664,"props":2220,"children":2221},{},[2222],{"type":35,"value":2223},"Auditer la DoD actuelle en atelier",{"type":30,"tag":664,"props":2225,"children":2226},{},[2227],{"type":35,"value":2228},"Identifier les items fantômes et les manques",{"type":30,"tag":642,"props":2230,"children":2231},{},[2232,2237,2242],{"type":30,"tag":664,"props":2233,"children":2234},{},[2235],{"type":35,"value":2236},"2",{"type":30,"tag":664,"props":2238,"children":2239},{},[2240],{"type":35,"value":2241},"Définir les 7 critères non-négociables",{"type":30,"tag":664,"props":2243,"children":2244},{},[2245],{"type":35,"value":2246},"DoD précise et actionnable",{"type":30,"tag":642,"props":2248,"children":2249},{},[2250,2255,2260],{"type":30,"tag":664,"props":2251,"children":2252},{},[2253],{"type":35,"value":2254},"3",{"type":30,"tag":664,"props":2256,"children":2257},{},[2258],{"type":35,"value":2259},"Intégrer dans Jira et GitHub",{"type":30,"tag":664,"props":2261,"children":2262},{},[2263],{"type":35,"value":2264},"DoD consultée au bon moment dans le workflow",{"type":30,"tag":642,"props":2266,"children":2267},{},[2268,2273,2278],{"type":30,"tag":664,"props":2269,"children":2270},{},[2271],{"type":35,"value":2272},"4",{"type":30,"tag":664,"props":2274,"children":2275},{},[2276],{"type":35,"value":2277},"Réviser chaque trimestre",{"type":30,"tag":664,"props":2279,"children":2280},{},[2281],{"type":35,"value":2282},"DoD qui progresse avec la maturité de l'équipe",{"type":30,"tag":52,"props":2284,"children":2285},{},[],{"type":30,"tag":568,"props":2287,"children":2289},{"cta":806,"href":807,"title":2288,"type":809},"Une DoD solide, c'est une pratique parmi 100 autres qui font le code propre",[2290],{"type":30,"tag":31,"props":2291,"children":2292},{},[2293],{"type":35,"value":2294},"Définir une Definition of Done qui tient vraiment, c'est un seul réflexe de craft parmi beaucoup d'autres. Le Craft Bundle réunit les 100 pratiques que j'applique au quotidien pour coder propre, de la revue de code au découpage de stories, celles que l'IA ne vous apprendra jamais parce qu'elle ne les a jamais vues protéger une mise en prod.",{"type":30,"tag":52,"props":2296,"children":2297},{},[],{"type":30,"tag":56,"props":2299,"children":2301},{"id":2300},"faq-sur-la-definition-of-done",[2302],{"type":35,"value":2303},"FAQ sur la Definition of Done",{"type":30,"tag":826,"props":2305,"children":2306},{},[2307,2312],{"type":30,"tag":830,"props":2308,"children":2309},{},[2310],{"type":35,"value":2311},"1. Quelle est la différence entre la DoD et les critères d'acceptation ?",{"type":30,"tag":31,"props":2313,"children":2314},{},[2315],{"type":35,"value":2316},"Les critères d'acceptation sont spécifiques à une story : ils décrivent ce que cette story particulière doit faire. La DoD est transversale à toutes les stories : elle décrit les standards de qualité qui s'appliquent à toute livraison, quelles que soient les fonctionnalités. Une story peut respecter tous ses critères d'acceptation et ne pas respecter la DoD (ex : pas de tests écrits, code non reviewé).",{"type":30,"tag":826,"props":2318,"children":2319},{},[2320,2325],{"type":30,"tag":830,"props":2321,"children":2322},{},[2323],{"type":35,"value":2324},"2. La DoD doit-elle être la même pour tous les types de stories ?",{"type":30,"tag":31,"props":2326,"children":2327},{},[2328],{"type":35,"value":2329},"Généralement oui, avec des nuances légères. Certains items peuvent être contextuels (la documentation n'est pas mise à jour pour une story de refactoring interne). Mais les items fondamentaux (code reviewé, build vert, tests écrits) s'appliquent à toutes les stories sans exception. Trop d'exceptions crée de l'ambiguïté et ouvre la porte aux contournements.",{"type":30,"tag":826,"props":2331,"children":2332},{},[2333,2338],{"type":30,"tag":830,"props":2334,"children":2335},{},[2336],{"type":35,"value":2337},"3. Comment gérer la résistance de l'équipe à une DoD plus stricte ?",{"type":30,"tag":31,"props":2339,"children":2340},{},[2341,2343,2349],{"type":35,"value":2342},"La résistance vient généralement de la peur que la DoD crée un blocage en fin de sprint. La réponse est de traiter la cause : si la DoD ne peut pas être respectée dans un sprint, le problème est en amont (stories trop grandes, ",{"type":30,"tag":454,"props":2344,"children":2346},{"href":2345},"\u002Ffr\u002Fpratiques-agiles\u002Fdefinition-of-ready-bugs-sprint",[2347],{"type":35,"value":2348},"Definition of Ready absente",{"type":35,"value":2350},", capacité surestimée) pas dans la DoD elle-même. Impliquer l'équipe dans la rédaction de la DoD réduit significativement la résistance à son application.",{"type":30,"tag":826,"props":2352,"children":2353},{},[2354,2359],{"type":30,"tag":830,"props":2355,"children":2356},{},[2357],{"type":35,"value":2358},"4. Faut-il une DoD différente par équipe dans une organisation avec plusieurs équipes ?",{"type":30,"tag":31,"props":2360,"children":2361},{},[2362],{"type":35,"value":2363},"Une base commune + des extensions par équipe est la meilleure approche. La base commune garantit un niveau minimum de qualité cohérent à travers l'organisation, particulièrement important pour les composants partagés. Les extensions permettent aux équipes d'adapter aux spécificités de leur contexte (ex : une équipe data peut avoir des items spécifiques sur la validation des schémas).",{"type":30,"tag":826,"props":2365,"children":2366},{},[2367,2372],{"type":30,"tag":830,"props":2368,"children":2369},{},[2370],{"type":35,"value":2371},"5. Comment mesurer si la DoD améliore réellement la qualité ?",{"type":30,"tag":31,"props":2373,"children":2374},{},[2375],{"type":35,"value":2376},"Trois métriques à suivre avant\u002Faprès l'amélioration de la DoD : le taux de bugs de prod sur les stories \"Done\" (doit baisser), le nombre de réouvertures de tickets (doit baisser), et le temps passé en correction de bugs vs développement de features (doit s'améliorer). Sur les équipes que j'accompagne, une DoD bien appliquée réduit le taux de bugs de prod de 25 à 40% en 3 mois.",{"type":30,"tag":52,"props":2378,"children":2379},{},[],{"type":30,"tag":568,"props":2381,"children":2384},{"cta":2382,"href":919,"title":2383,"type":921},"Accéder à l'assessment gratuit →","Ressource gratuite : Engineering Maturity Self-Assessment",[2385],{"type":30,"tag":31,"props":2386,"children":2387},{},[2388],{"type":35,"value":2389},"L'assessment évalue vos pratiques de qualité, incluant la Definition of Done, les pratiques de tests et de revue de code. Identifiez votre niveau actuel et les 3 actions prioritaires pour progresser.",{"title":8,"searchDepth":131,"depth":131,"links":2391},[2392,2393,2394,2395,2396,2397,2398,2399],{"id":1807,"depth":131,"text":1810},{"id":1834,"depth":131,"text":1837},{"id":1908,"depth":131,"text":1911},{"id":2035,"depth":131,"text":2038},{"id":2098,"depth":131,"text":2101},{"id":2162,"depth":131,"text":2165},{"id":2180,"depth":131,"text":2183},{"id":2300,"depth":131,"text":2303},"content:fr:dette-technique:definition-of-done-qualite.md","fr\u002Fdette-technique\u002Fdefinition-of-done-qualite.md","fr\u002Fdette-technique\u002Fdefinition-of-done-qualite",{"_path":746,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":2404,"description":2405,"id":341,"date":2406,"listed":13,"nocomments":7,"hidden":7,"categories":2407,"tags":2408,"cover":2412,"readingTime":2413,"body":2417,"_type":943,"_id":3901,"_source":945,"_file":3902,"_stem":3903,"_extension":948},"Tester du code généré par l'IA : la checklist en 12 points","Le code généré par l'IA passe les tests syntaxiques et rate les tests de logique métier. Une checklist pour valider du code IA avant de le merger.","2026-02-25",[6],[2409,2410,19,2411],"Tests","Code IA","Checklist","covers\u002Farticles\u002Ftester-code-ia-checklist.jpg",{"text":963,"minutes":2414,"time":2415,"words":2416},8.55,513000,1710,{"type":27,"children":2418,"toc":3893},[2419,2432,2437,2452,2455,2461,2495,2507,2510,2516,2524,2529,2549,2557,2562,2585,2593,2598,2606,2611,2620,2623,2629,2637,2642,2650,2655,2668,3036,3044,3049,3057,3062,3088,3091,3097,3105,3110,3611,3619,3632,3640,3645,3653,3661,3666,3669,3675,3692,3702,3712,3715,3794,3803,3806,3812,3825,3838,3851,3864,3877,3880,3889],{"type":30,"tag":31,"props":2420,"children":2421},{},[2422,2424,2430],{"type":35,"value":2423},"En développant crmcoaching seul avec Claude, j'ai vécu exactement ça : Claude m'a généré l'implémentation d'une règle de calcul de disponibilité pour les slots d'un coach. Le code compilait. Les tests Vitest passaient, des tests que Claude avait également écrits. La PR a été mergée sur staging. Deux jours plus tard, en testant manuellement, j'ai découvert que certains créneaux étaient marqués disponibles alors qu'un ",{"type":30,"tag":114,"props":2425,"children":2427},{"className":2426},[],[2428],{"type":35,"value":2429},"slot-hold",{"type":35,"value":2431}," actif les bloquait. La règle métier avait une condition de priorité que Claude avait silencieusement simplifiée.",{"type":30,"tag":31,"props":2433,"children":2434},{},[2435],{"type":35,"value":2436},"Ce n'était pas un bug de code. C'était un bug de jugement métier que Claude ne pouvait pas avoir sans mes spécifications complètes.",{"type":30,"tag":31,"props":2438,"children":2439},{},[2440],{"type":30,"tag":46,"props":2441,"children":2442},{},[2443,2445,2450],{"type":35,"value":2444},"Le code généré par un LLM compile, passe les tests de type, et peut même faire passer une suite de tests unitaires, tout en étant incorrect sur la logique métier. C'est la caractéristique la plus trompeuse du code IA-assisté : les ",{"type":30,"tag":454,"props":2446,"children":2447},{"href":456},[2448],{"type":35,"value":2449},"vulnérabilités de sécurité spécifiques aux LLMs",{"type":35,"value":2451}," s'y cachent de la même façon : il a l'air juste avant d'être évalué en profondeur.",{"type":30,"tag":52,"props":2453,"children":2454},{},[],{"type":30,"tag":56,"props":2456,"children":2458},{"id":2457},"pourquoi-claude-se-trompe-sur-le-métier",[2459],{"type":35,"value":2460},"Pourquoi Claude se trompe sur le métier",{"type":30,"tag":31,"props":2462,"children":2463},{},[2464,2466,2472,2474,2480,2481,2487,2488,2493],{"type":35,"value":2465},"Claude génère du code plausible basé sur des patterns statistiques. Il ne connaît pas les règles métier de crmcoaching : les contraintes entre ",{"type":30,"tag":114,"props":2467,"children":2469},{"className":2468},[],[2470],{"type":35,"value":2471},"lead",{"type":35,"value":2473},", ",{"type":30,"tag":114,"props":2475,"children":2477},{"className":2476},[],[2478],{"type":35,"value":2479},"client",{"type":35,"value":2473},{"type":30,"tag":114,"props":2482,"children":2484},{"className":2483},[],[2485],{"type":35,"value":2486},"offre",{"type":35,"value":2473},{"type":30,"tag":114,"props":2489,"children":2491},{"className":2490},[],[2492],{"type":35,"value":2429},{"type":35,"value":2494},", les invariants de domaine dans chaque bounded context. Il génère du code qui ressemble à du code qui gère des créneaux ou des paiements, mais pas du code qui gère mes créneaux, selon mes règles, dans mon contexte Prisma\u002FPostgreSQL.",{"type":30,"tag":31,"props":2496,"children":2497},{},[2498,2500,2505],{"type":35,"value":2499},"La conséquence est directe : le code IA-généré peut être techniquement impeccable (pas d'injection, pas de null assertion sauvage, bonne gestion des erreurs) et fonctionnellement incorrect (mauvaise règle de calcul, cas d'utilisation manqué, contrainte business ignorée). La recherche de ",{"type":30,"tag":46,"props":2501,"children":2502},{},[2503],{"type":35,"value":2504},"NYU (2023)",{"type":35,"value":2506}," sur le code IA-assisté confirme que les développeurs sous-estiment systématiquement les erreurs de logique dans le code généré, précisément parce que le code \"a l'air propre\".",{"type":30,"tag":52,"props":2508,"children":2509},{},[],{"type":30,"tag":56,"props":2511,"children":2513},{"id":2512},"checklist-partie-1-correction-logique-et-cas-limites-points-1-4",[2514],{"type":35,"value":2515},"Checklist partie 1 : Correction logique et cas limites (points 1-4)",{"type":30,"tag":31,"props":2517,"children":2518},{},[2519],{"type":30,"tag":46,"props":2520,"children":2521},{},[2522],{"type":35,"value":2523},"Point 1 : La logique métier correspond aux règles de votre domaine",{"type":30,"tag":31,"props":2525,"children":2526},{},[2527],{"type":35,"value":2528},"Ne pas se fier au fait que le code \"a l'air logique\". Vérifier explicitement que chaque règle métier implémentée correspond exactement à la spécification. Claude a tendance à implémenter des règles \"standard\" qui peuvent différer des règles spécifiques de votre domaine.",{"type":30,"tag":31,"props":2530,"children":2531},{},[2532,2534,2539,2541,2547],{"type":35,"value":2533},"Exemple concret sur crmcoaching : Claude peut implémenter la disponibilité d'un slot en ignorant la priorité d'un ",{"type":30,"tag":114,"props":2535,"children":2537},{"className":2536},[],[2538],{"type":35,"value":2429},{"type":35,"value":2540}," actif, ou gérer la conversion lead -> client sans propager le ",{"type":30,"tag":114,"props":2542,"children":2544},{"className":2543},[],[2545],{"type":35,"value":2546},"createdBy",{"type":35,"value":2548}," attendu par l'audit trail.",{"type":30,"tag":31,"props":2550,"children":2551},{},[2552],{"type":30,"tag":46,"props":2553,"children":2554},{},[2555],{"type":35,"value":2556},"Point 2 : Les cas limites sont couverts",{"type":30,"tag":31,"props":2558,"children":2559},{},[2560],{"type":35,"value":2561},"Vérifiez explicitement :",{"type":30,"tag":1588,"props":2563,"children":2564},{},[2565,2570,2575,2580],{"type":30,"tag":1592,"props":2566,"children":2567},{},[2568],{"type":35,"value":2569},"Que se passe-t-il si la collection est vide ?",{"type":30,"tag":1592,"props":2571,"children":2572},{},[2573],{"type":35,"value":2574},"Que se passe-t-il avec des valeurs nulles ou undefined ?",{"type":30,"tag":1592,"props":2576,"children":2577},{},[2578],{"type":35,"value":2579},"Que se passe-t-il avec les valeurs extrêmes (0, négatif, très grand nombre) ?",{"type":30,"tag":1592,"props":2581,"children":2582},{},[2583],{"type":35,"value":2584},"Que se passe-t-il si une opération concurrente modifie l'état entre deux étapes ?",{"type":30,"tag":31,"props":2586,"children":2587},{},[2588],{"type":30,"tag":46,"props":2589,"children":2590},{},[2591],{"type":35,"value":2592},"Point 3 : Les conditions métier sont correctement combinées",{"type":30,"tag":31,"props":2594,"children":2595},{},[2596],{"type":35,"value":2597},"Claude a tendance à simplifier les conditions logiques complexes. Une règle business comme \"eligible si (A ET B) OU (C ET PAS D)\" peut être simplifiée en \"eligible si A ET B OU C\", ce qui produit des résultats incorrects pour les cas qui impliquent D. C'est exactement le type d'erreur que j'ai rencontré sur le calcul de disponibilité des slots.",{"type":30,"tag":31,"props":2599,"children":2600},{},[2601],{"type":30,"tag":46,"props":2602,"children":2603},{},[2604],{"type":35,"value":2605},"Point 4 : Le comportement en cas d'erreur est métier-correct",{"type":30,"tag":31,"props":2607,"children":2608},{},[2609],{"type":35,"value":2610},"Le code généré peut gérer les erreurs techniques correctement (try\u002Fcatch, retours d'erreur) tout en gérant incorrectement les erreurs métier. Vérifiez : quelle est la réponse attendue quand une règle métier est violée ? Est-ce une exception ? Un résultat partiel ? Un état spécifique ?",{"type":30,"tag":568,"props":2612,"children":2614},{"cta":570,"href":571,"title":2613,"type":573},"Vous voulez développer le réflexe qui attrape les bugs de logique métier dans le code IA ?",[2615],{"type":30,"tag":31,"props":2616,"children":2617},{},[2618],{"type":35,"value":2619},"Repérer une règle métier silencieusement simplifiée par Claude, ça ne s'apprend pas en lisant une checklist : ça se travaille. En mentoring 1:1, je relis votre code IA-assisté avec vous, on confronte chaque branche aux invariants de votre domaine, et vous commencez à voir ce que le modèle ne voit pas avant que ça parte en prod.",{"type":30,"tag":52,"props":2621,"children":2622},{},[],{"type":30,"tag":56,"props":2624,"children":2626},{"id":2625},"checklist-partie-2-sécurité-et-gestion-des-erreurs-points-5-8",[2627],{"type":35,"value":2628},"Checklist partie 2 : Sécurité et gestion des erreurs (points 5-8)",{"type":30,"tag":31,"props":2630,"children":2631},{},[2632],{"type":30,"tag":46,"props":2633,"children":2634},{},[2635],{"type":35,"value":2636},"Point 5 : Les inputs utilisateurs sont validés et sanitisés",{"type":30,"tag":31,"props":2638,"children":2639},{},[2640],{"type":35,"value":2641},"Vérifiez systématiquement que tout input provenant de l'extérieur (utilisateur, API, message queue) est validé avant d'être utilisé. Claude oublie fréquemment la validation des types, des ranges, et des formats. Sur crmcoaching j'utilise Zod 4 pour parser et valider les DTOs à l'entrée de chaque controller NestJS : vérifier que Claude a bien branché le schéma Zod et qu'il ne fait pas confiance au type TypeScript seul.",{"type":30,"tag":31,"props":2643,"children":2644},{},[2645],{"type":30,"tag":46,"props":2646,"children":2647},{},[2648],{"type":35,"value":2649},"Point 6 : Aucune injection n'est possible",{"type":30,"tag":31,"props":2651,"children":2652},{},[2653],{"type":35,"value":2654},"Pour tout code qui génère des requêtes SQL brutes, des commandes shell, ou des requêtes LDAP : vérifiez que les valeurs dynamiques sont passées par des paramètres, jamais interpolées directement dans des strings.",{"type":30,"tag":31,"props":2656,"children":2657},{},[2658,2660,2666],{"type":35,"value":2659},"Avec Prisma, le client paramétrise automatiquement les requêtes. Le danger apparaît quand Claude utilise ",{"type":30,"tag":114,"props":2661,"children":2663},{"className":2662},[],[2664],{"type":35,"value":2665},"$queryRawUnsafe",{"type":35,"value":2667}," pour une requête qu'il ne sait pas exprimer avec le query builder :",{"type":30,"tag":107,"props":2669,"children":2671},{"code":2670,"language":111,"meta":8,"className":109,"style":8},"\u002F\u002F ❌ Injection possible : Claude a utilisé $queryRawUnsafe avec interpolation directe\nconst userId = req.params.id; \u002F\u002F non validé\nconst result = await prisma.$queryRawUnsafe(\n  `SELECT * FROM \"User\" WHERE id = '${userId}'`\n);\n\n\u002F\u002F ✅ Prisma paramétré : passer la valeur comme argument séparé\nconst result = await prisma.$queryRaw\u003CUser[]>`\n  SELECT * FROM \"User\" WHERE id = ${userId}\n`;\n\n\u002F\u002F ✅ Encore mieux : utiliser le query builder Prisma\nconst user = await prisma.user.findUnique({\n  where: { id: userId },\n});\n",[2672],{"type":30,"tag":114,"props":2673,"children":2674},{"__ignoreMap":8},[2675,2683,2733,2772,2801,2813,2820,2828,2888,2909,2920,2927,2935,2985,3021],{"type":30,"tag":118,"props":2676,"children":2677},{"class":120,"line":121},[2678],{"type":30,"tag":118,"props":2679,"children":2680},{"style":125},[2681],{"type":35,"value":2682},"\u002F\u002F ❌ Injection possible : Claude a utilisé $queryRawUnsafe avec interpolation directe\n",{"type":30,"tag":118,"props":2684,"children":2685},{"class":120,"line":131},[2686,2691,2696,2700,2705,2709,2714,2718,2723,2728],{"type":30,"tag":118,"props":2687,"children":2688},{"style":144},[2689],{"type":35,"value":2690},"const",{"type":30,"tag":118,"props":2692,"children":2693},{"style":155},[2694],{"type":35,"value":2695}," userId",{"type":30,"tag":118,"props":2697,"children":2698},{"style":161},[2699],{"type":35,"value":164},{"type":30,"tag":118,"props":2701,"children":2702},{"style":379},[2703],{"type":35,"value":2704}," req",{"type":30,"tag":118,"props":2706,"children":2707},{"style":367},[2708],{"type":35,"value":370},{"type":30,"tag":118,"props":2710,"children":2711},{"style":379},[2712],{"type":35,"value":2713},"params",{"type":30,"tag":118,"props":2715,"children":2716},{"style":367},[2717],{"type":35,"value":370},{"type":30,"tag":118,"props":2719,"children":2720},{"style":379},[2721],{"type":35,"value":2722},"id",{"type":30,"tag":118,"props":2724,"children":2725},{"style":385},[2726],{"type":35,"value":2727},";",{"type":30,"tag":118,"props":2729,"children":2730},{"style":125},[2731],{"type":35,"value":2732}," \u002F\u002F non validé\n",{"type":30,"tag":118,"props":2734,"children":2735},{"class":120,"line":140},[2736,2740,2745,2749,2754,2759,2763,2767],{"type":30,"tag":118,"props":2737,"children":2738},{"style":144},[2739],{"type":35,"value":2690},{"type":30,"tag":118,"props":2741,"children":2742},{"style":155},[2743],{"type":35,"value":2744}," result",{"type":30,"tag":118,"props":2746,"children":2747},{"style":161},[2748],{"type":35,"value":164},{"type":30,"tag":118,"props":2750,"children":2751},{"style":144},[2752],{"type":35,"value":2753}," await",{"type":30,"tag":118,"props":2755,"children":2756},{"style":379},[2757],{"type":35,"value":2758}," prisma",{"type":30,"tag":118,"props":2760,"children":2761},{"style":367},[2762],{"type":35,"value":370},{"type":30,"tag":118,"props":2764,"children":2765},{"style":373},[2766],{"type":35,"value":2665},{"type":30,"tag":118,"props":2768,"children":2769},{"style":379},[2770],{"type":35,"value":2771},"(\n",{"type":30,"tag":118,"props":2773,"children":2774},{"class":120,"line":173},[2775,2780,2786,2791,2796],{"type":30,"tag":118,"props":2776,"children":2777},{"style":167},[2778],{"type":35,"value":2779},"  `SELECT * FROM \"User\" WHERE id = '",{"type":30,"tag":118,"props":2781,"children":2783},{"style":2782},"--shiki-default:#949CBB;--shiki-dark:#9ECBFF",[2784],{"type":35,"value":2785},"${",{"type":30,"tag":118,"props":2787,"children":2788},{"style":379},[2789],{"type":35,"value":2790},"userId",{"type":30,"tag":118,"props":2792,"children":2793},{"style":2782},[2794],{"type":35,"value":2795},"}",{"type":30,"tag":118,"props":2797,"children":2798},{"style":167},[2799],{"type":35,"value":2800},"'`\n",{"type":30,"tag":118,"props":2802,"children":2803},{"class":120,"line":182},[2804,2809],{"type":30,"tag":118,"props":2805,"children":2806},{"style":379},[2807],{"type":35,"value":2808},")",{"type":30,"tag":118,"props":2810,"children":2811},{"style":385},[2812],{"type":35,"value":388},{"type":30,"tag":118,"props":2814,"children":2815},{"class":120,"line":190},[2816],{"type":30,"tag":118,"props":2817,"children":2818},{"emptyLinePlaceholder":13},[2819],{"type":35,"value":137},{"type":30,"tag":118,"props":2821,"children":2822},{"class":120,"line":199},[2823],{"type":30,"tag":118,"props":2824,"children":2825},{"style":125},[2826],{"type":35,"value":2827},"\u002F\u002F ✅ Prisma paramétré : passer la valeur comme argument séparé\n",{"type":30,"tag":118,"props":2829,"children":2830},{"class":120,"line":208},[2831,2835,2839,2843,2847,2851,2855,2860,2866,2872,2878,2883],{"type":30,"tag":118,"props":2832,"children":2833},{"style":144},[2834],{"type":35,"value":2690},{"type":30,"tag":118,"props":2836,"children":2837},{"style":155},[2838],{"type":35,"value":2744},{"type":30,"tag":118,"props":2840,"children":2841},{"style":161},[2842],{"type":35,"value":164},{"type":30,"tag":118,"props":2844,"children":2845},{"style":144},[2846],{"type":35,"value":2753},{"type":30,"tag":118,"props":2848,"children":2849},{"style":379},[2850],{"type":35,"value":2758},{"type":30,"tag":118,"props":2852,"children":2853},{"style":367},[2854],{"type":35,"value":370},{"type":30,"tag":118,"props":2856,"children":2857},{"style":373},[2858],{"type":35,"value":2859},"$queryRaw",{"type":30,"tag":118,"props":2861,"children":2863},{"style":2862},"--shiki-default:#99D1DB;--shiki-dark:#E1E4E8",[2864],{"type":35,"value":2865},"\u003C",{"type":30,"tag":118,"props":2867,"children":2869},{"style":2868},"--shiki-default:#E5C890;--shiki-default-font-style:italic;--shiki-dark:#B392F0;--shiki-dark-font-style:inherit",[2870],{"type":35,"value":2871},"User",{"type":30,"tag":118,"props":2873,"children":2875},{"style":2874},"--shiki-default:#E5C890;--shiki-default-font-style:italic;--shiki-dark:#E1E4E8;--shiki-dark-font-style:inherit",[2876],{"type":35,"value":2877},"[]",{"type":30,"tag":118,"props":2879,"children":2880},{"style":2862},[2881],{"type":35,"value":2882},">",{"type":30,"tag":118,"props":2884,"children":2885},{"style":167},[2886],{"type":35,"value":2887},"`\n",{"type":30,"tag":118,"props":2889,"children":2890},{"class":120,"line":216},[2891,2896,2900,2904],{"type":30,"tag":118,"props":2892,"children":2893},{"style":167},[2894],{"type":35,"value":2895},"  SELECT * FROM \"User\" WHERE id = ",{"type":30,"tag":118,"props":2897,"children":2898},{"style":2782},[2899],{"type":35,"value":2785},{"type":30,"tag":118,"props":2901,"children":2902},{"style":379},[2903],{"type":35,"value":2790},{"type":30,"tag":118,"props":2905,"children":2906},{"style":2782},[2907],{"type":35,"value":2908},"}\n",{"type":30,"tag":118,"props":2910,"children":2911},{"class":120,"line":225},[2912,2916],{"type":30,"tag":118,"props":2913,"children":2914},{"style":167},[2915],{"type":35,"value":364},{"type":30,"tag":118,"props":2917,"children":2918},{"style":385},[2919],{"type":35,"value":388},{"type":30,"tag":118,"props":2921,"children":2922},{"class":120,"line":234},[2923],{"type":30,"tag":118,"props":2924,"children":2925},{"emptyLinePlaceholder":13},[2926],{"type":35,"value":137},{"type":30,"tag":118,"props":2928,"children":2929},{"class":120,"line":243},[2930],{"type":30,"tag":118,"props":2931,"children":2932},{"style":125},[2933],{"type":35,"value":2934},"\u002F\u002F ✅ Encore mieux : utiliser le query builder Prisma\n",{"type":30,"tag":118,"props":2936,"children":2937},{"class":120,"line":252},[2938,2942,2946,2950,2954,2958,2962,2967,2971,2976,2980],{"type":30,"tag":118,"props":2939,"children":2940},{"style":144},[2941],{"type":35,"value":2690},{"type":30,"tag":118,"props":2943,"children":2944},{"style":155},[2945],{"type":35,"value":1126},{"type":30,"tag":118,"props":2947,"children":2948},{"style":161},[2949],{"type":35,"value":164},{"type":30,"tag":118,"props":2951,"children":2952},{"style":144},[2953],{"type":35,"value":2753},{"type":30,"tag":118,"props":2955,"children":2956},{"style":379},[2957],{"type":35,"value":2758},{"type":30,"tag":118,"props":2959,"children":2960},{"style":367},[2961],{"type":35,"value":370},{"type":30,"tag":118,"props":2963,"children":2964},{"style":379},[2965],{"type":35,"value":2966},"user",{"type":30,"tag":118,"props":2968,"children":2969},{"style":367},[2970],{"type":35,"value":370},{"type":30,"tag":118,"props":2972,"children":2973},{"style":373},[2974],{"type":35,"value":2975},"findUnique",{"type":30,"tag":118,"props":2977,"children":2978},{"style":379},[2979],{"type":35,"value":1111},{"type":30,"tag":118,"props":2981,"children":2982},{"style":385},[2983],{"type":35,"value":2984},"{\n",{"type":30,"tag":118,"props":2986,"children":2987},{"class":120,"line":261},[2988,2993,2997,3002,3007,3011,3016],{"type":30,"tag":118,"props":2989,"children":2990},{"style":379},[2991],{"type":35,"value":2992},"  where",{"type":30,"tag":118,"props":2994,"children":2995},{"style":367},[2996],{"type":35,"value":1279},{"type":30,"tag":118,"props":2998,"children":2999},{"style":385},[3000],{"type":35,"value":3001}," {",{"type":30,"tag":118,"props":3003,"children":3004},{"style":379},[3005],{"type":35,"value":3006}," id",{"type":30,"tag":118,"props":3008,"children":3009},{"style":367},[3010],{"type":35,"value":1279},{"type":30,"tag":118,"props":3012,"children":3013},{"style":379},[3014],{"type":35,"value":3015}," userId ",{"type":30,"tag":118,"props":3017,"children":3018},{"style":385},[3019],{"type":35,"value":3020},"},\n",{"type":30,"tag":118,"props":3022,"children":3023},{"class":120,"line":270},[3024,3028,3032],{"type":30,"tag":118,"props":3025,"children":3026},{"style":385},[3027],{"type":35,"value":2795},{"type":30,"tag":118,"props":3029,"children":3030},{"style":379},[3031],{"type":35,"value":2808},{"type":30,"tag":118,"props":3033,"children":3034},{"style":385},[3035],{"type":35,"value":388},{"type":30,"tag":31,"props":3037,"children":3038},{},[3039],{"type":30,"tag":46,"props":3040,"children":3041},{},[3042],{"type":35,"value":3043},"Point 7 : Les secrets ne sont pas hardcodés",{"type":30,"tag":31,"props":3045,"children":3046},{},[3047],{"type":35,"value":3048},"Recherchez dans le code généré : passwords, API keys, tokens, connection strings. Claude les hardcode fréquemment dans les exemples de code et les configurations, car c'est le pattern dominant dans le code d'exemple sur lequel il a été entraîné.",{"type":30,"tag":31,"props":3050,"children":3051},{},[3052],{"type":30,"tag":46,"props":3053,"children":3054},{},[3055],{"type":35,"value":3056},"Point 8 : La gestion des exceptions est appropriée",{"type":30,"tag":31,"props":3058,"children":3059},{},[3060],{"type":35,"value":3061},"Vérifiez que :",{"type":30,"tag":1588,"props":3063,"children":3064},{},[3065,3078,3083],{"type":30,"tag":1592,"props":3066,"children":3067},{},[3068,3070,3076],{"type":35,"value":3069},"Les exceptions sont capturées au bon niveau (pas de ",{"type":30,"tag":114,"props":3071,"children":3073},{"className":3072},[],[3074],{"type":35,"value":3075},"catch(e) {}",{"type":35,"value":3077}," vide qui avale les erreurs)",{"type":30,"tag":1592,"props":3079,"children":3080},{},[3081],{"type":35,"value":3082},"Les exceptions techniques ne leakent pas de détails d'implémentation dans les réponses API",{"type":30,"tag":1592,"props":3084,"children":3085},{},[3086],{"type":35,"value":3087},"Les ressources (connexions, fichiers, transactions Prisma) sont correctement fermées en cas d'exception",{"type":30,"tag":52,"props":3089,"children":3090},{},[],{"type":30,"tag":56,"props":3092,"children":3094},{"id":3093},"checklist-partie-3-performance-lisibilité-tests-points-9-12",[3095],{"type":35,"value":3096},"Checklist partie 3 : Performance, lisibilité, tests (points 9-12)",{"type":30,"tag":31,"props":3098,"children":3099},{},[3100],{"type":30,"tag":46,"props":3101,"children":3102},{},[3103],{"type":35,"value":3104},"Point 9 : Pas de N+1 query",{"type":30,"tag":31,"props":3106,"children":3107},{},[3108],{"type":35,"value":3109},"Le problème N+1 est l'un des patterns de performance les plus fréquemment générés par Claude : une query Prisma dans une boucle. Je l'ai rencontré plusieurs fois sur crmcoaching lors de la génération de listings agrégés.",{"type":30,"tag":107,"props":3111,"children":3113},{"code":3112,"language":111,"meta":8,"className":109,"style":8},"\u002F\u002F ❌ Pattern N+1 généré par Claude : 1 findUnique par client dans la boucle\nconst clients = await prisma.client.findMany();\nfor (const client of clients) {\n  \u002F\u002F 1 requête supplémentaire par client\n  const offres = await prisma.offre.findMany({\n    where: { clientId: client.id },\n  });\n  console.log(client.nom, offres.length);\n}\n\n\u002F\u002F ✅ Eager loading avec include : 1 seule requête JOIN\nconst clients = await prisma.client.findMany({\n  include: {\n    offres: true,\n  },\n});\nfor (const client of clients) {\n  console.log(client.nom, client.offres.length);\n}\n",[3114],{"type":30,"tag":114,"props":3115,"children":3116},{"__ignoreMap":8},[3117,3125,3174,3210,3218,3267,3309,3325,3381,3388,3395,3403,3450,3467,3490,3498,3513,3544,3604],{"type":30,"tag":118,"props":3118,"children":3119},{"class":120,"line":121},[3120],{"type":30,"tag":118,"props":3121,"children":3122},{"style":125},[3123],{"type":35,"value":3124},"\u002F\u002F ❌ Pattern N+1 généré par Claude : 1 findUnique par client dans la boucle\n",{"type":30,"tag":118,"props":3126,"children":3127},{"class":120,"line":131},[3128,3132,3137,3141,3145,3149,3153,3157,3161,3166,3170],{"type":30,"tag":118,"props":3129,"children":3130},{"style":144},[3131],{"type":35,"value":2690},{"type":30,"tag":118,"props":3133,"children":3134},{"style":155},[3135],{"type":35,"value":3136}," clients",{"type":30,"tag":118,"props":3138,"children":3139},{"style":161},[3140],{"type":35,"value":164},{"type":30,"tag":118,"props":3142,"children":3143},{"style":144},[3144],{"type":35,"value":2753},{"type":30,"tag":118,"props":3146,"children":3147},{"style":379},[3148],{"type":35,"value":2758},{"type":30,"tag":118,"props":3150,"children":3151},{"style":367},[3152],{"type":35,"value":370},{"type":30,"tag":118,"props":3154,"children":3155},{"style":379},[3156],{"type":35,"value":2479},{"type":30,"tag":118,"props":3158,"children":3159},{"style":367},[3160],{"type":35,"value":370},{"type":30,"tag":118,"props":3162,"children":3163},{"style":373},[3164],{"type":35,"value":3165},"findMany",{"type":30,"tag":118,"props":3167,"children":3168},{"style":379},[3169],{"type":35,"value":382},{"type":30,"tag":118,"props":3171,"children":3172},{"style":385},[3173],{"type":35,"value":388},{"type":30,"tag":118,"props":3175,"children":3176},{"class":120,"line":140},[3177,3182,3187,3191,3196,3201,3206],{"type":30,"tag":118,"props":3178,"children":3179},{"style":144},[3180],{"type":35,"value":3181},"for",{"type":30,"tag":118,"props":3183,"children":3184},{"style":379},[3185],{"type":35,"value":3186}," (",{"type":30,"tag":118,"props":3188,"children":3189},{"style":144},[3190],{"type":35,"value":2690},{"type":30,"tag":118,"props":3192,"children":3193},{"style":155},[3194],{"type":35,"value":3195}," client",{"type":30,"tag":118,"props":3197,"children":3198},{"style":144},[3199],{"type":35,"value":3200}," of",{"type":30,"tag":118,"props":3202,"children":3203},{"style":379},[3204],{"type":35,"value":3205}," clients) ",{"type":30,"tag":118,"props":3207,"children":3208},{"style":385},[3209],{"type":35,"value":2984},{"type":30,"tag":118,"props":3211,"children":3212},{"class":120,"line":173},[3213],{"type":30,"tag":118,"props":3214,"children":3215},{"style":125},[3216],{"type":35,"value":3217},"  \u002F\u002F 1 requête supplémentaire par client\n",{"type":30,"tag":118,"props":3219,"children":3220},{"class":120,"line":182},[3221,3226,3231,3235,3239,3243,3247,3251,3255,3259,3263],{"type":30,"tag":118,"props":3222,"children":3223},{"style":144},[3224],{"type":35,"value":3225},"  const",{"type":30,"tag":118,"props":3227,"children":3228},{"style":155},[3229],{"type":35,"value":3230}," offres",{"type":30,"tag":118,"props":3232,"children":3233},{"style":161},[3234],{"type":35,"value":164},{"type":30,"tag":118,"props":3236,"children":3237},{"style":144},[3238],{"type":35,"value":2753},{"type":30,"tag":118,"props":3240,"children":3241},{"style":379},[3242],{"type":35,"value":2758},{"type":30,"tag":118,"props":3244,"children":3245},{"style":367},[3246],{"type":35,"value":370},{"type":30,"tag":118,"props":3248,"children":3249},{"style":379},[3250],{"type":35,"value":2486},{"type":30,"tag":118,"props":3252,"children":3253},{"style":367},[3254],{"type":35,"value":370},{"type":30,"tag":118,"props":3256,"children":3257},{"style":373},[3258],{"type":35,"value":3165},{"type":30,"tag":118,"props":3260,"children":3261},{"style":379},[3262],{"type":35,"value":1111},{"type":30,"tag":118,"props":3264,"children":3265},{"style":385},[3266],{"type":35,"value":2984},{"type":30,"tag":118,"props":3268,"children":3269},{"class":120,"line":190},[3270,3275,3279,3283,3288,3292,3296,3300,3305],{"type":30,"tag":118,"props":3271,"children":3272},{"style":379},[3273],{"type":35,"value":3274},"    where",{"type":30,"tag":118,"props":3276,"children":3277},{"style":367},[3278],{"type":35,"value":1279},{"type":30,"tag":118,"props":3280,"children":3281},{"style":385},[3282],{"type":35,"value":3001},{"type":30,"tag":118,"props":3284,"children":3285},{"style":379},[3286],{"type":35,"value":3287}," clientId",{"type":30,"tag":118,"props":3289,"children":3290},{"style":367},[3291],{"type":35,"value":1279},{"type":30,"tag":118,"props":3293,"children":3294},{"style":379},[3295],{"type":35,"value":3195},{"type":30,"tag":118,"props":3297,"children":3298},{"style":367},[3299],{"type":35,"value":370},{"type":30,"tag":118,"props":3301,"children":3302},{"style":379},[3303],{"type":35,"value":3304},"id ",{"type":30,"tag":118,"props":3306,"children":3307},{"style":385},[3308],{"type":35,"value":3020},{"type":30,"tag":118,"props":3310,"children":3311},{"class":120,"line":199},[3312,3317,3321],{"type":30,"tag":118,"props":3313,"children":3314},{"style":385},[3315],{"type":35,"value":3316},"  }",{"type":30,"tag":118,"props":3318,"children":3319},{"style":379},[3320],{"type":35,"value":2808},{"type":30,"tag":118,"props":3322,"children":3323},{"style":385},[3324],{"type":35,"value":388},{"type":30,"tag":118,"props":3326,"children":3327},{"class":120,"line":208},[3328,3333,3337,3342,3347,3351,3356,3360,3364,3368,3373,3377],{"type":30,"tag":118,"props":3329,"children":3330},{"style":379},[3331],{"type":35,"value":3332},"  console",{"type":30,"tag":118,"props":3334,"children":3335},{"style":367},[3336],{"type":35,"value":370},{"type":30,"tag":118,"props":3338,"children":3339},{"style":373},[3340],{"type":35,"value":3341},"log",{"type":30,"tag":118,"props":3343,"children":3344},{"style":379},[3345],{"type":35,"value":3346},"(client",{"type":30,"tag":118,"props":3348,"children":3349},{"style":367},[3350],{"type":35,"value":370},{"type":30,"tag":118,"props":3352,"children":3353},{"style":379},[3354],{"type":35,"value":3355},"nom",{"type":30,"tag":118,"props":3357,"children":3358},{"style":385},[3359],{"type":35,"value":1121},{"type":30,"tag":118,"props":3361,"children":3362},{"style":379},[3363],{"type":35,"value":3230},{"type":30,"tag":118,"props":3365,"children":3366},{"style":367},[3367],{"type":35,"value":370},{"type":30,"tag":118,"props":3369,"children":3370},{"style":155},[3371],{"type":35,"value":3372},"length",{"type":30,"tag":118,"props":3374,"children":3375},{"style":379},[3376],{"type":35,"value":2808},{"type":30,"tag":118,"props":3378,"children":3379},{"style":385},[3380],{"type":35,"value":388},{"type":30,"tag":118,"props":3382,"children":3383},{"class":120,"line":216},[3384],{"type":30,"tag":118,"props":3385,"children":3386},{"style":385},[3387],{"type":35,"value":2908},{"type":30,"tag":118,"props":3389,"children":3390},{"class":120,"line":225},[3391],{"type":30,"tag":118,"props":3392,"children":3393},{"emptyLinePlaceholder":13},[3394],{"type":35,"value":137},{"type":30,"tag":118,"props":3396,"children":3397},{"class":120,"line":234},[3398],{"type":30,"tag":118,"props":3399,"children":3400},{"style":125},[3401],{"type":35,"value":3402},"\u002F\u002F ✅ Eager loading avec include : 1 seule requête JOIN\n",{"type":30,"tag":118,"props":3404,"children":3405},{"class":120,"line":243},[3406,3410,3414,3418,3422,3426,3430,3434,3438,3442,3446],{"type":30,"tag":118,"props":3407,"children":3408},{"style":144},[3409],{"type":35,"value":2690},{"type":30,"tag":118,"props":3411,"children":3412},{"style":155},[3413],{"type":35,"value":3136},{"type":30,"tag":118,"props":3415,"children":3416},{"style":161},[3417],{"type":35,"value":164},{"type":30,"tag":118,"props":3419,"children":3420},{"style":144},[3421],{"type":35,"value":2753},{"type":30,"tag":118,"props":3423,"children":3424},{"style":379},[3425],{"type":35,"value":2758},{"type":30,"tag":118,"props":3427,"children":3428},{"style":367},[3429],{"type":35,"value":370},{"type":30,"tag":118,"props":3431,"children":3432},{"style":379},[3433],{"type":35,"value":2479},{"type":30,"tag":118,"props":3435,"children":3436},{"style":367},[3437],{"type":35,"value":370},{"type":30,"tag":118,"props":3439,"children":3440},{"style":373},[3441],{"type":35,"value":3165},{"type":30,"tag":118,"props":3443,"children":3444},{"style":379},[3445],{"type":35,"value":1111},{"type":30,"tag":118,"props":3447,"children":3448},{"style":385},[3449],{"type":35,"value":2984},{"type":30,"tag":118,"props":3451,"children":3452},{"class":120,"line":252},[3453,3458,3462],{"type":30,"tag":118,"props":3454,"children":3455},{"style":379},[3456],{"type":35,"value":3457},"  include",{"type":30,"tag":118,"props":3459,"children":3460},{"style":367},[3461],{"type":35,"value":1279},{"type":30,"tag":118,"props":3463,"children":3464},{"style":385},[3465],{"type":35,"value":3466}," {\n",{"type":30,"tag":118,"props":3468,"children":3469},{"class":120,"line":261},[3470,3475,3479,3485],{"type":30,"tag":118,"props":3471,"children":3472},{"style":379},[3473],{"type":35,"value":3474},"    offres",{"type":30,"tag":118,"props":3476,"children":3477},{"style":367},[3478],{"type":35,"value":1279},{"type":30,"tag":118,"props":3480,"children":3482},{"style":3481},"--shiki-default:#EF9F76;--shiki-dark:#79B8FF",[3483],{"type":35,"value":3484}," true",{"type":30,"tag":118,"props":3486,"children":3487},{"style":385},[3488],{"type":35,"value":3489},",\n",{"type":30,"tag":118,"props":3491,"children":3492},{"class":120,"line":270},[3493],{"type":30,"tag":118,"props":3494,"children":3495},{"style":385},[3496],{"type":35,"value":3497},"  },\n",{"type":30,"tag":118,"props":3499,"children":3500},{"class":120,"line":279},[3501,3505,3509],{"type":30,"tag":118,"props":3502,"children":3503},{"style":385},[3504],{"type":35,"value":2795},{"type":30,"tag":118,"props":3506,"children":3507},{"style":379},[3508],{"type":35,"value":2808},{"type":30,"tag":118,"props":3510,"children":3511},{"style":385},[3512],{"type":35,"value":388},{"type":30,"tag":118,"props":3514,"children":3515},{"class":120,"line":287},[3516,3520,3524,3528,3532,3536,3540],{"type":30,"tag":118,"props":3517,"children":3518},{"style":144},[3519],{"type":35,"value":3181},{"type":30,"tag":118,"props":3521,"children":3522},{"style":379},[3523],{"type":35,"value":3186},{"type":30,"tag":118,"props":3525,"children":3526},{"style":144},[3527],{"type":35,"value":2690},{"type":30,"tag":118,"props":3529,"children":3530},{"style":155},[3531],{"type":35,"value":3195},{"type":30,"tag":118,"props":3533,"children":3534},{"style":144},[3535],{"type":35,"value":3200},{"type":30,"tag":118,"props":3537,"children":3538},{"style":379},[3539],{"type":35,"value":3205},{"type":30,"tag":118,"props":3541,"children":3542},{"style":385},[3543],{"type":35,"value":2984},{"type":30,"tag":118,"props":3545,"children":3546},{"class":120,"line":296},[3547,3551,3555,3559,3563,3567,3571,3575,3579,3583,3588,3592,3596,3600],{"type":30,"tag":118,"props":3548,"children":3549},{"style":379},[3550],{"type":35,"value":3332},{"type":30,"tag":118,"props":3552,"children":3553},{"style":367},[3554],{"type":35,"value":370},{"type":30,"tag":118,"props":3556,"children":3557},{"style":373},[3558],{"type":35,"value":3341},{"type":30,"tag":118,"props":3560,"children":3561},{"style":379},[3562],{"type":35,"value":3346},{"type":30,"tag":118,"props":3564,"children":3565},{"style":367},[3566],{"type":35,"value":370},{"type":30,"tag":118,"props":3568,"children":3569},{"style":379},[3570],{"type":35,"value":3355},{"type":30,"tag":118,"props":3572,"children":3573},{"style":385},[3574],{"type":35,"value":1121},{"type":30,"tag":118,"props":3576,"children":3577},{"style":379},[3578],{"type":35,"value":3195},{"type":30,"tag":118,"props":3580,"children":3581},{"style":367},[3582],{"type":35,"value":370},{"type":30,"tag":118,"props":3584,"children":3585},{"style":379},[3586],{"type":35,"value":3587},"offres",{"type":30,"tag":118,"props":3589,"children":3590},{"style":367},[3591],{"type":35,"value":370},{"type":30,"tag":118,"props":3593,"children":3594},{"style":155},[3595],{"type":35,"value":3372},{"type":30,"tag":118,"props":3597,"children":3598},{"style":379},[3599],{"type":35,"value":2808},{"type":30,"tag":118,"props":3601,"children":3602},{"style":385},[3603],{"type":35,"value":388},{"type":30,"tag":118,"props":3605,"children":3606},{"class":120,"line":305},[3607],{"type":30,"tag":118,"props":3608,"children":3609},{"style":385},[3610],{"type":35,"value":2908},{"type":30,"tag":31,"props":3612,"children":3613},{},[3614],{"type":30,"tag":46,"props":3615,"children":3616},{},[3617],{"type":35,"value":3618},"Point 10 : La complexité est acceptable",{"type":30,"tag":31,"props":3620,"children":3621},{},[3622,3624,3630],{"type":35,"value":3623},"Calculez mentalement (ou avec Biome via ",{"type":30,"tag":114,"props":3625,"children":3627},{"className":3626},[],[3628],{"type":35,"value":3629},"noExcessiveCognitiveComplexity",{"type":35,"value":3631},") la complexité du code généré. Claude peut générer des fonctions avec des imbrications de conditions très profondes difficiles à maintenir. Seuil d'alerte : complexité cyclomatique supérieure à 10, ou fonction de plus de 50 lignes sans extraction de helper.",{"type":30,"tag":31,"props":3633,"children":3634},{},[3635],{"type":30,"tag":46,"props":3636,"children":3637},{},[3638],{"type":35,"value":3639},"Point 11 : Le code est testé avec des tests indépendants",{"type":30,"tag":31,"props":3641,"children":3642},{},[3643],{"type":35,"value":3644},"Ne pas se contenter des tests Vitest générés par Claude pour valider le code de Claude. Écrire des tests indépendants, particulièrement pour les branches d'erreur et les cas limites identifiés au point 2.",{"type":30,"tag":107,"props":3646,"children":3648},{"code":3647},"Règle : au moins 1 test par branche métier critique\nRègle : au moins 1 test pour chaque cas d'erreur explicitement géré\n",[3649],{"type":30,"tag":114,"props":3650,"children":3651},{"__ignoreMap":8},[3652],{"type":35,"value":3647},{"type":30,"tag":31,"props":3654,"children":3655},{},[3656],{"type":30,"tag":46,"props":3657,"children":3658},{},[3659],{"type":35,"value":3660},"Point 12 : Le code est compréhensible par un humain sans explication",{"type":30,"tag":31,"props":3662,"children":3663},{},[3664],{"type":35,"value":3665},"Si vous devez lire le code 3 fois pour comprendre ce qu'il fait, le code est trop complexe. Claude peut générer du code \"intelligent\" avec des patterns avancés ou des one-liners obscurs qui réduisent la lisibilité. La lisibilité prévaut sur le \"clever code\". Toujours.",{"type":30,"tag":52,"props":3667,"children":3668},{},[],{"type":30,"tag":56,"props":3670,"children":3672},{"id":3671},"comment-intégrer-la-checklist-dans-le-workflow",[3673],{"type":35,"value":3674},"Comment intégrer la checklist dans le workflow",{"type":30,"tag":31,"props":3676,"children":3677},{},[3678,3683,3685,3690],{"type":30,"tag":46,"props":3679,"children":3680},{},[3681],{"type":35,"value":3682},"Option A : Dans le template de PR :",{"type":35,"value":3684}," ajouter la checklist comme section \"AI-generated code review\" dans le template de PR. Combinez-la avec un ",{"type":30,"tag":454,"props":3686,"children":3687},{"href":842},[3688],{"type":35,"value":3689},"outil d'analyse statique",{"type":35,"value":3691}," pour automatiser les vérifications de sécurité. Le reviewer coche les 12 points pour tout code généré par IA.",{"type":30,"tag":31,"props":3693,"children":3694},{},[3695,3700],{"type":30,"tag":46,"props":3696,"children":3697},{},[3698],{"type":35,"value":3699},"Option B : Dans le template de Story :",{"type":35,"value":3701}," pour les stories développées majoritairement avec assistance IA, ajouter la checklist comme critère de DoD. Le développeur self-review avant de créer la PR.",{"type":30,"tag":31,"props":3703,"children":3704},{},[3705,3710],{"type":30,"tag":46,"props":3706,"children":3707},{},[3708],{"type":35,"value":3709},"Option C : En session de travail solo :",{"type":35,"value":3711}," utiliser les 12 points comme checklist personnelle avant chaque merge. Identifier les patterns de lacune récurrents pour affiner les prompts et le contexte fourni à Claude.",{"type":30,"tag":52,"props":3713,"children":3714},{},[],{"type":30,"tag":634,"props":3716,"children":3717},{},[3718,3739],{"type":30,"tag":638,"props":3719,"children":3720},{},[3721],{"type":30,"tag":642,"props":3722,"children":3723},{},[3724,3729,3734],{"type":30,"tag":646,"props":3725,"children":3726},{},[3727],{"type":35,"value":3728},"Partie",{"type":30,"tag":646,"props":3730,"children":3731},{},[3732],{"type":35,"value":3733},"Points",{"type":30,"tag":646,"props":3735,"children":3736},{},[3737],{"type":35,"value":3738},"Focus",{"type":30,"tag":657,"props":3740,"children":3741},{},[3742,3759,3777],{"type":30,"tag":642,"props":3743,"children":3744},{},[3745,3749,3754],{"type":30,"tag":664,"props":3746,"children":3747},{},[3748],{"type":35,"value":673},{"type":30,"tag":664,"props":3750,"children":3751},{},[3752],{"type":35,"value":3753},"1-4",{"type":30,"tag":664,"props":3755,"children":3756},{},[3757],{"type":35,"value":3758},"Règles, cas limites, conditions, erreurs métier",{"type":30,"tag":642,"props":3760,"children":3761},{},[3762,3767,3772],{"type":30,"tag":664,"props":3763,"children":3764},{},[3765],{"type":35,"value":3766},"Sécurité",{"type":30,"tag":664,"props":3768,"children":3769},{},[3770],{"type":35,"value":3771},"5-8",{"type":30,"tag":664,"props":3773,"children":3774},{},[3775],{"type":35,"value":3776},"Validation, injections, secrets, exceptions",{"type":30,"tag":642,"props":3778,"children":3779},{},[3780,3784,3789],{"type":30,"tag":664,"props":3781,"children":3782},{},[3783],{"type":35,"value":19},{"type":30,"tag":664,"props":3785,"children":3786},{},[3787],{"type":35,"value":3788},"9-12",{"type":30,"tag":664,"props":3790,"children":3791},{},[3792],{"type":35,"value":3793},"Performance, complexité, tests, lisibilité",{"type":30,"tag":568,"props":3795,"children":3797},{"cta":806,"href":807,"title":3796,"type":809},"Ces 12 points de vérification ne sont qu'une pratique parmi 100",[3798],{"type":30,"tag":31,"props":3799,"children":3800},{},[3801],{"type":35,"value":3802},"Valider du code IA-généré point par point, c'est une seule des pratiques craft que j'applique au quotidien. Le Craft Bundle réunit les 100 pratiques que j'utilise pour coder propre : juger la logique métier, repérer les angles morts, garder un code lisible. Celles que l'IA ne vous apprendra jamais, parce qu'elle ne les a jamais vues tourner en prod.",{"type":30,"tag":52,"props":3804,"children":3805},{},[],{"type":30,"tag":56,"props":3807,"children":3809},{"id":3808},"faq-sur-le-test-du-code-ia-généré",[3810],{"type":35,"value":3811},"FAQ sur le test du code IA-généré",{"type":30,"tag":826,"props":3813,"children":3814},{},[3815,3820],{"type":30,"tag":830,"props":3816,"children":3817},{},[3818],{"type":35,"value":3819},"1. Faut-il appliquer la checklist complète à tout le code IA-assisté ?",{"type":30,"tag":31,"props":3821,"children":3822},{},[3823],{"type":35,"value":3824},"Non. Les points 6 (injection), 7 (secrets), et 11 (tests) s'appliquent à tout le code IA-assisté sans exception. Les autres points s'appliquent en fonction du contexte : les points 1-4 (logique métier) sont critiques pour le code qui implémente des règles business ; les points 9-10 (performance) sont importants pour le code dans les chemins chauds.",{"type":30,"tag":826,"props":3826,"children":3827},{},[3828,3833],{"type":30,"tag":830,"props":3829,"children":3830},{},[3831],{"type":35,"value":3832},"2. Comment former rapidement une équipe à utiliser cette checklist ?",{"type":30,"tag":31,"props":3834,"children":3835},{},[3836],{"type":35,"value":3837},"Session de 2 heures avec des exemples réels de code IA-généré dans votre domaine. Pour chaque exemple, demandez à l'équipe d'identifier les problèmes sans la checklist d'abord, puis avec. La différence entre les deux passages révèle les angles morts de l'équipe, et ce sont précisément ces angles morts qu'il faut adresser en formation.",{"type":30,"tag":826,"props":3839,"children":3840},{},[3841,3846],{"type":30,"tag":830,"props":3842,"children":3843},{},[3844],{"type":35,"value":3845},"3. La checklist remplace-t-elle la [code review](\u002Ffr\u002Fintelligence-artificielle\u002Fia-code-review-retour-experience) standard ?",{"type":30,"tag":31,"props":3847,"children":3848},{},[3849],{"type":35,"value":3850},"Non, elle la complète. La review standard couvre l'architecture, le style, la cohérence avec les patterns de l'équipe. La checklist IA ajoute les vérifications spécifiques aux patterns de vulnérabilités et d'erreurs typiques du code LLM-généré. Les deux sont nécessaires.",{"type":30,"tag":826,"props":3852,"children":3853},{},[3854,3859],{"type":30,"tag":830,"props":3855,"children":3856},{},[3857],{"type":35,"value":3858},"4. Les LLMs s'améliorent. Cette checklist sera-t-elle obsolète dans 6 mois ?",{"type":30,"tag":31,"props":3860,"children":3861},{},[3862],{"type":35,"value":3863},"Elle évoluera, mais ne deviendra pas obsolète. Claude s'améliore sur les patterns de vulnérabilités bien documentés (injections basiques, hardcoded secrets). Il continue à se tromper sur les règles métier spécifiques à votre domaine, car ces règles ne sont pas dans ses données d'entraînement. Les points 1-4 resteront pertinents tant que Claude n'aura pas accès à vos spécifications métier propriétaires.",{"type":30,"tag":826,"props":3865,"children":3866},{},[3867,3872],{"type":30,"tag":830,"props":3868,"children":3869},{},[3870],{"type":35,"value":3871},"5. Comment décider qu'un morceau de code est \"IA-assisté\" et mérite la checklist ?",{"type":30,"tag":31,"props":3873,"children":3874},{},[3875],{"type":35,"value":3876},"La règle pragmatique : si plus de 30% du code d'une fonction a été généré par Claude, appliquer la checklist complète. Pour les petits snippets (autocomplétion d'une ligne), les points 6 et 7 suffisent. En cas de doute, appliquer la checklist : le coût d'une review supplémentaire est toujours inférieur au coût d'un bug en production.",{"type":30,"tag":52,"props":3878,"children":3879},{},[],{"type":30,"tag":568,"props":3881,"children":3883},{"cta":3882,"href":919,"title":920,"type":921},"Télécharger la checklist gratuite →",[3884],{"type":30,"tag":31,"props":3885,"children":3886},{},[3887],{"type":35,"value":3888},"La checklist AI-Ready inclut la checklist de validation du code IA-assisté, les critères de gouvernance des outils IA, et le framework d'évaluation d'adoption. Complète et adaptable à votre contexte d'équipe.",{"type":30,"tag":929,"props":3890,"children":3891},{},[3892],{"type":35,"value":933},{"title":8,"searchDepth":131,"depth":131,"links":3894},[3895,3896,3897,3898,3899,3900],{"id":2457,"depth":131,"text":2460},{"id":2512,"depth":131,"text":2515},{"id":2625,"depth":131,"text":2628},{"id":3093,"depth":131,"text":3096},{"id":3671,"depth":131,"text":3674},{"id":3808,"depth":131,"text":3811},"content:fr:intelligence-artificielle:tester-code-genere-ia-checklist.md","fr\u002Fintelligence-artificielle\u002Ftester-code-genere-ia-checklist.md","fr\u002Fintelligence-artificielle\u002Ftester-code-genere-ia-checklist",{"_path":1610,"_dir":1768,"_draft":7,"_partial":7,"_locale":8,"title":3905,"description":3906,"id":323,"date":3907,"listed":13,"nocomments":7,"hidden":7,"categories":3908,"tags":3909,"cover":3912,"readingTime":3913,"body":3917,"_type":943,"_id":4395,"_source":945,"_file":4396,"_stem":4397,"_extension":948},"Tests d'intégration : les pièges à éviter dans un legacy","Ajouter des tests d'intégration à un legacy est souvent plus difficile qu'écrire from scratch. Les 4 pièges classiques et la séquence qui fonctionne.","2026-02-20",[1768],[3910,3911,19],"Tests Intégration","Legacy","covers\u002Farticles\u002Ftests-integration-legacy.jpg",{"text":1778,"minutes":3914,"time":3915,"words":3916},7.95,477000,1590,{"type":27,"children":3918,"toc":4386},[3919,3924,3932,3943,3946,3952,3957,3983,3988,3991,3997,4002,4012,4029,4032,4038,4043,4052,4068,4081,4084,4093,4096,4102,4107,4115,4138,4154,4159,4162,4168,4173,4182,4202,4207,4210,4216,4287,4292,4301,4304,4310,4323,4336,4349,4362,4375,4378],{"type":30,"tag":31,"props":3920,"children":3921},{},[3922],{"type":35,"value":3923},"J'accompagnais une équipe dans un opérateur télécoms : des ingénieurs sérieux, déterminés à \"enfin écrire des tests sur le legacy\". Ils avaient décidé d'attaquer directement le moteur de facturation : 18 000 lignes de code, 30 dépendances, et une logique métier partiellement documentée. Quatre semaines plus tard, ils avaient produit 3 tests unitaires instables et une équipe découragée. Les tests ne compilaient pas parce que les dépendances ne pouvaient pas être initialisées dans un contexte de test. La motivation avait plongé. On a repris à zéro, mais différemment.",{"type":30,"tag":31,"props":3925,"children":3926},{},[3927],{"type":30,"tag":46,"props":3928,"children":3929},{},[3930],{"type":35,"value":3931},"Décider d'ajouter des tests d'intégration à un legacy est une bonne décision. Mal exécutée, c'est une décision qui peut paralyser l'équipe pendant 3 mois pour un résultat décevant. Les pièges sont prévisibles et évitables.",{"type":30,"tag":31,"props":3933,"children":3934},{},[3935,3937,3941],{"type":35,"value":3936},"Les tests unitaires sur le legacy ont une limite bien connue : ils testent des unités isolées mais ne testent pas le comportement d'ensemble. Pour un filet de sécurité au niveau de l'équipe, assurez-vous que votre ",{"type":30,"tag":454,"props":3938,"children":3939},{"href":1576},[3940],{"type":35,"value":1579},{"type":35,"value":3942}," exige des tests d'intégration sur les chemins critiques.. Un système peut avoir 70% de couverture unitaire et tomber en production parce que l'intégration entre composants n'est pas testée. Mais ajouter des tests d'intégration à un legacy n'est pas une opération simple. Le legacy n'a généralement pas été conçu pour être testé.",{"type":30,"tag":52,"props":3944,"children":3945},{},[],{"type":30,"tag":56,"props":3947,"children":3949},{"id":3948},"pourquoi-les-tests-unitaires-seuls-ne-suffisent-pas",[3950],{"type":35,"value":3951},"Pourquoi les tests unitaires seuls ne suffisent pas",{"type":30,"tag":31,"props":3953,"children":3954},{},[3955],{"type":35,"value":3956},"Un test unitaire isole une fonction et vérifie son comportement en isolation. C'est nécessaire. Mais c'est insuffisant pour détecter les bugs qui apparaissent à la jonction entre composants.",{"type":30,"tag":31,"props":3958,"children":3959},{},[3960,3965,3967,3973,3975,3981],{"type":30,"tag":46,"props":3961,"children":3962},{},[3963],{"type":35,"value":3964},"Exemple concret",{"type":35,"value":3966}," : deux classes parfaitement testées en isolation, l'une qui sérialise une date en ",{"type":30,"tag":114,"props":3968,"children":3970},{"className":3969},[],[3971],{"type":35,"value":3972},"MM\u002FDD\u002FYYYY",{"type":35,"value":3974}," et l'autre qui la désérialise en attendant ",{"type":30,"tag":114,"props":3976,"children":3978},{"className":3977},[],[3979],{"type":35,"value":3980},"YYYY-MM-DD",{"type":35,"value":3982},". Les tests unitaires passent. Le système plante en prod.",{"type":30,"tag":31,"props":3984,"children":3985},{},[3986],{"type":35,"value":3987},"Les tests d'intégration testent les interactions : entre services, entre couches, entre la couche application et la base de données. Ils ont un coût d'exécution plus élevé mais une valeur de détection différente et complémentaire. Sur un legacy, les bugs les plus coûteux sont presque toujours des bugs d'intégration, pas des bugs unitaires. J'ai rarement vu un incident de prod majeur causé par un bug unitaire. J'en ai vu des dizaines causés par des bugs d'intégration silencieux.",{"type":30,"tag":52,"props":3989,"children":3990},{},[],{"type":30,"tag":56,"props":3992,"children":3994},{"id":3993},"piège-1-tester-sans-comprendre-le-comportement-attendu",[3995],{"type":35,"value":3996},"Piège 1 : Tester sans comprendre le comportement attendu",{"type":30,"tag":31,"props":3998,"children":3999},{},[4000],{"type":35,"value":4001},"La première erreur est de commencer à écrire des tests sans savoir ce que le système est censé faire. Sur un legacy réel, le comportement attendu est souvent partiellement documenté ou connu uniquement par des personnes qui ont quitté l'entreprise.",{"type":30,"tag":31,"props":4003,"children":4004},{},[4005,4010],{"type":30,"tag":46,"props":4006,"children":4007},{},[4008],{"type":35,"value":4009},"Ce qui arrive",{"type":35,"value":4011}," : l'équipe écrit des tests qui vérifient le comportement actuel, y compris les bugs existants. Quand un vrai bug est corrigé, les tests cassent. L'équipe corrige les tests pour \"faire passer le build\" au lieu de corriger le comportement. Les tests deviennent un obstacle plutôt qu'un filet de sécurité.",{"type":30,"tag":31,"props":4013,"children":4014},{},[4015,4020,4022,4027],{"type":30,"tag":46,"props":4016,"children":4017},{},[4018],{"type":35,"value":4019},"La sortie",{"type":35,"value":4021}," : avant d'écrire le premier test d'intégration, j'organise une session de 2 à 3 heures avec un expert métier pour définir les ",{"type":30,"tag":46,"props":4023,"children":4024},{},[4025],{"type":35,"value":4026},"comportements de référence",{"type":35,"value":4028}," : quels sont les scénarios nominaux et les scénarios d'erreur qui doivent être garantis ? Cette session produit les spécifications des tests, pas l'inverse.",{"type":30,"tag":52,"props":4030,"children":4031},{},[],{"type":30,"tag":56,"props":4033,"children":4035},{"id":4034},"piège-2-commencer-par-le-code-le-plus-complexe",[4036],{"type":35,"value":4037},"Piège 2 : Commencer par le code le plus complexe",{"type":30,"tag":31,"props":4039,"children":4040},{},[4041],{"type":35,"value":4042},"L'instinct technique pousse à attaquer les modules les plus risqués en premier. C'est une mauvaise stratégie, je l'ai apprise à mes dépens dans mes premiers accompagnements.",{"type":30,"tag":31,"props":4044,"children":4045},{},[4046,4050],{"type":30,"tag":46,"props":4047,"children":4048},{},[4049],{"type":35,"value":4009},{"type":35,"value":4051}," : l'équipe passe 3 semaines à essayer de tester le module central du legacy, celui avec 10 000 lignes de code, 30 dépendances implicites, et une logique métier que personne ne comprend entièrement. Les tests ne compilent pas. L'équipe est bloquée et découragée.",{"type":30,"tag":31,"props":4053,"children":4054},{},[4055,4059,4061,4066],{"type":30,"tag":46,"props":4056,"children":4057},{},[4058],{"type":35,"value":4019},{"type":35,"value":4060}," : commencer par les modules ",{"type":30,"tag":46,"props":4062,"children":4063},{},[4064],{"type":35,"value":4065},"en bordure",{"type":35,"value":4067}," du système, c'est-à-dire les points d'entrée et de sortie. Un test d'intégration qui vérifie qu'une API renvoie le bon status code pour une requête valide est simple à écrire et immédiatement utile. Une fois les tests de bordure en place, progresser vers le centre.",{"type":30,"tag":2167,"props":4069,"children":4070},{},[4071],{"type":30,"tag":31,"props":4072,"children":4073},{},[4074,4079],{"type":30,"tag":46,"props":4075,"children":4076},{},[4077],{"type":35,"value":4078},"Retour sur l'équipe télécoms",{"type":35,"value":4080}," : après l'échec initial sur le moteur de facturation, j'ai proposé de pivoter vers les tests de bordure, à savoir les API REST qui alimentent le moteur. En 2 semaines, 15 tests d'intégration fonctionnels. Ce succès rapide a relancé la motivation et donné une base solide pour progresser vers le centre progressivement.",{"type":30,"tag":52,"props":4082,"children":4083},{},[],{"type":30,"tag":568,"props":4085,"children":4087},{"cta":570,"href":571,"title":4086,"type":573},"Vous voulez savoir par où attaquer un legacy sans tests, et tenir la séquence jusqu'au bout ?",[4088],{"type":30,"tag":31,"props":4089,"children":4090},{},[4091],{"type":35,"value":4092},"Choisir le bon point d'entrée, écrire un characterization test qui tient, savoir quand pivoter quand un module résiste : ça ne s'apprend pas en lisant un article, ça se travaille sur votre vrai code. En mentoring 1:1, on prend vos modules legacy et on construit ensemble la séquence de tests qui vous redonne confiance. Vous repartez avec le réflexe, pas juste avec la théorie.",{"type":30,"tag":52,"props":4094,"children":4095},{},[],{"type":30,"tag":56,"props":4097,"children":4099},{"id":4098},"piège-3-créer-une-dépendance-à-la-base-de-données-de-production",[4100],{"type":35,"value":4101},"Piège 3 : Créer une dépendance à la base de données de production",{"type":30,"tag":31,"props":4103,"children":4104},{},[4105],{"type":35,"value":4106},"Pour tester l'intégration, il faut des données. L'approche la plus simple est de pointer sur la base de données de production (ou une copie) dans les tests. C'est une très mauvaise idée.",{"type":30,"tag":31,"props":4108,"children":4109},{},[4110,4114],{"type":30,"tag":46,"props":4111,"children":4112},{},[4113],{"type":35,"value":4009},{"type":35,"value":1869},{"type":30,"tag":1588,"props":4116,"children":4117},{},[4118,4123,4128,4133],{"type":30,"tag":1592,"props":4119,"children":4120},{},[4121],{"type":35,"value":4122},"Les tests sont non-déterministes : ils dépendent de l'état des données, qui change",{"type":30,"tag":1592,"props":4124,"children":4125},{},[4126],{"type":35,"value":4127},"Les tests ralentissent avec le volume de données",{"type":30,"tag":1592,"props":4129,"children":4130},{},[4131],{"type":35,"value":4132},"Des tests mal écrits peuvent modifier des données réelles",{"type":30,"tag":1592,"props":4134,"children":4135},{},[4136],{"type":35,"value":4137},"La base de prod ne peut pas être réinitialisée entre les tests",{"type":30,"tag":31,"props":4139,"children":4140},{},[4141,4145,4147,4152],{"type":30,"tag":46,"props":4142,"children":4143},{},[4144],{"type":35,"value":4019},{"type":35,"value":4146}," : utiliser une base de test dédiée, initialisée à chaque exécution de test avec un jeu de données connu et contrôlé. Pour les bases relationnelles, les ",{"type":30,"tag":46,"props":4148,"children":4149},{},[4150],{"type":35,"value":4151},"test containers",{"type":35,"value":4153}," (Testcontainers Java, Python, Node.js) permettent de démarrer une vraie base de données dans Docker pour chaque suite de tests : propre, isolée, et détruite après.",{"type":30,"tag":31,"props":4155,"children":4156},{},[4157],{"type":35,"value":4158},"Pour les systèmes avec des données volumineuses, créer un dataset de test représentatif mais minimal (100 à 1 000 enregistrements couvrant tous les scénarios) plutôt que de copier des millions de lignes de prod.",{"type":30,"tag":52,"props":4160,"children":4161},{},[],{"type":30,"tag":56,"props":4163,"children":4165},{"id":4164},"piège-4-ignorer-les-tests-de-régression-comportementale",[4166],{"type":35,"value":4167},"Piège 4 : Ignorer les tests de régression comportementale",{"type":30,"tag":31,"props":4169,"children":4170},{},[4171],{"type":35,"value":4172},"Le legacy a un comportement actuel. Ce comportement, même imparfait, est probablement attendu par les utilisateurs. Des tests d'intégration qui ne couvrent pas ce comportement actuel permettent des régressions silencieuses.",{"type":30,"tag":31,"props":4174,"children":4175},{},[4176,4180],{"type":30,"tag":46,"props":4177,"children":4178},{},[4179],{"type":35,"value":4009},{"type":35,"value":4181}," : l'équipe écrit de nouveaux tests d'intégration basés sur la documentation (incomplète). Des comportements non-documentés mais attendus par les utilisateurs sont cassés lors d'un refactoring. L'équipe l'apprend en production.",{"type":30,"tag":31,"props":4183,"children":4184},{},[4185,4189,4191,4200],{"type":30,"tag":46,"props":4186,"children":4187},{},[4188],{"type":35,"value":4019},{"type":35,"value":4190}," : les ",{"type":30,"tag":46,"props":4192,"children":4193},{},[4194],{"type":30,"tag":454,"props":4195,"children":4197},{"href":4196},"\u002Ffr\u002Fdette-technique\u002Flegacy-code-evaluer-risque",[4198],{"type":35,"value":4199},"characterization tests",{"type":35,"value":4201}," d'abord. Avant d'écrire des tests qui vérifient le comportement attendu, écrire des tests qui documentent le comportement actuel. C'est le concept de Michael Feathers dans \"Working Effectively with Legacy Code\" : un characterization test capture ce que le système fait réellement, pas ce qu'il devrait faire.",{"type":30,"tag":31,"props":4203,"children":4204},{},[4205],{"type":35,"value":4206},"Ces tests ont une propriété précieuse : si un refactoring casse un characterization test, il faut une décision explicite pour valider que le changement de comportement est intentionnel. C'est le filet de sécurité que je rends obligatoire avant toute modification significative d'un legacy.",{"type":30,"tag":52,"props":4208,"children":4209},{},[],{"type":30,"tag":56,"props":4211,"children":4213},{"id":4212},"la-séquence-qui-fonctionne",[4214],{"type":35,"value":4215},"La séquence qui fonctionne",{"type":30,"tag":4217,"props":4218,"children":4219},"ol",{},[4220,4230,4240,4257,4267,4277],{"type":30,"tag":1592,"props":4221,"children":4222},{},[4223,4228],{"type":30,"tag":46,"props":4224,"children":4225},{},[4226],{"type":35,"value":4227},"Session de définition des comportements de référence",{"type":35,"value":4229}," (2-3h avec expert métier) → liste des scénarios à garantir",{"type":30,"tag":1592,"props":4231,"children":4232},{},[4233,4238],{"type":30,"tag":46,"props":4234,"children":4235},{},[4236],{"type":35,"value":4237},"Audit des dépendances",{"type":35,"value":4239}," (1 jour) → cartographie des intégrations externes, DB, services tiers",{"type":30,"tag":1592,"props":4241,"children":4242},{},[4243,4248,4250,4255],{"type":30,"tag":46,"props":4244,"children":4245},{},[4246],{"type":35,"value":4247},"Infrastructure de test",{"type":35,"value":4249}," (2-3 jours) → test containers, fixtures de données, ",{"type":30,"tag":454,"props":4251,"children":4252},{"href":950},[4253],{"type":35,"value":4254},"CI",{"type":35,"value":4256}," configurée",{"type":30,"tag":1592,"props":4258,"children":4259},{},[4260,4265],{"type":30,"tag":46,"props":4261,"children":4262},{},[4263],{"type":35,"value":4264},"Characterization tests sur les chemins critiques",{"type":35,"value":4266}," (1-2 semaines) → documentation du comportement actuel",{"type":30,"tag":1592,"props":4268,"children":4269},{},[4270,4275],{"type":30,"tag":46,"props":4271,"children":4272},{},[4273],{"type":35,"value":4274},"Tests d'intégration de bordure",{"type":35,"value":4276}," (2-3 semaines) → points d'entrée et de sortie du système",{"type":30,"tag":1592,"props":4278,"children":4279},{},[4280,4285],{"type":30,"tag":46,"props":4281,"children":4282},{},[4283],{"type":35,"value":4284},"Progression vers le centre",{"type":35,"value":4286}," (continu) → module par module, en priorisant par criticité",{"type":30,"tag":31,"props":4288,"children":4289},{},[4290],{"type":35,"value":4291},"Cette séquence n'est pas rapide : comptez 6 à 10 semaines pour une base solide. Mais elle produit des tests qui tiennent dans le temps et qui augmentent réellement la confiance de l'équipe.",{"type":30,"tag":568,"props":4293,"children":4295},{"cta":806,"href":807,"title":4294,"type":809},"Tester un legacy proprement n'est qu'une des 100 pratiques qui font un dev senior",[4296],{"type":30,"tag":31,"props":4297,"children":4298},{},[4299],{"type":35,"value":4300},"La séquence décrite ici (comportements de référence, characterization tests, bordure avant le centre) fait partie d'un référentiel plus large : le Craft Bundle, les 100 pratiques que j'applique pour coder propre et garder un legacy sous contrôle. Ce sont celles que l'IA ne vous apprendra jamais, parce qu'elle ne les a jamais vues éviter un incident en prod.",{"type":30,"tag":52,"props":4302,"children":4303},{},[],{"type":30,"tag":56,"props":4305,"children":4307},{"id":4306},"faq-sur-les-tests-dintégration-en-legacy",[4308],{"type":35,"value":4309},"FAQ sur les tests d'intégration en legacy",{"type":30,"tag":826,"props":4311,"children":4312},{},[4313,4318],{"type":30,"tag":830,"props":4314,"children":4315},{},[4316],{"type":35,"value":4317},"1. Quelle est la différence entre un test d'intégration et un test end-to-end ?",{"type":30,"tag":31,"props":4319,"children":4320},{},[4321],{"type":35,"value":4322},"Un test d'intégration vérifie l'interaction entre deux ou plusieurs composants internes du système (ex : service + base de données). Un test end-to-end vérifie un scénario utilisateur complet, de l'interface jusqu'à la persistance. Sur un legacy, je commence par les tests d'intégration : ils sont plus rapides, plus stables, et plus faciles à diagnostiquer que les tests E2E.",{"type":30,"tag":826,"props":4324,"children":4325},{},[4326,4331],{"type":30,"tag":830,"props":4327,"children":4328},{},[4329],{"type":35,"value":4330},"2. Combien de temps faut-il pour avoir une suite de tests d'intégration utile sur un legacy ?",{"type":30,"tag":31,"props":4332,"children":4333},{},[4334],{"type":35,"value":4335},"Pour un legacy de taille moyenne (50 000 à 200 000 lignes de code), comptez 6 à 10 semaines pour avoir une suite couvrant les 10 à 15 scénarios critiques. C'est un investissement qui se rentabilise dès le premier refactoring majeur : une régression évitée sur un module critique vaut facilement 10 fois le coût de la suite de tests.",{"type":30,"tag":826,"props":4337,"children":4338},{},[4339,4344],{"type":30,"tag":830,"props":4340,"children":4341},{},[4342],{"type":35,"value":4343},"3. Faut-il des développeurs dédiés aux tests ou tous les développeurs participent ?",{"type":30,"tag":31,"props":4345,"children":4346},{},[4347],{"type":35,"value":4348},"Tous les développeurs participent. Les tests d'intégration ne sont pas une spécialité, ils sont une responsabilité de l'équipe. En pratique, je désigne un \"test champion\" par équipe pour maintenir l'infrastructure et les standards, mais chaque développeur qui modifie un module doit ajouter ou mettre à jour les tests correspondants.",{"type":30,"tag":826,"props":4350,"children":4351},{},[4352,4357],{"type":30,"tag":830,"props":4353,"children":4354},{},[4355],{"type":35,"value":4356},"4. Comment gérer les tests qui tombent de façon intermittente (flaky tests) ?",{"type":30,"tag":31,"props":4358,"children":4359},{},[4360],{"type":35,"value":4361},"Les flaky tests sont le cancer des suites de tests : ils réduisent la confiance dans tous les tests et poussent les équipes à ignorer les échecs. Ma règle est simple : un flaky test est soit corrigé dans les 48h, soit désactivé avec un ticket de suivi. Un test désactivé qui n'a pas de ticket actif dans le backlog est supprimé. La discipline sur les flaky tests conditionne la confiance dans toute la suite.",{"type":30,"tag":826,"props":4363,"children":4364},{},[4365,4370],{"type":30,"tag":830,"props":4366,"children":4367},{},[4368],{"type":35,"value":4369},"5. Les test containers ralentissent-ils la CI de manière inacceptable ?",{"type":30,"tag":31,"props":4371,"children":4372},{},[4373],{"type":35,"value":4374},"Sur un pipeline bien configuré, non. Les test containers démarrent en 5 à 15 secondes pour une base PostgreSQL ou MySQL. En parallélisant les suites de tests et en utilisant un cache Docker sur la CI, l'impact sur le temps total est marginal. Le vrai coût est le premier setup : 1 à 2 jours pour configurer l'infrastructure. Après ça, chaque nouvelle suite de tests bénéficie de l'infrastructure existante.",{"type":30,"tag":52,"props":4376,"children":4377},{},[],{"type":30,"tag":568,"props":4379,"children":4380},{"cta":2382,"href":919,"title":2383,"type":921},[4381],{"type":30,"tag":31,"props":4382,"children":4383},{},[4384],{"type":35,"value":4385},"L'assessment inclut une évaluation complète de vos pratiques de tests : couverture, types de tests, intégration dans la CI. Identifiez vos angles morts et priorisez les améliorations à fort impact.",{"title":8,"searchDepth":131,"depth":131,"links":4387},[4388,4389,4390,4391,4392,4393,4394],{"id":3948,"depth":131,"text":3951},{"id":3993,"depth":131,"text":3996},{"id":4034,"depth":131,"text":4037},{"id":4098,"depth":131,"text":4101},{"id":4164,"depth":131,"text":4167},{"id":4212,"depth":131,"text":4215},{"id":4306,"depth":131,"text":4309},"content:fr:dette-technique:tests-integration-legacy-pieges.md","fr\u002Fdette-technique\u002Ftests-integration-legacy-pieges.md","fr\u002Fdette-technique\u002Ftests-integration-legacy-pieges",1783466548988]