Lesezeit : 12 minutes

Deine Codebase wächst. Die Abhängigkeiten zwischen den Modulen vermehren sich. Die Architektur-Dokumentation wird veraltet, bevor sie überhaupt geschrieben ist. Und wenn dein Gradle-Build automatisch aktuelle Diagramme aus der tatsächlichen Code-Struktur generieren könnte? Das ist genau das, was die Graphify + PlantUML Gradle Plugin-Pipeline macht:`graphify . --no-viz`extrahiert das Knowledge Graph,`./gradlew generateKnowledgeGraphDiagram`es verwandelt in PlantUML-Diagramme. Null LLM, null Handbuch, 100% deterministisch.

Tick

(Empty output)

Das Problem: Diagramme hinken ständig hinter dem Code her.

Jedes Projekt, das einige tausend Zeilen übersteigt, leidet unter diesem Syndrom:

  1. Am Anfang des Projekts zeichnet man ein Architekturdiagramm.

  2. Der Code entwickelt sich, die Abhängigkeiten ändern sich.

  3. Das Diagramm wird zu einer dekorativen Lüge.

  4. Niemand aktualisiert es, weil es mühsam ist

  5. Die Neuankommelinge stützen sich darauf und machen Fehler.

probleme diagrammes obsoletes

Die Frage ist nicht muss es Diagramme geben? — jeder weiß, dass ja. Die Frage lautet:Wer hält sie auf dem neuesten Stand?

Die Antwort: niemand. Falls es automatisch ist.

Die Lösung: eine deterministische Pipeline Knowledge Graph → PlantUML

Das Prinzip ist einfach: Statt die Diagramme von Hand zu zeichnen, zeichnet man sieGeneriert aus der eigentlichen Struktur des Codes.

Failed to generate image: PlantUML preprocessing failed: [From <input> (line 6) ]

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

actor Développeur
component "Graphify
^^^^^
 Syntax Error? (Assumed diagram type: sequence)

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

actor Développeur
component "Graphify
(pip install graphifyy)" as Graphify
collections "graphify-out/graph.json\n(Knowledge Graph)" as KGJSON
component "PlantUML Gradle-Plugin
(generateKnowledgeGraphDiagram)" as Plugin
component "KnowledgeGraphParser" as Parser
component "KnowledgeGraphRenderer" as Renderer
component "PlantumlService\n(Validierung + PNG-Rendering)" as PS
collections "diagrams/knowledge-graph/\n(.puml + .png)" as Output

Développeur --> Graphify : graphify . --no-viz
Graphify --> KGJSON : extrait la structure\ndu code source
Développeur --> Plugin : ./gradlew generateKnowledgeGraphDiagram
Plugin --> Parser : parse(graph.json)
Parser --> Plugin : KnowledgeGraph\n(noeuds + arêtes + communautés)
Plugin --> Renderer : render(graph, filters)
Renderer --> Plugin : code PlantUML\ndéterministe
Plugin --> PS : validateSyntax + generateImage
PS --> Output : .puml + .png

note bottom of Plugin
  Pipeline DÉTERMINISTE
  Aucun appel LLM
  Résultat reproductible
end note

@enduml

Zwei Befehle. Das ist alles.

# Étape 1 : extraire le Knowledge Graph
graphify . --no-viz

# Étape 2 : générer les diagrammes PlantUML
./gradlew generateKnowledgeGraphDiagram

Das Ergebnis? Dateien`.puml` et .png`in`diagrams/knowledge-graph/, in Git versioniert, stets auf dem neuesten Stand des Codes.

Schritt 1: Graphify installieren und das Knowledge Graph extrahieren

Installation

Graphify ist ein Python-Tool, das Ihre Codebasis analysiert und einen strukturierten Wissensgraphen erstellt :

# Méthode recommandée
uv tool install graphifyy && graphify install --platform opencode

# Alternative avec pip
pip install graphifyy && graphify install --platform opencode

Ausnahmen konfigurieren

