# Konzept: Diagramme von PR Lens im Review-Kommentar Stand: 2026-10-18, Übergabe aus einer Sitzung im Repo hsadmin-ng; noch nichts umgesetzt. ## Ziel werkrevisor macht das Review weiter allein. Zusätzlich hängt es an seinen Review-Kommentar ein Architektur- und Datenfluss-Diagramm des PR. Das Diagramm hilft dem menschlichen Reviewer zu sehen, was ein PR berührt. Die Risiko-Triage von werkrevisor verbessert es nicht direkt. ## PR Lens [PR Lens](https://prlens.dev) von Coldtea erzeugt animierte Diagramme zu einem PR; der Kern ist MIT-lizenziert: [github.com/coldteadotai/pr-lens](https://github.com/coldteadotai/pr-lens). - Die GitHub-App macht Diagramm und Review, unterstützt aber nur GitHub, GitLab und Bitbucket, kein Gitea. - Das CLI-Kommando `analyze` liest den Diff gegen die Merge-Base, fragt ein LLM und schreibt `.pr-lens/graph.json`. Anbieter: `gemini` (Standard), `openai` oder `openai-compatible` mit eigener Base-URL. Nur `analyze` ruft ein Modell auf. - Das Format von `graph.json` beschreibt `packages/schema`. - `@coldtea/pr-lens-renderer` (npm, ohne Abhängigkeiten) macht aus `graph.json` animierte SVGs, hell und dunkel, und ein Manifest. - Für GitLab lädt PR Lens die SVGs als Anhänge ins Projekt hoch, für Bitbucket in die Downloads; für Gitea gibt es nichts Fertiges. Das Review von PR Lens brauchen wir nicht, es deckt sich mit werkrevisor. ## Was werkrevisor schon hat - `werkrevisor/gitea.py`: `create_issue_comment`, `create_review` und `edit_issue_comment` mit `GITEA_TOKEN`. Der Client sendet bisher nur JSON. - OpenRouter als LLM-Zugang, für hsadmin-ng mit `openrouter/anthropic/claude-sonnet-5.5` (`config/hsadmin-ng.toml`). OpenRouter ist OpenAI-kompatibel; `analyze` kann es also mit `openai-compatible` nutzen. ## Zwei Betriebsarten - **git.javagil.de:** werkrevisor läuft als Build in Werkator und kommentiert selbst; hier ist der volle Ablauf unten möglich. - **dev.hostsharing.net:** dort läuft nur `hs-review` auf der Workstation; es schreibt einen Entwurf, nur lesend, und der Mensch stellt die Befunde selbst ein. Die Schritte 3 und 4 entfallen; `hs-review` legt die SVGs neben den Entwurf, und der Mensch hängt sie beim Einstellen an. ## Möglicher Ablauf 1. `graph.json` erzeugen, nach Variante A oder B. 2. `pr-lens-renderer` erzeugt die SVGs. 3. werkrevisor legt den Review-Kommentar an und lädt die SVGs mit `POST /repos/{owner}/{repo}/issues/comments/{id}/assets` (multipart) hoch. 4. werkrevisor ergänzt den Kommentar per `edit_issue_comment` um die Bildlinks. **Variante A:** werkrevisor ruft `pr-lens analyze` mit OpenRouter als `openai-compatible` auf. Der Prompt von PR Lens bleibt in Gebrauch; das kostet aber einen zweiten LLM-Aufruf je Review. **Variante B:** Das Review-LLM liefert `graph.json` im selben Lauf mit. Das ist günstiger, und der Diff geht an kein zweites Modell. Dafür müssen wir den Prompt für das Schema selbst schreiben und pflegen. ## Grenzen des Diagramms Das Diagramm ist nur eine Sichthilfe, keine Aussage darüber, was der PR tut. In beiden Varianten geht der Inhalt des PR in den Prompt. Ein gezielt gebauter PR kann so ein harmlos wirkendes Diagramm erzeugen, das z. B. einen Abfluss von Daten verschweigt; die Messung vom 2026-10-17 zeigt, dass ein solcher Abfluss in einer passenden Datei leicht übersehen wird. Der Kommentar sagt das beim Diagramm in einem Satz. ## Neue Abhängigkeiten - Node.js für CLI und Renderer. Das ist eine neue Technik und braucht eine eigene Entscheidung des Menschen, mit den Alternativen, z. B.: - Node.js nur in einem Container, nicht auf dem Host; - den Renderer nach Python portieren, er hat keine Abhängigkeiten; - nur Variante B, dann braucht es `analyze` nicht. - Multipart-Upload im `GiteaClient`. - Kein neuer Token, falls der Upload mit derselben Berechtigung `write:issue` geht wie das Kommentieren. ## Lieferkette werkrevisor läuft wie `pull_request_target` und hält `GITEA_TOKEN` und den Schlüssel für OpenRouter. - Die npm-Pakete laufen mit festen Versionen und Prüfsummen, in einem Container ohne `GITEA_TOKEN`. - `analyze` bekommt nur den Schlüssel für OpenRouter, der Renderer keinen Schlüssel und kein Netz. - Mit npm werden `npm audit` und `license-checker` Pflicht-Prüfungen im Build (siehe agentic-workflow). ## Offene Fragen - [x] TODO.svg: Lässt `[attachment] ALLOWED_TYPES` auf dev.hostsharing.net und git.javagil.de SVG-Anhänge zu? Ja, auf beiden; aber höchstens 5 Dateien je Kommentar (`max_files`), bei 100 MB je Datei. - [x] TODO.anzeige: Zeigt Gitea ein angehängtes SVG im Kommentar mit Animation an, oder nur als Download? Inline und animiert; Gitea liefert `image/svg+xml` mit einer CSP, die Skripte sperrt. - [x] TODO.zugriff: Sind Anhänge privater Repos nur für angemeldete Benutzer mit Leserecht sichtbar? Ja; ohne Anmeldung kommt 404. - [x] TODO.token: Reicht `write:issue` des Bot-Tokens für den Upload? Mit dem Token von `claude-code` geht es; das Bot-Token hat keinen Zugriff auf werkrevisor-bench. Das erste eingeschaltete Repo zeigt es; ein fehlendes Recht gibt nur eine Zeile im Log. - [x] TODO.dateien: Höchstens 5 Anhänge je Kommentar, PR Lens macht je Diagramm 2 SVGs. Nur die helle Fassung, höchstens `max_diagrams = 5`. - [x] TODO.variante: Variante A oder B; dafür Kosten und Qualität an einigen hsadmin-ng-PRs messen. Variante A, entschieden am 2026-10-18 nach dem Versuch unten. - [x] TODO.schalter: Wie heißt der Schalter je Repo in der Konfiguration, und gilt er als Standard aus? `[diagrams] enabled`, nur in der Host-Konfiguration, Standard aus. - [x] TODO.grenzen: Was passiert bei großen Diffs oder einem Fehler von `analyze`? Ein fehlendes Diagramm darf das Review nie beenden und das Ergebnis nicht ändern. Der Diff wird nach `max_diff_bytes` abgeschnitten; ein Fehler oder eine Zeitüberschreitung gibt nur eine Zeile im Log. ## Versuch von Hand, 2026-10-18 Ohne Änderung an werkrevisor, für hsadmin-ng PR#319 (Tarife am Partner, 36 Dateien, +1489 −13): - `@coldtea/pr-lens-cli@0.13.2` in `node:22` unter Podman; MIT, 4 Abhängigkeiten, `npm audit` ohne Befund. - `analyze` spricht nur mit dem genannten Anbieter; `prlens.dev` nur bei `canvas` und `auth`. - `analyze --provider openai-compatible --base-url https://openrouter.ai/api/v1 --model anthropic/claude-sonnet-5.5`, nur mit `OPENROUTER_API_KEY` im Container: 174 KB Prompt (etwa 45k Token), 35 s, 15 Knoten, 16 Kanten, 2 Abläufe. - `render` ohne Netz: 3 Diagramme (Architektur, 2 Abläufe), je hell und dunkel; keine Skripte, keine externen Verweise. - Inhalt brauchbar: Controller, Tarif-Domäne, neuer Trigger und neue Tabelle, mit NEW und CHANGED markiert. - Upload mit `POST /repos/{owner}/{repo}/issues/comments/{id}/assets` und Bildlinks per Edit: [werkrevisor-bench Issue 89](https://git.javagil.de/mi/werkrevisor-bench/issues/89). Variante B, nachgestellt mit einem eigenen Skript: ein Aufruf mit kurzer Review-Anweisung, dem System-Prompt von PR Lens, Schema und Diff; die Antwort ist `{"review": …, "graph": …}`. - 71k Token Eingabe, 5,3k Ausgabe, 31 s, 0,195 USD. - `graph` gültig im ersten Versuch: 11 Knoten, 14 Kanten, 2 Abläufe; die Abläufe zeigen auch die 400-Fälle. - Das Review daneben ist brauchbar: 5 Befunde mit Datei und Zeile. Kosten je Review mit `anthropic/claude-sonnet-5.5` (2 USD je 1M Token Eingabe, 10 USD je 1M Ausgabe): | Variante | Zusatzkosten | Grund | |----------|--------------|--------------------------------------------------------------| | A | etwa 0,21 USD | Diff und Anweisungen ein zweites Mal, dazu etwa 7k Token Ausgabe | | B | etwa 0,10 USD | nur Anweisungen und Schema (etwa 15k Token) und die Ausgabe | Haken an B: werkrevisor fragt das Review-Modell über PR-Agent 0.47.0; dessen Antwort ist ein festes YAML-Format, `extra_instructions` ändern es nicht. B im selben Lauf heißt also, in PR-Agent einzugreifen, oder einen eigenen Aufruf neben PR-Agent; der eigene Aufruf ist aber Variante A mit eigenem Prompt. Für das Rendern braucht B weiter Node.js, außer der Renderer wird portiert. ## Entscheidung, 2026-10-18 Variante A, mit dem Diff aus der Gitea-API statt einer Arbeitskopie: `werkrevisor/pr_lens.mjs` nutzt Prompt, Schema und Prüfung des festgelegten PR Lens. Node.js und PR Lens liegen im schreibgeschützten Basis-Archiv, nicht in einem Container: die Sandbox von werkdock auf mih09 hat keine Container-Laufzeit. nvm im Konto `mih09-werkator` hilft nicht: die Sandbox sieht es nicht, und das Toolchain-Home, das sie einbindet, können normale PR-Builds beschreiben. Der Kindprozess bekommt nur den Schlüssel für OpenRouter; er könnte als derselbe Benutzer aber die Umgebung von werkrevisor aus `/proc` lesen. Je Host abschaltbar, Standard aus. Auf git.javagil.de hängt werkrevisor die hellen SVGs an seinen Kommentar; `hs-review` folgt in einem eigenen PR. ## Nächster Schritt Umsetzung in werkrevisor PR#121; siehe `docs/prs/2026-10-18-PR#121-pr-lens-diagrams.md` und `docs/DECISIONS.md`.