# Updates — die Sonntags-Kette, Festhalten, Freigeben _Stand 24.09.2026, Code in `main` = `75611be`. Für Techniker und Agenten; für den User: Seite „Updates" in [BEDIENUNG.md](BEDIENUNG.md)._ Die Box aktualisiert ihre Fremd-Software jeden Sonntag selbst: erst llama-swap, dann den Motor (llama.cpp), dann Hermes. Jeder Baustein wird danach geprüft; ist die Prüfung rot, rollt die Box zurück und hält den Baustein fest, bis ihn jemand freigibt. Sicherheitsupdates des Betriebssystems laufen getrennt über unattended-upgrades. Modelle wechseln nie automatisch (Modell-Radar, Knopf „Übernehmen"). ## Ablauf ```mermaid flowchart TD T["mc2-autoupdate.timer
So 04:30 (+≤10 min)"] --> S["jobs/sonntags-update.sh"] S --> A["autoupdate.sh"] A --> R["1 · llama-swap
update-swap.sh"] R --> E["2 · Motor
update-engine.sh"] E --> H["3 · Hermes
Job über MC2"] H --> W["Wochenbericht
[Box-Update]"] W --> N{"Neustart nötig?
nur So 04–07 Uhr"} ``` 1. `mc2-autoupdate.timer` (`Persistent=true`, bis 10 min Zufallsverzug) startet `mc2-autoupdate.service` (einmaliger Lauf nach `mc2-backup.service`, Zeitlimit 3 h). Die Unit ruft `deploy/jobs/sonntags-update.sh`, das `deploy/autoupdate.sh` startet und nur dann selbst meldet, wenn `autoupdate.sh` mit Fehler endet (letzte 15 Zeilen). Der Hermes-Cron „Updates am Sonntag" ist seit 24.09. pausiert. 2. `autoupdate.sh` bricht mit Meldung ab, wenn MC2 (`/api/health`) nicht antwortet. 3. **llama-swap und Motor:** Ein festgehaltener Baustein wird übersprungen. Sonst liefert `GET /api/maintenance/update-details?kind=swap` bzw. `kind=engine` die installierte und die neueste Version. Gibt es Neues, läuft `sudo -n bash deploy/update-swap.sh` bzw. `update-engine.sh` (fehlt die sudo-Freigabe, wartet der Baustein mit Hinweis). Die Skripte sichern die alte Version (`/usr/local/bin/llama-swap.bak`, `/opt/llamacpp-vulkan.bak`), stoppen llama-swap, tauschen, starten und prüfen mit `stack-postcheck.sh`. Ergebnis 0 = eingespielt, 1 = zurückgerollt (Baustein wird festgehalten, Meldung), 2 = Update und Rückweg gescheitert (Meldung „KRITISCH", dringend). 4. **Hermes:** Ein festgehaltener Hermes wird übersprungen. Sonst sagt `update-details?kind=hermes`, wie viele Commits Hermes zurückliegt. `autoupdate.sh` startet `POST /api/maintenance/hermes-update` und wartet bis zu 20 Minuten. Der Job: Sicherung → Dashboard stoppen → `hermes update --yes --no-gateway-restart` → `hermes doctor` → Dashboard-Oberfläche mit Basis `/hermes-ui/` bauen → `hermes-gateway` und `hermes-builtin-ui` neu starten → `hermes-postcheck.sh`. - Grün: Meldung. - Rot oder Zeitlimit: erst `self-repair.sh` (kommentiert eindeutige, nicht sicherheitsrelevante Config-Schlüssel aus, an denen die neue Version scheitert; der Gehirn-Check muss danach grün sein). - Hilft das nicht: Rückweg — `git reset --hard` auf den alten Commit in `~/.hermes/hermes-agent`, `config.yaml` und `.env` aus der letzten Sicherung, Neustart, Gehirn-Check. Grün: Hermes wird festgehalten, Meldung. Sonst „KRITISCH" (dringend). 5. **Wochenbericht** „Commander, die Wochenpflege der Box ist durch" mit einer Zeile je Baustein. 6. **Neustart**, wenn Ubuntu ihn verlangt (`/var/run/reboot-required`), nur sonntags 04:00–06:59; außerhalb gibt es nur eine Ankündigung. Vorher prüft das Skript: Linger an, keine laufenden Jobs, `mission-control-2`, `mc2-gateway` und `mc2-steward` im Autostart; sonst Meldung statt Neustart. `MC_AUTOUPDATE_REBOOT=0` schaltet den Neustart ab, `MC_AUTOUPDATE_REBOOT_JETZT=1` erzwingt ihn außerhalb des Fensters. Nachts landen alle Meldungen außer „KRITISCH" in der Morgenmeldung um 07:00. ## Prüfungen nach dem Update - **`stack-postcheck.sh`** (nach llama-swap, Motor und Betriebssystem): llama-swap aktiv; `/v1/models` antwortet (bis 120 s); das Hirn liefert eine echte Antwort (1 Token); das Embedding-Modell liefert Vektoren; MC2 meldet den Motor erreichbar; Gateway gesund; Steward aktiv. - **`hermes-postcheck.sh`** (nach Hermes): keine Config-Warnungen im Gateway-Log der letzten 3 Minuten; Werkzeug-Test durch den echten Agenten (`echo postcheck-ok`, bis 3 Versuche); Sprach-Test über `/api/voice/chat` (bis 3 Versuche); Browser-Werkzeug `agent-browser` lauffähig (einen toten Link setzt das Skript selbst neu). ## Festhalten und Freigeben - Rot mit grünem Rückweg ergibt einen Eintrag in `/srv/models/mc2-pins.json`: `{"": {"pinned": true, "version": …, "grund": …, "datum": …}}` mit den Bausteinen `swap`, `engine`, `hermes`. Künftige Sonntage überspringen ihn. - Der Wächter zeigt jeden festgehaltenen Baustein als gelben Hinweis „… bekommt keine Updates mehr" mit Knopf „Freigeben"; die Updates-Seite zeigt ihn ebenso. Freigeben löscht den Eintrag (`POST /api/updates/festgehalten/{baustein}/freigeben`); der nächste Sonntag versucht das Update erneut. - Warum sichtbar: Vom 06. bis 17.09. hielt die Box Motor und Hermes fest, ohne dass es jemand merkte, elf Tage ohne Updates. ## Von Hand - **Seite „Updates":** „Nach Neuem suchen" (`apt-get update`), je Baustein „Aktualisieren", „Alles jetzt aktualisieren" (mit Rückfrage). Es läuft immer nur ein Wartungs-Job; ein zweiter Klick startet kein zweites Update. - **„Alles jetzt aktualisieren"** kettet in einem Job, was ansteht: Motor → llama-swap → Hermes → Betriebssystem (`apt-get upgrade`, danach `stack-postcheck.sh`). Scheitert ein Teil, stoppt die Kette. - **Zeitlimits der Jobs:** Suche 15 min, Betriebssystem 90 min, Motor 60 min, llama-swap 30 min, Hermes 45 min, alles zusammen 3 h. „Abbrechen" beendet die ganze Prozessgruppe. - **Per SSH:** `bash ~/mission-control-v2/deploy/autoupdate.sh` (neu gestartet wird trotzdem nur im Wartungsfenster). - Kann eine Update-Prüfung nicht prüfen (Netz, API, apt), zeigt die Oberfläche „Prüfung unklar" statt „aktuell". Nach jedem Update prüft sie sofort neu. - Update-Jobs leben im MC2-Prozess; ein Neustart von MC2 bricht sie ab. Der Deploy wartet deshalb. ## Update-Verlauf `backend/services/update_verlauf.py` baut den Verlauf der Updates-Seite aus `~/mc2-notify.log`. Es liest die Zeilen `OK telegram`, `OK telegram direkt` (Zweitweg über die Bot-API), `QUEUED für Morgen-Digest` und `FALLBACK (…)`. Meldungen mit weniger als 45 Minuten Abstand gehören zu einem Lauf; die Morgenmeldung zählt nicht als eigener Lauf. Der Wortlaut der Meldungen von `autoupdate.sh` und der Protokolleinträge muss deshalb bleiben: Eine Umformulierung bricht den Verlauf ohne Fehlermeldung. ## Betriebssystem Sicherheitsupdates spielt `unattended-upgrades` ein. Wartet danach ein Kernel oder libc auf den Neustart, startet der Sonntagslauf die Box im Wartungsfenster neu. Weitere Pakete: Knopf „Aktualisieren" beim Baustein Betriebssystem. ## Fallen - llama.cpp hat `--no-mmap` gestrichen (seit b10936); die Config nutzt `--load-mode none`. Vor einem Engine-Sprung die Config-Zeilen mit dem neuen `llama-server` prüfen. - `hermes update` meldet Exit 1 trotz Erfolg, deshalb `--no-gateway-restart`. - Ein Timer mit `Persistent=true` holt verpasste Läufe beim Einschalten sofort nach (24.09.: Neustart um 14:51). - Der Updater läuft nicht mehr als Hermes-Cron (20.09.: Hermes startete sich beim eigenen Update neu). Einzelheiten: [wissen/FALLEN.md](wissen/FALLEN.md).