Files
mission-control-v2/docs/DISASTER_RECOVERY.md
T
Hitonabi 64efe18500 Docs: Komplett-Review 2026-07-02 (IST live verifiziert + Roadmap P0-P3) + Session-Docs
- REVIEW_2026-07-02.md: Latenz-Baseline (STT 2s dominant, LLM-TTFT 65ms), chat-Lane-Bug,
  SOLL-Recherche (Parakeet v3, Silero VAD v6, KV-Quant, MoE-Spec-Trap), Verdikte bestaetigt
- Audit-/TTS-/ZeroClaw-/DR-Docs von main nachgezogen; launch.json

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 10:30:12 +02:00

18 KiB
Raw Blame History

Konzept: Bare-Metal-Wiederaufbau + First-Run-Wizard (VOLLSTÄNDIG)

Zweck: Plan für den „hard crash"-Fall — die Box (tobisniceaiarbeitstier, Ubuntu 26.04, AMD Ryzen AI MAX+ 395 / gfx1151, 122 GB RAM) muss von null wiederherstellbar sein. Anspruch: ALLES ist erfasst — Engine, Hermes-Konfig 1:1, 3D-Avatare, Voice/Klonstimme, Memory, Browser, MCP, Skills, Secrets. Pro Komponente entscheidet der Nutzer im Wizard: 1:1 zurück · neu/Default · weglassen.

Dieses Dokument ist die Spezifikation für eine künftige Implementierungs-Session — es baut noch nichts. Stand: 2026-06-28.


1. Leitprinzip: 1:1 ODER modular — der Nutzer wählt

Der Wizard behandelt jede Komponente als eigene Kachel mit drei Modi:

Modus Bedeutung
📦 1:1 aus Backup Exakter alter Zustand wird zurückgespielt (Configs, Daten, Klonstimme, Avatare).
🆕 Neu / Default Frische Installation mit sinnvollen Defaults (z.B. entfesseltes Hermes-Profil, Default-Avatar).
⏭️ Weglassen Komponente wird (vorerst) nicht installiert.

Ein „Alles 1:1"-Knopf wählt überall 📦 (wo ein Backup existiert), sonst 🆕. So bekommt der Nutzer entweder den exakten alten Stand oder kann gezielt entrümpeln.


2. Was es schon gibt (wiederverwenden)

Asset Datei Deckt ab
Code-Deploy deploy/deploy.sh git pull + venvs + Units + Restart. Setzt Engine/llama-swap/Dirs/venvs voraus.
Zustands-Backup deploy/backup.sh + mc2-backup.{service,timer} Aktuell (live): mem0, ~/.hermes/{config.yaml,.env,plugins}, llama-swap-config. Retention 14. Für echtes 1:1 zu erweitern — fertiges Snippet in Anhang B (§5).
Restore deploy/restore.sh Spielt Tarball zurück (mit Pre-Restore-Sicherung).
Engine deploy/provision-engine.sh llama.cpp Vulkan/RADV-Build (root).
Voice-Setup voice_service/install.sh venv + Piper-Binary + dt. Piper-Stimmen + Chatterbox (best-effort).
Updates deploy/update-engine.sh, update-swap.sh Laufende Engine/Router-Updates.
Postchecks deploy/stack-postcheck.sh, hermes-postcheck.sh Funktionsprüfung → Wizard-Verifikationsschritt.

3. VOLLSTÄNDIGER Komponenten-Katalog

