---
title: "Graf kodu i testy mutacyjne w projekcie Monolynx"
description: "Jak zasilić graf zależności kodu przez graphify i krok CI oraz jak komenda mutation-check zamienia mutanty, które przeżyły, w brakujące przypadki testowe. Oba dodatki są opcjonalne."
url: "https://monolynx.com/blog/graf-kodu-i-testy-mutacyjne"
lang: "pl"
author: "Zespół Monolynx"
published: "2026-10-08T08:44:52.957326+00:00"
modified: "2026-10-09T10:35:20.033250+00:00"
last_verified: "2026-10-08"
tags: ["graf-kodu", "testy-mutacyjne", "plugin", "ci", "agenci-ai"]
translations: []
reading_time_minutes: 10
word_count: 1931
---

> [!TLDR]
> - Graf kodu mówi agentowi, co od czego zależy, zanim zmieni plik. Testy mutacyjne mówią, czy testy naprawdę łapią błędy.
> - Graf buduje zewnętrzne narzędzie graphify: lokalnie, bez modelu AI i bez kosztów API.
> - Graf zasilasz ręcznie komendą `/monolynx:graph-sync` albo automatycznie krokiem CI po merge do gałęzi głównej.
> - Komenda `/monolynx:mutation-check` zamienia mutanty, które przeżyły, w brakujące przypadki testowe: kryteria albo tickety.
> - Oba dodatki są opcjonalne i nigdy nie blokują builda ani merge.

## Po co projektowi graf kodu i testy mutacyjne?

Agent, który pisze kod, potrzebuje dwóch informacji, których nie da mu sam plik. Pierwsza: kto korzysta z funkcji, którą właśnie zmienia. Druga: czy zielone testy coś znaczą. Graf kodu odpowiada na pierwsze pytanie, a testy mutacyjne na drugie.


**Porównanie**

| Cecha | Graf kodu | Testy mutacyjne |
| --- | --- | --- |
| Pytanie | co zależy od tego kodu? | czy testy wykryją błąd w tym kodzie? |
| Kiedy pomaga | przy planowaniu ticketu i rozpoznaniu zmiany | po napisaniu kodu i testów |
| Skąd dane | analiza składni plików źródłowych | wielokrotne uruchomienie testów na celowo zepsutym kodzie |
| Koszt | sekundy do minut, lokalnie | minuty; rośnie z liczbą zmienionych linii |
| Gdzie widać wynik | moduł Połączenia w panelu | raport komendy, kryteria i tickety |



**Statystyki**

- **0** - wywołań modelu AI przy budowie grafu
- **20 000** - limit węzłów grafu jednego projektu
- **600** - sekund budżetu jednego przebiegu testów mutacyjnych
- **0** - buildów, które te dodatki mogą oblać


> [!NOTE]
> Oba dodatki są opcjonalne. Komendy `work`, `ticket-create` i `sprint-run` działają bez nich. Checklista `/monolynx:setup` pokaże ich brak, ale nie zatrzyma pracy.

## Jak zasilić graf kodu?

Graf powstaje w dwóch krokach. Najpierw narzędzie graphify czyta pliki źródłowe i zapisuje wynik do pliku `graphify-out/graph.json`. Potem skrypt `cicd/sync_graph.py` zamienia ten plik na węzły i krawędzie Monolynx i wysyła je na platformę.


**Droga od plików źródłowych do modułu Połączenia**

Narzędzie graphify analizuje składnię plików w repozytorium i zapisuje graf do pliku. Skrypt synchronizacji mapuje go na typy węzłów i krawędzi Monolynx, a potem jednym wywołaniem podmienia cały graf projektu na platformie. Z gotowego grafu korzystają panel i agenci.

```mermaid
flowchart LR
  A["Pliki źródłowe"] --> B["graphify update"]
  B --> C["graphify-out/graph.json"]
  C --> D["cicd/sync_graph.py"]
  D --> E["Graf projektu w Monolynx"]
  E --> F["Moduł Połączenia w panelu"]
  E --> G["Agenci: ticket-create, work"]
```


### Ręcznie: /monolynx:graph-sync

Komenda prowadzi przez cały proces za rękę. Dobra na pierwszy raz i dla projektu bez CI.


