# Des workflows sûrs de migration de bases de données pour les agents de programmation IA

Les modifications apportées à une base de données de production nécessitent un processus différent de celui des simples changements de code. Un agent de programmation IA peut inspecter un schéma, suivre les requêtes de l'application et préparer des fichiers de migration plus vite que la plupart des équipes ne peuvent organiser une revue. Cette rapidité ne doit pas lui donner l'autorisation de modifier la production parce qu'un prompt contenait par hasard le mot « deploy ».

Les workflows sûrs de migration séparent la planification de l'autorité. L'agent peut préparer les éléments de preuve et un ensemble précis de modifications. Une personne peut examiner les conséquences opérationnelles, vérifier que la récupération fonctionne et approuver une seule exécution limitée. Cette séparation évite l'échec classique où un `ALTER TABLE` apparemment inoffensif bloque le parcours de paiement, déclenche une réécriture incontrôlée ou produit un déploiement à moitié terminé que personne ne sait expliquer.

Cet article utilise des commandes PostgreSQL parce que son comportement en matière de verrous et de transactions est décrit explicitement dans sa documentation. Le processus s'applique à d'autres bases relationnelles, mais ne copiez pas la syntaxe ni les hypothèses de PostgreSQL dans un autre moteur sans consulter sa documentation.

## Les changements de production doivent avoir une autorité distincte de la génération de code

Un fichier de migration et une migration en production sont deux actions différentes. Le premier décrit une intention. La seconde mobilise une autorité rare sur un système actif, avec des utilisateurs, de la réplication, des sauvegardes et des versions d'application qui peuvent ne pas être compatibles entre elles.

Les équipes commettent souvent l'erreur d'accorder à un agent une seule connexion générale à la base de données, parce que cela simplifie le développement local. Cette connexion finit par traverser les environnements, et l'agent ne peut plus distinguer un nom d'hôte de préproduction d'un cluster de production si les deux acceptent les mêmes identifiants. Pire encore, un agent capable d'exécuter du SQL arbitraire n'a aucune raison naturelle de s'arrêter avant une réécriture de table. Il voit une tâche et un outil.

Donnez au travail des phases distinctes, avec des entrées et des permissions différentes :

1. La découverte lit les métadonnées du schéma, l'historique des migrations, le code des requêtes et les contraintes opérationnelles.
2. La planification produit le SQL, le comportement attendu des verrous, les effets sur les données, les contrôles préalables, les requêtes de vérification et une décision de récupération.
3. La revue confirme que le plan correspond à l'état réel de la production et que l'organisation accepte le risque.
4. L'exécution applique un artefact approuvé à une cible nommée.
5. La vérification prouve que l'application et la base de données ont atteint l'état prévu avant que quiconque ne considère le déploiement comme terminé.

La distinction utile est celle entre *réversibilité* et *récupérabilité*. Ajouter une colonne nullable est généralement réversible : une instruction ultérieure peut la supprimer si aucun code n'en dépend. Modifier des millions de lignes avec une expression incorrecte peut ne pas être réversible, même si quelqu'un écrit une mise à jour inverse en apparence. Vous ne saurez peut-être pas quelles valeurs d'origine ont été écrasées. La récupérabilité signifie que vous disposez d'une méthode testée pour restaurer le système ou limiter les dégâts. Traitez ces deux notions comme des champs distincts dans chaque plan de migration.

Un agent ne doit jamais déduire une autorité de production d'une branche de dépôt, d'une étiquette de ticket ou d'une variable d'environnement fournie dans un prompt. Ces signaux décrivent une intention, et l'intention est souvent erronée. L'exécution doit exiger une cible sélectionnée en dehors du contexte textuel de l'agent, un artefact préparé dont l'empreinte est enregistrée et une personne qui voit exactement ce qui va être exécuté.

## Faites du plan de migration un artefact vérifiable

Un plan vérifiable donne à l'opérateur suffisamment d'informations pour refuser une migration avant qu'elle n'atteigne la base de données. « Ajouter un index » n'est pas un plan. La taille de la table, l'objectif de la requête, la forme de l'index, la contrainte transactionnelle, l'exposition aux verrous et la requête de vérification en font un plan.

Demandez à l'agent de produire un répertoire contenant des fichiers fixes plutôt qu'un paragraphe dans une pull request. Par exemple :