Scan-verifiziert (2026-06-28) gegen backend/config.py, alle backend/services/* & routers/*, frontend/src/{nav.ts,views,components/voice}, voice_service/app.py, mem0_service/, deploy/*. Alle persistenten Schreibpfade, Dienste, Secrets und Env-Vars sind unten erfasst.

Legende Restore-Quelle: 📦 = aus Backup-Tarball · ⬇️ = Re-Download/Install (Skript) · 🌐 = Git · 🔑 = Secret (Nutzer/Generieren) · 🆕 = im Wizard neu gewählt. „Im Backup?" = deckt der aktuelle backup.sh es ab.

A · OS & System (L0, root/sudo, einmalig)

Komponente Ort Quelle Im Backup?
Ubuntu 26.04, User hitonabi, enable-linger ⬇️ manuell n/a
System-Pakete: python3.14+venv, git, curl, jq, ttyd, uv ⬇️ apt/curl nein
Vulkan-Stack: mesa-vulkan-drivers, libvulkan1, vulkan-tools ⬇️ apt nein
Chrome-Libs (Browser): agent-browser install --with-deps ⬇️ apt nein
Verzeichnis-Layout: /srv/models/{,mem0,mc2-backups,drafts}, /etc/llama-swap/ ⬇️ mkdir+chown nein

B · Inferenz-Engine + Router (L1, root)

Komponente Ort Quelle Im Backup?
llama.cpp (Vulkan) → llama-server /opt/llamacpp-vulkan, /usr/local/bin/llama-server ⬇️ provision-engine.sh / update-engine.sh (ggml-org Release) nein (re-build)
llama-swap Binary (Router :8080) /usr/local/bin/llama-swap ⬇️ bekannt: mostlygeek/llama-swap-Release (Rezept in update-swap.sh) nein (re-download)
llama-swap systemd-System-Unit /etc/systemd/system/llama-swap.service (+ .d/ Drop-ins) ⬇️ Bootstrap legt sie an — kompletter Unit-Inhalt in Anhang A (von der Box abgegriffen; Drop-ins via provision-engine.sh) nein
llama-swap-Config (Modelle/Rollen) /etc/llama-swap/config.yaml 📦 ja
Draft-Modelle (Spec-Decoding) /srv/models/drafts/ ⬇️ Re-Download nein

C · MC2-App (L2, userspace)

Komponente Ort Quelle Im Backup?
MC2-Code ~/mission-control-v2 🌐 Git (Gitea) n/a
Backend-venv (Python 3.14) backend/.venv ⬇️ deploy.sh nein (rebuild)
Frontend (gebaut, inkl. 3D-Avatar avatar.vrm) frontend/dist, frontend/public/avatar.vrm 🌐 Git n/a
systemd-User-Dienst mission-control-2 (:9001) ~/.config/systemd/user/ ⬇️ deploy.sh nein

D · 3D-Avatar (Sprechen-Tab)

Komponente Ort Quelle Im Backup?
Default-Avatar (VRM) frontend/public/avatar.vrm (→ dist) 🌐 Git n/a
Renderer frontend/src/components/voice/Avatar3D.tsx 🌐 Git n/a
Eigene/zusätzliche Avatare (falls Nutzer welche ablegt) TODO: Ablageort definieren (z.B. /srv/models/avatars/ + DB-Verweis) 📦/🆕 nein (Lücke)

Heute ist der Avatar fest (avatar.vrm, kommt mit dem Git-Frontend zurück). Wenn künftig Nutzer-Avatare hochgeladen werden, brauchen sie einen persistenten Ablageort, der ins Backup geht.

E · Voice-Sidecar (STT + TTS + Klonstimme)

Komponente Ort Quelle Im Backup?
Voice-venv (Python 3.12) ~/.voice/venv ⬇️ install.sh nein (rebuild)
STT (faster-whisper Modell) ~/.voice/ (Cache) ⬇️ install.sh / 1. Start nein
Piper-Binary + dt. Stimmen (thorsten/kerstin) ~/.voice/piper, ~/.voice/voices ⬇️ install.sh nein
Chatterbox (Premium-TTS, CPU-torch) venv ⬇️ install.sh (best-effort) nein
Klonstimme / Voice-Referenz-Audio (Nutzer) ~/.voice/refs/ref.wav (VOICE_REFS_DIR, /api/voice/reference) 📦 nein → Anhang B
ElevenLabs-Key ~/.hermes/.env 🔑 ja
Stimm-/Lautstärke-Wahl Browser-localStorage (pro Gerät) 🆕 client n/a
Dienst voice-service (:8650) systemd-User ⬇️ deploy.sh nein

F · Mem0 (Langzeitgedächtnis)

Komponente Ort Quelle Im Backup?
Mem0-venv (Python 3.12, uv) ~/.mem0/venv ⬇️ deploy.sh nein (rebuild)
Gedächtnis-Daten (Chroma + history.db) /srv/models/mem0/ 📦 ja
Hermes-Memory-Plugin ~/.hermes/plugins/mc2-memory/ 📦/🌐 ja
Dienst mem0-service (:8765) systemd-User ⬇️ deploy.sh nein

G · Hermes-Agent (das Herz)

Komponente Ort Quelle Im Backup?
Hermes-Code ~/.hermes/hermes-agent 🌐 Git (NousResearch) nein (re-clone)
Bundled Node v22 ~/.hermes/node/bin ⬇️ (kommt mit Hermes) nein
Hermes-venv ~/.hermes/hermes-agent/venv ⬇️ rebuild nein
config.yaml 1:1 (Toolsets, MCP, Engine, Browser, Personalities, alles) ~/.hermes/config.yaml 📦 ja
.env (Secrets: TELEGRAM_BOT_TOKEN, API_SERVER_KEY, ElevenLabs …) ~/.hermes/.env 📦/🔑 ja
Plugins ~/.hermes/plugins/ 📦 ja
Skills (eigene) ~/.hermes/skills/ (45M; .hub-Cache re-downloadbar) 📦 nein → Anhang B (ohne .hub)
Sessions/History (optional) ~/.hermes/sessions/ (856K) 📦 nein → Anhang B
Checkpoints (optional) ~/.hermes/checkpoints/ (existiert nicht) ⏭️ skip nein
Token-/Ersparnis-Statistik ~/.hermes/token_stats.json 📦 nein → Anhang B
Dienst hermes-gateway (:8642) systemd-User ⬇️ nein
Hermes-Terminal (ttyd → hermes chat, :7681) systemd-User hermes-terminal ⬇️ deploy.sh (+ttyd apt) nein

H · MCP-Server (4)

Komponente Ort Quelle Im Backup?
mission-control-memory, -stack (MC2-venv) ~/mission-control-v2/mcp/*.py 🌐 Git über config.yaml
hermes-pc-control, hermes-web-fetch (Hermes-venv) dito 🌐 Git über config.yaml
MCP-Verdrahtung ~/.hermes/config.yaml → mcp_servers 📦 ja

I · Browser-Stack

Komponente Ort Quelle Im Backup?
agent-browser (npm global) ~/.local/..., symlink ~/.hermes/node/bin ⬇️ npm i -g nein
Chrome (engine) + System-Libs ~/.agent-browser/browsers/ + apt-Libs ⬇️ install --with-deps nein
lightpanda (optional, leicht) ~/.local/bin/lightpanda ⬇️ Download nein
Browser-Verdrahtung (engine=chrome, toolset) ~/.hermes/config.yaml 📦 ja

J · Modelle (GGUF — der große Brocken)

Komponente Ort Quelle Im Backup?
GGUF-Modelle (Brain, fast, heavy, coder, vision, embedding …) /srv/models/ ⬇️ Re-Download aus llama-swap-Manifest nein (zu groß, bewusst)

K · Extern (anderer Rechner)

Komponente Ort Quelle Im Backup?
PC-Executor (Windows) client/hermes-pc/ → Scheduled Task 🌐 Git + Task n/a (anderer Host)
Hermes-WebUI (nesquena, optional, :8787) ~/hermes-webui ⬇️ git clone nein

4. Ziel-Architektur

4.1 deploy/bootstrap.sh — orchestrierter From-Zero-Lauf

  • Idempotent & resumierbar (Schritt-Marker in ~/.mc2-bootstrap.state).
  • Getrennt nach sudo-Bedarf: bootstrap-root.sh (L0+L1, bewusst mit sudo) + bootstrap.sh (L2+, sudo-frei = Kern ist deploy.sh). Passt zum Nordstern „Runtime ohne sudo".
  • Mündet in den Wizard: startet MC2 im First-Run-Modus, gibt Wizard-URL aus.

Phasen: 0 Vorflug → 1[sudo] System+Dirs → 2[sudo] Engine+llama-swap → 3 Code(MC2+Hermes+Node) → 4 venvs(backend/mem0/voice/hermes) → 5 Browser → 6 deploy.sh(Units/enable/restart) → 7 Restore(optional) → 8 Wizard hoch + postcheck.

4.2 First-Run-Wizard (browserbasiert, von MC2 serviert)

MC2 erkennt unkonfigurierten Zustand → Frontend-Route /setup statt Dashboard. Schritte:

  1. Systemcheck — Live-Ampel je Komponente aus §3 (GET /api/setup/status + …/system/services).
  2. Restore-Quelle wählen — Backup-Tarball erkennen → globaler Modus „Alles 1:1" / „selektiv" / „frisch".
  3. Komponenten-Auswahl (Kernstück) — pro Katalog-Eintrag aus §3 eine Kachel mit 📦/🆕/⏭️ (siehe §1). Zeigt Größe + ob Backup-Daten vorhanden.
  4. Netzwerk & Identität — Box-IP (→ HERMES_TERMINAL_URL, PC_EXECUTOR_URL), Hostname.
  5. Secrets 🔑TELEGRAM_BOT_TOKEN, erlaubte User-ID, API_SERVER_KEY (oder generieren), ElevenLabs-Key → ~/.hermes/.env (chmod 600). Bei 📦 vorbefüllt aus Backup.
  6. Hermes-Profil — Brain-Alias + Toolset-Profil (Default = entfesselt: vision/tts/memory/browser an, image_gen/video aus — siehe project-hermes-setup). Bei 📦 = exakte alte config.yaml.
  7. Avatar & Voice — Avatar wählen (Default-VRM oder eigener), Stimme/Klonstimme (📦 Referenz-Audio zurück, oder neu aufnehmen/hochladen).
  8. Modelle — aus llama-swap-Manifest automatisch nachladen (POST /api/models/install, Fortschritt GET /api/jobs) ODER geführte Discover-Neuauswahl. Reihenfolge: Brain → heavy → Rest.
  9. Externe Checkliste — PC-Executor (Windows-Task), Hermes-WebUI als Haken.
  10. Verifikation & Abschlussstack-postcheck.sh + hermes-postcheck.sh → grün/rot-Liste → Dashboard.

Technik: neuer Router backend/routers/setup.py (GET /api/setup/status, POST /api/setup/{secrets,network,hermes,components,finish}). First-Run-Gate: MC2 prüft beim Boot Marker ~/.mc2-setup-done bzw. Pflicht-Secrets → leitet auf /setup.


5. Backup-Scope für echtes 1:1 ERWEITERN (umzusetzen — Snippet in Anhang B)

Der aktuelle backup.sh (live auf der Box, unverändert) reicht für „1:1" nicht. Für die Bau-Session liegt das fertige Erweiterungs-Snippet in Anhang B — es ergänzt den Tarball um:

  • Voice-Klonstimme~/.voice/refs/ (ref.wav)
  • Token-/Ersparnis-Statistik~/.hermes/token_stats.json
  • Hermes-Skills~/.hermes/skills/ (re-downloadbarer .hub-Cache per tar --exclude ausgelassen)
  • Hermes-Sessions/History~/.hermes/sessions/

Restore soll skills/sessions mergen (frisch geladenen .hub nicht überschreiben) und voice-service mit neu starten.

Offen bleibt: eigene Avatare (sobald Upload existiert — Ablageort heute undefiniert, siehe §3·D).

Bewusst NICHT im Backup (re-downloadbar/rebuildbar): Piper-Stimmen (install.sh), .hub-Skill-Cache, /srv/models/mc2-discover.json (Cache), /srv/models/mc2-memory.db (Legacy-Migration), alle venvs, GGUF-Modelle.

→ Aufgabe der Bau-Session: backup.sh + restore.sh um diese Pfade erweitern (mit klarer „opt-in für große/optionale Teile"-Logik), und den MANIFEST-Inhalt entsprechend.


6. Secrets-Strategie

  • Single Source: ~/.hermes/.env (chmod 600), im Tarball (selbst 600).
  • Rebuild ohne Backup → Wizard-Schritt 5 erzeugt sie. API_SERVER_KEY generierbar; Telegram/ElevenLabs liefert Nutzer.
  • Nie ins Git, nie in Logs, nie in die MC2-DB. Off-Box-Spiegelung des Tarballs noch offen (mc2-backup-restore).

7. Modell-Strategie

  • A (empfohlen): /etc/llama-swap/config.yaml (im Backup) listet alle Modelle → Wizard leitet Repos/Quants ab und lädt automatisch (/api/models/install). „Ein Klick, lädt über Nacht."
  • B: geführte Discover-Neuauswahl je Rolle. Reihenfolge Brain → heavy → Rest, danach warmup.sh.

8. Implementierungs-Reihenfolge (neue Session)

  1. Box-Verifikation erledigt (2026-06-28, nur gelesen — nichts verändert): llama-swap.service-Inhalt in Anhang A; skills/sessions/refs/token_stats existieren (Pfade in §3 verifiziert); Backup-Erweiterung als fertiges Snippet in Anhang B. Keine offenen Box-Fragen mehr außer §10·36. → mit Schritt 2 starten.
  2. backup.sh/restore.sh um die 1:1-Lücken erweitern (§5).
  3. deploy/bootstrap.sh + bootstrap-root.sh (Phasen, State-Marker); llama-swap-Install skripten.
  4. backend/routers/setup.py + First-Run-Gate.
  5. Frontend /setup-Wizard (Schritte 110), Komponenten-Auswahl als Kernstück; bestehende Views (Cockpit/AgentView/Sprechen) wiederverwenden.
  6. Modell-Restore-aus-Manifest.
  7. Abnahme in frischer VM (§9).

Vorschlag: 24 zuerst (Skelett lauffähig), Wizard danach. Branch + PR.

9. Abnahmekriterien

  • Frisches Ubuntu 26.04 → bootstrap-root.sh + bootstrap.sh → laufender Stack, kein Spezialwissen.
  • Postchecks grün; Telegram, Voice (inkl. Klonstimme bei 📦), 3D-Avatar, Browser funktionieren.
  • „Alles 1:1" stellt mem0, Hermes-config.yaml, Secrets, Klonstimme, Skills exakt wieder her.
  • Selektiver Modus: einzelne Komponenten ⏭️ überspringbar, Stack läuft trotzdem.
  • Idempotenz: zweiter Lauf = No-op.

10. Offene Entscheidungen (vor dem Bau)

  1. llama-swap systemd-Unit-Inhaltgeklärt: kompletter Unit in Anhang A (in der Bau-Session anlegen).
  2. Voice-Referenz-Audio-Ortgeklärt: ~/.voice/refs/ (Backup-Snippet in Anhang B, in der Bau-Session umsetzen).
  3. Eigene Avatare: künftiger Upload-/Ablage-Mechanismus + Backup-Pfad (einziger offener 1:1-Daten-Punkt).
  4. Off-Box-Backup-Ziel (NAS/2. Platte/Cloud) — mc2-backup-restore.
  5. Python 3.14 auf frischem Ubuntu beschaffen (deadsnakes?).
  6. Bootstrap-sudo-Modell: getrenntes bootstrap-root.sh (empfohlen) vs. interaktives sudo.

11. Referenzen


Anhang A — llama-swap.service (1:1 von der Box abgegriffen, 2026-06-28)

Base-Unit nach /etc/systemd/system/llama-swap.service (root). User/GFX sind boxspezifisch (hitonabi, gfx1151 → HSA 11.5.1) — auf anderer Hardware anpassen. Die .d/-Drop-ins (vulkan.conf, warmup.conf) legt provision-engine.sh an.

[Unit]
Description=llama-swap (lokaler LLM Router)
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=hitonabi
Environment=HSA_OVERRIDE_GFX_VERSION=11.5.1
Environment=PATH=/usr/local/bin:/usr/bin:/bin
ExecStart=/usr/local/bin/llama-swap --config /etc/llama-swap/config.yaml --listen 0.0.0.0:8080 --watch-config
Restart=on-failure
RestartSec=3

[Install]
WantedBy=multi-user.target
# /etc/systemd/system/llama-swap.service.d/vulkan.conf
[Service]
Environment=LD_LIBRARY_PATH=/opt/llamacpp-vulkan
# /etc/systemd/system/llama-swap.service.d/warmup.conf
[Service]
ExecStartPost=-/usr/local/bin/llama-swap-warmup.sh

Erstinstall-Reihenfolge: bash deploy/update-swap.sh (Binary) → Unit kopieren → sudo bash deploy/provision-engine.sh (Engine+Drop-ins) → sudo systemctl enable --now llama-swap.


Anhang B — Backup-Scope-Erweiterung für echtes 1:1 (fertiges Snippet)

In deploy/backup.sh ergänzen (Variablen oben: VOICE="${VOICE_HOME:-$HOME/.voice}", Stage zusätzlich "$STAGE/voice"):

# 1:1-Erweiterung (scan-verifiziert 2026-06-28):
[ -f "$HERMES/token_stats.json" ] && cp -a "$HERMES/token_stats.json" "$STAGE/hermes/" || true
[ -d "$HERMES/skills" ]           && cp -a "$HERMES/skills" "$STAGE/hermes/skills"   || true
[ -d "$HERMES/sessions" ]         && cp -a "$HERMES/sessions" "$STAGE/hermes/sessions" || true
[ -d "$VOICE/refs" ]              && cp -a "$VOICE/refs" "$STAGE/voice/refs"         || true

tar-Aufruf um den re-downloadbaren Skill-Cache erleichtern:

tar --exclude='./hermes/skills/.hub' -czf "$OUT" -C "$STAGE" .

In deploy/restore.sh spiegelbildlich (skills/sessions mergen, nicht ersetzen) und voice-service mit neustarten:

VOICE="${VOICE_HOME:-$HOME/.voice}"
SERVICES="mem0-service voice-service mission-control-2 hermes-gateway"
[ -f "$STAGE/hermes/token_stats.json" ] && cp -a "$STAGE/hermes/token_stats.json" "$HERMES/"
[ -d "$STAGE/hermes/skills" ]   && { mkdir -p "$HERMES/skills";   cp -a "$STAGE/hermes/skills/." "$HERMES/skills/"; }
[ -d "$STAGE/hermes/sessions" ] && { mkdir -p "$HERMES/sessions"; cp -a "$STAGE/hermes/sessions/." "$HERMES/sessions/"; }
[ -d "$STAGE/voice/refs" ]      && { mkdir -p "$VOICE/refs";      cp -a "$STAGE/voice/refs/." "$VOICE/refs/"; }