# LAI Automatisierung Kontrollierter Coding-Agent fuer Failure Reports aus [`lai`](https://gitea.tisinfra.de/christian.meyer/lai). Der Orchestrator verwendet [Aider](https://aider.chat/) headless als austauschbaren Coding-Kern. Git-, Gitea-, Policy- und Freigabelogik bleiben in diesem Projekt. ## Warum Aider? - scriptbarer Einmal-Auftrag mit `--message-file` - gute Git- und Repository-Map-Unterstuetzung - Mistral ueber LiteLLM nutzbar - automatische Commits koennen deaktiviert werden - deutlich kleinerer Betriebsumfang als OpenHands OpenHands bleibt eine moegliche spaetere Alternative fuer komplexere, mehrstufige Agentenlaeufe. Sein Headless-Modus arbeitet jedoch immer mit `always-approve`; deshalb muessen auch dort unsere externen Policy-Gates erhalten bleiben. ## Ablauf ```text failure_reports(open) -> transaktionales Claiming (SKIP LOCKED) -> anonymisierter Agentenauftrag -> frischer Clone von lai.git -> Aider-Aenderung ohne Commit -> Pfad-, Groessen- und Sicherheitsgates -> Tests -> Commit -> PR oder kontrollierter Push auf main -> failure_reports(resolved/agent_failed) ``` Der Coding-Agent erhaelt keinen Zugang zur ERP- oder Kundendatenbank. Rohdaten und `.env`-Dateien sind ausgeschlossen. Repository-Pushes verwenden `GIT_ASKPASS`; Tokens werden nicht in Remote-URLs oder Prozessargumenten gespeichert. Der Orchestrator laeuft als privilegierter Containerprozess, startet Aider aber als separaten Benutzer `coder`. Dieser Unterprozess erhaelt nur Modell-Credentials, nicht die Failure-DB- oder Gitea-Zugangsdaten. Die Workspace-Setup- und Testprozesse erhalten separat konfigurierte `TEST_DB_*`-Zugangsdaten. Dieser Benutzer darf ausschliesslich die isolierten Testschemas bearbeiten. Fuer Laravel werden daraus `DB_*`, `ERP_DB_*` und `COCKPIT_CONFIG_DATABASE` gesetzt; Aider selbst sieht diese Werte nie. Produktive ERP- oder Kundenzugangsdaten duerfen hier nicht verwendet werden. Vor Aider und erneut vor der abschliessenden Validierung installiert `SETUP_COMMANDS` die Abhaengigkeiten, erstellt die Vite-Assets und initialisiert mit `php artisan migrate:fresh --force` das isolierte Laravel-Schema neu. `TEST_COMMANDS` enthaelt die eigentlichen Pruefungen. Deshalb muessen alle `TEST_DB_*`-Schemas dediziert und vollstaendig entbehrlich sein. Lokale Ollama-Modelle laufen fuer Produktionsdateien in einem einzelnen Whole-File-Durchgang. Devstral und andere externe Coding-Modelle verwenden direkt das Diff-Format statt desselben Modells zusaetzlich als Architect und Editor aufzurufen. Das halbiert Modellrunden fuer kleine Reparaturen. Bei gezielt gerouteten Dateien ist die zusaetzliche Repo-Map deaktiviert. Automatische URL-Erkennung und Web-Scraping sind deaktiviert, damit URLs in Anwendungscode oder Tests niemals als externe Rechercheauftraege interpretiert werden. `AGENT_TIMEOUT_SECONDS` begrenzt Agentenprozess und Modell-API-Aufruf. `AGENT_IDLE_TIMEOUT_SECONDS` beendet zusaetzlich einen Agenten, der trotz laufendem Prozess standardmaessig fuenf Minuten keine Ausgabe mehr erzeugt; vorhandene Teilpatches werden danach weiterhin validiert. Setup-Fehler werden als Infrastrukturfehler beendet und nicht als Codekorrektur an das Modell zurueckgegeben. Hat ein lokales Modell vor einem Timeout bereits Dateien geaendert, durchlaufen diese Teilresultate trotzdem Policy, Syntaxpruefung und Tests; nur ein Timeout ohne Diff verwirft den Versuch sofort. Laravel-Tests laufen mit PHP und Composer direkt im isolierten Worker. Der Docker-Socket des Hosts wird nicht eingebunden. Abgebrochene Claims werden nach standardmaessig 90 Minuten wieder freigegeben; `STALE_CLAIM_MINUTES` passt dieses Intervall an. Explizite Nur-Entfernen-Auftraege werden als negativer SQL-Vertrag geprueft: Der verlangte Ausdruck muss aus der passenden Referenzabfrage verschwinden, in einer negativen Test-Assertion vorkommen, und alle anderen Felder, Joins, Filter, Gruppierungen sowie bestehenden Tests muessen unveraendert bleiben. Ist der Ausdruck in einer eindeutig zur Benutzerfrage passenden, getrackten Referenzabfrage bereits entfernt, wird ein veralteter Report ohne Agentenlauf und ohne PR als `already_fixed` abgeschlossen. Schlaegt Policy, Syntax oder isolierte Validierung fehl, erhaelt Aider kontrollierte Korrekturversuche mit redigierter Diagnose. Syntaxgueltige Teilpatches werden als Checkpoint erhalten; unerwartete Dateien werden verworfen. Nach einem Testfehler bleiben alle gerouteten Produktions- und Testdateien sichtbar, damit der Agent die Ursache korrigieren kann, statt nur Assertions an fehlerhaftes Verhalten anzupassen. Mehrteilige Feedbacks zu Antwortformat und expliziten Routing-Praefixen werden an ihre jeweiligen Anwendungseigentuemer geroutet und muessen vollstaendig abgedeckt sein. Zwei identische Policy-Fehler hintereinander brechen frueh ab. `MAX_AGENT_ATTEMPTS` ist auf 1 bis 7 begrenzt. ## Schnellstart ```bash cp .env.example .env # FAILURE_DB_PASSWORD und bei Bedarf MISTRAL_API_KEY eintragen # TEST_DB_PASSWORD fuer den Benutzer der isolierten Testschemas eintragen docker compose build docker compose run --rm automation check docker compose run --rm automation once ``` Der Default `AUTOMATION_MODE=dry-run` claimt einen offenen Report, erzeugt den anonymisierten Auftrag und setzt ihn danach wieder auf `open`. Es wird weder ein Agent gestartet noch gepusht. ## Fortschritt beobachten ```bash docker compose ps automation docker compose exec automation lai-agent check docker compose logs -f automation ``` Der Worker protokolliert keine unredigierten Prompts, SQL-Ergebnisse oder Secrets. Aider-Ausgabe wird ohne Terminalfarben live, redigiert und pro Zeile begrenzt protokolliert; in Report-Metadaten landet nur ein begrenzter Ausgabetail. Fuer jeden Versuch erscheinen Modell, Edit-Strategie, Dateien, PID, Laufzeit, Ausgabeaktivitaet und Ergebnisstatus. Zusaetzlich erscheinen Workspace-Vorbereitung, Policy-Pruefung, jeder Validierungsbefehl, Commit, PR-URL und Cleanup. Bei laengeren Agenten- oder Testphasen wird alle 30 Sekunden Laufzeitfortschritt ausgegeben und `updated_at` als Datenbank-Lease erneuert. Nur wirklich verwaiste Claims werden nach `STALE_CLAIM_MINUTES` wieder freigegeben. ## PR-Modus ```dotenv AUTOMATION_MODE=pr GITEA_USERNAME=automation-bot GITEA_TOKEN=... MISTRAL_API_KEY=... ``` Der Bot benoetigt Schreibzugriff auf `christian.meyer/lai` und die Berechtigung, Branches sowie Pull Requests anzulegen. Jeder Lauf erstellt `ai/failure-{report_id}` und einen PR gegen `main`. ## Direkter main-Modus ```dotenv AUTOMATION_MODE=direct-main ALLOW_DIRECT_MAIN=true GITEA_TOKEN=... ``` Der zweite Schalter ist ein Kill-Switch. In diesem Modus sind Migrationen, Routes, Auth, Middleware, PermissionService und SQLValidatorService zusaetzlich blockiert. Branch Protection muss den Bot fuer direkte Pushes explizit zulassen. PR-Modus bleibt die empfohlene Betriebsart. ## Modelle Das Modell wird ausschliesslich ueber `AGENT_MODEL` gewaehlt. Devstral ist der Default und ein Coding-Agent, nicht das Chat-Modell der Laravel-Anwendung: ```dotenv AGENT_MODEL=mistral/devstral-latest MISTRAL_API_KEY=... ``` Codestral verwendet denselben Mistral-Zugang: ```dotenv AGENT_MODEL=mistral/codestral-latest MISTRAL_API_KEY=... ``` Qwen 3.5 27B ueber OpenRouter: ```dotenv AGENT_MODEL=openrouter/qwen/qwen3.5-27b OPENROUTER_API_KEY=... ``` Oder mit einem lokalen Ollama auf dem Docker-Host: ```dotenv AGENT_MODEL=ollama_chat/qwen3.5:27b OLLAMA_API_BASE=http://host.docker.internal:11434 ``` Nach einer Aenderung wird der Worker neu erstellt, damit Compose die neue Umgebung uebernimmt: ```bash docker compose up -d --force-recreate automation docker compose exec -T automation lai-agent check ``` Aider verwendet fuer lokale Produktionsreparaturen `whole` und sonst das praezise `diff`-Format. Das Chat-Modell und Coding-Modell sind bewusst getrennt. Fuer Coding-Agenten sollte ein agentisch/coding-optimiertes Modell verwendet werden. Ein Wechsel zu OpenHands oder einem anderen Backend erfordert einen neuen Adapter neben `AiderAgent`. ## Tests ```bash python -m venv .venv . .venv/bin/activate pip install ".[dev]" ruff check src tests pytest -q ``` ## Repositorys - Chat: `https://gitea.tisinfra.de/christian.meyer/lai.git` - Automatisierung: `https://gitea.tisinfra.de/christian.meyer/lai_automatisierung.git`