```text
migrations/2025-04-add-orders-status-index/
  up.sql
  verify.sql
  preflight.sql
  recovery.md
  manifest.json
```

Le manifeste doit associer les fichiers à la cible prévue et indiquer ce que l'agent a appris. Cet exemple n'expose aucun identifiant et ne prétend pas qu'une sauvegarde existe simplement parce que quelqu'un en a demandé une.

```json
{
  "migration_id": "2025-04-add-orders-status-index",
  "engine": "postgresql",
  "target": "production-orders",
  "change": "create index for filtered order status query",
  "transaction_mode": "outside_transaction",
  "requires_backup_restore_check": true,
  "expected_write_blocking": "none during index build",
  "stop_conditions": [
    "target schema differs from preflight result",
    "backup restore check fails",
    "index is invalid after execution"
  ]
}
```

Une personne qui effectue la revue doit pouvoir répondre à cinq questions grâce à cet artefact :

- Quelle base de données et quel schéma recevront la modification ?
- Quel SQL exact sera exécuté, et l'outil d'exécution l'entoure-t-il d'une transaction ?
- Quelle opération va bloquer, réécrire des données, effectuer un scan ou consommer davantage d'espace ?
- Quelle preuve montre que la base peut être récupérée si la modification échoue ?
- Quelles requêtes ou quels signaux applicatifs prouvent la réussite ?

Demandez à l'agent d'indiquer ses incertitudes. S'il ne peut pas établir la version de PostgreSQL, la taille de la table, la version actuelle des migrations ou la plage de compatibilité de l'application appelante, il doit le signaler comme une condition d'arrêt. Inventer un niveau de confiance à partir d'un accès partiel au dépôt est pire que laisser un point ouvert.

Rendez le SQL généré immuable après la revue. Si une personne modifie `up.sql`, régénérez la somme de contrôle et renvoyez l'artefact en revue. Un échec fréquent commence par une migration revue, suivie d'une « petite correction » faite dans la précipitation dans le shell de déploiement. La commande réelle n'est alors plus celle qui a été revue, tandis que l'audit raconte une histoire rassurante mais fausse.

## Classez l'opération avant de décider comment l'exécuter

Le verbe SQL ne suffit pas à déterminer le risque opérationnel. `ALTER TABLE` couvre des changements qui se terminent rapidement et d'autres qui prennent des verrous ou réécrivent suffisamment de données pour remplir l'espace disque. Un processus sûr classe l'opération réelle, la version de la base, la taille de la table et la charge concurrente avant de choisir un chemin d'exécution.

La documentation PostgreSQL consacrée à `ALTER TABLE` expose un point délicat : de nombreuses formes acquièrent un verrou `ACCESS EXCLUSIVE`, sauf indication contraire dans la documentation. Ce verrou entre en conflit avec les lectures et les écritures. « Cela a été rapide en préproduction » ne veut pas dire grand-chose si cet environnement n'a ni transactions longues, ni trafic de rapports, ni volume de données comparable.

Utilisez quatre catégories pratiques :

| Catégorie | Exemple courant | Attente d'exécution |
|---|---|---|
| Métadonnées uniquement | Ajouter une colonne nullable sans valeur par défaut | Opération courte, mais vérifiez le comportement des verrous pour votre version |
| Création concurrente | Créer un nouvel index | Forme de commande particulière et gestion séparée des transactions |
| Modification des données par lots | Remplir une nouvelle colonne | Petites validations, débit mesuré, progression reprenable |
| Réécriture ou modification destructive | Modifier le type d'une grande colonne ou supprimer des données | Décision de maintenance avec plan de récupération explicite |

Ne qualifiez pas de sûre toute opération en ligne. `CREATE INDEX CONCURRENTLY` de PostgreSQL évite de bloquer les écritures pendant sa construction, comme l'indique la documentation de `CREATE INDEX`. La commande prend aussi plus de temps, ne peut pas s'exécuter dans un bloc transactionnel et peut laisser un index invalide après un échec. Le conseil courant « utilisez toujours concurrently » ignore ces conditions. Utilisez cette forme lorsque la disponibilité des écritures compte et que votre outil de migration sait gérer ses règles.

Une requête de planification peut donner à la personne chargée de la revue une première estimation utile de la taille de la table et des index :

```sql
SELECT
  pg_size_pretty(pg_total_relation_size('public.orders')) AS total_size,
  pg_size_pretty(pg_relation_size('public.orders')) AS table_size,
  pg_size_pretty(pg_indexes_size('public.orders')) AS indexes_size;
```

