Att hålla specifikationer, tester och kod synkroniserade i AI-utveckling

Stoppa AI-agenter som avviker från specifikationer, tester och kod.

Sidinnehåll

AI-kodningsagenter levererar funktioner snabbt, men specifikationer, tester och kod drar långsamt isär. Den här guiden täcker en spårbarhetsmodell, mappning från spec till test och från spec till kod, samt de CI-kontroller som fångar avvikelse innan en sammanslagning.

En specifikation som ingen återkontrollerar mot det körande systemet är värre än ingen specifikation alls, eftersom den skapar falsk trygghet. Granskare litar på dokumentet istället för skillnaderna (diff), och en AI-agent som blir ombedd att “följa befintliga mönster” kommer glatt att göra vad koden faktiskt gör, även när det strider mot den kravspecifikation den var tänkt att uppfylla.

Lösningen är inte mer dokumentation. Det är en liten, genomförbar länk mellan fyra saker som redan finns i de flesta arkiv: kravet, designbeslutet bakom det, testerna som bevisar det och de commits eller pull requests (PR) som ändrade det.

spårbarhetslänkar som kopplar samman specifikationer, tester och kod

När den länken finns som data snarare än som en delad förståelse kan du fråga om den. Du kan fråga vilka krav som saknar testcoverage, vilka tester inte längre mappar mot något krav och vilka filer ändrades i en pull request utan en matchande krav-ID. Den frågan är den faktiska leveransen i denna artikel, och resten av inlägget går igenom hur du bygger den med verktyg du förmodligen redan använder.

Problem med avvikelse: Varför specifikationer, tester och kod hamnar ur takt

Avvikelse visar sig i fyra igenkännbara former, och AI-assisterade team tenderar att stöta på alla fyra snabbare än team som skriver varje rad i hand.

  • Specifikationen ändras, koden gör det inte. Ett krav klargörs i en uppföljning eller en kommentarstråd, men ingen regenererar eller redigerar implementationen för att matcha.
  • Koden ändras, specifikationen gör det inte. En agent eller utvecklare fixar ett bugg eller refaktorerar en modul, och specifikationen fortsätter att beskriva den gamla beteendet som om den fortfarande var aktuell.
  • Testerna täcker implementationen, inte avsikten. Enhetstester påstår vad koden för närvarande gör, vilket är cirkulärt: de går igenom per konstruktion även när koden uppfyller fel krav.
  • Pull requests refererar inte till krav. Granskare godkänner en diff baserat på att det “ser rimligt ut” eftersom det inte finns någon explicit påstående att kontrollera mot.

Ny processforskning om AI-utvecklingsramar identifierar specifikationsavvikelse som en återkommande risk just för att agenter regenererar kod snabbt och upprepade gånger, och varje regeneration är en ny möjlighet för specifikation och implementation att divergera lite till. Debatten om Spec-driven Development vs Vibe Coding är egentligen ett argument om samma felmod: en specifikation som ingen genomför degenererar till samma avvikelse som du får utan en, bara med extra ceremoni.

Moderna arbetsflöden i spec-kit-stil beskriver detta alltmer som specifikationsruttnings: specifikationen ser fortfarande auktoritativ ut medan den tyst förlorar sin koppling till vad systemet faktiskt gör. Kärndefinitionen av spec-driven development behandlar specifikationen som källan till sanning, men en sanningkälla förblir bara sann om något kontinuerligt kontrollerar den mot verkligheten.

En spårbarhetsmodell för AI-assisterad utveckling

En fungerande spårbarhetsmodell behöver sex identifierare som kopplar ett affärskrav hela vägen ner till koden och den pull request som implementerade det. De flesta team har redan tre eller fyra av dessa; de som saknas är oftast designbesluts-ID:t och den explicita länken tillbaka från tester och commits.

Identifierare Finns i Exempel
Krav-ID requirements.md eller spec-verktyg REQ-014
Designbesluts-ID ADR / beslutsregister ADR-0032
Aktivitets-ID aktivitetsbrytning eller ärendespårare TASK-014-3
Test-ID testfil eller testnamn test_req_014_password_reset
Commit-/PR-länk Git-historik PR #482
Ändrade filer Git-diff auth/reset.go, auth/reset_test.go

