Tous les articles

Quand l'IA doit filmer sa propre relecture

Écouter l'article (expérimental) · 15:04

00:00 / 15:04

Une fenêtre de navigateur en cours d'enregistrement sur un fond sombre de lignes à peine visibles, la timeline de l'enregistrement s'étirant en dessous, et un moment de cette timeline éclairé d'ambre dans un anneau vert, relié par une ligne pointillée à l'élément de la page qu'il a capté

Quand une pull request est ouverte, la mienne ou celle d'un collègue qu'on m'a demandé de relire, voici les lignes que je colle dans l'agent :

Maintenant, relisons celle-ci : [ajouter le lien GitHub de la PR]

Mais je veux que tu la lances en local en E2E, que tu regardes si tout se passe bien et que tu en fasses des enregistrements Playwright. Je veux aussi que tu l'attaques, que tu essaies de la casser ET que tu la testes à fond [ajouter ici plus de contexte si besoin, par exemple dans les deux périmètres, personnel et organisation].

Ensuite, je le laisse travailler : il lance le changement sur ma machine, de bout en bout, pendant que Playwright enregistre le navigateur au fur et à mesure. Playwright est une bibliothèque d'automatisation de navigateur que l'agent peut piloter, et elle sait filmer les pages qu'elle ouvre. Ce que l'agent me rend, c'est un rapport écrit, accompagné des enregistrements et des captures d'écran des moments qu'il désigne.

Beaucoup de choses ont changé depuis que j'ai écrit en juillet sur la relecture à vue du code écrit par l'IA, y compris ma façon de relire les pull requests. Cette manière de relire m'a impressionné ces derniers temps, et je pense que la plupart des développeurs seraient surpris de ce qu'elle vaut désormais.

Ce que je disais en juillet, et ce qui a changé

Je soutenais alors que, lorsque l'agent lance le code à votre place, la relecture ne disparaît pas. Elle se déplace vers la preuve, et le remède que je proposais était d'ouvrir les logs vous-même et d'y retrouver ce que l'agent disait y figurer.

Ce remède fonctionne toujours, mais la plupart du temps je n'en ai plus besoin. En juillet, j'écrivais aussi que la relecture lente, c'était le lancer, le tracer, chercher à le casser, et exiger de l'agent qu'il montre son travail. Ce qui est nouveau, c'est une façon de demander tout cela en un seul message et de récupérer le travail sous une forme que je peux vérifier sans le refaire. L'agent se charge de l'exécution, et les enregistrements me montrent ce qui s'est passé à l'écran.

Les modèles penchent vers la réponse la plus rapide. Quand on leur demande si un changement fonctionne, ils préfèrent dire que oui plutôt que d'aller vérifier, et il m'est arrivé d'en voir un décrire des logs qui n'existaient pas. Une réponse qui a l'air aboutie est le chemin le plus court pour terminer son tour.

Je ne suis pas le seul à l'avoir constaté. La system card qu'Anthropic a publiée pour Claude Opus 4.8 recense des défaillances tirées de l'usage interne qu'en fait l'entreprise elle-même, et l'une d'elles tombe presque exactement dans mon cas de figure. Le modèle disait garder un œil sur les pull requests d'un chercheur, ce qui n'était pas le cas. La même liste consigne un cas où il affirmait avoir effectué une vérification qu'il n'avait pas faite.

Dire à un modèle de faire plus attention, c'est formuler une demande, et une demande, c'est ce qu'il saute quand il est pressé. Un enregistrement change ce que le modèle doit rendre.

Pourquoi un enregistrement est plus difficile à truquer

Une phrase sur ce qui s'est passé peut s'écrire sans que rien ne se passe. Un enregistrement exige que quelque chose ait réellement tourné, et ce qui a tourné est là, à l'écran, pour que j'en juge.

Quand l'agent doit se filmer en train de lancer le changement, le moyen le moins coûteux de satisfaire la demande, c'est de le lancer pour de bon. Pour tout ce qui passe devant la caméra, il n'y a plus de place pour un paragraphe plein d'assurance qui tiendrait lieu de travail. Livré seul, un rapport est l'unique récit de ce qui s'est passé, et je ne peux distinguer un test d'une phrase sur un test qu'en le refaisant moi-même. L'enregistrement sépare la phrase de l'événement. Si l'agent dit avoir testé le formulaire vide, le formulaire vide est dans la vidéo, ou il n'y est pas. Tout ce que le rapport avance sans que cela soit jamais passé devant la caméra redevient une affirmation.