**Kroki**

1. **Sprawdzenie graphify** Komenda sprawdza, czy narzędzie jest zainstalowane. Gdy go brakuje, podaje polecenie instalacji dla Twojego systemu i czeka na zgodę.
2. **Plik wykluczeń** Komenda sprawdza albo proponuje plik `.graphifyignore`, który pomija testy, migracje, dokumentację i kod zewnętrzny.
3. **Ekstrakcja** Polecenie `graphify update .` buduje graf lokalnie z samej składni plików.
4. **Przebieg próbny** Skrypt synchronizacji uruchomiony z flagą `--dry-run` pokazuje liczby węzłów i krawędzi, ale niczego nie wysyła.
5. **Wysyłka po Twojej zgodzie** Komenda uprzedza, że wysyłka podmienia cały graf projektu, i czeka na potwierdzenie.



**Instalacja graphify i pierwsza synchronizacja**

```console
$ uv tool install graphifyy
$ graphify --version
$ graphify update .
$ python cicd/sync_graph.py --dry-run
$ python cicd/sync_graph.py
```


> [!WARNING]
> Pakiet w PyPI nazywa się `graphifyy`, z podwójnym "y". Polecenie po instalacji to `graphify`.

> [!IMPORTANT]
> Synchronizacja używa osobnego tokenu w zmiennej `MONOLYNX_GRAPH_TOKEN`. Token ustawiasz w środowisku, nigdy w rozmowie z agentem i nigdy w pliku zapisanym w repozytorium. Skrypt potrzebuje też zmiennych `MONOLYNX_URL` i `MONOLYNX_PROJECT_SLUG`. Token generujesz w panelu, w profilu, na liście tokenów API.

Skrypt `cicd/sync_graph.py` nie jest częścią Twojego repozytorium, dopóki go nie wygenerujesz. Tworzy go komenda `/monolynx:create-graph-ci-script`, a gdy pliku brakuje, `/monolynx:graph-sync` generuje go sam według tej samej specyfikacji.

### Automatycznie: /monolynx:create-graph-ci-script

Ta komenda dodaje do CI krok, który odświeża graf po każdym merge do gałęzi głównej. Wykrywa system CI (GitLab, GitHub Actions, Bitbucket albo Jenkins), tworzy plik wykluczeń i skrypt synchronizacji, a potem dopisuje krok.

```yaml title=".gitlab-ci.yml: krok dodawany dla GitLab"
sync-graph:
  stage: deploy
  allow_failure: true
  script:
    - command -v graphify || { echo "graphify nie zainstalowane na runnerze"; exit 0; }
    - graphify update .
    - python cicd/sync_graph.py
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      when: on_success
```

Krok ma trzy cechy, które warto znać przed uruchomieniem.


**Porównanie**

| Cecha | Co oznacza |
| --- | --- |
| Nie instaluje graphify | narzędzie instaluje właściciel maszyny wykonującej CI, raz |
| Nie blokuje | brak narzędzia, pliku grafu albo tokenu kończy krok komunikatem i sukcesem |
| Podmienia cały graf | każdy przebieg usuwa stary graf projektu i wstawia nowy |



**Dlaczego plik wykluczeń ma znaczenie**

Bez pliku `.graphifyignore` graf bywa pięć razy większy, a większość węzłów to testy. Platforma przyjmuje w jednej synchronizacji najwyżej 20 000 węzłów i 60 000 krawędzi.

Graf w obecnej wersji obejmuje tylko kod projektu. Dokumentacja, pakiety i symbole z zewnętrznych bibliotek są pomijane. Skutek uboczny: krawędź dziedziczenia po klasie z biblioteki znika, bo jej drugi koniec nie należy do projektu. To nie jest błąd.


## Jak działają testy mutacyjne?

Narzędzie mutacyjne wprowadza do kodu drobny błąd, na przykład zamienia `>=` na `>`, i uruchamia testy. Gdy któryś test pada, mutant został wykryty. Gdy wszystkie testy są zielone, mutant przeżył: w tym miejscu kod można zepsuć, a testy tego nie zauważą.


**Przebieg na zmianie z bieżącego brancha**