Relationerna mellan dessa identifierare bildar en graf snarare än en rät linje, eftersom ett krav kan ge upphov till flera aktiviteter, och en pull request kan beröra flera krav samtidigt.

graph TD REQ["Krav
REQ-014"] --> ADR["Designbeslut
ADR-0032"] ADR --> TASK["Aktivitet
TASK-014-3"] TASK --> CODE["Kodändring
auth/reset.go"] TASK --> TEST["Test
test_req_014_password_reset"] CODE --> PR["Pull Request
#482"] TEST --> PR PR --> COMMIT["Commit-historik"]

Att lagra denna graf som strukturerad data, inte prosa, är det som låter dig fråga om den senare. GitHub:s Spec Kit-ekosystem har rört sig exakt i denna riktning: tillägg som spec-kit-trace skannar REQ-XXX-token som är inbäddade i spec- och testfiler och genererar en deterministisk matris från den litterala textmatchningen, vilket medvetet undviker oskarpa, namnbaserade gissningar som producerar tysta falska positiva resultat.

Mappning från spec till test: Att omvandla acceptanskriterier till testfall

Varje acceptanskriterium i en specifikation är per konstruktion en beteendepåstående: givet detta tillstånd, när aktören gör detta, ska systemet svara på detta sätt. Det är redan formen på ett testfall, vilket är varför de starkaste SDD-arbetsflödena genererar tester från samma acceptanskriterier som genererar koden, istället för att be den kodgenererande agenten att också uppfinna sina egna tester efteråt.

Ett vanligt format för att skriva dessa kriterier är EARS (Easy Approach to Requirements Syntax), som tvingar varje krav in i ett entydigt, testbart mönster som “När <trigger>, ska systemet <svar>.” Den strukturen mappar rent på fyra kategorier av tester som varje krav bör ha:

  • Positiva tester — den lyckliga vägen som kravet explicit beskriver.
  • Negativa tester — indata eller tillstånd som kravet säger måste avvisas.
  • Gränstest — kanterna av intervall, gränser och trösklar som nämns i acceptanskriterierna.
  • Migreringstester — beteende för data eller tillstånd som är äldre än kravet, så att en gammal post inte tyst kringgår en ny regel.
Kravtyp Testkategori att lägga till Vanligt missnöje
“Systemet ska avvisa X” Negativt Endast acceptvägen testas
“Gränsen är N objekt” Gränstest N-1, N och N+1 täcks inte alla
“Ny fält ersätter gammalt fält” Migrering Gamla poster utan nytt fält kraschar tyst
“Inom 60 sekunder” Gränstest + tidning Testet påstår logik, inte den faktiska tidsbudgeten

Enhetstester skrivna på detta sätt är fortfarande viktiga som det snabba, billiga lagret i pyramiden; de praktiska mönstren för att strukturera dem täcks i guiden för Go-enhetstestning och guiden för Python-enhetstestning. Det som spårbarhet lägger till ovanpå detta är en litteral, stabil kravtoken inbäddad i testnamnet eller en testkommentar, så att en senare frågan kan bevisa — inte anta — att REQ-014 har coverage.

Mappning från spec till kod: Från designplaner till en spårbarhetstabell

Mappning från spec till test bevisar beteende; mappning från spec till kod bevisar omfattning. Den besvarar en annan fråga: vilka filer var faktiskt tänkta att ändras för detta krav, och höll diffen sig inom den gränsen eller spred den sig till orelaterade moduler?

En designplan som listar berörda filer på förhand — även en grov lista — ger dig något att jämföra den faktiska pull requesten mot senare. Kommentarer i kod bör bara referera till ett krav-ID när det lägger till information en granskare inte kan få från specifikationen själv; en kommentar som upprepar kravtexten ordagrant är brus, men // genomför REQ-014-gräns: max 5 återställningsförsök per timme intjänar sin plats eftersom numret annars är osynligt i diffen.

En genererad spårbarhetstabell gör detta till något som kan granskas på sekunder snarare än något en granskare måste rekonstruera genom att läsa båda dokumenten sida vid sida:

Krav Designbeslut Ändrade filer Tester Status
REQ-014 ADR-0032 auth/reset.go, auth/reset_test.go test_req_014_* (4) Täckt
REQ-015 ADR-0032 auth/reset.go inga Glapp
REQ-016 auth/notify.go test_notify_basic Orphan spec-länk

Den enskilda tabellen visar två av de vanligaste felmönstren på en blick: REQ-015 ändrade kod med noll matchande tester, och testet kopplat till REQ-016 refererar inte faktiskt till ett krav-ID, vilket betyder att antingen är specifikationen saknad eller så testet felplacerat.

Arbetsflödet för pull request: Att granska spec, kod och test-diffs tillsammans

En pull request byggd kring spårbarhet granskar tre diffs sida vid sida istället för en: vad som ändrades i specifikationen, vad som ändrades i koden och vad som ändrades i testerna. Granskfrågan slutar vara “ser detta rätt ut?” och blir den mycket mer specifika “vilket krav uppfyller denna ändring, och bevisar bevisen det?”

sequenceDiagram participant Dev as Utvecklare eller Agent participant PR som Pull Request participant CI som CI-pipeline participant Rev som Granskare Dev->>PR: Öppna PR med spec-diff + kod-diff + test-diff PR->>CI: Aktivera spårbarhetskontroller CI->>CI: Verifiera att REQ-ID finns i PR-beskrivningen CI->>CI: Kör kontroll för spec-till-test-coverage CI->>CI: Kör kontroll för spec-till-kod-filomfattning CI-->>PR: Publicera spårbarhetsrapport som PR-kommentar Rev->>PR: Granska mot "vilket krav uppfyller detta?" Rev->>PR: Godkänn eller begär ändringar

En kort, konkret grankningschecklista fungerar bättre här än en lång, eftersom granskare hoppar över långa checklists under tidspress:

  1. Namnger PR-beskrivningen krav-ID:n som den uppfyller?
  2. Syns varje ändrad fil i designplanens lista över berörda filer, eller förklaras den extra omfattningen?
  3. Refererar minst ett nytt eller befintligt test till varje krav-ID som berörs av denna PR?
  4. Om specifikationen ändrades, ändrades koden och testerna i samma PR, eller finns det en spårad uppföljning?

Automatisera spårbarhet i CI

Manuell granskning fångar avvikelse bara lika ofta som granskare minns att leta efter den, vilket är varför kontrollerna ovan hör hemma i CI snarare än på en wikisida som ingen läser om. Samma GitHub Actions-fuskblad-mönster du redan använder för build- och testjobb gäller direkt här — spårbarhetskontroller är bara ett till jobb i samma pipeline.

Praktiska automatiseringsidéer, ungefär i ordning av insats:

  • CI-kontroller för spec-filer — misslyckas med bygget om en specfil redigerades utan en motsvarande kod- eller teständring i samma PR, eller tvärtom.
  • Kräv krav-ID:n i PR-titlar eller beskrivningar — en lättviktig regex-kontroll (REQ-\d+) blockerar sammanslagningar som inte namnger vad de implementerar.
  • Agentgenererade spårbarhetssammanfattningar — låt en agent producera en kort sammanfattning av vilka krav en PR berör, för att en människa ska bekräfta snarare än skriva från scratch.
  • Testcoverage per acceptanskriterium, inte bara per rad — radcoverage berättar att koden kördes; kravcoverage berättar att ett påstående kontrollerades.
  • Varningar för övergålda specifikationer — flagga specifikationer som inte har berörts på N commits som berör deras länkade filer, eftersom långt tysta specifikationer är de som med störst sannolikhet har ruttnat tystt.

Tillägg byggda ovanpå GitHub:s Spec Kit implementerar redan flera av dessa mekaniskt: en skannar litterala REQ-XXX-token över spec- och testfiler för att bygga en matris och flagga föräldralösa tester, och en striktare V-modell-inriktad pack går längre, genom att generera en parad testspecifikation för varje utvecklingsspecifikation och producera flera spårbarhetsmatriser för team som arbetar under regelverk som IEC 62304 eller ISO 26262. Du behöver inte den nivån av ceremoni för de flesta projekt, men den underliggande idén — en deterministisk, skriptgenererad matris snarare än ett handunderhållen kalkylark — skalas ner lika bra som den skalas upp.

Använda AI-agenter för spårbarhet, inte som en orakel

AI-agenter är väl lämpade för de mekaniska delarna av spårbarhet och mindre lämpade att vara den slutgiltige domaren över om ett krav faktiskt uppfyllts. Tre uppgifter passar en agents styrkor direkt:

  • Jämför specifikation och diff — be agenten lista varje krav som nämns i specfilerna som berörs av en PR, och varje sådan som den inte hittade motsvarande kod för.
  • Hitta täckta krav — be agenten skanna testsuiten efter kravtoken och rapportera vilka krav i specifikationen som saknas.
  • Upptäck kod som inte beskrivs av specifikationen — be agenten flagga ändrade filer eller funktioner som berör kravbärande moduler men inte motsvarar något krav-ID i diffen.

Felmoden att skydda sig mot är att lita på agentens sammanfattning som grundsanning istället som en utgångspunkt för granskaren. En agent kan missförstå en kommentar, missa en kravtoken som delas över två filer, eller självsäkert deklarera coverage för ett test som bara övar kodvägen ytligt. Behandla varje agentgenererad spårbarhetsrapport på samma sätt som du skulle behandla en junior granskares pass: användbar, snabb, men fortfarande föremål för en andra titt innan den blockerar en sammanslagning. Detta är samma försiktighet som gäller för beslutsregister för AI-driven utveckling — registret förblir bara trovärdigt om något annat än agenten som skrev det slutligen kontrollerar det.

En minimal spårbarhetsmall du kan kopiera

Du behöver inte ett tungt ramverk för att komma igång. En mall med fem filer, incheckad i arkivet bredvid koden den beskriver, täcker det viktigaste:

docs/
  requirements.md     # REQ-ID:n med EARS-stil acceptanskriterier
  design.md           # ADR-ID:n, berörda filer, arkitekturbeslut
  tasks.md            # TASK-ID:n mappade till ett eller flera REQ-ID:n
  tests.md            # vilka testfiler/funktioner refererar vilka REQ-ID:n
  traceability.md     # genererad tabell: REQ -> ADR -> TASK -> filer -> tester -> PR

requirements.md, design.md och tasks.md skrivs eller redigeras av människor och agenter tillsammans, på samma sätt som spec-driven development-arbetsflödet redan beskriver. tests.md och traceability.md bör genereras, inte handunderhålls, även om generatoren är ett kort skript som bara grep för REQ-\d+ över testkatalogen och specfilerna — handunderhållna spårbarhetstabeller är i sig en form av avvikelse risk, eftersom ingen uppdaterar ett kalkylark under tidspress.

Slutsats

Spec-driven development är inte klar i det ögonblick koden kommer ut ur en agent; den är bara användbar när kod, tester och specifikationer håller varann ärliga över tid, genom PR:n, refactorings och kravändringar som kommer månader isär. En spårbarhetsmodell byggd från sex enkla identifierare, genomförd av en handfull CI-kontroller och granskad med en kort PR-checklista ger dig de flesta fördelarna utan overheaden av ett fullständigt compliance-ramverk. Börja med den minimala mallen, koppla den billigaste CI-kontrollen först — krav-ID:n i PR-beskrivningar — och lägg till spårbarhetstabellen och varningarna för övergålda specifikationer när den vanan sitter fast.

Spårbarhet är en del av en större test- och dokumentationsdisciplin som täcks över App Architecture in Production-klustret, och den sitter bredvid verktygsmässiga frågor som utforskas i AI-utvecklareverktyg-klustret för team som väljer vilka arbetsflöden för agenter som ska standardiseras.

Prenumerera

Få nya inlägg om system, infrastruktur och AI-ingenjörskonst.