Le film montre ce que l'agent a tenté, et ce qu'il laisse hors champ indique ce dont je n'ai aucune preuve : l'écran qu'il n'a jamais ouvert, le formulaire qu'il n'a jamais soumis avec des données invalides, le second compte auquel il ne s'est jamais connecté.

Il y a un second effet, et il compte tout autant. Devant la caméra, faire comme si un problème n'avait pas eu lieu, ou en inventer un, cesse d'être un raccourci sans risque pour l'agent, puisque la vidéo est là pour être vérifiée. Alors, quand il en trouve un, il me le signale au lieu de l'enterrer dans le résumé.

J'ai rarement besoin de regarder une vidéo en entier pour que tout cela fonctionne. L'essentiel de l'effet se produit avant que j'ouvre quoi que ce soit, parce que c'est en demandant le film que j'oblige l'agent à lancer le changement. Ce que je regarde, en revanche, ce sont les captures d'écran des moments qui comptent, et cela inclut les réussites. J'aime voir le parcours aller au bout comme il le doit, dans chacun des périmètres que j'ai indiqués, autant que l'erreur à l'écran ou une page qui s'est ouverte pour un compte qui n'aurait jamais dû y accéder. La vidéo reste en réserve, pour le cas où une capture d'écran soulèverait une question.

Le rapport devient un index des preuves, ce qui, pour un résumé, est un meilleur emploi que de tenir lieu de preuve. Je me demande toujours « est-ce vrai ? », mais désormais une capture d'écran y répond, ou au pire un court passage de la vidéo, et une plus grande part de mon temps va à « est-ce que ça compte ? ».

Quand la réponse du serveur compte, la trace de Playwright vaut la peine d'être demandée en plus de la vidéo. La vidéo, ce sont les pixels. Une trace conserve, pour chaque action, un instantané de la page avant et après, avec les requêtes réseau, le corps de leurs réponses et la console du navigateur. Si l'agent dit que le serveur a répondu par un 403, la trace contient la réponse.

Le Playwright MCP de Microsoft, l'un des outils qui permettent à un agent de piloter un navigateur, passe par l'arbre d'accessibilité de la page, une vue textuelle structurée de celle-ci, plutôt que par les pixels. Le film est pour moi, et c'est ce qui le rend utile : l'agent agit sur une vue textuelle de la page, et le film me montre les pixels qu'il ne regardait pas, sans aucun de ses commentaires en surimpression. Il peut tout de même choisir la prise qu'il me remet, ou relancer un parcours jusqu'à ce qu'il passe au vert, alors tous les enregistrements qu'il a faits, prises ratées comprises, valent la peine d'être demandés.

L'attaquer, et la tester

Le prompt demande, à dessein, deux choses qui tirent dans des sens différents.

Un modèle à qui l'on demande de confirmer a tendance à confirmer. La consigne de regarder « si tout se passe bien » l'invite à chercher ce qui se passe bien : il emprunte donc le chemin pour lequel la fonctionnalité a été conçue, voit l'écran attendu et annonce un succès. Cette exécution mérite d'être filmée, parce qu'un résultat au vert sans aucune preuve derrière, c'est exactement l'affirmation contre laquelle mettait en garde le billet de juillet. Mais elle ne couvre que le cas que l'auteur avait déjà en tête.

Demandez-lui de casser la chose, et il doit aller chercher ailleurs : un champ obligatoire laissé vide, le bouton d'envoi cliqué deux fois, la même page ouverte dans deux onglets, l'identifiant dans la barre d'adresse remplacé par celui de quelqu'un d'autre, le bouton retour pressé au milieu d'un parcours. Les bugs ont tendance à se cacher dans ce genre d'endroits.

Un agent à qui l'on demande seulement de casser a le problème inverse. Il peut passer toute la session sur un seul cas limite ingénieux sans jamais confirmer que le parcours ordinaire, celui que tout utilisateur emprunte, fonctionne toujours de bout en bout. Je veux, dans la même exécution, la visite du parcours ordinaire et l'assaut lancé contre lui, d'où le ET en majuscules.

Les deux consignes fonctionnent aussi mieux filmées que dans un rapport écrit. Une phrase comme « j'ai essayé de le casser et je n'y suis pas arrivé » ne me dit rien des efforts qu'il y a mis, alors que l'enregistrement des tentatives m'en dit beaucoup. Je vois s'il s'en est pris une seule fois au formulaire avant de passer à autre chose, ou s'il est revenu à la charge avec un autre compte ou un autre ordre d'étapes. Les attaques qui ont échoué font partie des preuves que le changement tient.

