Migration de stack avec un agent
Changer de framework, monter de version majeure, migrer une base de données : les migrations sont parmi les tâches les plus risquées à confier à un agent. Planifier avec le 80-20, découper en incréments vérifiés, utiliser les tests comme oracle, et éviter les modes de défaillance classiques.
Pourquoi les migrations sont risquées pour un agent
Une migration touche potentiellement chaque fichier du projet : packages, imports, API remplacées, configuration, scripts de build, tests. C’est l’inverse d’une tâche bien bornée — et un agent excelle justement quand la portée est claire et le feedback immédiat.
Les trois dangers principaux d’une migration mal cadrée :
- Portée explosée — l’agent tire un fil (une API dépréciée) et se retrouve à modifier des dizaines de fichiers en cascade, sans vue d’ensemble.
- Changements comportementaux silencieux — le code compile avec le nouveau framework, mais un comportement subtil a changé (sérialisation, ordre d’exécution, valeurs par défaut). Sans tests ciblés, personne ne le détecte.
- Dependency hell — une montée de version entraîne des incompatibilités transitives que l’agent résout par tâtonnement, créant un état incohérent dans les fichiers de packages.
Point clé : Une migration combine portée large + feedback faible : exactement le profil de tâche où un agent non cadré dérive le plus vite. Il faut compenser par du planning et des checkpoints vérifiés.
Planifier avec le 80-20
Le principe 80-20 Planning appliqué aux migrations : investir ~20 % du temps total à planifier pour éliminer ~80 % des fausses pistes. Concrètement, avant de lancer l’agent en mode modification :
- Inventorier les points de rupture — faire lister par l’agent toutes les API dépréciées, les breaking changes du changelog, les dépendances impactées.
- Classifier par risque — distinguer les changements mécaniques (renommage d’import, signature modifiée) des changements sémantiques (nouveau comportement par défaut, sérialisation différente).
- Définir l’ordre de migration — commencer par les couches basses (packages, configuration), puis les adaptateurs, puis le domaine si nécessaire.
- Fixer les critères de succès — quels tests doivent passer à chaque étape, quels comportements doivent être préservés.
Attention — ne pas laisser l’agent planifier et exécuter dans le même souffle. Si on lui dit « migre de .NET 6 à .NET 8 », il va commencer à modifier des fichiers immédiatement. Séparer explicitement la phase plan (lecture seule) de la phase exécution (modifications).
Incrémental vs big-bang
Une migration big-bang tente de tout basculer d’un coup : on change le TFM, on met à jour tous les packages, on corrige toutes les erreurs de compilation en une session. C’est tentant avec un agent rapide, mais c’est un piège : si quelque chose régresse, on ne sait plus quelle modification en est la cause.
La voie incrémentale découpe la migration en étapes vérifiables :
- Étape 1 — Mettre à jour le TFM et les packages, sans toucher au code. Vérifier que ça compile.
- Étape 2 — Corriger les breaking changes mécaniques (renommages, signatures). Relancer les tests.
- Étape 3 — Traiter les changements sémantiques un par un, avec un test dédié pour chacun.
- Étape 4 — Nettoyer les workarounds et le code de compatibilité devenu inutile.
Chaque étape produit un commit propre et un build vert. Si une régression apparaît, on sait exactement où chercher.
Point clé : En architecture hexagonale, la migration est naturellement contenue : on migre d’abord les adaptateurs (infrastructure), puis on vérifie que le domaine n’est pas impacté. Les ports isolent le blast radius.
Les tests comme filet de migration
Les tests existants sont le meilleur allié d’une migration assistée. Ils servent d’oracle : si le code migré passe les mêmes tests qu’avant, le comportement est préservé. C’est le principe de la boucle fermée (Closed-Loop Prompting) appliqué à la migration : l’agent modifie, exécute les tests, corrige si rouge, recommence.
Mais attention aux pièges :
- Tests qui passent par accident — un test mocké à l’excès valide la structure mais pas le comportement réel avec le nouveau framework.
- Tests absents sur les zones critiques — si la sérialisation JSON n’est pas testée et que le nouveau framework change les conventions de nommage, la régression passe inaperçue.
- Tests qu’il faut migrer eux-mêmes — si les tests utilisent des API du framework qu’on migre, il faut les migrer en premier et les valider manuellement avant de s’en servir comme oracle.
Attention — règle ZTE pour les migrations : vérifier chaque étape explicitement. « Ça compile » n’est pas « ça marche ». Exiger un build vert ET les tests au vert à chaque incrément, pas seulement à la fin.
Modes de défaillance courants
Voici les échecs les plus fréquents quand un agent exécute une migration sans cadrage suffisant :
| Mode de défaillance | Cause | Parade |
|---|---|---|
| Changement comportemental silencieux | Nouvelle version change un défaut (sérialisation, null handling, encodage) | Tests de caractérisation sur les frontières avant migration |
| Dependency hell | Mise à jour en cascade non maîtrisée | Mettre à jour un package à la fois, build entre chaque |
| Migration incomplète | L’agent oublie des fichiers (config, scripts, CI) | Checklist exhaustive en phase plan + grep post-migration |
| Tests migrés et code en même temps | L’oracle est modifié pendant qu’on s’en sert | Migrer les tests d’abord, valider, puis migrer le code |
| Scope creep | L’agent « améliore » le code en migrant | Interdire explicitement tout refacto pendant la migration |
Point clé : La discipline clé : une migration ne fait que migrer. Tout refacto, toute amélioration, tout nettoyage doit attendre un commit séparé après la migration validée. Mélanger migration et refacto rend les régressions introuvables.