Eine Datei erstellen`.graphifyignore`im Wurzelverzeichnis des Projekts, um die Dateien auszuschließen, die nicht zur Geschäftslogik gehören:

# Secrets — JAMAIS dans le graphe
*-context.yml
*.env

# Fichiers générés
build/
.gradle/

# Tests fonctionnels
src/functionalTest/

Den Knowledge Graph extrahieren

graphify . --no-viz

Das Flag`--no-viz`Überspringt die HTML-Generierung (unnötig in einem Gradle-Pipeline). Das Ergebnis ist eine Datei.`graphify-out/graph.json`enthält:

  • Knoten: Klassen, Funktionen, Dateien — mit ihrem Typ und Gemeinschaft

  • Kanten: Beziehungen zwischen Knoten (EXTRACTED aus dem Code, INFERRED vom LLM)

  • Gemeinschaften: automatische Gruppierungen von verbundenen Knoten

Beispiel einer Struktur`graph.json`
{
  "nodes": [
    {"id": "0", "label": "LlmService", "file_type": "code", "community": 0},
    {"id": "1", "label": "ApiKeyPool", "file_type": "code", "community": 0},
    {"id": "2", "label": "PlantumlService", "file_type": "code", "community": 1}
  ],
  "links": [
    {"source": "1", "target": "0", "relation": "uses", "confidence": "EXTRACTED", "weight": 0.9},
    {"source": "0", "target": "2", "relation": "calls", "confidence": "INFERRED", "weight": 0.7}
  ]
}

Der Quellcode (.kt, .java) wird lokal von tree-sitter analysiert,nicht anfechtbar. Nur die Dokumentationsdateien (.adoc, .md) erfordern einen LLM-Aufruf für die semantische Extraktion. Also`--update`sur Kotlin-Code ist nahezu sofort.

Schritt 2: Das Gradle-Plugin wandelt das Knowledge Graph in PlantUML um

Pipeline-Architektur

Das Plugin`com.cheroliv.plantuml`integriert eine Aufgabe`generateKnowledgeGraphDiagram`der verwandelt`graph.json`auf diese Weise in PlantUML-Diagrammenvollständig deterministisch</think>

architecture pipeline kg

Die inneren Komponenten

Komponente Rolle

KnowledgeGraphParser

Parsen`graph.json`— unterstützt 3 Formate: nativen Graphify`nodes`(Empty)links), legacy (communities), flat. löst die numerischen IDs in die Labels auf

KnowledgeGraphRenderer

transformiert deterministischen einen`KnowledgeGraph`Im PlantUML-Code. Gruppen nach Typ, Gemeinschaften in Paketen, automatische Legende.

GenerateKnowledgeGraphDiagramTask

Gradle-Aufgabe, die orchestriert: parse → render → validate → PNG. Konfigurierbar über Gradle-Eigenschaften.

kgmodels.kt

Datenmodelle:`KnowledgeGraph`, KnowledgeGraphNode, KnowledgeGraphEdge, KnowledgeGraphCommunity, EdgeType.

PlantumlService

Syntaktische Validierung + PNG-Rendering (von allen Aufgaben des Plugins wiederverwendet)

Renderregeln

Der Renderer wendet deterministische visuelle Konventionen an :

Typ der Kante PlantUML-Notation Bedeutung

EXTRAHIERT

-→(durchgezogene Linie, schwarz)

Aus dem Quellcode extrahierte Beziehung (Gewissheit)

INFERRED

..>(gepunktete Linie)

Vom LLM abgeleitete Relation (Vertrauensscore)

mehrdeutig

--x(rote gepunktete Linie)

Ambigüe Beziehung (zu überprüfen)

Gemeinden werden als PlantUML-Pakete mit einer automatischen Farbpalette gerendert.

Schritt 3: Tägliche Nutzung

vollständiges Diagramm

# Générer le diagramme du Knowledge Graph complet
./gradlew generateKnowledgeGraphDiagram

Ausgabe :`diagrams/knowledge-graph/knowledge-graph-full.puml`+.png

Nach Gemeinschaft filtern

