Nell'ultimo output generato da Claude Code per la nostra migration SQL il problema non è nel codice generato ma in quello che l'agente non ha considerato.
Cosa ha tralasciato Claude Code
La tabella tickets contiene dati esistenti. Aggiungere una colonna JSONB con un default significa che tutti i record esistenti riceveranno quel default automaticamente, e fin qui nessun problema. Ma aggiungere un check constraint su una tabella con dati esistenti significa che PostgreSQL verificherà il constraint su tutti i record al momento dell'esecuzione dell'ALTER TABLE.
Se esistesse anche un solo record con un campo metadata già presente che non rispetta il constraint, per esempio perché era stato inserito manualmente in precedenza senza seguire la struttura, la migration fallirebbe a runtime con un errore che blocca l'intero deploy.
Claude Code non ha menzionato questo rischio. Non ha suggerito di aggiungere il constraint con NOT VALID, una clausola PostgreSQL che aggiunge il constraint senza validarlo sui dati esistenti, delegando la validazione a un successivo VALIDATE CONSTRAINT che può essere eseguito in modo non bloccante, né ha proposto di verificare preventivamente l'esistenza di record non conformi prima di eseguire la migration.
Su un database di sviluppo o staging con pochi record, questa omissione non produce nessun sintomo. Su un database di produzione con anni di dati, potrebbe trasformare un deploy di routine in un incidente.
Il pattern che emerge: cosa sa fare e cosa non vede
Guardando le tre migration nel loro insieme, emerge un pattern abbastanza netto che vale la pena articolare con perché è utile per calibrare come usare Claude Code su questo tipo di task.
L'agente conosce in modo molto accurato la sintassi di Laravel e le API di Schema Builder, i pattern convenzionali del framework (relazioni polimorfiche, convenzioni di naming, struttura dei file di migration..) e le funzionalità avanzate di PostgreSQL quando sono direttamente rilevanti per il requisito descritto, come nel caso del JSONB. Su questi fronti, l'output è spesso corretto alla prima iterazione e talvolta più completo dei requisiti originali, grazie all'aggiunta di dettagli (lo slug sui tag, il rollback coerente, il cast esplicito) che derivano dalla conoscenza del dominio.
Quello che l'agente non vede è la dimensione temporale del database. Uno schema non è uno stato statico, è il risultato di anni di migration successive, con dati che si sono accumulati seguendo le regole di ogni versione precedente. Ogni modifica su un database in produzione ha implicazioni sui dati esistenti che non sono visibili guardando solo lo schema corrente. L'agente legge lo schema come se fosse un progetto verde, e genera migration che sarebbero perfette su un database vuoto ma che possono fallire o, peggio, produrre regressioni silenziose su un database reale.
Un agente che legge i file dello schema non ha accesso ai dati, non può interrogare il database, non sa quanti record esistono, non conosce la distribuzione dei valori. Quelle informazioni richiedono un essere umano con accesso al database di produzione, o almeno a un dump statisticamente rappresentativo.
Come usare Claude Code sulle migration in modo affidabile
L'esperimento non porta alla conclusione che Claude Code sia inutile per scrivere migration SQL. La qualità media dell'output è genuinamente alta, e su molti task standard il codice generato è direttamente utilizzabile. Porta alla conclusione più sfumata che la review di una migration generata dalla AI richiede competenze diverse rispetto alla review di una migration scritta da un "collega umano".
Con un collega umano, la review si concentra sulla correttezza logica e sulla coerenza con l'architettura. Con una migration generata da un agente, la review deve coprire anche le assunzioni implicite. Ad esempio cosa ha deciso senza dirlo, cosa ha ottimizzato senza chiedere, cosa ha ignorato perché non visibile nello schema statico. È un tipo di lettura critica che richiede di pensare non solo a cosa fa il codice, ma a cosa non fa e perché.
Il modo più produttivo di usare Claude Code su questo tipo di task è fornire contesto esplicito su ciò che l'agente non può inferire dallo schema. Il volume approssimativo dei dati, i pattern di accesso più frequenti, i constraint di integrità che esistono per ragioni di business e non devono mai essere rimossi, le limitazioni dell'ambiente di deployment, per esempio se le migration vengono eseguite durante una finestra di manutenzione o in zero-downtime.
Ogni informazione aggiuntiva che si fornisce riduce lo spazio delle assunzioni silenziose e aumenta la probabilità che il codice generato sia corretto anche nel contesto specifico del progetto.
Un agente che lavora con più contesto produce migration migliori. Ma la responsabilità di fornire quel contesto e di verificare che le migration risultanti rispettino le invarianti del sistema rimane dello sviluppatore che conosce il database, i dati e le conseguenze di ogni modifica strutturale in produzione.
Se vuoi aggiornamenti su Quando Claude Code tralascia qualcosa inserisci la tua email nel box qui sotto: