En résumé : j'ai migré le backend de mon jeu Galactic Reigns de Laravel vers NestJS en confiant l'essentiel du portage à une chaîne d'agents IA. Ce qui a fonctionné, ce ne sont pas de meilleures consignes, mais des barrières automatiques que les agents ne peuvent pas contourner, une revue adverse obligatoire, et l'ancien code utilisé comme oracle de test.

Le contexte

Galactic Reigns est un MMO de stratégie spatiale en temps réel que je développe seul depuis août 2025. La première version du backend était en Laravel. J'ai voulu passer en TypeScript, avec une architecture modulaire stricte : chaque domaine métier (flottes, bâtiments, recherche, planètes…) découpé en couches domaine, application, infrastructure et présentation.

Deux choix de départ ont simplifié tout le reste :

  • Une nouvelle base de données, sans partage avec l'ancienne. Les différences avec le PHP sont donc des choix documentés, pas des bugs à aligner à tout prix.
  • Le code PHP comme oracle de comportement, pas comme cible de compatibilité : on ne cherche pas à faire tourner les deux en parallèle, on cherche à reproduire ce que l'ancien code calcule.

La chaîne d'agents, domaine par domaine

Pour chaque domaine métier, la même chaîne de sous-agents (Claude Sonnet), sous ma supervision :

  1. Scout : un agent lit le code PHP du domaine et en tire une spécification.
  2. Port : un agent écrit le domaine en TypeScript, couche par couche, avec ses tests.
  3. Verify : typage, tests, règles d'architecture et conventions, avec une boucle de réparation bornée.
  4. Revue adverse : un relecteur cherche les erreurs sous trois angles, le comportement, les frontières entre modules et la fidélité à l'original.
  5. Synthèse : un bilan, et la liste des décisions qui me reviennent.

Ce que les agents ont mal fait

Les agents écrivent vite du code plausible. Le problème, c'est le plausible :

  • La taxonomie des ressources des planètes avait été inventée, avec des valeurs fausses d'un facteur 100 environ.
  • La liste des paramètres de partie comptait une quarantaine de clés inventées, et il en manquait 31 de l'original.
  • Les consignes du type « n'invente pas » ou « écris des tests indépendants » ont dérivé dès qu'aucun contrôle ne les imposait.

Sans référence externe, ces erreurs passent : le code compile, les tests écrits par le même agent passent aussi.

L'ancien code comme oracle

La parade a été le golden master. De petits extracteurs lisent le code PHP et produisent des jeux de données de référence : taxonomie des planètes, paramètres de partie, types d'étoiles, recherches, coûts des bâtiments. Chaque fichier sert deux fois :

  • comme source de vérité : l'agent lit la référence au lieu d'inventer ;
  • comme oracle de test : les tests vérifient le nouveau code contre ces références, qui ne sont jamais générées par le code qu'elles contrôlent.

La mécanique bat le prompt

La leçon principale tient en une phrase : chaque erreur récurrente des agents a été transformée en contrôle automatique, pas en consigne supplémentaire.

Levier Type Ce qu'on a observé
Typage, règles d'architecture, conventions, golden master Automatique Tient. Une fois le gabarit de portage durci, le domaine des parties est passé du premier coup.
Revue adverse sous trois angles Semi-automatique Indispensable : environ 8 divergences par domaine que les contrôles automatiques laissaient passer.
Consignes dans le prompt Texte Dérive tant qu'aucun contrôle ne l'impose.
Décisions de gameplay Humaine Irréductible : c'est moi qui tranche.

Concrètement, les barrières sont :

  • le typage strict ;
  • les règles de dépendances entre couches, vérifiées par un outil (le domaine ne peut pas importer l'infrastructure) ;
  • un script de conventions qui interdit par exemple les dates et les nombres aléatoires créés directement dans le code métier, en dehors des adaptateurs prévus pour ça (ce qui rend tout déterministe et testable) ;
  • le golden master.

Ce que la migration a corrigé au passage

Relire l'ancien code avec cette rigueur a fait remonter de vrais bugs du PHP, corrigés dans la nouvelle version :

  • une vérification de rôle qui, face à un rôle inconnu, laissait passer au lieu de refuser ;
  • une vérification d'appartenance manquante à la partie en cours ;
  • une information de session globale au processus, si bien qu'un joueur pouvait hériter de la partie choisie par un autre.

Le piège : des tests verts qui ne disent rien du démarrage

À un moment, plus de 4 000 tests passaient alors que le serveur refusait de démarrer depuis cinq commits : une injection de dépendances mal déclarée, invisible pour les tests unitaires. Depuis, après chaque modification de module, la règle est simple : compiler, redémarrer, et faire un vrai appel à l'API.

Le résultat

La migration est terminée : les 24 domaines métier du jeu tournent en production sur le nouveau backend NestJS, en bêta fermée. La méthode a été mise au point et éprouvée sur les six premiers domaines.

Ce que je retiens pour des projets clients :

  • Un agent ne remplace pas une méthode. Il accélère l'écriture ; la fiabilité vient de ce qui vérifie son travail.
  • Investir d'abord dans les contrôles automatiques rapporte plus que n'importe quel raffinement de prompt.
  • Garder l'humain comme oracle métier, sur les décisions que le code ne peut pas trancher seul.