```console
> /monolynx:mutation-check

Mutacje (diff względem 4f2a9c1): 4 przeżyło / 17 mutantów

| plik:linia            | mutator             | oryginał -> mutant |
| src/rozliczenia.py:88 | ConditionalBoundary | >= -> >            |
```


Komenda ma dwa tryby. Wybiera je argument.


**Porównanie**

| Cecha | Tryb na zmianie | Tryb pełny |
| --- | --- | --- |
| Wywołanie | bez argumentu | ze ścieżką modułu |
| Zakres | linie zmienione względem gałęzi głównej | cały wskazany moduł |
| Wynik | liczba mutantów, które przeżyły | wynik procentowy, wartość bazowa i różnica |
| Kiedy | po każdym tickecie | okresowo, dla najważniejszych modułów |


> [!NOTE]
> W trybie na zmianie komenda nie podaje procentu. Przy kilku mutantach wynik procentowy skacze o dziesiątki punktów między przebiegami i nic nie mówi. Liczy się lista miejsc.

### Skąd komenda zna polecenie?

Komenda niczego nie zgaduje. Polecenie, ścieżkę raportu i jego format czyta z sekcji `## Mutacje` strony wiki `toolchain`. Tę sekcję zapisuje komenda `/monolynx:project-toolchain`, która wykrywa narzędzie pasujące do języka projektu.


**Porównanie**

| Język | Narzędzie | Raport rozumiany przez plugin |
| --- | --- | --- |
| Python | mutmut | tak |
| JavaScript i TypeScript | Stryker | tak |
| Java i Kotlin | PIT | tak |
| C# | Stryker.NET | tak |
| Rust | cargo-mutants | tak |
| Scala | Stryker4s | w kroku CI tak; komenda `mutation-check` pokazuje surowy raport |
| PHP | Infection | zależy od ustawionego formatu raportu |
| Go | gremlins | nie; surowy raport |
| Ruby | mutant | nie; surowy raport |


Plugin nie instaluje narzędzia mutacyjnego. Gdy sekcji brakuje albo narzędzie nie jest zainstalowane, komenda mówi to wprost, odsyła do `/monolynx:project-toolchain` i kończy pracę.

### Co się dzieje z mutantem, który przeżył?

Mutant, który przeżył, jest brakującym przypadkiem testowym, a nie wynikiem do poprawienia. Komenda najpierw czyta kod wokół wskazanej linii, nazywa niesprawdzane zachowanie, a potem pyta, co z tym zrobić.


**Porównanie**

| Wybór | Skutek |
| --- | --- |
| Kryteria przy tickecie | każde brakujące zachowanie staje się kryterium akceptacji wskazanego ticketu |
| Ticket na każdy przypadek | osobny ticket o niskim priorytecie dla każdego miejsca |
| Jeden ticket zbiorczy | jeden ticket z listą przypadków jako kryteriami |
| Tylko raport | nic nie jest zapisywane |


> [!CAUTION]
> Wynik procentowy łatwo podnieść testami, które przypinają szczegóły implementacji. Taki test kupuje punkt i płaci za niego każdym przyszłym refaktorem. Komenda ma to wpisane jako zakaz: treść kryterium opisuje brakujące zachowanie, a nie mutanta.


**Mutant równoważny: kiedy odpuścić**

Część mutantów zmienia kod, ale nie zmienia zachowania, które da się zaobserwować. Przykład: zamiana `<=` na `<` na granicy, której program nigdy nie osiąga. Takiego mutanta nie da się wykryć żadnym sensownym testem.

Komenda uzasadnia taki przypadek jednym zdaniem, pomija go przy zapisie i wymienia osobno w raporcie. To poprawna odpowiedź, nie dług.


## Jak dodać testy mutacyjne do CI?

Komenda `/monolynx:create-mutation-ci-script` dodaje osobny etap CI, który działa tylko na merge requestach i liczy mutacje na zmianie. Raport narzędzia trafia do artefaktów. Etap kopiuje też do katalogu `cicd/` dwa skrypty: jeden sprowadza raport do wspólnego formatu, drugi porównuje wynik z zapisaną wartością bazową.

Porównanie działa jak zapadka: wartość bazowa może tylko rosnąć.


**Porównanie**

