Tradurre Cobol non è tradurre: l'architettura AI dietro la modernizzazione del codice legacy
Perché la conversione di applicativi legacy non è un problema di traduzione linguistica ma di ricostruzione semantica, e come abbiamo affrontato il problema in Scriba.

C’è un’affermazione che circola con insistenza nell’ultimo anno, e che merita di essere disinnescata prima di qualsiasi altra cosa: gli LLM moderni sono ormai in grado di convertire codice legacy in codice moderno. È l’implicito di ogni demo che mostra GPT o Claude trasformare un blocco Cobol in Python funzionante in tre secondi. È l’assunto dietro l’annuncio di Anthropic del febbraio 2026, quello che, in una sola giornata, ha fatto perdere a IBM il 13% in Borsa.
L’affermazione non è falsa. È incompleta in un modo che la rende, operativamente, non vera.
Un LLM generalista traduce un blocco di Cobol come traduce una poesia dal francese all’inglese: preservando il senso letterale riga per riga, perdendo sistematicamente ciò che quel blocco significa all’interno di un applicativo di trecentomila linee scritte da venti sviluppatori diversi nell’arco di trent’anni, con dipendenze implicite verso sistemi JCL, chiamate a sottoprogrammi di cui non esiste più documentazione, costanti hardcoded che codificano normative fiscali del 1994 ancora applicabili a un sottoinsieme di clienti. Il risultato è codice plausibile, compilabile, superficialmente corretto — e funzionalmente pericoloso.
Il problema della modernizzazione del legacy non è un problema di traduzione. È un problema di archeologia semantica: ricostruire l’intenzione di un sistema partendo dall’unico artefatto rimasto, il codice stesso, quando tutti gli altri (specifiche, documentazione, autori, contesto organizzativo) sono andati persi.
Questo articolo descrive l’architettura che abbiamo costruito in Scriba per affrontare questo problema. Non è una presentazione di prodotto. È una riflessione su cosa serve, strutturalmente, perché un sistema AI possa fare conversione di codice legacy in modo affidabile e perché un singolo modello frontier, per quanto capace, non è l’architettura giusta.
Il problema, nella sua forma reale
Prima di parlare di soluzioni, vale la pena di precisare cosa significa davvero codice legacy. Nel senso tecnico stretto, è codice scritto in linguaggi ormai marginali — Cobol, RPG, Fortran, PL/I, Natural, Assembler IBM, Pro*C — che continua a eseguire funzioni business-critical. Nel senso operativo, è qualcosa di più: è codice di cui si è perso il contesto.
Un applicativo bancario in Cobol, tipicamente, presenta tutte queste caratteristiche insieme:
- Stratificazione storica: porzioni scritte negli anni ’80, patchate negli anni ’90, estese negli anni 2000, ogni strato con convenzioni diverse e commenti nelle lingue e negli stili di chi ha lavorato in quel periodo.
- Dipendenze opache: chiamate a programmi esterni identificati solo da codici numerici, file di controllo letti da percorsi hardcoded, variabili di ambiente JCL che modificano il comportamento in modi non documentati.
- Logica di business implicita: regole che non sono scritte da nessuna parte nelle specifiche — perché le specifiche non esistono più, o non sono mai esistite — ma sono emergenti dall’interazione di decine di condizioni sparse nel codice.
- Ottimizzazioni deliberate ma oscure: pattern idiomatici del linguaggio (l’uso di
REDEFINESin Cobol, diOCCURS DEPENDING ON, di campi packed decimal) che hanno senso solo se si conosce la filosofia del linguaggio e i vincoli dell’hardware originale.
Prendere un file sorgente di questo tipo e passarlo in pasto a un LLM con il prompt “convert this to Java” è un’operazione che produce output sintatticamente valido con probabilità alta e semanticamente corretto con probabilità che non può essere stimata. E nei domini in cui Scriba opera, bancario, assicurativo, logistica, difesa, “non può essere stimata” è un sinonimo funzionale di “inaccettabile”.
La soluzione, quindi, non è un modello più grosso. È un’architettura che rende il problema trattabile.
Perché un singolo LLM non basta
C’è una tentazione, di fronte a un problema complesso che coinvolge linguaggio naturale e linguaggio di programmazione, di pensare che basti un modello sufficientemente capace. È la stessa tentazione che per anni ha dominato il dibattito sugli agenti AI: se GPT-4 non ci riesce, GPT-5 ci riuscirà. Gli ultimi due anni di lavoro applicato su sistemi agentici in produzione hanno mostrato che questa è la direzione sbagliata, e le ragioni sono tecniche, non ideologiche.
Il primo problema è di contesto. Un applicativo legacy reale non sta in una finestra di contesto. Un singolo modulo Cobol di medie dimensioni è sui duemila-cinquemila token; un applicativo completo può superare facilmente il milione. Anche con i modelli a contesto lunghissimo del 2026, la degradazione dell’attenzione su input estesi, il lost in the middle ormai documentato in decine di paper, rende impraticabile un approccio monolitico.
Il secondo problema è di specializzazione. Le sottoattività coinvolte nella conversione di codice sono qualitativamente diverse tra loro: identificare la struttura sintattica di un file Cobol, ricostruire il flusso di controllo, mappare le strutture dati su equivalenti moderni, rilevare idiomi peculiari del linguaggio di origine, scrivere codice idiomatico nel linguaggio di arrivo, generare test che verificano l’equivalenza comportamentale. Nessun singolo modello è ottimale su tutti questi compiti. Un LLM generalista è un buon generatore di codice target, ma è un mediocre parser di Cobol, perché i token Cobol sono sottorappresentati nel training e i suoi idiomi sono, per l’LLM, rumore statistico.
Il terzo problema è di verificabilità. Un sistema monolitico produce un output unico e opaco: funziona, o non funziona. Una pipeline articolata produce output intermedi ispezionabili (rappresentazioni intermedie, documentazione ricostruita, asserzioni esplicite sui contratti delle funzioni) che possono essere validati separatamente, corretti quando sbagliati, e che permettono di circoscrivere il danno quando qualcosa va storto.
Per queste tre ragioni, l’architettura di Scriba non è un modello. È un sistema.
Architettura: la pipeline
Scriba è strutturato come una pipeline di dieci stadi, ognuno dei quali incapsula una trasformazione ben definita sull’artefatto in lavorazione. Gli stadi sono sequenziali nel senso del flusso principale, ma ognuno ha la possibilità di richiedere un ritorno agli stadi precedenti quando rileva condizioni di incertezza. È, in questo senso, una pipeline con backtracking controllato, non un DAG puro.
Descrivo qui i cinque stadi concettualmente più rilevanti, raggruppando il resto per brevità.
Stadio 1: Parsing e rappresentazione intermedia
Il primo problema è ridurre il codice sorgente a una rappresentazione che non dipenda dal linguaggio specifico. Non usiamo un AST del linguaggio sorgente: un AST Cobol non si mappa a un AST Java, e qualunque tentativo di conversione AST-to-AST introduce perdite strutturali. Usiamo una rappresentazione intermedia di più alto livello, che cattura intenzioni semantiche anziché costrutti sintattici: “questa funzione legge un record da un file indicizzato e lo valida contro un insieme di regole di business”. Questa rappresentazione è estratta dal codice sorgente usando parser deterministici (per la struttura) e modelli AI specializzati (per la semantica delle porzioni che i parser non sanno classificare).
Il vantaggio di questo approccio è che il linguaggio target non entra mai in questa fase. La rappresentazione intermedia è la stessa per qualunque coppia sorgente-destinazione, e questo ci permette di supportare più di trenta linguaggi con un numero di combinazioni lineare, non quadratico.
Stadio 3: Ricostruzione della logica di business
Questo è lo stadio più delicato, e quello che distingue Scriba da un semplice transcompilatore. Dato il codice sorgente e la sua rappresentazione intermedia, il sistema cerca di ricostruire perché il codice fa quello che fa — non solo cosa fa.
La differenza è concreta. Un transcompilatore, davanti a una condizione IF CODICE-CLIENTE = 'X1' THEN PERFORM ROUTINE-SPECIALE, produce la versione equivalente nel linguaggio target e si ferma. Scriba cerca di rispondere a una domanda ulteriore: che cosa significa, in termini di business, il codice ‘X1’? La risposta “clienti istituzionali con contratti antecedenti al 2003, soggetti a una normativa fiscale specifica” potrebbe non essere ricostruibile dal solo codice, ma spesso è ricostruibile dal contesto: dal nome delle variabili circostanti, dai commenti sparsi in moduli correlati, dalla struttura della tabella dei clienti referenziata altrove.
Questo stadio usa modelli AI con prompting strutturato, ma non è un modello: è un processo iterativo in cui il sistema formula ipotesi, le verifica contro il resto del codebase, e le rivede quando trova evidenza contraria. Il risultato è una documentazione ricostruita, spesso la prima documentazione accurata che quell’applicativo ha mai avuto, che viene consegnata al cliente insieme al codice convertito.
Stadio 5: Generazione del codice target
Solo a questo punto interviene la generazione. E interviene non su tutto l’applicativo, ma funzione per funzione, con il contesto arricchito dalla rappresentazione intermedia, dalla logica di business ricostruita, dalle convenzioni idiomatiche del linguaggio target, e dalle specifiche del cliente (stile di codifica, framework utilizzati, pattern architetturali preferiti).
La generazione usa modelli AI di frontiera: qui un LLM è la scelta corretta, perché il compito è esattamente quello in cui questi modelli eccellono: produrre codice idiomatico in un linguaggio moderno dato un contesto ricco. Ma il prompt che riceve non è “convert this Cobol to Java”. È un documento strutturato che include la specifica funzionale ricostruita, i vincoli di interfaccia, gli esempi di chiamata attesa, e le linee guida di stile. È l’equivalente di un ticket di sviluppo ben scritto, non di una richiesta di traduzione.
Stadio 7: Generazione di test di equivalenza
Il codice generato, per quanto idiomatico, non ha valore se non è comportamentalmente equivalente all’originale. Questo stadio genera automaticamente una suite di test che confrontano l’output del codice originale e del codice nuovo su input sintetici generati a partire dalla struttura dei dati reali del cliente. È una forma di differential testing automatizzata, che diventa lo strumento principale di validazione.
Dove i test falliscono, il sistema non si limita a segnalare il problema: usa il fallimento come segnale per tornare agli stadi precedenti e rivedere l’ipotesi di conversione. È il meccanismo di backtracking controllato di cui parlavo sopra.
Stadio 9: Segnalazione degli hotspot irrisolvibili
Non tutto il codice legacy è convertibile in modo completamente automatico. Ci sono porzioni, tipicamente quelle che dipendono da comportamenti hardware specifici, o che implementano logiche di business di cui non esiste più alcuna traccia ricostruibile, che richiedono l’intervento umano.
Il valore architetturale di Scriba non è nel pretendere di convertire il 100% del codice automaticamente. È nel sapere quando non sa. Uno dei requisiti progettuali più importanti è che il sistema non produca mai silenziosamente codice plausibile ma sbagliato. Quando l’incertezza supera una soglia quantificabile, l’applicativo isola la porzione problematica, documenta le ipotesi che ha provato e fallito, e la segnala allo sviluppatore umano come hotspot da risolvere manualmente.
Questo è, dal punto di vista del cliente, il singolo vantaggio più importante rispetto all’uso di un LLM generalista. Un LLM non sa di non sapere: produce sempre un output. Scriba quantifica la propria incertezza e la rende visibile.
Il vincolo non tecnico che ha plasmato il sistema: private-AI
C’è un vincolo che non viene dalla teoria dell’architettura AI ma dalla realtà dei settori in cui operiamo: il codice dei clienti non può uscire dal perimetro del cliente. Una banca non invia il proprio core banking a OpenAI. Un’assicurazione non manda il sistema di gestione polizze a Anthropic. Una compagnia di difesa non fa nemmeno iniziare il discorso, se il discorso comincia con “allora, prima uploadate il codice sul nostro cloud”.
Questo vincolo ha una conseguenza architetturale radicale: Scriba deve poter operare on-premise, con modelli che girano dentro il perimetro del cliente. In pratica, questo significa che non possiamo appoggiarci esclusivamente a LLM frontier chiusi, e che la pipeline deve essere progettata per funzionare con una combinazione di modelli più piccoli, eseguibili su hardware ragionevole, più eventualmente un modello frontier chiamato solo sulle porzioni che davvero ne richiedono la potenza e chiamato in modalità che garantiscono la non-ritenzione dei dati.
Il vantaggio inatteso di questo vincolo è che ha forzato un’architettura migliore. Se fossimo potuti partire dall’assunzione “abbiamo accesso illimitato a GPT-5”, avremmo probabilmente costruito un sistema più pigro e meno strutturato. Il vincolo del private-AI ha reso necessaria la specializzazione, la modularità, la delegazione intelligente tra modelli di scale diverse e queste proprietà si sono rivelate virtuose anche dal punto di vista della qualità del risultato, non solo della conformità.
Ne ho scritto in termini più generali in Building Private AI Systems: il vincolo di sovranità dei dati, quando preso sul serio fin dall’inizio, produce architetture strutturalmente migliori di quelle nate in cloud.
Perché questo è un problema italiano, e perché questo conta
Chiudo con un’osservazione che esula dalla tecnica ma che ha pesato nelle scelte progettuali.
Il codice legacy è un problema globale, ma l’infrastruttura tecnologica italiana lo vive con un’intensità particolare. Le nostre banche, le nostre assicurazioni, la nostra pubblica amministrazione, la nostra logistica dipendono in misura sproporzionata da applicativi legacy scritti a partire dagli anni ’70 e ’80, spesso su mainframe IBM, spesso mai rimpiazzati perché i costi stimati della riscrittura sono sempre risultati superiori al valore percepito dell’operazione. È una dipendenza storica che ha mantenuto il Sistema Paese vincolato a un fornitore tecnologico e a un paradigma di sviluppo che hanno trent’anni più di noi.
Scriba è nato dalla collaborazione tra Algoretico, la società che ho fondato e di cui sono CEO, e Lagiste23, il family office di Marco Landi (ex Presidente di Apple Computer). Algoretico porta l’architettura tecnologica e la direzione di prodotto. Lagiste23 porta la visione industriale e la rete internazionale costruita in quarant’anni ai vertici del settore. Il CEO operativo è Franco Mastrorilli. Io guido la direzione AI.
L’ambizione non è costruire un prodotto migliore dei competitor americani. È dimostrare che il problema della modernizzazione del legacy può essere risolto con un’architettura AI progettata qui, che rispetti vincoli, sovranità dei dati, audit completo, operazione on-premise, che negli ambienti cloud-first tendono a essere trattati come costi da minimizzare anziché come requisiti di progetto.
La differenza tra un sistema che tratta la privacy come vincolo di mercato e uno che la tratta come requisito architetturale non è ideologica. È misurabile nella struttura del codice, nelle scelte di modello, nelle garanzie che puoi offrire a un CISO che sa leggere un DPIA. È la differenza tra fare prodotto e fare infrastruttura.
Scriba, per come è costruito, è dalla parte dell’infrastruttura.
— ✦ —
Il sito ufficiale di Scriba è scriba-ai.dev.


