Przejdź do treści
Blog

Spec-driven development: kiedy kazać agentowi najpierw napisać specyfikację

Specyfikacja przed kodem zamienia jedną dużą decyzję modelu na kilka małych, które da się sprawdzić. Pokazuję, co mówią badania, jak robią to Spec Kit i Kiro i kiedy ten narzut się nie zwraca.

Przemysław Zagórski6 min czytania

Prosisz agenta o eksport raportu do CSV. Po kilku minutach dostajesz kilkaset linii kodu, testy przechodzą, całość wygląda porządnie. Dopiero przy przeglądzie widzisz, że agent wybrał przecinek jako separator, choć kwoty w raporcie mają przecinek dziesiętny, i że eksportuje wszystkie kolumny, także te, których odbiorca raportu nie powinien widzieć.

Żadna z tych decyzji nie była błędem technicznym. Były to założenia, które model przyjął po cichu, bo polecenie ich nie rozstrzygało. Spec-driven development to sposób na to, żeby takie założenia wyszły na wierzch, zanim zamienią się w kod.

Poniżej opisuję, co to podejście zmienia, na co są dowody i gdzie przestaje się opłacać.

Co to jest, bez słownika marketingowego

Zamiast jednego polecenia „zrób funkcję” agent przechodzi przez trzy etapy, a między nimi stoi człowiek.

  1. Wymagania. Co ma powstać i po czym poznać, że działa. Przypadki brzegowe, rzeczy wyłączone z zakresu i pytania, na które agent nie zna odpowiedzi.
  2. Projekt. Jak to zbudować w tym konkretnym repozytorium: które moduły, jakie struktury danych, gdzie testy.
  3. Zadania. Lista kroków na tyle małych, że każdy kończy się czymś, co da się sprawdzić.

Kod powstaje dopiero po trzecim etapie, zadanie po zadaniu.

Dwa narzędzia zrobiły z tego produkt. Kiro zapisuje każdą specyfikację w trzech plikach: requirements.md z wymaganiami i kryteriami akceptacji, design.md z architekturą i tasks.md z planem wykonania. Spec Kit od GitHuba rozkłada to samo na polecenia dla agenta: /speckit.specify definiuje wymagania, /speckit.plan tworzy plan techniczny, /speckit.tasks rozpisuje zadania, a /speckit.implement je wykonuje. Obok są jeszcze /speckit.constitution z zasadami całego projektu i /speckit.clarify, które dopytuje o niedookreślone miejsca.

Nazwy się różnią, konstrukcja jest ta sama. Da się ją odtworzyć w zwykłym czacie bez instalowania czegokolwiek, co pokazuję niżej.

Na co są dowody

Najlepiej zmierzona jest wersja najprostsza: model najpierw pisze plan, a dopiero potem kod. Zespół Xue Jianga nazwał to self-planning i porównał z generowaniem kodu wprost. Praca została przyjęta do ACM TOSEM. Wynik to do 25,4 procent względnej poprawy w Pass@1, czyli w odsetku zadań rozwiązanych za pierwszym podejściem, wobec generowania wprost. Wobec chain-of-thought, czyli rozumowania krok po kroku bez osobnego planu, poprawa sięga 11,9 procent.

Dwa zastrzeżenia, zanim ktoś wstawi tę liczbę do prezentacji. Słowo „do” oznacza najlepszy wynik spośród wielu zestawień, a nie typowy. Mierzono też zadania z benchmarków, w których model pisze pojedynczą funkcję na podstawie opisu, a nie funkcjonalność w cudzym repozytorium. Kierunek jest dobrze udokumentowany, ale przenoszenie samej liczby na pracę z agentem byłoby naciąganiem.

Ciekawiej robi się przy zestawieniu z badaniem, które opisywałem przy pliku instrukcji dla agenta. Tam plik z ogólnymi regułami repozytorium skrócił czas pracy o 28 procent, a skuteczności nie poprawił. Nie widzę w tym sprzeczności. Plik instrukcji odpowiada na pytania, które agent zadaje sobie przy każdym zadaniu: czym się buduje projekt, gdzie są testy. Specyfikacja odpowiada na pytania, które pojawiają się tylko w tym jednym zadaniu, i właśnie tam model najczęściej zgaduje.