Le résultat attendu contient une ligne avec trois valeurs de taille lisibles. Considérez-le comme un indicateur de dimensionnement, pas comme une promesse de durée. La largeur des lignes, l'état du cache, les écritures concurrentes, la réplication, le débit du disque et les transactions actives changent tous le résultat.

L'agent doit aussi rechercher les blocages avant une opération exposée de manière significative aux verrous. PostgreSQL expose les sessions actives dans `pg_stat_activity`, mais cela ne vous autorise pas à les interrompre. Le plan doit nommer le responsable de toute charge longue et préciser si la migration attend, est replanifiée ou bénéficie d'une fenêtre de maintenance.

## Une sauvegarde restaurée est le ticket d'entrée

Une commande de sauvegarde réussie prouve qu'un programme a écrit un fichier. Elle ne prouve pas que ce fichier peut être restauré, qu'il contient les objets nécessaires ou que la procédure de restauration fonctionne sous pression. Effectuez une vérification de restauration avant tout travail destructif ou difficilement réversible.

Pour une base PostgreSQL, un dump logique au format personnalisé peut ressembler à ceci :

```sh
pg_dump -Fc -d "$SOURCE_DATABASE" -f "orders-preflight.dump"
pg_restore -l "orders-preflight.dump" | sed -n '1,12p'
createdb migration_restore_check
pg_restore -d migration_restore_check "orders-preflight.dump"
psql -d migration_restore_check -c "SELECT count(*) FROM public.orders;"
```

La commande d'affichage doit imprimer des entrées d'archive comme une définition de table, une entrée de données de table et des définitions d'index. La dernière requête doit afficher un résultat à une colonne contenant le nombre de lignes restaurées. Enregistrez le résultat de la commande, l'identifiant du dump, la cible de restauration et le résultat du contrôle dans le dossier de migration. N'y placez ni URL de base de données ni mot de passe.

Une vérification de restauration logique ne remplace pas un test de récupération physique, une restauration à un instant donné, un exercice de promotion de réplica ou l'assurance de sauvegarde d'un fournisseur. Elle répond à une question plus limitée : ce dump peut-il être restauré dans une base de données et produire les objets et la forme de données attendus ? Cette réponse limitée permet tout de même de détecter les archives endommagées, les extensions manquantes, les problèmes de rôles et les procédures qui ne fonctionnaient que sur l'ordinateur de leur auteur.

Choisissez la méthode de récupération avant l'exécution, pas après l'erreur. Le plan doit indiquer laquelle de ces situations s'applique :

- Une migration inverse est sûre parce qu'aucune donnée n'a été supprimée et que l'application peut tolérer le retour en arrière.
- Une restauration dans une base de remplacement est la voie de récupération, avec la personne qui décide du basculement.
- Une procédure de récupération par réplica ou fournisseur est la voie retenue, avec un objectif de point de récupération documenté.
- La modification ne peut pas être récupérée proprement. Elle nécessite donc une fenêtre de maintenance et une acceptation explicite.

Cette dernière catégorie est légitime. Prétendre qu'une restauration existe parce que le modèle de déploiement exige un champ ne l'est pas. J'ai vu des équipes écrire `DROP COLUMN` comme restauration d'un remplissage qui avait modifié les données client, puis découvrir que supprimer la nouvelle colonne ne faisait qu'effacer leurs preuves tandis que les anciennes valeurs restaient erronées.

## Étendez d'abord, supprimez ensuite

La plupart des changements de schéma destinés à l'application doivent rester compatibles avec plusieurs versions applicatives en circulation. Pendant un déploiement, les anciens et les nouveaux processus peuvent fonctionner ensemble parce que les workers se vident lentement, que les utilisateurs gardent des requêtes ouvertes ou qu'une restauration relance une ancienne version. Une migration qui suppose une version d'application unique et instantanée transforme un comportement normal du déploiement en panne.

Supposons que vous deviez remplacer `orders.status_text` par un `orders.status_code` contraint. La version dangereuse ajoute la nouvelle colonne, réécrit chaque ligne, modifie le code de l'application et supprime l'ancienne colonne en une seule livraison. Elle comporte plusieurs points de défaillance et aucun endroit calme où s'arrêter.

Utilisez plutôt une séquence d'extension et de contraction :

