Utrzymywanie spójności specyfikacji, testów i kodu w procesie rozwoju AI

Zapobiegaj odchyleniom agentów AI od specyfikacji, testów i kodu.

Page content

Agenci kodujący z wykorzystaniem sztucznej inteligencji (AI) szybkodostarczają funkcje, ale specyfikacje, testy i kod cicho się od siebie oddalają. Ten przewodnik omawia model śledzenia (traceability), mapowanie specyfikacji na testy oraz kodu, a także sprawdzenia CI, które wychwytują rozbieżności przed scaleniem (merge).

Specyfikacja, która nie jest weryfikowana względem działającego systemu, jest gorsza niż brak specyfikacji w ogóle, ponieważ tworzy fałszywe poczucie bezpieczeństwa. Recenzenci ufają dokumentowi zamiast różnic (diff), a agent AI poproszony o „podążanie za istniejącym wzorcem” chętnie podąże za tym, co kod faktycznie robi, nawet jeśli sprzeciwia się to wymaganiu, które miał spełniać.

Rozwiązaniem nie jest więcej dokumentacji. Jest to mały, egzekwowalny link między czterema rzeczami, które już istnieją w większości repozytoriów: wymaganiem, decyzją projektową stojącą za nim, testami, które je potwierdzają, oraz commitami lub pull requestami (PR), które je zmieniły.

linki śledzenia łączące specyfikacje, testy i kod

Gdy ten link istnieje jako dane, a nie jako wspólne rozumienie, można go zapytać. Można zapytać, które wymagania nie mają pokrycia testowego, które testy nie mapują się już na żadne wymagania, a które pliki zmieniły się w pull requestcie bez odpowiadającego ID wymagania. To zapytanie jest właściwym dostarczanym elementem tego artykułu, a reszta posta opisuje, jak zbudować go przy użyciu narzędzi, które prawdopodobnie już używasz.

Problem rozbieżności: Dlaczego specyfikacje, testy i kod tracą synchronizację

Rozbieżność pojawia się w czterech rozpoznawalnych formach, a zespoły wspierane przez AI mają tendencję do napotkania wszystkich czterech szybciej niż zespoły piszące każdy wiersz ręcznie.

  • Zmiana specyfikacji, kod nie zmienia się. Wymaganie zostaje wyjaśnione w dalszej rozmowie lub wątku komentarzy, ale nikt nie regeneruje ani nie edytuje implementacji, aby odpowiadała tej zmianie.
  • Zmiana kodu, specyfikacja się nie zmienia. Agent lub deweloper naprawia błąd lub refaktoryzuje moduł, a specyfikacja nadal opisuje stare zachowanie, jakby wciąż było aktualne.
  • Testy pokrywają implementację, a nie intencję. Testy jednostkowe assertują (twierdzą), co kod aktualnie robi, co jest kołem złośliwości: przechodzą przez konstrukcję nawet wtedy, gdy kod spełnia błędne wymagania.
  • Pull requesty nie odnoszą się do wymagań. Recenzenci zatwierdzają diff na podstawie „wygląda rozsądnie”, ponieważ nie ma wyraźnego twierdzenia, z którym można byłoby go porównać.

Ostatnie badania procesowe nad frameworkami deweloperskimi AI identyfikują rozbieżność specyfikacji jako powtarzające się ryzyko właśnie dlatego, że agenci regenerują kod szybko i wielokrotnie, a każda regeneracja jest nową okazją do jeszcze większego rozbieżności między specyfikacją a implementacją. Debata Spec-Driven Development vs Vibe Coding jest w rzeczywistości argumentem o ten sam tryb awarii: specyfikacja, której nikt nie egzekuuje, degeneruje się w tę samą rozbieżność, co jej brak, tylko z dodatkową ceremonią.

