← Wstecz Harupa
2026-07-04RU EN UA BY PL

My Architect, część 10: pamięć repozytorium — graf kodu, któremu nie wolno wierzyć na słowo

To dziesiąty artykuł serii o My Architect i ciąg dalszy dziewiątego — historii skilla recursive-context, który uczy agenta dyscypliny pracy z danymi większymi niż okno kontekstowe. Tym razem: cztery wydania w jeden dzień (v1.14.0 → v1.16.1), które dały agentowi trwały graf kodu, oraz kontrolowany eksperyment, który zmierzył jego realną wartość zamiast powtarzać cudzy marketing. Wszystkie liczby z naszych przebiegów pochodzą z telemetrii realnych uruchomień z 2026-07-03; fakty o Graphify — z jego README i żywej instalacji; szacunki są oznaczone jawnie. Nic nie jest zmyślone.

Prolog. Agent z amnezją

Agent LLM nie ma pamięci między sesjami. Każda nowa rozmowa o twoim repozytorium zaczyna się od czystej kartki: agent znów grepuje, znów czyta te same pliki, znów buduje w głowie tę samą mapę — i wyrzuca ją na końcu sesji. Zmierzyliśmy to na własnym repozytorium: zebranie faktów o dobrze znanej bazie kodu kosztowało ~77 tysięcy tokenów i 20 wywołań narzędzi — i tak każdą sesję, w kółko.

Osobna bolączka to pytania w rodzaju „co się zepsuje, jeśli zmienię sygnaturę tej funkcji?". Odpowiedź wymaga znajomości wszystkich konsumentów symbolu. Grep ich znajdzie, ale za cenę pełnego przejścia; a co ważniejsze — agent nie ma miejsca, w którym ta wiedza mogłaby przeżyć sesję.

Wokół tego bólu wyrósł już rynek narzędzi „kod-jako-graf" — z hasłami w stylu „90% oszczędności tokenów" i „agent 500 razy mądrzejszy". Nam nie były potrzebne hasła, tylko odpowiedź na dwa pytania: jakie klasy błędów to usuwa i gdzie oszczędność jest prawdziwa, a gdzie to populizm. Spoiler: na końcu artykułu — tabela ze zmierzonymi liczbami.

Rozdział 1. Nie budować swojego: Graphify

Narzędzie do trwałej pamięci o kodzie już istnieje — Graphify (open source, MIT, ~77k gwiazdek): parsuje kod tree-sitterem w pełni lokalnie (36 języków, bez wywołań API i telemetrii), składa graf symboli i powiązań do graphify-out/graph.json, obok kładzie interaktywną mapę HTML i gotowy tekstowy raport o repozytorium. Świeżość indeksu utrzymują git-hooki; do pracy zespołowej jest merge-driver, żeby graf dało się commitować bez konfliktów.

