Files
werkrevisor/docs/anleitung-dev.hostsharing.net.md
claude-codeandClaude Opus 5.5 3e6c6b5424
ai-review/assessment AI findings; a developer approval after checking them unlocks the merge; a human review request is pending
ai-review/gate build succeeded after 00:14
werkator/server build succeeded after 00:00
werkator build succeeded after 00:13
werkator/werkrevisor-statistics build succeeded after 00:00
PR#15 doc lists the hsadmin-ng tiers as configured; the guide's tier bullets are clear; a test no longer sits after unittest.main()
Fixes the three findings of the self-review.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 20:55:33 +02:00

15 KiB
Raw Permalink Blame History

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). 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; RBAC und Security werden ORANGE, Migrationen bleiben YELLOW, bis das Team anders entscheidet.

Zusammenspiel

So arbeiten die Systeme zusammen:

flowchart LR
    dev["Entwickler"] -- "push, PR ohne WIP" --> gitea
    human["Mensch, z. B. mi"] -- "Approval bei YELLOW oder ORANGE" --> 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:<br/>Build ai-review, Secrets,<br/>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 /<br/>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.

Ab werkrevisor 0.8.0 kann hsadmin-ng eine eigene Datei .werkrevisor.toml im Wurzelverzeichnis bekommen. Sie liegt über der Host-Konfiguration und gewinnt je Schlüssel. werkrevisor liest sie über die Gitea-API aus dem Basis-Commit des PRs, nie aus dem PR selbst. Dorthin gehören Größe, Kategorien, harte ORANGE- und YELLOW-Pfade, PR-Dokumente, Review-Anweisungen und die Fragen an Jev.

Modell, Preise, Budget, Gate und Engine bleiben in der Host-Konfiguration; setzt die Datei einen dieser Schlüssel, endet der Review mit ERROR. Eine Änderung an .werkrevisor.toml braucht immer ein menschliches Approval und wirkt erst nach dem Merge. Bis dahin bleibt config/hsadmin-ng.toml vollständig.

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_context_tokens = 150000 begrenzt die Eingabe, weil lange Prompts den Review auch innerhalb des Kontextfensters verschlechtern.
    • werkrevisor leitet aus max_usd_per_review und max_output_tokens eine zweite Grenze ab: die größte Eingabe, für die 2 × (Input × Preis + Output × Preis) höchstens 1 USD ergibt, hier 200.000 Tokens. Es gilt die kleinere der beiden Grenzen; ein PR darüber bekommt keinen KI-Review und wird YELLOW.
  • Größe: [size] max_changed_lines = 1000 und max_files = 40; Dateien der Kategorie docs zählen nicht. Ein größerer PR wird ORANGE: Ein Entwickler gibt ihn bewusst frei, das Modell prüft ihn trotzdem. 1000 Zeilen trifft etwa jeden vierten hsadmin-ng-PR und liegt knapp unter der harten Grenze von tools/pr-quick-check.
  • Kategorien: docs = doc/**, **/*.md; tests = src/test/**; main = src/main/**; api_spec = src/main/resources/api-definition/**. Ab werkrevisor 0.10.0 ist auch Hauptcode mit nur hinzugefügten Tests automatisch freigebbar (feature_with_tests). Eine geänderte oder entfernte Testzeile oder ein abgeschalteter Test ergibt YELLOW. [categories] harmless nennt weitere harmlose Dateien, z. B. .editorconfig; der Standard ist leer.
  • Harte ORANGE-Regeln, Vorschlag ([hard_orange] paths, ein Entwickler prüft den PR bewusst):
    • RBAC (**/rbac/**, src/main/resources/db/changelog/1-rbac/**);
    • Security und Anmeldung (**/*Security*, **/*ApiKey*, **/*Auth*, **/*auth*, **/*Jwt*, **/*Oidc*);
    • Rechte und Rollen (**/*Rbac*, **/*rbac*, **/*Permission*);
    • Secrets (**/*secret*, **/*.pem, **/*.key, .env*, .tc-environment).
  • Harte YELLOW-Regeln, Vorschlag ([hard_yellow] paths):
    • Liquibase-Changelogs src/main/resources/db/**; ab werkrevisor 0.10.0 sind DB-Schema-Pfade eingebaut, z. B. **/*.sql, **/db/changelog/** und **/migrations/**; keine Konfigurationsebene kann sie entfernen;
    • 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. Eine Datei, die zu beiden Stufen passt, zählt nur als ORANGE. Dateien der Kategorie docs zählen nie dazu, z. B. doc/PR/…-rbac-….md.
  • Secret-Scan: secret_scan_exclude = ["src/test/**"], weil Testdaten erfundene Passwörter enthalten; private Schlüssel, AWS-Schlüssel und vollständige hsak_- und sk-or-v1--Schlüssel zählen auch dort.
  • Offene Fragen: [pr_doc] globs = ["doc/PR/*.md"]; ein offener Punkt im Abschnitt „Open Questions“ oder „Offene Fragen“ eines geänderten PR-Dokuments ergibt RED ohne Modellaufruf. Erlaubt sind nur Punkte, die mit [x] als erledigt markiert sind.
  • 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). Ab 0.8.0 gilt das nicht für Doku: Sie erreicht das Modell nur als Diff und zählt nicht gegen die Grenzen. Passt eine Datei nicht in die Grenzen max_full_file_chars bzw. max_full_files_chars, wird das Ergebnis höchstens YELLOW. Die vollständigen Dateien teilen sich die Eingabegrenze mit dem Diff: 300.000 Zeichen sind etwa 86.000 der 150.000 Tokens und lassen Platz für den Diff eines PRs mit 1000 Zeilen.
  • 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 ORANGE, 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:

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):

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.8.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_context_tokens = 150000
          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 max_context_tokens); 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 <PR-URL> 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/<owner>/<repo>/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 und ORANGE sperren bis zum Approval, RED bis zu einem neuen Commit.

Der Administrator der Repositories auf dev.hostsharing.net ist Betreiber, kein Entwickler. Ein Merge über die Sperre hinweg ist deshalb kein Ausweg aus einem falschen RED. Aus diesem Grund ergeben Befunde des Modells und des Classifiers nur ORANGE: Ein Entwickler prüft sie und gibt den PR mit seinem Approval frei. RED kommt nur aus festen Regeln, die ein neuer Commit erfüllen muss.

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:<version> 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:<version>).

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:<version>.

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.