Auto-miglioramento ricorsivo dei linguaggi: il grind della Code Intelligence su ~280 linguaggi
> Supportiamo la Code Intelligence per ~280 linguaggi. Nessun essere umano può controllarli a mano uno per uno. Così abbiamo costruito un loop di auto-miglioramento ricorsivo dei linguaggi — campionamento, LLM come giudice, correggi una cosa, rivalida — e lo facciamo girare con una flotta di agenti isolati finché l'estrazione non è davvero corretta, non solo verde.
I numeri in questo articolo riflettono il sistema al momento della pubblicazione (maggio 2026). Consulta la nostra pagina del team per le cifre attuali.
Maguyva estrae simboli, riferimenti e un grafo delle dipendenze dal codice sorgente in circa 280 linguaggi. Ogni linguaggio è un handler tree-sitter su misura — query, euristiche, casi limite — e ogni handler può essere sottilmente sbagliato a modo suo. Una chiamata a metodo emessa come una lettura. Una funzione attribuita allo scope contenitore sbagliato. Una relazione che semplicemente non esiste.
Questo non lo puoi controllare a mano. Nessun team può leggere l’output di estrazione su 280 grammatiche e individuare gli edge sbagliati. Quindi la domanda interessante non è “la nostra estrazione è corretta” — è “come scopri che è sbagliata, a questa ampiezza, senza un essere umano in ogni loop.” La nostra risposta è l’auto-miglioramento ricorsivo dei linguaggi: un loop di qualità guidato da agenti linguistici, un LLM che agisce da giudice, e una regola che continuiamo a reimparare: verde non è lo stesso di corretto.
Verde non è corretto
Ogni linguaggio ha una suite di fixture, e un gate di rilascio lo valuta su cinque dimensioni — accuratezza, integrità strutturale, completezza, qualità e performance. Un linguaggio diventa VERDE solo quando, sulle sue fixture, precisione ≥ 0,95, recall ≥ 0,99, e F1 ≥ 0,97, con almeno 20 edge attesi per confidenza statistica. Sotto quella soglia è GIALLO o ROSSO, e non viene rilasciato.
Quel gate è necessario ma non sufficiente. Le fixture validano contro fixture che abbiamo scritto noi. Codificano i casi a cui abbiamo già pensato. Un handler può essere impeccabile sulle sue fixture e comunque devastare un pattern che compare solo nel codice reale — un idioma da macro, un metodo con vincolo generico, una feature del linguaggio per cui nessuno ha scritto una fixture. VERDE significa che le fixture passano. Non significa che un repository reale venga estratto in modo pulito. Quindi il loop deve lasciarsi alle spalle le fixture e guardare al selvaggio.
Il loop interno: campiona, giudica, correggi, dimostra
Il loop centrale gira un linguaggio alla volta:
┌──────────────────────────────────────────────────────────┐
│ │
▼ │
1. corpus run ── clone real-world repos, extract relationships │
│ │
▼ │
2. spot-check 100 edges (seed 42, then seed 123 to cross-check) │
│ │
▼ │
3. LLM judge classifies every sampled edge: │
CORRECT · FALSE_POSITIVE · TYPE_ERROR · │
SCOPE_ERROR · METADATA_ERROR │
│ │
▼ │
4. fix ONE thing — handler .py, .scm query, or config │
│ │
▼ │
5. re-validate — F1 + re-classify + manifest diff (no regressions)│
│ │
better? ──no──► revert, try a different fix ────────────────────┤
│ yes │
▼ │
6. promote the fix into fixtures (a permanent regression guard) ──┘
Alcune cose fanno funzionare tutto questo invece di farlo arrancare a vuoto.
Il giudice è l’agente, non una chiamata API. Quando diciamo “LLM come giudice”, intendiamo che l’agente linguistico stesso legge ogni edge campionato contro il codice sorgente reale e lo classifica con una rubrica fissa a cinque categorie: questo edge è corretto, un falso positivo, la relazione giusta con il tipo sbagliato, attaccato allo scope sbagliato, o porta metadati sbagliati? Quella rubrica è tutto il gioco — “23% di tasso di errore” non significa nulla finché non sai se sono difetti reali o il giudice che conta male.
Correggi una cosa, poi dimostralo. Ogni iterazione modifica esattamente un asset modificabile, poi esegue di nuovo contro un harness fisso e mantiene la modifica solo se F1 migliora e la riclassificazione sembra migliore. Se non è così, va in rollback. Nessun lotto di modifiche speculative, nessun “dovrebbe essere meglio”. Una modifica si guadagna il suo posto o sparisce. E quando una correzione regge, viene promossa nella suite di fixture — così il bug che ha corretto non può mai tornare silenziosamente. Quel passaggio di promozione è ciò che rende il loop ricorsivo invece di semplicemente ripetitivo: ogni passata rafforza l’oracolo contro cui la passata successiva valida.
La lezione che continuiamo a reimparare: le metriche sovrastimano
Ecco la trappola, e ci siamo caduti dritti. Le metriche secondarie del corpus — con che frequenza un target estratto non ha un simbolo risolvibile, quanti simboli sembrano “orfani”, e così via — sovrastimano enormemente i problemi. Sono per lo più artefatti del paradigma, non bug.
L’esempio più pulito: llvm una volta mostrava un tasso del 73% di “sorgente senza simbolo” e fu bollato come catastrofico. Abbiamo scavato. L’accuratezza reale era del 98,5%. I “simboli mancanti” erano quasi tutti riferimenti esterni legittimi — chiamate nella libreria standard, in framework, in codice che vive fuori dal repository. La metrica stava misurando una proprietà del linguaggio, non un difetto dell’handler. Linguaggi come Zig, COBOL e Odin mostrano tassi di “orfani” del 65-70% e sono completamente corretti; COBOL aveva zero errori reali.
Se avessimo lasciato che quei numeri guidassero il lavoro, avremmo passato settimane a “correggere” handler già corretti e ignorando i linguaggi con bug reali e silenziosi. La conclusione è netta: le metriche aggregate sono al massimo un rozzo segnale di triage. Il vero segnale di qualità è il controllo a campione con classificazione degli edge — guardare gli edge reali in repository reali e giudicarli uno per uno. Dati sopra l’intuizione, ma solo una volta che sai quali dati dicono la verità.
Il loop esterno: una flotta, non una maratona
Un linguaggio alla volta ci vorrebbe un’eternità su 280 di essi, quindi il loop interno è avvolto in uno esterno che ne fa girare molti in parallelo.
pick a wave of near-GREEN / high-error languages
│
▼
fan out 10–15 agents, each ISOLATED in its own git worktree,
each grinding ONE language, committing to its own branch
│
▼
orchestrator integrates serially: file-scoped apply, then
`manifest diff` — any cross-language regression blocks the batch
│
▼
gated push (reviewed and confirmed) ──► rotate to the next wave
Ogni agente lavora in un worktree usa-e-getta così da non pestarsi i piedi a vicenda. L’orchestratore integra le loro correzioni una alla volta, ciascuna dietro un controllo di regressione a manifest completo: una modifica che aiuta il suo linguaggio ma silenziosamente ne rompe altri tre non viene integrata. L’integrazione è vincolata e confermata prima che qualcosa venga pushato — il gate di regressione decide cosa è sicuro, un essere umano decide ancora cosa viene rilasciato. Poi il pool ruota verso il prossimo gruppo di linguaggi e tutto il processo si ripete.
Cosa resta imperfetto
Il giudice può sbagliare, e l’errore ha una direzione: un agente che gira con troppo poco contesto sovrastima. In un lotto, otto linguaggi sono stati segnalati con un errore del 5-20%; all’ispezione solo uno era un vero bug specifico del linguaggio — il resto erano errori del giudice dovuti a non aver colto la semantica propria del linguaggio (una riga sorgente che legittimamente emette più edge, binding di parametri modellati come assegnazioni, linguaggi con riferimento-per-identificatore). Ecco perché campioniamo con due seed e facciamo cross-check, e perché un disaccordo tra il giudice e le fixture è trattato come il segnale più interessante, non un verdetto definitivo — a volte è la fixture a essere sbagliata.
Siamo anche onesti sull’obiettivo. Il traguardo è zero errori reali, punto e basta — ma “zero” è una direzione verso cui maciniamo, linguaggio per linguaggio, non una casella da spuntare. C’è sempre un altro repository con un altro idioma.
Guadagnato, non asserito
Tutto ciò che Maguyva fa per un agente — trovare un simbolo, tracciare una dipendenza, rispondere a una domanda con codice citato — poggia sul fatto che l’estrazione sottostante sia corretta. Su 280 linguaggi, “corretto” non può essere asserito; deve essere continuamente guadagnato contro codice reale. Il loop è come lo guadagniamo: un ciclo autonomo di campionamento-e-correzione che tratta le proprie metriche con sospetto, dimostra ogni modifica, e trasforma ogni correzione in una guardia contro la prossima regressione. Non è affascinante. È il lavoro che ci permette di dire “supportiamo il tuo linguaggio” e intenderlo davvero. Verde è facile. Corretto è guadagnato.
Letture correlate
Altro dal diario di costruzione di Maguyva
Perché abbiamo aggiornato la ricerca sul codice a voyage-4-large_
Abbiamo spostato i nostri embedding del codice su voyage-4-large — attualmente in cima alla classifica pubblica RTEB per il retrieval di codice. La versione onesta: il compromesso che facciamo, cosa indicizziamo davvero, e perché paghiamo per embedding premium.
Ricerca a fusione multi-modale: scegliere il retriever giusto per ogni query_
Una query come 'dove è definito parseConfig' vuole una ricerca diversa da 'come funziona l'auth'. Maguyva classifica l'intento, pesa di conseguenza quattro modalità di retrieval, e fonde i risultati con una Reciprocal Rank Fusion pesata.
Osservabilità degli agenti: hook, Alloy e Grafana_
Abbiamo collegato Claude Code e Codex a un unico stack Grafana con OpenTelemetry e Alloy, poi abbiamo usato trace e log per trovare e correggere i problemi di comportamento degli agenti alla fonte.