hermes update sabotiert deine Arbeit nicht mehr: Gateways drainen, Backends überleben, präzise Windows-Kills

Kennst du das? Eine langlaufende Aufgabe ist auf halbem Weg, du tippst beiläufig hermes update – und im nächsten Moment wird das Gateway einfach gekillt: Die Konversation stirbt mitten im Turn, und alles, worauf du gewartet hast, ist weg. Unter Windows war es noch schlimmer: Der Updater hat einmal jede hermes.exe auf dem Rechner gekillt und dabei auch fremde Installationen und Projekte mitgerissen. In den letzten Wochen hat das Team den Upgrade-Flow von Grund auf neu gebaut (Kampagne #91277), und das neueste Paket ist gerade gelandet. Upgrades sind jetzt sanft: Laufende Turns drainen vor dem Beenden, Remote-Verbindungen bleiben bestehen, und containerbasierte Installationen sind komplett geschützt.
Updates waren früher ein Glücksspiel
Die alte Update-Pipeline war im Kern ein Force-Kill-Pfad: hermes update musste die venv-Dateien freigeben, also tree-killte es jedes laufende Gateway – egal, ob es mitten in einem Turn feststeckte. Die Identifikation „welche Prozesse gehören mir?“ stützte sich auf einen argv-Pattern-Scan – unpräzise und anfällig für Kollateralschäden.
Unter Windows war der Trade-off noch schärfer: Das Gateway musste sterben, damit das Update weiterlaufen konnte, und die alte Pause-Mechanik zwang dich, zwischen „Gateway übersteht App-Schließen“ und „Update kann fortfahren“ zu wählen. Ein Update mitten im Turn zerstörte diesen Turn einfach.
Verbesserung 1: Gateways drainen statt zu sterben (#95695)
hermes update bittet ein laufendes Gateway jetzt, sich über seinen Control-Socket zu drainen und zu beenden – über ein neues pause-for-update-Verb: neue Turns ablehnen, den aktiven beenden, seine finale Antwort ausliefern, alle venv-Dateihandles freigeben, dann stoppen – exakt der Drain-Pfad, den auch SIGUSR1 und Service-Neustarts nutzen.
Ist der Socket nicht erreichbar (ein Step-1-Gateway ohne das Verb, oder gar kein Socket), bekommt der Client None zurück und fällt bytegenau auf den Legacy-Pfad zurück. Ein erfolgreiches ACK trägt pausing / already_stopping / pid / drain_timeout, und der Updater verlängert seine Wartezeit auf das selbst deklarierte Drain-Budget des Gateways (plus 10 s Tear-Down-Gnadenfrist), statt ein Gateway mitten im Turn am Ende eines zu kurzen lokalen Defaults wegzukillen.
Für die meisten Nutzer heißt das: Der Turn, der beim Upgraden läuft, darf zu Ende gehen.
Verbesserung 2: Remote-Serve-Backends überleben das Update (#95576)
Wenn du hermes serve --host <ip> betreibst, um ein Remote-Desktop zu versorgen, kannte die alte Pipeline den Prozess nicht: Er fehlte im Runtime-Inventory, war für --status unsichtbar – und wurde nach dem Kill nie wieder gestartet, sodass der Remote-Client an einem toten Endpoint strandete.
Serve-/Dashboard-Backends registrieren sich jetzt selbst im Spawn-Ledger – mit ihrem tatsächlich gebundenen Host/Port/Profile (bewusst selbst registrierte Identität, kein weiterer argv-Pattern-Scan). Nach einem Update laufen sie auf ihrem aufgezeichneten Endpoint weiter, Remote-Verbindungen werden also nicht unterbrochen. Das schließt auch eine lange bestehende Asymmetrie: Serve-Backends waren per hermes dashboard --stop killbar, aber vor --status versteckt – jetzt listet --status sie auf.
Verbesserung 3: Der Windows-Updater killt nur die hermes.exe dieser Installation (#95086)
Das war das Gruseligste. Der alte Windows-Updater führte taskkill /IM hermes.exe aus – einen Kill über den gesamten Image-Namen, der jeden Prozess namens hermes.exe auf dem Rechner traf, inklusive fremder Installationen und laufender Arbeit (Issue #91964 war ein echter Fall, in dem der Updater-Shim fremde Installationen mitten im Lauf mitriss).
force_kill_other_hermes() beendet jetzt nur noch Prozesse, deren voller Executable-Pfad zum eigenen venv-Scripts-Verzeichnis dieser Installation passt (Toolhelp32-Snapshot + QueryFullProcessImageNameW, case-insensitives Pfad-Prädikat). Mehrere Hermes-Installationen auf einem Rechner stören sich nicht mehr gegenseitig – ein Update fasst immer nur die eigene an.
Verbesserung 4: SSH-Backends und fremde HOMEs sind kein Kollateralschaden mehr (#95641)
Die Stale-Backend-Bereinigung hat dieselbe Disziplin bekommen: Der Sweep killt keine SSH-eigenen Backends mehr (SSH-Eigentum bleibt während Updates erhalten) und startet nie Backends aus einem fremden HERMES_HOME neu (#94030). Früher konnte ein Update deine Remote-SSH-Sitzungen und Prozesse in fremden Verzeichnissen killen; diese Grenzen sind jetzt durchgesetzt.
Verbesserung 5: Per Image verwaltete Installationen verweigern In-Place-Updates (#95722)
Docker-, Nix- und apt-Installationen sollten durch Pullen eines neuen Images und Neubau des Containers aktualisiert werden – nicht durch hermes update innerhalb eines Containers, das ein unveränderliches Image mutiert. Vorher hatten die drei Update-Oberflächen (hermes update, hermes update --check und der Desktop-Update-Button) jeweils eigene Docker/Nix/apt-Heuristiken – und ein bind-gemountetes Checkout im Container sah aus wie eine git-Installation und täuschte die Checks. Verweigerungen hinterließen außerdem keine Spur.
Der Image-Build bäckt jetzt /etc/hermes/image-provenance.json ins Image (außerhalb des bind-mountbaren Checkouts und des HERMES_HOME-Volumes), und alle drei Einstiegspunkte laufen durch ein gemeinsames Admission-Gate:
- Marker vorhanden (auch fehlerhaft) → image-verwaltet; In-Place-Updates werden verweigert, die CLI endet mit Exit-Code 2 (refused-by-contract) und druckt
not updatable in place (<code>); use: <command>; - Marker fehlt → die bisherigen Heuristiken gelten wie gehabt;
hermes update --planmeldet jetzt ehrlichupdatable_in_place=False– selbst wenn ein bind-gemountetes Checkout die alten git-Heuristiken täuschen würde.
So sollte dein Upgrade-Flow aussehen
Standard-Installationen (das curl-Skript) funktionieren wie bisher:
hermes update --check # zuerst den Plan prüfen – keine Überraschungen
hermes update # Gateways drainen, Serve-Backends überleben
Docker-Nutzer, denk dran: führe hermes update nicht in einem Container aus. Zieh das neue Image und baue neu:
docker pull <your-hermes-image>:latest
docker compose up -d --build # oder wie auch immer du es orchestrierst
Mehrere Installationen unter Windows? Du kannst dich entspannen – ein Update fasst nur die eigene an. Vor dem Upgraden zeigt dir hermes status die Serve-/Dashboard-Backends, damit du weißt, was läuft.
Fazit
Diese Runde bringt keine neuen Features, aber sie verwandelt „Upgrade“ von etwas, das jederzeit explodieren konnte, in etwas, das du mitten im Arbeitstag sicher ausführen kannst: Turns laufen zu Ende, Remote-Verbindungen halten, andere Installationen bleiben unangetastet, und Container-Installationen können sich nicht selbst kaputt machen. Zusammen mit dem Gateway-Loop-Watchdog und den gemeinsam genutzten Docker-Containern, die wir vorher behandelt haben, wird der Alltag spürbar zuverlässiger. Diese Änderungen liegen gerade alle auf main, noch in keinem Release-Tag – um sie heute auszuprobieren, aktualisiere per hermes update auf den neuesten Dev-Build; die v0.20.5-Release-Notes fassen derweil die vorherige Welle operativer Verbesserungen zusammen.