Files
mission-control-v2/deploy/jobs/stack-radar.sh
T
HitonabiandClaude Fable 5.1 a8a6ce3b29 feat(radar): Blick nach draussen als Skript — und heavy zieht auf Qwen3.8-27B
Warum: DFlash2 fuer den Coder lag vom 19.08. bis 04.09. ungenutzt auf der
Platte, weil der KISS-Radar nur nach innen sah. stack-upstream.py fragt die
Watchlist als Fakten ab (GitHub-Issues/PRs/Releases/Branches, PyPI, neue
Repos eines HF-Autors, Zeilen einer URL), vergleicht mit dem letzten Lauf und
meldet nur Aenderungen als ACHTUNG NEU. stack-radar.sh haengt das an den
IST-Zustand; faellt es aus, bleibt der Innen-Bericht vollstaendig.
Erster Lauf fand sofort: MMQ-Issue 21284 ist geschlossen, pocket-tts 3.1.0,
Electron 44 — alles Dinge, die der Radar seit Juli haette melden sollen.

heavy: gpt-oss-120b (AA-Index 24, 60 GB) gibt die Rolle an Qwen3.8-27B ab
(Index 52, 17 GB, 31 t/s mit DFlash2) — ein Modell, zwei Rollen. gpt-oss
bleibt ohne Alias als Rollback. Live gemessen ueber :9010 mit Reasoning.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 14:52:50 +02:00

124 lines
4.9 KiB
Bash