Świadomie nie zaczęliśmy budować własnego silnika grafowego. Zamiast tego nauczyliśmy nasz skill dyscypliny dekompozycji rozpoznawać leżący w repozytorium indeks i poprawnie z niego korzystać. Cała funkcja to markdownowy przewodnik z regułami plus kilka linijek-drogowskazów: plugin nie zyskał ani jednej twardej zależności. Nie ma grafu — wszystko działa jak dawniej; nie ma grafu, a zadanie jest ciężkie — agent raz zaproponuje właścicielowi instalację i budowę (i zrobi to sam po „tak"; ciche instalacje są zakazane).

Jak tanie jest to w praktyce: na naszym repozytorium (351 plików) budowa grafu zajęła sekundy i dała 2655 węzłów, 4948 krawędzi i 153 automatycznie znalezione klastry — 6.1 MB na dysku, zero kosztów API. Jedno zapytanie po tym wygląda tak:

$ graphify explain "getBlockers"
Node: getBlockers()   Source: src/hierarchy/model.ts L419   Degree: 9
  <-- NodePropertiesPanel.tsx [imports]
  <-- validator.ts [imports]
  <-- validateHierarchy() [calls]
  ...

Sekunda — i agent ma wszystkich konsumentów funkcji ze ścieżkami. To, co wcześniej wymagało pełnego przejścia po repozytorium, stało się zapytaniem. Ważny szczegół dla całej dalszej rozmowy o ekonomii: sam graf w ogóle nie zużywa tokenów — i budowa, i zapytania to lokalne narzędzia, a nie wywołania modelu.

Rozdział 2. Reguła, dla której to wszystko powstało

Indeks to cache, a cache umie kłamać: zostaje w tyle za kodem między przebudowami. Dlatego w centrum funkcji nie stoją komendy, lecz trzy reguły:

  1. Graf to nawigacja i kandydaci, NIE źródło faktów. Odpowiedź grafu mówi, GDZIE patrzeć; faktem staje się tylko to, co potwierdził żywy plik. Kontrakt faktów ({twierdzenie, ścieżka-dowód, pewność}) nie zmienił się ani na jotę.
  2. Freshness-check jest obowiązkowy. Pierwszym krokiem agent porównuje czas budowy indeksu z czasem ostatniego commita. Przeterminowany — powiedzieć głośno, zaproponować właścicielowi przebudowę (a jeśli git-hooka nie ma — raz zaproponować też hooka, żeby przeterminowanie nie powtarzało się co sesję), kandydatów oznaczać „według nieaktualnego indeksu".
  3. Verify — oszczędnie, regionami. Kandydat przychodzi ze ścieżką:linią — weryfikacja czyta ±30 linii wokół, a nie cały plik. Bez tej reguły weryfikacja zjada wszystko, co graf zaoszczędził na wyszukiwaniu.

Rozdział 3. Jak to testowaliśmy

Skill to tekst, który ma zmieniać zachowanie modelu. Tekstu nie skompilujesz i unit-testem nie pokryjesz, dlatego weryfikacja jest warstwowa, a każda warstwa łapie swoją klasę błędów. Żelazna zasada wszystkich wydań: testy pisze się przed poprawkami, a najpierw utrwala się, „jak agent myli się bez nich".

Warstwa 1 — triggery: czy skill załaduje się sam. Sędziowie widzą tylko nazwę i opis skilla (dokładnie to, co widzi Claude Code przy wyborze) plus zapytanie; trzech niezależnych sędziów na case; w zestawie — pozytywy w dwóch językach, podstępne prawie-trafienia („zmień nazwę zmiennej" — wygląda jak pytanie o impact, ale skill ma milczeć) i cross-check, że nowy skill nie kradnie triggerów sąsiedniego. Finalny przebieg: 30/30 głosów dokładnie według klucza.

Warstwa 2 — zachowanie: czy dyscyplina jest przestrzegana. Wykonawca czyta skill z dysku i pisze plan według scenariusza; niezależny grader linijka po linijce porównuje go z zapisanymi wcześniej twierdzeniami. Każdy scenariusz uderza w konkretny sposób zepsucia się: świeży graf → zapytania przed grepem, ale fakty z plików; przeterminowany → zauważyć i nie ufać; grafu nie ma → zaproponować raz i nie instalować po cichu.

Warstwa 3 — złośliwe review samego tekstu. Osobny recenzent nie czyta skilla uprzejmie — on go wykonuje: uruchamia shellowe snippety na wejściach brzegowych, podnosi dockera, sprawdza każdą nazwę komendy z README upstreamu.

Warstwa 4 — przebiegi live: prawdziwa instalacja (za zgodą), prawdziwy graf, prawdziwy agent na prawdziwym repozytorium.

Warstwa 5 — kontrolowany eksperyment (rozdział 5): gdy jakościowe sprawdzenia są zaliczone, zostaje pytanie „a ile to kosztuje?" — i na nie odpowiada tylko A/B z telemetrią.

Rozdział 4. Co złapaliśmy przed eksperymentem. Cztery historie

Pułapka warunkowego routingu. Dodaliśmy gałąź „grafu nie ma → zaproponuj właścicielowi budowę" — a review pokazało, że jest nieosiągalna: wszystkie drogowskazy prowadzące agenta do przewodnika grafu zaczynały się od słów „jeśli graf JEST". Agent bez grafu po prostu nie otworzyłby pliku z propozycją. Klasyczny błąd: nowa gałąź istnieje, ale wszystkie drogi do niej są bramkowane na stan, w którym nie jest potrzebna.

Bug, który żyłby tylko na Linuksie. Snippet sprawdzania świeżości używał macOS-owej składni stat z fallbackiem na wariant GNU. Recenzent podniósł dockera i pokazał: w GNU stat ten sam flag znaczy co innego — komenda „pomyślnie" drukuje śmieci, a bramka wiecznie odpowiada STALE. Na każdej maszynie linuksowej graph-first nie włączyłby się nigdy, po cichu.

Upstream wie lepiej. Radziliśmy chować graphify-out/ w .gitignore — a README Graphify rekomenduje zespołom commitowanie grafu (wspólna mapa; konflikty rozwiązuje ich merge-driver). Nasza rada po cichu wyrzucała scenariusz zespołowy; teraz propozycja uczciwie daje wybór. Przy okazji wyszło, że pakiet na PyPI nazywa się graphifyy — z dwoma „y".

Wykonawca, który nie uwierzył warunkom zadania. Scenariusz testu behawioralnego twierdził „graf jest świeży" — agent sprawdził mtime naprawdę, odkrył, że graf jego realnego środowiska się przeterminował (nasze własne commity zdążyły go wyprzedzić), i obsłużył rozbieżność według przepisu. Dyscyplina „nie ufaj, sprawdzaj" zadziałała nawet przeciw tekstowi zadania.

Osobnym podejściem przeprowadziliśmy audyt „na co agent sam nie wpadnie" — i zamknęliśmy trzy luki: pytania o impact dostały własne wejście do skilla (wcześniej „co się zepsuje, jeśli zmienię X?" poza trackowanym zadaniem nie prowadziło do grafu w ogóle), gotowy raport GRAPH_REPORT.md jest teraz czytany jako pierwszy przy audycie (podsumowanie jest już policzone — głupio zbierać je zapytaniami), a przy przeterminowanym grafie bez hooka agent proponuje hooka.

Rozdział 5. Eksperyment: mierzymy sami, a nie cytujemy marketing

Projekt. Nieznane obu grupom duże repozytorium — NestJS, 2125 plików (o rząd wielkości więcej niż nasze). Dwa identyczne klony: ramię A — z grafem (12309 węzłów, 22895 krawędzi, 738 klastrów; zbudowany tree-sitterem w sekundy, $0), ramię B — bez. Trzy klasy pytań, prompty identyczne co do ścieżki, o grafie — ani słowa (ramię A ma obowiązek znaleźć go samo, według dyscypliny skilla), jeden model (Sonnet), jeden kontrakt wyjścia (≥8 faktów ze ścieżkami + uczciwe pokrycie + dziennik wszystkich wywołań). Metryki — tokeny i wywołania z telemetrii, jakość — liczba faktów i wyrywkowa weryfikacja ścieżek.

Wyniki:

Klasa pytaniaA (graf)B (bez grafu)Delta
Impact: „konsumenci ModuleRef, co się zepsuje przy zmianie get()"71.4k tokenów · 26 wywołań · solo · 12 faktów71.9k · 31 wywołań · solo · 14 faktówparytet (A: −16% wywołań i czasu)
Zrozumienie: „HTTP-request lifecycle end-to-end"75.9k · solo · 13 faktów56.1k na wierzchu + 205.8k w ukrytych sub-agentach (zmierzone) ≈ 262k · 21 faktówgraf tańszy ~3.5× (−71%)
Mapa: „packages/core: moduły, API, ryzyka"≈445k (8 sub-agentów, szacunek*) · 24 fakty≈500k (9 sub-agentów, szacunek*) · 25 faktów~parytet

\* Szacunek kosztu zagnieżdżonego jest skalibrowany na jedynej dokładnie zmierzonej komórce (Q2-B: 205 759 tokenów na 5 agentów) i oznaczony jako szacunek; kierunek błędu jest nieznany.

Wniosek 1: oszczędność jest prawdziwa, ale selektywna. W klasie „zrozumieć podsystem" — zmierzone −71%: nie dlatego, że zapytania grafu są tańsze od grepa, lecz dlatego, że graf od razu zawęził korpus i jeden agent poradził sobie tam, gdzie ramię B było zmuszone po cichu rozwinąć piątkę. W klasie impact oszczędność — zero (grep po dosłownej nazwie symbolu jest tani nawet na 2125 plikach; wygrana grafu to tam kompletność i szybkość, nie tokeny). Na pełnym audycie — zero (orkiestracja jest potrzebna obu; graf daje gotowe partycjonowanie i kandydatów, nie zniżkę). Uniwersalny mnożnik „90%" nie istnieje — istnieje klasa zadań.

Wniosek 2, metodologiczny — ukryta orkiestracja. Po wierzchnich liczbach ramię B na „zrozumieniu" wyglądało taniej (56k wobec 76k) — dopóki nie odkryliśmy w jego transkryptach 205.8k tokenów zagnieżdżonych agentów. Ładne porównania „agent z narzędziem kontra agent bez" systematycznie niedoszacowują ramię, które po cichu deleguje. Uczciwy pomiar ma obowiązek liczyć całe drzewo agentów — podejrzewamy, że niemała część popularnych liczb tego nie robi.

Dyscyplina nieufności wobec grafu zadziałała także wewnątrz eksperymentu: ramię A na pytaniu o impact odsiało fałszywie pozytywnych kandydatów grafu (barrel-importy) żywym grepem, a na audycie zweryfikowało cykle z grafu i dwa fałszywe odrzuciło. Graf dawał tropy — faktami stawało się tylko potwierdzone.

Bonus, którego nikt nie zamawiał: audytowe agenty ramienia B znalazły w rdzeniu NestJS dwa wyglądające na prawdziwe bugi (przypisanie do Map przez indeks, które nigdy nie jest czytane; return zamiast continue, po cichu ucinający rejestrację middleware) — nieplanowane potwierdzenie, że głębia audytu tej dyscypliny jest prawdziwa.

Ograniczenia — uczciwie: n=1 na komórkę (bez wariancji), jedno repozytorium, jeden tier modelu; koszt zagnieżdżony dwóch komórek oszacowano przez kalibrację na jedynej dokładnie zmierzonej (i oznaczono jako szacunek); ramiona same wybierały strategię — to cecha projektu (mierzymy system jako całość), ale miesza ona „graf" z „decyzją, by nie orkiestrować"; długoterminowa amortyzacja powtarzanych sesji nie została tym eksperymentem zmierzona — pozostaje hipotezą z mocnym a priori (~77k „podatku na ponowne uczenie się" za sesję wobec jednorazowej darmowej budowy).

Rozdział 6. Było → jest

ByłoJest
Wiedza o repo między sesjaminie przeżywa sesji; ~77k tokenów na ponowne uczenie sięgraf buduje się w sekundy jeden raz; kandydaci — natychmiastowe darmowe zapytania
„Kto woła X / co się zepsuje?"pełne przejście grepem; poza trackowanym zadaniem agent o grafie nie wiedziałsamodzielne wejście: graphify affected "X" → verify regionami ±30 linii — łącznie z powiązaniami indirect, których grep nie widzi
Zrozumienie podsystemu na dużym repoukryty fan-out sub-agentów, ~262k tokenówjeden agent z grafem, ~76k — −71%, zmierzone
Audyt repozytoriumrekonesans od zeraGRAPH_REPORT.md (gotowe huby, klastry, nieoczekiwane powiązania) czytany jako pierwszy
Zaufanie do indeksubramka freshness; przeterminowany → głośno + propozycja przebudowy i hooka; fakty — tylko z żywych plików
Instalacjaza jawnym „tak" właściciela: agent proponuje raz, instaluje i buduje sam; odmowa jest respektowana całą sesję

Epilog

Formuła funkcji: istniejące narzędzie (Graphify) + dyscyplina obchodzenia się z nim (nasz skill) + warstwowe testy, które nie wierzą nikomu — ani autorowi tekstu, ani ładnemu snippetowi, ani warunkom własnego scenariusza, ani — jak się okazało w rozdziale 5 — wierzchniej linijce cudzego benchmarku. Ze wszystkich istotnych znalezisk czterech wydań ani jedno nie zostało znalezione „wyczytaniem" — wszystkie przyniosło wykonanie: sędziowie, graderzy, docker, żywe przebiegi i telemetria eksperymentu.

Świadomie odłożone: triage pull requestów przez graf (nie mamy procesu PR — narzędzia bez konsumenta nie robimy), pętla pamięci zapytań save-result/reflect (osobna rozmowa) i powtórzenie eksperymentu z n>1 i drugim repozytorium — jeśli selektywna oszczędność potwierdzi się i tam, „hajp 90%" dostanie uczciwego zastępcę: „−70% w klasie «zrozumienie», zero w pozostałych".

Jak wypróbować

Graf kodu jedzie w pluginie my-architect od v1.14.0 (aktualna — v1.16.1). Nie trzeba go wołać ręcznie: skill sam rozpoznaje graf w repozytorium, a przy ciężkim zadaniu bez grafu — sam zaproponuje instalację.

  1. Załóż konto na my-architect.app, weź token na stronie API Keys i wyeksportuj go w tej samej sesji, w której uruchamiasz Claude Code:

``bash export MCP_API_KEY=mcp_TWÓJ_TOKEN ``

  1. Dodaj marketplace i postaw plugin:

`` /plugin marketplace add d7561985/my-architect-marketplace /plugin install my-architect@my-architect-marketplace ``

  1. Graf można zbudować i ręcznie, nie czekając na propozycję agenta:

``bash pip install graphifyy && graphify build . ``

  1. Masz już plugin? /plugin marketplace update my-architect-marketplace/plugin update my-architect.

---

Fakty i linki