# Une seule communauté
./gradlew generateKnowledgeGraphDiagram \
  -Pplantuml.kg.community=community_0

# Limiter le nombre de noeuds (lisibilité)
./gradlew generateKnowledgeGraphDiagram \
  -Pplantuml.kg.community=community_0 \
  -Pplantuml.kg.maxNodes=15

Nach Kantentyp filtern

# Uniquement les relations certaines (EXTRACTED)
./gradlew generateKnowledgeGraphDiagram \
  -Pplantuml.kg.edgeTypes=EXTRACTED

# Relations certaines + inférées
./gradlew generateKnowledgeGraphDiagram \
  -Pplantuml.kg.edgeTypes=EXTRACTED,INFERRED

Nach Knotentyp und Konfidenz filtern

# Uniquement les classes de code
./gradlew generateKnowledgeGraphDiagram \
  -Pplantuml.kg.nodeTypes=code

# Seuil de confiance minimum (pour les INFERRED)
./gradlew generateKnowledgeGraphDiagram \
  -Pplantuml.kg.minConfidence=0.7

Benutzerdefiniertes Ausgabeverzeichnis

./gradlew generateKnowledgeGraphDiagram \
  -Pplantuml.kg.outputDir=docs/architecture

Vollständige Referenz der Eigenschaften

Eigentum Standard Beschreibung

plantuml.kg.community

(alle)

Gemeinschaften nach Namen filtern (Teilstring-Übereinstimmung)

plantuml.kg.edgeTypes

(alle)

Kantenarten getrennt durch Kommas :`EXTRACTED`, INFERRED, AMBIGUOUS

plantuml.kg.minConfidence

0.0

Mindestkonfidenzschwelle für die Kanten

plantuml.kg.maxNodes

(unbegrenzt)

Maximale Anzahl der anzuzeigenden Knoten

plantuml.kg.nodeTypes

(alle)

Knotentypen, getrennt durch Kommata (Beispiel.class, code)

plantuml.kg.outputDir

diagrams/knowledge-graph

Ausgabeverzeichnis für die Dateien`.puml` et .png

Das vollständige Pipeline in einem Gradle-Workflow

Workflow‑Typ

workflow complet

Integration in den Entwicklungszyklus

Der Pipeline integriert sich natürlich in die Schlüsselstufen der Entwicklung :

Failed to generate image: PlantUML preprocessing failed: [From <input> (line 5) ]

@startuml
skinparam backgroundColor #FEFEFE

state "Entwicklung" as dev
state "Extraktion
^^^^^
 Syntax Error? (Assumed diagram type: state)

@startuml
skinparam backgroundColor #FEFEFE

state "Entwicklung" as dev
state "Extraktion
graphify . --no-viz" as extract
state "Erzeugung
./gradlew generateKnowledgeGraphDiagram" as generate
state "Commit
versionierte Diagramme" as commit

[*] --> dev
dev --> extract : Code modifié
extract --> generate : graph.json à jour
generate --> commit : .puml + .png générés
commit --> dev : Diagrammes dans le repo

note right of extract
  Quasi instantané sur du code Kotlin
  (tree-sitter, pas de LLM)
end note

note right of generate
  Déterministe
  Pas de LLM
  Résultat reproductible
end note

@enduml

Inkrementelles Update

Wenn sich der Code ändert, bauen wir nicht den gesamten Graphen von Grund auf neu:

# Mise à jour incrémentale (fichiers modifiés uniquement)
graphify . --update

# Puis régénérer les diagrammes
./gradlew generateKnowledgeGraphDiagram

--update`re-extrahiert nur die geänderten Dateien (mittels SHA256 erkannt in`graphify-out/cache/). Auf Kotlin-Code ist es nahezu sofort, weil tree-sitter lokal arbeitet, ohne LLM-Aufruf.

Dogfooding: Das Plugin dokumentiert sich selbst

Der PlantUML-Plug‑in existiert, um Prompts in Diagramme zu verwandeln. Er kann auch den Knowledge Graph seiner propre Codebasis in Dokumentationsdiagramme umwandeln. Das ist dogfooding: Der Plug‑in konsumiert seinen eigenen Dienst.

