5a236b4b28
Fallstrick #2: Worker koennen in die falsche Ebene wandern - Patches im Live-Checkout ~/mission-control-v2 ablegen oder die Hermes-Quelle ~/.hermes/hermes-agent anfassen. Hermes' native is_write_denied deckt diese Pfade NICHT ab (nur Credentials/System, live geprueft). deploy/agent-hooks/tabu-pfade-guard.py (neu): pre_tool_call-Hook, blockt Schreib-Operationen (write_file/patch + terminal git-write/sed-i/redirect/rm) auf den home-verankerten Live-Checkout und die Hermes-Quelle - NUR fuer echte Kanban-Worker (task_id t_<hex>); Lucy/CLI (UUID) = No-op (~15 ms). Der Workspace-KLON (<workspace>/mission-control-v2) bleibt beschreibbar (nur der home-verankerte Pfad ist tabu) -> legitime Worker-Arbeit ungestoert. Lesen erlaubt. 25 Faelle gruen (Block + Allow, inkl. git log 2>/dev/null, Redirect nach /tmp, Workspace-Commit). deploy.sh synct den Hook (cmp-Guard). Registrierung in ~/.hermes/config.yaml (pre_tool_call) einmalig von Hand. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
194 lines
14 KiB
Bash
194 lines
14 KiB
Bash
#!/usr/bin/env bash
|
|
# Deploy AUF DER BOX als systemd-USER-Dienst — KEIN sudo, KEIN /opt, KEIN Passwort.
|
|
# Erstinstallation + Updates in einem. Läuft als User hitonabi.
|
|
#
|
|
# Erstinstallation (einmalig):
|
|
# git clone https://git.tobisniceshomelab.ddnsfree.com/Hitonabi/mission-control-v2 ~/mission-control-v2
|
|
# bash ~/mission-control-v2/deploy/deploy.sh
|
|
set -euo pipefail
|
|
|
|
SRC="${MC2_SRC:-$HOME/mission-control-v2}"
|
|
|
|
cd "$SRC"
|
|
git fetch -q origin && git reset -q --hard origin/main
|
|
|
|
# venv + Abhängigkeiten
|
|
if [ ! -d "$SRC/backend/.venv" ]; then
|
|
python3 -m venv "$SRC/backend/.venv"
|
|
fi
|
|
"$SRC/backend/.venv/bin/python" -m pip install -q --upgrade pip
|
|
"$SRC/backend/.venv/bin/python" -m pip install -q -r "$SRC/backend/requirements.txt"
|
|
|
|
# Mem0-Sidecar (auto-lernendes Gedächtnis) — eigenes Python-3.12-venv (~/.mem0/venv),
|
|
# weil mem0+chromadb unter dem 3.14-Backend-venv nicht laufen. mem0ai/chromadb sind dort
|
|
# bereits installiert; hier nur den HTTP-Server nachziehen + Alt-DB einmalig migrieren.
|
|
if [ -x "$HOME/.mem0/venv/bin/python" ]; then
|
|
# ~/.mem0/venv ist uv-managed (kein pip) → uv pip nutzen.
|
|
UV="$(command -v uv || echo "$HOME/.local/bin/uv")"
|
|
"$UV" pip install -q --python "$HOME/.mem0/venv/bin/python" -r "$SRC/mem0_service/requirements.txt"
|
|
( cd "$SRC/mem0_service" && "$HOME/.mem0/venv/bin/python" migrate.py ) || true
|
|
else
|
|
echo "WARN: ~/.mem0/venv fehlt — Mem0-Sidecar wird nicht gestartet (siehe Plan A1)."
|
|
fi
|
|
|
|
# Voice-Sidecar (lokales STT + gestuftes TTS für „Mit Hermes reden") — eigenes Python-3.12-venv
|
|
# (~/.voice/venv), weil torch/chatterbox/faster-whisper nicht ins 3.14-Backend-venv passen.
|
|
# install.sh ist idempotent (venv + Deps + Piper-Stimmen). Best-effort: schlägt es fehl, läuft
|
|
# der restliche Stack weiter (der Voice-Tab meldet den Sidecar dann als offline).
|
|
bash "$SRC/voice_service/install.sh" || echo "WARN: Voice-Sidecar-Setup fehlgeschlagen — Voice-Tab bleibt offline."
|
|
|
|
# Hermes-Memory-Provider-Plugin (auto-lernen/Recall via Mem0-Sidecar) nach ~/.hermes/plugins/
|
|
# spiegeln. Context-only (kein Tool-Loop). Aktivierung in ~/.hermes/config.yaml:
|
|
# memory.memory_enabled: true + memory.provider: mc2-memory (einmalig, box-lokal).
|
|
if [ -d "$HOME/.hermes" ]; then
|
|
mkdir -p "$HOME/.hermes/plugins/mc2-memory"
|
|
cp "$SRC/hermes/plugins/mc2-memory/__init__.py" "$SRC/hermes/plugins/mc2-memory/plugin.yaml" \
|
|
"$HOME/.hermes/plugins/mc2-memory/"
|
|
fi
|
|
|
|
# systemd-USER-Units installieren/aktualisieren
|
|
mkdir -p "$HOME/.config/systemd/user"
|
|
cp "$SRC/deploy/mission-control-2.service" "$HOME/.config/systemd/user/mission-control-2.service"
|
|
# MC2-Diät (Hermes Desktop, 07/2026): das Hermes-Terminal-ttyd (:7681) und das standalone
|
|
# hermes-webui (nesquena, Karteileiche seit dem Built-in-UI-Umbau) sind entfallen — die
|
|
# Agent-Oberfläche ist die Desktop-App bzw. /hermes-ui/. Einmalige, idempotente Stilllegung:
|
|
systemctl --user disable --now hermes-terminal 2>/dev/null || true
|
|
systemctl --user disable --now hermes-webui 2>/dev/null || true
|
|
rm -f "$HOME/.config/systemd/user/hermes-terminal.service" "$HOME/.config/systemd/user/hermes-webui.service"
|
|
# Box-Konsole (ttyd -> Login-Shell auf :7682), in MC2 als Konsole-Seite eingebettet.
|
|
cp "$SRC/deploy/box-console.service" "$HOME/.config/systemd/user/box-console.service"
|
|
# Mem0-Sidecar-Unit (nur wenn das venv existiert).
|
|
[ -x "$HOME/.mem0/venv/bin/python" ] && cp "$SRC/deploy/mem0-service.service" "$HOME/.config/systemd/user/mem0-service.service"
|
|
# Voice-Sidecar-Unit (nur wenn das venv existiert).
|
|
[ -x "$HOME/.voice/venv/bin/python" ] && cp "$SRC/deploy/voice-service.service" "$HOME/.config/systemd/user/voice-service.service"
|
|
# Tägliches Zustands-Backup (mem0 + Configs/Secrets) — Timer + oneshot-Service. Siehe docs/BACKUP.md.
|
|
cp "$SRC/deploy/mc2-backup.service" "$HOME/.config/systemd/user/mc2-backup.service"
|
|
cp "$SRC/deploy/mc2-backup.timer" "$HOME/.config/systemd/user/mc2-backup.timer"
|
|
# Wöchentliches Auto-Update (Router/Engine/Hermes, Rollback+Pin+Telegram) — Autonomie E2.
|
|
cp "$SRC/deploy/mc2-autoupdate.service" "$HOME/.config/systemd/user/mc2-autoupdate.service"
|
|
cp "$SRC/deploy/mc2-autoupdate.timer" "$HOME/.config/systemd/user/mc2-autoupdate.timer"
|
|
# Tägliche Selbst-Smoke-Tests (Gateway/Tools/Voice aktiv, Alarm bei Rot) — Autonomie 0d.
|
|
cp "$SRC/deploy/mc2-selfsmoke.service" "$HOME/.config/systemd/user/mc2-selfsmoke.service"
|
|
cp "$SRC/deploy/mc2-selfsmoke.timer" "$HOME/.config/systemd/user/mc2-selfsmoke.timer"
|
|
# Bagatell-Annahme (Ideen-Queue, 10.07.2026): reine Doku-Vorschläge nachts ohne Klick einspielen.
|
|
cp "$SRC/deploy/mc2-bagatell.service" "$HOME/.config/systemd/user/mc2-bagatell.service"
|
|
cp "$SRC/deploy/mc2-bagatell.timer" "$HOME/.config/systemd/user/mc2-bagatell.timer"
|
|
# Evolution-Radar-Feed (Autonomie E4): Hermes-cron speist ihn als Prompt ein.
|
|
# Cron-Job selbst wird EINMALIG registriert (hermes cron create, siehe docs/RUNBOOK.md).
|
|
mkdir -p "$HOME/.hermes/scripts"
|
|
cp "$SRC/deploy/radar-feed.sh" "$HOME/.hermes/scripts/radar-feed.sh"
|
|
# Selbstkritik-Cron (Faden 11b): Zwilling des Radars, Blick nach INNEN (Latenzen/Journal/Skills).
|
|
cp "$SRC/deploy/selbstkritik-feed.sh" "$HOME/.hermes/scripts/selbstkritik-feed.sh"
|
|
# Monats-Review-Wrapper (Cron 1. d. M. 09:00): Radar + Selbstkritik in EINEM Lauf.
|
|
cp "$SRC/deploy/radar-selbstkritik-wrapper.sh" "$HOME/.hermes/scripts/radar-selbstkritik-wrapper.sh"
|
|
# Traum-Cron (Dreaming, Phase 2): Blick auf das GELERNTE → Wissens-Vault. Bootstrappt ~/wissens-vault.
|
|
cp "$SRC/deploy/dreaming-feed.sh" "$HOME/.hermes/scripts/dreaming-feed.sh"
|
|
# Fremdblick-Helfer: Ein-Schuss-Zweitmeinung von einem anderen Modell (umgeht 64K-Delegations-Floor).
|
|
cp "$SRC/deploy/fremdblick.sh" "$HOME/.hermes/scripts/fremdblick.sh"
|
|
# Worker-Helfer (Orchestrator): Ein-Schuss-Arbeitsauftrag an ein Worker-Modell (Gegenstück zu fremdblick).
|
|
cp "$SRC/deploy/worker.sh" "$HOME/.hermes/scripts/worker.sh"
|
|
# Chef-Gutachter-Cron (Orchestrator-Finale): gpt-oss urteilt nachts über die autonome Arbeit.
|
|
cp "$SRC/deploy/chef-gutachter-feed.sh" "$HOME/.hermes/scripts/chef-gutachter-feed.sh"
|
|
# Release-Radar-Cron (10.07.2026): hält neue hermes-agent-Releases wöchentlich gegen die
|
|
# Eigenbau-Landkarte im Wissens-Vault ("mehr Hermes nativ, weniger Eigenkreationen").
|
|
cp "$SRC/deploy/hermes-release-radar-feed.sh" "$HOME/.hermes/scripts/hermes-release-radar-feed.sh"
|
|
# Idle-Radar (S4 "Zuendung", 12.07.2026): die Box gibt sich nachts selbst Arbeit —
|
|
# Journal-Fehlermuster + Traum-Funde -> belegte rohe Ideen (triage) im nativen Kanban.
|
|
cp "$SRC/deploy/idle-radar-feed.sh" "$HOME/.hermes/scripts/idle-radar-feed.sh"
|
|
# "Lucy kennt sich" (12.07.2026): Selbst-Inventur generiert den Steckbrief + bemerkt
|
|
# eigene Aenderungen; der Karten-Gutachter stempelt jede Karte mit einer Empfehlung.
|
|
cp "$SRC/deploy/selbst-inventur.sh" "$HOME/.hermes/scripts/selbst-inventur.sh"
|
|
cp "$SRC/deploy/karten-gutachter.sh" "$HOME/.hermes/scripts/karten-gutachter.sh"
|
|
# Werkstatt-Kanban-Profil (Ideen-Queue, 10.07.2026): Leitplanken des Worker-Profils nachziehen
|
|
# (Profil selbst wurde einmalig per `hermes profile create werkstatt --clone` angelegt).
|
|
[ -d "$HOME/.hermes/profiles/werkstatt" ] && cp "$SRC/deploy/werkstatt-SOUL.md" "$HOME/.hermes/profiles/werkstatt/SOUL.md"
|
|
# betrieb-Profil (Ideen-Queue Faden 7, 13.07.2026): Ops-/Mess-/Bench-Worker mit Box-Wissen
|
|
# statt Lucy-default. Profil selbst wird einmalig per `hermes profile create betrieb
|
|
# --clone-from werkstatt` angelegt (model coder→hermes, Description fürs Specifier-Routing).
|
|
[ -d "$HOME/.hermes/profiles/betrieb" ] && cp "$SRC/deploy/betrieb-SOUL.md" "$HOME/.hermes/profiles/betrieb/SOUL.md"
|
|
chmod +x "$HOME/.hermes/scripts/fremdblick.sh" "$HOME/.hermes/scripts/dreaming-feed.sh" "$HOME/.hermes/scripts/worker.sh" "$HOME/.hermes/scripts/chef-gutachter-feed.sh" "$HOME/.hermes/scripts/hermes-release-radar-feed.sh" "$HOME/.hermes/scripts/radar-selbstkritik-wrapper.sh" "$HOME/.hermes/scripts/idle-radar-feed.sh" "$HOME/.hermes/scripts/selbst-inventur.sh" "$HOME/.hermes/scripts/karten-gutachter.sh"
|
|
# Werkstatt-Skill (Autonomie E6): Selbstwartungs-Kreislauf für Hermes.
|
|
mkdir -p "$HOME/.hermes/skills/wartung"
|
|
cp "$SRC/deploy/skills/wartung/SKILL.md" "$HOME/.hermes/skills/wartung/SKILL.md"
|
|
# Orchestrator-Skill (Autonomie): Werkstatt verallgemeinert — zerlegen → an Worker delegieren → gaten.
|
|
mkdir -p "$HOME/.hermes/skills/orchestrator"
|
|
cp "$SRC/deploy/skills/orchestrator/SKILL.md" "$HOME/.hermes/skills/orchestrator/SKILL.md"
|
|
# PC-Pfad-Cache-Skill (Traum-Entwurf 09.07.2026, aufbereitet): Cache lesen → bei Miss pc_shell-Tool → merken.
|
|
mkdir -p "$HOME/.hermes/skills/pc-pfad-cache"
|
|
cp "$SRC/deploy/skills/pc-pfad-cache/SKILL.md" "$HOME/.hermes/skills/pc-pfad-cache/SKILL.md"
|
|
cp "$SRC/deploy/skills/pc-pfad-cache/pc_path_lookup.sh" "$HOME/.hermes/scripts/pc_path_lookup.sh"
|
|
chmod +x "$HOME/.hermes/scripts/pc_path_lookup.sh"
|
|
# Projekt-Start-Skill (Abloesung 13.07.2026): "erst denken, dann bauen" fuer neue Coding-Projekte
|
|
# in Hermes Desktop — Plan-Riegel, Savepoints, AGENTS.md/SAVEPOINT.md-Ritual, Kontext-Waechter.
|
|
# Portiert vom PC-Skill (F:\Coding Stuff\projekt-start), Zed-Verweise durch Hermes Desktop ersetzt.
|
|
mkdir -p "$HOME/.hermes/skills/projekt-start"
|
|
cp "$SRC/deploy/skills/projekt-start/SKILL.md" "$HOME/.hermes/skills/projekt-start/SKILL.md"
|
|
# Agent-Hooks (Faden 5, 13.07.2026): Skripte frisch halten (reproduzierbar, ueberlebt
|
|
# Box-Neuaufbau). box-steckbrief-inject.sh = Box-Selbstwissen in JEDEN Kanban-Worker
|
|
# (pre_llm_call, scoped auf task_id → Lucy-Chat unberuehrt); pre-verify-gates.sh = das
|
|
# bestehende py_compile/dist-Gate. Die REGISTRIERUNG in ~/.hermes/config.yaml (hooks:)
|
|
# ist EINMALIG von Hand (config.yaml ist Zwei-Schreiber-sensibel, kein Deploy-Schreiber).
|
|
mkdir -p "$HOME/.hermes/agent-hooks"
|
|
# Nur kopieren, wenn der Inhalt sich WIRKLICH geaendert hat — ein blindes cp aendert die
|
|
# mtime auch bei identischem Inhalt und loest sonst bei JEDEM Deploy die harmlose
|
|
# "script modified since approval"-Warnung von `hermes hooks doctor` aus.
|
|
for _h in box-steckbrief-inject.sh pre-verify-gates.sh tabu-pfade-guard.py; do
|
|
_src="$SRC/deploy/agent-hooks/$_h"; _dst="$HOME/.hermes/agent-hooks/$_h"
|
|
cmp -s "$_src" "$_dst" 2>/dev/null || { cp "$_src" "$_dst"; chmod +x "$_dst"; }
|
|
done
|
|
# Eingebaute Hermes-Web-GUI (`hermes serve`) für die Einbettung in MC2 (routers/hermes_ui.py →
|
|
# same-origin /hermes-ui/) vorbereiten: das SPA-Bundle mit Vite-base=/hermes-ui/ (neu) bauen, sonst
|
|
# kollidieren seine absoluten Pfade (/assets, /api) mit MC2s eigenen. Läuft auch nach jedem
|
|
# Hermes-Update mit → hält die Einbettung frisch. Best-effort + Build-zu-Temp-dann-Swap, damit ein
|
|
# Fehlschlag die laufende web_dist NICHT leert (emptyOutDir).
|
|
cp "$SRC/deploy/hermes-builtin-ui.service" "$HOME/.config/systemd/user/hermes-builtin-ui.service"
|
|
_HUI_WEB="$HOME/.hermes/hermes-agent/web"
|
|
_HUI_DIST="$HOME/.hermes/hermes-agent/hermes_cli/web_dist"
|
|
if [ -d "$_HUI_WEB" ] && [ -x "$HOME/.hermes/node/bin/npx" ]; then
|
|
if ( cd "$_HUI_WEB" && PATH="$HOME/.hermes/node/bin:$PATH" npx --no-install vite build \
|
|
--base=/hermes-ui/ --outDir /tmp/hermes-ui-build --emptyOutDir ) >/tmp/hermes-ui-build.log 2>&1; then
|
|
# Dienst VOR dem Tausch stoppen — sonst crasht der laufende `hermes serve`, wenn er index.html
|
|
# im Lösch-Fenster (rm→cp) liest (FileNotFoundError → Start-Limit → tot). Der reguläre restart
|
|
# weiter unten bringt ihn sauber auf der neuen web_dist hoch.
|
|
systemctl --user stop hermes-builtin-ui 2>/dev/null || true
|
|
rm -rf "$_HUI_DIST" && cp -r /tmp/hermes-ui-build "$_HUI_DIST" && echo "Hermes-GUI (base=/hermes-ui/) gebaut."
|
|
else
|
|
echo "WARN: Hermes-GUI-Build fehlgeschlagen (siehe /tmp/hermes-ui-build.log) — bestehende web_dist bleibt."
|
|
fi
|
|
fi
|
|
systemctl --user daemon-reload
|
|
systemctl --user enable mission-control-2 >/dev/null 2>&1 || true
|
|
systemctl --user enable box-console >/dev/null 2>&1 || true
|
|
systemctl --user enable mem0-service >/dev/null 2>&1 || true
|
|
systemctl --user enable voice-service >/dev/null 2>&1 || true
|
|
systemctl --user enable hermes-builtin-ui >/dev/null 2>&1 || true
|
|
systemctl --user enable --now mc2-backup.timer >/dev/null 2>&1 || true
|
|
# mc2-autoupdate.timer wird hier BEWUSST NICHT geschaltet — der Zustand wird nur von Hand
|
|
# geändert (Lehre 09.07.: die frühere enable-Zeile hat einen User-Entscheid bei jedem Deploy
|
|
# still rückgängig gemacht). Aktueller User-Entscheid (10.07.2026): Timer ist AN —
|
|
# Router/Engine/Hermes dürfen So 04:30 automatisch (Fangnetz Backup→Postcheck→Rollback+Pin).
|
|
systemctl --user enable --now mc2-selfsmoke.timer >/dev/null 2>&1 || true
|
|
systemctl --user enable --now mc2-bagatell.timer >/dev/null 2>&1 || true
|
|
loginctl enable-linger "$USER" >/dev/null 2>&1 || true
|
|
# Mem0-Sidecar VOR dem Backend (re)starten, damit /api/memory sofort bedient wird.
|
|
[ -x "$HOME/.mem0/venv/bin/python" ] && systemctl --user restart mem0-service 2>/dev/null || true
|
|
# Voice-Sidecar (re)starten (best-effort; Erststart lädt das STT-Modell vor).
|
|
[ -x "$HOME/.voice/venv/bin/python" ] && systemctl --user restart voice-service 2>/dev/null || true
|
|
# Eingebaute Hermes-Web-GUI (Loopback :9119) (re)starten — MC2 bettet sie unter /hermes-ui/ ein.
|
|
# reset-failed, damit ein zuvor am Start-Limit gestorbener Dienst wieder anläuft.
|
|
systemctl --user reset-failed hermes-builtin-ui 2>/dev/null || true
|
|
systemctl --user restart hermes-builtin-ui 2>/dev/null || true
|
|
systemctl --user restart mission-control-2
|
|
command -v ttyd >/dev/null 2>&1 && systemctl --user restart box-console 2>/dev/null || true
|
|
|
|
sleep 2
|
|
echo "--- Health ---"
|
|
curl -sf http://127.0.0.1:9001/api/health && echo
|
|
|
|
# Warm-Set (Hirn + Augen/vision + Gedächtnis/embed) nach dem Deploy nachladen — ein Deploy bzw.
|
|
# watch-config-Reload verwirft es sonst und die erste Anfrage wäre kalt (D16d). warmup.sh ist
|
|
# selbst-detachend (blockiert den Deploy nicht) und lädt jedes Modell über den richtigen Endpunkt.
|
|
bash "$SRC/deploy/warmup.sh" || true
|
|
|
|
echo "OK — Mission Control 2.0 läuft auf :9001 (User-Dienst, sudo-frei)."
|