#!/usr/bin/env bash
# stack-radar.sh — Job 3: "KI & Stack Radar" (21.08.2026).
#
# Ablauf: IST-Zustand holen (Fakten) -> Modell bewerten lassen (Prosa)
# -> ueber notify.sh melden (Telegram + Lucys Stimme)
#
# KUGELSICHER heisst hier konkret:
# * Die Fakten kommen aus stack-ist.sh, nicht aus dem Modell. Faellt das Modell
# aus, werden die ROTEN Zeilen trotzdem gemeldet — roh statt gar nicht.
# * Es meldet IMMER. "Alles gruen" ist ein Ergebnis, kein Grund zu schweigen.
# * Kein set -e: ein einzelner Fehlschlag darf den Bericht nicht abschneiden.
#
# Aufruf ueber Hermes-Cron:
# hermes cron create '0 8 * * 6' --name 'KI & Stack Radar' \
# --no-agent --script stack-radar.sh --deliver local
# (--no-agent, weil dieses Skript selbst meldet. Leere Ausgabe = Hermes schweigt.)
set -uo pipefail
HIER="$(cd "$(dirname "$0")" && pwd)"
IST_SKRIPT="${IST_SKRIPT:-$HOME/.hermes/scripts/stack-ist.sh}"
NOTIFY="${NOTIFY:-$HOME/mission-control-v2/deploy/notify.sh}"
GATEWAY="${GATEWAY_URL:-http://127.0.0.1:9010/v1}"
MODELL="${RADAR_MODELL:-fast}" # bewusst NICHT heavy: das laedt 68 GB und der
# Radar meldet danach seinen eigenen Speicherverbrauch als Befund
[ -x "$IST_SKRIPT" ] || IST_SKRIPT="$HIER/stack-ist.sh"
melde() {
if [ -x "$NOTIFY" ] || [ -f "$NOTIFY" ]; then
bash "$NOTIFY" -s "[Stack-Radar]" "$1"
else
# Letzte Rueckfallebene: wenigstens ins Log, damit nichts still verschwindet.
echo "[stack-radar] MELDEWEG FEHLT — Bericht folgt roh:" >&2
echo "$1" >&2
fi
}
# ------------------------------------------------------------- 1. Fakten ---
IST="$(bash "$IST_SKRIPT" 2>&1)"
if [ -z "$IST" ]; then
melde "Radar konnte den IST-Zustand nicht erheben — $IST_SKRIPT lieferte nichts. Das ist selbst ein Befund: bitte nachsehen."
exit 1
fi
# Der Blick nach DRAUSSEN (04.09.2026): Releases, PRs, neue Entwurfsmodelle —
# als Skript-Fakten, gegen den letzten Lauf verglichen. Ohne das lag DFlash2 fuer
# den Coder zwei Wochen ungenutzt auf der Platte. Faellt es aus, bleibt der
# Innen-Bericht vollstaendig; das Ausbleiben steht dann selbst als ACHTUNG drin.
UPSTREAM_SKRIPT="${UPSTREAM_SKRIPT:-$HIER/stack-upstream.py}"
if [ -f "$UPSTREAM_SKRIPT" ]; then
UPSTREAM="$(timeout 240 python3 "$UPSTREAM_SKRIPT" 2>&1)" \
|| UPSTREAM="UPSTREAM (Watchlist)
ACHTUNG Upstream-Pruefung abgebrochen (exit $?) — $UPSTREAM_SKRIPT nachsehen"
IST="$IST
$UPSTREAM"
fi
ROT="$(printf '%s\n' "$IST" | grep -E '^\s+(ROT|ACHTUNG)' || true)"
ANZ_ROT="$(printf '%s\n' "$ROT" | grep -c 'ROT' || true)"
# ------------------------------------------------------- 2. Bewertung ------
# Das Modell bekommt NUR die Fakten und darf nichts dazuerfinden. Es soll
# einordnen, nicht ermitteln.
PROMPT="Du bist der Stack-Radar einer selbstgehosteten KI-Box. Unten steht der
gemessene IST-Zustand. Schreibe einen kurzen Bericht auf Deutsch, per Du.
Regeln:
- Erfinde NICHTS. Nur was unten steht.
- Beginne mit einer Zeile Gesamturteil.
- Dann: was ist ROT oder ACHTUNG, und was waere jeweils der naechste Schritt.
- Verbesserungsvorschlaege NUR, wenn sich aus den Zahlen unten wirklich etwas
Konkretes ergibt. Gibt es nichts, lass den Abschnitt ersatzlos weg. Schreibe
lieber gar keinen Vorschlag als einen ausgedachten - ein Bericht mit
Fuellmaterial wird nicht gelesen.
- Was du an den Messwerten selbst merkwuerdig findest, gehoert unter ACHTUNG,
nicht unter Verbesserungen.
- Zeilen mit NEU im Abschnitt UPSTREAM sind Neuigkeiten von draussen. Nenne
jede kurz und gib den Hinweis dahinter (der Pfeil-Satz) als naechsten Schritt
wieder. 'erstmals erfasst' und 'unveraendert' sind KEINE Neuigkeiten.
- Wenn alles gruen ist, sag das in einem Satz und hoere auf.
- Keine Ueberschriften-Deko, keine Emojis, hoechstens 200 Woerter.
IST-ZUSTAND:
$IST"
ANTWORT=""
if NUTZLAST="$(python3 -c '
import json, sys
print(json.dumps({
"model": sys.argv[1],
"messages": [{"role": "user", "content": sys.argv[2]}],
"max_tokens": 900,
"temperature": 0.3,
}))' "$MODELL" "$PROMPT" 2>/dev/null)"; then
ANTWORT="$(curl -s -m 300 -X POST "$GATEWAY/chat/completions" \
-H 'Content-Type: application/json' -d "$NUTZLAST" 2>/dev/null \
| python3 -c '
import json, sys
try:
print(json.load(sys.stdin)["choices"][0]["message"]["content"].strip())
except Exception:
pass' 2>/dev/null)"
fi
# ------------------------------------------------------------- 3. Melden ---
if [ -n "$ANTWORT" ]; then
melde "$ANTWORT"
else
# Modell stumm oder kaputt -> die Fakten gehen TROTZDEM raus. Genau dafuer
# steht das Modell nicht im kritischen Pfad.
if [ -n "$ROT" ]; then
melde "Radar: Bewertung durch das Modell hat nicht geklappt — hier die Rohbefunde:
$ROT"
else
melde "Radar: alles gruen (Bewertung durch das Modell hat nicht geklappt, die Messung schon)."
fi
fi
# Hermes bekommt eine LEERE Ausgabe -> keine zweite Nachricht. Gemeldet wurde
# bereits ueber notify.sh, und das erreicht Telegram UND Lucys Stimme.
exit 0