Files
agentic-codemod-pipeline/docs/architecture.md
T
2026-08-29 13:17:59 +02:00

9.9 KiB

Architektura sieci agentowej modyfikującej kod

1. Problem

Zmiany typu "podnieś wersję SDK w 60 repozytoriach" są mechanicznie proste, ale kosztowne: każde repozytorium ma inny układ, inne miejsca użycia biblioteki i inny poziom pokrycia testami. Klasyczna automatyzacja (skrypt + sed) załatwia 70% przypadków i zostawia najgorsze 30%. Agent z LLM załatwia pozostałe 30%, ale wprowadza trzy nowe problemy: niepowtarzalność, brak audytowalności i nieograniczony zakres zmian.

Ten projekt jest odpowiedzią na pytanie: jak wpuścić agenta do repozytorium tak, żeby dało się to pokazać audytorowi.

2. Trzy warstwy i jedna zasada

┌───────────────────────────────────────────────────────────────────┐
│  KONTEKST — APM (Microsoft Agent Package Manager)                 │
│  apm.yml + .apm/{instructions,skills,prompts,agents,context}      │
│  Wersjonowany, pinowany lockfile'em, audytowany polityką.         │
└──────────────────────────────┬────────────────────────────────────┘
                               │ apm install  →  apm_modules/
┌──────────────────────────────▼────────────────────────────────────┐
│  RUNTIME — agno Workflow                                          │
│  Kompilacja prymitywów APM → Agent/Skills/Steps.                  │
│  Deterministyczne kroki + sandboxowane narzędzia.                 │
└──────────────────────────────┬────────────────────────────────────┘
                               │ agentic-codemod run
┌──────────────────────────────▼────────────────────────────────────┐
│  EGZEKUCJA — GitLab CI                                            │
│  Efemeryczny job, bramka manualna, artefakty audytowe, MR.        │
└───────────────────────────────────────────────────────────────────┘

Zasada nadrzędna: kontekst jest artefaktem, nie kodem. Zmiana zachowania sieci agentowej (nowa reguła migracji, ostrzejszy guardrail, inny model dla roli) to podbicie wersji pakietu APM, a nie merge request do Pythona. Dzięki temu zespół właściciela SDK może dostarczyć wiedzę migracyjną, nie mając dostępu do silnika pipeline'u.

3. Przepływ

flowchart TD
    T[Trigger: issue z labelką / MR / harmonogram / formularz] --> C[apm install + apm audit]
    C --> I[intake: deterministyczny wsad zadania]
    I --> R[recon: fakty o repozytorium]
    R --> P[plan: ChangePlan z kryteriami akceptacji]
    P --> G{jest co wdrażać?}
    G -- nie --> M[manifest + komentarz w issue]
    G -- tak --> B[bump wersji: deterministyczny]
    B --> L[pętla: implement → verify]
    L -- czerwono, iteracja < limit --> L
    L -- zielono --> V[review: recenzja diffa]
    V --> S[scribe: opis merge requesta]
    S --> H{bramka manualna w CI}
    H -- zatwierdzone --> MR[branch + commit + push + MR]
    H -- nie --> A[artefakty do wglądu, zero zmian zdalnych]

Role w sieci

Agent Model Narzędzia Wyjście
scout planner odczyt, wyszukiwanie RepoProfile
planner planner odczyt, wyszukiwanie ChangePlan
coder coder odczyt, edycja, weryfikacja zmieniony kod
reviewer reviewer odczyt, diff ReviewVerdict
scribe scribe diff MergeRequestDraft

