Hoppa till innehåll
cd /blog

Rekursiv självförbättring för språk: att slita fram kodintelligens över ~280 språk

[Arkitektur][Språk][Agenter]

> Vi stöder kodintelligens för cirka 280 språk. Ingen människa kan granska det för hand. Så vi byggde en rekursiv självförbättringsloop för språk — stickprov, LLM som domare, fixa en sak, omvalidera — och kör den med en flotta av isolerade agenter tills extraktionen faktiskt är korrekt, inte bara grön.

Siffrorna i det här inlägget speglar systemet vid publicering (maj 2026). Se vår teamsida för aktuella siffror.

Maguyva extraherar symboler, referenser och en beroendegraf ur källkod på ungefär 280 språk. Varje språk har en skräddarsydd tree-sitter-hanterare — queries, heuristik, specialfall — och varje hanterare kan vara subtilt fel på sitt eget sätt. Ett metodanrop som avges som en läsning. En funktion som tillskrivs fel omslutande scope. En relation som helt enkelt inte finns.

Det går inte att granska för hand. Inget team kan läsa extraktionsutdata över 280 grammatiker och upptäcka de dåliga kanterna. Så den intressanta frågan är inte “är vår extraktion korrekt” — den är “hur tar man reda på att den är fel, i den här skalan, utan en människa i varje loop.” Vårt svar är rekursiv självförbättring för språk: en kvalitetsloop driven av språkagenter, en LLM som fungerar som domare, och en regel vi ständigt lär oss om igen: grönt är inte samma sak som korrekt.

Grönt är inte korrekt

Varje språk har en fixture-svit, och en releasegrind poängsätter den över fem dimensioner — noggrannhet, strukturell integritet, fullständighet, kvalitet och prestanda. Ett språk blir GRÖNT bara när precisionen är ≥ 0,95, recall ≥ 0,99 och F1 ≥ 0,97 på dess fixtures, med minst 20 förväntade kanter för statistisk tillförlitlighet. Under det är det GULT eller RÖTT, och det skeppas inte.

Den grinden är nödvändig men inte tillräcklig. Fixtures valideras mot fixtures vi själva skrivit. De kodifierar de fall vi redan tänkt på. En hanterare kan vara felfri på sina fixtures och ändå förvanska ett mönster som bara dyker upp i verklig kod — ett makroidiom, en generisk-bunden metod, en språkfunktion ingen skrev en fixture för. GRÖNT betyder att fixtures godkänns. Det betyder inte att ett verkligt repositorium extraheras rent. Så loopen måste lämna fixtures bakom sig och titta på det vilda.

Innerloopen: stickprov, döma, fixa, bevisa

Kärnloopen kör ett språk i taget:

        ┌──────────────────────────────────────────────────────────┐
        │                                                          │
        ▼                                                          │
  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) ──┘

Ett par saker gör att det här fungerar istället för att stampa på stället.

Domaren är agenten, inte ett API-anrop. När vi säger “LLM som domare” menar vi att språkagenten själv läser varje utvald kant mot den verkliga källan och klassificerar den enligt en fast femkategorisk rubrik: är kanten korrekt, en falsk positiv, rätt relation med fel typ, kopplad till fel scope, eller bärande på fel metadata? Den rubriken är hela spelet — “23 % felfrekvens” är meningslöst tills man vet om det är verkliga defekter eller domaren som räknar fel.

Fixa en sak, bevisa den sedan. Varje iteration ändrar exakt en redigerbar tillgång, kör sedan om mot ett fast testställ och behåller ändringen bara om F1 förbättras och omklassificeringen ser bättre ut. Om inte, återställs den. Ingen bunt spekulativa ändringar, inget “borde bli bättre”. En ändring förtjänar sin plats eller så är den borta. Och när en fix håller, befordras den in i fixture-sviten — så att buggen den fixade aldrig tyst kan komma tillbaka. Det befordringssteget är det som gör loopen rekursiv snarare än bara repetitiv: varje pass härdar oraklet nästa pass valideras mot.