1. Ajoutez `status_code` comme colonne nullable et ajoutez les structures nécessaires qui ne perturbent pas l'application actuelle.
2. Déployez un code applicatif qui lit le nouveau champ lorsqu'il existe et écrit dans les deux champs, ou qui dérive l'un de manière sûre à partir de l'autre.
3. Remplissez les lignes existantes par lots limités, en enregistrant la progression en dehors du contexte de conversation temporaire de l'agent.
4. Vérifiez que toutes les lignes respectent le nouvel invariant et que les lecteurs utilisent le nouveau champ.
5. Dans une livraison ultérieure, arrêtez d'écrire dans l'ancien champ, attendez la période de conservation convenue, puis supprimez-le.

La boucle par lots est importante. Un `UPDATE` unique et massif conserve les ressources trop longtemps, produit un pic de journaux de transactions, sollicite les réplicas et rend la récupération plus difficile à raisonner. Une requête limitée donne à l'opérateur un moment entre deux validations pour examiner le retard de réplication, le taux d'erreur et la charge de la base.

Ce modèle PostgreSQL met à jour un lot sélectionné par clé primaire et renvoie les lignes modifiées :

```sql
WITH batch AS (
  SELECT id
  FROM public.orders
  WHERE status_code IS NULL
  ORDER BY id
  FOR UPDATE SKIP LOCKED
  LIMIT 500
)
UPDATE public.orders AS o
SET status_code = CASE o.status_text
  WHEN 'new' THEN 10
  WHEN 'paid' THEN 20
  WHEN 'shipped' THEN 30
  ELSE NULL
END
FROM batch
WHERE o.id = batch.id
RETURNING o.id;
```

L'outil répète cette opération tant que des lignes sont renvoyées et que le mappage produit des valeurs acceptables. `SKIP LOCKED` peut convenir à un worker contrôlé parce qu'il évite d'attendre les lignes détenues par une autre transaction. Ce n'est pas la preuve que chaque ligne a été traitée. La requête de vérification doit rechercher les valeurs nulles restantes et les valeurs sources inattendues :

```sql
SELECT status_text, count(*)
FROM public.orders
WHERE status_code IS NULL
GROUP BY status_text
ORDER BY count(*) DESC;
```

Si cette requête renvoie une valeur inconnue, arrêtez-vous. Ne laissez pas un agent décider qu'un état de production inattendu peut devenir une valeur enum par défaut simplement parce qu'il veut terminer la tâche.

## L'exécution nécessite des conditions d'arrêt strictes et des commandes limitées

Une migration approuvée peut tout de même rencontrer un état de production différent de celui inspecté par le planificateur. L'outil d'exécution doit effectuer les contrôles préalables immédiatement avant l'exécution et s'arrêter en cas de désaccord. C'est ce qui rend un processus plus sûr qu'une procédure que quelqu'un suit de mémoire.

Utilisez un exécuteur dédié qui n'accepte qu'un identifiant d'artefact et un sélecteur de cible. Il doit refuser le SQL intégré collé depuis un terminal, rejeter un artefact dont la somme de contrôle a changé et afficher l'identité de la cible avant de commencer. Il peut exécuter d'abord le SQL préalable en lecture seule, puis exiger une approbation distincte pour la partie modificatrice.

Définissez explicitement les limites de temps de session. PostgreSQL documente `lock_timeout` et `statement_timeout` comme deux contrôles distincts. Un préambule raisonnable pour une courte opération sur les métadonnées pourrait être :

```sql
SET lock_timeout = '5s';
SET statement_timeout = '60s';
SELECT current_database(), current_user, now();
```

Ne reprenez pas ces valeurs sans réflexion pour les créations d'index ou les remplissages. Un délai d'expiration est un budget que le plan doit justifier. Si la commande nécessite trente minutes sous la charge prévue, un délai d'expiration d'instruction de soixante secondes ne fera que provoquer un échec prévisible. Pour une création d'index concurrente, utilisez un chemin d'exécution qui n'entoure pas la commande d'une transaction :

```sql
CREATE INDEX CONCURRENTLY IF NOT EXISTS orders_status_code_idx
ON public.orders (status_code);
```

Après cette commande, vérifiez l'index au lieu de déduire sa réussite de l'absence d'erreur du processus. PostgreSQL enregistre sa validité dans les métadonnées du catalogue, et une création concurrente échouée peut laisser un index invalide qu'il faut inspecter et supprimer avant une nouvelle tentative. Placez ce contrôle dans `verify.sql`, avec un plan de requête orienté vers l'application lorsque cela est pertinent.