Failed to generate image: PlantUML preprocessing failed: [From <input> (line 29) ]

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

package "Normale Pipeline\n(Benutzer → Diagramme)" as normal {
    [Fichier .prompt] as prompt
    [LlmService\n+ ApiKeyPool] as llm1
    [ProcessPlantumlPromptsTask] as task1
    [Diagramme PNG] as out1

    prompt --> task1
    task1 --> llm1
    llm1 --> out1
}

package "Pipeline Knowledge Graph (deterministischer Ansatz, kein LLM)" as kg {
    [graphify-out/graph.json] as kgjson
    [KnowledgeGraphParser] as parser
    [KnowledgeGraphRenderer] as renderer
    [PlantumlService] as ps
    [Diagramme PNG\n(documentation du plugin)] as out2

    kgjson --> parser
    parser --> renderer
    renderer --> ps
    ps --> out2
}

package "Pipeline Dogfooding
^^^^^
 Syntax Error? (Assumed diagram type: component)

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

package "Normale Pipeline\n(Benutzer → Diagramme)" as normal {
    [Fichier .prompt] as prompt
    [LlmService\n+ ApiKeyPool] as llm1
    [ProcessPlantumlPromptsTask] as task1
    [Diagramme PNG] as out1

    prompt --> task1
    task1 --> llm1
    llm1 --> out1
}

package "Pipeline Knowledge Graph (deterministischer Ansatz, kein LLM)" as kg {
    [graphify-out/graph.json] as kgjson
    [KnowledgeGraphParser] as parser
    [KnowledgeGraphRenderer] as renderer
    [PlantumlService] as ps
    [Diagramme PNG\n(documentation du plugin)] as out2

    kgjson --> parser
    parser --> renderer
    renderer --> ps
    ps --> out2
}

package "Pipeline Dogfooding
(LLM → Dokumentation des Plugins)" as dogfood {
    [GraphifyPromptAdapter] as gpa
    [Fichiers .prompt\nauto-générés] as auto_prompt
    [LlmService\n+ ApiKeyPool] as llm2
    [ProcessPlantumlPromptsTask] as task2
    [Diagramme PNG\n(documentation LLM)] as out3

    kgjson --> gpa
    gpa --> auto_prompt
    auto_prompt --> task2
    task2 --> llm2
    llm2 --> out3
}

note "Dasselbe LlmService, dasselbe ApiKeyPool,
dasselbe PlantumlService
— NULL Duplikation" as N

@enduml

Zugehörige Gradle-Tasks :

Aufgabe LLM ? Beschreibung

generateKnowledgeGraphDiagram

Nein

Transformiere`graph.json`in PlantUML (deterministisch)

generateDiagramDocs

Ja

Erzeuge einige`.prompt`Seit dem Graphen werden sie mit LLM verarbeitet (dogfooding)

# Documentation déterministe (rapide, pas de LLM)
./gradlew generateKnowledgeGraphDiagram

# Documentation LLM (plus riche, consomme des tokens)
./gradlew generateDiagramDocs

Warum es deterministisch ist (und warum das zählt)

Der Schlüsselpunkt des Pipelines`generateKnowledgeGraphDiagram` : Er ruft keinen LLM an. Die Transformation`graph.json`PlantUML ist eine reine Funktion.

Failed to generate image: PlantUML preprocessing failed: [From <input> (line 6) ]

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

rectangle "deterministische Pipeline
(generateKnowledgeGraphDiagram)" as det {
^^^^^
 Syntax Error? (Assumed diagram type: activity)

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

rectangle "deterministische Pipeline
(generateKnowledgeGraphDiagram)" as det {
    [graph.json] as json
    [KnowledgeGraphParser] as parser
    [KnowledgeGraphRenderer] as renderer
    [PlantUML code] as puml

    json --> parser : parse
    parser --> renderer : KnowledgeGraph
    renderer --> puml : render (fonction pure)
}

