# Betrieb: KI-Review für git.javagil.de
Stand: 2026-10-20.
Diese Datei beschreibt den Betrieb für acht Repositories:
werkprobe, werkrevisor, werkator, werkcrappit, werkregie, werkbaum, werkkompass und werkdock.
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, fragt Jev nach den Risiken,
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 oder ORANGE" --> 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")]
stats[("Statistik-Dienst
werkrevisor.javagil.de")]
end
subgraph internet["Dienste im Internet"]
openrouter["OpenRouter"] --> llm["Sprachmodelle"]
typesafe["TypeSafe: Jev"]
end
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 -- "Review-Prompt" --> openrouter
werkrevisor -- "Zusammenfassung des Diffs,
Auswahl von Ausschnitten" --> openrouter
werkrevisor -- "Fragen zu Dateien, PR-Dokument,
Findings und Kategorien" --> typesafe
werkrevisor -- "Nutzungsdatensatz" --> stats
werkrevisor -- "Ergebniskommentar, Zeilenkommentare, Approval,
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` |
| ORANGE | Kommentar mit den Befunden, offizielle Review-Anfrage an `mi`, kein Bot-Review | success | gesperrt bis zu einem Approval von `mi` nach Prüfung der Befunde |
| RED | Kommentar, Review `COMMENT` mit höchstens 3 verletzten Regeln | failure | gesperrt bis zu einem neuen Commit, der die Regel erfüllt |
| 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.
## Regeln
Die Regeln und ihre Gründe stehen in der [README](../README.md); hier nur das Wichtigste für den Betrieb:
- RED kommt nur aus festen Regeln, z. B. aus offenen Fragen im PR-Dokument; kein Approval hebt es auf.
- Befunde des Modells ergeben höchstens ORANGE, weil das Modell irren kann; Jev bewertet jeden Befund.
- YELLOW ist eine gefährliche Änderung ohne Befund, z. B. ein mögliches Secret, ein PR über den `[size]`-Grenzen
oder ein Bild über den `[images]`-Grenzen.
- Geringe Befunde und Verstöße gegen die Schreibregeln sind Hinweise; ein offener Zeilenkommentar hält den Merge auf.
- In allen acht Repositories bewertet Jev jede geänderte Datei (`[path_judge] scope = "all"`),
und das Modell berät nur (`[engine] model_role = "advises"`).
- Ein Repository kann eine eigene `.werkrevisor.toml` haben; werkrevisor liest sie am Kopf des Standard-Branches
und legt sie über die Host-Konfiguration; Modell, Budget und Gate bleiben beim Host.
Eine neue Version, die eine solche Datei braucht, erst nach deren Merge installieren.
## Versionen
| Komponente | Version |
| ----------- | ---------------------------------------------------------------------------------------- |
| Gitea | 1.27.3 (git.javagil.de) |
| Werkator | 1.42.1 auf mih09 |
| werkrevisor | `main` von `mi/werkrevisor`, verteilt vom Build `release`; Rootfs `werkrevisor-rootfs-.tar.zst`, Konfiguration in `WERKREVISOR_CONFIG_TOML` |
| PR-Agent | 0.47.0, Image `pragent/pr-agent@sha256:7d98954c29289846a08faf00aaea0f1f1375b1676cd8a2ed303e0af07010af7a` |
| Modell | werkprobe: `openrouter/anthropic/claude-sonnet-5.5`; die anderen: `openrouter/minimax/minimax-m3` |
| Ausschnitte | `openrouter/openai/gpt-6-luna` wählt die Zeilen eines Ausschnitts |
| Jev | `jev-latest` bei TypeSafe |
## Konfiguration ohne Secrets
Die Host-Konfiguration jedes Repositorys ist `config/.toml` in werkrevisor.
Auf mih09 steht sie als `WERKREVISOR_CONFIG_TOML` in der Maschinen-Konfiguration `~//.git/werkator/.werkator.yml`
(Rechte `600`), zusammen mit der Build-Definition `ai-review` und den Secrets.
Ein PR kann sie nicht ändern, und ein Branch kann die Build-Definition weder ändern noch abschalten.
werkator, werkcrappit und werkdock haben dort nur den Host-Teil; den Rest setzt ihre `.werkrevisor.toml`.
Eine Änderung, z. B. ein anderes Modell, geht so:
1. `config/.toml` in einem PR von werkrevisor ändern.
2. Nach dem Merge überträgt der Build `release` die Datei, zusammen mit dem neuen Archiv.
Er bricht vor jedem Schreiben ab, wenn auf mih09 ein Schlüssel steht, den die neue Version noch liest
und den die Datei nicht oder mit einem anderen Wert hat, z. B. ein dort umgestelltes Modell.
Einen Schlüssel, den die neue Version nicht mehr kennt, entfernt er.
Von Hand vergleicht `tools/sync-host-config mih09-werkator@mih09.hostsharing.net `;
mit `--apply` überträgt es, und der nächste Review nutzt die neue Konfiguration ohne neues Archiv.
Es gibt nur Zeilennummern und Namen von Schlüsseln aus, nie Werte, weil die Datei Tokens enthält.
Immer die ganze Konfiguration übertragen: Fehlende Abschnitte bekommen Standardwerte.
Wichtige Werte von werkprobe:
- Preise 2,00 / 10,00 USD pro 1 Mio. Input- / Output-Tokens;
- höchstens 100.000 Input-Tokens, die das Budget ergibt, und 4.000 Output-Tokens;
- höchstens 0,48 USD pro Review, einschließlich einer Wiederholung;
- automatisch freigebbar sind alle Änderungsarten, auch `mixed`;
- immer mindestens YELLOW: Pfade zu Secrets und jede Änderung am DB-Schema (`[db_schema] judge = "never"`);
Dateien der Kategorie `docs` zählen nie zu den Pfaden;
- Secret-Scan der hinzugefügten Zeilen: Ein Treffer führt zu YELLOW, ohne Modellaufruf;
unter `src/test/**` zählen nur echte Schlüsselformate, weil Testdaten erfundene Passwörter enthalten;
- Jev bewertet CI und Build als `judged_paths` und jede andere geänderte Datei;
- offene Fragen in einem geänderten PR-Dokument: RED ohne Modellaufruf.
Die Build-Definition startet werkrevisor aus dem Archiv:
```yaml
buildCommand: python -s -m werkrevisor
werkdock:
enabled: true
rootfs: /home/storage/mih09/users/werkator/werkrevisor-rootfs-.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/.toml
```
werkdock bindet auf mih09 das gemeinsame Toolchain-Home des Repositorys als `/root`; normale PR-Builds können es beschreiben.
Deshalb startet werkrevisor nur mit `python -s` und `PYTHONNOUSERSITE=1`, liest nichts aus dem Home-Verzeichnis
und bricht sonst mit Exit 30 ab.
Alle acht Repositories laufen mit `[engine] mode = "combined"`: Jev, dann das Modell mit den Hinweisen von Jev.
Dafür braucht `werkdock.env` zusätzlich `TYPESAFE_API_KEY`.
## Secrets und Rechte
| Secret | Fundort | Rechte |
| ------------------------- | ------------------------------------------------------------------ | ----------------------------------------------------------------- |
| `GITEA_BOT_TOKEN` | mih09: `~//.git/werkator/.werkator.yml` jedes geprüften Repositorys | Token `pr-agent-bot` von `ai-reviewer`: repository, issue (Lesen und Schreiben), user (Lesen) |
| `OPENROUTER_API_KEY` | ebenda | OpenRouter-Key `review-agents`, Limit 100 USD, monatlich zurückgesetzt |
| `TYPESAFE_API_KEY` | ebenda | TypeSafe-Key für Jev, nur für `[engine] mode` `classifier` oder `combined` |
| `WERKREVISOR_STATS_TOKEN` | ebenda, mit `WERKREVISOR_STATS_URL` | Source-Token des Statistik-Dienstes: darf nur Nutzungsdatensätze melden |
| `WERKREVISOR_STATISTICS_SOURCE_TOKENS` | mih09, Konto `mih09-werkrevisor`: Umgebung des Dienstes `werkrevisor-statistics` | die gültigen Source-Tokens, durch Kommas getrennt |
| Werkator-Token | mih09: `~/.werkator.yml`, `defaults.git.token` | Token von `mi`; meldet die Werkator-Status |
`ai-reviewer` ist Mitarbeiter mit Schreibrecht in den acht geprüften Repositories;
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 und für die Coding-Agents liegt auf dem Arbeitsrechner
in `~/.config/ai-coding-agents/secrets.env` (Rechte `600`); der Codex-Runner liest dort `GITEA_BOT_TOKEN`.
### Secrets austauschen
Ein Secret muss neu, sobald sein Wert sichtbar wurde, z. B. in einer Ausgabe, einem Transkript oder einer Prozessliste.
Immer nur ein Secret auf einmal austauschen.
Alter und neuer Wert gelten eine Zeit lang beide; so läuft jeder Review weiter.
`tools/rotate-secret` ändert einen Wert in jeder Maschinen-Konfiguration auf mih09, die ihn hat,
und in `~/.config/ai-coding-agents/secrets.env`.
Es gibt nie einen Wert aus und übergibt ihn nie als Argument; ist die Eingabe ein Terminal, fragt es verdeckt nach ihm.
Werkator liest die geänderten Dateien beim nächsten Poll, ein Neustart ist nicht nötig.
Im Folgenden steht `mih09` für `mih09-werkator@mih09.hostsharing.net`.
1. Den neuen Wert anlegen, den alten noch nicht widerrufen; wo, steht in der Tabelle unten.
Fehlt der Schlüssel in `secrets.env`, wie am 2026-10-20 `WERKREVISOR_STATS_TOKEN`,
holt `tools/rotate-secret fetch mih09 ` den alten Wert vom Host, ohne ihn auszugeben;
sonst fehlt er Schritt 6 in der Sicherung.
2. Den neuen Wert prüfen: `tools/rotate-secret probe -` fragt den Dienst, ohne Review und ohne Kosten.
3. Den neuen Wert verteilen: `tools/rotate-secret set mih09 `.
Es sichert jede Datei als `.bak-secret--`
und bricht ohne Änderung ab, wenn die Dateien mehr als einen alten Wert haben.
Danach prüft es jede Datei und nennt den SHA-256 des alten Werts für Schritt 7.
4. `tools/rotate-secret probe ` prüft den Wert, der jetzt in `secrets.env` steht.
5. Je Art von Repository einen echten Review abwarten, der durchläuft:
werkprobe mit Sonnet 5.5 und ein anderes Repository mit MiniMax M3;
beim OpenRouter-Key auch einen PR von werkrevisor mit Diagrammen.
Fehlt ein PR, einen Review in der Werkator-Oberfläche neu starten.
Dass der neue Wert genutzt wird, zeigen OpenRouter mit der Nutzung je Key und Gitea mit „Zuletzt verwendet“ am Token.
6. Den alten Wert beim Dienst widerrufen.
Die Probe mit der Sicherung muss ihn ablehnen:
`WERKREVISOR_SECRETS_ENV=~/.config/ai-coding-agents/secrets.env.bak-secret-- tools/rotate-secret probe `.
Danach noch einen Review abwarten.
7. Die Sicherungen löschen, die den alten Wert enthalten, auf mih09 und lokal:
`tools/rotate-secret purge mih09 `.
Es löscht nur Sicherungen; es verweigert die Arbeit, solange eine Maschinen-Konfiguration den alten Wert noch hat.
Erst austauschen, wenn auf mih09 werkdock 0.13.2 oder neuer läuft:
Ältere Versionen schreiben die Umgebung jedes laufenden Builds in
`/home/storage/mih09/users/werkator/werkdock/instances//config.json`, lesbar für die anderen Konten von mih09.
Nach dem letzten der vier Secrets dort die Verzeichnisse beendeter Builds löschen, die `--rm` nach einem Abbruch übrig ließ.
`tools/rotate-secret check mih09 ` zeigt jederzeit, ob jede Datei den Wert von `secrets.env` hat
und wie viele Sicherungen ihn enthalten.
| Secret | Neuen Wert anlegen | Alten Wert widerrufen |
| ------------------------- | -------------------------------------------------------------------- | ----------------------------------------- |
| `GITEA_BOT_TOKEN` | in git.javagil.de als `ai-reviewer` unter „Einstellungen“ → „Anwendungen“, mit den Rechten der Tabelle oben | dort den alten Token löschen |
| `OPENROUTER_API_KEY` | auf https://openrouter.ai/settings/keys, Limit 100 USD, monatlich zurückgesetzt | dort den alten Key löschen |
| `TYPESAFE_API_KEY` | auf https://console.typesafe.ai/keys | dort den alten Key löschen |
| `WERKREVISOR_STATS_TOKEN` | einen Zufallswert in `WERKREVISOR_STATISTICS_SOURCE_TOKENS` anhängen, mit Komma, und den Dienst neu starten | den alten Wert dort entfernen und den Dienst neu starten |
Der Statistik-Dienst nimmt alle Source-Tokens der Liste an; erst wenn er den neuen kennt, ihn verteilen.
Ein Neustart des Dienstes dauert Sekunden; eine Meldung, die in dieser Zeit scheitert, schreibt werkrevisor ins Log,
und der Review läuft weiter.
Einen Zufallswert ergibt z. B. `python3 -c 'import secrets; print(secrets.token_urlsafe(32))'` im Terminal des Menschen.
### Später automatisch austauschen
Was eine Automatik je Secret braucht:
- `WERKREVISOR_STATS_TOKEN`: nichts Neues, denn beide Seiten sind unsere.
Ein Werkzeug erzeugt den Wert, trägt ihn in die Umgebung des Dienstes ein und verteilt ihn.
- `OPENROUTER_API_KEY`: einen Management-Key von OpenRouter.
`POST /api/v1/keys` legt einen Key mit `name`, `limit` und `limit_reset` an, `DELETE /api/v1/keys/{hash}` löscht ihn.
Ein Management-Key kann keine Modelle aufrufen; er gehört nur auf den Arbeitsrechner.
- `GITEA_BOT_TOKEN`: das Passwort von `ai-reviewer`, denn `POST` und `DELETE /api/v1/users/ai-reviewer/tokens`
nehmen nur Basic Auth an.
Ohne Passwort legt `gitea admin user generate-access-token` auf dem Gitea-Host einen Token an.
- `TYPESAFE_API_KEY`: eine API für Keys, die TypeSafe nicht anbietet.
Die öffentliche API hat nur `/v1/models` und `/v1/systemone`.
Die Konsole https://console.typesafe.ai/keys legt mehrere Keys an, ändert und löscht sie,
aber über die Sitzung einer Anmeldung, nicht über eine dokumentierte API.
Eine Automatik bräuchte eine Verwaltungs-API von TypeSafe; bis dahin bleibt dieser Austausch Handarbeit.
## 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` | ein menschliches `REQUEST_CHANGES` sperrt |
| `block_on_official_review_requests` | `true` | die YELLOW- oder ORANGE-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 |
`block_admin_merge_override` bleibt hier bewusst aus: Als Administrator kann `mi` an der Sperre vorbei mergen.
Das ist der Ausweg aus einem falschen RED; dafür kann ein Merge aus Gewohnheit das Approval übergehen,
wie am 2026-10-06 bei Werkator PR#127.
Für `mi/werkator` gilt seit 2026-10-06 dieselbe Regel; die vorherige liegt in
`~/.config/ai-coding-agents/backups/werkator-branch-protections.backup-2026-10-06.json`.
Für weitere Repositories setzt `tools/branch-protection` diese Felder mit dem Token eines Repository-Administrators;
es sichert die bisherige Regel vorher als JSON-Datei.
Die bisherige Regel ist gesichert in `~/.config/ai-coding-agents/backups/werkprobe-branch-protections.backup-2026-10-04.json`.
Sie verlangte nur den Status `werkator` und kein Approval.
## PR-Ablauf und automatischer Merge
In den acht geprüften Repositories eröffnet Claude jeden PR als `claude-code` mit „WIP: “;
den ganzen Ablauf beschreibt [agentic-workflow.md](agentic-workflow.md).
Ist der PR fertig, entfernt Claude das Präfix per `PATCH /api/v1/repos///pulls/` mit dem neuen `title`.
Nur dieser protokollierte Wechsel startet den Review (`[gate] require_wip_transition`);
ein PR ohne vorheriges „WIP: “ bekommt ERROR und kein Approval.
Nach GREEN, YELLOW oder ORANGE plant der Bot den Merge ein (`[gate] automerge`):
GREEN mergt sofort, YELLOW und ORANGE mit dem Approval von `mi`.
## Abnahme im Versuch vom 2026-10-05
| 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; ab 0.6.0 wäre das ORANGE |
| 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
Am 2026-10-13 kostete ein Review mit MiniMax M3, der Zusammenfassung, der Auswahl der Ausschnitte und Jev
zwischen etwa 0,01 und 0,06 USD.
Der Statistik-Dienst https://werkrevisor.javagil.de zeigt die Kosten jedes Reviews.
Im Versuch vom 2026-10-05 mit Sonnet 5.5, 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`.
Ein Lauf ohne Modellaufruf steht als `none` mit 0 USD; der Kommentar sagt dann „no model call, cost 0 USD“.
## Bekannte Grenzen
- Das Modell sieht den Diff, die geänderten Dateien ganz oder als Ausschnitt und `AGENTS.md`, 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 `~//.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:** Nach jedem Merge auf `main` baut Werkator sie selbst,
mit dem Build `release` des Repositorys werkrevisor.
Er setzt das Archiv aus dem Basis-Archiv `werkrevisor-base-.tar.zst` und den Dateien von `main` zusammen
und trägt es in jede Maschinen-Konfiguration ein, die ein werkrevisor-Archiv nennt.
Eine schon verteilte Version baut er nicht noch einmal.
Der Teil des Hosts in `~/werkrevisor/.git/werkator/.werkator.yml` steht im README unter „Operation“.
**Neues Basis-Archiv:** Das Basis-Archiv enthält das PR-Agent-Image, Node.js und PR Lens;
ein neues PR-Agent-Image oder eine neue Version in `tools/pr-lens/package-lock.json` ändert seinen Namen.
Der Build `release` schlägt fehl, bis das neue Basis-Archiv daliegt.
Deshalb vor dem Merge eines solchen PR auf der Workstation im Stand des PR `tools/build-rootfs --base` aufrufen
und das Archiv nach `/home/storage/mih09/users/werkator/` kopieren.
`python3 tools/release_rootfs.py base-name` nennt den erwarteten Namen.
**Von Hand**, etwa wenn Werkator nicht läuft: mit `tools/build-rootfs` das Archiv bauen und es verteilen:
```bash
tools/deploy-rootfs werkrevisor-rootfs-.tar.zst mih09-werkator@mih09.hostsharing.net \
/home/storage/mih09/users/werkator
```
Das Werkzeug setzt `werkdock.rootfs` in jeder Maschinen-Konfiguration, die ein werkrevisor-Archiv nennt, sichert sie vorher
und behält die zwei neuesten Archive.
**Vollständiger Rückbau** am Beispiel von werkprobe; für jedes andere Repository entsprechend:
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.