Une véritable décision d'interruption nécessite des signaux nommés. Arrêtez l'exécution si les contrôles préalables trouvent une version de migration inattendue, un espace de stockage insuffisant, un blocage actif en dehors de la fenêtre autorisée, une restauration de sauvegarde échouée, une somme de contrôle incorrecte ou un résultat différent du prédicat de vérification. L'opérateur ne devrait pas avoir à négocier avec un agent pendant que l'attente d'un verrou s'allonge.

## L'approbation doit associer une personne à une seule exécution réelle

La fatigue liée aux approbations apparaît lorsque les systèmes demandent aux personnes d'approuver chaque appel SQL. Elles finissent par approuver machinalement ou désactiver les demandes. Une approbation unique au début d'un processus d'agent défini est utile lorsqu'elle identifie le processus, expire avec lui et ne couvre pas discrètement une autre session par la suite.

L'approbation doit afficher suffisamment de contexte pour permettre à une personne de refuser l'exécution : identité signée du processus, cible sélectionnée, identifiant de l'artefact, classe d'action prévue et indication que le canal d'action peut écrire. Elle ne doit pas afficher de mot de passe en clair ni demander à l'agent d'en manipuler un. La personne autorise l'action, pas la divulgation d'un secret.

Sallyport respecte cette limite en conservant les identifiants API et SSH dans son coffre chiffré, en permettant à un agent compatible avec MCP de demander des actions via `sp mcp` et en renvoyant les résultats des actions plutôt que les secrets en clair. Son approbation de session séparée et son approbation facultative par clé peuvent faire dépendre une action sur une base de production d'une décision humaine, sans placer d'identifiant réutilisable dans le contexte de l'agent.

Limitez l'approbation à la phase d'exécution. L'agent de découverte peut utiliser un chemin en lecture seule. L'agent d'exécution peut recevoir une session qui expire avec son processus et qui donne accès uniquement au chemin d'action approuvé. La révocation instantanée est importante, car l'opérateur doit pouvoir arrêter une exécution après un résultat préalable surprenant, et pas seulement après la fin du script de déploiement.

Ne remplacez pas une conception opérationnelle claire par un langage de politiques que votre équipe ne peut pas expliquer sous pression. La limite fiable est simple : un accès verrouillé refuse toutes les actions, un nouveau processus d'exécution exige une autorisation et les identifiants particulièrement sensibles peuvent exiger une nouvelle décision à chaque utilisation. C'est plus facile à auditer qu'un ensemble de règles déduites que personne ne se souvient avoir écrites.

## Les journaux d'audit doivent reconstituer la modification sans secrets

Après une migration échouée, les questions sont simples : qui l'a exécutée, sur quelle cible, quel artefact exact a été utilisé, quand s'est-elle arrêtée et a-t-elle modifié des données ? Une transcription générique du terminal répond rarement à toutes ces questions. Elle peut omettre la cible, perdre la commande après un nettoyage de l'historique du shell ou contenir des secrets qui n'auraient jamais dû être enregistrés.

Enregistrez des événements structurés pour la planification, l'approbation, les contrôles préalables, l'exécution, la vérification, la révocation et l'échec. Chaque événement doit inclure l'identifiant de migration et l'empreinte de l'artefact afin qu'un enquêteur puisse relier la revue à l'exécution réelle. Incluez l'identité de la base renvoyée par les contrôles préalables, plutôt que le seul nom demandé par l'appelant.

Une forme minimale d'événement ressemble à ceci :

```json
{
  "event": "migration.verify",
  "migration_id": "2025-04-add-orders-status-index",
  "artifact_sha256": "recorded-digest",
  "target_identity": "production-orders",
  "result": "passed",
  "observed": "index valid; query returned expected columns"
}
```

Évitez d'enregistrer les paramètres SQL lorsqu'ils peuvent contenir des données personnelles, des jetons ou du contenu client. Enregistrez plutôt l'empreinte de l'artefact et un identifiant d'instruction sans risque. Le système d'exécution peut conserver des diagnostics protégés selon une politique de conservation définie, mais un journal d'audit doit rester utile sans devenir un autre coffre à secrets.

