Gemini a relu la PR de Claude. Trente-six commentaires plus tard, elle était meilleure.
Un relecteur qui est toujours d'accord avec l'auteur n'est pas un relecteur. Faites passer le code de votre IA devant une IA rivale et les angles morts s'illuminent — y compris les bugs de thread-safety qui seraient partis en production.
Le schéma vers lequel je reviens sans cesse est celui où Claude écrit le code et Gemini le relit. Entraînement différent. Angles morts différents. Opinions différentes sur ce qui est un motif défendable et ce qui est une odeur de code. Ce samedi fut la démonstration la plus concrète de pourquoi je pense que ce schéma est le bon.
Un lot de PR d’expansion d’endpoints de Phase 2 avait atterri sur toute la surface API au cours de la semaine précédente. Huit sous-systèmes distincts ont chacun vu leur surface publique étendue. Claude avait écrit la majeure partie de l’implémentation. Avant de fusionner l’une d’entre elles, je les ai toutes fait passer par Gemini comme passe de relecture. Gemini est revenu avec trente-six commentaires précis sur l’ensemble du lot.
J’ai traité chacun d’entre eux. Voici le billet sur ce que Gemini a attrapé et ce que cela signifie que les prises étaient du genre qu’elles étaient.
Ce qu’étaient les huit sous-systèmes
Les PR couvraient les huit modules de routeur API qui avaient besoin de l’expansion de Phase 2 : animation, réseau, audio, perception IA, géométrie constructive de solides de scène, liaisons d’action d’entrée et de manette, types de pose d’ancrage XR, et cycle de vie de la VM Lua de scripting. Chaque PR ajoutait entre une douzaine et quarante endpoints, avec des schémas de requête/réponse complets, des assistants, et des tests.
Les PR n’étaient pas subtiles. Chacune était une expansion substantielle de la surface publique. Ensemble, elles représentaient plusieurs semaines de travail de conception que les agents ont implémenté sur environ deux week-ends.
Ce que Gemini a attrapé
Je veux être précis car les catégories comptent.
Animation et réseau : références d’arbres de mélange et assistants. Gemini a remarqué que les assistants d’arbre de mélange dans l’API d’animation et les assistants de topologie dans l’API réseau avaient des conventions subtilement différentes pour la façon dont ils géraient les références manquantes. Animation retournait un équivalent-None et laissait l’appelant décider. Réseau levait une exception. Les deux sont des motifs valides. Ils étaient incohérents entre deux PR qui avaient atterri à un jour d’intervalle l’une de l’autre. Le correctif a été de les aligner ; nous avons choisi le chemin d’exception explicite car il fait remonter la référence manquante à la frontière de l’API au lieu de la laisser se propager comme un null silencieux.
Audio : valeurs par défaut des modèles de réponse et assistants. Gemini a trouvé que plusieurs modèles de réponse audio avaient des valeurs par défaut incohérentes pour les champs optionnels. Certains par défaut à des chaînes vides, certains à None, certains à un null explicite. L’incohérence aurait produit un comportement déroutant au niveau de la couche de liaison client (où différents langages sérialisent chaque option différemment). Le correctif a été de choisir une seule convention (None dans les types Python, null sur le fil) et de l’appliquer de manière cohérente.
Perception IA : cartes de handles et liaisons. Gemini a signalé une préoccupation de thread-safety dans la carte de handles du sous-système de perception : la carte était mutée depuis un thread d’arrière-plan tout en étant lue depuis le thread de requête API, sans verrou. Sous charge, cela produirait des bugs intermittents de corruption de carte très difficiles à diagnostiquer. Le correctif a été un verrou lecteur-écrivain avec le chemin de lecture optimisé pour le cas courant (les recherches surpassent largement les insertions en nombre).
Scène : cartes de handles et réponses CSG. Même famille de bug que le constat de perception IA. Gemini a attrapé la même préoccupation de thread-safety dans la carte de handles CSG du sous-système de scène. Le correctif était de la même forme : un verrou lecteur-écrivain. C’est le genre de bug qu’un ensemble d’yeux entraînés signale partout parce qu’il a vu le motif ; Claude avait écrit le même motif à deux endroits sans le remarquer.
Entrée : liaisons d’action et de manette. Gemini a trouvé que l’API de liaison d’action utilisait une convention de nombre magique pour les ID d’action invalides (-1), tandis que l’API de liaison de manette utilisait une valeur de struct sentinelle. L’incohérence produirait des bugs subtils quand un développeur travaillant sur les deux API utiliserait accidentellement le mauvais marqueur d’invalidité. Le correctif a été d’introduire une constante typée ActionId::Invalid dans les deux API et de migrer tous les nombres magiques vers celle-ci.
XR : types de pose d’ancrage et réutilisation de handler. Gemini a attrapé que l’API XR exposait deux types de pose subtilement différents dans différents endpoints : l’un en coordonnées monde et l’autre en coordonnées locales à l’ancrage. La différence est réelle et compte pour le consommateur, mais les endpoints ne documentaient pas clairement la différence. Gemini a suggéré de séparer les types afin que le système de types applique la distinction. Le correctif a été d’introduire WorldPose et AnchorPose comme types distincts sans conversion implicite entre eux.
Scripting : cycle de vie de la VM Lua et fuites. Gemini a trouvé que la VM Lua était allouée par requête sans chemin de démontage clair. Sous charge soutenue, cela ferait fuir l’état de VM dans l’espace d’adressage jusqu’à ce que le serveur API s’effondre. Le correctif a été d’introduire un pool de VM par thread serveur avec une sémantique d’acquisition et de libération explicite, et d’ajouter un chemin de démontage qui s’exécute à la fin de la requête quel que soit le succès ou l’échec.
Ce que j’ai remarqué à propos des prises en tant que catégorie
Trois observations.
La plupart des prises étaient des prises de cohérence. Les deux tiers des commentaires de Gemini étaient « cette convention diffère de la convention utilisée dans un autre sous-système que vous venez d’ajouter ». C’est exactement le genre de prise qu’un seul modèle fait mal, parce que chaque PR a atterri isolément et le modèle qui l’écrivait n’avait pas les autres PR en contexte. Un relecteur travaillant sur l’ensemble du lot voit les incohérences que l’auteur n’avait pas en tête.
Quelques prises étaient de vrais bugs. Les constats de thread-safety sur les cartes de handles étaient de vrais bugs. Ils seraient partis en production. Ils auraient été intermittents et difficiles à diagnostiquer. Gemini a attrapé les deux instances dans le lot (une en perception IA, une en CSG de scène) parce qu’il avait la reconnaissance de motif pour « carte mutable partagée sans verrou = préoccupation de thread-safety ». Modèle différent, entraînement différent, choses différentes pour lesquelles il a été calibré à signaler.
Quelques-unes étaient stylistiques et ont été débattues. Tous les commentaires de Gemini n’étaient pas justes. Une poignée étaient des préférences stylistiques auxquelles j’ai soit résisté soit demandé un jugement humain. Le fait que certains commentaires aient été rejetés n’affaiblit pas le schéma ; il le renforce. Un relecteur qui est toujours d’accord avec l’auteur n’est pas un relecteur.
Ce que cela fait et ne fait pas
Ce que cela fait : attraper une classe de bugs que la relecture par un seul modèle manque. Spécifiquement les bugs de cohérence inter-PR et les prises de reconnaissance de motif où un relecteur entraîné sur des données différentes signale quelque chose que l’entraînement de l’auteur n’a pas vu.
Ce que cela ne fait pas : remplacer la relecture humaine. Les commentaires de Gemini étaient une première passe. J’ai lu chacun d’entre eux. J’en ai rejeté certains. J’en ai accepté la plupart. La décision finale de fusion était la mienne. Le schéma est « Claude écrit, Gemini relit, l’humain décide ». Pas « Gemini décide ».
Ce que cela suggère pour les labos IA : la métrique à optimiser n’est pas « le code du modèle passe-t-il sa propre relecture ». C’est « le code du modèle passe-t-il la relecture par le modèle d’un fournisseur différent ». Les agents qui réussissent bien sur la métrique inter-fournisseurs sont ceux en qui je fais confiance pour le travail sérieux.
Ce que partenaires et bâtisseurs devraient en retenir
Si vous exécutez un flux de travail piloté par agents et que vous ne faites pas encore passer la relecture de PR par le modèle d’un autre fournisseur, essayez-le sur le prochain lot. Le coût de mise en place est faible. Le taux de capture de bugs n’est pas négligeable. Le lot d’aujourd’hui a attrapé deux vrais bugs de thread-safety qui seraient partis en production.
Si vous êtes un labo IA et que vous n’avez pas optimisé votre agent de codage pour « la relecture de PR contre le modèle d’un autre fournisseur » comme cible, envisagez-le. La métrique est honnête. Le signal est réel. Les agents qui obtiennent de bons résultats dessus sont ceux que les équipes sérieuses adopteront.
Si vous évaluez un moteur pour un partenariat, le schéma de relecture multi-fournisseur est l’un des signaux de discipline que je demanderais. Une équipe qui exécute une relecture inter-fournisseurs sur chaque PR significative est une équipe différente de celle qui ne le fait pas. La base de code reflète la différence.
Trente-six commentaires, huit sous-systèmes, un samedi. Le lot est meilleur que ce matin. Le schéma prouve sa valeur, encore.
Retour à la construction.
Le runtime avec lequel les labos IA relisent — et construisent
RakuAI est le runtime spatial contre lequel les fabricants de LLM expédient. Relecture inter-fournisseurs, métriques honnêtes, discipline digne d'un partenaire. Voyez où vos modèles s'inscrivent dans le monde réel.