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ć.
Zamiast jednego polecenia „zrób funkcję” agent przechodzi przez trzy etapy, a między nimi stoi człowiek.
- 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.
- Projekt. Jak to zbudować w tym konkretnym repozytorium: które moduły, jakie struktury danych, gdzie testy.
- 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.
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.
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.
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.
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 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.
- Wybierz jedną zmianę z najbliższego sprintu, która da się zrozumieć na więcej niż jeden sposób.
- Poproś o wymagania bez kodu, z obowiązkową sekcją pytań.
- Zapisz zatwierdzoną wersję w repozytorium, obok kodu, którego dotyczy.
- Wykonuj po jednym zadaniu, każde zakończone testem.
- 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.