Współczesne przepływy pracy w stylu spec-kit coraz częściej określają to jako zgniliznę specyfikacji (specification rot): specyfikacja nadal wygląda autorytatywnie, podczas gdy cicho traci połączenie z tym, co system faktycznie robi. Podstawowa definicja spec-driven development traktuje specyfikację jako źródło prawdy, ale źródło prawdy pozostaje prawdziwe tylko wtedy, gdy coś stale sprawdza je względem rzeczywistości.

Model śledzenia (Traceability) dla rozwoju wspieranego przez AI

Działający model śledzenia potrzebuje sześciu identyfikatorów, które łączą wymaganie biznesowe aż do wierszy kodu i pull requesta, który je zaimplementował. Większość zespołów ma już trzy lub cztery z nich; brakujące to zazwyczaj ID decyzji projektowej (design decision) i wyraźny link z powrotem z testów i commitów.

Identyfikator Znajduje się w Przykład
ID Wymagania requirements.md lub narzędzie specyfikacji REQ-014
ID Decyzji Projektowej ADR / rejestr decyzji ADR-0032
ID Zadania rozkład zadań lub tracker issue TASK-014-3
ID Testu plik testowy lub nazwa testu test_req_014_password_reset
Link do Commita / PR historia Git PR #482
Zmienione pliki różnica Git (diff) auth/reset.go, auth/reset_test.go

Zależności między tymi identyfikatorami tworzą graf, a nie prostą linię, ponieważ jedno wymaganie może wygenerować kilka zadań, a jeden pull request może dotknąć kilku wymagań naraz.