Dlaczego to działa

Model podejmuje decyzje projektowe niezależnie od tego, czy go o to prosisz. Specyfikacja nie sprawia, że podejmuje lepsze. Sprawia, że widzisz je, zanim staną się kodem.

Druga rzecz to koszt przeglądu. Stronę wymagań czyta się szybciej niż diff na kilkaset linii, a błędne założenie znalezione w wymaganiach poprawia się jednym zdaniem. To samo założenie znalezione w kodzie oznacza przepisywanie, często razem z testami, które zostały napisane pod błędną wersję.

Trzecia rzecz jest mniej oczywista. Lista zadań dzieli pracę na odcinki, po których możesz się zatrzymać, sprawdzić wynik i zacząć nową rozmowę z czystym kontekstem. Agent, który realizuje zadanie trzecie z siedmiu, nie musi mieć w pamięci całej dyskusji o zadaniu pierwszym. Wystarczy mu zatwierdzona specyfikacja i aktualny stan kodu.

Zatwierdzenie specyfikacji jest bramką i podlega tym samym regułom

Jeśli napiszesz w poleceniu „przedstaw plan i poczekaj na akceptację”, model zwykle poczeka, ale decyzja o zatrzymaniu nadal należy do niego. Pisałem o tym przy człowieku w pętli: prośba w instrukcji nie jest bramką. Jeśli Twoje narzędzie pozwala oddzielić etap planowania od etapu zmieniania plików, korzystaj z tego. Jeśli nie pozwala, rozdziel etapy sam: osobna rozmowa na specyfikację, osobna na kod.

Trzy kroki w zwykłym czacie

Pierwsze polecenie ma zabronić kodu i wymusić pytania:

Zanim cokolwiek zmienisz, opisz wymagania dla tej zmiany:
- co ma działać i po czym to poznam,
- przypadki brzegowe,
- czego w tym zadaniu nie robimy,
- pytania, na które nie znajdziesz odpowiedzi w repozytorium.
Nie zmieniaj żadnych plików.

Przeczytaj wynik, popraw to, co się nie zgadza, i odpowiedz na pytania z ostatniej sekcji. Ta sekcja jest najcenniejsza, bo zawiera dokładnie te założenia, które inaczej model przyjąłby po cichu. W przykładzie z eksportem pytanie o separator i o zakres kolumn pojawiłoby się właśnie tam.

Drugie polecenie zamienia zatwierdzone wymagania w plan:

Na podstawie zatwierdzonych wymagań rozpisz zadania.
Każde zadanie ma kończyć się testem, który przechodzi.
Nadal nie zmieniaj plików.

Trzeci krok to wykonanie po jednym zadaniu. Po każdym przeglądasz zmianę i dopiero potem prosisz o następne.

Zatwierdzoną specyfikację zapisz w repozytorium, na przykład w katalogu docs/spec/. Dzięki temu kolejna sesja zaczyna od pliku, a nie od odtwarzania ustaleń z pamięci, a zespół widzi, na co się umówiliście.

Kiedy się nie opłaca

Anthropic w przewodniku o budowaniu agentów radzi szukać najprostszego rozwiązania i zwiększać złożoność dopiero wtedy, gdy jest potrzebna. Ta zasada dotyczy także procesu. Specyfikacja jest narzutem i są przypadki, w których nie ma czego zwracać.

  • Zmiana, której diff przeczytasz szybciej niż specyfikację. Poprawka w konfiguracji, zmiana nazwy, skrypt uruchamiany raz.
  • Prototyp, który ma sprawdzić pomysł. Specyfikacja czegoś, czego jeszcze nie rozumiesz, będzie fikcją spisaną porządnym językiem.
  • Błąd z jednoznaczną reprodukcją. Tu specyfikacją jest test, który błąd odtwarza. Napisz go najpierw i każ agentowi doprowadzić go do zielonego.