Definicje ról leżą w .apm/agents/*.agent.md. Kod nie zna nazw agentów - czyta je z kontekstu.

4. Co jest deterministyczne, a co należy do modelu

To jest najważniejsza decyzja projektowa. Model dostaje wyłącznie tę część pracy, której nie da się zrobić inaczej.

Krok Wykonawca Dlaczego
Wykrycie ekosystemu, plików zależności, komendy testowej kod (adapters/) jednoznaczne, sprawdzalne
Podbicie deklaracji wersji kod (adapters/) zero powodów, by ryzykować halucynację w pliku zależności
Migracja objęta regułami codemod kod (workflow/codemod.py) reguły z pakietu APM, w pełni powtarzalne
Nietypowe użycia API, kontekst biznesowy model (coder) tu klasyczna automatyzacja się kończy
Ocena zakresu i ryzyka zmiany model (reviewer) + kontrola mechaniczna dwa niezależne spojrzenia
Uruchomienie testów kod (tools/verification.py) agent nie dostaje powłoki
Branch, commit, push, MR kod (workflow/runner.py) jednoznaczny autor i format historii

Konsekwencja: pipeline ma dwa tryby o identycznej topologii. Tryb --offline używa wyłącznie reguł (RuleBrain), tryb domyślny dokłada agentów (LlmBrain). Tryb offline jest bramką jakości na każdym MR - sprawdza cały przepływ bez kosztu GPU i bez dostępu do modelu.

5. Model bezpieczeństwa

Guardraile istnieją w dwóch warstwach, bo prompt nie jest zabezpieczeniem.

Warstwa promptowa (.apm/instructions/security.instructions.md) - dla modelu: zakaz zmian w plikach pipeline'u, zakaz sekretów, zakaz rozszerzania zakresu, zakaz usuwania testów, zakaz nowych zależności.

Warstwa egzekucji (tools/workspace.py, config.py) - dla audytora:

  • każda ścieżka rozwiązywana względem korzenia repozytorium; wyjście przez .. i dowiązania niemożliwe,
  • lista DEFAULT_DENY_GLOBS blokuje zapis do .gitlab-ci.yml, .git/, Dockerfile*, *.pem, .env*, manifestów APM,
  • budżety: liczba zmienionych plików, rozmiar pliku, liczba wywołań narzędzi, limit czasu weryfikacji,
  • agent nie ma powłoki - jedyna operacja wykonawcza to run_verification z komendą ustaloną przez adapter,
  • środowisko weryfikacji jest czyszczone ze zmiennych zawierających TOKEN, SECRET, PASSWORD, API_KEY,
  • każde wywołanie narzędzia trafia do trace.jsonl z redakcją sekretów.

Warstwa dostawy kontekstu (apm-policy.yml): dozwolone źródła pakietów, zakaz prymitywu hooks (wykonuje kod na runnerze), wymagane piny po tagu, wymagany lockfile, apm audit wykrywający ręczną edycję zainstalowanego kontekstu.

6. Artefakty przebiegu

Każde uruchomienie zostawia w --run-dir komplet dowodów:

Plik Zawartość
run.json manifest: zadanie, profil, plan, weryfikacje, werdykt, modele, hash lockfile'a APM
plan.json plan zmian z kryteriami akceptacji i pozycjami requires_human
profile.json ustalone fakty o repozytorium
review.json werdykt recenzenta z findingami
merge_request.md tytuł i opis MR
changes.patch pełny diff
trace.jsonl każde wywołanie narzędzia z czasem i wynikiem

To jest odpowiedź na pytanie audytora "na jakiej podstawie ta zmiana weszła do repozytorium".

7. Backend LLM

Silnik zna wyłącznie jeden kontrakt: endpoint zgodny z API OpenAI pod CODEMOD_LLM_BASE_URL. Cała wiedza o dostawcy jest w llm.py (fabryka modeli) i llm/models.yml (adresy, modele per rola).

Docelowo jest to vLLM na OpenShifcie. Lokalnie nie ma jednej ścieżki dla obu systemów - Docker na macOS nie ma dostępu do Metala - więc task llm:up wykrywa platformę:

Backend Kiedy Mechanizm
vllm-gpu Linux + NVIDIA + Docker vllm/vllm-openai przez docker compose
vllm-metal macOS Apple Silicon plugin vllm-project/vllm-metal (MLX), natywny vllm serve
ollama awaryjnie, obie platformy /v1 zgodne z OpenAI, natywnie lub w kontenerze
mock testy i CI llm/mock_server.py - stdlib, zero pobierania

Każdy backend serwujący realny model wymusza --enable-auto-tool-choice z parserem hermes. Bez tego vLLM zwraca opis wywołania w treści odpowiedzi zamiast tool_calls, agent coder nie tknąłby żadnego pliku, a przebieg kończyłby się "sukcesem" bez jednej zmiany - awaria cicha, czyli najgorszy rodzaj.

Atrapa jako test double

mock nie jest symulatorem modelu. Odpowiada z góry ustalonymi wywołaniami narzędzi i strukturami zestrojonymi z fixture'em acme-app, a rozpoznaje pytającego po nazwie agenta, którą agno wstrzykuje do komunikatu systemowego. Dzięki temu tests/test_llm_path.py przepuszcza pełny przebieg przez LlmBrain - budowę agentów z definicji APM, tool-calling, parsowanie strukturalnych wyjść i pętlę weryfikacji - na każdym MR, bez GPU i bez sieci.

Podział odpowiedzialności testów jest więc taki:

Co jest sprawdzane Czym
reguły, adaptery, sandbox, workflow tryb --offline (RuleBrain)
agenci, narzędzia, schematy, pętla tryb llm na atrapie (LlmBrain + mock)
jakość migracji na nietypowym kodzie realny model, ręcznie

8. Granice rozwiązania

  • Bez agenta-nadzorcy. Topologia jest jawnym przepływem (agno Workflow), a nie swobodną delegacją między agentami. W zamian za mniejszą elastyczność dostajemy przewidywalny koszt, powtarzalny ślad i możliwość wstawienia bramki między krokami.
  • Bez AgentOS. Runtime to efemeryczny job CI. Nie utrzymujemy usługi z pamięcią sesji - stan przebiegu żyje w artefaktach.
  • Bez dostępu do sieci z poziomu agenta. Cała wiedza migracyjna przychodzi w pakiecie APM. Jeśli notatki migracyjnej nie ma, pipeline zatrzymuje się i zgłasza requires_human, zamiast migrować "z pamięci modelu".
  • Nie każde repozytorium się nadaje. Bez działającej komendy testowej weryfikacja nic nie znaczy, a bez weryfikacji ten pipeline nie ma prawa niczego publikować.