La ligne que je suis seul à pouvoir écrire

La dernière partie du prompt est un espace à remplir qui change à chaque pull request. C'est là que je dis à l'agent où se trouve le risque.

Mon exemple à moi, c'est « dans les deux périmètres, personnel et organisation ». Quand une fonctionnalité doit se comporter correctement dans un compte personnel comme au sein d'une organisation, l'essentiel de ce qui peut mal tourner se loge à la jointure des deux : quelque chose qui appartient à un périmètre et qui apparaît dans l'autre, ou une page qui fonctionne pour le propriétaire et échoue pour un membre. L'agent peut lire le diff et faire des suppositions là-dessus. Il ne sait pas quels chemins les utilisateurs empruntent réellement, ni quelle erreur serait gênante et laquelle serait grave. Moi, je le sais, parce que je connais le produit et ce que je veux qu'il fasse.

Ce passage entre crochets, c'est ma part de la relecture. Il détourne l'agent de ce que suggère le diff pour l'orienter vers ce qui, je le sais, peut être endommagé, et l'enregistrement me montre s'il y est vraiment allé.

Ce que le film ne montre pas

Le film a ses limites.

C'est l'agent qui choisit ce qu'il filme : les chemins qu'il emprunte et, selon l'outillage, le moment où l'enregistrement commence et s'arrête. Si le périmètre organisation que j'ai demandé n'est pas sur la bande, je n'ai aucune preuve qu'il ait été testé, quoi qu'en dise le rapport.

Tout ce que Playwright enregistre se passe dans le navigateur. Les logs du serveur, les lignes de la base de données et la tâche d'arrière-plan qui tourne une minute plus tard ne figurent ni dans la vidéo ni dans la trace. Un écran peut passer au vert alors qu'en dessous, une ligne a été rattachée au mauvais compte. Un contrôle d'autorisation peut manquer côté serveur pendant que l'interface masque parfaitement le bouton devant la caméra, et l'API derrière accepterait quand même la requête de quiconque l'enverrait directement.

C'est là que la moitié « attaque » du prompt se rentabilise. Un film du cas nominal ne passe jamais par ce contrôle, alors qu'un film de l'agent qui ouvre une fiche appartenant à un autre compte, ou qui envoie la requête avec le bouton masqué, y passe. Pour tout ce qui touche aux accès, cette attaque mérite d'être nommée dans la ligne de contexte. Quand le changement atteint la base de données ou le serveur, les requêtes et les logs de la même exécution ont leur place à côté de l'enregistrement, sauvegardés là où le rapport peut y renvoyer.

Un enregistrement peut aussi avoir l'air correct pour une mauvaise raison. Si l'agent a simulé le backend pour que la page se charge, l'enregistrement est celui de la simulation. Le prompt demande une exécution locale et de bout en bout, et avant de se fier à ce que l'application a affiché, il faut savoir avec quoi elle communiquait réellement. Les requêtes réseau de la trace répondent à cette question.

Une remarque pratique : une vidéo Playwright n'est écrite sur le disque qu'une fois le contexte du navigateur fermé. Si l'agent dit avoir enregistré l'exécution et que le fichier manque ou est vide, cela aussi est une preuve.

Dans ces limites, le film, c'est la relecture lente de juillet, avec l'agent qui se charge de l'exécution et le jugement qui me revient.

C'est toujours moi qui tranche

Les modèles ont beaucoup progressé depuis que j'ai écrit le billet de juillet, et ma preuve, ce sont mes propres relectures. Ce que je constate, c'est que lorsque l'agent doit lancer la chose et la filmer, et que quelque chose casse, il le dit, et je peux le voir par moi-même. Là non plus, je ne le crois pas sur parole.

Les développeurs qui n'ont connu la relecture par IA que sous la forme d'un bot laissant des commentaires sur un diff en ont vu la version minimale. C'est plus proche d'un testeur installé à mon poste, qui prendrait des raccourcis si je le laissais faire, qui utilise le changement comme le ferait un utilisateur, essaie de le casser et laisse la bande pour que je voie quels raccourcis ont été pris.

Lire le code compte toujours, et l'enregistrement couvre ce que la lecture ne peut pas atteindre : le comportement de la chose une fois lancée. Ce n'est pas gratuit. Une exécution prend plus de temps qu'une lecture, l'application a besoin de données assez réalistes pour que le test ait un sens, et il faut toujours que quelqu'un regarde ce que l'agent rapporte.

