Hopp til innhold
cd /blog

Rekursiv språkforbedring: Kverning av kodeintelligens på tvers av ~280 språk

[Arkitektur][Språk][Agenter]

> Vi støtter kodeintelligens for ~280 språk. Ingen mennesker kan manuelt revidere det. Så vi bygde en rekursiv selvforbedringsløkke for språk — stikkprøver, LLM som dommer, fiks én ting, valider på nytt — og kjører den med en flåte av isolerte agenter helt til ekstraheringen faktisk er riktig, ikke bare grønn.

Tallene i dette innlegget gjenspeiler systemet ved publisering (mai 2026). Se teamsiden for gjeldende tall.

Maguyva ekstraherer symboler, referanser og en avhengighetsgraf fra kildekode på rundt 280 språk. Hvert språk er en tilpasset tree-sitter-håndterer — spørringer, heuristikker, edge cases — og hver håndterer kan være subtilt feil på sin egen måte. Et metodekall utstedt som en lesing. En funksjon tilskrevet feil omsluttende scope. En relasjon som rett og slett ikke finnes.

Det kan du ikke manuelt revidere. Ingen team kan lese ekstraksjonsresultater på tvers av 280 grammatikker og fange opp de dårlige kantene (edges). Så det interessante spørsmålet er ikke «er ekstraksjonen vår korrekt» — det er «hvordan finner du ut at den er feil, i denne bredden, uten et menneske i hver løkke». Svaret vårt er rekursiv selvforbedring for språk: en kvalitetsløkke drevet av språkagenter, en LLM som fungerer som dommer, og én regel vi stadig lærer på nytt: grønn er ikke det samme som korrekt.

Grønn er ikke korrekt

Hvert språk har en fixture-suite, og en utgivelsesport (release gate) scorer den langs fem dimensjoner — nøyaktighet, strukturell integritet, fullstendighet, kvalitet og ytelse. Et språk blir GRØNT bare når, på sine fixtures, presisjon ≥ 0,95, recall ≥ 0,99, og F1 ≥ 0,97, med minst 20 forventede edges for statistisk pålitelighet. Under det er det GULT eller RØDT, og det shippes ikke.

Den porten er nødvendig, men ikke tilstrekkelig. Fixtures valideres mot fixtures vi selv skrev. De koder for tilfellene vi allerede har tenkt på. En håndterer kan være feilfri på sine fixtures og likevel ødelegge et mønster som bare dukker opp i ekte kode — et makro-idiom, en generisk-bundet metode, en språkfunksjon ingen skrev en fixture for. GRØNT betyr at fixturene passerer. Det betyr ikke at et ekte repository ekstraheres rent. Så løkken må forlate fixturene og se på det ville.

Den indre løkken: stikkprøve, dømme, fikse, bevise

Kjerneløkken kjører ett språk om gangen:

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

Noen ting gjør at dette fungerer i stedet for å tråkke vann.

Dommeren er agenten, ikke et API-kall. Når vi sier «LLM som dommer», mener vi at selve språkagenten leser hver samplede edge mot den ekte kildekoden og klassifiserer den med en fast femkategorisk rubrikk: er denne edgen korrekt, et falskt positiv, riktig relasjon med feil type, festet til feil scope, eller bærer den feil metadata? Den rubrikken er hele spillet — «23 % feilrate» er meningsløst inntil du vet om det er ekte defekter eller dommeren som teller feil.

Fiks én ting, bevis den så. Hver iterasjon endrer nøyaktig én redigerbar ressurs, kjører deretter på nytt mot en fast test-rigg, og beholder endringen bare hvis F1 forbedres og den nye klassifiseringen ser bedre ut. Hvis ikke, rulles den tilbake. Ingen bunke med spekulative endringer, ingen «burde bli bedre». En endring tjener seg plassen, eller den er borte. Og når en fiks holder, blir den forfremmet inn i fixture-suiten — slik at feilen den fikset aldri kan komme snikende tilbake. Det forfremmelsestrinnet er det som gjør løkken rekursiv snarere enn bare repeterende: hver runde herder oraklet neste runde valideres mot.

