Naucz się tworzyć specyfikacje funkcji Claude Code bezpośrednio z kodu — wydobywaj rzeczywiste zachowanie z tras i komponentów, a potem twórz żywą specyfikację i listę luk.

Ludzie mają różne wspomnienia o tym, co robi aplikacja, bo pamiętają różne wersje. Support pamięta ostatni zły ticket. Sprzedaż pamięta ścieżkę z dema. Inżynierowie pamiętają, co funkcja miała robić. Zapytaj trzy osoby, a usłyszysz trzy pewne odpowiedzi — i żadna nie będzie pasować do obecnej wersji.
Z czasem kod staje się jedynym źródłem, które pozostaje aktualne. Dokumenty odpływają, tickety są zamykane, a szybkie poprawki się kumulują. Trasa dostaje nowe reguły walidacji. Przełącznik w UI zmienia domyślną wartość. Handler zaczyna zwracać inne błędy. Nikt nie aktualizuje specyfikacji, bo wydaje się to opcjonalne, a każda zmiana zbyt drobna, by ją zapisywać.
To tworzy przewidywalne problemy. Zespoły wypuszczają zmiany, które psują przypadki brzegowe, o których nie wiedziały. QA testuje happy path i przegapia reguły ukryte w handlerach. Nowi członkowie zespołu kopiują zachowanie z UI nie rozumiejąc prawdziwych ograniczeń. Interesariusze spierają się opiniami zamiast wskazywać na uzgodnione zachowanie.
Dobry rezultat to nie idealny dokument, lecz wspólna jasność. Każdy powinien potrafić odpowiedzieć: "Co się stanie, jeśli zrobię X?" i "Co system gwarantuje?" bez zgadywania. Mniej niespodzianek, krótsze przeglądy i mniej momentów "Czekaj, już to robi" — bo zespół patrzy na tę samą prawdę.
Gdy specyfikacja zgadza się z kodem, można bezpiecznie planować zmiany. Widać, co jest stabilne, co jest przypadkowe i czego brakuje, zanim wdroisz.
Żywa specyfikacja to krótki, edytowalny opis tego, co aplikacja faktycznie robi dziś. To nie dokument jednorazowy. Zmienia się zawsze, gdy zmienia się zachowanie, dzięki czemu zespół jej ufa.
Gdy mówimy o specyfikacjach funkcji wygenerowanych z kodu (na przykład z użyciem Claude Code), cel jest prosty: odczytać rzeczywiste zachowanie z tras, handlerów i ekranów, a potem zapisać to prostym językiem.
Przydatna żywa specyfikacja skupia się na tym, co widzi użytkownik i co system obiecuje. Powinna obejmować:
Czego nie powinno obejmować: organizacji kodu. Jeśli zaczynasz wymieniać nazwy plików i plany refaktoryzacji, schodzisz w szczegóły implementacyjne. Unikaj:
Lista luk to coś oddzielnego. To krótka lista niezgodności i niejasności, które znajdujesz podczas pisania specyfikacji.
Przykład: jedna trasa odrzuca pliki >10MB, ale UI mówi 25MB. To luka dopóki zespół nie zdecyduje, która reguła jest prawdziwa i nie zaktualizuje kodu lub specyfikacji.
Zacznij od małego fragmentu. Jeśli spróbujesz udokumentować całą aplikację, skończysz z kupą notatek, którym nikt nie zaufa. Wybierz jedną ścieżkę, którą użytkownicy potrafią opisać zdaniem, np. "zaprosić współpracownika", "checkout" lub "reset hasła". Dobry zakres to pojedynczy obszar funkcji, moduł lub podróż użytkownika od punktu wejścia do rezultatu.
Wybierz punkt wejścia według tego, gdzie leży prawda:
Zanim zaczniesz czytać kod, zbierz kilka wejść, żeby rozbieżności były widoczne szybko: istniejąca dokumentacja API, stare notatki produktowe, tickety supportu i „znane bolączki”. Nie zastępują one kodu, ale pomagają zauważyć brakujące stany jak błędy, przypadki brzegowe i uprawnienia.
Trzymaj format specyfikacji prosty i spójny. Zespoły szybciej się porozumiewają, gdy każda specyfikacja czyta się tak samo.
Używaj tej struktury wielokrotnie — twoje specyfikacje będą czytelne, porównywalne i łatwe do aktualizacji.
Zacznij od punktów wejścia na serwerze. Trasy i handlery pokazują „co aplikacja robi” w konkretnych terminach: kto może je wywołać, co muszą przesłać, co dostają w odpowiedzi i co zmienia się w systemie.
Wypisz trasy w zakresie i przypisz każdej zamiar użytkownika. Nie pisz „POST /api/orders.” Napisz „Złóż zamówienie” lub „Zapisz szkic.” Jeśli nie potrafisz nazwać zamiaru prostymi słowami, to już luka w specyfikacji.
Czytając każdy handler, zapisuj inputy i reguły walidacji jako wymagania widoczne dla użytkownika. Dołącz pola wymagane, dopuszczalne formaty i reguły, które powodują rzeczywiste błędy. Na przykład: „E‑mail musi być poprawny”, „Ilość musi być co najmniej 1”, „Data rozpoczęcia nie może być w przeszłości.”
Zapisuj też sprawdzenia autoryzacji i ról w prosty sposób. Zamiast "middleware: requireAdmin" udokumentuj: "Tylko admini mogą anulować dowolne zamówienie. Zwykli użytkownicy mogą anulować tylko swoje zamówienie w ciągu 10 minut." Jeśli kod sprawdza własność, flagi funkcji lub granice tenantów, dodaj to również.
Następnie zanotuj wyjścia i wyniki. Co zwraca sukces (stworzony ID, zaktualizowany obiekt)? Jak wyglądają typowe niepowodzenia (401 niezalogowany, 403 brak uprawnień, 404 nie znaleziono, 409 konflikt, 422 błąd walidacji)?
Na koniec zapisz efekty uboczne, bo są częścią zachowania: tworzone/aktualizowane rekordy, wysyłane e‑maile/powiadomienia, publikowane zdarzenia, kolejkowane zadania w tle i wszystko, co uruchamia inne przepływy. Te szczegóły zapobiegają niespodziankom, gdy później zespół będzie polegać na specyfikacji.
Trasy mówią, co aplikacja może zrobić. Komponenty mówią, jak użytkownik to doświadcza. Traktuj UI jako część kontraktu: co się wyświetla, co jest zablokowane i co się dzieje, gdy coś pójdzie nie tak.
Znajdź ekrany wejściowe dla funkcji. Szukaj komponentu strony, wrappera layoutu i kilku „komponentów decyzyjnych”, które kontrolują pobieranie danych, uprawnienia i nawigację. To zwykle tam leży prawdziwe zachowanie.
Czytając komponenty, zapisuj reguły, które użytkownik odczuwa: kiedy akcje są wyłączone, wymagane kroki, pola warunkowe, stany ładowania i jak błędy się pojawiają (błędy pod polem vs toast, automatyczne ponawianie, przycisk „spróbuj ponownie”). Zwróć uwagę na stan i cache: wyświetlanie przestarzałych danych najpierw, optymistyczne aktualizacje czy znaczniki „ostatnio zapisano”.
Szukaj też ukrytych przepływów, które cicho zmieniają to, co użytkownicy widzą. Przeszukaj kod pod kątem feature flagów, eksperymentów i bramek tylko dla adminów. Zauważ też ciche przekierowania, np. wysyłanie niezalogowanych do logowania lub użytkowników bez dostępu na ekran uaktualnienia.
Konkret: na ekranie „Zmień e‑mail” udokumentuj, że przycisk Zapisz jest wyłączony, dopóki e‑mail nie będzie poprawny, podczas żądania pokazuje się spinner, sukces wyświetla baner potwierdzający, a błędy walidacji z backendu renderują się pod polem. Jeśli w kodzie pojawia się flaga newEmailFlow, zanotuj obie warianty i różnice.
Pisz każdy przepływ UI jako krótkie kroki (co użytkownik robi, co UI robi w odpowiedzi) i trzymaj warunki oraz błędy przy kroku, którego dotyczą. To ułatwia czytelność i wykrywanie luk.
Surowe notatki z tras i komponentów są przydatne, ale trudne do dyskusji. Przepisz obserwacje w specyfikację, którą PM, designer, QA i inżynier mogą przeczytać i zgodzić się co do niej.
Praktyczny wzorzec to jedna historia użytkownika na trasę lub ekran. Trzymaj ją małą i konkretną. Na przykład: „Jako zalogowany użytkownik mogę zresetować hasło, aby odzyskać dostęp.” Jeśli kod pokazuje różne zachowanie w zależności od roli (admin vs user), rozdziel to na osobne historie zamiast ukrywać w przypisach.
Napisz kryteria akceptacji, które odzwierciedlają rzeczywiste ścieżki kodu, nie idealny produkt. Jeśli handler zwraca 401, gdy brakuje tokena, to jest kryterium. Jeśli UI wyłącza wysyłanie, dopóki pole nie będzie poprawne, to też jest kryterium.
Dołącz reguły dotyczące danych prostym językiem, zwłaszcza te, które powodują zaskoczenia: limity, kolejność, unikalność, pola wymagane. „Nazwy użytkowników muszą być unikalne (sprawdzane przy zapisie)” jest jaśniejsze niż „unikalny indeks”.
Przypadki brzegowe często decydują o tym, czy dokument jest ładny, czy użyteczny. Wypisz stany puste, wartości null, ponawiania, limity czasowe i to, co widzi użytkownik przy błędzie API.
Gdy natrafisz na nieznane, zaznacz to zamiast zgadywać:
Takie markery zamienią się w szybkie pytania dla zespołu, zamiast w ciche założenia.
Lista luk to nie kolejny Jira. To krótki, oparty na dowodach zapis miejsc, gdzie kod i zamierzona funkcja się nie zgadzają lub gdzie nikt nie potrafi jasno wyjaśnić, co jest „poprawne”. Dobrze zrobiona, staje się narzędziem do porozumienia, nie walki o priorytety.
Bądź rygorystyczny przy definiowaniu luki:
Gdy wpisujesz lukę, dołącz trzy elementy, by pozostała uziemiona:
Dowód zapobiega przemianie listy w opinie. Przykład: „POST /checkout/apply-coupon akceptuje przeterminowane kupony, ale CouponBanner.tsx blokuje je w UI. Wpływ: przychody i zamieszanie użytkowników. Typ: bug lub brakująca decyzja (potwierdź docelową regułę).”
Trzymaj listę krótką. Ustal twardy limit, np. 10 pozycji na pierwszy przegląd. Jeśli znajdziesz 40 problemów, pogrupuj je w wzory (niespójności walidacji, sprawdzenia uprawnień, stany puste) i zachowaj tylko najlepsze przykłady.
Unikaj dat i harmonogramów w liście luk. Jeśli potrzebujesz właściciela, zanotuj, kto powinien podjąć decyzję (produkt) lub kto może zweryfikować zachowanie (inżynieria), a planowanie przenieś do backlogu.
Wybierz mały, często używany zakres: checkout z kodami promocyjnymi i opcjami wysyłki. Celem nie jest przepisywanie całego produktu, lecz uchwycenie tego, co aplikacja robi dziś.
Zacznij od backendowych tras. To tam często pojawiają się reguły. Możesz znaleźć trasy takie jak POST /checkout/apply-promo, GET /checkout/shipping-options, POST /checkout/confirm.
Z tych handlerów zapisz zachowanie prostym językiem:
Następnie sprawdź komponenty UI. PromoCodeInput może pokazywać, że sumy odświeżają się dopiero po udanej odpowiedzi, a błędy renderują pod polem. ShippingOptions może automatycznie wybrać najtańszą opcję przy pierwszym załadowaniu i wywołać pełne odświeżenie rozbicia ceny, gdy użytkownik ją zmieni.
Masz teraz czytelną specyfikację i małą listę luk. Na przykład: komunikaty o błędach różnią się między trasą promocyjną a UI ("Invalid code" vs "Not eligible") i nikt nie potrafi wskazać jasnej reguły zaokrąglania podatku (po pozycji vs suma zamówienia).
W planowaniu zespół najpierw zgadza się co do rzeczywistości, a potem decyduje, co zmienić. Zamiast debatować opinie, przegląda się udokumentowane zachowania, wybiera jedną niespójność do naprawy i zostawia resztę jako "aktualne zachowanie" dopóki nie będzie warto go zmieniać.
Spec pomaga tylko wtedy, gdy zespół zgadza się, że odzwierciedla rzeczywistość. Zrób krótkie czytanie z jednym inżynierem i jedną osobą z produktu. Krótkie i konkretne: 20–30 minut skupienia na tym, co użytkownik może zrobić i co system odpowiada.
Podczas przeglądu zamieniaj stwierdzenia na pytania tak/nie. "Gdy użytkownik trafi na tę trasę, czy zawsze zwracamy 403 bez sesji?" "Czy ten pusty stan jest zamierzony?" To oddziela zamierzone zachowanie od przypadkowego, które wślizgnęło się z upływem czasu.
Uzgodnij słownictwo zanim zaczniesz edytować. Używaj słów widocznych w UI (napisy przycisków, tytuły stron, komunikaty). Dodawaj nazwy wewnętrzne tylko wtedy, gdy pomagają inżynierom znaleźć kod (nazwy tras, komponentów). To zapobiega rozjazdom typu produkt mówi "Workspace", a spec mówi "Org".
Aby utrzymać aktualność, określ właścicielstwo i rytm:
Jeśli używasz narzędzia typu Koder.ai, snapshoty i rollback pomagają porównać "przed" i "po" podczas aktualizacji specyfikacji, szczególnie po dużym refaktorze.
Najszybszy sposób, by stracić zaufanie do specyfikacji, to opisywać produkt, jaki chcesz, a nie ten, który masz. Twarda zasada: każde stwierdzenie powinno być poparte czymś, na co możesz wskazać w kodzie lub na ekranie.
Inna pułapka to przepisywanie kształtu kodu w dokumencie. Spec, który wygląda jak "Controller -> Service -> Repository" nie jest specyfikacją, to mapa folderów. Pisz w języku użytkownika: co wyzwala akcję, co widzi użytkownik, co jest zapisywane i jak wyglądają błędy.
Uprawnienia i role często ignorowane są na końcu — potem wszystko się sypie. Dodaj reguły dostępu wcześnie, nawet jeśli są nieporządne. Wypisz, które role mogą przeglądać, tworzyć, edytować, usuwać, eksportować lub zatwierdzać oraz gdzie reguła jest wymuszana (tylko UI, tylko API, albo oba).
Nie pomijaj ścieżek nie‑happy. Rzeczywiste zachowanie ukrywa się w ponowieniach, niepełnych błędach i regułach czasowych jak wygaśnięcia, cooldowny, zadania harmonogramowe czy limity typu "raz na dzień". Traktuj je jako pierwszorzędne zachowania.
Szybki sposób na odkrycie luk to sprawdzenie:
Wreszcie, popychaj listę luk do przodu. Każda luka powinna dostać etykietę: "unknown/needs decision", "bug/fix" lub "missing feature/plan". Jeśli coś nie zostanie oznaczone, lista stoi, a spec przestaje być żywy.
Zrób szybki przegląd pod kątem jasności, pokrycia i możliwości działania. Ktoś, kto nie pisał specu, powinien zrozumieć, co funkcja robi dziś i co jest nadal niejasne.
Przeczytaj spec jak nowy członek zespołu w dniu pierwszym. Jeśli potrafi podsumować funkcję w minutę, jesteś blisko. Jeśli ciągle pyta "gdzie to się zaczyna?" lub "jaka jest wolna ścieżka?", popraw otwarcie.
Sprawdź:
Każda luka powinna być konkretna i testowalna. Zamiast "Obsługa błędów niejasna", napisz: "Jeśli provider płatności zwróci 402, UI pokazuje ogólny toast; potwierdź docelowy komunikat i zachowanie ponawiania." Dodaj jedną następną akcję (zapytać produkt, dodać test, sprawdzić logi) i zanotuj, kto powinien odpowiedzieć.
Wybierz jedną funkcję i ogranicz ją czasowo do 60 minut. Wybierz coś małego, ale realnego (logowanie, checkout, wyszukiwanie, ekran admina). Napisz jedno zdanie zakresu: co jest w zakresie, a co wykluczone.
Przeprowadź workflow end‑to‑end raz: przejrzyj kluczowe trasy/handlery, prześledź główny przepływ UI i zapisz obserwowalne zachowania (inputy, outputy, walidacja, stany błędów). Jeśli utkniesz — zapisz pytanie jako lukę i idź dalej.
Gdy skończysz, udostępnij spec zespołowi do komentarzy i ustal jedną zasadę: każda zmiana zachowania powinna zaktualizować spec w tym samym oknie dostawy, nawet jeśli to tylko pięć linijek.
Trzymaj listę luk oddzielnie od backlogu. Grupuj je w "nieznane zachowanie", "niespójne zachowanie" i "brak testów", potem przeglądaj szybko co tydzień, by zdecydować, co jest ważne teraz.
Jeśli tworzenie i iteracja idą zbyt wolno, narzędzie czatowe jak Koder.ai może pomóc szybko uzyskać wersję początkową. Opisz funkcję, wklej kluczowe fragmenty lub nazwy tras, dopracuj w rozmowie i eksportuj źródła gdy potrzebujesz. Chodzi o szybkość i wspólną jasność, nie o większy proces.
Zacznij od jednej małej, widocznej dla użytkownika części (na przykład „reset hasła” lub „zaproszenie współpracownika”). Przeczytaj najpierw routes/handlers, aby uchwycić reguły i rezultaty, a potem przejrzyj przepływ UI, żeby zapisać, co użytkownicy faktycznie widzą (stany wyłączone, błędy, przekierowania). Zapisz to w spójnym szablonie i loguj nieznane kwestie osobno jako listę luk.
Domyślnie: traktuj bieżące zachowanie kodu jako źródło prawdy i je udokumentuj.
Jeśli zachowanie wygląda na przypadkowe lub niespójne, nie „naprawiaj” go w specyfikacji — oznacz jako lukę z dowodem (gdzie to zauważyłeś i jak się objawia), a potem podejmij decyzję, czy zmienić kod czy specyfikację.
Utrzymuj format nudny i powtarzalny. Praktyczny szablon to:
Taki układ ułatwia czytanie i szybkie wychwycenie rozbieżności.
Opisuj reguły w języku zrozumiałym dla użytkownika, a nie jako notatki do kodu.
Przykłady:
Zanotuj, co powoduje błąd i jak użytkownik to zobaczy.
Skup się na tym, co jest obserwowalne:
Efekty uboczne są ważne, bo wpływają na inne funkcje oraz oczekiwania supportu/ops.
Jeśli UI blokuje coś, co API akceptuje (lub odwrotnie), wpisz to jako lukę dopóki nie zapadnie decyzja.
Zapisz:
Następnie uzgodnij jedną regułę i zaktualizuj zarówno kod, jak i specyfikację.
Trzymaj listę luk krótką i opartą na dowodach. Każdy wpis powinien zawierać:
Unikaj planowania terminów lub zamieniania listy w drugi backlog.
Dokumentuj je jawnie zamiast ukrywać.
Uwzględnij:
To zwykle miejsca, gdzie pojawiają się niespodzianki i błędy.
Krótka sesja: 20–30 minut z jednym inżynierem i jedną osobą z produktu.
Zamieniaj stwierdzenia na pytania tak/nie (np. „Czy zawsze zwracamy 403 gdy brak sesji?”). Uzgadniaj słownictwo używając etykiet z UI (napisy przycisków, tytuły stron, komunikaty), żeby wszyscy mówili o tym samym.
Przytrzymaj spec blisko kodu i wprowadź aktualizacje razem z wdrożeniami.
Proste domyśły:
Cel: małe, częste poprawki — nie wielka refaktoryzacja.