{"id":17342,"date":"2026-07-29T03:45:01","date_gmt":"2026-07-29T07:45:01","guid":{"rendered":"https:\/\/wp.glbgpt.com\/?p=17342"},"modified":"2026-07-29T03:45:12","modified_gmt":"2026-07-29T07:45:12","slug":"codex-vs-claude-code","status":"publish","type":"post","link":"https:\/\/wp.glbgpt.com\/fr\/hub\/codex-vs-claude-code","title":{"rendered":"Codex ou Claude : quel agent de codage correspond le mieux \u00e0 votre flux de travail ?"},"content":{"rendered":"<p class=\"wp-block-paragraph\"><strong>Codex vs Claude : il ne s'agit pas tant de d\u00e9signer un vainqueur universel que de choisir le mode de fonctionnement auquel vous pouvez faire confiance au quotidien.<\/strong> Ces deux produits permettent d'inspecter un d\u00e9p\u00f4t, de modifier plusieurs fichiers, d'ex\u00e9cuter des commandes, de lancer des tests et d'expliquer un correctif. Les diff\u00e9rences significatives r\u00e9sident dans la mani\u00e8re dont vous d\u00e9l\u00e9guez le travail, la fr\u00e9quence \u00e0 laquelle vous intervenez pour orienter l'agent, la quantit\u00e9 de donn\u00e9es que vous pouvez examiner et la fa\u00e7on dont chaque outil s'int\u00e8gre \u00e0 votre environnement de d\u00e9veloppement existant.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Lors de notre test contr\u00f4l\u00e9 sur un r\u00e9f\u00e9rentiel comprenant quatre t\u00e2ches, Codex a obtenu un score de 98\/100 et Claude Code, un score de 99\/100. Les deux ont accompli le travail essentiel. Claude Code a fait preuve d\u2019une analyse plus approfondie et d\u2019une meilleure couverture des cas limites, tandis que Codex a souvent atteint le r\u00e9sultat requis avec une port\u00e9e plus restreinte et a produit des preuves d\u2019ex\u00e9cution plus solides dans notre configuration. Une diff\u00e9rence d\u2019un point sur un petit test Python ne suffit pas pour d\u00e9signer un vainqueur absolu.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Les d\u00e9veloppeurs qui ne souhaitent pas que le reste de leur flux de travail soit li\u00e9 \u00e0 un seul agent de codage peuvent ajouter GlobalGPT en tant que couche multimod\u00e8le et multimodale distincte. GlobalGPT int\u00e8gre plus de 100 mod\u00e8les de pointe, tels que GPT 5.6, Claude Opus 5 et GPT Image 2, dans un seul tableau de bord. De plus, le <a href=\"https:\/\/www.glbgpt.com\/home\/cli?inviter=hub_content_cli&amp;login=1\">GlobalGPT CLI<\/a>, les parcours MCP et Skill peuvent \u00eatre utilis\u00e9s \u00e0 partir de Codex ou du code Claude pour obtenir des avis compl\u00e9mentaires, planifier, documenter ou exploiter d'autres mod\u00e8les pris en charge, tandis que l'h\u00f4te de codage natif conserve le contr\u00f4le des modifications apport\u00e9es au r\u00e9f\u00e9rentiel et des tests.<\/p>\n\n\n\n<div class=\"wp-block-group is-layout-constrained wp-block-group-is-layout-constrained\">\n<figure class=\"wp-block-image size-large\"><img fetchpriority=\"high\" decoding=\"async\" width=\"1024\" height=\"645\" src=\"https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/glb-1024x645.png\" alt=\"Tableau de bord GlobalGPT\" class=\"wp-image-19280\" srcset=\"https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/glb-1024x645.png 1024w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/glb-300x189.png 300w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/glb-18x11.png 18w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/glb-767x483.png 767w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/glb-1536x967.png 1536w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/glb-2048x1289.png 2048w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div class=\"wp-block-buttons is-content-justification-center is-layout-flex wp-container-core-buttons-is-layout-3e41869c wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link has-black-color has-text-color has-background has-link-color wp-element-button\" href=\"https:\/\/www.glbgpt.com\/home?inviter=hub_popup&amp;login=1\" style=\"background:linear-gradient(135deg,rgba(250,183,0,0.55) 0%,rgba(255,106,0,0.66) 96%)\"><strong>Essayez plus de 100 mod\u00e8les phares sur GlobalGPT<\/strong><\/a><\/div>\n<\/div>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Cette comparaison associe des informations issues des plans officiels, un travail pratique sur les r\u00e9f\u00e9rentiels, des r\u00e9sultats complets et \u00e9volutifs, ainsi que des retours d'exp\u00e9rience clairement identifi\u00e9s par la communaut\u00e9. L'objectif est d'aider un d\u00e9veloppeur ind\u00e9pendant \u00e0 choisir un outil de d\u00e9veloppement principal sans se perdre dans les subtilit\u00e9s de l'acc\u00e8s par abonnement, des cr\u00e9dits suppl\u00e9mentaires et de la facturation des API.<\/p>\n\n\n\n<style>\n.cvc-toc{margin:28px 0;padding:22px;border:1px solid #e2e6ec;border-radius:8px;background:linear-gradient(145deg,#fff 0%,#f7f9fc 100%);color:#18202b;font:14px\/1.4 Inter,-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif}.cvc-toc *{box-sizing:border-box}.cvc-toc .head{display:flex;align-items:end;justify-content:space-between;gap:16px;margin-bottom:16px}.cvc-toc h2{margin:0;font-size:20px}.cvc-toc .hint{color:#667085;font-size:12px}.cvc-toc ol{display:grid;grid-template-columns:1fr 1fr;gap:8px 18px;margin:0;padding:0;list-style:none;counter-reset:toc}.cvc-toc li{counter-increment:toc}.cvc-toc a{display:flex;align-items:center;gap:10px;padding:9px 10px;border-radius:6px;color:#344054;text-decoration:none;transition:background .15s ease,color .15s ease}.cvc-toc a:before{content:counter(toc,decimal-leading-zero);min-width:24px;color:#2563eb;font-size:11px;font-weight:800;letter-spacing:.04em}.cvc-toc a:hover{background:#eef4ff;color:#174ea6}@media(max-width:720px){.cvc-toc ol{grid-template-columns:1fr}.cvc-toc .head{align-items:start;flex-direction:column}.cvc-toc{padding:18px}}\n<\/style>\n<nav class=\"cvc-toc\" aria-label=\"Table des mati\u00e8res\">\n  <div class=\"head\"><h2>Dans cette comparaison<\/h2><span class=\"hint\">Aller \u00e0 une section<\/span><\/div>\n  <ol>\n    <li><a href=\"#quick-comparison\">Comparaison rapide<\/a><\/li><li><a href=\"#what-they-are\">En quoi consistent ces outils ?<\/a><\/li><li><a href=\"#workflow-control\">Flux de travail et contr\u00f4le<\/a><\/li><li><a href=\"#repository-understanding\">Compr\u00e9hension du r\u00e9f\u00e9rentiel<\/a><\/li><li><a href=\"#implementation\">Mise en \u0153uvre et correction de bogues<\/a><\/li><li><a href=\"#code-review\">Qualit\u00e9 de la r\u00e9vision du code<\/a><\/li><li><a href=\"#safety\">Autorisations et s\u00e9curit\u00e9<\/a><\/li><li><a href=\"#customization\">MCP, comp\u00e9tences et personnalisation<\/a><\/li><li><a href=\"#pricing\">Tarifs et limites<\/a><\/li><li><a href=\"#controlled-test\">Essai contr\u00f4l\u00e9<\/a><\/li><li><a href=\"#user-experience\">T\u00e9moignages d'utilisateurs<\/a><\/li><li><a href=\"#globalgpt\">Couche d'extension GlobalGPT<\/a><\/li><li><a href=\"#which-one\">Lequel choisir ?<\/a><\/li><li><a href=\"#faq\">FAQ<\/a><\/li>\n  <\/ol>\n<\/nav>\n\n\n\n<h2 id=\"quick-comparison\" class=\"wp-block-heading\">Codex vs Claude : le code en bref<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Facteur d\u00e9terminant<\/th><th>Codex<\/th><th>Claude Code<\/th><\/tr><\/thead><tbody><tr><td>Travaux relatifs au r\u00e9f\u00e9rentiel principal<\/td><td>Lit, modifie, ex\u00e9cute des commandes et v\u00e9rifie les modifications sur toutes les interfaces Codex prises en charge<\/td><td>Agent de terminal interactif permettant de lire, de modifier, d'ex\u00e9cuter des commandes et de v\u00e9rifier les modifications<\/td><\/tr><tr><td>Style observ\u00e9 lors de notre test<\/td><td>Plus concis dans certaines parties relatives \u00e0 la mise en \u0153uvre et \u00e0 la correction des bogues<\/td><td>Une analyse plus approfondie des d\u00e9p\u00f4ts, des tests et de l'\u00e9tendue des revues<\/td><\/tr><tr><td>Compr\u00e9hension du r\u00e9f\u00e9rentiel<\/td><td colspan=\"2\">Lien fonctionnel avec la t\u00e2che gel\u00e9e<\/td><\/tr><tr><td>Examen du code<\/td><td>Deux d\u00e9fauts valides pr\u00e9sentant un niveau de gravit\u00e9 plus \u00e9lev\u00e9 ont \u00e9t\u00e9 d\u00e9tect\u00e9s et corrig\u00e9s<\/td><td>A signal\u00e9 davantage de probl\u00e8mes reproductibles et a fait passer la note de 19\/20 \u00e0 18\/20<\/td><\/tr><tr><td>Vitesse observ\u00e9e<\/td><td colspan=\"2\">R\u00e9sultats mitig\u00e9s ; les conditions n'\u00e9taient pas suffisamment comparables pour d\u00e9signer un vainqueur incontestable.<\/td><\/tr><tr><td>Gamme d'entr\u00e9e de gamme grand public<\/td><td>$20\/mois dans le cadre du plan ChatGPT correspondant<\/td><td>Claude Pro : $20 par mois aux \u00c9tats-Unis<\/td><\/tr><tr><td>Niveaux de consommation plus \u00e9lev\u00e9s<\/td><td>Niveaux $100 et $200<\/td><td>Max. 5x \u00e0 $100 et max. 20x \u00e0 $200<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Ce tableau pr\u00e9sente une d\u00e9cision d'achat et non un classement des mod\u00e8les. Des param\u00e8tres de mod\u00e8le, un r\u00e9f\u00e9rentiel, une configuration des autorisations ou une sp\u00e9cification de t\u00e2che diff\u00e9rents peuvent modifier le r\u00e9sultat. Si vous utilisez d\u00e9j\u00e0 un produit, la meilleure comparaison consiste \u00e0 utiliser une t\u00e2che d\u00e9limit\u00e9e issue de votre propre base de code, avec la m\u00eame commande de r\u00e9ussite et sans relance de qualit\u00e9.<\/p>\n\n\n\n<style>\n.cvc-profile{--ink:#18202b;--muted:#667085;--line:#e5e8ee;--codex:#2563eb;--claude:#d97706;margin:28px 0;padding:22px;border:1px solid var(--line);border-radius:8px;background:linear-gradient(145deg,#fff 0%,#f8fafc 100%);color:var(--ink);font:14px\/1.45 Inter,-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif}.cvc-profile *{box-sizing:border-box}.cvc-profile h3{margin:0 0 4px;font-size:20px}.cvc-profile .sub{margin:0 0 20px;color:var(--muted)}.cvc-profile .legend{display:flex;gap:18px;margin-bottom:18px;font-weight:700}.cvc-profile .dot{display:inline-block;width:9px;height:9px;margin-right:7px;border-radius:2px}.cvc-profile .task{display:grid;grid-template-columns:190px 1fr 52px;gap:12px;align-items:center;margin:13px 0}.cvc-profile .task strong{font-size:13px}.cvc-profile .tracks{display:grid;gap:5px}.cvc-profile .track{height:9px;overflow:hidden;border-radius:5px;background:#e9edf3}.cvc-profile .fill{height:100%;border-radius:5px}.cvc-profile .codex{background:var(--codex)}.cvc-profile .claude{background:var(--claude)}.cvc-profile .score{text-align:right;font-variant-numeric:tabular-nums;font-weight:800}.cvc-profile .note{margin:18px 0 0;padding-top:14px;border-top:1px solid var(--line);color:var(--muted);font-size:12px}@media(max-width:650px){.cvc-profile .task{grid-template-columns:1fr 46px}.cvc-profile .task>strong{grid-column:1\/-1}.cvc-profile{padding:18px}}\n<\/style>\n<section class=\"cvc-profile\" aria-label=\"Profil des r\u00e9sultats aux tests dans un cadre contr\u00f4l\u00e9\">\n  <h3>Profil d'essai contr\u00f4l\u00e9<\/h3>\n  <p class=\"sub\">Premier r\u00e9sultat valide, selon la m\u00eame grille d'\u00e9valuation fixe. Les barres sont normalis\u00e9es par rapport \u00e0 la note maximale de chaque t\u00e2che.<\/p>\n  <div class=\"legend\"><span><i class=\"dot\" style=\"background:#2563eb\"><\/i>Codex<\/span><span><i class=\"dot\" style=\"background:#d97706\"><\/i>Claude Code<\/span><\/div>\n  <div class=\"task\"><strong>T1 \u00b7 Compr\u00e9hension du r\u00e9f\u00e9rentiel<\/strong><div class=\"tracks\"><div class=\"track\"><div class=\"fill codex\" style=\"width:100%\"><\/div><\/div><div class=\"track\"><div class=\"fill claude\" style=\"width:100%\"><\/div><\/div><\/div><span class=\"score\">20 \/ 20<\/span><\/div>\n  <div class=\"task\"><strong>T2 \u00b7 Fonctionnalit\u00e9 de gestion de plusieurs fichiers<\/strong><div class=\"tracks\"><div class=\"track\"><div class=\"fill codex\" style=\"width:100%\"><\/div><\/div><div class=\"track\"><div class=\"fill claude\" style=\"width:100%\"><\/div><\/div><\/div><span class=\"score\">30 \/ 30<\/span><\/div>\n  <div class=\"task\"><strong>T3 \u00b7 Correction d'un bug li\u00e9 \u00e0 l'heure d'\u00e9t\u00e9<\/strong><div class=\"tracks\"><div class=\"track\"><div class=\"fill codex\" style=\"width:100%\"><\/div><\/div><div class=\"track\"><div class=\"fill claude\" style=\"width:100%\"><\/div><\/div><\/div><span class=\"score\">30 \/ 30<\/span><\/div>\n  <div class=\"task\"><strong>T4 \u00b7 V\u00e9rification et r\u00e9paration<\/strong><div class=\"tracks\"><div class=\"track\"><div class=\"fill codex\" style=\"width:90%\"><\/div><\/div><div class=\"track\"><div class=\"fill claude\" style=\"width:95%\"><\/div><\/div><\/div><span class=\"score\">18 \/ 19<\/span><\/div>\n  <p class=\"note\">Le graphique montre d'o\u00f9 provient cette diff\u00e9rence d'un point ; il ne transforme pas un petit match en classement g\u00e9n\u00e9ral.<\/p>\n<\/section>\n\n\n\n<h2 id=\"what-they-are\" class=\"wp-block-heading\">Qu'est-ce que le Codex et le code Claude ?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\u00ab Codex \u00bb et \u00ab Claude Code \u00bb sont des produits d'agent, et non de simples noms de mod\u00e8les. Le concept sous-jacent <a href=\"https:\/\/www.glbgpt.com\/hub\/best-ai-model-for-coding\/\">Mod\u00e8le d'IA pour le codage<\/a> C'est important, mais l'environnement qui l'entoure d\u00e9termine \u00e9galement quels fichiers l'agent peut consulter, quelles commandes il est autoris\u00e9 \u00e0 ex\u00e9cuter, comment fonctionnent les validations, comment le contexte est conserv\u00e9 et quelles donn\u00e9es sont conserv\u00e9es une fois la t\u00e2che termin\u00e9e. Se limiter \u00e0 comparer la r\u00e9putation des mod\u00e8les revient \u00e0 ignorer une grande partie de l'exp\u00e9rience que le d\u00e9veloppeur acquiert.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Codex couvre les flux de travail en ligne de commande, en IDE, sur ordinateur de bureau et orient\u00e9s cloud. Cette polyvalence le rend adapt\u00e9 aussi bien \u00e0 la collaboration locale directe qu\u2019\u00e0 une d\u00e9l\u00e9gation plus cibl\u00e9e. Claude Code s\u2019articule autour d\u2019un flux de travail conversationnel en terminal, avec des int\u00e9grations prises en charge et de nombreuses possibilit\u00e9s de personnalisation ; cela <a href=\"https:\/\/www.glbgpt.com\/hub\/how-to-use-claude-ai-for-coding\/\">Guide d'utilisation de Claude pour le codage<\/a> offre une introduction plus compl\u00e8te \u00e0 ce flux de travail. Pour certains d\u00e9veloppeurs, observer le fonctionnement d\u2019un agent dans le terminal est rassurant. Pour d\u2019autres, ce sont le diff final, les tests et la piste d\u2019audit qui constituent les \u00e9l\u00e9ments essentiels, plut\u00f4t qu\u2019un \u00e9change continu.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Cette distinction explique \u00e9galement pourquoi deux tests utilisant des mod\u00e8les th\u00e9oriquement performants peuvent donner des r\u00e9sultats diff\u00e9rents. C'est l'h\u00f4te qui d\u00e9termine la mani\u00e8re dont les instructions sont pr\u00e9sent\u00e9es, comment les outils sont appel\u00e9s et \u00e0 quel moment un humain doit valider une action. Les comparaisons au sein de la communaut\u00e9 qui ne tiennent pas compte de ce cadre de test risquent de confondre un comportement observ\u00e9 au niveau du produit avec une v\u00e9rit\u00e9 au niveau du mod\u00e8le.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Le mod\u00e8le<\/strong> offre des capacit\u00e9s de raisonnement et de g\u00e9n\u00e9ration.<\/li>\n\n\n\n<li><strong>Le harnais de l'agent<\/strong> g\u00e8re les fichiers, les commandes, le contexte, les validations et la restauration.<\/li>\n\n\n\n<li><strong>Le contrat de mission de l'utilisateur<\/strong> d\u00e9termine le champ d'application, les crit\u00e8res de r\u00e9ussite et le moment o\u00f9 l'agent doit s'arr\u00eater.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"1280\" height=\"800\" src=\"https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/x-harness-vs-model-caveat-annotated.webp\" alt=\"Un message X annot\u00e9 soulignant qu\u2019un \u00ab agent harness \u00bb peut influencer les comparaisons entre le code et l\u2019agent\" class=\"wp-image-17390\" srcset=\"https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/x-harness-vs-model-caveat-annotated.webp 1280w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/x-harness-vs-model-caveat-annotated-300x188.webp 300w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/x-harness-vs-model-caveat-annotated-1024x640.webp 1024w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/x-harness-vs-model-caveat-annotated-768x480.webp 768w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/x-harness-vs-model-caveat-annotated-18x12.webp 18w\" sizes=\"(max-width: 1280px) 100vw, 1280px\" \/><figcaption class=\"wp-element-caption\">Un commentaire de l'utilisateur X met en \u00e9vidence une r\u00e9serve importante concernant cette comparaison : le harnais de l'agent peut influencer les r\u00e9sultats. Il s'agit d'une information contextuelle utile, et non d'une preuve formelle d\u00e9montrant que l'un ou l'autre des produits est meilleur.<\/figcaption><\/figure>\n\n\n\n<h2 id=\"workflow-control\" class=\"wp-block-heading\">Processus de travail et pilotage : d\u00e9l\u00e9gation ou accompagnement continu ?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">La question la plus pertinente concernant le Codex et le code Claude n'est souvent pas \u201c Lequel permet d'\u00e9crire un meilleur code ? \u201d, mais \u201c Comment est-ce que je souhaite l'utiliser ? \u201d Une t\u00e2che claire et bien d\u00e9limit\u00e9e peut \u00eatre d\u00e9l\u00e9gu\u00e9e avec un objectif pr\u00e9cis, un p\u00e9rim\u00e8tre d\u00e9fini et une commande de v\u00e9rification. Une refactorisation ambigu\u00eb n\u00e9cessite une discussion, une inspection interm\u00e9diaire et la possibilit\u00e9 de r\u00e9orienter l'agent avant qu'il n'apporte trop de modifications.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">La gestion continue s'av\u00e8re utile lorsque les exigences \u00e9voluent ou que les choix architecturaux font encore l'objet de discussions. Elle devient un surco\u00fbt lorsque l'agent sollicite \u00e0 plusieurs reprises des d\u00e9cisions qui auraient pu \u00eatre prises \u00e0 partir des instructions du r\u00e9f\u00e9rentiel. L'ex\u00e9cution autonome est utile lorsque le cahier des charges de la t\u00e2che est stable. Elle devient risqu\u00e9e lorsque l'agent \u00e9met des hypoth\u00e8ses non v\u00e9rifi\u00e9es ou \u00e9largit le p\u00e9rim\u00e8tre de la t\u00e2che sans disposer d'une proc\u00e9dure de retour en arri\u00e8re claire.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Un rapport d\u00e9taill\u00e9 publi\u00e9 sur Reddit le 13 avril 2026 d\u00e9crivait environ 100 heures pass\u00e9es avec Claude Code et 20 heures avec Codex sur un projet Python et TypeScript d\u2019environ 80 000 lignes comprenant quelque 2 800 tests. L'auteur a qualifi\u00e9 Claude de plus rapide et plus interactif, mais n\u00e9cessitant davantage de surveillance, et Codex de plus lent et plus r\u00e9fl\u00e9chi. Ce rapport est particuli\u00e8rement utile car il inclut le contexte du projet et de l'exp\u00e9rience, mais il ne repr\u00e9sente n\u00e9anmoins que le flux de travail d'un seul d\u00e9veloppeur.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"1280\" height=\"800\" src=\"https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/reddit-claude-code-vs-codex-experience-annotated.webp\" alt=\"Exp\u00e9rience comment\u00e9e sur Reddit comparant Claude Code et Codex dans le cadre d&#039;un projet de 80 000 lignes de code\" class=\"wp-image-17391\" srcset=\"https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/reddit-claude-code-vs-codex-experience-annotated.webp 1280w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/reddit-claude-code-vs-codex-experience-annotated-300x188.webp 300w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/reddit-claude-code-vs-codex-experience-annotated-1024x640.webp 1024w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/reddit-claude-code-vs-codex-experience-annotated-768x480.webp 768w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/reddit-claude-code-vs-codex-experience-annotated-18x12.webp 18w\" sizes=\"(max-width: 1280px) 100vw, 1280px\" \/><figcaption class=\"wp-element-caption\">Exp\u00e9rience sp\u00e9cifique \u00e0 un projet d'un d\u00e9veloppeur avec Claude Code et Codex. Les observations mises en avant doivent \u00eatre consid\u00e9r\u00e9es comme des hypoth\u00e8ses \u00e0 v\u00e9rifier, et non comme des donn\u00e9es de performances applicables \u00e0 l'ensemble du produit.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Nos propres chronom\u00e9trages n\u2019ont pas permis de d\u00e9signer un vainqueur incontestable. Claude a termin\u00e9 les deux premi\u00e8res t\u00e2ches plus rapidement, tandis que Codex a termin\u00e9 les deux derni\u00e8res plus rapidement. Claude a \u00e9galement eu recours \u00e0 un sous-agent de secours lorsque son chemin d\u2019authentification CLI \u00e9tait indisponible ; les parcours d\u2019ex\u00e9cution n\u2019\u00e9taient donc pas \u00e9quivalents \u00e0 ceux du laboratoire. La conclusion qui s'impose est que la vitesse d\u00e9pend de la t\u00e2che, du mod\u00e8le s\u00e9lectionn\u00e9, du niveau d'effort, du contexte et de l'h\u00f4te \u2014 et non pas que l'un ou l'autre des produits soit syst\u00e9matiquement plus rapide.<\/p>\n\n\n\n<h2 id=\"repository-understanding\" class=\"wp-block-heading\">Compr\u00e9hension du r\u00e9f\u00e9rentiel et gestion du contexte<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">La compr\u00e9hension d'un r\u00e9f\u00e9rentiel ne se limite pas \u00e0 la simple d\u00e9nomination des dossiers. Un agent efficace doit suivre le parcours des donn\u00e9es d'un fichier \u00e0 l'autre, identifier les contraintes qui limitent une modification, localiser les tests, distinguer un sympt\u00f4me de sa source probable et expliquer le risque li\u00e9 \u00e0 la modification d'une couche inappropri\u00e9e. Une cartographie exhaustive peut r\u00e9v\u00e9ler des incoh\u00e9rences cach\u00e9es ; une cartographie concise peut permettre \u00e0 un d\u00e9veloppeur de prendre plus rapidement une d\u00e9cision de mise en \u0153uvre s\u00fbre.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dans notre t\u00e2che T1 en lecture seule, les deux agents ont obtenu un score de 20\/20 et ont \u00e9tay\u00e9 leurs r\u00e9ponses \u00e0 l\u2019aide du r\u00e9f\u00e9rentiel. Le code Claude s\u2019est r\u00e9v\u00e9l\u00e9 plus exhaustif et a mis en \u00e9vidence des incoh\u00e9rences suppl\u00e9mentaires dans les contrats. Codex s\u2019est montr\u00e9 plus concis tout en identifiant les fichiers pertinents, les risques et le plan de mise en \u0153uvre. Aucun des deux styles n\u2019est automatiquement sup\u00e9rieur. L\u2019exhaustivit\u00e9 est utile lors de migrations et d\u2019audits dans un contexte inconnu ; la concision est utile lorsque le d\u00e9veloppeur conna\u00eet d\u00e9j\u00e0 l\u2019architecture et souhaite un plan de changement cibl\u00e9.<\/p>\n\n\n\n<style>\n.evidence-t1-repository-understanding{--ink:#111318;--body:#414753;--muted:#707784;--line:#e4e7ec;--soft:#f6f7f9;--blue:#315efb;--violet:#7257e8;--green:#087a55;--greenSoft:#eaf8f2;--red:#a23131;--redSoft:#fff0f0;color:var(--ink);font-family:Inter,ui-sans-serif,-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif;line-height:1.5;border:1px solid var(--line);border-radius:8px;background:#fff;overflow:hidden;box-shadow:0 16px 42px rgba(24,32,56,.08)}\n.evidence-t1-repository-understanding *{box-sizing:border-box}.evidence-t1-repository-understanding .d-head{display:flex;align-items:flex-start;justify-content:space-between;gap:22px;padding:24px 26px 20px;border-bottom:1px solid var(--line)}\n.evidence-t1-repository-understanding .d-kicker{margin:0 0 6px;color:var(--muted);font:750 11px\/1.4 ui-monospace,SFMono-Regular,Menlo,monospace;letter-spacing:.08em;text-transform:uppercase}.evidence-t1-repository-understanding .d-title{margin:0;font-size:22px;line-height:1.2;letter-spacing:-.025em}.evidence-t1-repository-understanding .d-sub{margin:7px 0 0;color:var(--body);font-size:13px}.evidence-t1-repository-understanding .d-pill{flex:0 0 auto;padding:6px 10px;border:1px solid #ccd6ff;border-radius:999px;color:#2448ca;background:#f0f3ff;font-size:11px;font-weight:800}.evidence-t1-repository-understanding .d-grid{display:grid;grid-template-columns:1fr 1fr}.evidence-t1-repository-understanding .d-side{min-width:0;padding:24px 26px}.evidence-t1-repository-understanding .d-side+.d-side{border-left:1px solid var(--line)}.evidence-t1-repository-understanding .d-product{display:flex;align-items:baseline;justify-content:space-between;gap:14px;font-weight:800}.evidence-t1-repository-understanding .d-score{font-size:34px;line-height:1;letter-spacing:-.05em}.evidence-t1-repository-understanding .d-score small{color:var(--muted);font-size:12px;letter-spacing:0}.evidence-t1-repository-understanding .d-metrics{display:grid;grid-template-columns:repeat(3,1fr);gap:7px;margin:18px 0}.evidence-t1-repository-understanding .d-metric{padding:10px;border:1px solid var(--line);border-radius:6px;background:var(--soft)}.evidence-t1-repository-understanding .d-metric span{display:block;color:var(--muted);font-size:9px;font-weight:800;letter-spacing:.06em;text-transform:uppercase}.evidence-t1-repository-understanding .d-metric strong{display:block;margin-top:3px;font-size:13px}.evidence-t1-repository-understanding .d-preview{position:relative;height:192px;overflow:hidden;border:1px solid #29313f;border-radius:6px;background:#11151d;color:#edf0f5}.evidence-t1-repository-understanding .d-preview-label{padding:11px 13px;border-bottom:1px solid rgba(255,255,255,.1);color:#aeb7c7;font:750 9px\/1 ui-monospace,SFMono-Regular,Menlo,monospace;letter-spacing:.06em;text-transform:uppercase}.evidence-t1-repository-understanding .d-preview pre,.evidence-t1-repository-understanding .d-full pre{margin:0;white-space:pre-wrap;font:11px\/1.6 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.evidence-t1-repository-understanding .d-preview pre{padding:13px}.evidence-t1-repository-understanding .d-preview:after{content:\"\";position:absolute;left:0;right:0;bottom:0;height:55px;background:linear-gradient(transparent,#11151d)}.evidence-t1-repository-understanding .d-take{margin:14px 0 0;color:var(--body);font-size:12px}.evidence-t1-repository-understanding .d-fulls{padding:0 26px 22px}.evidence-t1-repository-understanding .d-full{margin-top:10px;border:1px solid var(--line);border-radius:6px}.evidence-t1-repository-understanding .d-full summary{cursor:pointer;padding:13px 14px;font-size:12px;font-weight:800;list-style:none}.evidence-t1-repository-understanding .d-full summary::-webkit-details-marker{display:none}.evidence-t1-repository-understanding .d-full summary:after{content:\"+\";float:right;color:var(--blue);font-size:17px}.evidence-t1-repository-understanding .d-full[open] summary:after{content:\"\u2212\"}.evidence-t1-repository-understanding .d-full-pane{padding:0 14px 14px}.evidence-t1-repository-understanding .d-full-note{margin:0 0 9px;color:var(--muted);font-size:10px}.evidence-t1-repository-understanding .d-full pre{max-height:620px;overflow:auto;padding:15px;border-radius:5px;background:#f5f6f8;color:#222936;border:1px solid #e0e3e8}.evidence-t1-repository-understanding .d-limit{margin:0;padding:12px 26px;border-top:1px solid var(--line);color:#5a6270;background:#fafbfc;font-size:11px}\n@media(max-width:760px){.evidence-t1-repository-understanding .d-head{display:block}.evidence-t1-repository-understanding .d-pill{display:inline-block;margin-top:12px}.evidence-t1-repository-understanding .d-grid{grid-template-columns:1fr}.evidence-t1-repository-understanding .d-side+.d-side{border-left:0;border-top:1px solid var(--line)}}@media(max-width:480px){.evidence-t1-repository-understanding .d-head,.evidence-t1-repository-understanding .d-side{padding:20px}.evidence-t1-repository-understanding .d-fulls{padding:0 20px 20px}.evidence-t1-repository-understanding .d-metrics{grid-template-columns:1fr}}\n<\/style><article class=\"evidence-t1-repository-understanding\"><header class=\"d-head\"><div><p class=\"d-kicker\">T1 \u00b7 Test du r\u00e9f\u00e9rentiel contr\u00f4l\u00e9<\/p><h3 class=\"d-title\">Se familiariser avec un r\u00e9f\u00e9rentiel que l'on ne conna\u00eet pas avant de le modifier<\/h3><p class=\"d-sub\">Cartographier l'architecture, suivre le flux de donn\u00e9es, identifier les risques li\u00e9s aux fonctionnalit\u00e9s prioritaires, sans apporter aucune modification aux fichiers.<\/p><\/div><span class=\"d-pill\">Cravate<\/span><\/header><div class=\"d-grid\"><section class=\"d-side\" aria-label=\"R\u00e9sultat du Codex\"><div class=\"d-product\"><span>Codex<\/span><span class=\"d-score\">20<small>\/20<\/small><\/span><\/div><div class=\"d-metrics\"><div class=\"d-metric\"><span>Dur\u00e9e<\/span><strong>108 s<\/strong><\/div><div class=\"d-metric\"><span>Ch\u00e8ques<\/span><strong>2 : valeur de r\u00e9f\u00e9rence<\/strong><\/div><div class=\"d-metric\"><span>Champ d'application<\/span><strong>Lecture seule<\/strong><\/div><\/div><div class=\"d-preview\"><div class=\"d-preview-label\">Extrait de la premi\u00e8re sortie valide<\/div><pre>Architecture : mod\u00e8le, r\u00e9f\u00e9rentiel, service et utilitaire de gestion du temps non connect\u00e9.\n\nPrincipaux risques : s\u00e9mantique des priorit\u00e9s non d\u00e9finie, compatibilit\u00e9, ordre d'ex\u00e9cution, validation et incompatibilit\u00e9 de port\u00e9e.<\/pre><\/div><p class=\"d-take\"><strong>Avis du critique :<\/strong> Concis, \u00e9tay\u00e9 par des \u00e9l\u00e9ments concrets et suffisant pour prendre la d\u00e9cision en suspens.<\/p><\/section><section class=\"d-side\" aria-label=\"R\u00e9sultat du code Claude\"><div class=\"d-product\"><span>Claude Code<\/span><span class=\"d-score\">20<small>\/20<\/small><\/span><\/div><div class=\"d-metrics\"><div class=\"d-metric\"><span>Dur\u00e9e<\/span><strong>61 s<\/strong><\/div><div class=\"d-metric\"><span>Ch\u00e8ques<\/span><strong>2 : valeur de r\u00e9f\u00e9rence<\/strong><\/div><div class=\"d-metric\"><span>Champ d'application<\/span><strong>Lecture seule<\/strong><\/div><\/div><div class=\"d-preview\"><div class=\"d-preview-label\">Extrait de la premi\u00e8re sortie valide<\/div><pre>Trois couches plus un module isol\u00e9. Pas de boucles ; injection de d\u00e9pendances minimale.\n\nCela a \u00e9galement mis en \u00e9vidence l'attribution des identifiants, les contrats d'erreur asym\u00e9triques et une couverture de test insuffisante.<\/pre><\/div><p class=\"d-take\"><strong>Avis du critique :<\/strong> Plus exhaustif tout en respectant le m\u00eame contrat de lecture seule.<\/p><\/section><\/div><div class=\"d-fulls\"><details class=\"d-full\"><summary>Afficher l'int\u00e9gralit\u00e9 des r\u00e9sultats de Codex<\/summary><div class=\"d-full-pane\"><p class=\"d-full-note\">Sortie compl\u00e8te, valid\u00e9e et aseptis\u00e9e<\/p><pre>Architecture ##\n\nIl s'agit d'un petit module Python utilisant uniquement les biblioth\u00e8ques standard et comportant quatre couches fonctionnelles :\n\n- **Mod\u00e8le de donn\u00e9es :** [`Job`]() est une classe de donn\u00e9es immuable contenant `identifier`, `name` et `owner`. La m\u00e9thode `Job.to_dict()` la s\u00e9rialise via `dataclasses.asdict()`.\n- **R\u00e9f\u00e9rentiel :** [`JobRepository`]() stocke les t\u00e2ches dans un dictionnaire en m\u00e9moire dont les cl\u00e9s sont les identifiants. Il n\u2019y a ni base de donn\u00e9es ni persistance durable.\n- **Service :** [`SchedulerService`]() g\u00e8re l\u2019attribution des identifiants, la normalisation des entr\u00e9es, la cr\u00e9ation, la liste et la suppression des t\u00e2ches.\n- **Utilitaire de temps :** [`next_daily_run()`]() calcule l\u2019heure de l\u2019ex\u00e9cution suivante, mais aucune fonction ne l\u2019importe ni ne le relie \u00e0 `Job`, `SchedulerService` ou `JobRepository`.\n- **API publique :** [`scheduler.__init__`]() n\u2019exporte que `SchedulerService`.\n\nMalgr\u00e9 le nom du r\u00e9f\u00e9rentiel, les t\u00e2ches ne contiennent actuellement aucune information de planification, et il n\u2019existe pas de file d\u2019attente d\u2019ex\u00e9cution. La priorit\u00e9 peut donc affecter les m\u00e9tadonn\u00e9es stock\u00e9es et l\u2019ordre d\u2019affichage, mais elle ne peut pas influencer l\u2019ex\u00e9cution effective des t\u00e2ches sans \u00e9largir consid\u00e9rablement le syst\u00e8me.\n\n## Flux de donn\u00e9es de cr\u00e9ation et d\u2019affichage\n\nCr\u00e9ation via `SchedulerService.create_job(name, owner)` :\n\n1. [`create_job()`]() rejette un nom compos\u00e9 uniquement d\u2019espaces.\n2. Il tronque `name` et `owner`, puis construit un objet `Job` immuable en utilisant le `_next_identifier` du service.\n3. [`JobRepository.save()`]() enregistre l\u2019objet dans `_jobs[job.identifier]`.\n4. Le service incr\u00e9mente `_next_identifier` et renvoie le m\u00eame `Job`.\n\nListe via `SchedulerService.list_jobs()` :\n\n1. [`list_jobs()`]() d\u00e9l\u00e8gue directement \u00e0 `repository.all()`.\n2. [`JobRepository.all()`]() trie les cl\u00e9s du dictionnaire par ordre num\u00e9rique.\n3. Les t\u00e2ches sont donc renvoy\u00e9es par ordre croissant d\u2019identifiant\/de cr\u00e9ation, et non par ordre de planification ou de priorit\u00e9.\n\n## Fichiers susceptibles d\u2019\u00eatre affect\u00e9s par les priorit\u00e9s des t\u00e2ches\n\nObligatoire :\n\n- [`scheduler\/models.py`]() : ajouter le champ \" priority \" et une valeur par d\u00e9faut \u00e9ventuelle. `to_dict()` l\u2019inclura automatiquement car il utilise `asdict()`.\n- [`scheduler\/service.py`]() : accepter, valider et transmettre la priorit\u00e9 \u00e0 `Job`.\n- [`tests\/test_scheduler.py`]() : tester les cas par d\u00e9faut, explicites, non valides, s\u00e9rialis\u00e9s et de classement.\n\nConditionnel :\n\n- [`scheduler\/repository.py`]() : ne modifier `all()` que si les priorit\u00e9s sont destin\u00e9es \u00e0 contr\u00f4ler l\u2019ordre d\u2019affichage. Une cl\u00e9 secondaire d\u00e9terministe telle que `identifier` devrait g\u00e9rer les ex aequo.\n- [`scheduler\/__init__.py`]() : \u00e0 mettre \u00e0 jour uniquement si la priorit\u00e9 devient une \u00e9num\u00e9ration publique ou un objet valeur.\n- [`README.md`]() : documenter les valeurs accept\u00e9es, la valeur par d\u00e9faut et la s\u00e9mantique de classement.\n\nProbablement non concern\u00e9 :\n\n- `scheduler\/time_rules.py`, car son seul symbole op\u00e8re sur une date-heure fournie et n\u2019a aucun rapport avec les t\u00e2ches ou le classement.\n\n## Risques majeurs\n\n- **S\u00e9mantique non d\u00e9finie :** le code ne fournit aucun indice permettant de d\u00e9terminer si des valeurs plus grandes ou plus petites correspondent \u00e0 une priorit\u00e9 plus \u00e9lev\u00e9e, quelles valeurs sont valides, ou si la priorit\u00e9 a une incidence sur le classement.\n- **Compatibilit\u00e9 :** L\u2019ajout d\u2019un argument obligatoire \u00e0 `Job` ou \u00e0 `create_job()` casserait les appels existants, tels que `create_job(\"Daily report\", \"Alex\")` dans le test actuel. Une valeur par d\u00e9faut permettrait de pr\u00e9server cet appel.\n- **Probl\u00e8me li\u00e9 \u00e0 la construction par position :** `Job` est actuellement construit par position dans `SchedulerService.create_job()`. Le placement des champs et les futurs appels par position pourraient attribuer silencieusement des valeurs erron\u00e9es ; une construction par mots-cl\u00e9s serait plus s\u00fbre.\n- **Modification de l\u2019ordre :** Le remplacement de l\u2019ordre des identifiants dans `JobRepository.all()` modifie le comportement \u00e9tabli. Les priorit\u00e9s \u00e9gales n\u00e9cessitent un crit\u00e8re de d\u00e9partage stable.\n- **Ambigu\u00eft\u00e9 de validation :** Une valeur Python non restreinte pourrait autoriser des cha\u00eenes de caract\u00e8res, des bool\u00e9ens ou des entiers arbitraires difficiles \u00e0 comparer de mani\u00e8re coh\u00e9rente.\n- **Incoh\u00e9rence au niveau de la port\u00e9e d\u2019ex\u00e9cution :** il n\u2019existe ni r\u00e9partiteur ni file d\u2019attente d\u2019ex\u00e9cution. L\u2019affirmation selon laquelle la priorit\u00e9 d\u00e9termine quel travail s\u2019ex\u00e9cute en premier ne serait \u00e9tay\u00e9e par aucun symbole actuel.\n- **Limitations en m\u00e9moire :** la priorit\u00e9, comme tous les autres champs de t\u00e2che, dispara\u00eet \u00e0 la fin du processus, car `_jobs` n\u2019est qu\u2019un dictionnaire d\u2019instance.\n\n## Plan de mise en \u0153uvre et de validation\n\n1. D\u00e9finir d\u2019abord le contrat : repr\u00e9sentation, valeurs autoris\u00e9es, valeur par d\u00e9faut, sens de la priorit\u00e9, r\u00e8gle de d\u00e9partage et indication pr\u00e9cisant si cela modifie l\u2019ordre d\u2019affichage.\n2. Ajouter `priority` \u00e0 `Job`, de pr\u00e9f\u00e9rence avec une valeur par d\u00e9faut r\u00e9trocompatible.\n3. \u00c9tendre `SchedulerService.create_job()` avec un param\u00e8tre de priorit\u00e9 par d\u00e9faut, le valider, puis construire `Job` \u00e0 l\u2019aide d\u2019arguments-cl\u00e9s.\n4. Si le classement tient compte de la priorit\u00e9, modifier `JobRepository.all()` pour trier d\u2019abord par priorit\u00e9, puis par identifiant. Sinon, laisser l\u2019ordre du r\u00e9f\u00e9rentiel inchang\u00e9.\n5. Ajouter des tests pour :\n   - La cr\u00e9ation existante \u00e0 deux arguments.\n   - La pr\u00e9servation explicite de la priorit\u00e9.\n   - La priorit\u00e9 par d\u00e9faut.\n   - Types non valides et valeurs hors plage.\n   - Sortie de `Job.to_dict()`.\n   - Ordre d\u2019affichage en cas de priorit\u00e9s multiples.\n   - Ordre stable pour des priorit\u00e9s \u00e9gales.\n   - Comportement actuel en cas de nom vide.\n6. Mettre \u00e0 jour le fichier README avec le contrat public exact.\n7. Ex\u00e9cuter la suite de tests hors ligne compl\u00e8te avec `python3 -m unittest discover -s tests -v`.\n\n## V\u00e9rification effectu\u00e9e\n\n- Suite de tests de r\u00e9f\u00e9rence : **2 tests r\u00e9ussis**.\n- La recherche de symboles \u00e0 l\u2019\u00e9chelle du r\u00e9f\u00e9rentiel a confirm\u00e9 que `next_daily_run()` est d\u00e9connect\u00e9 et qu\u2019il n\u2019existe aucun symbole de priorit\u00e9.\n- Fichiers modifi\u00e9s : **aucun**.\n- Impl\u00e9mentation de la fonctionnalit\u00e9 : **non effectu\u00e9e**, comme requis.\n\n&gt; **Conclusion + d\u00e9cision**\n&gt;\n&gt; La modification est mineure si la priorit\u00e9 ne concerne que les m\u00e9tadonn\u00e9es ou l\u2019ordre d\u2019affichage : principalement `models.py`, `service.py`, `repository.py` et les tests. Avant la mise en \u0153uvre, il convient de d\u00e9terminer si la priorit\u00e9 d\u00e9crit simplement une t\u00e2che ou si elle modifie l\u2019ordre de `list_jobs()`, ainsi que l\u2019\u00e9chelle de valeurs, la valeur par d\u00e9faut, la direction et la r\u00e8gle de d\u00e9partage.<\/pre><\/div><\/details><details class=\"d-full\"><summary>Afficher l'int\u00e9gralit\u00e9 du code de sortie Claude<\/summary><div class=\"d-full-pane\"><p class=\"d-full-note\">Compte rendu complet du transfert, y compris la transcription mot pour mot de la premi\u00e8re sortie valide<\/p><pre># T1 Journal d'ex\u00e9cution \u2014 Compr\u00e9hension d'un r\u00e9f\u00e9rentiel inconnu\n\n## Param\u00e8tres d'ex\u00e9cution\n\n| Champ | Valeur |\n| --- | --- |\n| T\u00e2che | `T1` |\n| Invite fig\u00e9e | `01-prompts\/T1.md` |\n| SHA-256 de la prompt gel\u00e9e | `a571ff15c2502ec29b172ae2e77dd9ab0caca2869b91f9468d47571434d16c17` |\n| Unit\u00e9 d\u2019ex\u00e9cution | sous-agent Claude isol\u00e9, `usage g\u00e9n\u00e9ral`, contexte vierge |\n| M\u00e9thode d\u2019isolation | **repli sur un sous-agent** (r\u00e9trogradation document\u00e9e \u2014 voir `results\/isolation-decision.md`) |\n| Copie propre attribu\u00e9e | `runtime\/workspaces\/T1` |\n| Version du code Claude | `2.1.220` |\n| Param\u00e9trage du mod\u00e8le | `claude-opus-5` |\n| start_utc | `2026-07-28T10:27:31Z` |\n| end_utc | `2026-07-28T10:28:32Z` |\n| Dur\u00e9e | 61 s (en parall\u00e8le avec T2\u2013T4 ; mesure de latence non fiable) |\n| Num\u00e9ro de tentative | 1 |\n| Statut | `valide` |\n| Intervention humaine | aucune |\n\n## R\u00e9sum\u00e9 de l\u2019outil Safe\n\n`date`, `find`, `ls`, `wc`, `stat`, `grep`, `Read` sur 7 fichiers de l'espace de travail, `python3 -V`,\n`python3 -m unittest discover -s tests -v`. Toutes les lectures sont confin\u00e9es \u00e0 l'espace de travail attribu\u00e9.\nPas de r\u00e9seau, pas d\u2019installations, pas d\u2019\u00e9critures.\n\n## R\u00e9sultat de la v\u00e9rification hors ligne\n\n`python3 -m unittest discover -s tests -v` \u2192 2 tests, OK (sortie 0). V\u00e9rification effectu\u00e9e par le\ncoordinateur depuis l\u2019ext\u00e9rieur de l\u2019espace de travail : voir `results\/checks\/T1-public.txt`.\n\n## Correctif\n\nAucun. `results\/T1\/patch.diff` est vide, et `diff -ru 02-fixture runtime\/workspaces\/T1`\nne renvoie aucune diff\u00e9rence. La t\u00e2che n\u00e9cessitait une inspection sans modification des fichiers ; ceci est\nconfirm\u00e9 plut\u00f4t qu\u2019affirm\u00e9.\n\n## Erreurs corrig\u00e9es\n\nUne erreur de shell r\u00e9cup\u00e9rable : un `grep` initial utilisait des motifs `--include=*.py` non entre guillemets que\nle shell a tent\u00e9 d\u2019interpr\u00e9ter comme des expressions globales ; la commande a \u00e9t\u00e9 r\u00e9ex\u00e9cut\u00e9e avec des motifs entre guillemets et a abouti. Aucun effet sur les r\u00e9sultats.\n\n## Sortie visible (mot pour mot)\n\n### 1. Description de ce d\u00e9p\u00f4t\n\nUn fixture autonome de la biblioth\u00e8que standard Python nomm\u00e9 `local-scheduler-1.0.0` (`fixture-manifest.json`), sous licence MIT, sans d\u00e9pendance r\u00e9seau ni de production (`README.md`, `\"network_required\": false`). Il est tr\u00e8s l\u00e9ger : 8 fichiers source\/doc plus le manifeste, soit 103 lignes au total. L\u2019interpr\u00e9teur utilis\u00e9 est **Python 3.9.6**. Il n\u2019y a ni `pyproject.toml`, ni `setup.py`, ni configuration CI, ni linter, ni configuration de v\u00e9rificateur de types \u2014 le seul workflow d\u00e9clar\u00e9 est `python3 -m unittest discover -s tests -v` (`README.md`).\n\n### 2. Architecture\n\nTrois couches plus un module orphelin, tous sous `scheduler\/` :\n\n| Couche | Fichier | Symbole | Responsabilit\u00e9 |\n|---|---|---|---|\n| Fa\u00e7ade du paquet | `scheduler\/__init__.py` | `__all__ = [\"SchedulerService\"]` | R\u00e9exporte uniquement `SchedulerService` ; `Job`, `JobRepository` et `time_rules` ne font pas partie de l\u2019interface publique |\n| Mod\u00e8le de domaine | `scheduler\/models.py` | `Job` (`@dataclass(frozen=True)`) | Objet de valeur immuable avec les champs `identifier: int`, `name: str`, `owner: str`, ainsi que `to_dict()` impl\u00e9ment\u00e9 sous la forme `asdict(self)` |\n| Persistance | `scheduler\/repository.py` | `JobRepository` | `dict` en m\u00e9moire dont les cl\u00e9s sont des identifiants ; `save`, `get`, `all`, `delete` |\n| Service d\u2019application | `scheduler\/service.py` | `SchedulerService` | Validation, attribution d\u2019identifiant, orchestration : `create_job`, `list_jobs`, `delete_job` |\n| Orphelin | `scheduler\/time_rules.py` | `next_daily_run` | Calcul de r\u00e9currence \u2014 **n'est import\u00e9 par aucun fichier** |\n\nLe sens des d\u00e9pendances est clair et unidirectionnel : `service.py` importe depuis `.models` et `.repository` ; `repository.py` importe depuis `.models` ; `models.py` n\u2019importe que des `dataclasses`. Aucun cycle. L\u2019injection de d\u00e9pendances est pr\u00e9sente mais minimale \u2014 `SchedulerService.__init__(self, repository=None)` effectue `self.repository = repository or JobRepository()`, ce qui permet de substituer un faux r\u00e9f\u00e9rentiel lors des tests.\n\nNotez que `scheduler\/time_rules.py` est aujourd\u2019hui du code mort. J\u2019ai recherch\u00e9 `time_rules` et `next_daily_run` dans l\u2019arborescence compl\u00e8te ; les seuls r\u00e9sultats sont sa propre d\u00e9finition et sa mention dans `expected_files` du fichier `fixture-manifest.json`. Il est livr\u00e9 mais n\u2019est pas connect\u00e9.\n\n### 3. Flux de donn\u00e9es\n\n**Cr\u00e9ation d\u2019une t\u00e2che** \u2014 `SchedulerService.create_job(name, owner)` :\n1. Contr\u00f4le : `if not name.strip(): raise ValueError('name is required\")`. Il s\u2019agit de la *seule* validation du syst\u00e8me \u2014 `owner` n\u2019est jamais v\u00e9rifi\u00e9, donc un propri\u00e9taire vide est accept\u00e9.\n2. Construction : `Job(self._next_identifier, name.strip(), owner.strip())` \u2014 construction par position, et les deux cha\u00eenes sont normalis\u00e9es par suppression des espaces.\n3. Persistance : `self.repository.save(job)`, qui effectue `self._jobs[job.identifier] = job` et renvoie le job.\n4. Incr\u00e9mentation du compteur : `self._next_identifier += 1` \u2014 *apr\u00e8s* l\u2019enregistrement ; ainsi, si une exception est lev\u00e9e, le compteur reste inchang\u00e9.\n5. Retour de l\u2019instance `Job` (le service renvoie son propre `job` local, et non la valeur de retour du r\u00e9f\u00e9rentiel).\n\nL\u2019attribution des identifiants se fait au niveau du **service**, et non du r\u00e9f\u00e9rentiel (`self._next_identifier = 1` dans `SchedulerService.__init__`). Il s\u2019agit l\u00e0 d\u2019un point de jonction important : l\u2019injection d\u2019un r\u00e9f\u00e9rentiel contenant d\u00e9j\u00e0 des t\u00e2ches les \u00e9crasera silencieusement, car le nouveau service recommence la num\u00e9rotation \u00e0 1.\n\n**Liste des t\u00e2ches** \u2014 `SchedulerService.list_jobs()` est un simple passage vers `JobRepository.all()`, qui renvoie `[self._jobs[key] for key in sorted(self._jobs)]`. Le tri s\u2019effectue donc **par ordre croissant selon l\u2019identifiant entier**, ce qui correspond actuellement \u00e0 l\u2019ordre d\u2019insertion. Une nouvelle liste est construite \u00e0 chaque appel, mais les objets `Job` sont des r\u00e9f\u00e9rences partag\u00e9es \u2014 ce qui n\u2019est sans risque que parce que `Job` est gel\u00e9.\n\n**Suppression** \u2014 `SchedulerService.delete_job(identifier)` d\u00e9l\u00e8gue \u00e0 `JobRepository.delete`, qui correspond \u00e0 `self._jobs.pop(identifier)` sans valeur par d\u00e9faut, ce qui l\u00e8ve une exception `KeyError` en cas d\u2019identifiant manquant. Cela est incoh\u00e9rent avec `JobRepository.get`, qui renvoie `None` dans la m\u00eame situation.\n\n**Couverture de test de ces chemins** \u2014 `tests\/test_scheduler.py` comporte exactement deux cas : `test_create_and_list_jobs` (v\u00e9rifie que `job.identifier == 1` et que `[job] == service.list_jobs()`) et `test_blank_name_is_rejected`. Les deux r\u00e9ussissent sur l\u2019arborescence actuelle.\n\n### 4. Fichiers susceptibles d\u2019\u00eatre affect\u00e9s par l\u2019ajout de priorit\u00e9s aux t\u00e2ches\n\nPar ordre d\u00e9croissant de certitude :\n\n1. **`scheduler\/models.py`** \u2014 certain. `Job` a besoin d\u2019un champ `priority`. Comme la classe de donn\u00e9es est d\u00e9finie avec `frozen=True` et que les champs sont positionnels, un nouveau champ doit comporter une valeur par d\u00e9faut (par exemple `priority: int = 0`) ou \u00eatre plac\u00e9 apr\u00e8s les trois champs existants, sinon toutes les constructions positionnelles existantes seront rompues. `to_dict()` ne n\u00e9cessite aucune modification \u2014 `asdict(self)` r\u00e9cup\u00e8re automatiquement le champ, ce qui constitue un changement silencieux du contrat de s\u00e9rialisation plut\u00f4t qu\u2019une modification du code.\n2. **`scheduler\/service.py`** \u2014 certain. `create_job` n\u00e9cessite un param\u00e8tre `priority` et doit le transmettre au constructeur positionnel `Job(...)` \u00e0 la ligne 13. Si la priorit\u00e9 est valid\u00e9e (plage, appartenance \u00e0 une \u00e9num\u00e9ration), la condition de validation doit \u00eatre plac\u00e9e \u00e0 c\u00f4t\u00e9 de la v\u00e9rification existante `name.strip()`. Si la liste doit \u00eatre tri\u00e9e par priorit\u00e9, c\u2019est dans `list_jobs` qu\u2019il faudrait impl\u00e9menter une politique de tri si l\u2019on souhaite que le r\u00e9f\u00e9rentiel reste un simple magasin de donn\u00e9es.\n3. **`scheduler\/repository.py`** \u2014 probable. La m\u00e9thode `sorted(self._jobs)` de `JobRepository.all()` trie les *cl\u00e9s* du dictionnaire, c'est-\u00e0-dire les identifiants. Un classement par priorit\u00e9 n\u00e9cessite de modifier cela pour trier les valeurs selon une cl\u00e9 telle que `(-job.priority, job.identifier)`, ou d'ajouter un accesseur ordonn\u00e9 distinct. Ne laissez pas le d\u00e9nouement en cas d\u2019\u00e9galit\u00e9 implicite : l\u2019ordre d\u2019insertion dans le dictionnaire n\u2019est pas un contrat stable sur lequel on peut compter.\n4. **`tests\/test_scheduler.py`** \u2014 certain. Nouveaux cas pour la priorit\u00e9 par d\u00e9faut, la priorit\u00e9 explicite, le classement et le rejet des priorit\u00e9s invalides. Notez que l\u2019expression existante `assertEqual([job], service.list_jobs())` compare le *m\u00eame* objet ; elle r\u00e9siste donc \u00e0 l\u2019ajout d\u2019un champ ; elle ne r\u00e9sisterait pas si elle comparait un litt\u00e9ral `Job` nouvellement construit.\n5. **`README.md`** \u2014 probablement, si la s\u00e9mantique des priorit\u00e9s (quelle extr\u00e9mit\u00e9 de la plage l\u2019emporte, valeur par d\u00e9faut) doit \u00eatre mentionn\u00e9e quelque part.\n6. **`scheduler\/__init__.py`** \u2014 uniquement si une \u00e9num\u00e9ration de priorit\u00e9s ou des constantes doivent \u00eatre export\u00e9es avec `SchedulerService`.\n7. **`fixture-manifest.json`** \u2014 uniquement si vous ajoutez un nouveau fichier de module ; son tableau `expected_files` constitue un inventaire explicite et risquerait de devenir obsol\u00e8te.\n8. **`scheduler\/time_rules.py`** \u2014 ne doit *pas* \u00eatre modifi\u00e9. La priorit\u00e9 est orthogonale \u00e0 la r\u00e9currence, et ce module n\u2019est pas connect\u00e9.\n\n### 5. Risques majeurs\n\n- **La s\u00e9mantique de tri constitue un changement de comportement silencieux.** `JobRepository.all()` garantit actuellement un ordre croissant des identifiants et `list_jobs` en h\u00e9rite. Tout utilisateur s\u2019appuyant sur cette garantie verra son code ne plus fonctionner en cas de reclassement. Il faut d\u00e9cider explicitement : est-ce que `list_jobs()` change de signification, ou est-ce qu\u2019une nouvelle fonction `list_jobs_by_priority()` appara\u00eet \u00e0 c\u00f4t\u00e9 ? La premi\u00e8re option est la plus risqu\u00e9e et le test existant `test_create_and_list_jobs` est trop faible pour d\u00e9tecter une r\u00e9gression (liste \u00e0 un seul \u00e9l\u00e9ment).\n- **Le sens du tri est v\u00e9ritablement ambigu.** La \" priorit\u00e9 1 ' signifie conventionnellement *la plus \u00e9lev\u00e9e* dans certains syst\u00e8mes et *la plus faible* dans d\u2019autres. Il n\u2019y a rien dans ce d\u00e9p\u00f4t \u2014 ni commentaire, ni cha\u00eene de documentation, ni ligne dans le README \u2014 qui permette de trancher. Choisissez une convention, documentez-la dans `models.py`, et encodez-la dans un test comportant au moins trois priorit\u00e9s distinctes afin que le sens du tri soit clairement d\u00e9fini.\n- **\u00c9galit\u00e9 instable lors du tri.** Si deux t\u00e2ches partagent la m\u00eame priorit\u00e9, le r\u00e9sultat doit n\u00e9anmoins \u00eatre d\u00e9terministe. La fonction `sorted` de Python est stable, mais cette stabilit\u00e9 n\u2019est utile que si l\u2019ordre d\u2019entr\u00e9e est lui-m\u00eame d\u00e9fini. Incluez toujours `identifier` comme cl\u00e9 secondaire explicite.\n- **Ordre des champs dans une dataclass gel\u00e9e.** `Job` est une `dataclass` avec `@dataclass(frozen=True)` comportant trois champs positionnels, et `service.py:13` le construit de mani\u00e8re positionnelle. Ins\u00e9rer `priority` \u00e0 un autre emplacement que le dernier, ou sans valeur par d\u00e9faut, constitue un changement de compatibilit\u00e9 que les deux tests existants pourraient ne pas signaler clairement.\n- **\u00c9largissement du contrat de `to_dict()`.** `asdict(self)` refl\u00e8te tous les champs. L\u2019ajout de `priority` modifie chaque charge utile s\u00e9rialis\u00e9e sans modification visible du corps de la m\u00e9thode dans `models.py`. Tout ce qui v\u00e9rifie la forme exacte du dictionnaire ne fonctionne plus.\n- **Contraintes de Python 3.9.6.** Pas de `@dataclass(slots=True)` (3.10+), pas de `kw_only=True` (3.10+), et les annotations PEP 604 `int | None` \u00e9chouent lors de l\u2019ex\u00e9cution sans `from __future__ import annotations`. Si la priorit\u00e9 est mod\u00e9lis\u00e9e sous forme d\u2019\u00e9num\u00e9ration, `enum.StrEnum` est disponible \u00e0 partir de la version 3.11 et n\u2019est donc pas accessible. N\u2019importe lequel de ces cas entra\u00eenerait une d\u00e9faillance du fixture sur cet interpr\u00e9teur.\n- **L\u2019attribution des identifiants se situe au mauvais niveau.** `SchedulerService._next_identifier` signifie que le service g\u00e8re la g\u00e9n\u00e9ration des identifiants tandis que le r\u00e9f\u00e9rentiel g\u00e8re le stockage. Si le travail sur les priorit\u00e9s conduit \u00e0 la mise en place d\u2019un deuxi\u00e8me r\u00e9f\u00e9rentiel ou de fixtures pr\u00e9charg\u00e9es, cette s\u00e9paration entra\u00eenera des collisions d\u2019identifiants et l\u2019\u00e9crasement de t\u00e2ches.\n- **Contrats d\u2019erreur asym\u00e9triques.** `JobRepository.get` renvoie `None` en cas d\u2019\u00e9chec, tandis que `JobRepository.delete` l\u00e8ve une `KeyError`. Toute nouvelle recherche li\u00e9e \u00e0 la priorit\u00e9 devrait adopter d\u00e9lib\u00e9r\u00e9ment une convention plut\u00f4t que d\u2019h\u00e9riter accidentellement de cette incoh\u00e9rence.\n- **Pr\u00e9c\u00e9dent de lacune de validation.** `create_job` valide `name` mais pas `owner`. Ne reproduisez pas ce laxisme pour `priority` : une priorit\u00e9 non valid\u00e9e se propage dans la cl\u00e9 de tri et peut lever une exception `TypeError` au c\u0153ur de `sorted` (par exemple, en comparant un `int` \u00e0 `None`) plut\u00f4t qu\u2019au niveau du site d\u2019appel.\n- **Pi\u00e8ge du code mort.** `scheduler\/time_rules.py` ressemble \u00e0 une logique de planification et attirera des modifications. Il n\u2019est import\u00e9 par aucun fichier, et sa propre cha\u00eene de documentation admet le bug : il ajoute 24 heures \u00e9coul\u00e9es en UTC et \" d\u00e9cale l\u2019heure locale r\u00e9elle lors des changements d\u2019heure d\u2019\u00e9t\u00e9 \". Le modifier n\u2019a aucun effet observable sur le syst\u00e8me test\u00e9 ; l\u2019effort consacr\u00e9 \u00e0 cette t\u00e2che est donc vain et aucun test \u00e9crit \u00e0 son sujet ne valide quoi que ce soit de ce qui sera livr\u00e9.\n- **Filet de s\u00e9curit\u00e9 fragile.** Deux tests, pas de CI, pas de linter, pas de v\u00e9rification de types. Rien ne permet de d\u00e9tecter une r\u00e9gression, sauf ce que vous \u00e9crivez vous-m\u00eame. Consid\u00e9rez la suite de tests existante comme une couverture de base insuffisante, et non comme un filtre.\n\n### 6. Plan de mise en \u0153uvre (non ex\u00e9cut\u00e9)\n\n1. **D\u00e9finir d\u2019abord la s\u00e9mantique, par \u00e9crit.** Type de priorit\u00e9 (`int` ou \u00e9num\u00e9ration), plage valide, valeur par d\u00e9faut pour les t\u00e2ches existantes\/non sp\u00e9cifi\u00e9es, et sens de tri. Consignez-les sous forme de cha\u00eene de documentation (`docstring`) sur `Job` dans `scheduler\/models.py` \u2014 c\u2019est le seul endroit dont toutes les couches d\u00e9pendent d\u00e9j\u00e0.\n2. **\u00c9tendre le mod\u00e8le.** Ajouter `priority: int = 0` en tant que *dernier* champ de `Job` dans `scheduler\/models.py`, en pr\u00e9servant la compatibilit\u00e9 positionnelle avec `service.py:13` et en laissant `to_dict()` inchang\u00e9.\n3. **Int\u00e9grez-le dans le service.** Ajoutez un param\u00e8tre `priority` par d\u00e9faut \u00e0 `SchedulerService.create_job`, validez-le \u00e0 c\u00f4t\u00e9 de la condition existante `name.strip()` (en levant une exception `ValueError`, correspondant au type d\u2019erreur \u00e9tabli), puis transmettez-le au constructeur `Job`.\n4. **D\u00e9finir explicitement le contrat de liste.** Option privil\u00e9gi\u00e9e \u00e0 faible risque : laisser `JobRepository.all()` tel quel en tant que primitive tri\u00e9e par identifiant, et ajouter un accesseur distinct tri\u00e9 par priorit\u00e9. Si, au contraire, la signification de `list_jobs()` doit changer, modifiez la compr\u00e9hension de `JobRepository.all()` pour trier les valeurs selon une cl\u00e9 compos\u00e9e explicite incluant `identifier` comme crit\u00e8re de d\u00e9partage, et notez cette modification dans `README.md`.\n5. **Maintenez `scheduler\/__init__.py` \u00e0 jour** uniquement si une \u00e9num\u00e9ration ou une constante publique a \u00e9t\u00e9 introduite.\n6. **Ne modifiez pas `scheduler\/time_rules.py`**, et n\u2019ajoutez pas de fichiers \u00e0 moins que la propri\u00e9t\u00e9 `expected_files` du fichier `fixture-manifest.json` ne soit mise \u00e0 jour dans le cadre de la m\u00eame modification.\n\n### 7. Plan de validation\n\n- **Commencez par la base de r\u00e9f\u00e9rence.** Ex\u00e9cutez `python3 -m unittest discover -s tests -v` avant toute modification et v\u00e9rifiez que les deux tests sont r\u00e9ussis. Je l\u2019ai d\u00e9j\u00e0 fait \u2014 tout passe sans probl\u00e8me.\n- **Contr\u00f4le de r\u00e9gression.** Les deux tests existants doivent toujours r\u00e9ussir sans modification. Si `test_create_and_list_jobs` n\u00e9cessite une modification, cela indique que la modification introduit un bug, et non une raison de modifier le test.\n- **Nouveaux cas dans `tests\/test_scheduler.py` :**\n  - Priorit\u00e9 par d\u00e9faut lorsque `create_job` est appel\u00e9 avec l\u2019ancienne signature \u00e0 deux arguments (pour prouver la compatibilit\u00e9 ascendante).\n  - Allers-retours explicites de priorit\u00e9 via `create_job` \u2192 `list_jobs`.\n  - Tri avec **trois priorit\u00e9s distinctes ou plus**, v\u00e9rifiant la liste compl\u00e8te \u2014 c\u2019est ce qui d\u00e9termine le sens du tri.\n  - \u00c9galit\u00e9 : deux t\u00e2ches de priorit\u00e9 \u00e9gale sont class\u00e9es par ordre croissant d\u2019identifiant.\n  - Une priorit\u00e9 non valide l\u00e8ve une exception `ValueError`, \u00e0 l\u2019instar du cas d\u2019un nom vide.\n  - `to_dict()` inclut `priority` avec la valeur attendue.\n  - Chemin de d\u00e9p\u00f4t inject\u00e9 : `SchedulerService(repository=fake)` attribue toujours correctement la priorit\u00e9, en testant la jonction `repository or JobRepository()`.\n- **V\u00e9rification de compatibilit\u00e9.** V\u00e9rifier que tout fonctionne sp\u00e9cifiquement sous Python 3.9.6 \u2014 pas de `slots=`, pas de `kw_only=`, pas d\u2019unions PEP 604 nues, pas de `StrEnum`.\n- **V\u00e9rification de l\u2019inventaire.** Relisez `fixture-manifest.json` et v\u00e9rifiez que l\u2019ensemble des fichiers sur le disque correspond toujours \u00e0 `expected_files`.\n- **D\u00e9terminisme.** Ex\u00e9cutez la suite de tests deux ou trois fois ; des bogues de tri li\u00e9s \u00e0 l\u2019ordre d\u2019it\u00e9ration des dictionnaires peuvent se manifester de mani\u00e8re intermittente.\n- **Propret\u00e9.** Ex\u00e9cutez avec `PYTHONDONTWRITEBYTECODE=1` afin que les r\u00e9pertoires `__pycache__` n\u2019apparaissent pas comme des \u00e9carts non suivis par rapport au manifeste.\n<\/pre><\/div><\/details><\/div><p class=\"d-limit\">Limitation li\u00e9e \u00e0 l'environnement de test : il s'agissait d'un petit r\u00e9f\u00e9rentiel Python hors ligne. Claude utilisait un sous-agent de secours apr\u00e8s l'expiration de l'OAuth via l'interface en ligne de commande (CLI) ; par cons\u00e9quent, l'isolation et la visibilit\u00e9 des jetons n'\u00e9taient pas identiques.<\/p><\/article>\n\n\n\n<p class=\"wp-block-paragraph\">Ce r\u00e9sultat ne permet pas d'\u00e9valuer les performances sur un monorepo de grande envergure ni lors d'une session autonome d'une semaine. Le sc\u00e9nario a \u00e9t\u00e9 d\u00e9lib\u00e9r\u00e9ment con\u00e7u pour \u00eatre de petite envergure et contr\u00f4l\u00e9. Pour une \u00e9valuation r\u00e9elle, commencez par une invite en lecture seule : demandez \u00e0 chaque outil de cartographier le chemin d'appel, de nommer les fichiers qu'il modifierait, d'identifier les tests et de r\u00e9pertorier les hypoth\u00e8ses non r\u00e9solues avant d'autoriser les modifications.<\/p>\n\n\n\n<h2 id=\"implementation\" class=\"wp-block-heading\">Mode de mise en \u0153uvre, port\u00e9e du correctif et correction des bogues<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Travail sur plusieurs fichiers<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Un m\u00eame comportement de r\u00e9ussite peut r\u00e9sulter de choix techniques diff\u00e9rents. Dans le cadre du test T2, les deux produits ont obtenu un score de 30\/30 et ont r\u00e9ussi le test de validation \u00ab frozen hidden \u00bb. Le code Claude a int\u00e9gr\u00e9 des validations \u00e0 plusieurs points de d\u00e9limitation et a ajout\u00e9 des tests plus complets portant sur le mod\u00e8le direct et les seuils. Codex a utilis\u00e9 une impl\u00e9mentation plus l\u00e9g\u00e8re, centr\u00e9e sur les services, qui respectait \u00e9galement le contrat.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Pour un d\u00e9veloppeur ind\u00e9pendant, il s\u2019agit l\u00e0 d\u2019un v\u00e9ritable compromis. Une validation plus large permet de prot\u00e9ger les invariants lorsque les objets sont cr\u00e9\u00e9s via plusieurs chemins. Un correctif plus restreint peut r\u00e9duire la surface de r\u00e9gression et le temps de r\u00e9vision lorsqu\u2019un seul service est le point d\u2019entr\u00e9e pr\u00e9vu. La bonne r\u00e9ponse d\u00e9pend des r\u00e8gles de propri\u00e9t\u00e9 du r\u00e9f\u00e9rentiel, et non du simple d\u00e9compte des lignes modifi\u00e9es ou des tests pris isol\u00e9ment.<\/p>\n\n\n\n<style>\n.evidence-t2-multifile-feature{--ink:#111318;--body:#414753;--muted:#707784;--line:#e4e7ec;--soft:#f6f7f9;--blue:#315efb;--violet:#7257e8;--green:#087a55;--greenSoft:#eaf8f2;--red:#a23131;--redSoft:#fff0f0;color:var(--ink);font-family:Inter,ui-sans-serif,-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif;line-height:1.5;border:1px solid var(--line);border-radius:8px;background:#fff;overflow:hidden;box-shadow:0 16px 42px rgba(24,32,56,.08)}\n.evidence-t2-multifile-feature *{box-sizing:border-box}.evidence-t2-multifile-feature .d-head{display:flex;align-items:flex-start;justify-content:space-between;gap:22px;padding:24px 26px 20px;border-bottom:1px solid var(--line)}\n.evidence-t2-multifile-feature .d-kicker{margin:0 0 6px;color:var(--muted);font:750 11px\/1.4 ui-monospace,SFMono-Regular,Menlo,monospace;letter-spacing:.08em;text-transform:uppercase}.evidence-t2-multifile-feature .d-title{margin:0;font-size:22px;line-height:1.2;letter-spacing:-.025em}.evidence-t2-multifile-feature .d-sub{margin:7px 0 0;color:var(--body);font-size:13px}.evidence-t2-multifile-feature .d-pill{flex:0 0 auto;padding:6px 10px;border:1px solid #ccd6ff;border-radius:999px;color:#2448ca;background:#f0f3ff;font-size:11px;font-weight:800}.evidence-t2-multifile-feature .d-grid{display:grid;grid-template-columns:1fr 1fr}.evidence-t2-multifile-feature .d-side{min-width:0;padding:24px 26px}.evidence-t2-multifile-feature .d-side+.d-side{border-left:1px solid var(--line)}.evidence-t2-multifile-feature .d-product{display:flex;align-items:baseline;justify-content:space-between;gap:14px;font-weight:800}.evidence-t2-multifile-feature .d-score{font-size:34px;line-height:1;letter-spacing:-.05em}.evidence-t2-multifile-feature .d-score small{color:var(--muted);font-size:12px;letter-spacing:0}.evidence-t2-multifile-feature .d-metrics{display:grid;grid-template-columns:repeat(3,1fr);gap:7px;margin:18px 0}.evidence-t2-multifile-feature .d-metric{padding:10px;border:1px solid var(--line);border-radius:6px;background:var(--soft)}.evidence-t2-multifile-feature .d-metric span{display:block;color:var(--muted);font-size:9px;font-weight:800;letter-spacing:.06em;text-transform:uppercase}.evidence-t2-multifile-feature .d-metric strong{display:block;margin-top:3px;font-size:13px}.evidence-t2-multifile-feature .d-preview{position:relative;height:192px;overflow:hidden;border:1px solid #29313f;border-radius:6px;background:#11151d;color:#edf0f5}.evidence-t2-multifile-feature .d-preview-label{padding:11px 13px;border-bottom:1px solid rgba(255,255,255,.1);color:#aeb7c7;font:750 9px\/1 ui-monospace,SFMono-Regular,Menlo,monospace;letter-spacing:.06em;text-transform:uppercase}.evidence-t2-multifile-feature .d-preview pre,.evidence-t2-multifile-feature .d-full pre{margin:0;white-space:pre-wrap;font:11px\/1.6 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.evidence-t2-multifile-feature .d-preview pre{padding:13px}.evidence-t2-multifile-feature .d-preview:after{content:\"\";position:absolute;left:0;right:0;bottom:0;height:55px;background:linear-gradient(transparent,#11151d)}.evidence-t2-multifile-feature .d-take{margin:14px 0 0;color:var(--body);font-size:12px}.evidence-t2-multifile-feature .d-fulls{padding:0 26px 22px}.evidence-t2-multifile-feature .d-full{margin-top:10px;border:1px solid var(--line);border-radius:6px}.evidence-t2-multifile-feature .d-full summary{cursor:pointer;padding:13px 14px;font-size:12px;font-weight:800;list-style:none}.evidence-t2-multifile-feature .d-full summary::-webkit-details-marker{display:none}.evidence-t2-multifile-feature .d-full summary:after{content:\"+\";float:right;color:var(--blue);font-size:17px}.evidence-t2-multifile-feature .d-full[open] summary:after{content:\"\u2212\"}.evidence-t2-multifile-feature .d-full-pane{padding:0 14px 14px}.evidence-t2-multifile-feature .d-full-note{margin:0 0 9px;color:var(--muted);font-size:10px}.evidence-t2-multifile-feature .d-full pre{max-height:620px;overflow:auto;padding:15px;border-radius:5px;background:#f5f6f8;color:#222936;border:1px solid #e0e3e8}.evidence-t2-multifile-feature .d-limit{margin:0;padding:12px 26px;border-top:1px solid var(--line);color:#5a6270;background:#fafbfc;font-size:11px}\n@media(max-width:760px){.evidence-t2-multifile-feature .d-head{display:block}.evidence-t2-multifile-feature .d-pill{display:inline-block;margin-top:12px}.evidence-t2-multifile-feature .d-grid{grid-template-columns:1fr}.evidence-t2-multifile-feature .d-side+.d-side{border-left:0;border-top:1px solid var(--line)}}@media(max-width:480px){.evidence-t2-multifile-feature .d-head,.evidence-t2-multifile-feature .d-side{padding:20px}.evidence-t2-multifile-feature .d-fulls{padding:0 20px 20px}.evidence-t2-multifile-feature .d-metrics{grid-template-columns:1fr}}\n<\/style><article class=\"evidence-t2-multifile-feature\"><header class=\"d-head\"><div><p class=\"d-kicker\">T2 \u00b7 Test du r\u00e9f\u00e9rentiel contr\u00f4l\u00e9<\/p><h3 class=\"d-title\">Mettre en \u0153uvre une fonctionnalit\u00e9 prioritaire dans plusieurs fichiers<\/h3><p class=\"d-sub\">Ajouter le comportement \u00ab frozen \u00bb, pr\u00e9server la compatibilit\u00e9 et passer les tests publics et cach\u00e9s.<\/p><\/div><span class=\"d-pill\">Cravate fonctionnelle<\/span><\/header><div class=\"d-grid\"><section class=\"d-side\" aria-label=\"R\u00e9sultat du Codex\"><div class=\"d-product\"><span>Codex<\/span><span class=\"d-score\">30<small>\/30<\/small><\/span><\/div><div class=\"d-metrics\"><div class=\"d-metric\"><span>Dur\u00e9e<\/span><strong>115 s<\/strong><\/div><div class=\"d-metric\"><span>Ch\u00e8ques<\/span><strong>7 + cach\u00e9s<\/strong><\/div><div class=\"d-metric\"><span>Champ d'application<\/span><strong>Patch plus petit<\/strong><\/div><\/div><div class=\"d-preview\"><div class=\"d-preview-label\">Extrait de la premi\u00e8re sortie valide<\/div><pre>J'ai ajout\u00e9 une priorit\u00e9 au mod\u00e8le immuable, je l'ai valid\u00e9 au niveau de la limite du service et j'ai conserv\u00e9 l'ordre dans le r\u00e9f\u00e9rentiel.\n\nLes sept tests publics et le validateur cach\u00e9 fig\u00e9 ont tous r\u00e9ussi.<\/pre><\/div><p class=\"d-take\"><strong>Avis du critique :<\/strong> Une impl\u00e9mentation plus concise, ax\u00e9e sur les services, qui prenait en charge tous les comportements fig\u00e9s.<\/p><\/section><section class=\"d-side\" aria-label=\"R\u00e9sultat du code Claude\"><div class=\"d-product\"><span>Claude Code<\/span><span class=\"d-score\">30<small>\/30<\/small><\/span><\/div><div class=\"d-metrics\"><div class=\"d-metric\"><span>Dur\u00e9e<\/span><strong>101 s<\/strong><\/div><div class=\"d-metric\"><span>Ch\u00e8ques<\/span><strong>14 + cach\u00e9<\/strong><\/div><div class=\"d-metric\"><span>Champ d'application<\/span><strong>Tests plus approfondis<\/strong><\/div><\/div><div class=\"d-preview\"><div class=\"d-preview-label\">Extrait de la premi\u00e8re sortie valide<\/div><pre>Validation de la priorit\u00e9 tant au niveau de la limite du service qu\u2019au niveau du mod\u00e8le immuable, pr\u00e9servation du filtrage du r\u00e9f\u00e9rentiel et ajout d\u2019une couverture des seuils.\n\nQuatorze tests publics et le validateur cach\u00e9 ont \u00e9t\u00e9 r\u00e9ussis.<\/pre><\/div><p class=\"d-take\"><strong>Avis du critique :<\/strong> Une couverture plus large du mod\u00e8le direct et du seuil, sans avantage en termes de score fonctionnel.<\/p><\/section><\/div><div class=\"d-fulls\"><details class=\"d-full\"><summary>Afficher l'int\u00e9gralit\u00e9 des r\u00e9sultats de Codex<\/summary><div class=\"d-full-pane\"><p class=\"d-full-note\">Sortie compl\u00e8te, valid\u00e9e et aseptis\u00e9e<\/p><pre>Mise en place de la fonctionnalit\u00e9 de priorit\u00e9 des t\u00e2ches planifi\u00e9es.\n\nFichiers modifi\u00e9s :\n\n- [scheduler\/models.py](.\/scheduler\/models.py:5) \u2014 ajout d'une variable s\u00e9rialis\u00e9e `priority`, dont la valeur par d\u00e9faut est `0`.\n- [scheduler\/service.py](.\/scheduler\/service.py:11) \u2014 Ajout de la validation, du stockage et du filtrage `list_jobs(min_priority=0)` tout en conservant l'ordre des identifiants.\n- [tests\/test_scheduler.py](.\/tests\/test_scheduler.py:16) \u2014 ajout de la couverture pour les valeurs par d\u00e9faut, la s\u00e9rialisation, le stockage, les limites, les valeurs non valides et le filtrage.\n\nTests ex\u00e9cut\u00e9s :\n\n```text\npython3 -m unittest discover -s tests -v\n7 tests ex\u00e9cut\u00e9s \u2014 OK\n```\n\n**Conclusion :** La t\u00e2che gel\u00e9e est termin\u00e9e et v\u00e9rifi\u00e9e.  \n**D\u00e9cision requise :** Aucune.<\/pre><\/div><\/details><details class=\"d-full\"><summary>Afficher l'int\u00e9gralit\u00e9 du code de sortie Claude<\/summary><div class=\"d-full-pane\"><p class=\"d-full-note\">Compte rendu complet du transfert, y compris la transcription mot pour mot de la premi\u00e8re sortie valide<\/p><pre>Fichier d'ex\u00e9cution # T2 \u2014 Fonctionnalit\u00e9 de priorit\u00e9 multi-fichiers\n\nParam\u00e8tres d'ex\u00e9cution ##\n\n| Champ | Valeur |\n| --- | --- |\n| T\u00e2che | `T2` |\n| Invite fig\u00e9e | `01-prompts\/T2.md` |\n| SHA-256 de la invite gel\u00e9e | `8476a56034c4e719b97ee4081b32b4c73efd45feafe1bda9d477c83cb8fdb698` |\n| Unit\u00e9 d\u2019ex\u00e9cution | sous-agent Claude isol\u00e9, `usage g\u00e9n\u00e9ral`, contexte vierge |\n| M\u00e9thode d\u2019isolation | **repli sur sous-agent** (r\u00e9trogradation document\u00e9e \u2014 voir `results\/isolation-decision.md`) |\n| Copie propre attribu\u00e9e | `runtime\/workspaces\/T2` |\n| Version du code Claude | `2.1.220` |\n| Param\u00e8tres du mod\u00e8le | `claude-opus-5` |\n| start_utc | `2026-07-28T10:27:52Z` |\n| end_utc | `2026-07-28T10:29:33Z` |\n| Dur\u00e9e | 101 s (en parall\u00e8le avec T1, T3, T4 ; mesure de latence non fiable) |\n| Num\u00e9ro de tentative | 1 |\n| Statut | `valide` |\n| Intervention humaine | aucune |\n\n## R\u00e9sum\u00e9 de l'outil de s\u00e9curit\u00e9\n\n`date`, `Lecture`\/`Modification`\/`\u00c9criture` uniquement dans l\u2019espace de travail attribu\u00e9, `grep`,\n`python3 -m unittest discover`, `python3 -m compileall`, v\u00e9rifications de base `python3 -c` en ligne.\nPas de r\u00e9seau, pas d\u2019installations, biblioth\u00e8que standard uniquement.\n\n## Fichiers modifi\u00e9s\n\n`scheduler\/models.py`, `scheduler\/repository.py`, `scheduler\/service.py`,\n`tests\/test_scheduler.py`. Aucun fichier n\u2019a \u00e9t\u00e9 ajout\u00e9 ni supprim\u00e9, donc `fixture-manifest.json` reste\nexact. Patch complet : `results\/T2\/patch.diff`.\n\n## R\u00e9sultats des v\u00e9rifications hors ligne\n\nRapport\u00e9s par l\u2019ex\u00e9cuteur de t\u00e2ches :\n\n| V\u00e9rification | R\u00e9sultat |\n| --- | --- |\n| `python3 -m unittest discover -s tests -v` (r\u00e9f\u00e9rence, avant modification) | 2 r\u00e9ussis, 0 \u00e9chou\u00e9s |\n| `python3 -m compileall -q scheduler tests` | sans erreur |\n| tests de fum\u00e9e int\u00e9gr\u00e9s (construction h\u00e9rit\u00e9e \u00e0 3 arguments, seuil de mot-cl\u00e9\/positionnel, `to_dict`) | r\u00e9ussi |\n| `python3 -m unittest discover -s tests -v` (final) | **14 r\u00e9ussis, 0 \u00e9chou\u00e9s** |\n\nRev\u00e9rifi\u00e9 de mani\u00e8re ind\u00e9pendante par le coordinateur depuis l\u2019ext\u00e9rieur de l\u2019espace de travail :\n\n| V\u00e9rification | Sortie | R\u00e9sultat |\n| --- | --- | --- |\n| suite publique (`results\/checks\/T2-public.txt`) | 0 | 14 tests, OK |\n| validateur cach\u00e9 `03-checks\/test_t2_hidden.py` (`results\/checks\/T2-hidden.txt`) | 0 | 2 tests, OK |\n\nLe validateur cach\u00e9 \u00e9choue (sortie 1) sur une copie vierge du fixture, ce qui confirme que la r\u00e9ussite est\npertinente. Voir `results\/checks\/validator-controls.md`.\n\n## Couverture des comportements de la carte de r\u00e9f\u00e9rence\n\nLes cinq comportements requis dans `03-checks\/gold-map.json` sont tous satisfaits :\n\n| Comportement requis | Preuve |\n| --- | --- |\n| priorit\u00e9 par d\u00e9faut 0 | `Job.priority: int = MIN_PRIORITY` ; `create_job(..., priority=MIN_PRIORITY)` ; `test_priority_defaults_to_zero` |\n| plage d\u2019entiers de 0 \u00e0 9 | `validate_priority` rejette les valeurs non enti\u00e8res et hors plage ; `test_out_of_range_priority_is_rejected`, `test_non_integer_priority_is_rejected` |\n| priorit\u00e9 s\u00e9rialis\u00e9e | `to_dict()` via `asdict` ; `test_priority_appears_in_serialized_output` v\u00e9rifie que le dictionnaire est exact |\n| filtrage par priorit\u00e9 minimale | `list_jobs(min_priority=0)` \u2192 `JobRepository.all(min_priority)` ; `test_filter_is_inclusive_of_the_threshold` |\n| tri des identifiants | filtre appliqu\u00e9 \u00e0 l\u2019int\u00e9rieur de la compr\u00e9hension existante `sorted(self._jobs)` ; `test_filter_preserves_ascending_identifier_order` |\n\n## Erreurs corrig\u00e9es\n\nAucune. Les artefacts `__pycache__` issus des ex\u00e9cutions de tests ont \u00e9t\u00e9 supprim\u00e9s par le gestionnaire de t\u00e2ches ; un balayage du coordinateur\na confirm\u00e9 que l'espace de travail est propre.\n\n## Sortie visible (mot pour mot)\n\nAjout d\u2019un champ entier `priority` aux t\u00e2ches planifi\u00e9es dans les couches mod\u00e8le, r\u00e9f\u00e9rentiel et service du dispositif de planification local, ainsi qu\u2019\u00e0 la liste filtr\u00e9e.\n\n**`scheduler\/models.py`** \u2014 Ajout des constantes de module `MIN_PRIORITY = 0` \/ `MAX_PRIORITY = 9` et d\u2019une fonction r\u00e9utilisable `validate_priority(priority)` qui l\u00e8ve une exception `ValueError` pour les valeurs non enti\u00e8res et pour celles situ\u00e9es en dehors de la plage comprise entre 0 et 9 inclus. Le type `bool` est explicitement rejet\u00e9 bien qu\u2019il s\u2019agisse d\u2019une sous-classe de `int` ; ainsi, `True` ne peut pas passer pour une priorit\u00e9 1. La classe de donn\u00e9es fig\u00e9e `Job` se voit ajouter `priority: int = MIN_PRIORITY` en tant que champ final avec une valeur par d\u00e9faut, ce qui permet de conserver le fonctionnement de la construction \u00e0 3 arguments existante, ainsi qu\u2019une m\u00e9thode `__post_init__` qui appelle le validateur afin qu\u2019aucune priorit\u00e9 invalide ne puisse \u00eatre construite, quel que soit le chemin. `to_dict()` a \u00e9t\u00e9 conserv\u00e9 sous la forme `asdict(self)`, de sorte que la priorit\u00e9 appara\u00eet automatiquement dans la sortie s\u00e9rialis\u00e9e, dans l\u2019ordre des champs.\n\n**`scheduler\/repository.py`** \u2014 `JobRepository.all()` accepte un argument facultatif `min_priority` et effectue le filtrage au sein de la compr\u00e9hension existante `sorted(self._jobs)`, ce qui garantit un ordre croissant des identifiants via le m\u00eame chemin de code unique qui le fournissait d\u00e9j\u00e0, plut\u00f4t que de le r\u00e9tablir apr\u00e8s le filtrage. L\u2019argument par d\u00e9faut pr\u00e9serve le comportement pr\u00e9c\u00e9dent (sans argument) pour les appelants existants. Le stockage lui-m\u00eame n\u2019a n\u00e9cessit\u00e9 aucune modification : le r\u00e9f\u00e9rentiel stocke des instances `Job` compl\u00e8tes, de sorte que la priorit\u00e9 est conserv\u00e9e et transmise lors des allers-retours via `save`\/`get`\/`all`.\n\n**`scheduler\/service.py`** \u2014 `create_job` accepte un argument `priority` facultatif en fin de liste (valeur par d\u00e9faut : 0) et le valide avant de construire l\u2019objet `Job` ; ainsi, l\u2019exception est lev\u00e9e \u00e0 la limite du service avec le m\u00eame contrat `ValueError` que la v\u00e9rification existante du nom vide. `list_jobs(min_priority=0)` d\u00e9l\u00e8gue la t\u00e2che au r\u00e9f\u00e9rentiel. Le tri et le filtrage sont regroup\u00e9s en un seul endroit plut\u00f4t que d\u2019\u00eatre dupliqu\u00e9s.\n\n**Remarque de conception concernant la validation de `min_priority` :** sa valeur est v\u00e9rifi\u00e9e comme \u00e9tant un entier, mais elle n\u2019est d\u00e9lib\u00e9r\u00e9ment *pas* limit\u00e9e \u00e0 la plage 0\u20139. La r\u00e8gle 0\u20139 impose des contraintes sur ce qu\u2019un job peut stocker ; un seuil est un param\u00e8tre de requ\u00eate, et rejeter par exemple `min_priority=10` transformerait une requ\u00eate l\u00e9gitime \" ne correspondant \u00e0 rien \" en une erreur. Le fait que `list_jobs(min_priority=9)` renvoie `[]` lorsqu\u2019aucune t\u00e2che n\u2019a la priorit\u00e9 9 est couvert par un test.\n\nLe fichier `scheduler\/time_rules.py` a \u00e9t\u00e9 consult\u00e9 mais n\u2019a pas \u00e9t\u00e9 modifi\u00e9 \u2014 le d\u00e9calage li\u00e9 \u00e0 l\u2019heure d\u2019\u00e9t\u00e9 qui y est document\u00e9 correspond \u00e0 un comportement pr\u00e9existant, hors du champ d\u2019application de cette t\u00e2che, et le modifier aurait entra\u00een\u00e9 un changement de comportement sans rapport avec celle-ci. Aucun fichier n\u2019a \u00e9t\u00e9 ajout\u00e9 ni supprim\u00e9 ; le fichier `fixture-manifest.json` reste donc exact (v\u00e9rifi\u00e9 par programmation).\n\n### Couverture de test ajout\u00e9e\n\nValeur par d\u00e9faut de 0 ; aller-retour en m\u00e9moire via `JobRepository` ; priorit\u00e9 dans la sortie de `to_dict()` ; valeurs limites 0 et 9 accept\u00e9es ; valeurs hors plage \u22121\/10\/100 rejet\u00e9es ; valeurs non enti\u00e8res `\"3\"`\/`3.5`\/`None`\/`True` rejet\u00e9es ; validation directe au niveau du mod\u00e8le ; ordre de liste non filtr\u00e9 ; liste filtr\u00e9e conservant l\u2019ordre croissant des identifiants ; seuil inclusif ; r\u00e9sultat vide ; valeur non enti\u00e8re de `min_priority` rejet\u00e9e.\n<\/pre><\/div><\/details><\/div><p class=\"d-limit\">Limitation li\u00e9e \u00e0 l'environnement de test : il s'agissait d'un petit r\u00e9f\u00e9rentiel Python hors ligne. Claude utilisait un sous-agent de secours apr\u00e8s l'expiration de l'OAuth via l'interface en ligne de commande (CLI) ; par cons\u00e9quent, l'isolation et la visibilit\u00e9 des jetons n'\u00e9taient pas identiques.<\/p><\/article>\n\n\n\n<h3 class=\"wp-block-heading\">Correction de bogues dans des cas limites<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">T3 a test\u00e9 un d\u00e9faut de planification li\u00e9 \u00e0 l'heure d'\u00e9t\u00e9. Les deux agents ont obtenu un score de 30\/30 et ont r\u00e9ussi les m\u00eames contr\u00f4les cach\u00e9s au printemps et \u00e0 l'automne. Le code Claude a ajout\u00e9 une couverture explicite pour les heures locales ambigu\u00ebs ou ignor\u00e9es, les entr\u00e9es na\u00efves et les cycles de plusieurs jours. Codex a apport\u00e9 une modification plus restreinte au calendrier et a satisfait au contrat fig\u00e9.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Des tests plus complets couvrant les cas limites renforcent la confiance lorsque la biblioth\u00e8que est largement r\u00e9utilis\u00e9e ou que le co\u00fbt d\u2019une erreur d\u2019ordonnancement est \u00e9lev\u00e9. Une modification cibl\u00e9e est pr\u00e9f\u00e9rable lorsque le d\u00e9faut est bien isol\u00e9 et que l\u2019\u00e9quipe souhaite minimiser les changements de comportement. La question pratique \u00e0 se poser n\u2019est pas \u201c Qui a \u00e9crit le plus de code ? \u201d, mais de savoir si le correctif r\u00e9sout la cause premi\u00e8re identifi\u00e9e, pr\u00e9serve les contrats environnants et v\u00e9rifie les limites \u00e0 risque.<\/p>\n\n\n\n<style>\n.evidence-t3-dst-bug-fix{--ink:#111318;--body:#414753;--muted:#707784;--line:#e4e7ec;--soft:#f6f7f9;--blue:#315efb;--violet:#7257e8;--green:#087a55;--greenSoft:#eaf8f2;--red:#a23131;--redSoft:#fff0f0;color:var(--ink);font-family:Inter,ui-sans-serif,-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif;line-height:1.5;border:1px solid var(--line);border-radius:8px;background:#fff;overflow:hidden;box-shadow:0 16px 42px rgba(24,32,56,.08)}\n.evidence-t3-dst-bug-fix *{box-sizing:border-box}.evidence-t3-dst-bug-fix .d-head{display:flex;align-items:flex-start;justify-content:space-between;gap:22px;padding:24px 26px 20px;border-bottom:1px solid var(--line)}\n.evidence-t3-dst-bug-fix .d-kicker{margin:0 0 6px;color:var(--muted);font:750 11px\/1.4 ui-monospace,SFMono-Regular,Menlo,monospace;letter-spacing:.08em;text-transform:uppercase}.evidence-t3-dst-bug-fix .d-title{margin:0;font-size:22px;line-height:1.2;letter-spacing:-.025em}.evidence-t3-dst-bug-fix .d-sub{margin:7px 0 0;color:var(--body);font-size:13px}.evidence-t3-dst-bug-fix .d-pill{flex:0 0 auto;padding:6px 10px;border:1px solid #ccd6ff;border-radius:999px;color:#2448ca;background:#f0f3ff;font-size:11px;font-weight:800}.evidence-t3-dst-bug-fix .d-grid{display:grid;grid-template-columns:1fr 1fr}.evidence-t3-dst-bug-fix .d-side{min-width:0;padding:24px 26px}.evidence-t3-dst-bug-fix .d-side+.d-side{border-left:1px solid var(--line)}.evidence-t3-dst-bug-fix .d-product{display:flex;align-items:baseline;justify-content:space-between;gap:14px;font-weight:800}.evidence-t3-dst-bug-fix .d-score{font-size:34px;line-height:1;letter-spacing:-.05em}.evidence-t3-dst-bug-fix .d-score small{color:var(--muted);font-size:12px;letter-spacing:0}.evidence-t3-dst-bug-fix .d-metrics{display:grid;grid-template-columns:repeat(3,1fr);gap:7px;margin:18px 0}.evidence-t3-dst-bug-fix .d-metric{padding:10px;border:1px solid var(--line);border-radius:6px;background:var(--soft)}.evidence-t3-dst-bug-fix .d-metric span{display:block;color:var(--muted);font-size:9px;font-weight:800;letter-spacing:.06em;text-transform:uppercase}.evidence-t3-dst-bug-fix .d-metric strong{display:block;margin-top:3px;font-size:13px}.evidence-t3-dst-bug-fix .d-preview{position:relative;height:192px;overflow:hidden;border:1px solid #29313f;border-radius:6px;background:#11151d;color:#edf0f5}.evidence-t3-dst-bug-fix .d-preview-label{padding:11px 13px;border-bottom:1px solid rgba(255,255,255,.1);color:#aeb7c7;font:750 9px\/1 ui-monospace,SFMono-Regular,Menlo,monospace;letter-spacing:.06em;text-transform:uppercase}.evidence-t3-dst-bug-fix .d-preview pre,.evidence-t3-dst-bug-fix .d-full pre{margin:0;white-space:pre-wrap;font:11px\/1.6 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.evidence-t3-dst-bug-fix .d-preview pre{padding:13px}.evidence-t3-dst-bug-fix .d-preview:after{content:\"\";position:absolute;left:0;right:0;bottom:0;height:55px;background:linear-gradient(transparent,#11151d)}.evidence-t3-dst-bug-fix .d-take{margin:14px 0 0;color:var(--body);font-size:12px}.evidence-t3-dst-bug-fix .d-fulls{padding:0 26px 22px}.evidence-t3-dst-bug-fix .d-full{margin-top:10px;border:1px solid var(--line);border-radius:6px}.evidence-t3-dst-bug-fix .d-full summary{cursor:pointer;padding:13px 14px;font-size:12px;font-weight:800;list-style:none}.evidence-t3-dst-bug-fix .d-full summary::-webkit-details-marker{display:none}.evidence-t3-dst-bug-fix .d-full summary:after{content:\"+\";float:right;color:var(--blue);font-size:17px}.evidence-t3-dst-bug-fix .d-full[open] summary:after{content:\"\u2212\"}.evidence-t3-dst-bug-fix .d-full-pane{padding:0 14px 14px}.evidence-t3-dst-bug-fix .d-full-note{margin:0 0 9px;color:var(--muted);font-size:10px}.evidence-t3-dst-bug-fix .d-full pre{max-height:620px;overflow:auto;padding:15px;border-radius:5px;background:#f5f6f8;color:#222936;border:1px solid #e0e3e8}.evidence-t3-dst-bug-fix .d-limit{margin:0;padding:12px 26px;border-top:1px solid var(--line);color:#5a6270;background:#fafbfc;font-size:11px}\n@media(max-width:760px){.evidence-t3-dst-bug-fix .d-head{display:block}.evidence-t3-dst-bug-fix .d-pill{display:inline-block;margin-top:12px}.evidence-t3-dst-bug-fix .d-grid{grid-template-columns:1fr}.evidence-t3-dst-bug-fix .d-side+.d-side{border-left:0;border-top:1px solid var(--line)}}@media(max-width:480px){.evidence-t3-dst-bug-fix .d-head,.evidence-t3-dst-bug-fix .d-side{padding:20px}.evidence-t3-dst-bug-fix .d-fulls{padding:0 20px 20px}.evidence-t3-dst-bug-fix .d-metrics{grid-template-columns:1fr}}\n<\/style><article class=\"evidence-t3-dst-bug-fix\"><header class=\"d-head\"><div><p class=\"d-kicker\">T3 \u00b7 Test du r\u00e9f\u00e9rentiel contr\u00f4l\u00e9<\/p><h3 class=\"d-title\">Corriger la planification quotidienne lors des changements d'heure d'\u00e9t\u00e9<\/h3><p class=\"d-sub\">Conserver l'heure de New York demand\u00e9e pendant les p\u00e9riodes de transition entre le printemps et l'automne.<\/p><\/div><span class=\"d-pill\">Cravate \u00b7 diff\u00e9rentes \u00e9paisseurs<\/span><\/header><div class=\"d-grid\"><section class=\"d-side\" aria-label=\"R\u00e9sultat du Codex\"><div class=\"d-product\"><span>Codex<\/span><span class=\"d-score\">30<small>\/30<\/small><\/span><\/div><div class=\"d-metrics\"><div class=\"d-metric\"><span>Dur\u00e9e<\/span><strong>99 s<\/strong><\/div><div class=\"d-metric\"><span>Ch\u00e8ques<\/span><strong>4 + 2 cach\u00e9s<\/strong><\/div><div class=\"d-metric\"><span>Champ d'application<\/span><strong>Solution partielle<\/strong><\/div><\/div><div class=\"d-preview\"><div class=\"d-preview-label\">Extrait de la premi\u00e8re sortie valide<\/div><pre>Cause premi\u00e8re : la mise en \u0153uvre a ajout\u00e9 24 heures UTC \u00e9coul\u00e9es.\n\nSolution : avancer d'un jour civil local. Les contr\u00f4les \u00ab spring \u00bb et \u00ab fall \u00bb fig\u00e9s ont tous deux r\u00e9ussi.<\/pre><\/div><p class=\"d-take\"><strong>Avis du critique :<\/strong> La partie la plus restreinte a adopt\u00e9 l'ensemble du contrat gel\u00e9.<\/p><\/section><section class=\"d-side\" aria-label=\"R\u00e9sultat du code Claude\"><div class=\"d-product\"><span>Claude Code<\/span><span class=\"d-score\">30<small>\/30<\/small><\/span><\/div><div class=\"d-metrics\"><div class=\"d-metric\"><span>Dur\u00e9e<\/span><strong>118 s<\/strong><\/div><div class=\"d-metric\"><span>Ch\u00e8ques<\/span><strong>10 + 2 cach\u00e9s<\/strong><\/div><div class=\"d-metric\"><span>Champ d'application<\/span><strong>Couverture des bords<\/strong><\/div><\/div><div class=\"d-preview\"><div class=\"d-preview-label\">Extrait de la premi\u00e8re sortie valide<\/div><pre>Prise en compte du printemps et de l'automne, des heures locales manquantes ou ambigu\u00ebs, des donn\u00e9es brutes et des cycles de plusieurs jours.\n\nLes deux contr\u00f4les cach\u00e9s \u00ab gel\u00e9s \u00bb ont \u00e9t\u00e9 valid\u00e9s apr\u00e8s une couverture de r\u00e9gression \u00e9largie.<\/pre><\/div><p class=\"d-take\"><strong>Avis du critique :<\/strong> Une couverture plus large des cas limites ; le m\u00eame score fonctionnel selon la grille d'\u00e9valuation fig\u00e9e.<\/p><\/section><\/div><div class=\"d-fulls\"><details class=\"d-full\"><summary>Afficher l'int\u00e9gralit\u00e9 des r\u00e9sultats de Codex<\/summary><div class=\"d-full-pane\"><p class=\"d-full-note\">Sortie compl\u00e8te, valid\u00e9e et aseptis\u00e9e<\/p><pre>Correction du probl\u00e8me li\u00e9 \u00e0 l'heure d'\u00e9t\u00e9 mise en \u0153uvre.\n\nFichiers modifi\u00e9s :\n\n- [scheduler\/time_rules.py](.\/scheduler\/time_rules.py)\n- [tests\/test_time_rules.py](.\/tests\/test_time_rules.py)\n\nModifications :\n\n- Avance d'un jour civil local au lieu de 24 heures UTC.\n- Ajout de tests de r\u00e9gression pour le passage \u00e0 l'heure d'\u00e9t\u00e9 et le retour \u00e0 l'heure d'hiver \u00e0 New York.\n- V\u00e9rification que les intervalles UTC \u00e9coul\u00e9s sont respectivement de 23 et 25 heures.\n\nV\u00e9rifications :\n\n- Tests unitaires : 4 r\u00e9ussis.\n- V\u00e9rification syntaxique en m\u00e9moire : 7 fichiers Python ont r\u00e9ussi.\n- La compilation du bytecode a \u00e9t\u00e9 bloqu\u00e9e car Python redirige son cache en dehors de l\u2019espace de travail attribu\u00e9 ; aucun fichier externe n\u2019a \u00e9t\u00e9 \u00e9crit.\n\n**Conclusion :** `next_daily_run` conserve d\u00e9sormais l\u2019heure r\u00e9elle demand\u00e9e lors des transitions d\u2019heure d\u2019\u00e9t\u00e9. Aucune d\u00e9cision n\u2019est requise.<\/pre><\/div><\/details><details class=\"d-full\"><summary>Afficher l'int\u00e9gralit\u00e9 du code de sortie Claude<\/summary><div class=\"d-full-pane\"><p class=\"d-full-note\">Compte rendu complet du transfert, y compris la transcription mot pour mot de la premi\u00e8re sortie valide<\/p><pre>Fichier d'ex\u00e9cution # T3 \u2014 Correction d'un bug DST\n\nParam\u00e8tres d'ex\u00e9cution ##\n\n| Champ | Valeur |\n| --- | --- |\n| T\u00e2che | `T3` |\n| Invite fig\u00e9e | `01-prompts\/T3.md` |\n| SHA-256 de la invite gel\u00e9e | `3fee50d0230f27f8d6dd7f12e050fa3f0b7f5fb77d9559361fee96e5f1a47307` |\n| Unit\u00e9 d\u2019ex\u00e9cution | sous-agent Claude isol\u00e9, `usage g\u00e9n\u00e9ral`, contexte neuf |\n| M\u00e9thode d\u2019isolation | **repli sur sous-agent** (r\u00e9trogradation document\u00e9e \u2014 voir `results\/isolation-decision.md`) |\n| Copie propre attribu\u00e9e | `runtime\/workspaces\/T3` |\n| Version du code Claude | `2.1.220` |\n| Param\u00e9trage du mod\u00e8le | `claude-opus-5` |\n| start_utc | `2026-07-28T10:28:05Z` |\n| end_utc | `2026-07-28T10:30:03Z` |\n| Dur\u00e9e | 118 s (en parall\u00e8le avec T1, T2, T4 ; mesure de latence non pure) |\n| Num\u00e9ro de tentative | 1 |\n| Statut | `valide` |\n| Intervention humaine | aucune |\n\n## R\u00e9sum\u00e9 de l\u2019outil Safe\n\n`date`, `Lecture`\/`Modification` uniquement dans l\u2019espace de travail attribu\u00e9, `python3 -m unittest discover`,\n`python3 -m compileall`, une ex\u00e9cution de contr\u00f4le n\u00e9gatif en m\u00e9moire, une v\u00e9rification de l\u2019int\u00e9grit\u00e9 du manifeste.\nBiblioth\u00e8que standard uniquement (`datetime`, `zoneinfo`, `unittest`). Pas de r\u00e9seau, pas d\u2019installations.\n\n## Fichiers modifi\u00e9s\n\n`scheduler\/time_rules.py` (la correction \u2014 uniquement le corps et la cha\u00eene de documentation de `next_daily_run`),\n`tests\/test_scheduler.py` (ajout de `NextDailyRunTests`, 8 tests, plus une fonction d'aide `_elapsed` ;\nles tests existants n\u2019ont pas \u00e9t\u00e9 modifi\u00e9s). Aucun autre module n\u2019a \u00e9t\u00e9 modifi\u00e9, aucun fichier n\u2019a \u00e9t\u00e9 ajout\u00e9. Patch complet :\n`results\/T3\/patch.diff`.\n\n## R\u00e9sultats de la v\u00e9rification hors ligne\n\nRapport\u00e9s par l\u2019ex\u00e9cuteur de t\u00e2ches :\n\n| V\u00e9rification | R\u00e9sultat |\n| --- | --- |\n| `python3 -m unittest discover -s tests -v` | **10 r\u00e9ussis, 0 \u00e9chou\u00e9s** (2 pr\u00e9existants + 8 nouveaux) |\n| `python3 -m compileall -q scheduler tests` | sans erreur |\n| Int\u00e9grit\u00e9 du manifeste par rapport \u00e0 `fixture-manifest.json` | 0 \u00e9l\u00e9ment manquant, 0 \u00e9l\u00e9ment inattendu |\n| Contr\u00f4le n\u00e9gatif : impl\u00e9mentation de r\u00e9f\u00e9rence patch\u00e9e en m\u00e9moire, `NextDailyRunTests` uniquement | 8 tests ex\u00e9cut\u00e9s, **5 \u00e9checs comme pr\u00e9vu**, y compris les deux tests DST |\n\nRev\u00e9rifi\u00e9 de mani\u00e8re ind\u00e9pendante par le coordinateur depuis l\u2019ext\u00e9rieur de l\u2019espace de travail :\n\n| V\u00e9rification | Sortie | R\u00e9sultat |\n| --- | --- | --- |\n| suite publique (`results\/checks\/T3-public.txt`) | 0 | 10 tests, OK |\n| validateur cach\u00e9 `03-checks\/test_t3_hidden.py` (`results\/checks\/T3-hidden.txt`) | 0 | 2 tests, OK |\n\nLe validateur cach\u00e9 \u00e9choue (sortie 1) sur une copie vierge du fixture. Voir\n`results\/checks\/validator-controls.md`.\n\n## Couverture des comportements de la carte de r\u00e9f\u00e9rence\n\nLes quatre comportements requis dans `03-checks\/gold-map.json` sont tous satisfaits :\n\n| Comportement requis | Preuve |\n| --- | --- |\n| Heure de l\u2019horloge murale conserv\u00e9e | incr\u00e9ment appliqu\u00e9 \u00e0 l\u2019horloge murale locale na\u00efve, fuseau horaire r\u00e9attribu\u00e9 ; v\u00e9rifi\u00e9 dans chaque test d\u2019heure d\u2019\u00e9t\u00e9 |\n| Transition de printemps couverte | `test_spring_forward_keeps_requested_hour` \u2014 heure 09h30 conserv\u00e9e, d\u00e9calage `-04:00`, dur\u00e9e \u00e9coul\u00e9e : 23 h |\n| Transition d\u2019automne couverte | `test_fall_back_keeps_requested_hour` \u2014 heure 09h30 conserv\u00e9e, d\u00e9calage `-05:00`, dur\u00e9e \u00e9coul\u00e9e : 25 h |\n| Fuseau horaire IANA utilis\u00e9 | `ZoneInfo(\"America\/New_York\")` issu de la biblioth\u00e8que standard |\n\nAu-del\u00e0 de l\u2019ensemble requis, le testeur a \u00e9galement couvert les deux cas limites de la PEP 495 \u2014 un temps r\u00e9el\nignor\u00e9 lors du passage \u00e0 l\u2019heure d\u2019\u00e9t\u00e9 et un temps r\u00e9el ambigu lors du retour \u00e0 l\u2019heure d\u2019hiver \u2014 ainsi que des cycles de sept jours\nchevauchant chaque transition et un comportement en cas d\u2019entr\u00e9e na\u00efve.\n\n## Erreurs corrig\u00e9es\n\nDeux \u00e9checs d\u2019assertions de test dus \u00e0 une erreur de notre part : `following - previous` sur deux dates-heures partageant un\n`tzinfo` soustrait les heures r\u00e9elles na\u00efves, ce qui a conduit les assertions de temps \u00e9coul\u00e9 \u00e0 afficher 1 jour et \u00e0 \u00e9chouer.\nL\u2019impl\u00e9mentation \u00e9tait correcte et les assertions \u00e9taient erron\u00e9es ; correction effectu\u00e9e \u00e0 l\u2019aide d\u2019une fonction auxiliaire `_elapsed`\nqui convertit d\u2019abord les deux op\u00e9randes en UTC. Aucune erreur d\u2019outils, d\u2019importation ou d\u2019environnement.\nLes artefacts `__pycache__` ont \u00e9t\u00e9 supprim\u00e9s apr\u00e8s l\u2019ex\u00e9cution.\n\n## Sortie visible (textuel)\n\n**Reproduction**\n\n`scheduler\/time_rules.py::next_daily_run` a \u00e9t\u00e9 appel\u00e9 avec une date-heure `America\/New_York` de part et d\u2019autre d\u2019un changement d\u2019heure d\u2019\u00e9t\u00e9 en 2024 :\n\n```\n2024-03-09T09:30:00-05:00 -&gt; 2024-03-10T10:30:00-04:00   # : d\u00e9calage horaire de +1\n2024-11-02T09:30:00-04:00 -&gt; 2024-11-03T08:30:00-05:00   # : d\u00e9calage horaire de -1\n```\n\nUne t\u00e2che pr\u00e9vue \u00e0 09h30 heure locale a \u00e9t\u00e9 lanc\u00e9e \u00e0 10h30 apr\u00e8s le passage \u00e0 l\u2019heure d\u2019\u00e9t\u00e9 et \u00e0 08h30 apr\u00e8s le retour \u00e0 l\u2019heure d\u2019hiver.\n\n**Cause premi\u00e8re**\n\nL\u2019impl\u00e9mentation d\u2019origine traitait \" daily \" comme une dur\u00e9e absolue fixe :\n\n```python\nelapsed = previous_run.astimezone(timezone.utc) + timedelta(hours=24)\nreturn elapsed.astimezone(previous_run.tzinfo)\n```\n\nLa conversion pr\u00e9alable en UTC fait que `timedelta(hours=24)` correspond exactement \u00e0 24 heures \u00e9coul\u00e9es. Or, un jour calendaire local dans un fuseau horaire IANA dure 23 h le jour du passage \u00e0 l\u2019heure d\u2019\u00e9t\u00e9 et 25 h le jour du retour \u00e0 l\u2019heure d\u2019hiver ; un d\u00e9calage constant de 24 h se retrouve donc n\u00e9cessairement \u00e0 une heure de l\u2019heure r\u00e9elle demand\u00e9e.\n\n**La correction** (`scheduler\/time_rules.py`)\n\nLa r\u00e9currence quotidienne est une r\u00e8gle de calendrier ; l\u2019incr\u00e9ment est donc d\u00e9sormais appliqu\u00e9 \u00e0 l\u2019heure locale brute, le fuseau horaire \u00e9tant r\u00e9attribu\u00e9 par la suite :\n\n```python\ntzinfo = previous_run.tzinfo\nnaive_next = previous_run.replace(tzinfo=None) + timedelta(days=1)\nif tzinfo is None:\n    return naive_next\ncandidate = naive_next.replace(tzinfo=tzinfo, fold=0)\nreturn candidate.astimezone(timezone.utc).astimezone(tzinfo)\n```\n\nPourquoi cela est correct :\n- Le calcul de l\u2019horloge murale sur la valeur \u00ab na\u00efve \u00bb est ind\u00e9pendant du d\u00e9calage horaire ; ainsi, l\u2019heure et la minute demand\u00e9es sont conserv\u00e9es par construction ; `zoneinfo` fournit ensuite le d\u00e9calage UTC en vigueur \u00e0 la nouvelle date (v\u00e9rifi\u00e9 : `-04:00` apr\u00e8s le passage \u00e0 l\u2019heure d\u2019\u00e9t\u00e9, `-05:00` apr\u00e8s le retour \u00e0 l\u2019heure d\u2019hiver, temps r\u00e9el \u00e9coul\u00e9 respectivement de 23 h et 25 h).\n- `fold=0`, combin\u00e9 au cycle aller-retour UTC, g\u00e8re les deux cas limites que l\u2019arithm\u00e9tique pure de l\u2019horloge murale laisse mal d\u00e9finis. Conform\u00e9ment \u00e0 la PEP 495, une heure murale *saut\u00e9e* (02 h 30 le 10\/03\/2024) a le d\u00e9calage d\u2019avant la transition \u00e0 `fold=0` ; le va-et-vient le normalise donc \u00e0 l\u2019instant r\u00e9el 03 h 30 EDT plut\u00f4t que de renvoyer une date-heure ne d\u00e9signant aucun instant. Une heure r\u00e9elle *ambigu\u00eb* (01 h 30 le 03\/11\/2024) est r\u00e9solue de mani\u00e8re d\u00e9terministe vers sa premi\u00e8re occurrence (EDT) au lieu d\u2019\u00eatre arbitraire.\n- Une entr\u00e9e \u00ab na\u00efve \u00bb conserve sa signification ant\u00e9rieure (simplement +1 jour calendaire) \u2014 aucune nouvelle exigence `tzinfo` n\u2019est impos\u00e9e aux appelants.\n\nLa port\u00e9e a \u00e9t\u00e9 maintenue \u00e9troite : seuls le corps et la cha\u00eene de documentation de `next_daily_run` ont \u00e9t\u00e9 modifi\u00e9s. `service.py`, `models.py`, `repository.py` et `__init__.py` n\u2019ont pas \u00e9t\u00e9 modifi\u00e9s, aucun nouveau fichier n\u2019a \u00e9t\u00e9 ajout\u00e9 et le manifeste des fixtures correspond toujours exactement (aucun fichier manquant ou inattendu). Utilisation exclusive de la biblioth\u00e8que standard (`datetime`, `zoneinfo`, `unittest`).\n\n**Tests de r\u00e9gression** (`tests\/test_scheduler.py`, nouveau `NextDailyRunTests`, 8 tests) couvrent : la stabilit\u00e9 en temps normal, le passage \u00e0 l\u2019heure d\u2019\u00e9t\u00e9 + d\u00e9calage + 23 h \u00e9coul\u00e9es, le passage \u00e0 l\u2019heure d\u2019hiver + d\u00e9calage + 25 h \u00e9coul\u00e9es, des cycles de sept jours chevauchant chaque transition, un temps r\u00e9el saut\u00e9e, un temps r\u00e9el ambigu et une entr\u00e9e na\u00efve.\n\nDeux remarques m\u00e9ritent d\u2019\u00eatre not\u00e9es. Premi\u00e8rement, mes assertions initiales sur le temps \u00e9coul\u00e9 utilisaient `following - previous` ; Python ignore un `tzinfo` partag\u00e9 et soustrait les heures r\u00e9elles na\u00efves, ce qui a conduit les deux \u00e0 renvoyer 1 jour et \u00e0 \u00e9chouer. L\u2019impl\u00e9mentation \u00e9tait correcte et les assertions erron\u00e9es \u2014 correction effectu\u00e9e \u00e0 l\u2019aide d\u2019une fonction auxiliaire `_elapsed` qui convertit les deux op\u00e9randes en UTC. Deuxi\u00e8mement, j\u2019ai v\u00e9rifi\u00e9 que les tests d\u00e9tectaient bien le d\u00e9faut d\u2019origine en r\u00e9ex\u00e9cutant `NextDailyRunTests` sur une copie en m\u00e9moire de l\u2019impl\u00e9mentation initialis\u00e9e : 5 tests sur 8 ont \u00e9chou\u00e9, y compris les deux tests relatifs \u00e0 l\u2019heure d\u2019\u00e9t\u00e9. Les trois tests qui r\u00e9ussissent avec la version bogu\u00e9e (jour ordinaire, saut, ambigu\u00eft\u00e9) documentent le comportement plut\u00f4t que de d\u00e9tecter une r\u00e9gression \u2014 les cas \u00ab saut \u00bb et \u00ab ambigu\u00eft\u00e9 \u00bb co\u00efncident par hasard, car un d\u00e9calage absolu de +24 h tombe justement sur le m\u00eame instant normalis\u00e9.\n<\/pre><\/div><\/details><\/div><p class=\"d-limit\">Limitation li\u00e9e \u00e0 l'environnement de test : il s'agissait d'un petit r\u00e9f\u00e9rentiel Python hors ligne. Claude utilisait un sous-agent de secours apr\u00e8s l'expiration de l'OAuth via l'interface en ligne de commande (CLI) ; par cons\u00e9quent, l'isolation et la visibilit\u00e9 des jetons n'\u00e9taient pas identiques.<\/p><\/article>\n\n\n\n<h2 id=\"code-review\" class=\"wp-block-heading\">Qualit\u00e9 de la r\u00e9vision du code et v\u00e9rification humaine<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Les t\u00e2ches de r\u00e9vision de code font appel \u00e0 des comp\u00e9tences diff\u00e9rentes de celles requises pour la mise en \u0153uvre de fonctionnalit\u00e9s. Un r\u00e9viseur comp\u00e9tent doit identifier des probl\u00e8mes reproductibles, \u00e9valuer leur impact, indiquer le chemin d'acc\u00e8s exact au code et distinguer un v\u00e9ritable d\u00e9faut d'un avertissement hypoth\u00e9tique. La correction d'un probl\u00e8me implique un test suppl\u00e9mentaire : le correctif ne doit pas introduire de nouvelle r\u00e9gression.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Le code Claude pr\u00e9sentait l'avantage le plus net dans la cat\u00e9gorie T4. Il a signal\u00e9 cinq r\u00e9sultats reproductibles de mani\u00e8re ind\u00e9pendante, y compris les deux cibles d\u2019audit pr\u00e9\u00e9tablies, et a obtenu une note de 19\/20. Codex a signal\u00e9 et corrig\u00e9 deux d\u00e9fauts valides de gravit\u00e9 \u00e9lev\u00e9e, mais n\u2019a pas mentionn\u00e9 la paire pr\u00e9\u00e9tablie, obtenant ainsi une note de 18\/20. Les r\u00e9sultats de Codex n\u2019\u00e9taient pas des faux positifs ; la diff\u00e9rence observ\u00e9e tenait davantage \u00e0 l\u2019exhaustivit\u00e9 qu\u2019\u00e0 l\u2019exactitude fondamentale.<\/p>\n\n\n\n<style>\n.evidence-t4-review-and-repair{--ink:#111318;--body:#414753;--muted:#707784;--line:#e4e7ec;--soft:#f6f7f9;--blue:#315efb;--violet:#7257e8;--green:#087a55;--greenSoft:#eaf8f2;--red:#a23131;--redSoft:#fff0f0;color:var(--ink);font-family:Inter,ui-sans-serif,-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif;line-height:1.5;border:1px solid var(--line);border-radius:8px;background:#fff;overflow:hidden;box-shadow:0 16px 42px rgba(24,32,56,.08)}\n.evidence-t4-review-and-repair *{box-sizing:border-box}.evidence-t4-review-and-repair .d-head{display:flex;align-items:flex-start;justify-content:space-between;gap:22px;padding:24px 26px 20px;border-bottom:1px solid var(--line)}\n.evidence-t4-review-and-repair .d-kicker{margin:0 0 6px;color:var(--muted);font:750 11px\/1.4 ui-monospace,SFMono-Regular,Menlo,monospace;letter-spacing:.08em;text-transform:uppercase}.evidence-t4-review-and-repair .d-title{margin:0;font-size:22px;line-height:1.2;letter-spacing:-.025em}.evidence-t4-review-and-repair .d-sub{margin:7px 0 0;color:var(--body);font-size:13px}.evidence-t4-review-and-repair .d-pill{flex:0 0 auto;padding:6px 10px;border:1px solid #ccd6ff;border-radius:999px;color:#2448ca;background:#f0f3ff;font-size:11px;font-weight:800}.evidence-t4-review-and-repair .d-grid{display:grid;grid-template-columns:1fr 1fr}.evidence-t4-review-and-repair .d-side{min-width:0;padding:24px 26px}.evidence-t4-review-and-repair .d-side+.d-side{border-left:1px solid var(--line)}.evidence-t4-review-and-repair .d-product{display:flex;align-items:baseline;justify-content:space-between;gap:14px;font-weight:800}.evidence-t4-review-and-repair .d-score{font-size:34px;line-height:1;letter-spacing:-.05em}.evidence-t4-review-and-repair .d-score small{color:var(--muted);font-size:12px;letter-spacing:0}.evidence-t4-review-and-repair .d-metrics{display:grid;grid-template-columns:repeat(3,1fr);gap:7px;margin:18px 0}.evidence-t4-review-and-repair .d-metric{padding:10px;border:1px solid var(--line);border-radius:6px;background:var(--soft)}.evidence-t4-review-and-repair .d-metric span{display:block;color:var(--muted);font-size:9px;font-weight:800;letter-spacing:.06em;text-transform:uppercase}.evidence-t4-review-and-repair .d-metric strong{display:block;margin-top:3px;font-size:13px}.evidence-t4-review-and-repair .d-preview{position:relative;height:192px;overflow:hidden;border:1px solid #29313f;border-radius:6px;background:#11151d;color:#edf0f5}.evidence-t4-review-and-repair .d-preview-label{padding:11px 13px;border-bottom:1px solid rgba(255,255,255,.1);color:#aeb7c7;font:750 9px\/1 ui-monospace,SFMono-Regular,Menlo,monospace;letter-spacing:.06em;text-transform:uppercase}.evidence-t4-review-and-repair .d-preview pre,.evidence-t4-review-and-repair .d-full pre{margin:0;white-space:pre-wrap;font:11px\/1.6 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.evidence-t4-review-and-repair .d-preview pre{padding:13px}.evidence-t4-review-and-repair .d-preview:after{content:\"\";position:absolute;left:0;right:0;bottom:0;height:55px;background:linear-gradient(transparent,#11151d)}.evidence-t4-review-and-repair .d-take{margin:14px 0 0;color:var(--body);font-size:12px}.evidence-t4-review-and-repair .d-fulls{padding:0 26px 22px}.evidence-t4-review-and-repair .d-full{margin-top:10px;border:1px solid var(--line);border-radius:6px}.evidence-t4-review-and-repair .d-full summary{cursor:pointer;padding:13px 14px;font-size:12px;font-weight:800;list-style:none}.evidence-t4-review-and-repair .d-full summary::-webkit-details-marker{display:none}.evidence-t4-review-and-repair .d-full summary:after{content:\"+\";float:right;color:var(--blue);font-size:17px}.evidence-t4-review-and-repair .d-full[open] summary:after{content:\"\u2212\"}.evidence-t4-review-and-repair .d-full-pane{padding:0 14px 14px}.evidence-t4-review-and-repair .d-full-note{margin:0 0 9px;color:var(--muted);font-size:10px}.evidence-t4-review-and-repair .d-full pre{max-height:620px;overflow:auto;padding:15px;border-radius:5px;background:#f5f6f8;color:#222936;border:1px solid #e0e3e8}.evidence-t4-review-and-repair .d-limit{margin:0;padding:12px 26px;border-top:1px solid var(--line);color:#5a6270;background:#fafbfc;font-size:11px}\n@media(max-width:760px){.evidence-t4-review-and-repair .d-head{display:block}.evidence-t4-review-and-repair .d-pill{display:inline-block;margin-top:12px}.evidence-t4-review-and-repair .d-grid{grid-template-columns:1fr}.evidence-t4-review-and-repair .d-side+.d-side{border-left:0;border-top:1px solid var(--line)}}@media(max-width:480px){.evidence-t4-review-and-repair .d-head,.evidence-t4-review-and-repair .d-side{padding:20px}.evidence-t4-review-and-repair .d-fulls{padding:0 20px 20px}.evidence-t4-review-and-repair .d-metrics{grid-template-columns:1fr}}\n<\/style><article class=\"evidence-t4-review-and-repair\"><header class=\"d-head\"><div><p class=\"d-kicker\">T4 \u00b7 Test du r\u00e9f\u00e9rentiel contr\u00f4l\u00e9<\/p><h3 class=\"d-title\">Identifier les d\u00e9fauts reproductibles et corriger les probl\u00e8mes pr\u00e9sentant le plus haut niveau de fiabilit\u00e9<\/h3><p class=\"d-sub\">Examinez le test, reproduisez les d\u00e9fauts r\u00e9els, appliquez les corrections autoris\u00e9es et v\u00e9rifiez que les tests de r\u00e9gression valident le comportement.<\/p><\/div><span class=\"d-pill\">Bord de couverture Claude<\/span><\/header><div class=\"d-grid\"><section class=\"d-side\" aria-label=\"R\u00e9sultat du Codex\"><div class=\"d-product\"><span>Codex<\/span><span class=\"d-score\">18<small>\/20<\/small><\/span><\/div><div class=\"d-metrics\"><div class=\"d-metric\"><span>Dur\u00e9e<\/span><strong>223 s<\/strong><\/div><div class=\"d-metric\"><span>Ch\u00e8ques<\/span><strong>4 ont r\u00e9ussi<\/strong><\/div><div class=\"d-metric\"><span>Champ d'application<\/span><strong>2 corrig\u00e9<\/strong><\/div><\/div><div class=\"d-preview\"><div class=\"d-preview-label\">Extrait de la premi\u00e8re sortie valide<\/div><pre>1. \u00c9lev\u00e9 \u2014 Les t\u00e2ches existantes pourraient \u00eatre \u00e9cras\u00e9es sans avertissement.\n\n2. Moyen \u2014 Les ex\u00e9cutions quotidiennes ont connu des d\u00e9calages lors des changements d'heure.\n\nV\u00e9rification : quatre tests r\u00e9ussis, aucun \u00e9chec.<\/pre><\/div><p class=\"d-take\"><strong>Avis du critique :<\/strong> Des r\u00e9sultats utiles concernant les probl\u00e8mes de gravit\u00e9 \u00e9lev\u00e9e et des corrections cibl\u00e9es, mais les deux objectifs de r\u00e9vision fix\u00e9s n'ont pas \u00e9t\u00e9 atteints.<\/p><\/section><section class=\"d-side\" aria-label=\"R\u00e9sultat du code Claude\"><div class=\"d-product\"><span>Claude Code<\/span><span class=\"d-score\">19<small>\/20<\/small><\/span><\/div><div class=\"d-metrics\"><div class=\"d-metric\"><span>Dur\u00e9e<\/span><strong>235 s<\/strong><\/div><div class=\"d-metric\"><span>Ch\u00e8ques<\/span><strong>9 ont \u00e9t\u00e9 adopt\u00e9es<\/strong><\/div><div class=\"d-metric\"><span>Champ d'application<\/span><strong>5 cas signal\u00e9s<\/strong><\/div><\/div><div class=\"d-preview\"><div class=\"d-preview-label\">Extrait de la premi\u00e8re sortie valide<\/div><pre>D1 D\u00e9rive de l'heure d'\u00e9t\u00e9 (DST) \u00b7 \u00c9lev\u00e9\nD2 Acquisition na\u00efve du fuseau horaire \u00b7 Moyen\nD3 Collision d'identifiants \u00b7 \u00c9lev\u00e9\nD4 L'absence de suppression provoque une erreur \u00ab KeyError \u00bb \u00b7 Moyen\nD5 Propri\u00e9taire non valid\u00e9 \u00b7 Faible<\/pre><\/div><p class=\"d-take\"><strong>Avis du critique :<\/strong> Une couverture d'analyse plus \u00e9tendue, sans aucun faux positif reproduit ; deux anomalies li\u00e9es au contrat n'ont pas \u00e9t\u00e9 corrig\u00e9es.<\/p><\/section><\/div><div class=\"d-fulls\"><details class=\"d-full\"><summary>Afficher l'int\u00e9gralit\u00e9 des r\u00e9sultats de Codex<\/summary><div class=\"d-full-pane\"><p class=\"d-full-note\">Sortie compl\u00e8te, valid\u00e9e et aseptis\u00e9e<\/p><pre>## Conclusions n\u00e9cessitant une action\n\n1. **Risque \u00e9lev\u00e9 \u2014 Les t\u00e2ches existantes pourraient \u00eatre \u00e9cras\u00e9es sans avertissement**\n\n   - Preuve : initialisation de l\u2019identifiant dans [service.py](.\/scheduler\/service.py:8), combin\u00e9e au remplacement du dictionnaire dans [repository.py](.\/scheduler\/repository.py:9).\n   - Impact : la cr\u00e9ation d\u2019un service \u00e0 partir d\u2019un r\u00e9f\u00e9rentiel existant pourrait r\u00e9utiliser l\u2019identifiant `1`, rempla\u00e7ant ainsi la t\u00e2che stock\u00e9e et entra\u00eenant une perte de donn\u00e9es.\n   - Reproduction minimale : enregistrer `Job(1, ...)`, construire `SchedulerService(repository)`, puis cr\u00e9er une autre t\u00e2che. Avant la correction, seule la nouvelle t\u00e2che subsistait.\n   - Correction : initialiser l\u2019identifiant suivant \u00e0 partir de l\u2019identifiant existant le plus \u00e9lev\u00e9 du r\u00e9f\u00e9rentiel.\n   - Test de r\u00e9gression : [test_scheduler.py](.\/tests\/test_scheduler.py:22).\n\n2. **Impact moyen \u2014 Les ex\u00e9cutions quotidiennes ont subi des d\u00e9calages lors des changements d\u2019heure d\u2019\u00e9t\u00e9**\n\n   - Preuve : calcul corrig\u00e9 dans [time_rules.py](.\/scheduler\/time_rules.py:4).\n   - Impact : une t\u00e2che quotidienne planifi\u00e9e \u00e0 09h00 s\u2019ex\u00e9cutait \u00e0 10h00 apr\u00e8s le passage \u00e0 l\u2019heure d\u2019\u00e9t\u00e9 au printemps.\n   - Reproduction minimale : calculer la prochaine ex\u00e9cution apr\u00e8s `2026-03-07 09:00 America\/New_York`. Avant la correction, le r\u00e9sultat \u00e9tait `2026-03-08 10h00`.\n   - Correction : ajouter un jour civil local au lieu de 24 heures UTC \u00e9coul\u00e9es.\n   - Test de r\u00e9gression : [test_scheduler.py](.\/tests\/test_scheduler.py:33).\n\n## Fichiers modifi\u00e9s\n\n- [scheduler\/service.py](.\/scheduler\/service.py)\n- [scheduler\/time_rules.py](.\/scheduler\/time_rules.py)\n- [tests\/test_scheduler.py](.\/tests\/test_scheduler.py)\n\n## V\u00e9rification\n\n- Les deux tests de r\u00e9gression ont \u00e9chou\u00e9 avant leur correction.\n- Chacun a r\u00e9ussi apr\u00e8s la correction correspondante.\n- `PYTHONDONTWRITEBYTECODE=1 python3 -m unittest discover -s tests -v`\n- R\u00e9sultat : **4 tests r\u00e9ussis, 0 \u00e9chec**.\n- Il ne reste aucun artefact de cache Python g\u00e9n\u00e9r\u00e9.\n\n## Conclusion et d\u00e9cision\n\n- **Conclusion :** Les deux d\u00e9fauts confirm\u00e9s sont corrig\u00e9s et couverts par des tests de r\u00e9gression cibl\u00e9s.\n- **D\u00e9cision requise :** Aucune.<\/pre><\/div><\/details><details class=\"d-full\"><summary>Afficher l'int\u00e9gralit\u00e9 du code de sortie Claude<\/summary><div class=\"d-full-pane\"><p class=\"d-full-note\">Compte rendu complet du transfert, y compris la transcription mot pour mot de la premi\u00e8re sortie valide<\/p><pre># T4 : Compte-rendu d'ex\u00e9cution \u2014 Test et r\u00e9vision du code\n\n## Param\u00e8tres d'ex\u00e9cution\n\n| Champ | Valeur |\n| --- | --- |\n| T\u00e2che | `T4` |\n| Invite fig\u00e9e | `01-prompts\/T4.md` |\n| SHA-256 de la prompt fig\u00e9e | `5e69546007ea776f40b3d334ddb75671ff684c151c77551bad27de3b0fdce640` |\n| Unit\u00e9 d\u2019ex\u00e9cution | sous-agent Claude isol\u00e9, `usage g\u00e9n\u00e9ral`, contexte neuf |\n| M\u00e9thode d\u2019isolation | **repli sur sous-agent** (r\u00e9trogradation document\u00e9e \u2014 voir `results\/isolation-decision.md`) |\n| Copie propre attribu\u00e9e | `runtime\/workspaces\/T4` |\n| Version du code Claude | `2.1.220` |\n| Param\u00e9trage du mod\u00e8le | `claude-opus-5` |\n| start_utc | `2026-07-28T10:28:22Z` |\n| end_utc | `2026-07-28T10:32:17Z` |\n| Dur\u00e9e | 235 s (simultan\u00e9e avec T1\u2013T3 ; mesure de latence non pr\u00e9cise) |\n| Num\u00e9ro de tentative | 1 |\n| Statut | `valid` |\n| Intervention humaine | aucune |\n\nLa condition figurant dans l\u2019invite de commande gel\u00e9e \u2014 \" corrigez-les si la configuration d\u2019ex\u00e9cution gel\u00e9e autorise\nles corrections \" \u2014 a \u00e9t\u00e9 r\u00e9solue par le coordinateur \u00e0 partir des fichiers `00-control\/run-config.json` et\n`00-control\/safety-policy.json`, qui autorisent l\u2019\u00e9criture de copies isol\u00e9es des fixtures. Le runner a \u00e9t\u00e9\ninform\u00e9 que les corrections \u00e9taient autoris\u00e9es. Aucun fichier de contr\u00f4le ne lui a \u00e9t\u00e9 pr\u00e9sent\u00e9.\n\n## R\u00e9sum\u00e9 des outils s\u00e9curis\u00e9s\n\n`date`, `Lecture`\/`Modification`\/`\u00c9criture` uniquement dans l\u2019espace de travail attribu\u00e9, `grep`,\n`python3 -m unittest discover`, `python3 -m compileall`, une ex\u00e9cution sur une copie temporaire vide, une\nv\u00e9rification de la pr\u00e9sence du manifeste. Pas de r\u00e9seau, pas d\u2019installations, biblioth\u00e8que standard uniquement.\n\n## Fichiers modifi\u00e9s\n\n`scheduler\/time_rules.py` (modifi\u00e9), `scheduler\/service.py` (modifi\u00e9),\n`tests\/test_scheduler.py` (modifi\u00e9, +2 tests), `tests\/test_time_rules.py` (ajout\u00e9, 5 tests).\nPatch complet : `results\/T4\/patch.diff`.\n\n## R\u00e9sultats de la v\u00e9rification hors ligne\n\nSignal\u00e9s par le gestionnaire de t\u00e2ches :\n\n| V\u00e9rification | R\u00e9sultat |\n| --- | --- |\n| `python3 -m unittest discover -s tests -v` | **9 r\u00e9ussis, 0 \u00e9chou\u00e9s, 0 ignor\u00e9s** (r\u00e9f\u00e9rence 2) |\n| `python3 -m compileall -q scheduler tests` | r\u00e9ussi |\n| V\u00e9rification de la pr\u00e9sence du manifeste par rapport \u00e0 `expected_files` | les 8 fichiers sont pr\u00e9sents |\n| Ex\u00e9cution de vacuity sur les impl\u00e9mentations d\u2019origine restaur\u00e9es | 5 \u00e9checs, 4 r\u00e9ussis, comme pr\u00e9vu |\n\nRev\u00e9rifi\u00e9 de mani\u00e8re ind\u00e9pendante par le coordinateur depuis l\u2019ext\u00e9rieur de l\u2019espace de travail :\n\n| V\u00e9rification | Sortie | R\u00e9sultat |\n| --- | --- | --- |\n| suite publique (`results\/checks\/T4-public.txt`) | 0 | 9 tests, OK |\n\nContr\u00f4le crois\u00e9 \u00e0 titre informatif, non not\u00e9 : le validateur cach\u00e9 T3 r\u00e9ussit \u00e9galement sur cet\nespace de travail (sortie 0), car T4 a corrig\u00e9 de mani\u00e8re ind\u00e9pendante le m\u00eame d\u00e9faut `next_daily_run`. Voir\n`results\/checks\/validator-controls.md`.\n\n## Couverture des d\u00e9fauts de la carte de r\u00e9f\u00e9rence\n\n`03-checks\/gold-map.json` implante deux d\u00e9fauts pour l\u2019\u00e9valuation T4. Les deux ont \u00e9t\u00e9 d\u00e9tect\u00e9s :\n\n| D\u00e9faut implant\u00e9 | D\u00e9tect\u00e9 | Signal\u00e9 comme |\n| --- | --- | --- |\n| propri\u00e9taire vide accept\u00e9 | oui | **D5**, `scheduler\/service.py:11,13`, gravit\u00e9 Faible, signal\u00e9 et d\u00e9lib\u00e9r\u00e9ment non corrig\u00e9 |\n| La suppression d\u2019un identifiant manquant provoque une erreur `KeyError` | oui | **D4**, `scheduler\/repository.py:19` \u2192 `service.py:22`, gravit\u00e9 moyenne, signal\u00e9 et d\u00e9lib\u00e9r\u00e9ment non corrig\u00e9 |\n\nTrois autres anomalies ont \u00e9t\u00e9 signal\u00e9es en plus de celles initialement introduites. Aucune n\u2019est un faux positif :\n\n- **D1** \u2014 D\u00e9calage de l\u2019heure d\u2019\u00e9t\u00e9 dans `next_daily_run`. Il s\u2019agit du troisi\u00e8me d\u00e9faut r\u00e9pertori\u00e9 dans\n  `03-checks\/seeded-defects.md` (il est class\u00e9 sous T3 et non sous T4, mais il s\u2019agit bien d\u2019un bug pr\u00e9-int\u00e9gr\u00e9).\n- **D2** \u2014 Une entr\u00e9e na\u00efve dans `next_daily_run` r\u00e9cup\u00e8re silencieusement le fuseau horaire de l\u2019h\u00f4te et renvoie une\n  date-heure adapt\u00e9e. R\u00e9el et d\u00e9pendant de l\u2019h\u00f4te ; v\u00e9rifi\u00e9 par le coordinateur par rapport au code source du test.\n- **D3** \u2014 collision d\u2019identificateurs entre un service et un r\u00e9f\u00e9rentiel inject\u00e9 ou partag\u00e9, provoquant un\n  \u00e9crasement silencieux. R\u00e9el : `SchedulerService._next_identifier` commence toujours \u00e0 1 tandis que\n  `JobRepository.save` est une affectation de dictionnaire non prot\u00e9g\u00e9e. T1 a identifi\u00e9 de mani\u00e8re ind\u00e9pendante la m\u00eame\n  faille \u00e0 partir du test initial.\n\nNombre de faux positifs : **0**. Le runner a \u00e9galement correctement signal\u00e9 l\u2019absence de probl\u00e8mes de s\u00e9curit\u00e9, notant que\nle test ne pr\u00e9sente aucune surface d\u2019attaque li\u00e9e au r\u00e9seau, aux E\/S, \u00e0 la d\u00e9s\u00e9rialisation, aux sous-processus ou aux identifiants.\n\n## \u00c9cart digne d\u2019\u00eatre not\u00e9\n\nL\u2019invite fig\u00e9e demandait des tests et des corrections sur \" les deux d\u00e9fauts pr\u00e9sentant le plus haut niveau de confiance \". L\"\nex\u00e9cuteur a s\u00e9lectionn\u00e9 D1\/D2 (une correction, m\u00eame fonction) et D3, plut\u00f4t que les deux d\u00e9fauts implant\u00e9s dans la carte de r\u00e9f\u00e9rence\nD4 et D5. La raison invoqu\u00e9e est d\u00e9fendable : D4 et D5 reposent tous deux sur un contrat API\nnon sp\u00e9cifi\u00e9, leur correction rel\u00e8verait donc de la conjecture. Le cr\u00e9dit de d\u00e9tection n\u2019est pas affect\u00e9 : les deux d\u00e9fauts pr\u00e9-int\u00e9gr\u00e9s\nont \u00e9t\u00e9 d\u00e9tect\u00e9s, avec indication du fichier, de la ligne, de la gravit\u00e9, de l\u2019impact et de la reproduction. Les corrections appliqu\u00e9es concernaient de v\u00e9ritables\nd\u00e9fauts et sont valid\u00e9es par un contr\u00f4le de vacuit\u00e9.\n\n## Erreurs corrig\u00e9es\n\nDeux \u00e9checs de test auto-provoqu\u00e9s dus \u00e0 une soustraction entre le temps r\u00e9el et le temps absolu sur des dates-heures\npartageant un `tzinfo` ; corrig\u00e9s et rev\u00e9rifi\u00e9s. Aucune erreur li\u00e9e aux outils ou \u00e0 l\u2019environnement. Les artefacts `__pycache__`\nont \u00e9t\u00e9 supprim\u00e9s apr\u00e8s l\u2019ex\u00e9cution.\n\n## Sortie visible (mot pour mot)\n\n### Rapport de d\u00e9faut\n\n**D1 \u2014 `scheduler\/time_rules.py:10-11` \u2014 Le planning quotidien pr\u00e9sente un d\u00e9calage d\u2019une heure lors du passage \u00e0 l\u2019heure d\u2019\u00e9t\u00e9 \u2014 Gravit\u00e9 : \u00c9lev\u00e9e**\n\n`next_daily_run` ajoute 24 heures *\u00e9coul\u00e9es* via un aller-retour UTC au lieu de faire avancer le jour calendaire. Une t\u00e2che quotidienne \u00e9tant d\u00e9finie par l\u2019heure r\u00e9elle, chaque t\u00e2che dans un fuseau horaire appliquant l\u2019heure d\u2019\u00e9t\u00e9 se d\u00e9clenche silencieusement avec une heure d\u2019avance ou de retard \u00e0 partir du jour du changement d\u2019heure, et l\u2019erreur persiste (chaque ex\u00e9cution se r\u00e9initialise \u00e0 partir de l\u2019heure d\u00e9cal\u00e9e). La cha\u00eene de documentation elle-m\u00eame reconnaissait ce comportement.\n\n```\nprev = datetime(2024, 3, 9, 9, 0, tzinfo=ZoneInfo(\"America\/New_York\"))\nnext_daily_run(prev)   # -&gt; 10\/03\/2024 10:00:00-04:00, attendu 09:00-04:00\nprev = datetime(2024, 11, 2, 9, 0, tzinfo=ZoneInfo(\"America\/New_York'))\nnext_daily_run(prev)   # -&gt; 03\/11\/2024 08:00:00-05:00, pr\u00e9vu \u00e0 09:00-05:00\n```\n\n**D2 \u2014 `scheduler\/time_rules.py:10-11` \u2014 Une entr\u00e9e na\u00efve r\u00e9cup\u00e8re silencieusement le fuseau horaire local de la machine \u2014 Gravit\u00e9 : Moyenne**\n\nLes deux m\u00eames lignes. `.astimezone(timezone.utc)` sur un objet `datetime` na\u00eff suppose l'heure locale du syst\u00e8me, et `.astimezone(None)` renvoie un objet `datetime` conscient du fuseau horaire. Un appel avec une valeur ' na\u00efve \" en entr\u00e9e renvoie une valeur \" consciente \" en sortie ; le r\u00e9sultat n\u2019est donc pas comparable aux autres valeurs \" na\u00efves \" de l\u2019appelant (`TypeError` lors de la comparaison) et la r\u00e9ponse d\u00e9pend du param\u00e8tre `TZ` de l\u2019h\u00f4te.\n\n```\nnext_daily_run(datetime(2024, 1, 1, 9, 0))\n# -&gt; datetime(2024, 1, 2, 9, 0, tzinfo=timezone(timedelta(hours=8), \"CST\"))  # d\u00e9pendant de l\u2019h\u00f4te\n```\n\n**D3 \u2014 `scheduler\/service.py:8,13,15` (pr\u00e9fixe) \u2014 Une collision d\u2019identifiants d\u00e9truit silencieusement les t\u00e2ches stock\u00e9es \u2014 Gravit\u00e9 : \u00c9lev\u00e9e**\n\nLe compteur d\u2019identifiants \u00e9tait propre \u00e0 chaque `SchedulerService` et commen\u00e7ait toujours \u00e0 1, sans tenir compte du contenu du r\u00e9f\u00e9rentiel inject\u00e9. Tout deuxi\u00e8me service utilisant un r\u00e9f\u00e9rentiel partag\u00e9, ou tout service utilisant un r\u00e9f\u00e9rentiel pr\u00e9rempli, r\u00e9attribuait l\u2019identifiant 1 ; `JobRepository.save` \u00e9tant une affectation de dictionnaire, la t\u00e2che existante \u00e9tait \u00e9cras\u00e9e sans g\u00e9n\u00e9rer d\u2019erreur. Perte de donn\u00e9es.\n\n```\nrepo = JobRepository()\nSchedulerService(repo).create_job(\"Sauvegarde nocturne', 'Alex')    # id 1\nSchedulerService(repo).create_job('Exportation des fiches de paie\", \"Blake\")   # id 1 \u00e0 nouveau\nrepo.all()   # -&gt; [Job(1, \"Exportation des fiches de paie', 'Blake')]  \u2014 La t\u00e2che d\u2019Alex a disparu\n```\n\n**D4 \u2014 `scheduler\/repository.py:19` \u2192 `scheduler\/service.py:22` \u2014 `delete_job` l\u00e8ve une exception `KeyError` pour un identifiant inconnu \u2014 Gravit\u00e9 : Moyenne**\n\n`delete` utilise `dict.pop` sans valeur par d\u00e9faut, tandis que la m\u00e9thode s\u0153ur `get` (ligne 13) renvoie `None` en cas d\u2019absence de valeur. Cette incoh\u00e9rence provoque une exception `KeyError` brute via `SchedulerService.delete_job`, que les appelants ont peu de chances d\u2019intercepter. Reproduction : `SchedulerService().delete_job(999)` \u2192 `KeyError: 999`. La correction consisterait \u00e0 utiliser `pop(identifier, None)` ou \u00e0 lever explicitement une exception de domaine \u2014 probl\u00e8me d\u00e9lib\u00e9r\u00e9ment laiss\u00e9 tel quel, car le choix du comportement correct (op\u00e9ration silencieuse sans effet vs. erreur typ\u00e9e) rel\u00e8ve d\u2019une d\u00e9cision relative \u00e0 l\u2019API qui incombe au propri\u00e9taire.\n\n**D5 \u2014 `scheduler\/service.py:11,13` \u2014 Le champ ' owner ' n\u2019est pas valid\u00e9 \u2014 Gravit\u00e9 : Faible**\n\nLa valeur de `name` est v\u00e9rifi\u00e9e pour s'assurer qu'elle n'est pas vide, mais pas celle de `owner` : `create_job('ok\", \"   \")` stocke `owner=''`. Les deux param\u00e8tres appellent \u00e9galement `.strip()` sans protection, de sorte que `None` se traduit par `AttributeError : l\u2019objet 'NoneType' n\u2019a pas d\u2019attribut 'strip'` plut\u00f4t que par la `ValueError` que l\u2019API utilise habituellement en cas d\u2019entr\u00e9e incorrecte. Laiss\u00e9e telle quelle \u2014 le contrat pr\u00e9vu pour `owner` n\u2019est mentionn\u00e9 nulle part dans le fixture.\n\n**S\u00e9curit\u00e9 :** aucune anomalie d\u00e9tect\u00e9e. Le fixture ne pr\u00e9sente aucune surface d\u2019exposition au niveau du r\u00e9seau, des E\/S, de la d\u00e9s\u00e9rialisation, des sous-processus ou des identifiants ; le stockage est un dictionnaire interne au processus.\n\n**Lacune de couverture :** les fichiers `scheduler\/time_rules.py` et `scheduler\/repository.py` pr\u00e9sentaient une couverture de test nulle avant cette ex\u00e9cution ; les deux tests initialis\u00e9s ne couvraient que le sc\u00e9nario normal du service.\n\n### Tests et corrections appliqu\u00e9s\n\nLes deux d\u00e9fauts pr\u00e9sentant le plus haut niveau de confiance \u00e9taient **D1\/D2** (m\u00eame fonction, une seule correction) et **D3**.\n\n**Correction 1 \u2014 `scheduler\/time_rules.py` :** remplacement du calcul aller-retour UTC par `previous_run + timedelta(days=1)`. Python effectue des calculs en temps r\u00e9el sur les dates-heures \u00ab aware \u00bb, et `zoneinfo` recalcule le d\u00e9calage UTC de mani\u00e8re diff\u00e9r\u00e9e \u00e0 partir de la nouvelle heure r\u00e9elle \u2014 ainsi, 09:00 reste 09:00 tandis que le d\u00e9calage \u00e9volue correctement de `-05:00 \u2192 -04:00`. Cela corrige \u00e0 la fois D1 et D2 : les entr\u00e9es \u00ab na\u00efves \u00bb restent d\u00e9sormais \u00ab na\u00efves \u00bb et le fuseau horaire local n\u2019est jamais d\u00e9duit. Le cas de transition horaire entre \u00ab inaccessible \u00bb et \u00ab ambigu \u00bb est document\u00e9 comme se r\u00e9f\u00e9rant aux r\u00e8gles de repli de `tzinfo`.\n\n**Correction 2 \u2014 `scheduler\/service.py` :** suppression du compteur `_next_identifier` par instance ; les identifiants sont d\u00e9sormais attribu\u00e9s \u00e0 partir de l\u2019\u00e9tat du r\u00e9f\u00e9rentiel selon la formule `max(identifiants existants, par d\u00e9faut = 0) + 1` au moment de la cr\u00e9ation. Cela fonctionne correctement aussi bien pour les r\u00e9f\u00e9rentiels partag\u00e9s que pour ceux pr\u00e9remplis. Compromis : O(n) par cr\u00e9ation au lieu de O(1), ce qui est acceptable pour un magasin en m\u00e9moire bas\u00e9 sur un dictionnaire, et garantit l\u2019exactitude par rapport \u00e0 un compteur qui ne peut pas voir le magasin dans lequel il \u00e9crit.\n\n**Tests \u2014 `tests\/test_time_rules.py` (nouveau, 5 tests) :** pr\u00e9servation de l\u2019heure r\u00e9elle lors du passage \u00e0 l\u2019heure d\u2019\u00e9t\u00e9 et au retour \u00e0 l\u2019heure d\u2019hiver, temps \u00e9coul\u00e9 absolu de 23 h\/25 h lors de ces transitions, recalcul du d\u00e9calage UTC, \u00ab naive-stays-naive \u00bb et avancement d\u2019un jour en UTC simple. Saute proprement si aucune base de donn\u00e9es IANA n\u2019est pr\u00e9sente.\n\n**Tests \u2014 `tests\/test_scheduler.py` (\u00e9tendu, +2 tests) :** deux services partageant un m\u00eame r\u00e9f\u00e9rentiel doivent \u00e9mettre des identifiants distincts et conserver les deux t\u00e2ches ; un service utilisant un r\u00e9f\u00e9rentiel pr\u00e9rempli avec les identifiants 1 et 7 doit \u00e9mettre l\u2019identifiant 8 et laisser les t\u00e2ches existantes intactes.\n\n**V\u00e9rification de vacuit\u00e9 :** j\u2019ai restaur\u00e9 les deux impl\u00e9mentations d\u2019origine dans une copie temporaire et relanc\u00e9 la suite de tests \u2014 les 5 nouveaux tests ont tous \u00e9chou\u00e9 (`FAILED (failures=5)`), et tous ont r\u00e9ussi avec le code corrig\u00e9. Les tests identifient bien les d\u00e9fauts.\n\nUne correction a \u00e9t\u00e9 apport\u00e9e pendant l\u2019ex\u00e9cution : dans ma premi\u00e8re \u00e9bauche, j\u2019avais v\u00e9rifi\u00e9 le temps \u00e9coul\u00e9 en heure d\u2019\u00e9t\u00e9 (DST) en utilisant `result - previous`, ce que Python \u00e9value comme une op\u00e9ration arithm\u00e9tique en temps r\u00e9el lorsque les deux op\u00e9randes partagent un tzinfo ; cela donnait donc `24h` et les tests \u00e9chouaient. Les assertions convertissent d\u00e9sormais les valeurs en UTC avant la soustraction. L\u2019\u00e9chec provenait de mon test, et non de la correction.\n\n### Notes \u00e0 l\u2019attention du responsable\n\nLe fichier `fixture-manifest.json` n\u2019a pas \u00e9t\u00e9 modifi\u00e9 ; `tests\/test_time_rules.py` est donc un nouveau fichier valide qui ne figure pas dans `expected_files` \u2014 mettez \u00e0 jour le manifeste si une v\u00e9rification impose un ensemble de fichiers pr\u00e9cis. Par ailleurs, les probl\u00e8mes D4 et D5 ont \u00e9t\u00e9 signal\u00e9s mais n\u2019ont d\u00e9lib\u00e9r\u00e9ment pas \u00e9t\u00e9 corrig\u00e9s : ils d\u00e9pendent tous deux d\u2019une d\u00e9cision relative au contrat d\u2019API (s\u00e9mantique \u00ab miss-on-delete \u00bb, r\u00e8gles de validation du propri\u00e9taire) qui n\u2019est sp\u00e9cifi\u00e9e nulle part dans le fixture ; choisir l\u2019une des deux options aurait donc relev\u00e9 de la conjecture plut\u00f4t que d\u2019une v\u00e9ritable correction.\n<\/pre><\/div><\/details><\/div><p class=\"d-limit\">Limitation li\u00e9e \u00e0 l'environnement de test : il s'agissait d'un petit r\u00e9f\u00e9rentiel Python hors ligne. Claude utilisait un sous-agent de secours apr\u00e8s l'expiration de l'OAuth via l'interface en ligne de commande (CLI) ; par cons\u00e9quent, l'isolation et la visibilit\u00e9 des jetons n'\u00e9taient pas identiques.<\/p><\/article>\n\n\n\n<p class=\"wp-block-paragraph\">Aucun de ces deux scores ne dispense d'un contr\u00f4le humain. Une fois la r\u00e9paration effectu\u00e9e par l'un ou l'autre des agents, v\u00e9rifiez les interfaces modifi\u00e9es, la port\u00e9e inattendue des fichiers, l'absence de tests n\u00e9gatifs, l'historique des autorisations ou des commandes, ainsi que la proc\u00e9dure de restauration. Une explication convaincante ne remplace pas un test reproductible.<\/p>\n\n\n\n<h2 id=\"safety\" class=\"wp-block-heading\">Autorisations, environnement isol\u00e9 et s\u00e9curit\u00e9 op\u00e9rationnelle<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Un agent de codage peut lire du code priv\u00e9, ex\u00e9cuter des commandes shell, modifier de nombreux fichiers et appeler des outils externes. La conception des autorisations fait donc partie int\u00e9grante de la qualit\u00e9 du produit. Les questions pertinentes sont les suivantes : quelles op\u00e9rations n\u00e9cessitent une autorisation, \u00e0 quoi l\u2019agent a-t-il acc\u00e8s par d\u00e9faut, dans quelle mesure les actions \u00e0 risque sont-elles clairement signal\u00e9es, et un d\u00e9veloppeur peut-il v\u00e9rifier les modifications qui en r\u00e9sultent ?.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ne consid\u00e9rez pas syst\u00e9matiquement qu\u2019un nombre r\u00e9duit de demandes d\u2019approbation est pr\u00e9f\u00e9rable. Une proc\u00e9dure simplifi\u00e9e est utile dans un environnement isol\u00e9, sans identifiants ni connexions de production. Ce m\u00eame comportement peut s\u2019av\u00e9rer dangereux dans un r\u00e9f\u00e9rentiel reli\u00e9 \u00e0 des scripts de d\u00e9ploiement, \u00e0 de v\u00e9ritables donn\u00e9es clients ou \u00e0 des autorisations cloud \u00e9tendues. \u00c0 l\u2019inverse, un nombre excessif de demandes d\u2019approbation peut rendre l\u2019automatisation s\u00e9curis\u00e9e peu pratique et inciter les utilisateurs \u00e0 approuver des demandes sans les lire.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Notre test a \u00e9t\u00e9 r\u00e9alis\u00e9 \u00e0 partir de copies locales r\u00e9centes, sans faire appel \u00e0 des syst\u00e8mes de production, sans d\u00e9ploiement et sans intervention humaine pendant l'ex\u00e9cution. Il \u00e9value donc la r\u00e9alisation des t\u00e2ches dans des conditions s\u00fbres, et non la s\u00e9curit\u00e9 relative des deux produits. Avant d\u2019utiliser l\u2019un ou l\u2019autre de ces outils pour des t\u00e2ches importantes, commencez par un acc\u00e8s en lecture seule, d\u00e9finissez les r\u00e9pertoires et les commandes autoris\u00e9s, examinez les diff\u00e9rences et effectuez des v\u00e9rifications objectives dans un environnement r\u00e9cup\u00e9rable.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Commencez par une architecture en lecture seule ou optez pour la solution de secours.<\/li>\n\n\n\n<li>N'approuvez que les commandes dont vous comprenez la port\u00e9e et les cons\u00e9quences.<\/li>\n\n\n\n<li>Veillez \u00e0 ce que les identifiants, les donn\u00e9es de production et les droits d'acc\u00e8s au d\u00e9ploiement ne soient pas inclus dans la version d'essai.<\/li>\n\n\n\n<li>Exigez un fichier de comparaison, des tests et une proc\u00e9dure de restauration claire avant d'accepter le r\u00e9sultat.<\/li>\n<\/ul>\n\n\n\n<h2 id=\"customization\" class=\"wp-block-heading\">MCP, comp\u00e9tences, instructions relatives aux projets et personnalisation<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Ces deux \u00e9cosyst\u00e8mes peuvent \u00eatre \u00e9tendus, mais les termes \u00ab extension \u00bb et \u00ab extension \u00bb ne doivent pas \u00eatre consid\u00e9r\u00e9s comme synonymes. Les instructions de projet indiquent \u00e0 un agent comment se comporter au sein d\u2019un r\u00e9f\u00e9rentiel. Les comp\u00e9tences r\u00e9utilisables regroupent un workflow reproductible ou une expertise. MCP relie un h\u00f4te \u00e0 des outils ou des donn\u00e9es externes. Les hooks et les commandes permettent d\u2019automatiser des \u00e9tapes sp\u00e9cifiques d\u2019un cycle de d\u00e9veloppement. Un produit peut exceller dans une couche sans pour autant correspondre point par point \u00e0 une fonctionnalit\u00e9 d\u2019une autre couche.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">La question d\u00e9terminante pour l'achat n'est pas de savoir s'il existe un logo d'int\u00e9gration. Il s'agit plut\u00f4t de savoir si la connexion peut \u00eatre install\u00e9e, authentifi\u00e9e, valid\u00e9e et exploit\u00e9e sur l'h\u00f4te que vous utilisez r\u00e9ellement. Il faut \u00e9galement que le mode de d\u00e9faillance soit compr\u00e9hensible. Un serveur MCP qui fonctionne en mode interactif mais qui attend une validation lors d\u2019une session sans surveillance reste utile, mais il ne devrait pas \u00eatre qualifi\u00e9 d\u2019automatisation \u00ab sans friction \u00bb.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Les instructions r\u00e9utilisables pr\u00e9sentent une mise en garde similaire. La longueur des fichiers d'instructions ne garantit pas le respect des r\u00e8gles, et un ensemble de r\u00e8gles trop complexe peut occulter le contexte ou cr\u00e9er des contradictions. Veillez \u00e0 ce que les consignes du r\u00e9f\u00e9rentiel soient concises, v\u00e9rifiables et \u00e9troitement li\u00e9es au code. Pr\u00e9cisez les commandes de v\u00e9rification obligatoires, les zones prot\u00e9g\u00e9es, les r\u00e8gles de style, ainsi que les cas dans lesquels l'agent doit s'arr\u00eater pour demander confirmation.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Instructions relatives au projet :<\/strong> r\u00e8gles sp\u00e9cifiques au r\u00e9f\u00e9rentiel et commandes de v\u00e9rification.<\/li>\n\n\n\n<li><strong>Comp\u00e9tences :<\/strong> proc\u00e9dures r\u00e9utilisables ou modules d'expertise.<\/li>\n\n\n\n<li><strong>MCP :<\/strong> connexions \u00e0 des outils et des donn\u00e9es externes.<\/li>\n\n\n\n<li><strong>Hooks et commandes :<\/strong> automatisation autour d'\u00e9v\u00e9nements d\u00e9finis du flux de travail.<\/li>\n<\/ul>\n\n\n\n<h2 id=\"pricing\" class=\"wp-block-heading\">Codex vs Claude : tarifs et limites d'utilisation<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">L'offre \u00ab Clean Consumer \u00bb est propos\u00e9e \u00e0 partir de $20 par mois. L'acc\u00e8s \u00e0 Codex est inclus dans le forfait $20 ChatGPT correspondant, tandis que l'offre Claude Pro co\u00fbte $20 par mois aux \u00c9tats-Unis et inclut Claude Code. Les deux formules proposent des niveaux de forfait grand public pour une utilisation plus intensive, \u00e0 $100 et $200. Des prix affich\u00e9s similaires ne signifient pas pour autant des capacit\u00e9s identiques.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Le forfait \u201c Max 5x \u201d Claude co\u00fbte $100 par mois et le forfait \u201c Max 20x \u201d co\u00fbte $200 par mois. Les appellations \u00ab 5x \u00bb et \u00ab 20x \u00bb d\u00e9crivent l\u2019utilisation par session par rapport \u00e0 la version Pro, et non un nombre garanti de t\u00e2ches de codage. Les forfaits Claude et Claude Code partagent les m\u00eames limites de session et hebdomadaires. La longueur du contexte, les fichiers joints, le choix du mod\u00e8le et l\u2019utilisation des fonctionnalit\u00e9s peuvent influencer la vitesse \u00e0 laquelle le quota est consomm\u00e9.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1280\" height=\"800\" src=\"https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/claude-max-plan.webp\" alt=\"Page du forfait Claude Max pr\u00e9sentant les capacit\u00e9s d&#039;utilisation de Max 5x et Max 20x\" class=\"wp-image-17388\" srcset=\"https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/claude-max-plan.webp 1280w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/claude-max-plan-300x188.webp 300w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/claude-max-plan-1024x640.webp 1024w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/claude-max-plan-768x480.webp 768w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/claude-max-plan-18x12.webp 18w\" sizes=\"(max-width: 1280px) 100vw, 1280px\" \/><figcaption class=\"wp-element-caption\">La page officielle du forfait Max de Claude pr\u00e9sente les options de capacit\u00e9 d'utilisation 5x et 20x. Les tarifs mensuels sont indiqu\u00e9s dans ce m\u00eame article officiel ; les d\u00e9tails du forfait ont \u00e9t\u00e9 v\u00e9rifi\u00e9s en juillet 2026.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Les cr\u00e9dits d'utilisation optionnels de Claude permettent, lorsqu'ils sont activ\u00e9s, de poursuivre les op\u00e9rations \u00e9ligibles au-del\u00e0 du volume d'utilisation inclus ; ces cr\u00e9dits sont factur\u00e9s s\u00e9par\u00e9ment aux tarifs standard de l'API. L'authentification par cl\u00e9 API constitue un autre mode de facturation distinct. Qualifier l'un ou l'autre de ces modes d\u201c\u201d illimit\u00e9 \u00bb masquerait le co\u00fbt marginal r\u00e9el.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1280\" height=\"800\" src=\"https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/claude-code-plan-limits.webp\" alt=\"Documentation relative au forfait Claude expliquant le fonctionnement des sessions partag\u00e9es et les limites d&#039;utilisation hebdomadaires\" class=\"wp-image-17389\" srcset=\"https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/claude-code-plan-limits.webp 1280w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/claude-code-plan-limits-300x188.webp 300w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/claude-code-plan-limits-1024x640.webp 1024w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/claude-code-plan-limits-768x480.webp 768w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/claude-code-plan-limits-18x12.webp 18w\" sizes=\"(max-width: 1280px) 100vw, 1280px\" \/><figcaption class=\"wp-element-caption\">Le code Claude utilise le quota de l'abonnement Pro ou Max associ\u00e9, y compris les limites de sessions partag\u00e9es et les limites hebdomadaires. La capacit\u00e9 exacte varie en fonction de la charge de travail.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Codex distingue \u00e9galement l'utilisation incluse dans le forfait grand public, les cr\u00e9dits achet\u00e9s \u00e9ligibles et la facturation API. Les messages locaux et les discussions sur le cloud partagent un cr\u00e9neau de cinq heures, et des limites hebdomadaires peuvent \u00e9galement s'appliquer. Un champ \u00ab token \u00bb dans un journal CLI ne peut pas \u00eatre converti directement en pourcentage sur cinq heures, en montant de cr\u00e9dit d'abonnement ou en facture API.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Pour une utilisation occasionnelle en solo, le niveau $20, quel que soit le c\u00f4t\u00e9, constitue un point de d\u00e9part raisonnable. Un travail quotidien sur des r\u00e9f\u00e9rentiels impliquant des contextes longs peut justifier un niveau d\u2019utilisation sup\u00e9rieur, mais uniquement apr\u00e8s avoir observ\u00e9 les r\u00e9initialisations r\u00e9elles et la consommation des t\u00e2ches. Les travaux parall\u00e8les intensifs n\u00e9cessitent encore plus de prudence : opter pour un niveau sup\u00e9rieur ne dispense pas de contr\u00f4ler le contexte, de fractionner les t\u00e2ches et de r\u00e9server les ressources de raisonnement co\u00fbteuses aux t\u00e2ches n\u00e9cessitant un haut niveau de jugement.<\/p>\n\n\n\n<h2 id=\"controlled-test\" class=\"wp-block-heading\">R\u00e9sultats de notre test comparatif entre le Codex et le Code Claude<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Nous avons fig\u00e9 quatre consignes en anglais, un ensemble de tests Python publics, des contr\u00f4les objectifs, une grille d\u2019\u00e9valuation et une r\u00e8gle du \u00ab premier r\u00e9sultat valide \u00bb avant que l\u2019un ou l\u2019autre des agents ne soit lanc\u00e9. Les t\u00e2ches portaient sur la compr\u00e9hension d\u2019un d\u00e9p\u00f4t inconnu, une fonctionnalit\u00e9 multi-fichiers, la correction d\u2019un bug li\u00e9 \u00e0 l\u2019heure d\u2019\u00e9t\u00e9 et la r\u00e9vision de code avec corrections. Les r\u00e9sultats valides n\u2019ont fait l\u2019objet d\u2019aucune intervention humaine, et les r\u00e9sultats faibles mais valides ne pouvaient pas \u00eatre r\u00e9ex\u00e9cut\u00e9s pour obtenir un meilleur score.<\/p>\n\n\n\n<style>.comparison-setup-card{--ink:#111318;--body:#414753;--muted:#707784;--line:#e4e7ec;--soft:#f6f7f9;--blue:#315efb;--violet:#7257e8;--green:#087a55;--greenSoft:#eaf8f2;--red:#a23131;--redSoft:#fff0f0;color:var(--ink);font-family:Inter,ui-sans-serif,-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif;line-height:1.5;border:1px solid var(--line);border-radius:8px;background:#fff;overflow:hidden;box-shadow:0 16px 42px rgba(24,32,56,.08)}.comparison-setup-card *{box-sizing:border-box}.comparison-setup-card .s-head{padding:24px 26px 20px;border-bottom:1px solid var(--line)}.comparison-setup-card .s-kicker{margin:0 0 6px;color:var(--muted);font:750 11px\/1.4 ui-monospace,SFMono-Regular,Menlo,monospace;letter-spacing:.08em;text-transform:uppercase}.comparison-setup-card h3{margin:0;font-size:22px;line-height:1.2;letter-spacing:-.025em}.comparison-setup-card .s-sub{margin:7px 0 0;color:var(--body);font-size:13px}.comparison-setup-card .s-body{padding:24px 26px}.comparison-setup-card .s-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:10px}.comparison-setup-card .s-stat{padding:15px;border:1px solid var(--line);border-radius:6px;background:var(--soft)}.comparison-setup-card .s-stat span{display:block;color:var(--muted);font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:.06em}.comparison-setup-card .s-stat strong{display:block;margin-top:5px;font-size:20px}.comparison-setup-card table{width:100%;border-collapse:collapse;font-size:12px}.comparison-setup-card th,.comparison-setup-card td{padding:11px 12px;border:1px solid var(--line);text-align:left;vertical-align:top}.comparison-setup-card th{background:var(--soft)}.comparison-setup-card .s-note{margin:16px 0 0;padding:12px 14px;border-left:3px solid var(--blue);background:#f3f5ff;color:#38466c;font-size:12px}.comparison-setup-card details{margin-top:12px;border:1px solid var(--line);border-radius:6px}.comparison-setup-card summary{cursor:pointer;padding:12px 14px;font-size:12px;font-weight:800}.comparison-setup-card pre{max-height:560px;overflow:auto;margin:0;padding:14px;white-space:pre-wrap;background:#f5f6f8;color:#222936;font:11px\/1.6 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}@media(max-width:680px){.comparison-setup-card .s-grid{grid-template-columns:1fr}.comparison-setup-card .s-head,.comparison-setup-card .s-body{padding:20px}}<\/style><aside class=\"comparison-setup-card\"><header class=\"s-head\"><p class=\"s-kicker\">D\u00e9roulement du test<\/p><h3>M\u00eames t\u00e2ches, r\u00e8gles fig\u00e9es, premiers r\u00e9sultats valides<\/h3><\/header><div class=\"s-body\"><div class=\"s-grid\"><div class=\"s-stat\"><span>Codex<\/span><strong>gpt-5.6-sol<\/strong><small>Moyen T1\u2013T3 \u00b7 \u00c9lev\u00e9 T4<\/small><\/div><div class=\"s-stat\"><span>Claude Code<\/span><strong>claude-opus-5<\/strong><small>Divulgation de la solution de repli du sous-agent<\/small><\/div><\/div><table><tbody><tr><th>Calendrier des rencontres<\/th><td>Petit d\u00e9p\u00f4t Python public, contenant uniquement des biblioth\u00e8ques standard<\/td><\/tr><tr><th>R\u00e8gle d'ex\u00e9cution<\/th><td>Le premier r\u00e9sultat valide est conserv\u00e9 ; les nouvelles ex\u00e9cutions de contr\u00f4le de qualit\u00e9 sont interdites<\/td><\/tr><tr><th>S\u00e9curit\u00e9<\/th><td>Copies r\u00e9centes, t\u00e2ches hors ligne, pas d'acc\u00e8s \u00e0 l'environnement de production, pas de push ni de d\u00e9ploiement<\/td><\/tr><tr><th>Marquage<\/th><td>Grille d'\u00e9valuation \u00ab Frozen \u00bb \u00e0 100 points, avec contr\u00f4les ind\u00e9pendants publics et cach\u00e9s<\/td><\/tr><\/tbody><\/table><\/div><\/aside>\n\n\n\n<p class=\"wp-block-paragraph\">Codex a ex\u00e9cut\u00e9 des processus CLI isol\u00e9s avec du JSONL brut, en conservant les champs de jetons \u00e9mis par l\u2019interface CLI. La session OAuth CLI Claude de notre coll\u00e8gue ayant expir\u00e9, Claude Code a utilis\u00e9 un coordinateur avec des contextes de sous-agents r\u00e9cents. Nous avons reconstitu\u00e9 les correctifs de Claude dans des copies d\u2019audit vierges et avons r\u00e9ex\u00e9cut\u00e9 les v\u00e9rifications publiques et cach\u00e9es. Cela a permis d\u2019obtenir des preuves pratiques cr\u00e9dibles, mais sans obtenir d\u2019isolation ni de surfaces de contr\u00f4le de mod\u00e8le identiques.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>T\u00e2che<\/th><th>Codex<\/th><th>Claude Code<\/th><th>Interpr\u00e9tation born\u00e9e<\/th><\/tr><\/thead><tbody><tr><td>T1 : Compr\u00e9hension du r\u00e9f\u00e9rentiel<\/td><td>20\/20<\/td><td>20\/20<\/td><td>\u00c9galit\u00e9 : approche compacte contre approche exhaustive<\/td><\/tr><tr><td>T2 : fonctionnalit\u00e9 de gestion de plusieurs fichiers<\/td><td>30\/30<\/td><td>30\/30<\/td><td>Lien fonctionnel ; port\u00e9e diff\u00e9rente de la validation et des tests<\/td><\/tr><tr><td>T3 : R\u00e9paration du DST<\/td><td>30\/30<\/td><td>30\/30<\/td><td>Les deux ont \u00e9t\u00e9 approuv\u00e9s : un patch plus \u00e9troit par rapport \u00e0 une couverture plus large des bords<\/td><\/tr><tr><td>T4 : contr\u00f4le et r\u00e9paration<\/td><td>18\/20<\/td><td>19\/20<\/td><td>Le code Claude a montr\u00e9 une plus grande \u00e9tendue de l'examen<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<style>.aggregate-verdict-card{--ink:#111318;--body:#414753;--muted:#707784;--line:#e4e7ec;--soft:#f6f7f9;--blue:#315efb;--violet:#7257e8;--green:#087a55;--greenSoft:#eaf8f2;--red:#a23131;--redSoft:#fff0f0;color:var(--ink);font-family:Inter,ui-sans-serif,-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif;line-height:1.5;border:1px solid var(--line);border-radius:8px;background:#fff;overflow:hidden;box-shadow:0 16px 42px rgba(24,32,56,.08)}.aggregate-verdict-card *{box-sizing:border-box}.aggregate-verdict-card .s-head{padding:24px 26px 20px;border-bottom:1px solid var(--line)}.aggregate-verdict-card .s-kicker{margin:0 0 6px;color:var(--muted);font:750 11px\/1.4 ui-monospace,SFMono-Regular,Menlo,monospace;letter-spacing:.08em;text-transform:uppercase}.aggregate-verdict-card h3{margin:0;font-size:22px;line-height:1.2;letter-spacing:-.025em}.aggregate-verdict-card .s-sub{margin:7px 0 0;color:var(--body);font-size:13px}.aggregate-verdict-card .s-body{padding:24px 26px}.aggregate-verdict-card .s-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:10px}.aggregate-verdict-card .s-stat{padding:15px;border:1px solid var(--line);border-radius:6px;background:var(--soft)}.aggregate-verdict-card .s-stat span{display:block;color:var(--muted);font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:.06em}.aggregate-verdict-card .s-stat strong{display:block;margin-top:5px;font-size:20px}.aggregate-verdict-card table{width:100%;border-collapse:collapse;font-size:12px}.aggregate-verdict-card th,.aggregate-verdict-card td{padding:11px 12px;border:1px solid var(--line);text-align:left;vertical-align:top}.aggregate-verdict-card th{background:var(--soft)}.aggregate-verdict-card .s-note{margin:16px 0 0;padding:12px 14px;border-left:3px solid var(--blue);background:#f3f5ff;color:#38466c;font-size:12px}.aggregate-verdict-card details{margin-top:12px;border:1px solid var(--line);border-radius:6px}.aggregate-verdict-card summary{cursor:pointer;padding:12px 14px;font-size:12px;font-weight:800}.aggregate-verdict-card pre{max-height:560px;overflow:auto;margin:0;padding:14px;white-space:pre-wrap;background:#f5f6f8;color:#222936;font:11px\/1.6 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}@media(max-width:680px){.aggregate-verdict-card .s-grid{grid-template-columns:1fr}.aggregate-verdict-card .s-head,.aggregate-verdict-card .s-body{padding:20px}}<\/style><article class=\"aggregate-verdict-card\"><header class=\"s-head\"><p class=\"s-kicker\">\u00c9preuve surveill\u00e9e \u00b7 Grille d'\u00e9valuation \u00ab Frozen \u00bb<\/p><h3>Codex 98\/100 contre Claude Code 99\/100<\/h3><p class=\"s-sub\">Cet \u00e9cart d'un point ne constitue pas un signal de r\u00e9ussite universel. Les diff\u00e9rences pertinentes d\u00e9pendent de la t\u00e2che \u00e0 accomplir.<\/p><\/header><div class=\"s-body\"><div class=\"s-grid\"><div class=\"s-stat\"><span>Codex<\/span><strong>98\/100<\/strong><\/div><div class=\"s-stat\"><span>Claude Code<\/span><strong>99\/100<\/strong><\/div><\/div><table><thead><tr><th>Domaine de d\u00e9cision<\/th><th>R\u00e9sultat observ\u00e9<\/th><th>Lecture pratique<\/th><\/tr><\/thead><tbody><tr><td>Compr\u00e9hension du r\u00e9f\u00e9rentiel<\/td><td>\u00c9galit\u00e9 \u00b7 20\/20 chacun<\/td><td>Claude \u00e9tait plus complet ; Codex \u00e9tait plus concis.<\/td><\/tr><tr><td>Fonctionnalit\u00e9 de gestion de plusieurs fichiers<\/td><td>\u00c9galit\u00e9 \u00b7 30\/30 chacun<\/td><td>Les deux ont pass\u00e9 avec succ\u00e8s des contr\u00f4les discrets ; Claude a ajout\u00e9 des tests plus approfondis.<\/td><\/tr><tr><td>Correction d'un bug li\u00e9 \u00e0 l'heure d'\u00e9t\u00e9<\/td><td>\u00c9galit\u00e9 \u00b7 30\/30 chacun<\/td><td>La version Claude couvrait davantage de bords ; Codex a utilis\u00e9 le patch plus \u00e9troit.<\/td><\/tr><tr><td>V\u00e9rification et r\u00e9paration<\/td><td>Claude 19\/20 ; Codex 18\/20<\/td><td>La m\u00e9thode Claude a permis de mettre en \u00e9vidence davantage de d\u00e9fauts reproductibles.<\/td><\/tr><tr><td>Vitesse observ\u00e9e<\/td><td>Mixte<\/td><td>Claude a men\u00e9 les T1\/T2 ; Codex a men\u00e9 les T3\/T4.<\/td><\/tr><\/tbody><\/table><p class=\"s-note\"><strong>Mention l\u00e9gale :<\/strong> m\u00eames invites et m\u00eame configuration, mais des chemins d'isolation diff\u00e9rents. Ne g\u00e9n\u00e9ralisez pas ce petit test \u00e0 tous les r\u00e9f\u00e9rentiels, niveaux de mod\u00e8le ou sessions autonomes.<\/p><\/div><\/article>\n\n\n\n<p class=\"wp-block-paragraph\">Ce test est trop limit\u00e9 pour permettre d'\u00e9valuer les performances sur de grands r\u00e9f\u00e9rentiels, tous les langages, tous les niveaux de mod\u00e8les ou lors de longues sessions autonomes. L'\u00e9cart total d'un point doit \u00eatre interpr\u00e9t\u00e9 comme signifiant que \u201c les deux ont r\u00e9ussi, avec une diff\u00e9rence quant \u00e0 l'\u00e9tendue de l'analyse \u201d, et non comme un classement universel.<\/p>\n\n\n\n<h2 id=\"user-experience\" class=\"wp-block-heading\">Ce que rapportent les utilisateurs r\u00e9els \u2014 et dans quelle mesure on peut s'y fier<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Les retours de la communaut\u00e9 sont utiles lorsqu\u2019ils portent sur un projet, une t\u00e2che, un mod\u00e8le, un contexte d\u2019utilisation et un horizon temporel. Ils sont en revanche peu pertinents lorsqu\u2019un message se contente d\u2019indiquer qu\u2019un produit \u201c semble plus intelligent \u201d ou \u201c est beaucoup plus rapide \u201d. Les utilisateurs comparent en effet des r\u00e9f\u00e9rentiels, des niveaux d\u2019abonnement, des invites, des extensions et des niveaux de supervision diff\u00e9rents.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">L'exemple contextuel tir\u00e9 de Reddit ci-dessus sugg\u00e8re un compromis en mati\u00e8re d'interaction : une approche rapide et conversationnelle peut exiger davantage d'attention, tandis qu'une ex\u00e9cution r\u00e9fl\u00e9chie peut sembler plus lente mais n\u00e9cessiter moins de corrections. Notre test contr\u00f4l\u00e9 ne recoupe que partiellement ce t\u00e9moignage. Il a r\u00e9v\u00e9l\u00e9 des vitesses variables et l\u2019absence d\u2019intervention humaine lors des ex\u00e9cutions valides ; il ne permet donc pas de valider l\u2019affirmation selon laquelle une \u00ab surveillance \u00bb serait n\u00e9cessaire. C\u2019est pr\u00e9cis\u00e9ment pour cette raison que les t\u00e9moignages de la communaut\u00e9 et les r\u00e9sultats des tests contr\u00f4l\u00e9s doivent \u00eatre pr\u00e9sent\u00e9s conjointement, sans \u00eatre confondus.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Le commentaire sur le \u00ab X harness \u00bb soul\u00e8ve un deuxi\u00e8me point int\u00e9ressant : le r\u00e9sultat d'un codage appartient \u00e0 l'ensemble du syst\u00e8me, et pas seulement \u00e0 l'\u00e9tiquette du mod\u00e8le. Aucun de ces deux messages ne doit \u00eatre consid\u00e9r\u00e9 comme une donn\u00e9e d'enqu\u00eate. Utilisez-les pour identifier les questions \u00e0 se poser pour votre propre essai : nombre d'interventions, ampleur des diff\u00e9rences, qualit\u00e9 des tests et capacit\u00e9 \u00e0 se remettre d'une hypoth\u00e8se erron\u00e9e.<\/p>\n\n\n\n<h2 id=\"globalgpt\" class=\"wp-block-heading\">Extension des codes Codex et Claude avec le code GlobalGPT<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">GlobalGPT est un <a href=\"https:\/\/www.glbgpt.com\/hub\/best-all-in-one-ai-tools-and-platforms-11-options-compared\/\">espace de travail multimod\u00e8le et multimodal<\/a>, il ne remplace pas les agents de r\u00e9f\u00e9rentiel natifs. Son r\u00f4le concret est de compl\u00e9ter un h\u00f4te existant : utiliser un autre mod\u00e8le d\u2019agent disponible pour obtenir un deuxi\u00e8me avis, proc\u00e9der \u00e0 une r\u00e9vision des plans, valider la documentation ou g\u00e9n\u00e9rer des r\u00e9sultats sp\u00e9cialis\u00e9s, tandis que Codex ou Claude Code reste responsable de l\u2019acc\u00e8s au r\u00e9f\u00e9rentiel, des commandes shell, des tests et des validations.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">GlobalGPT publie des guides officiels sur l'interface de ligne de commande (CLI) pour <a href=\"https:\/\/www.glbgpt.com\/hub\/how-to-use-globalgpt-cli-in-codex\/\">Codex<\/a> et <a href=\"https:\/\/www.glbgpt.com\/hub\/how-to-use-globalgpt-cli-in-claude-code\/\">Claude Code<\/a>, ainsi que Cursor. Lors de notre test d'int\u00e9gration T5 en mode s\u00e9curis\u00e9, l'interface CLI a men\u00e9 \u00e0 bien la m\u00eame t\u00e2che \u00ab gel\u00e9e \u00bb dans les deux environnements compar\u00e9s. Dans Codex, nous avons \u00e9galement v\u00e9rifi\u00e9 un appel en lecture seule de la liste des mod\u00e8les MCP, puis install\u00e9, charg\u00e9 et utilis\u00e9 la comp\u00e9tence GlobalGPT.<\/p>\n\n\n\n<style>.globalgpt-integration-card{--ink:#111318;--body:#414753;--muted:#707784;--line:#e4e7ec;--soft:#f6f7f9;--blue:#315efb;--violet:#7257e8;--green:#087a55;--greenSoft:#eaf8f2;--red:#a23131;--redSoft:#fff0f0;color:var(--ink);font-family:Inter,ui-sans-serif,-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif;line-height:1.5;border:1px solid var(--line);border-radius:8px;background:#fff;overflow:hidden;box-shadow:0 16px 42px rgba(24,32,56,.08)}.globalgpt-integration-card *{box-sizing:border-box}.globalgpt-integration-card .s-head{padding:24px 26px 20px;border-bottom:1px solid var(--line)}.globalgpt-integration-card .s-kicker{margin:0 0 6px;color:var(--muted);font:750 11px\/1.4 ui-monospace,SFMono-Regular,Menlo,monospace;letter-spacing:.08em;text-transform:uppercase}.globalgpt-integration-card h3{margin:0;font-size:22px;line-height:1.2;letter-spacing:-.025em}.globalgpt-integration-card .s-sub{margin:7px 0 0;color:var(--body);font-size:13px}.globalgpt-integration-card .s-body{padding:24px 26px}.globalgpt-integration-card .s-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:10px}.globalgpt-integration-card .s-stat{padding:15px;border:1px solid var(--line);border-radius:6px;background:var(--soft)}.globalgpt-integration-card .s-stat span{display:block;color:var(--muted);font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:.06em}.globalgpt-integration-card .s-stat strong{display:block;margin-top:5px;font-size:20px}.globalgpt-integration-card table{width:100%;border-collapse:collapse;font-size:12px}.globalgpt-integration-card th,.globalgpt-integration-card td{padding:11px 12px;border:1px solid var(--line);text-align:left;vertical-align:top}.globalgpt-integration-card th{background:var(--soft)}.globalgpt-integration-card .s-note{margin:16px 0 0;padding:12px 14px;border-left:3px solid var(--blue);background:#f3f5ff;color:#38466c;font-size:12px}.globalgpt-integration-card details{margin-top:12px;border:1px solid var(--line);border-radius:6px}.globalgpt-integration-card summary{cursor:pointer;padding:12px 14px;font-size:12px;font-weight:800}.globalgpt-integration-card pre{max-height:560px;overflow:auto;margin:0;padding:14px;white-space:pre-wrap;background:#f5f6f8;color:#222936;font:11px\/1.6 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}@media(max-width:680px){.globalgpt-integration-card .s-grid{grid-template-columns:1fr}.globalgpt-integration-card .s-head,.globalgpt-integration-card .s-body{padding:20px}}<\/style><article class=\"globalgpt-integration-card\"><header class=\"s-head\"><p class=\"s-kicker\">Int\u00e9gration GlobalGPT \u00b7 Non prise en compte dans le score de codage<\/p><h3>CLI v\u00e9rifi\u00e9 dans les deux flux de travail ; MCP et Skill v\u00e9rifi\u00e9s dans Codex<\/h3><p class=\"s-sub\">Cet indicateur mesure les parcours d'int\u00e9gration, et non pas si GlobalGPT remplace l'un ou l'autre des agents de codage natifs.<\/p><\/header><div class=\"s-body\"><table><thead><tr><th>Chemin d'acc\u00e8s<\/th><th>Environnement Codex<\/th><th>Course organis\u00e9e par les coll\u00e8gues de Claude<\/th><\/tr><\/thead><tbody><tr><td>GlobalGPT CLI<\/td><td>V\u00e9rifi\u00e9 avec gpt-5.6-sol et gpt-5.6-luna<\/td><td>V\u00e9rifi\u00e9 avec les m\u00eames t\u00e2ches gel\u00e9es<\/td><\/tr><tr><td>MCP<\/td><td>Liste interactive des mod\u00e8les en lecture seule v\u00e9rifi\u00e9e<\/td><td>Non connect\u00e9 pendant la course<\/td><\/tr><tr><td>Comp\u00e9tence<\/td><td>Install\u00e9, charg\u00e9 et test\u00e9<\/td><td>Install\u00e9 mais non utilis\u00e9 pour les appels en attente<\/td><\/tr><tr><td>MCP sans surveillance<\/td><td>Limite d'autorisation respect\u00e9e<\/td><td>Non test\u00e9<\/td><\/tr><\/tbody><\/table><details><summary>Consulter l'ensemble des preuves d'int\u00e9gration<\/summary><pre>R\u00e9sum\u00e9 des tests d'int\u00e9gration # GlobalGPT\n\nPort\u00e9e de # #\n\nLe test T5 \u00e9value l'int\u00e9gration de GlobalGPT et n'est pas pris en compte dans le score de codage natif de Codex. Yukie n'a pas \u00e9t\u00e9 utilis\u00e9.\n\n## Verrouillage et \u00e9tat de pr\u00e9paration des mod\u00e8les\n\n- Mod\u00e8le A : `gpt-5.6-sol`\n- Mod\u00e8le B : `gpt-5.6-luna`\n- Les deux mod\u00e8les figuraient dans la liste des mod\u00e8les actifs.\n- Les deux sondes de pr\u00e9paration all\u00e9g\u00e9es ont renvoy\u00e9 un texte valide et analysable.\n- Les mod\u00e8les ont \u00e9t\u00e9 verrouill\u00e9s avant les appels de sortie formels T5A et T5B.\n\n## R\u00e9sultats formels de l\u2019interface CLI\n\n| T\u00e2che | Mod\u00e8le | Statut | Dur\u00e9e | Tokens de la prompt | Tokens de la r\u00e9ponse | En-t\u00eates requis |\n|---|---|---|---:|---:|---:|---:|\n| T5A | gpt-5.6-sol | Valide | 27 s | 2 116 | 1 207 | 6\/6 |\n| T5B | gpt-5.6-luna | Valide | 14 s | 2 116 | 1 441 | 6\/6 |\n\nLes deux appels formels ont utilis\u00e9 la m\u00eame t\u00e2che fig\u00e9e de planification de produit en anglais via `glbgpt exec`, ont renvoy\u00e9 une sortie visible uniquement en anglais et n\u2019ont divulgu\u00e9 aucune information d\u2019identification. Aucune nouvelle ex\u00e9cution de contr\u00f4le qualit\u00e9 n\u2019a eu lieu.\n\n## R\u00e9sultat MCP\n\n- La commande `codex mcp list` a indiqu\u00e9 que `globalgpt` \u00e9tait activ\u00e9.\n- Une session Codex non interactive a d\u00e9tect\u00e9 et tent\u00e9 d\u2019ex\u00e9cuter `mcp__globalgpt__glbgpt_list_models`, mais l\u2019appel a \u00e9t\u00e9 annul\u00e9 car l\u2019approbation MCP sans surveillance n\u2019\u00e9tait pas disponible. Aucun param\u00e8tre de s\u00e9curit\u00e9 n\u2019a \u00e9t\u00e9 assoupli.\n- La session Codex interactive active a appel\u00e9 avec succ\u00e8s le m\u00eame outil MCP GlobalGPT en lecture seule et a re\u00e7u neuf mod\u00e8les de chat.\n- R\u00e9sultat : acc\u00e8s MCP interactif v\u00e9rifi\u00e9 ; l\u2019ex\u00e9cution MCP non interactive et sans surveillance reste soumise \u00e0 une restriction d\u2019approbation.\n\nR\u00e9sultat de la comp\u00e9tence ##\n\n- Les comp\u00e9tences GlobalGPT et GlobalGPT Coding sont install\u00e9es dans le r\u00e9pertoire des comp\u00e9tences Codex via des liens vers le package de comp\u00e9tences CLI fourni.\n- La comp\u00e9tence GlobalGPT a \u00e9t\u00e9 charg\u00e9e et suivie pour la v\u00e9rification de la session configur\u00e9e, la s\u00e9lection de mod\u00e8les en temps r\u00e9el, la pr\u00e9paration, les options de s\u00e9curit\u00e9 des cr\u00e9dits et la gestion des \u00e9checs.\n- R\u00e9sultat : install\u00e9e et test\u00e9e dans le flux de travail actif de Codex.\n\n## Conclusion limit\u00e9e\n\nCette ex\u00e9cution v\u00e9rifie le bon fonctionnement des appels CLI GlobalGPT, un appel MCP GlobalGPT interactif en lecture seule depuis Codex, ainsi qu\u2019un chemin de comp\u00e9tence GlobalGPT install\u00e9 et utilis\u00e9. Elle ne prouve pas que chaque mod\u00e8le, outil multim\u00e9dia, h\u00f4te, compte ou configuration MCP sans intervention fonctionne. Elle ne teste pas Yukie et ne corrobore pas l\u2019affirmation selon laquelle GlobalGPT remplace Codex ou Claude Code.\n<\/pre><\/details><p class=\"s-note\">Port\u00e9e v\u00e9rifi\u00e9e : appels CLI sp\u00e9cifiques, une lecture interactive de MCP et un parcours de comp\u00e9tence install\u00e9\/utilis\u00e9. Cela ne prouve pas la prise en charge de tous les mod\u00e8les, outils multim\u00e9dias, h\u00f4tes ou configurations sans intervention.<\/p><\/div><\/article>\n\n\n\n<p class=\"wp-block-paragraph\">La limite est importante. L'ex\u00e9cution Claude de notre coll\u00e8gue a permis de v\u00e9rifier le chemin d'acc\u00e8s CLI, et non le MCP c\u00f4t\u00e9 Claude. La comp\u00e9tence y \u00e9tait install\u00e9e, mais n'a pas \u00e9t\u00e9 utilis\u00e9e pour les appels mis en attente. Une tentative automatis\u00e9e via le MCP Codex n\u00e9cessitait tout de m\u00eame une validation manuelle. La disponibilit\u00e9 des mod\u00e8les et les cr\u00e9dits d\u00e9pendent \u00e9galement du forfait GlobalGPT en cours ; les d\u00e9veloppeurs doivent donc v\u00e9rifier la liste en ligne plut\u00f4t que de supposer que tous les mod\u00e8les sont inclus.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">GlobalGPT couvre \u00e9galement les images, les vid\u00e9os, les fichiers audio et les workflows guid\u00e9s par l'Agent. Les entr\u00e9es \u00ab Slides \u00bb, \u00ab Document \u00bb et \u00ab Image \u00bb de Yukie constituent une cat\u00e9gorie \u00e0 part : elles proposent des mod\u00e8les pr\u00eats \u00e0 l\u2019emploi et des instructions \u00e9tape par \u00e9tape dans le navigateur pour les t\u00e2ches ne n\u00e9cessitant pas de code. Cela peut s\u2019av\u00e9rer plus simple que d\u2019ouvrir une interface CLI de programmation pour cr\u00e9er une pr\u00e9sentation ou un document structur\u00e9, mais cela ne remplace pas la lecture du d\u00e9p\u00f4t, l\u2019ex\u00e9cution de tests ou la r\u00e9vision du code.<\/p>\n\n\n\n<style>.yukie-workflow-summary-card{--ink:#111318;--body:#414753;--muted:#707784;--line:#e4e7ec;--soft:#f6f7f9;--blue:#315efb;--violet:#7257e8;--green:#087a55;--greenSoft:#eaf8f2;--red:#a23131;--redSoft:#fff0f0;color:var(--ink);font-family:Inter,ui-sans-serif,-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif;line-height:1.5;border:1px solid var(--line);border-radius:8px;background:#fff;overflow:hidden;box-shadow:0 16px 42px rgba(24,32,56,.08)}.yukie-workflow-summary-card *{box-sizing:border-box}.yukie-workflow-summary-card .s-head{padding:24px 26px 20px;border-bottom:1px solid var(--line)}.yukie-workflow-summary-card .s-kicker{margin:0 0 6px;color:var(--muted);font:750 11px\/1.4 ui-monospace,SFMono-Regular,Menlo,monospace;letter-spacing:.08em;text-transform:uppercase}.yukie-workflow-summary-card h3{margin:0;font-size:22px;line-height:1.2;letter-spacing:-.025em}.yukie-workflow-summary-card .s-sub{margin:7px 0 0;color:var(--body);font-size:13px}.yukie-workflow-summary-card .s-body{padding:24px 26px}.yukie-workflow-summary-card .s-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:10px}.yukie-workflow-summary-card .s-stat{padding:15px;border:1px solid var(--line);border-radius:6px;background:var(--soft)}.yukie-workflow-summary-card .s-stat span{display:block;color:var(--muted);font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:.06em}.yukie-workflow-summary-card .s-stat strong{display:block;margin-top:5px;font-size:20px}.yukie-workflow-summary-card table{width:100%;border-collapse:collapse;font-size:12px}.yukie-workflow-summary-card th,.yukie-workflow-summary-card td{padding:11px 12px;border:1px solid var(--line);text-align:left;vertical-align:top}.yukie-workflow-summary-card th{background:var(--soft)}.yukie-workflow-summary-card .s-note{margin:16px 0 0;padding:12px 14px;border-left:3px solid var(--blue);background:#f3f5ff;color:#38466c;font-size:12px}.yukie-workflow-summary-card details{margin-top:12px;border:1px solid var(--line);border-radius:6px}.yukie-workflow-summary-card summary{cursor:pointer;padding:12px 14px;font-size:12px;font-weight:800}.yukie-workflow-summary-card pre{max-height:560px;overflow:auto;margin:0;padding:14px;white-space:pre-wrap;background:#f5f6f8;color:#222936;font:11px\/1.6 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}@media(max-width:680px){.yukie-workflow-summary-card .s-grid{grid-template-columns:1fr}.yukie-workflow-summary-card .s-head,.yukie-workflow-summary-card .s-body{padding:20px}}<\/style><article class=\"yukie-workflow-summary-card\"><header class=\"s-head\"><p class=\"s-kicker\">Autre cat\u00e9gorie de flux de travail<\/p><h3>Tests guid\u00e9s de l'agent de navigation Yukie<\/h3><p class=\"s-sub\">Utile pour les flux de travail Web sp\u00e9cifiques \u00e0 certaines t\u00e2ches ; n'a pas \u00e9t\u00e9 test\u00e9 en tant que remplacement d'un agent de codage de r\u00e9f\u00e9rentiel.<\/p><\/header><div class=\"s-body\"><table><thead><tr><th>Flux de travail<\/th><th>Crit\u00e8res remplis<\/th><th>Premier r\u00e9sultat valide<\/th><\/tr><\/thead><tbody><tr><td>Diapositives<\/td><td>5\/6<\/td><td>Une pr\u00e9sentation de cinq diapositives a \u00e9t\u00e9 g\u00e9n\u00e9r\u00e9e ; les notes du pr\u00e9sentateur n'ont pas pu \u00eatre v\u00e9rifi\u00e9es.<\/td><\/tr><tr><td>Document<\/td><td>6\/6<\/td><td>Fiche de recherche structur\u00e9e avec fonction d'exportation et historique des versions.<\/td><\/tr><tr><td>Image + l\u00e9gende<\/td><td>5\/6<\/td><td>Image carr\u00e9e bien mise en valeur ; la l\u00e9gende requise \u00e9tait manquante.<\/td><\/tr><\/tbody><\/table><p class=\"s-note\">Conclusion fond\u00e9e : points d'entr\u00e9e clairs et flux de travail multimodaux guid\u00e9s. Conclusions non \u00e9tay\u00e9es : utilisation illimit\u00e9e, prix exact ou remplacement complet du code Codex\/Claude.<\/p><\/div><\/article>\n\n\n\n<h2 id=\"which-one\" class=\"wp-block-heading\">Quel langage de programmation un d\u00e9veloppeur ind\u00e9pendant devrait-il choisir ?<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Choisissez Codex<\/strong> lorsque l'ex\u00e9cution compacte et born\u00e9e, la combinaison des surfaces disponibles ou les donn\u00e9es d'ex\u00e9cution disponibles dans votre configuration correspondent \u00e0 votre fa\u00e7on de travailler.<\/li>\n\n\n\n<li><strong>S\u00e9lectionnez le code Claude<\/strong> lorsqu'une boucle de terminal conversationnelle, les fonctionnalit\u00e9s de personnalisation que vous avez v\u00e9rifi\u00e9es ou un comportement de r\u00e9vision plus g\u00e9n\u00e9ral, comme celui observ\u00e9 dans notre fixture, rev\u00eatent une importance plus grande.<\/li>\n\n\n\n<li><strong>Utilisez l'une ou l'autre option pour un d\u00e9p\u00f4t que vous ne connaissez pas<\/strong> uniquement apr\u00e8s avoir valid\u00e9 l'architecture en lecture seule et \u00e9valu\u00e9 les risques. Les deux outils ont bien rempli cette t\u00e2che.<\/li>\n\n\n\n<li><strong>Utilisez les deux de mani\u00e8re s\u00e9lective<\/strong> lorsqu'un examen par un deuxi\u00e8me agent justifie le co\u00fbt suppl\u00e9mentaire li\u00e9 \u00e0 l'abonnement et \u00e0 la coordination. Demandez \u00e0 ce deuxi\u00e8me outil de remettre en question une diff\u00e9rence ou un plan plut\u00f4t que de se contenter de reproduire aveugl\u00e9ment la t\u00e2che.<\/li>\n\n\n\n<li><strong>Ajouter GlobalGPT<\/strong> lorsque le routage multimod\u00e8le ou le traitement multimodal constitue le maillon manquant. Conservez les op\u00e9rations natives sur le r\u00e9f\u00e9rentiel au sein de l'environnement de d\u00e9veloppement.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Une p\u00e9riode d'essai de sept jours est plus r\u00e9v\u00e9latrice qu'un classement. Choisissez une fonctionnalit\u00e9 r\u00e9elle mais hors production, un bug et une r\u00e9vision. Figez la consigne et la commande de validation. Enregistrez le premier diff valide, les tests r\u00e9ussis, le temps \u00e9coul\u00e9, les interventions humaines, les implications inattendues et l\u2019impact de ce travail sur votre quota d\u2019utilisation disponible. Le meilleur produit est celui dont vous pouvez d\u00e9tecter les erreurs et dont vous pouvez maintenir le flux de travail.<\/p>\n\n\n\n<h2 id=\"faq\" class=\"wp-block-heading\">FAQ : Codex vs code Claude<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Le Codex est-il meilleur que le code Claude ?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Pas syst\u00e9matiquement. Les deux ont men\u00e9 \u00e0 bien les quatre t\u00e2ches pr\u00e9vues dans notre programme. Claude Code s'est distingu\u00e9 par l'\u00e9tendue de son analyse, tandis que Codex s'est r\u00e9v\u00e9l\u00e9 plus concis dans certains aspects de la mise en \u0153uvre et de la correction des bogues.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Quelle est la meilleure solution pour les d\u00e9p\u00f4ts volumineux ?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Notre petit outil ne peut pas r\u00e9pondre \u00e0 cette question. Testez les deux dans le cadre d'une t\u00e2che en mode lecture seule \u00e0 partir de votre propre r\u00e9f\u00e9rentiel avant d'autoriser les modifications.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Quel agent de codage n\u00e9cessite le moins de supervision ?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Cela d\u00e9pend de la clart\u00e9 de la t\u00e2che, des param\u00e8tres du mod\u00e8le, des instructions du r\u00e9f\u00e9rentiel et du style d'interaction souhait\u00e9. Un utilisateur de Reddit a fait \u00e9tat de diff\u00e9rents mod\u00e8les de supervision, mais cette exp\u00e9rience individuelle ne constitue pas une r\u00e8gle applicable \u00e0 l'ensemble du produit.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Lequel est le moins cher ?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Les principaux niveaux de forfait pour les particuliers correspondent \u00e0 $20, $100 et $200 par mois, mais les m\u00e9canismes relatifs au volume inclus et aux limites diff\u00e8rent. Les cr\u00e9dits optionnels et la facturation via l'API sont trait\u00e9s s\u00e9par\u00e9ment.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Les forfaits Claude et Claude partagent-ils les m\u00eames limites d'utilisation ?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Oui. Les forfaits Claude et Claude Code sont soumis \u00e0 des limites de sessions partag\u00e9es et \u00e0 des limites hebdomadaires dans le cadre des forfaits Pro ou Max associ\u00e9s.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Les t\u00e2ches locales et celles ex\u00e9cut\u00e9es dans le cloud de Codex partagent-elles les m\u00eames limites ?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Les messages locaux et les discussions sur le cloud partagent un cr\u00e9neau de cinq heures, et des limites hebdomadaires peuvent \u00e9galement s'appliquer.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Le mod\u00e8le GlobalGPT peut-il remplacer le Codex ou le mod\u00e8le Claude Code ?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Non. Il permet d'\u00e9tendre l'un ou l'autre de ces workflows avec des mod\u00e8les suppl\u00e9mentaires, une interface en ligne de commande (CLI), MCP, des comp\u00e9tences (Skills) et des outils multimodaux, mais l'acc\u00e8s au r\u00e9f\u00e9rentiel et le comportement des agents de codage restent du ressort de l'h\u00f4te.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Puis-je utiliser le code GlobalGPT pour les deux produits ?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">GlobalGPT propose des tutoriels officiels sur l'interface en ligne de commande (CLI) pour les deux solutions. Nous avons v\u00e9rifi\u00e9 le fonctionnement de la CLI dans les deux environnements, ainsi que l'utilisation de MCP et de Skill dans Codex, avec une restriction d'autorisation pour MCP en mode sans surveillance.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>Les tarifs, les conditions des formules, les int\u00e9grations et les sources d'information ont \u00e9t\u00e9 v\u00e9rifi\u00e9s en juillet 2026. Les caract\u00e9ristiques du produit sont susceptibles d'\u00e9voluer.<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/www.glbgpt.com\/home?inviter=hub_content_home&amp;login=1\">Ouvert GlobalGPT<\/a> si vous souhaitez int\u00e9grer une approche multimod\u00e8le et multimodale \u00e0 votre processus de codage actuel.<\/p>\n\n\n<\/article>","protected":false},"excerpt":{"rendered":"<p>Codex vs Claude Code is less about finding one universal winner and more about choosing the working style you can trust every day. Both products can inspect a repository, edit multiple files, run commands, execute tests, and explain a patch. The meaningful differences appear in how you delegate work, how often you steer the agent, [&hellip;]<\/p>","protected":false},"author":7,"featured_media":17361,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_seopress_robots_primary_cat":"","_seopress_titles_title":" Codex vs Claude Code: Features, Pricing & Hands-On Tests","_seopress_titles_desc":"A neutral Codex vs Claude Code comparison covering features, pricing, limits, real repository tests, user experience, and GlobalGPT integrations.","_seopress_robots_index":"","footnotes":""},"categories":[7],"tags":[],"class_list":["post-17342","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ai-chat"],"_links":{"self":[{"href":"https:\/\/wp.glbgpt.com\/fr\/wp-json\/wp\/v2\/posts\/17342","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wp.glbgpt.com\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wp.glbgpt.com\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wp.glbgpt.com\/fr\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/wp.glbgpt.com\/fr\/wp-json\/wp\/v2\/comments?post=17342"}],"version-history":[{"count":2,"href":"https:\/\/wp.glbgpt.com\/fr\/wp-json\/wp\/v2\/posts\/17342\/revisions"}],"predecessor-version":[{"id":17393,"href":"https:\/\/wp.glbgpt.com\/fr\/wp-json\/wp\/v2\/posts\/17342\/revisions\/17393"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wp.glbgpt.com\/fr\/wp-json\/wp\/v2\/media\/17361"}],"wp:attachment":[{"href":"https:\/\/wp.glbgpt.com\/fr\/wp-json\/wp\/v2\/media?parent=17342"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wp.glbgpt.com\/fr\/wp-json\/wp\/v2\/categories?post=17342"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wp.glbgpt.com\/fr\/wp-json\/wp\/v2\/tags?post=17342"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}