Lærdommen vi stadig lærer på nytt: metrikker overrapporterer

Her er fellen, og vi gikk rett i den. De sekundære korpusmetrikkene — hvor ofte et ekstrahert mål mangler et løsbart symbol, hvor mange symboler ser «foreldreløse» ut, og så videre — overrapporterer problemer massivt. De er for det meste paradigme-artefakter, ikke feil.

Det klareste eksempelet: llvm viste en gang en 73 % «kilde-uten-symbol»-rate og ble stemplet som katastrofalt. Vi gravde i det. Reell nøyaktighet var 98,5 %. De «manglende symbolene» var nesten alle legitime eksterne referanser — kall inn i standardbiblioteket, inn i rammeverk, inn i kode som lever utenfor repoet. Metrikken målte en egenskap ved språket, ikke en defekt i håndtereren. Språk som Zig, COBOL og Odin viser 65–70 % «foreldreløs»-rate og er helt korrekte; COBOL hadde null reelle feil.

Hvis vi hadde latt de tallene styre arbeidet, ville vi ha brukt uker på å «fikse» håndterere som allerede var riktige og ignorert språkene med stille, ekte feil. Konklusjonen er brutal: de aggregerte metrikkene er i beste fall et grovt triage-signal. Det ekte kvalitetssignalet er stikkprøven med edge-klassifisering — å se på faktiske edges i faktiske repositorier og dømme dem én for én. Data foran intuisjon, men bare når du vet hvilke data som forteller sannheten.

Den ytre løkken: en flåte, ikke et maraton

Ett språk om gangen ville tatt evigheter på tvers av 280 av dem, så den indre løkken er pakket inn i en ytre løkke som kjører mange parallelt.

   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

Hver agent jobber i et engangs-worktree slik at de ikke kan tråkke i hverandres bed. Orkestratoren integrerer fiksene deres én om gangen, hver bak en full-manifest regresjonssjekk: en endring som hjelper sitt eget språk, men stille ødelegger tre andre, lander ikke. Integrasjon er portet og bekreftet før noe pushes — regresjonsporten avgjør hva som er trygt, et menneske avgjør fortsatt hva som shippes. Deretter roterer poolen til neste sett med språk, og hele greia kjører igjen.

Hva som fortsatt er ufullkomment

Dommeren kan ta feil, og feilen har en retning: en agent som kjører med for lite kontekst, overrapporterer. I én batch ble åtte språk flagget med 5–20 % feil; ved nærmere ettersyn var bare én en reell per-språk-feil — resten var dommerfeil fra å gå glipp av språkets egen semantikk (én kildekodelinje som legitimt sender ut flere edges, parameterbindinger modellert som tilordninger, referanse-per-identifikator-språk). Det er derfor vi sampler med to seeds og krysssjekker, og hvorfor en uenighet mellom dommeren og fixturene behandles som det mest interessante signalet, ikke en avgjort dom — noen ganger er det fixturen som er feil.

Vi er også ærlige om målet. Målet er null reelle feil, punktum — men «null» er en retning vi kverner mot, språk for språk, ikke en boks som krysses av. Det finnes alltid et nytt repo med et nytt idiom.

Fortjent, ikke påstått

Alt Maguyva gjør for en agent — å finne et symbol, spore en avhengighet, svare på et spørsmål med sitert kode — hviler på at ekstraksjonen under er riktig. På tvers av 280 språk kan «riktig» ikke påstås; det må kontinuerlig fortjenes mot ekte kode. Løkken er hvordan vi fortjener det: en autonom stikkprøve-og-fiks-syklus som behandler sine egne metrikker med mistenksomhet, beviser hver endring, og gjør hver fiks til en vakt mot neste regresjon. Det er ikke glamorøst. Det er arbeidet som lar oss si «vi støtter språket ditt» og mene det. Grønt er lett. Korrekt er fortjent.

Relatert lesning

Mer fra Maguyva-byggeloggen