# Betriebs-Fallen — hart erarbeitet, nicht nochmal reintreten _Stand 24.09.2026. Jede Falle hat mindestens einmal real Zeit gekostet. Neue Fallen hier eintragen, mit Datum und Symptom; Erledigtes streichen (die Git-Historie behält es)._ ## Git und Deploy - **Timer mit `Persistent=true` holen verpasste Läufe beim ersten Einschalten sofort nach (24.09.).** `mc2-autoupdate.timer` war seit August aus; beim `enable --now` lief der Sonntagslauf an einem Donnerstag um 14:51 und startete die Box neu. Seitdem startet `autoupdate.sh` die Box nur So 04:00–06:59 neu, und `deploy.sh` startet den Timer nur, wenn er nicht schon läuft. - **Wer den llama-swap-Abzug im Repo ändert, überschreibt beim Deploy die lebende Config komplett (24.09.).** Was Oberfläche oder Radar seitdem eingetragen haben, ist dann weg (Sicherung: `/etc/llama-swap/config.yaml.bak-*`, die letzten 5). Vorher `diff /etc/llama-swap/config.yaml deploy/llama-swap.config.yaml` und den lebenden Stand ins Repo holen. `MC_DEPLOY_SKIP_SWAP_CONFIG=1` lässt die Config ganz in Ruhe. Bis 24.09. überschrieb jeder Deploy sie bei jeder Abweichung und startete den Motor neu. - **Aufträge überleben einen Neustart von MC2, aber keinen der Box (seit 24.09., Phase 2b).** Jeder Auftrag läuft als eigene systemd-Einheit `mc2-job-`. Ein Deploy wartet trotzdem, solange ein Update-Auftrag (Gruppe `maintenance`) läuft, weil der Skripte aus dem Checkout ausführt; Downloads laufen weiter (`MC_DEPLOY_TROTZDEM=1` erzwingt). Bis 24.09. waren es Kindprozesse von MC2, jeder Neustart brach sie ab. - **Am PC grün heißt nicht auf der Box grün (24.09.).** Ein Test mit Wettlauf lief unter Windows durch und scheiterte im Deploy-Prüftor auf der Box (der Rückweg griff). Vor dem Merge nach `main`: `bash deploy/probelauf-box.sh` lässt das Prüftor mit dem lokalen HEAD auf der Box laufen. - **`deploy.sh` schaltet alles in `AKTIV` wieder ein.** Wer einen Dienst oder Timer dauerhaft aus haben will, nimmt ihn dort heraus, sonst dreht der nächste Deploy den User-Entscheid zurück (mit `mc2-autoupdate` schon passiert). Schlafende Units (`box-console`, `voice-service`) stehen nur in `UNITS`. - **Den Box-Checkout nie von Hand ändern.** Stufe 1 holt `main` nur per fast-forward; geänderte oder eigene Commits im Checkout lassen den Deploy scheitern, bevor er etwas umstellt. - **Paralleler Git-Zugriff auf den geteilten Checkout am PC:** Mehrere Agenten arbeiten zeitweise im selben `F:\`-Verzeichnis, HEAD kann wandern. Änderungen sofort committen; zum Landen einen isolierten Worktree nutzen (`git worktree add --detach origin/main` → cherry-pick → `git push origin HEAD:main` → Worktree weg). - **Gitea-SSH: Benutzer `gitea`, nicht `git`, Port 2222 (21.08.).** Mit `git@` kommt nur `Permission denied (publickey)`, der Grund steht nur im Gitea-Log. Bei vielen Schlüsseln am PC `IdentitiesOnly yes` setzen, sonst bricht Gitea vorher ab. Bei Aussetzern: Push mit Retry. - **Repo-Name aus der Remote-URL, nicht aus dem Ordnernamen (21.08.):** lokal `mission-control-2`, auf Gitea `mission-control-v2` (`deploy/push-und-sync.ps1` liest die URL). - **CRLF:** `.gitattributes` erzwingt LF für `*.sh`, `*.service`, `*.timer` und `deploy/**/*.py`, sonst bricht bash an `pipefail\r`. Was per Pipe vom Windows-PC auf die Box geht: `sed 's/\r$//'`. - **Stale `index.lock`** im Box-Repo nach einem abgebrochenen Deploy: Alter prüfen, dann löschen. - **Veraltete Branches mit echtem Konflikt:** vor dem Merge `git rebase main`; kollidiert auch das, Branch verwerfen und neu aufsetzen. - **Untracked Dateien fehlen in `git diff`:** Wer Änderungen prüfen lässt, erst `git add -A`, dann `git diff --cached`. ## Box, systemd, llama-swap - **User-Units über SSH:** erst `export XDG_RUNTIME_DIR=/run/user/$(id -u)`, sonst sieht `systemctl --user` nichts. - **Ohne `exclusive: false` ist eine llama-swap-Gruppe exklusiv (24.09.).** Jede Anfrage ans Hirn entlud den Coder samt Prompt-Cache; OpenChamber rechnete danach den ganzen Vorlauf neu. - **Draft und Bild in einem `llama-server` ergeben HTTP 500 (04.09., bestätigt 24.09.):** „failed to process speculative batch", geprüft mit b11057 und b11157, auch mit `speculative.n_max=0` je Anfrage. Lösung: Bild-Zwillinge ohne Draft. - **llama-swap versteht nur `persistent:`**, `persist:` ignoriert es still (MC2 liest `persist`, deshalb stehen beide in der Config). `persistent` schützt nur vor Verdrängung, nicht vor dem ttl-Entladen: Warm-Mitglieder brauchen `ttl: 0`. Nach jedem Config-Reload ist alles entladen; der Steward wärmt das Hirn nach. - **`warmup.sh` liegt als Root-Kopie** unter `/usr/local/bin/llama-swap-warmup.sh`; `deploy.sh` aktualisiert sie nicht. Nach einer Änderung: `sudo install -m 0755 deploy/warmup.sh /usr/local/bin/llama-swap-warmup.sh`. - **llama-swap nie ohne Not neu starten:** Alle Modelle sind danach entladen, Lucy antwortet langsam. - **Nie zwei ~70-GB-Messungen direkt nacheinander** (OOM-Kill beim zweiten). - **llama.cpp streicht Flags ohne Vorwarnung (17.09.):** `--no-mmap` gibt es seit b10936 nicht mehr; jedes Modell stirbt 2 s nach dem Start, llama-swap meldet nur „upstream command exited prematurely". Ersatz: `--load-mode none`. Vor einem Engine-Sprung jede Config-Kommandozeile mit dem neuen `llama-server` parsen lassen (Port 5899, `timeout 6`, `${PORT}` ersetzen). - **Die Box ist deutschsprachig (de_DE):** Parser von CLI-Ausgaben brauchen `LC_ALL=C` (apt sagt sonst „aktualisierbar von:"). - **`pkill -f` über SSH trifft die eigene Remote-Shell** → Muster klammern (`'[g]en…'`). - **Wer einen Dienst schlafen legt, prüft alle Proben, die ihn abfragen (24.09.).** Nach dem Abschalten der Spracherkennung meldete die Kern-Probe des Wächters um 14:56 „Der Hör-Dienst antwortet nicht" samt Telegram (Fehlalarm). Die Probe läuft seitdem nur, wenn der Dienst nicht schläft. - **Einmal-Dienste hinter Timern fallen still aus (07.–23.09.):** `projekte-sync` scheiterte 16 Tage lang stündlich an einem leeren Gitea-Repo, niemand merkte es. Seit 23.09. meldet der Wächter gescheiterte Timer-Läufe. ## Hermes - **Ein Updater darf nicht als Kind von Hermes laufen (20.09.).** Der Hermes-Cron „Updates am Sonntag" startete beim Hermes-Update das eigene Gateway neu: 180 s Drain, dann Exit FAILURE. Seit 24.09. läuft das Update als eigener Timer. - **`hermes update` meldet Exit 1 trotz Erfolg (06. und 17.09.):** Nach dem eigenen Gateway-Neustart wartet es auf Zeilen des „Fleet version check", unter systemd kommen keine. Die Update-Kette brach ab, `autoupdate.sh` rollte zurück und hielt Hermes fest, obwohl der Gehirn-Check grün war. Deshalb `--no-gateway-restart`: Neustart und Urteil gehören dem Job. - **Festgehalten heißt still eingefroren (06.–17.09.):** Motor und Hermes bekamen elf Tage keine Updates. Seit 23.09. zeigt der Wächter jeden festgehaltenen Baustein als Hinweis mit Knopf „Freigeben". - **Werkzeugsätze haben zwei Ebenen:** aktiv ist, was nicht in `agent.disabled_toolsets` steht UND in `platform_toolsets.`. Cron-Jobs hatten bis 21.08. die volle Werkzeugkiste, weil `platform_toolsets.cron` fehlte (heute `[web, terminal]`). `hermes prompt-size` ist für die Allowlist blind; echte Kontrolle nur per Live-Aufruf. - **Wer einen Werkzeugsatz abschaltet, muss `SOUL.md` mitlesen (21.08.):** Dort standen noch Anweisungen, die auf abgeschaltete Werkzeuge zeigten. - **Cron-Fallen:** kein TZ-Feld (`next_run_at` = System-TZ beim Anlegen; nach einem TZ-Wechsel `hermes cron edit --schedule ""`); Prompt und Positionsargumente vor die Flags; `--script` allein reicht nicht (braucht Prompt oder Skill); Cron-Kontext hat `HERMES_CRON_SESSION=1`. `hermes cron edit "text"` speichert nichts, der Prompt muss über `--prompt` kommen (21.08.). - **`hermes` ist über SSH nicht im PATH** → `bash -lc 'hermes …'`. - **Hermes' `terminal`-Werkzeug bricht nach 30 s ab (22.08.):** Der Agent hielt den Aufruf für gescheitert und rief `news-melden.sh` ein zweites Mal auf, der Bericht kam doppelt. Das Skript kehrt deshalb sofort zurück und sperrt Doppelversand. - **Hermes' `write_file` überschreibt keine vorhandene Datei (23.09.):** Lag der Bericht vom Vortag noch in `/tmp`, scheiterte jeder Morgenlauf erst an „Refusing to overwrite". `news-melden.sh` räumt den Bericht jetzt weg. - **`web_extract` wertet kurze Seiten als Fehler (24.09.):** Hermes hängt an jedes Ergebnis ein leeres `"error"`-Feld und prüft nur die ersten 500 Zeichen. Der Wächter zählt mehrzeilige `"results"`-Treffer deshalb nicht als Werkzeugfehler. - **Lucys Stimme ist `lucy-stimme` auf `:8021`, nicht `voice-service` auf `:8650` (21.08.):** Dort sind nur Cloud-Stimmen geladen. - **Reasoning-Modelle:** `content` kommt nach `reasoning_content`; `max_tokens` großzügig setzen (für Werkzeug-Aufrufe ≥ 1500), sonst bleibt die Antwort leer. - **Hooks:** Die Zustimmung bleibt nur über einen CLI- oder Gateway-Start mit `HERMES_ACCEPT_HOOKS=1` erhalten; `hermes hooks test` schreibt die Allowlist nicht; eine Skript-Änderung macht die Zustimmung ungültig (mtime). - **Feed-Skripte: Pipe und Heredoc zugleich, dann gewinnt der Heredoc stdin** → JSON über eine Temp-Datei übergeben. Einen ehrlichen Ausfallpfad einbauen (API kaputt → „AUSGEFALLEN", nicht „0 Funde"). ## Windows-PC - **Git-Bash hat kein `python3` (Store-Alias, 24.09.):** `deploy/pruefen.sh` nimmt `backend/.venv/Scripts/python.exe`; `ruff` liegt global. - **`sed` mit `$` und `\n` über PowerShell zerlegt sich ohne Fehlermeldung (21.08.).** In einzelne Ersetzungen aufteilen und danach nachsehen. - **`Start-Process -ArgumentList` quotet nicht (PS 5.1):** Pfade mit Leerzeichen zerbrechen, die gestartete PowerShell stirbt still. Anführungszeichen ins Element einbetten: `'-File','"F:\Coding Stuff\…\skript.ps1"'`. - **`\"` in f-String-Ausdrücken ist seit Python 3.12 ein SyntaxError** (die Box hat 3.14). Werte vorher in Variablen ziehen. - **pythonw + subprocess ohne `CREATE_NO_WINDOW`:** Jedes gestartete Konsolenprogramm bekommt ein sichtbares Fenster. - **PC-Aufgabe `HermesPCExecutor`** (seit 24.09. aus) läuft aus dem Repo mit pythonw; nach einer Änderung an `executor.py` die Aufgabe neu starten. Logs in `%LOCALAPPDATA%\HermesPCExecutor\`. - **MSIX-Sandbox der Claude-Desktop-Werkzeuge:** Schreibzugriffe nach `AppData\Local\` landen in `AppData\Local\Packages\Claude_*\LocalCache\`. Windows-Apps nie über Agent-Werkzeuge installieren; den Installer startet der User per Doppelklick. ## Lucy (Desktop-App) - **file://-Fallen im Electron-Build:** Asset-Pfade relativ; `import()` verzeiht keine relativen Präfixe (`new URL("vad/", document.baseURI)`). - **Lucy immer über `Lucy-Neustart.bat` neu starten:** Hartes Beenden hinterlässt Waisen auf `:8130`. - `LUCY_WORKERS=2` (User-Env): 4 Worker bedeuten ~4 × 1,9 GB Kopien des Stimm-Modells. - Gerade `"` in Prompt-Strings von `config.ts` zerschießen den String → „…" nutzen. - Zustands-Features immer mit sichtbarem Zustand und Sofort-Feedback bauen: Der User testet nach Produkt-Gefühl. - **Training der Mini-Stimme (Colab):** Drive-Sync je Epoche; Notebook-Zellen vor Abgabe per `ast` prüfen; synthetische Datensätze per STT-Rundlauf prüfen (der XTTS-Datensatz war unbrauchbar); Kokoro-Ausgabe auf 0,95 normalisieren.