# Betrieb: KI-Review für git.javagil.de (Versuch mit `mi/werkprobe`) Stand: 2026-10-05. Diese Datei beschreibt die laufende Testintegration. Sie enthält keine Secrets, nur deren Fundorte. ## Überblick Werkator startet für jeden neuen Head-Commit eines offenen PRs ohne WIP-Präfix einen Review-Build. Der Build läuft in einer Werkdock-Sandbox mit werkrevisor. werkrevisor liest den PR über die Gitea-API, wendet feste Regeln an, lässt PR-Agent das Modell fragen und bildet das Urteil. Danach schreibt werkrevisor einen Kommentar und ein Review in Gitea. Werkator meldet den Exit-Code als Status `ai-review/gate` an die Head-SHA. ```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["mih09"] werkator["Werkator"] subgraph sandbox["Werkdock-Sandbox, 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 ``` | Urteil | Gitea-Aktion von werkrevisor | `ai-review/gate` | Merge | | ------ | ----------------------------------------------------------------- | ---------------- | ---------------------------------------- | | GREEN | Kommentar, Review `APPROVED` für die Head-SHA | success | möglich, wenn die CI grün ist | | YELLOW | Kommentar, offizielle Review-Anfrage an `mi` | success | gesperrt bis zu einem Approval von `mi` | | RED | Kommentar, Review `REQUEST_CHANGES` mit höchstens 3 Befunden | failure | gesperrt bis zu einem neuen Review | | ERROR | Kommentar „review not completed“, kein Review | failure | gesperrt | Ein PR mit WIP-Präfix bekommt keinen Review und deshalb keinen `ai-review/gate`-Status; er ist damit gesperrt. ## Versionen | Komponente | Version | | ----------- | ---------------------------------------------------------------------------------------- | | Gitea | 1.27.3 (git.javagil.de) | | Werkator | 1.36.1 auf mih09 (`trigger.onPullRequestTarget`, PR#117; frisches Home je Review, PR#118) | | werkrevisor | 0.4.0 (`mi/werkrevisor`), Rootfs `werkrevisor-rootfs-0.4.0.tar.zst`, Konfiguration in `WERKREVISOR_CONFIG_TOML` | | PR-Agent | 0.47.0, Image `pragent/pr-agent@sha256:7d98954c29289846a08faf00aaea0f1f1375b1676cd8a2ed303e0af07010af7a` | | Modell | `openrouter/anthropic/claude-sonnet-5.5` | ## Konfiguration ohne Secrets Die Betreiber-Konfiguration ist `config/werkprobe.toml` im werkrevisor-Image (`/werkrevisor/config/werkprobe.toml`). Ein PR kann sie nicht ändern. Wichtige Werte: - Preise 2,00 / 10,00 USD pro 1 Mio. Input- / Output-Tokens; - höchstens 25.000 Input- und 4.000 Output-Tokens; - höchstens 0,20 USD pro Review, einschließlich einer Wiederholung; - automatisch freigebbar: nur Doku, nur hinzugefügte Tests, Doku plus Tests, Refactoring mit unveränderten Tests; - immer mindestens YELLOW: Pfade zu Auth, Rechten, Migrationen, Secrets, CI und Deployment (`.werkator*`, `.gitea/**`, `Dockerfile*`, Build-Dateien); - Secret-Scan der hinzugefügten Zeilen: Ein Treffer führt zu YELLOW, ohne Modellaufruf. Ab werkrevisor 0.4.0 kann die Konfiguration stattdessen in der Maschinen-Konfiguration stehen; sie hat dann Vorrang vor der Datei im Image: ```yaml buildCommand: python -s -m werkrevisor werkdock: enabled: true rootfs: /home/storage/mih09/users/werkator/werkrevisor-rootfs-0.4.0.tar.zst env: PATH: /app/.venv/bin:/usr/local/bin:/usr/bin:/bin PYTHONPATH: /werkrevisor:/app PYTHONNOUSERSITE: "1" WERKREVISOR_CONFIG_TOML: | # vollständiger Inhalt von config/werkprobe.toml, angepasst ``` Modell und Reasoning-Stufe wechselt man dort über `id`, die beiden Preise und `reasoning_effort`; der nächste Review nutzt sie ohne neues Archiv. Immer die ganze Konfiguration einfügen: Fehlende Abschnitte bekommen Standardwerte, z. B. ohne riskante Pfade. werkdock bindet auf mih09 das gemeinsame Toolchain-Home des Repositories als `/root`; normale PR-Builds können es beschreiben. Deshalb startet werkrevisor ab 0.4.0 nur mit `python -s` und `PYTHONNOUSERSITE=1`, liest nichts aus dem Home-Verzeichnis und bricht sonst mit Exit 30 ab. Ab werkrevisor 0.5.0 wählt `[engine] mode` den Review: `llm` ist der bisherige LLM-Review und der Standard, `classifier` bewertet nur die PR-Dokumente mit Jev, `combined` beides. Für `classifier` und `combined` braucht `werkdock.env` zusätzlich `TYPESAFE_API_KEY`; `config/werkprobe.toml` enthält dafür schon den Abschnitt `[classifier]` mit Fragen und Schwellwerten. Die Werkator-Build-Definition steht in der Maschinen-Konfiguration auf mih09: `~/werkprobe/.git/werkator/.werkator.yml` (Rechte `600`), Build `ai-review`. Ein Branch kann diese Definition weder ändern noch abschalten. ## Secrets und Rechte | Secret | Fundort | Rechte | | -------------------- | ----------------------------------------------------------------------- | ----------------------------------------------------------------- | | `GITEA_BOT_TOKEN` | mih09: `werkdock.env` in `~/werkprobe/.git/werkator/.werkator.yml` | Token `pr-agent-bot` von `ai-reviewer`: repository, issue (Lesen und Schreiben), user (Lesen) | | `OPENROUTER_API_KEY` | ebenda | OpenRouter-Key `review-agents`, Limit 5 USD, monatlich zurückgesetzt | | `TYPESAFE_API_KEY` | noch nicht eingerichtet; gehört neben `OPENROUTER_API_KEY` | TypeSafe-Key für Jev, nur für `[engine] mode` `classifier` oder `combined` | | Werkator-Token | mih09: `~/.werkator.yml`, `defaults.git.token` | Token von `mi`; meldet die Werkator-Status | `ai-reviewer` ist Mitarbeiter mit Schreibrecht nur in `mi/werkprobe`; ohne Schreibrecht zählt sein Approval nicht als offiziell. Das Konto darf keine Repositories oder Organisationen anlegen. Eine lokale Kopie der Secrets für Tests liegt auf dem Arbeitsrechner in `~/.config/pr-agent-test/secrets.env` (Rechte `600`). ### OpenRouter-Key austauschen 1. Auf https://openrouter.ai/settings/keys einen neuen Key mit Limit anlegen. 2. Auf mih09 in `~/werkprobe/.git/werkator/.werkator.yml` den Wert von `OPENROUTER_API_KEY` ersetzen. Werkator liest die Datei beim nächsten Poll, ein Neustart ist nicht nötig. 3. Den alten Key auf OpenRouter löschen. ## Branch Protection von `main` in `mi/werkprobe` | Feld | Wert | Zweck | | ------------------------------------ | ---------------------------- | -------------------------------------------------------- | | `enable_status_check` | `true` | | | `status_check_contexts` | `werkator`, `ai-review/gate` | CI und KI-Review sind Pflicht | | `required_approvals` | `1` | das Approval ist die Sperre für YELLOW | | `enable_approvals_whitelist` | `true` | | | `approvals_whitelist_username` | `ai-reviewer`, `mi` | GREEN-Bot-Approval oder menschliches Approval | | `block_on_rejected_reviews` | `true` | RED sperrt | | `block_on_official_review_requests` | `true` | die YELLOW-Anfrage an `mi` sperrt | | `dismiss_stale_approvals` | `true` | neue Commits entwerten alte Approvals | | `block_on_outdated_branch` | `true` | eine bewegte Basis braucht ein Update und damit einen neuen Review | Die bisherige Regel ist gesichert in `~/.config/pr-agent-test/werkprobe-branch-protections.backup-2026-10-04.json`. Sie verlangte nur den Status `werkator` und kein Approval. ## Abnahme | Fall | PR | Ergebnis | | ------------------------------------------------- | -------------------------------------------------------- | ------------------------------------------------------------------------ | | 1. harmlose Änderung | [#8](https://git.javagil.de/mi/werkprobe/pulls/8) | GREEN, Bot-Approval, gemergt ohne menschliches Approval | | 2. riskanter Bereich | [#9](https://git.javagil.de/mi/werkprobe/pulls/9) | YELLOW, Merge abgelehnt („Does not have enough approvals“), nach Approval von `mi` gemergt | | 3. eingebauter Fehler | [#10](https://git.javagil.de/mi/werkprobe/pulls/10) | RED mit 2 zutreffenden Befunden, Merge abgelehnt | | 4. neuer Head, bewegte Basis | #8 | Merge mit alter Basis abgelehnt; nach dem Update gesperrt bis zum neuen GREEN | | 5. ungültiger Key, Timeout, Budget, abgeschnittene Antwort | lokal mit `tools/dry-run` | jeweils ERROR, nie GREEN | | 6. wiederholter Lauf | #10, Neustart in Werkator | Urteil wiederverwendet, kein Modellaufruf, kein zweiter Kommentar | Modellqualität und Gate-Mechanik sind getrennt zu bewerten: - `gemini-3.8-flash` hat den Fehler in #10 übersehen, Sonnet 5.5 hat ihn gefunden. - Einen Fehler, der eine Randbedingung außerhalb des Diffs verletzt ([#11](https://git.javagil.de/mi/werkprobe/pulls/11)), fanden weder Sonnet 5.5 noch DeepSeek V4 Pro noch GPT-6 Astra „high“. Den Merge hat dort die feste Regel verhindert (Kategorie `mixed`). ## Kosten Gemessen mit den von OpenRouter gemeldeten Kosten: | Lauf | Tokens (Input / Output) | Kosten | | ----------------------------- | ----------------------- | ---------- | | #8, Doku-Änderung, GREEN | 2.936 / 94 | 0,0068 USD | | #9, CI-Konfiguration, YELLOW | 3.030 / 315 | 0,0092 USD | | #10, Fehler, RED | 3.497 / 590 | 0,0129 USD | Der ganze Versuch mit allen lokalen Vergleichsläufen kostete 0,142 USD. Jeder Kommentar nennt die Kosten seines Laufs; Werkator archiviert `build/werkrevisor/usage.jsonl` als Artefakt. Fehlende Verbrauchsdaten stehen dort als `unknown`, geschätzte Kosten als `estimated`. ## Bekannte Grenzen - Das Modell sieht den Diff und die vollständigen geänderten Dateien (ab 0.3.0, `full_files = true`), aber keine anderen Dateien. Randbedingungen, die nur in nicht geänderten Dateien stehen, erkennt es nicht. Mit Diff allein hat kein getestetes Modell den Fehler in #11 gefunden; mit den vollständigen Dateien fand Sonnet 5.5 ihn. - Ein menschliches Approval startet keinen neuen Review; `ai-review/assessment` zeigt deshalb weiter den Stand des letzten Reviews. Für den Merge ist nur `ai-review/gate` verpflichtend. - Wenn nur die Basis sich bewegt, startet kein neuer Review; `block_on_outdated_branch` erzwingt dann ein Update. - Review-Builds teilen sich das Limit `maxConcurrentPerRepository: 1` mit der CI und warten auf sie. - Bei Modellen mit wechselnden Anbietern (z. B. DeepSeek) kann der tatsächliche Preis über dem eingetragenen liegen. - `block_admin_merge_override` ist `false`: Ein Gitea-Administrator kann die Sperre beim Merge übergehen. ## Stoppen, neu starten, zurückbauen **Reviews anhalten:** In `~/werkprobe/.git/werkator/.werkator.yml` den Block `builds.ai-review` auskommentieren. Solange `ai-review/gate` Pflicht ist, sind dann alle PRs gesperrt; deshalb gleichzeitig die Branch Protection zurücksetzen (siehe unten) oder nur `ai-review/gate` aus `status_check_contexts` nehmen. **Neu starten:** Den Block wieder aktivieren. Einen einzelnen Review wiederholt die Werkator-Oberfläche („Restart“) am Build `@ai-review`. **Neue werkrevisor-Version:** Mit `tools/build-rootfs` ein Archiv bauen, nach `/home/storage/mih09/users/werkator/` kopieren und in der Maschinen-Konfiguration den Pfad `werkdock.rootfs` auf das neue Archiv setzen. Beim Wechsel auf 0.4.0 zusätzlich `buildCommand: python -s -m werkrevisor` und `PYTHONNOUSERSITE: "1"` in `werkdock.env` setzen. Jede Version braucht einen eigenen Dateinamen. **Vollständiger Rückbau:** 1. Branch Protection wiederherstellen, mit einem Admin-Token von `mi`: ```bash curl -X PATCH -H "Authorization: token $GITEA_SETUP_TOKEN" -H 'Content-Type: application/json' \ https://git.javagil.de/api/v1/repos/mi/werkprobe/branch_protections/main \ -d '{"status_check_contexts":["werkator"],"required_approvals":0,"enable_approvals_whitelist":false,"approvals_whitelist_username":[],"block_on_rejected_reviews":false,"block_on_official_review_requests":false,"dismiss_stale_approvals":false,"block_on_outdated_branch":false}' ``` 2. Auf mih09 die Maschinen-Konfiguration aus `~/werkprobe/.git/werkator/.werkator.yml.bak-2026-10-05-before-ai-review` zurückkopieren. 3. Die Archive `werkrevisor-rootfs-*.tar.zst` in `/home/storage/mih09/users/werkator/` löschen; Werkator entfernt das zugehörige Werkdock-Image selbst. 4. In Gitea `ai-reviewer` und `werkprobe-dev` aus den Mitarbeitern von `mi/werkprobe` entfernen, ihre Tokens löschen und die Konten deaktivieren. 5. Den OpenRouter-Key `review-agents` löschen, sofern ihn nichts anderes mehr nutzt. 6. Den Einrichtungs-Token `pr-agent-setup` von `mi` löschen.