graph TD REQ["Wymaganie
REQ-014"] --> ADR["Decyzja Projektowa
ADR-0032"] ADR --> TASK["Zadanie
TASK-014-3"] TASK --> CODE["Zmiana Kodu
auth/reset.go"] TASK --> TEST["Test
test_req_014_password_reset"] CODE --> PR["Pull Request
#482"] TEST --> PR PR --> COMMIT["Historia commitów"]

Przechowywanie tego grafu jako danych strukturalnych, a nie prozy, pozwala na późniejsze zapytania. Ekosystem Spec Kit GitHuba poruszył się dokładnie w tym kierunku: rozszerzenia takie jak spec-kit-trace skanują tokeny REQ-XXX osadzone w plikach specyfikacji i testów i generują deterministyczną macierz z tego dosłownego dopasowania tekstu, celowo unikając nieostrego zgadywania opartego na nazwach, które powoduje ciche fałszywe pozytywy.

Mapowanie Specyfikacji na Testy: Przekształcanie Kryteriów Akceptacji w Przypadki Testowe

Każde kryterium akceptacji w specyfikacji jest z definicji asercją behawioralną: mając ten stan, gdy aktor robi to, system powinien odpowiedzieć w ten sposób. To już jest kształt przypadku testowego, dlatego najmocniejsze przepływy pracy SDD (Spec-Driven Development) generują testy z tych samych kryteriów akceptacji, które generują kod, zamiast prosić agenta generującego kod o wynalezienie własnych testów po fakcie.

Szeroko używanym formatem do pisania tych kryteriów jest EARS (Easy Approach to Requirements Syntax), który wymusza wpasowanie każdego wymagania w jednoznaczny, testowalny wzorzec, taki jak „Gdy <trigger>, system powinien <response>”. Ta struktura mapuje się czysto na cztery kategorie testów, które każde wymaganie powinno posiadać:

  • Testy pozytywne — szczęśliwa ścieżka (happy path), którą wymaganie wyraźnie opisuje.
  • Testy negatywne — wejścia lub stany, które według wymagania muszą zostać odrzucone.
  • Testy graniczne — krawędzie zakresów, limitów i progów wymienionych w kryteriach akceptacji.
  • Testy migracyjne — zachowanie dla danych lub stanu z okresu przed wymaganiami, aby stara pozycja nie omijała cicho nowej reguły.
Typ Wymagania Kategoria Testu do dodania Częsty błąd
„System ma odrzucić X” Negatywny Testowana jest tylko ścieżka akceptacji
„Limit to N elementów” Graniczny N-1, N i N+1 nie są wszystkie pokryte
„Nowe pole zastępuje stare pole” Migracyjny Stare rekordy bez nowego pola crashują cicho
„W ciągu 60 sekund” Graniczny + czasowy Test assertuje logikę, nie rzeczywisty budżet czasu

Testy jednostkowe napisane w ten sposób nadal mają znaczenie jako szybka, tania warstwa piramidy; praktyczne wzorce ich strukturyzacji są omawiane w przewodniku po testowaniu jednostkowym w Go oraz w przewodniku po testowaniu jednostkowym w Pythonie. Co śledzenie dodaje na wierzchu, to dosłowny, stabilny token wymagania osadzony w nazwie testu lub komentarzu testowym, dzięki czemu późniejsze zapytanie może udowodnić — a nie zakładać — że REQ-014 ma pokrycie.

Mapowanie Specyfikacji na Kod: Od Planów Projektowych do Tabeli Śledzenia

Mapowanie specifikacji na testy udowadnia zachowanie; mapowanie specifikacji na kod udowadnia zakres. Odpowiada na inne pytanie: które pliki miały się faktycznie zmienić dla tego wymagania, czy różnica (diff) pozostała w granicach tego zakresu, czy rozlała się na niezwiązane moduły?

Plan projektowy, który wymienia dotknięte pliki z góry — nawet w przybliżeniu — daje Ci coś, z czym można później porównać rzeczywisty pull request. Komentarze w kodzie powinny odnosić się do ID wymagania tylko wtedy, gdy dodają one informacje, których recenzent nie może uzyskać ze samej specyfikacji; komentarz powtarzający tekst wymagania dosłownie to szum, ale `// wymusza granicę REQ-014: maks 5 prób resetu na godzinę» zasługuje na swoje miejsce, ponieważ liczba ta jest w inny sposób niewidoczna w diffie.

Generowana tabela śledzenia przekształca to w coś, co można przejrzeć w kilka sekund, a nie w coś, co recenzent musi odtworzyć, czytając oba dokumenty obok siebie:

Wymaganie Decyzja Projektowa Zmienione pliki Testy Status
REQ-014 ADR-0032 auth/reset.go, auth/reset_test.go test_req_014_* (4) Pokryte
REQ-015 ADR-0032 auth/reset.go brak Luka
REQ-016 auth/notify.go test_notify_basic Osierocony link specyfikacji

Ta jedna tabela ujawnia na pierwszy rzut oka dwa najczęstsze wzorce awarii: REQ-015 zmieniło kod z zerowym pokryciem testowym, a test powiązany z REQ-016 nie odnosi się faktycznie do ID wymagania, co oznacza, że albo specyfikacja jest brakuje, albo test został błędnie sklasyfikowany.

Przepływ Pracy Pull Request: Recenzja Specyfikacji, Kodu i Testów Razem

Pull request zbudowany wokół śledzenia recenzuje trzy diffy obok siebie, zamiast jednego: co zmieniło się w specyfikacji, co zmieniło się w kodzie i co zmieniło się w testach. Pytanie recenzjne przestaje być „czy to wygląda dobrze?” i staje się o wiele bardziej specyficzne: „jakiemu wymaganiu ta zmiana zaspokaja, czy dowody to potwierdzają?”

sequenceDiagram participant Dev as Deweloper lub Agent participant PR as Pull Request participant CI as Pipeline CI participant Rev as Recenzent Dev->>PR: Otwórz PR z diffem specyfikacji + diffem kodu + diffem testów PR->>CI: Wywołaj sprawdzenia śledzenia CI->>CI: Zweryfikuj obecność ID REQ w opisie PR CI->>CI: Uruchom sprawdzenie pokrycia spec-to-test CI->>CI: Uruchom sprawdzenie zakresu plików spec-to-code CI-->>PR: Opublikuj raport śledzenia jako komentarz do PR Rev->>PR: Przeglądaj pod kątem „jakiemu wymaganiu zaspokaja?” Rev->>PR: Zatwierdź lub poproś o zmiany

Krótka, konkretna lista kontrolna recenzenta działa lepiej tutaj niż długa, ponieważ recenzenci pomijają długie listy pod presją terminów:

  1. Czy opis PR nazywa ID wymagania (lub wymagań), które zaspokaja?
  2. Czy każdy zmieniony plik pojawia się na liście dotkniętych plików w planie projektowym, czy też dodatkowy zakres jest wyjaśniony?
  3. Czy co najmniej jeden nowy lub istniejący test odnosi się do każdego ID wymagania dotkniętego przez ten PR?
  4. Jeśli specyfikacja się zmieniła, czy kod i testy zmieniły się w tym samym PR, czy też istnieje śledzone dalsze działanie?

Automatyzacja Śledzenia w CI

Recenzja ręczna wychwytuje rozbieżność tylko tak często, jak recenzenci pamiętają, aby jej szukać, dlatego powyższe sprawdzenia należą do CI, a nie do strony w wiki, której nikt nie czyta ponownie. Te same wzorce GitHub Actions cheatsheet, które już używasz do zadań budowania i testowania, stosują się tutaj bezpośrednio — sprawdzenia śledzenia to po prostu kolejne zadanie w tym samym pipeline.

Praktyczne pomysły na automatyzację, mniej więcej w kolejności wysiłku:

  • Sprawdzenia CI dla plików specyfikacji — nieudany build, jeśli plik specyfikacji został edytowany bez odpowiedniej zmiany kodu lub testu w tym samym PR, lub odwrotnie.
  • Wymagaj ID wymagań w tytułach lub opisach PR — lekkie sprawdzenie regexem (REQ-\d+) blokuje merge’y, które nie nazywają, co implementują.
  • Podsumowania śledzenia generowane przez agenta — poproś agenta o wygenerowanie krótkiego podsumowania, które wymagania dotyka PR, dla człowieka do potwierdzenia, zamiast pisać od zera.
  • Pokrycie testów według kryteriów akceptacji, a nie tylko linii — pokrycie linii mówi Ci, że kod się uruchomił; pokrycie wymagań mówi, że twierdzenie zostało sprawdzone.
  • Ostrzeżenia o przestarzałych specyfikacjach — flaguj specyfikacje, które nie były dotknięte w N commitach dotykających ich powiązanych plików, ponieważ długo milczące specyfikacje są tymi, które najprawdopodobniej zeszły w zgniliznę.

Rozszerzenia zbudowane na podstawie Spec Kit GitHuba już mechanicznie implementują kilka z tych funkcji: jedno skanuje dosłowne tokeny REQ-XXX przez pliki specyfikacji i testów, aby zbudować macierz i flagować osieroczone testy, a bardziej rygorystyczny pakiet zorientowany na Model V idzie dalej, generując parowane specyfikacje testowe dla każdej specyfikacji deweloperskiej i produkując wiele macierzy śledzenia dla zespołów pracujących w ramach frameworków regulacyjnych, takich jak IEC 62304 lub ISO 26262. Nie potrzebujesz tego poziomu ceremonii dla większości projektów, ale podstawowa idea — deterministyczna, generowana skryptem macierz, a nie ręcznie utrzymywana arkusz kalkulacyjny — skaluje się tak samo dobrze w dół, jak w górę.

Używanie Agentów AI dla Śledzenia, Nie Jako Orakla

Agenci AI są dobrze dostosowani do mechanicznych części śledzenia i słabo dostosowani do bycia sędzią ostatniej instancji, czy wymaganie zostało faktycznie zaspokojone. Trzy zadania pasują bezpośrednio do mocnych stron agenta:

  • Porównaj specyfikację i diff — poproś agenta o wylistowanie każdego wymagania wspomnianego w plikach specyfikacji dotkniętych przez PR i każdego, dla którego nie znalazł odpowiadającego kodu.
  • Znajdź niepokryte wymagania — poproś agenta o przeskanowanie zestawu testów pod kątem tokenów wymagań i raportowanie, które wymagania w specyfikacji nie mają żadnych.
  • Wykryj kod nieopisany przez specyfikację — poproś agenta o flagowanie zmienionych plików lub funkcji, które dotykają modułów niosących wymagania, ale nie odpowiadają żadnemu ID wymagania w diffie.

Trybem awarii, przed którym należy się strzec, jest ufać podsumowaniu agenta jako prawdzie obiektywnej, zamiast jako punktowi wyjścia dla recenzenta. Agent może źle odczytać komentarz, przeoczyć token wymagania podzielony między dwa pliki lub pewnie ogłosić pokrycie dla testu, który tylko powierzchownie ćwiczy ścieżkę kodu. Traktuj każdy raport śledzenia generowany przez agenta tak, jak traktowałbyś przegląd juniora recenzenta: użyteczny, szybki i nadal podlegający drugiemu spojrzeniu przed zablokowaniem merge’a. To ta sama ostrożność, która stosuje się do rejestru decyzji dla rozwoju napędzanego przez AI — rejestr pozostaje wiarygodny tylko wtedy, gdy coś innego niż agent, który go napisał, ostatecznie go sprawdza.

Minimalny Szablon Śledzenia do Skopiowania

Nie potrzebujesz ciężkiego frameworku, aby zacząć. Szablon pięciu plików, zapisany do repozytorium obok kodu, który opisuje, pokrywa podstawy:

docs/
  requirements.md     # ID REQ z kryteriami akceptacji w stylu EARS
  design.md           # ID ADR, dotknięte pliki, decyzje architektoniczne
  tasks.md            # ID TASK powiązane z jednym lub wieloma ID REQ
  tests.md            # które pliki/funkcje testowe odnoszą się do których ID REQ
  traceability.md     # generowana tabela: REQ -> ADR -> TASK -> pliki -> testy -> PR

requirements.md, design.md i tasks.md są pisane lub edytowane przez ludzi i agentów razem, w ten sam sposób, jak opisuje to już przepływ pracy spec-driven development. tests.md i traceability.md powinny być generowane, a nie ręcznie utrzymywane, nawet jeśli generatorem jest krótki skrypt, który tylko grep-uje REQ-\d+ przez katalog testów i pliki specyfikacji — ręcznie utrzymywane tabele śledzenia są same w formie ryzyka rozbieżności, ponieważ nikt nie aktualizuje arkusza kalkulacyjnego pod presją terminów.

Podsumowanie

Spec-driven development nie jest zakończony w momencie, gdy kod wychodzi z agenta; jest użyteczny dopiero wtedy, gdy kod, testy i specyfikacje utrzymują się w prawdze przez czas, poprzez PR, refaktoryzacje i zmiany wymagań, które przybywają miesiącami później. Model śledzenia zbudowany z sześciu prostych identyfikatorów, egzekwowany przez garść sprawdzeń CI i recenzowany z krótką listą kontrolną PR daje Ci większość korzyści bez narzutu pełnego frameworku zgodności. Zacznij od minimalnego szablonu, podłącz najtańsze sprawdzenie CI jako pierwsze — ID wymagań w opisach PR — i dodaj tabelę śledzenia oraz ostrzeżenia o przestarzałych specyfikacjach, gdy ta zwyczajność się przyzwyczai.

Śledzenie jest jednym elementem szerszej dyscypliny testowania i dokumentacji omawianej w klastrze Architektura Aplikacji w Produkcji, a towarzyszy mu zagadnieniom narzędziowym omawianym w klastrze Narzędzia Deweloperskie AI dla zespołów wybierających, które przepływy pracy agenta mają zostać ustandaryzowane.

Subskrybuj

Otrzymuj nowe wpisy o systemach, infrastrukturze i inżynierii AI.