rectangle "Pipeline LLM\n(processPlantumlPrompts)" as llm {
    [.prompt] as prompt
    [LlmService] as llmSvc
    [ChatModel] as model
    [PlantUML code] as puml2

    prompt --> llmSvc
    llmSvc --> model : API call
    model --> puml2 : réponse non-déterministe
}

note bottom of det
  Même entrée → même sortie
  Pas de latence réseau
  Pas de coût en tokens
  Reproductible en CI
end note

note bottom of llm
  Même entrée → sortie variable
  Latence réseau (1-5s)
  Coût en tokens
  Nécessite une clave API
end note

@enduml

Die konkreten Vorteile:

Vorteil Einfluss

Reproduzierbarkeit

gleich`graph.json`→ derselbe Diagramm. Genau. Jedes Mal.

Null Kosten

Kein LLM-Aufruf = keine Tokens = keine API-Rechnung

Null Latenz

Parse + render dauert ~100ms, nicht 1-5 Sekunden.

CI-kompatibel

Kein API‑Schlüssel erforderlich. Kein flaky Test aufgrund einer variablen LLM‑Antwort.

versionierbar

Le .puml`generiert ist Text. Man kann es`diff, den PR-Reviewer, ihn in Git versionieren

Die Diagramme der Pipeline selbst

Um den Kreis zu schließen, hier ist das Diagramm der Pipeline, wie es vom Plugin generiert würde :

pipeline sequence

Einbindung in die Projektgovernance

In unserem Projekt integriert sich diese Pipeline in eine EAGER/LAZY-Kontextverwaltungsstrategie für den KI-Agenten. Der Knowledge Graph ersetzt die manuelle Architektur-Dokumentation durch einen strukturierten, abfragbaren und automatisch aktualisierbaren Graph.

Failed to generate image: PlantUML preprocessing failed: [From <input> (line 16) ]

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