Lärdomen vi ständigt lär oss om igen: mätvärden överrapporterar

Här är fällan, och vi gick rakt in i den. De sekundära korpusmätvärdena — hur ofta ett extraherat mål saknar en upplösbar symbol, hur många symboler ser “föräldralösa” ut, och så vidare — överrapporterar problem massivt. De är mestadels paradigmartefakter, inte buggar.

Det renaste exemplet: llvm visade en gång en 73-procentig andel “källa-utan-symbol” och stämplades som katastrofalt. Vi grävde i det. Den verkliga noggrannheten var 98,5 %. De “saknade symbolerna” var nästan uteslutande legitima externa referenser — anrop in i standardbiblioteket, in i ramverk, in i kod som ligger utanför repot. Måttet mätte en egenskap hos språket, inte en defekt i hanteraren. Språk som Zig, COBOL och Odin visar 65–70 % “föräldralösa” och är helt korrekta; COBOL hade noll verkliga fel.

Om vi hade låtit de siffrorna styra arbetet hade vi lagt veckor på att “fixa” hanterare som redan var korrekta och ignorerat de språk som hade tysta, verkliga buggar. Slutsatsen är rättfram: de aggregerade mätvärdena är på sin höjd en grov triage-signal. Den verkliga kvalitetssignalen är stickprovet med kantklassificering — att titta på faktiska kanter i faktiska repositorier och döma dem en och en. Data före intuition, men bara när man vet vilken data som talar sanning.

Ytterloopen: en flotta, inte ett maraton

Ett språk i taget skulle ta en evighet över 280 av dem, så innerloopen omsluts av en ytterloop som kör många parallellt.

   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

Varje agent arbetar i en engångs-worktree så att de inte kan gå på varandras tår. Orkestreraren integrerar deras fixar en i taget, var och en bakom en regressionskontroll mot hela manifestet: en ändring som hjälper sitt eget språk men tyst förstör tre andra landar inte. Integrationen är grindad och bekräftad innan något pushas — regressionsgrinden avgör vad som är säkert, en människa avgör fortfarande vad som skeppas. Sedan roterar poolen till nästa uppsättning språk och alltihop körs igen.

Vad som fortfarande är ofullständigt

Domaren kan ha fel, och felaktigheten har en riktning: en agent som kör med för lite kontext överrapporterar. I en batch flaggades åtta språk med 5–20 % fel; vid granskning var bara en en verklig språkspecifik bugg — resten var domarmisstag från att missa språkets egen semantik (en källkodsrad som legitimt avger flera kanter, parameterbindningar modellerade som tilldelningar, referens-per-identifierare-språk). Det är därför vi tar stickprov med två frön och korskontrollerar, och varför en oenighet mellan domaren och fixtures behandlas som den mest intressanta signalen, inte en avgjord dom — ibland är det fixturen som har fel.

Vi är också ärliga om målet. Målet är noll verkliga fel, punkt slut — men “noll” är en riktning vi sliter oss mot, språk för språk, inte en ruta som bockas av. Det finns alltid ännu ett repo med ännu ett idiom.

Förtjänat, inte påstått

Allt Maguyva gör för en agent — hitta en symbol, spåra ett beroende, besvara en fråga med citerad kod — vilar på att extraktionen under är korrekt. Över 280 språk kan “korrekt” inte påstås; det måste kontinuerligt förtjänas mot verklig kod. Loopen är hur vi förtjänar det: en autonom cykel av stickprov och fix som behandlar sina egna mätvärden med misstänksamhet, bevisar varje ändring och gör varje fix till ett skydd mot nästa regression. Det är inte glamoröst. Det är arbetet som låter oss säga “vi stöder ditt språk” och mena det. Grönt är lätt. Korrekt är förtjänat.

Relaterad läsning

Mer från byggloggen för Maguyva