Feat: Stack-Funktionsprüfung nach OS-/Engine-/Router-Update

Bisher hatte nur das Hermes-Update einen echten Post-Check; OS/Engine/Router
liefen mit Exit 0 durch, auch wenn der neue Build den Stack zerschoss (gruener
Job trotz totem Stack). Neu: deploy/stack-postcheck.sh prueft nach jedem Update
funktional — llama-swap aktiv, /v1/models 200, ECHTE 1-Token-Inferenz auf dem
Hirn-Modell (beweist Laden+Generieren), MC2 /api/health engine_reachable, Mem0
erreichbar. Eingehaengt als `<update> && bash stack-postcheck.sh` in os/engine/
swap-update-job → Exit 1 macht den jobengine-Job ROT. Pendant zu hermes-postcheck.sh.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Hitonabi
2026-06-28 11:29:32 +02:00
parent 637cbd9135
commit 9923743219
2 changed files with 82 additions and 3 deletions
+13 -3
View File
@@ -38,6 +38,10 @@ SWAP_BIN = os.environ.get("MC_SWAP_BIN", "/usr/local/bin/llama-swap")
SWAP_REPO = os.environ.get("MC_SWAP_REPO", "mostlygeek/llama-swap")
_swap_cache = {"ts": 0.0, "avail": False}
# Stack-Funktionsprüfung NACH jedem Update (OS/Engine/Router): verifiziert per echter
# Inferenz, dass der Stack noch läuft → Job wird rot, wenn ein Update etwas zerschossen hat.
STACK_POSTCHECK = os.path.join(_REPO_ROOT, "deploy", "stack-postcheck.sh")
def _installed_engine_build() -> int | None:
"""Build-Nummer der installierten llama-server-Binary (z.B. 9821), oder None.
@@ -475,7 +479,9 @@ def check_updates_job(sudo_password: str | None = None) -> dict:
def os_update_job(sudo_password: str | None = None) -> dict:
if err := check_sudo_needs_password(sudo_password):
return err
cmd = "sudo apt-get update && sudo DEBIAN_FRONTEND=noninteractive apt-get upgrade -y"
# Nach dem apt-Upgrade den Stack funktional prüfen (Job wird rot, wenn etwas kaputt ging).
cmd = ("sudo apt-get update && sudo DEBIAN_FRONTEND=noninteractive apt-get upgrade -y "
f"&& bash {STACK_POSTCHECK}")
job_id = jobengine.start_job(["bash", "-c", cmd], "OS-Update (apt)", sudo_password=sudo_password)
return {"ok": True, "job_id": job_id}
@@ -490,7 +496,9 @@ def engine_update_job(sudo_password: str | None = None) -> dict | None:
_engine_cache.update(ts=0.0, avail=False) # Cache leeren → frischer Build-Vergleich
# update-engine.sh läuft via sudo als root und startet llama-swap am Ende selbst neu.
job_id = jobengine.start_job(["bash", "-c", ENGINE_UPDATE_CMD],
# Danach Stack-Funktionsprüfung (echte Inferenz) → Job wird rot, wenn der neue Build kaputt ist.
cmd = f"{ENGINE_UPDATE_CMD} && bash {STACK_POSTCHECK}"
job_id = jobengine.start_job(["bash", "-c", cmd],
"Engine-Update (llama.cpp Vulkan)",
on_done=on_done, sudo_password=sudo_password)
return {"ok": True, "job_id": job_id}
@@ -506,7 +514,9 @@ def swap_update_job(sudo_password: str | None = None) -> dict | None:
_swap_cache.update(ts=0.0, avail=False) # Cache leeren → frischer Versions-Vergleich
# update-swap.sh läuft via sudo als root, ersetzt die Binary und startet llama-swap neu.
job_id = jobengine.start_job(["bash", "-c", SWAP_UPDATE_CMD],
# Danach Stack-Funktionsprüfung (echte Inferenz) → Job wird rot, wenn der Router kaputt ist.
cmd = f"{SWAP_UPDATE_CMD} && bash {STACK_POSTCHECK}"
job_id = jobengine.start_job(["bash", "-c", cmd],
"Router-Update (llama-swap)",
on_done=on_done, sudo_password=sudo_password)
return {"ok": True, "job_id": job_id}