Otwórz repozytorium sześć miesięcy po wdrożeniu funkcji, a da się odtworzyć naprawdę wiele. Możesz prześledzić architekturę, sprawdzić schemat, przeczytać testy i zobaczyć dokładnie, które linie się zmieniły.
Tego, czego zwykle nie da się odtworzyć, to rozmowa, która sprawiła, że te linie stały się konieczne.
Kod nie powie ci, że reguła walidacji istnieje dlatego, że jeden klient wysyła błędnie sformatowane eksporty. Nie wyjaśni, że nietypowa polityka ponawiania prób zapobiega duplikowaniu transakcji w systemie downstream. Nie pokaże, że bardziej przejrzysty interfejs odrzucono po teście dostępności ani że granica między usługami wynika z ograniczenia kontraktowego, a nie z preferencji inżynieryjnych.
Git świetnie zachowuje historię kodu. Intencję zachowuje tylko wtedy, gdy zespół świadomie ją zapisuje i utrzymuje jej powiązanie z implementacją.
Ta luka zawsze była częścią inżynierii oprogramowania. Narzędzia AI do pisania kodu czynią ją bardziej widoczną. System może przeczytać każdy plik w repozytorium, prześledzić każdy symbol i wygenerować technicznie przekonujący patch, a mimo to rozwiązywać niewłaściwy problem.
Problem nie polega na tym, że kod wprowadza w błąd. Kod odpowiada na węższe pytanie.
Pięć warstw prawdy inżynieryjnej
Większość istotnych zmian w oprogramowaniu zależy od pięciu różnych warstw dowodów.
- Intencja — Jakiego rezultatu oczekuje użytkownik, klient lub firma? Może to być zapisane w specyfikacji, zgłoszeniu, rozmowie z supportem lub notatce ze spotkania.
- Ograniczenia — Czego nie wolno zepsuć? Obietnice kompatybilności, granice bezpieczeństwa, regulacje, umowy, budżety i terminy często znajdują się poza repozytorium.
- Implementacja — Jak system działa dziś? Tę warstwę tworzą kod, testy, schematy, zależności i konfiguracja wdrożenia.
- Dowody z działania systemu — Co dzieje się w rzeczywistym systemie? Logi, ślady, metryki, dane produkcyjne i raporty z incydentów mogą przeczyć założeniom, które w kodzie wyglądają rozsądnie.
- Historia decyzji — Dlaczego wybrano obecne podejście? Odpowiedź kryje się w pull requestach, dyskusjach projektowych, odrzuconych alternatywach i wcześniejszych incydentach.
Repozytorium jest najmocniejsze w trzeciej warstwie. Zawiera elementy pozostałych, ale rzadko w stopniu wystarczającym, by reprezentować je w pełni.
To ma znaczenie, ponieważ awarie oprogramowania często pojawiają się na granicach między warstwami. Implementacja odpowiada nieaktualnej specyfikacji. Poprawka spełnia wymagania zgłoszenia, ale narusza ograniczenie operacyjne. Testy przechodzą, bo kodują założenia z wczoraj. Kod jest wewnętrznie spójny, podczas gdy dane produkcyjne podążają za wzorcem, którego nikt nie udokumentował.
Lokalnie poprawny patch nadal może być niewłaściwą zmianą.
Czego samo repozytorium nie potrafi rozstrzygnąć
Wyobraź sobie użytkownika, który edytuje dokument, a potem wyszukuje zaktualizowane zdanie, ale w wynikach nadal widzi starą wersję. „Spraw, żeby wyszukiwanie aktualizowało się natychmiast” brzmi jak jasna prośba. Repozytorium pokazuje kilka możliwych miejsc, od których można zacząć, ale samo nie potrafi wskazać właściwej poprawki.
| Pytanie | Prawdopodobne źródło |
|---|---|
| Która wersja dokumentu jest autorytatywna? | Dokument źródłowy i historia zmian |
| Gdzie pozostaje stary tekst? | Logi synchronizacji, wynik ekstrakcji, indeks wyszukiwania lub cache |
| Co oznacza „natychmiast” w tym produkcie? | Obietnica produktowa lub cel świadczenia usługi |
| Czy uprawnienia dokumentu zmieniły się wraz z jego treścią? | Uprawnienia źródłowe i historia audytu |
| Czy nieaktualny wynik ogranicza się do jednego użytkownika, źródła lub regionu? | Ślady żądań i metryki produkcyjne |
Kod wyszukiwania może wyjaśniać, jak zwracane są wyniki. Nie powie jednak, czy rzeczywistym problemem jest opóźnienie synchronizacji, nieaktualna ekstrakcja, unieważnianie cache, propagacja uprawnień czy oczekiwanie, którego produkt nigdy nie zdefiniował.
To rozróżnienie staje się jeszcze ważniejsze w dojrzałych systemach. Pole, które wygląda na przestarzałe, może nadal obsługiwać starszego klienta. Usługa wyglądająca na zduplikowaną może rozdzielać dane o różnych wymaganiach dotyczących uprawnień. Pozornie nadmiarowa kontrola może być jedynym śladem w kodzie po incydencie produkcyjnym, którego obecny zespół nigdy nie widział.
Usuwanie złożoności ma wartość. Usuwanie historii przebranej za złożoność jest kosztowne.
Więcej kontekstu nadal może prowadzić do błędnej odpowiedzi
Oczywistym rozwiązaniem wydaje się dostarczenie AI większej ilości materiału: całego repozytorium, każdego zgłoszenia, każdego dokumentu, każdej wiadomości i każdego logu.
To daje dostęp, a nie zrozumienie.
Źródła mogą być nieaktualne, sprzeczne, spekulatywne albo pisane z myślą o różnych odbiorcach. Burza mózgów nie powinna mieć większej wagi niż zatwierdzona specyfikacja. Wymaganie sprzed sześciu miesięcy nie powinno po cichu unieważniać wczorajszej decyzji produktowej. Log produkcyjny powinien być powiązany z wydaniem, środowiskiem i ścieżką kodu, które go wygenerowały. Prośba klienta nie powinna być traktowana jako uniwersalne wymaganie bez sprawdzenia jej zakresu.
Poważny system kontekstowy potrzebuje więc czegoś więcej niż tylko wyszukiwania. Potrzebuje sposobu rozumowania o:
- Autorytecie: Które źródło ma prawo definiować wymaganie?
- Aktualności: Które informacje są bieżące, a które zostały zastąpione?
- Pochodzeniu: Skąd wzięło się każde twierdzenie, ograniczenie lub wniosek?
- Powiązaniach: Które zgłoszenie, wydanie, klient, zbiór danych i ścieżka kodu należą do siebie?
- Uprawnieniach: Których źródeł wolno użyć do tego zadania i pokazać tej osobie?
Kontekst nie jest stosem tokenów. To graf z czasem, autorytetem i granicami.
Więcej kontekstu powinno dawać więcej dowodów, a nie większą pewność bez dowodów.
Rzeczywistą jednostką pracy jest zmiana
Edytory i narzędzia programistyczne są zorganizowane wokół plików, bo to pliki modyfikujemy. Zespoły inżynieryjne są zorganizowane wokół zmian.
Zmiana zaczyna się od powodu. Przeradza się w wymaganie, dotyka kodu i danych, przechodzi przez review, trafia na produkcję i tworzy nowe dowody. Jeśli te etapy pozostają rozłączne, każde przyszłe zadanie zaczyna się od kolejnej rundy archeologii.
System AI pracujący nad rzeczywistym oprogramowaniem powinien podążać za tym cyklem życia.
Przed implementacją powinien zidentyfikować zgłoszenie, istotne ograniczenia i wszelkie sprzeczne źródła. Powinien wiedzieć, czy naprawia defekt, zmienia oczekiwane zachowanie, czy wprowadza nowy kontrakt.
W trakcie implementacji powinien łączyć każdą istotną decyzję z dowodami. Dlaczego ten moduł? Dlaczego ta strategia migracji? Dlaczego zachować tę gałąź? To wyjaśnienie powinno przetrwać dłużej niż czat, w którym powstał kod.
Po wdrożeniu powinien dołączyć do zmiany wyniki weryfikacji, decyzje z przeglądu i nowo odkryte ograniczenia. W przeciwnym razie kolejna osoba — albo kolejna sesja AI — będzie musiała odkrywać je na nowo.
Na tym polega różnica między narzędziem, które potrafi edytować repozytorium, a systemem, który potrafi uczestniczyć w pracy inżynierskiej.
AI powinno ograniczać odtwarzanie kontekstu, a nie zastępować osąd
Lepszy kontekst bywa czasem przedstawiany jako droga do autonomicznego tworzenia oprogramowania. Jego bezpośrednia wartość jest mniej spektakularna i bardziej użyteczna: obniża koszt odtwarzania rzeczywistości przed wprowadzeniem zmiany.
AI może zestawić pierwotne wymaganie z odpowiednim kodem. Może wydobyć incydent, który wyjaśnia nietypowe zabezpieczenie. Może powiązać zawodzący wskaźnik z wydaniem, które go zmieniło. Może pokazać, że dwa autorytatywne źródła są ze sobą sprzeczne, zanim jeszcze rozpocznie się implementacja.
Te możliwości nie eliminują inżynierskiego osądu. Sprawiają, że jest on lepiej poinformowany.
Człowiek nadal musi zdecydować, który kompromis jest akceptowalny, czy wymaganie jest kompletne i ile ryzyka może nieść wydanie. System powinien uwidaczniać dowody i umożliwiać prześledzenie toku rozumowania. Nie powinien ukrywać niepewności za dopracowaną łatką.
Standardem nie jest „czy potrafi generować kod?”
Standardem jest „czy potrafi wyjaśnić, dlaczego to jest teraz właściwa zmiana?”
Od świadomości repozytorium do świadomości pracy
Asystenci programowania po raz pierwszy stali się użyteczni, gdy zaczęli rozumieć plik znajdujący się przed programistą. Świadomość repozytorium była kolejnym dużym krokiem: odnajdywanie powiązanego kodu, śledzenie symboli i wprowadzanie zmian w całym projekcie.
Kolejnym krokiem jest świadomość pracy otaczającej repozytorium.
Oznacza to łączenie kodu ze specyfikacją, która go wymagała, rozmową, która go doprecyzowała, dowodami z produkcji, które go podważyły, oraz decyzją, którą później należy zapamiętać. Oznacza to również wykluczanie kontekstu, który jest nieistotny, nieaktualny lub wykracza poza uprawnienia użytkownika.
Budując Dvina, stale wracamy do tej idei. Praca nie toczy się w obrębie jednego pliku, aplikacji ani rozmowy. Znaczenie tkwi w połączeniach między nimi oraz w tym, jak te połączenia zmieniają się w czasie.
Repozytorium pozostaje niezbędne. Jest wykonywalnym źródłem prawdy o zachowaniu systemu. Po prostu nie jest pełnym źródłem prawdy o intencji produktu, rzeczywistości operacyjnej ani pamięci organizacyjnej.
Cała historia zmienia to, co powstaje
Mając tylko kod, naturalne pytanie brzmi:
Jaka zmiana pasuje do tego systemu?
Przy szerszym kontekście pytanie brzmi:
Jaka zmiana pasuje do tego systemu, tego wymagania, tej historii i tej chwili?
To drugie pytanie pozwala wychwycić ograniczenia, zanim przerodzą się w regresje. Daje recenzentom uzasadnienie stojące za implementacją. Pomaga nowym członkom zespołu zrozumieć, dlaczego system wygląda właśnie tak. Nadaje AI konkretną, osadzoną w realiach rolę: nie wyroczni w edytorze, lecz uczestnika, który potrafi zebrać dowody z całego procesu pracy.
Twoje repo nigdy nie było całą historią.
Szansa polega na budowaniu systemów, które potrafią odczytać całą resztę — i pokazać, jak do tego doszły.