Rien de tout cela ne fait de l'agent le relecteur. Il fait le travail de terrain. C'est toujours moi qui, à la fin, décide de ce qui est juste et de ce que je veux. Quand l'enregistrement montre un parcours qui fonctionne mais qui n'est pas ce que le produit devrait faire, l'agent ne peut pas le savoir, et quand il signale comme bug un comportement voulu, c'est moi qui le dis.

Le billet de juillet se terminait sur la ligne entre le diff que vous avez compris et le diff que vous avez seulement vu. Les enregistrements permettent d'atteindre à moindre coût le côté compris de cette ligne. Je n'ai pas besoin de regarder chaque exécution en entier, seulement de voir les moments qui comptent et de savoir quels chemins la bande couvre. Ce qui a changé, c'est que je fais désormais filmer son travail à la machine, si bien que je me demande moins si elle a fait ce qu'elle disait, et davantage si elle a regardé aux bons endroits. Je ne peux en juger que parce que je sais à quoi sert le produit, et quand elle regarde aux mauvais endroits, j'envoie une ligne de contexte de plus et je lui demande de tout relancer.

Les questions auxquelles cet article répond

  • Quel prompt utilisez-vous pour faire relire une pull request par un agent IA ?

    Je colle le lien de la pull request et je demande à l'agent de la lancer en local, de bout en bout, de regarder si tout se passe bien et de faire des enregistrements Playwright de l'exécution. Je lui demande aussi d'attaquer le changement, d'essayer de le casser et de le tester à fond, et je termine par une ligne de contexte sur l'endroit où se trouve le risque, par exemple que cela doit fonctionner dans les deux périmètres, personnel et organisation. L'agent lance le changement sur ma machine, de bout en bout, pendant que Playwright enregistre le navigateur, et rapporte ce qu'il a trouvé, enregistrements et captures d'écran des moments clés à l'appui.

  • Pourquoi un enregistrement rend-il la relecture faite par une IA plus fiable qu'un rapport écrit ?

    Les modèles penchent vers la réponse la plus rapide, et un paragraphe plein d'assurance sur ce qui s'est passé coûte moins cher qu'une exécution. J'en ai vu un décrire des logs qui n'existaient pas. Un enregistrement exige que quelque chose ait réellement tourné, si bien que la phrase et l'événement se séparent : si l'agent dit avoir testé le formulaire vide, le formulaire vide est dans la vidéo, ou il n'y est pas. Devant la caméra, laisser tomber un problème ou en inventer un n'est plus sans risque, alors quand quelque chose casse, l'agent me montre le moment. Les captures d'écran des moments qui comptent, les réussites comme les échecs, sont en général tout ce que j'ai besoin de voir, et la vidéo complète est là quand l'une d'elles soulève une question.

  • Un enregistrement Playwright prouve-t-il qu'une pull request peut être mergée sans risque ?

    Non. Il prouve ce qui s'est passé dans le navigateur, sur les chemins que l'agent a choisi d'emprunter. Les logs du serveur, les lignes de la base de données, les tâches d'arrière-plan et les contrôles d'autorisation absents sur des endpoints que l'interface n'appelle jamais sont tous hors champ, et une exécution sur un backend simulé peut paraître parfaite à l'image, peu importe ce qu'aurait fait le vrai serveur. Un chemin absent de la bande est un chemin pour lequel je n'ai aucune preuve, quoi qu'en dise le rapport. Pour les changements qui touchent au serveur ou aux données, les requêtes et les logs ont leur place à côté de la vidéo, et la profondeur de la relecture doit toujours être à la mesure des dégâts que le changement peut causer et de la facilité avec laquelle on peut l'annuler.

  • Demander à l'agent de tester et de filmer la pull request remplace-t-il le relecteur humain ?

    Non. L'agent fait le travail de terrain : lancer le changement, l'attaquer, le filmer et noter ce qu'il a trouvé. C'est moi qui décide de ce qui est juste et de ce que je veux. L'agent ne sait pas quel parcours le produit devrait proposer, il peut donc valider un parcours qui fonctionne mais qui n'est pas le bon, ou signaler comme bug un comportement voulu, et quand il manque sur la bande le chemin qui m'importe, je renvoie l'agent au travail avec une ligne de contexte de plus. Maintenant que je fais filmer son travail à la machine, je me demande moins si elle a fait ce qu'elle disait, et davantage si elle a vérifié les bonnes choses.