feat: initial commit
This commit is contained in:
@@ -0,0 +1,175 @@
|
||||
# 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
|
||||
|
||||
```mermaid
|
||||
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ć.
|
||||
Reference in New Issue
Block a user