package "EAGER\n(immer geladen)" as eager {
    [PROMPT_REPRISE.adoc\n(contexte session)] as pr
    [INDEX.adoc\n(vue d'ensemble)] as idx
    [GRAPH_REPORT.adoc\n(~50 lignes)] as gr
}

package "LAZY — Strategie\n(auf Anfrage)" as lazy_strat {
    [Méthodologies] as meth
    [Archives sessions] as sessions
}

package "LAZY — Graphify
^^^^^
 Syntax Error? (Assumed diagram type: component)

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

package "EAGER\n(immer geladen)" as eager {
    [PROMPT_REPRISE.adoc\n(contexte session)] as pr
    [INDEX.adoc\n(vue d'ensemble)] as idx
    [GRAPH_REPORT.adoc\n(~50 lignes)] as gr
}

package "LAZY — Strategie\n(auf Anfrage)" as lazy_strat {
    [Méthodologies] as meth
    [Archives sessions] as sessions
}

package "LAZY — Graphify
(gezielte Anfragen)" as lazy_graph {
    [graph.json] as gj
    [Queries\n(query/path/explain)] as queries
}

package "Pipeline PlantUML
(auto-generiert)" as puml {
    [generateKnowledgeGraphDiagram] as kgTask
    [generateDiagramDocs] as ddTask
    [Diagrammes PNG] as diagrams
}

Agent --> eager : Lit en début de session
Agent ..> lazy_strat : Charge si type détecté
Agent ..> lazy_graph : Query si besoin structurel
kgTask --> diagrams : Déterministe
ddTask --> diagrams : Via LLM

note right of gr
  Condensé du Knowledge Graph
  God nodes + communautés
  Remplace ECOSYSTEM_OVERVIEW
  (225 lignes → 50 lignes)
end note

@enduml

Die Ehe der beiden Systeme ist komplementär:

  • Die Strategie verwaltet das WANN und das WIE— Governance, Workflow, Archivierung

  • Graphify verwaltet das WAS und das WO— Code-Struktur, Beziehungen, gezielte Anfragen

(leer) Die Sitzungsstrategie verwaltet daswann et le wie(Governance, Workflow, Schwellenwerte), Graphify verwaltet dasWAS et le WO(Struktur des Codes, Beziehungen, gezielte Anfragen). Der PlantUML-Pipeline verwaltet dasMit was?(Diagramme, deterministische, versioniert, immer aktuell). __

Einrichtung: Checkliste in 5 Minuten

# Schritt Bestellung

1

Graphify installieren

uv tool install graphifyy

2

Ausnahmen konfigurieren

Erstellen`.graphifyignore`

3

Knowledge Graph extrahieren

graphify . --no-viz

4

Die Diagramme generieren

./gradlew generateKnowledgeGraphDiagram

5

Ergebnisse committen

git add diagrams/knowledge-graph/

# Script complet en 5 commandes
uv tool install graphifyy
cat > .graphifyignore << 'EOF'
*-context.yml
*.env
build/
.gradle/
EOF
graphify . --no-viz
./gradlew generateKnowledgeGraphDiagram
git add graphify-out/GRAPH_REPORT.adoc graphify-out/graph.json diagrams/knowledge-graph/

Fallen und Minderungen

Falle Beschreibung Minderung

Zu dichter Graph

Ein großes Projekt erzeugt Hunderte von unlesbaren Knoten

Verwenden`-Pplantuml.kg.maxNodes=30`und nach Gemeinschaft filtern

Zu breite Ausschlüsse

Zu viele Dateien in`.graphifyignore`reduziert den Wert des Graphen

Zuerst nur credentials und build ausschließen

Richtung der Pfeile

Die Kanten INFERRED können eine mehrdeutige Richtung haben

Filtern nach`-Pplantuml.kg.edgeTypes=EXTRACTED`nur für bestimmte Beziehungen

veralteter Graph

Der Code ändert sich, aber der Graph wird nicht neu erstellt

verwenden`graphify . --update`regelmäßig oder der Git-Hook`graphify hook install`

Aktualisierte Kosten

Inkrementelle Updates sind nahezu kostenlos (tree-sitter lokal)

Nur die Dokumente (.adoc) sie verbrauchen LLM-Token

Was man am Ende erhält

Failed to generate image: PlantUML preprocessing failed: [From <input> (line 6) ]

@startuml
skinparam backgroundColor #FEFEFE

rectangle "Vor" as avant {
    card "Von Hand gezeichnete Diagramme
Immer veraltet
^^^^^
 Syntax Error? (Assumed diagram type: activity)

@startuml
skinparam backgroundColor #FEFEFE

rectangle "Vor" as avant {
    card "Von Hand gezeichnete Diagramme
Immer veraltet
Niemand aktualisiert sie" as av1 #FDEDEC
}

rectangle "NACH" as apres {
    card "Automatisch generierte Diagramme
Immer auf dem neuesten Stand mit dem Code
In Git versioniert
Deterministisch und reproduzierbar" as ap1 #E8F8E8
}

avant --> apres : graphify . --no-viz\n+ ./gradlew generateKnowledgeGraphDiagram

@enduml

Die konkreten Vorteile:

Gewinn Detail

Immer aktuelle Dokumentation

Die Diagramme spiegeln den aktuellen Code wider, kein manueller Snapshot

Kein Wartungsaufwand

Die Diagramme regenerieren sich bei jedem Build

Reduzierung der technischen Schulden

Es ist nicht mehr notwendig, Diagramme manuell zu pflegen

Visueller Kontext für die neuen

Ein neuer Entwickler versteht die Architektur, indem er die Diagramme betrachtet

potenzielles Fine-tuning

Die Paare (Untergraph → Diagramm) sind Beispiele für KI-Training

Automatische Validierung

`PlantumlService.validateSyntax()`prüft jedes generierte Diagramm

Schnelles Onboarding

5 Diagramme = vollständige Übersicht der Architektur

(No output needed; keep empty.) Wer ein Warum hat kann alle Wie ertragen. __

Der Warum : stets aktuelle Diagramme. Der Wie : zwei Befehle in einem Gradle-Pipeline.

Verwandte Artikel