Moja reguła kciuka, nie wynik żadnego badania: jeśli zmiana dotyka więcej niż jednego modułu albo da się ją sensownie zrozumieć na dwa sposoby, zaczynam od specyfikacji. W pozostałych przypadkach nie.

Kiro i Spec Kit: czym są, a czym nie

Kiro to środowisko programistyczne od AWS, zbudowane wokół specyfikacji. Ma dwa mechanizmy, które łatwo pomylić. Specyfikacje dotyczą pojedynczej funkcjonalności i żyją tyle, co ona. Steering to pliki w .kiro/steering/, domyślnie product.md, tech.md i structure.md, które według dokumentacji trafiają do każdej interakcji. Kiro czyta też AGENTS.md. Steering to więc odpowiednik pliku instrukcji dla całego repozytorium, a specyfikacja to dokument jednego zadania. Mieszanie tych dwóch rzeczy prowadzi do złych porad, bo pierwszą piszesz raz i rzadko ruszasz, a druga powstaje i znika razem z funkcją.

Spec Kit nie jest środowiskiem. To zestaw poleceń i szablonów na licencji MIT, który według opisu projektu działa z ponad trzydziestoma agentami kodującymi. Jego README obiecuje, że specyfikacje „stają się wykonywalne”. Traktowałbym to ostrożnie: specyfikacja niczego nie wykonuje, agent generuje z niej kod, który nadal trzeba przejrzeć.

Oba narzędzia są dobrym punktem wyjścia, jeśli chcesz wymusić ten proces w zespole. Żadne nie jest do niego potrzebne.

Od czego zacząć

  1. Wybierz jedną zmianę z najbliższego sprintu, która da się zrozumieć na więcej niż jeden sposób.
  2. Poproś o wymagania bez kodu, z obowiązkową sekcją pytań.
  3. Zapisz zatwierdzoną wersję w repozytorium, obok kodu, którego dotyczy.
  4. Wykonuj po jednym zadaniu, każde zakończone testem.
  5. Porównaj z tym, co zwykle. Ile poprawek wyszło przy przeglądzie tym razem, a ile przy podobnej zmianie robionej jednym poleceniem. To jest pomiar, który ma znaczenie dla Twojego zespołu, bardziej niż jakakolwiek liczba z benchmarku.

Specyfikacja to w gruncie rzeczy dobre polecenie rozciągnięte na całe zadanie. Pięć elementów takiego polecenia opisałem w tekście o prompcie jak adresie w nawigacji. Tam ustalasz cel jednej odpowiedzi, tu cel całej zmiany, zanim ktokolwiek zacznie pisać kod.

Źródła

  1. [1]Self-planning Code Generation with Large Language ModelsJiang i in., ACM TOSEM (arXiv)
  2. [2]Spec Kit: zestaw narzędzi do spec-driven developmentGitHub
  3. [3]Specs: requirements.md, design.md, tasks.mdKiro
  4. [4]Steering: product.md, tech.md, structure.md i AGENTS.mdKiro
  5. [5]Building effective agentsAnthropic
Przemysław Zagórski

Przemysław Zagórski

Programista i architekt, 14+ lat w telco i enterprise IT. Prowadzi warsztaty z inżynierii kontekstu, GitHub Copilota, Google ADK oraz ekosystemu Gemini dla zespołów, które muszą dowozić produkcyjnie.

Jeśli widzisz te problemy u siebie, zwykle da się je rozbroić w kilka dni roboczych. Nie kolejnym narzędziem, tylko zmianą sposobu pracy zespołu. Chętnie omówię Wasz przypadek.

7 min czytania

Plik z instrukcjami dla agenta: 28 procent szybciej, ale nie mądrzej

AGENTS.md ma już pomiar w recenzowanym badaniu: agenci pracują szybciej i taniej. Za to skuteczność zostaje ta sama. Rozbieram, co z tego wynika dla treści takiego pliku i dlaczego popularne szablony szkodzą.

  • Inżynieria kontekstu
  • Agenci
  • Jakość kodu
Czytaj