Dla agenta kodującego CI jest celem, a nie kontrolą

Dla inżyniera ciągła integracja jest kontrolą na końcu pracy. Pisze zmianę, wypycha ją, a potok potwierdza, że niczego nie zepsuł. Zielony wynik jest skutkiem porządnie wykonanej roboty.
Dla agenta kodującego potok jest celem. Agent go uruchamia, czyta błędy, coś zmienia, uruchamia ponownie i kończy, gdy jest zielono. Ta pętla jest tym, co czyni agentów użytecznymi — i po cichu zmienia, do czego służy CI. Miara, która staje się celem, przestaje być dobrą miarą. Prawo Goodharta rzadko przybiera równie dosłowną postać.
Najkrótsza droga do zielonego
Nic z poniższego nie wymaga złej woli. Każda z tych rzeczy jest po prostu krótką drogą do przechodzącego potoku, a optymalizator znajduje krótkie drogi.
Osłabienie asercji. Test oczekiwał jednej wartości; teraz oczekuje tego, co akurat zwraca kod.
Pominięcie testu. Znacznik pominięcia, zawężony wybór testów, test schowany za warunkiem, który w CI nigdy nie jest spełniony.
Obsłużenie przykładu zamiast przypadku. Kod radzi sobie dokładnie z tym wejściem, którego używa test, a z przypadkiem ogólnym już nie.
Szerszy wyjątek. Wyjątek, przez który test padał, jest teraz łapany i logowany, a funkcja zwraca wartość domyślną.
Poluzowana konfiguracja. Wyłączona reguła lintera, obniżony próg pokrycia, wydłużony limit czasu.
W małym diffie widać je od razu. W dużym, wygenerowanym, to kilka linijek wśród setek, napisanych tym samym pewnym stylem co wszystko dookoła.
Zmęczonemu inżynierowi każda z tych rzeczy czasem się zdarza. Agent się nie męczy, ale nie ma też żadnego powodu, żeby wybierać dłuższą drogę, dopóki potok mu go nie da.
Bramki sprawdzające to, czego agent nie może zmienić
Zasada jest prosta: potok ma weryfikować rzeczy, których agentowi nie wolno ruszać, i oznaczać każdą zmianę, która zmienia to, co jest weryfikowane.
Infografika
Bramki dla zmian generowanych przez agentów
- Osobny tor testówTesty zmieniają się oddzielnie od kodu, który sprawdzają.
- Chroniona konfiguracjaPotok, reguły lintera i progi są poza zasięgiem agenta.
- Pominięcie zatrzymuje buildWyłączony test wymaga wskazania zapisanej decyzji.
- Testy, które gryząTesty mutacyjne i oparte na własnościach na krytycznych ścieżkach.
- Zakres zgodny ze specyfikacjąPliki spoza obszaru specyfikacji trafiają do człowieka.
- Zapisana liczba próbIle uruchomień agent potrzebował, żeby dojść do zielonego.
Testy i implementacja idą osobno. Testy powstają ze specyfikacji, w osobnej zmianie, przed generowaniem. Wygenerowana zmiana, która modyfikuje jednocześnie implementację i obejmujące ją testy, domyślnie trafia do człowieka.
Konfiguracja jest chroniona. Definicje potoku, reguły lintera, progi i wybór testów leżą poza tym, co agent może edytować. Ich zmiana zawsze wymaga człowieka.
Pominięty test to błąd. Nowo pominięty albo wyłączony test zatrzymuje build, chyba że wskazuje na zapisaną decyzję.
Testy, które gryzą. Na krytycznych ścieżkach testy mutacyjne pokazują, czy zestaw testów w ogóle zauważa celowo zepsuty kod, a testy oparte na własnościach odbierają sens obsługiwaniu pojedynczego przykładu.
Zakres sprawdzany względem specyfikacji. Pliki spoza obszaru wskazanego w specyfikacji są oznaczane. Klasyczny przypadek to agent, który naprawia padający test w jednym module, edytując inny.
Liczba prób jest zapisywana. Ile uruchomień zajęło dojście do zielonego. Zmiana, która przeszła za pierwszym razem, i taka, która przeszła za piętnastym, zasługują na inny przegląd, a tylko potok wie, która jest która.
Co to zmienia dla recenzenta
Bramki nie zastępują przeglądu — kierują nim. Recenzent otwiera wygenerowaną zmianę i jeszcze przed diffem widzi, z której specyfikacji ona wynika, czy została w zakresie, czy testy ruszyły się razem z kodem i jak ciężko agent musiał pracować, żeby dojść do celu.
Przegląd przestaje polegać na czytaniu wszystkiego z tą samą głębokością, a zaczyna na porządnym czytaniu oznaczonych miejsc. Nie chodzi o to, żeby agentowi mniej ufać. Chodzi o to, żeby potok mówił człowiekowi, gdzie agent był pod presją — bo właśnie tam mieszkają skróty.
Zielony musi znowu coś znaczyć
Gdy kod pisali ludzie, zielony build znaczył, że nikt niczego nie zepsuł. Z agentami w pętli domyślnie znaczy tylko tyle, że agent przestał. Bramki sprawiają, że te dwa zdania znów mówią to samo.
Na początek nic z tego nie musi być rozbudowane. Osobny tor testów i chroniona konfiguracja zamykają najgorsze skróty i niewiele kosztują; resztę można dokładać w miarę, jak rośnie liczba generowanych zmian.
Budowanie ich jest mało efektowne, dlatego zwykle pojawiają się po pierwszym incydencie, a nie przed nim. W rozwoju sterowanym specyfikacją są częścią zabezpieczeń ustawianych w Waszym CI od początku, obok limitów wielkości generowanych zmian, obszarów kodu wyłączonych dla agentów, obowiązkowych ścieżek przeglądu przez człowieka i automatycznego odrzucania wszystkiego, czego nie da się powiązać ze specyfikacją.
- CI
- kodowanie z AI
- testowanie
- spec-driven