| Status | Kiedy | Co robi etap |
| --- | --- | --- |
| `first` | brak pliku z wartością bazową | zapisuje pierwszy pomiar do artefaktu |
| `up` | wynik wyższy niż wartość bazowa | zapisuje nową wartość do artefaktu |
| `same` | wynik równy | nic nie zapisuje |
| `down` | wynik niższy | wypisuje ostrzeżenie, wartości nie zmienia, etap zostaje zielony |
| `no-mutants` | zmiana bez mutantów, na przykład sama dokumentacja | pomija porównanie |


> [!IMPORTANT]
> Plik `cicd/mutation-baseline.json` zatwierdza w repozytorium człowiek, pobierając go z artefaktu. CI nie ma tokenu do zapisu i niczego nie wypycha. Dopóki pliku nie ma w repozytorium, każdy merge request raportuje status `first`.

> [!NOTE]
> Monolynx ma dwie wartości bazowe mutacji i nie zależą one od siebie. Plik `cicd/mutation-baseline.json` należy do etapu CI i dotyczy mutacji policzonych na zmianie w merge requeście. Linia `baseline:` na stronie wiki `toolchain` dotyczy pełnego przebiegu na modułach rdzenia, który proponuje `/monolynx:sprint-end`, a jej historię trzyma strona `Trend mutacji`. Drugą opisuje wpis [Jak działa /monolynx:sprint-end](https://monolynx.com/blog/jak-dziala-monolynx-sprint-end).

> [!TIP]
> Nie dodawaj progu procentowego ani czerwonego builda przy spadku. Wynik mutacji jest trendem. Bramka na różnicy kończy się zwykle wyłączeniem całego etapu.

## Najczęstsze pytania


**FAQ**

### Czy budowa grafu wysyła mój kod do modelu AI?
Nie. Graphify analizuje składnię plików lokalnie. Na platformę trafiają nazwy plików, klas i funkcji oraz powiązania między nimi, a nie treść kodu.

### Co się stanie, gdy graf jest nieaktualny?
Agenci dostaną nieaktualną mapę zależności, ale praca się nie zatrzyma. Graf jest warstwą pomocniczą. Odświeżysz go jednym poleceniem albo krokiem CI po merge.

### Ile trwa przebieg testów mutacyjnych?
Komenda ma budżet 600 sekund. Po jego przekroczeniu zatrzymuje proces i, jeśli raport jest kompletny, pokazuje wynik częściowy z wyraźnym oznaczeniem.

### Czy mutant, który przeżył, blokuje ticket?
Nie. Wynik jest informacją. Staje się pracą dopiero wtedy, gdy wybierzesz zapis jako kryteria albo tickety.

### Od czego zacząć w istniejącym projekcie?
Od `/monolynx:setup`. Checklista pokaże stan grafu i mutacji, a przy każdym braku wskaże komendę, która go usuwa.


## Słownik i następny krok


**Słownik**

- **Graf kodu** - mapa plików, klas i funkcji projektu oraz powiązań między nimi
- **Graphify** - zewnętrzne narzędzie, które buduje graf z analizy składni plików
- **Węzeł** - element grafu: plik, klasa, metoda, funkcja, stała albo moduł
- **Krawędź** - powiązanie między węzłami, na przykład wywołanie albo import
- **Mutant** - kopia kodu z jedną celowo wprowadzoną zmianą
- **Mutant, który przeżył** - zmiana, której nie wykrył żaden test
- **Wartość bazowa** - zapisany wynik mutacji, z którym porównuje się kolejne przebiegi
- **Zapadka** - zasada, że wartość bazowa może tylko rosnąć
- **Toolchain** - strona wiki z poleceniami lintu, testów i mutacji projektu


Stronę `toolchain` i resztę konfiguracji opisuje wpis [Pierwszy projekt w Monolynx](https://monolynx.com/blog/pierwszy-projekt-w-monolynx). Miejsce obu komend wśród pozostałych pokazuje [Mapa pluginu Monolynx](https://monolynx.com/blog/mapa-pluginu-monolynx).


**Wezwanie do działania**

Chcesz zobaczyć graf zależności swojego projektu w przeglądarce?

[Zobacz moduł Połączenia w Monolynx](https://monolynx.com/features/connections)

