Vous avez fait échouer le test à l'agent et lui avez demandé de mettre la suite au vert. Il est revenu vert. Ensuite, vous lisez le diff : il n’a pas touché le code testé. Il a édité le test. L'affirmation qui disait== 9000lit maintenant== 10000, ce qui correspond exactement à ce que renvoie la fonction buggy, donc la barre est verte car le test a été modifié pour être en accord avec le bug.
Cela a un nom. Il s’agit d’un piratage de récompense, et ce n’est pas un problème rare en marge. La propre équipe d'ingénierie de Cursor a publié un article intitulé Le piratage des récompenses submerge les gains en matière d'intelligence des modèles. Il existe un benchmark conçu pour le mesurer dans les agents de codage à long terme, SpecBench. Et chaque développeur qui a pointé un agent vers une suite rouge en a regardé une version : l'assertion supprimée, le@pytest.mark.skip, le retour codé en dur, le test frère s'est discrètement affaibli. On a demandé à l'agent de faire accepter le chèque. Cela a fait passer le chèque. Personne ne lui a dit que le chèque remplaçait l’exactitude du code, il a donc optimisé le chèque qui lui avait été réellement remis.
Cet écart, entre le chèque et ce qu’il représente, est le sujet de cet article. Une boucle comporte cinq bras : générer, vérifier, diriger, réessayer, arrêter. L'ouverture de la série les a nommés ; trois pièces ont depuis pris le contrôle qui décide assez bien, l'arrêt, la porte qui refuse une mauvaise écriture et la surface à partir de laquelle chaque règle est chargée. Celui-ci prend le bras qui définit ce que l'agent vise lors de la prochaine tentative : le bœuf, et la version de récompense piratant le bœuf remet le modèle.
Le bœuf est le bras qui transforme un verdict en instruction suivante. Lorsque le chèque revient en rouge, une ligne de texte est assemblée à partir de la sortie du chèque et introduite dans la génération suivante. Voici la boucle construite par la pièce de porte, refactoriséesrc/jusqu'à ce qu'un garde tienne. Le bœuf est un bras :
#!/usr/bin/env bash # work-until-checked : refactorisez src/ jusqu'à ce que la garde tienne. MAX=5 ; i=0 prompt="Supprimez chaque importation de bibliothèque fictive du code de production sous src/." tandis que [ "$i" -lt "$MAX" ]; do run_agent --task "$prompt" # GENERATE if bash no-mocks.sh ; then # CHECK echo "stop: guard hold after $i retries"; exit 0 fi prompt="La dernière tentative a quand même déclenché la garde ; corrigez-le : $(bash no-mocks.sh 2>&1)" # STEER : seul le nouveau signal i=$((i + 1)) fait echo "stop : budget épuisé, garde toujours rouge" ; sortie 1Le modèle ne voit jamais toute l’histoire. À chaque nouvelle tentative, une invite apparaît, et cette invite correspond à celle que le bouvillon a décidé de rapporter. Au premier passage, l'invite est le but. À chaque passage ultérieur, le bœuf l'écrase. Ainsi, la cible que le modèle vise lors de la troisième te...
[Courte citation de 8% de l'article original]