# Anleitung: KI-Review für hsadmin-ng auf dev.hostsharing.net Stand: 2026-10-05, nach dem Versuch auf git.javagil.de (siehe [betrieb-git.javagil.de.md](betrieb-git.javagil.de.md)). Diese Anleitung ist noch nicht ausgeführt. Was vor Ort zu prüfen ist, steht als „prüfen“ dabei. ## Ziel Die Repositories `hostsharing/hs.hsadmin.ng` und das Frontend-Repository (Name prüfen) bekommen denselben KI-Review wie `mi/werkprobe`. Unterschiede zum Versuch: - Ein Frontier-Modell und höchstens 1 USD pro Review, weil es nur 2–3 PRs pro Tag gibt. - Werkator läuft auf vm4006 mit rootless Docker statt Werkdock. - Eigene Regeln für automatisch freigebbare Änderungen; Migrationen und RBAC bleiben YELLOW, bis das Team anders entscheidet. ## Zusammenspiel So arbeiten die Systeme zusammen: ```mermaid flowchart LR dev["Entwickler"] -- "push, PR ohne WIP" --> gitea human["Mensch, z. B. mi"] -- "Approval bei YELLOW" --> gitea subgraph gitea["Gitea"] pr["Pull Request"] bp{"Branch Protection"} end subgraph host["vm4006"] werkator["Werkator"] subgraph sandbox["Docker-Container, frisches Home"] werkrevisor["werkrevisor"] --> pragent["PR-Agent"] end mcfg[("Maschinen-Konfiguration:
Build ai-review, Secrets,
WERKREVISOR_CONFIG_TOML")] end openrouter["OpenRouter"] --> llm["Sprachmodell"] werkator -- "pollt neue Heads und offene PRs" --> pr mcfg -. "Befehl, Umgebung" .-> werkator werkator -- "CI-Build" --> ci["normaler Build"] werkator -- "PR-Target-Build" --> werkrevisor werkrevisor -- "liest PR, Diff, Dateien" --> pr pragent -- "Prompt" --> openrouter werkrevisor -- "Kommentar, Approval / Request changes /
Review-Anfrage, ai-review/assessment" --> pr werkator -- "Status werkator und ai-review/gate" --> pr pr --> bp bp -- "Merge erlaubt oder gesperrt" --> dev ``` ## Voraussetzungen | Was | Soll | prüfen | | ----------------------- | ------------------------------------------ | ------------------------------------------------------------------ | | Gitea | 1.27.3 | erledigt: `GET https://dev.hostsharing.net/api/v1/version` | | Werkator auf vm4006 | mindestens 1.36.0 | Fußzeile der Werkator-Oberfläche | | Docker auf vm4006 | rootless, für den Werkator-Benutzer | `docker info` als dieser Benutzer | | Gitea-Administrator | darf Konten anlegen | Menü „Site Administration“ | | Werkator-Gitea-Token | in `.git/werkator/.werkator.yml` (`git.token`) | nötig, damit Werkator offene PRs liest | ## 1. Bot-Konto 1. In dev.hostsharing.net als Administrator das Konto `ai-reviewer` anlegen: - lokal; - Passwort im Passwort-Manager; - „Max. Anzahl an Repositorys“ `0`; - nicht Administrator, keine Organisationen. 2. In beiden Repositories `ai-reviewer` mit Recht „Schreiben“ eintragen. Bei Organisations-Repositories geht das als Mitarbeiter oder über ein eigenes Team nur für diese beiden Repositories. Ohne Schreibrecht zählt das Approval des Bots nicht als offiziell. 3. Als `ai-reviewer` den Token `pr-agent-bot` erzeugen: - repository: Lesen und Schreiben; - issue: Lesen und Schreiben; - user: Lesen. Ohne „user: Lesen“ kann werkrevisor seine eigenen Kommentare nicht erkennen. ## 2. OpenRouter-Key Einen eigenen Key für Hostsharing anlegen, damit die Kosten getrennt bleiben, z. B. `hostsharing-review`. Vorschlag für das Limit: 60 USD, monatlich zurückgesetzt; das reicht für etwa 60–90 Reviews bis 1 USD. Für den Classifier Jev (ab werkrevisor 0.5.0, `[engine] mode` `classifier` oder `combined`) kommt ein TypeSafe-Key hinzu. Er steht als `TYPESAFE_API_KEY` neben `OPENROUTER_API_KEY` in `docker.env`. Mit dem Standard `mode = "llm"` ist er nicht nötig. ## 3. Modell und Betreiber-Konfiguration Die Konfiguration steht in werkrevisor unter `config/hsadmin-ng.toml` und kommt ins Image; ein PR kann sie nicht ändern. Vor der Aktivierung festzulegen: - **Modell:** Kandidaten mit Preisen vom 2026-10-05 in USD pro 1 Mio. Tokens (Input / Output): - `anthropic/claude-sonnet-5.5`: 2 / 10; - `openai/gpt-6-astra`: 10 / 50. Auswahl nach einem Offline-Vergleich (Schritt 6), nicht nach Gefühl. - **Preise und Grenzen:** - Die Preise des gewählten Modells gehören in `[model]`. - `max_input_tokens` und `max_output_tokens` so wählen, dass `2 × (Input × Preis + Output × Preis)` höchstens 1 USD ergibt. - **Kategorien:** `docs` = `doc/**`, `**/*.md`; `tests` = `src/test/**`; `main` = `src/main/**`; `api_spec` = `src/main/resources/api-definition/**`. - **Harte YELLOW-Regeln, Vorschlag:** - Liquibase-Changelogs `src/main/resources/db/**`; - RBAC und Security (`**/rbac/**`, `**/*Security*`, `**/*ApiKey*`); - Build und Abhängigkeiten (`build.gradle.kts`, `buildSrc/**`, `gradle/**`); - CI und Deployment (`.werkator*`, `tools/remote`, `Dockerfile*`); - Profile (`src/main/resources/application*.yml`). Die endgültige Liste legt das Team fest. - **Projektwissen:** - `repo_context_files = ["AGENTS.md"]` gibt dem Modell die Review-Regeln des Projekts mit. - PR-Agent liest die Datei über die Gitea-API aus der Basis des PRs, nie aus dem PR selbst; ein PR kann seine eigenen Review-Regeln also nicht ändern. - **Gate:** `yellow_gate = "approval"`, `human_reviewers` = die drei Entwickler-Konten. - **Vollständige Dateien:** Ab werkrevisor 0.3.0 sieht das Modell nach dem Diff auch den vollständigen neuen Inhalt jeder geänderten Datei (`full_files = true`). Passt eine Datei nicht in die Grenzen `max_full_file_chars` bzw. `max_full_files_chars`, wird das Ergebnis höchstens YELLOW. - **Engine:** `[engine] mode = "llm"` bleibt der Standard. Mit `combined` bewertet Jev zuerst die Abschnitte und Gherkin-Szenarien der PR-Dokumente unter `doc/PR/`; ein klar schlechtes Szenario ergibt RED, auch ohne Befund des LLM. Die Fragen und Schwellwerte in `[classifier]` vorher mit `tools/jev-eval` an den vorhandenen PR-Dokumenten prüfen. ## 4. Image auf vm4006 Auf vm4006 als Werkator-Benutzer: ```bash git clone https://git.javagil.de/mi/werkrevisor.git && cd werkrevisor docker pull pragent/pr-agent:0.47.0@sha256:7d98954c29289846a08faf00aaea0f1f1375b1676cd8a2ed303e0af07010af7a docker build --pull=false -t werkrevisor:$(sed -n 's/^__version__ = "\(.*\)"$/\1/p' werkrevisor/__init__.py) . ``` Jede neue werkrevisor-Version bekommt ein eigenes Tag; die Build-Definition nennt das Tag ausdrücklich. ## 5. Werkator-Build-Definition Je Repository in der Maschinen-Konfiguration `.git/werkator/.werkator.yml` auf vm4006 (nie in eine eingecheckte Datei): ```yaml builds: ai-review: trigger: onPullRequestTarget: true statusContext: ai-review/gate cleanCommand: "" buildCommand: python -s -m werkrevisor timeout: 15m artifactDirs: [build/werkrevisor] docker: enabled: true image: werkrevisor:0.4.0 env: PYTHONNOUSERSITE: "1" GITEA_BOT_TOKEN: "…" OPENROUTER_API_KEY: "…" # nur für [engine] mode "classifier" oder "combined": # TYPESAFE_API_KEY: "…" # Die vollständige Betreiber-Konfiguration, Ausgangspunkt ist config/hsadmin-ng.toml. WERKREVISOR_CONFIG_TOML: | [model] id = "openrouter/anthropic/claude-sonnet-5.5" input_price_usd_per_mtok = 2.00 output_price_usd_per_mtok = 10.00 max_input_tokens = 190000 max_output_tokens = 10000 reasoning_effort = "medium" # … alle weiteren Abschnitte aus config/hsadmin-ng.toml … ``` Modell und Reasoning-Stufe wechselt man in `WERKREVISOR_CONFIG_TOML` (`id`, beide Preise, `reasoning_effort`, bei Bedarf die Token-Grenzen); der nächste Review nutzt sie, ein neues Image ist nicht nötig. Der eingebettete TOML-Text ersetzt die Datei vollständig, deshalb immer die ganze Konfiguration einfügen; fehlt ein Abschnitt, bricht werkrevisor mit ERROR ab. `python -s` und `PYTHONNOUSERSITE=1` verhindern, dass Python Code aus dem Home-Verzeichnis lädt; ohne sie bricht werkrevisor mit Exit 30 ab. Die Datei muss die Rechte `600` haben. Zuerst eine Sicherung der bisherigen Datei anlegen. Das Timeout muss über `timeout_seconds × (max_retries + 1) + 120` Sekunden liegen. ## 6. Erprobung vor der Aktivierung 1. **Nur Regeln, kostenlos:** `tools/dry-run config/hsadmin-ng.toml` für die letzten etwa 25 gemergten PRs. Ergebnis: Welche PRs würden die Regeln automatisch freigeben, welche würden sie sperren? 2. **Mit Modell:** dieselben PRs mit `--llm` und je Kandidatenmodell; zuerst PRs, deren Befunde aus menschlichen Reviews bekannt sind. Ergebnis: gefundene und übersehene Befunde sowie die Kosten je Modell. 3. Mit dem Team die Regeln und das Modell festlegen. `tools/dry-run` schreibt nichts nach Gitea; es braucht `GITEA_BOT_TOKEN` (Lesen genügt) und für `--llm` den OpenRouter-Key. ## 7. Branch Protection Erst nach Schritt 6 und erst, wenn ein paar echte PRs ohne Pflicht gelaufen sind. 1. Die bestehende Regel sichern: `GET /api/v1/repos///branch_protections/master` in eine Datei schreiben. 2. Die Regel per `PATCH` ergänzen; die bestehenden Status-Kontexte (z. B. `GitTally`) bleiben: | Feld | Wert | | ----------------------------------- | --------------------------------------------- | | `status_check_contexts` | bisherige Kontexte und `ai-review/gate` | | `required_approvals` | `1` | | `enable_approvals_whitelist` | `true` | | `approvals_whitelist_username` | `ai-reviewer` und die menschlichen Reviewer | | `block_on_rejected_reviews` | `true` | | `block_on_official_review_requests` | `true` | | `dismiss_stale_approvals` | `true` | | `block_on_outdated_branch` | `true` | | `block_admin_merge_override` | `true`, damit auch Administratoren die Sperre nicht übergehen | 3. Mit einem harmlosen PR prüfen: GREEN wird mergebar, YELLOW sperrt bis zum Approval. ## Vertrauensmodell Auf vm4006 laufen nur eng zusammengehörige Repositories (Backend und Frontend von hsadmin-ng). Pushen können nur Entwickler, die ohnehin Schreibrecht auf allen diesen Repositories und vollen Zugriff auf vm4006 haben. Ein CI-Build mit Docker-Socket (Testcontainers) könnte das Image `werkrevisor:` umbenennen oder ersetzen; dieses Restrisiko ist akzeptiert, weil ein PR niemandem mehr Zugriff verschafft, als er schon hat. Sobald Fremde pushen dürfen, etwa bei einem öffentlichen Repository, muss die Build-Definition das Image über seine ID ansprechen (`docker image inspect --format '{{.Id}}' werkrevisor:`). ## Rückbau 1. Die gesicherte Branch-Protection-Regel per `PATCH` zurückschreiben. 2. Den Block `builds.ai-review` aus der Maschinen-Konfiguration entfernen. 3. `ai-reviewer` aus den Repositories entfernen, Token löschen, Konto deaktivieren. 4. Den OpenRouter-Key löschen. 5. `docker image rm werkrevisor:`. ## Offene Punkte vor dem Einsatz - Vollständige geänderte Dateien als Kontext (werkrevisor). - Review-Builds sollen nicht hinter der CI warten; dazu müssen sie das Limit `maxConcurrentPerRepository` umgehen können (Werkator). - Ein menschliches Approval sollte `ai-review/assessment` aktualisieren (Werkator oder werkrevisor). - Konfiguration für das Frontend-Repository; dessen Pfade kenne ich noch nicht.