La preuve d'altération change la qualité d'une enquête. Un enregistrement que quelqu'un peut modifier après un mauvais déploiement prouve seulement que quelqu'un avait accès à cet enregistrement. Si vous utilisez un journal d'audit chaîné par hachage, vérifiez-le indépendamment pendant l'analyse de l'incident. La commande `sp audit verify` de Sallyport vérifie hors ligne sa chaîne d'audit chiffrée sans nécessiter l'accès au coffre, ce qui est la propriété recherchée par une personne chargée de la revue qui ne doit pas recevoir les identifiants de production.

## La vérification doit tester la charge de travail, pas seulement le DDL

Une migration réussit lorsque la charge de travail prévue fonctionne correctement, pas lorsque la base accepte une instruction. Une nouvelle colonne peut exister alors que les écritures applicatives ne la renseignent pas. Un index peut être valide alors que la requête cible ne peut pas l'utiliser parce que son prédicat ou son type de données diffère. Une contrainte peut être valide alors qu'un ancien worker envoie encore des données qui violent le nouveau contrat applicatif.

Écrivez les requêtes de vérification avant l'exécution, pendant que les personnes chargées de la revue peuvent encore remettre leurs hypothèses en question. Pour une migration d'index, vérifiez l'état du catalogue et examinez la requête qui l'a motivée. Pour un remplissage, comptez les lignes restantes, regroupez les valeurs sources inattendues et confirmez que le nouveau chemin d'écriture applicatif produit la représentation attendue. Pour une contrainte, testez les écritures valides et invalides dans une base temporaire avant de demander à la production de l'appliquer.

`EXPLAIN` de PostgreSQL est utile, mais facile à mal employer. La décision du planificateur dépend des statistiques, des valeurs des paramètres, de la distribution des données et de la configuration. `EXPLAIN (ANALYZE, BUFFERS)` exécute la requête et la mesure, donc ne le lancez pas sans précaution sur une requête de production coûteuse. Utilisez-le sur une requête sûre et représentative, et définissez un résultat acceptable avant d'observer la sortie. Sinon, chaque plan devient quelque chose qu'un opérateur fatigué peut rationaliser.

Surveillez les indicateurs applicatifs en direct pendant et après la modification : taux d'erreur des requêtes, latence du chemin concerné, pression sur les connexions, santé de la réplication et échecs des workers. L'agent peut collecter et présenter ces mesures, mais le responsable de la livraison décide si elles respectent la condition de sortie définie.

Ne planifiez pas la contraction destructive simplement parce que le déploiement d'extension a réussi. Attendez que l'observabilité et l'historique des livraisons montrent que les anciens processus applicatifs ne dépendent plus de l'ancien schéma. Exécutez ensuite la suppression comme une migration revue séparément. Cette modification supplémentaire coûte moins cher que de découvrir pendant une restauration que l'ancienne version attend une colonne supprimée une heure plus tôt.

## La première exécution en production doit être volontairement ennuyeuse

La première migration de production assistée par un agent doit ajouter une modification à faible risque et observable, pas repenser une table sous charge. Choisissez une colonne nullable additive, un commentaire ou une autre opération dont vous comprenez déjà le comportement. Utilisez-la pour tester les limites : génération de l'artefact, sélection de la cible, approbation, preuve de sauvegarde, événements d'audit, échec du contrôle préalable, exécution et vérification.

Faites en sorte que l'exercice prouve que le système sait refuser une action. Dirigez l'exécuteur vers une cible dont l'empreinte de schéma est incorrecte et vérifiez qu'il s'arrête. Modifiez le fichier revu et vérifiez que le contrôle de l'empreinte le rejette. Révoquez l'autorisation pendant une exécution de test sans risque et vérifiez que les actions suivantes échouent. Ces tests montrent si les contrôles fonctionnent quand quelqu'un en a besoin, plutôt que de simplement sembler cohérents dans un document de conception.

Ensuite, élargissez une par une les catégories de migrations autorisées. Une équipe capable d'ajouter une colonne sans risque n'a pas démontré qu'elle sait remplir une grande table, créer un index concurrent ou récupérer après une mauvaise transformation des données. Chaque catégorie nécessite sa propre exécution observée et ses propres critères d'échec.

Considérez l'autorité de production comme quelque chose que l'agent emprunte pour une tâche étroite, puis perd. Cette habitude opérationnelle évitera plus de dégâts que toutes les instructions ingénieuses placées dans un prompt.
