Files
mission-control-v2/deploy/jobs/stack-radar.sh
T
HitonabiandClaude Fable 5.1 e9c2599542
Ampel / ampel (push) Failing after 23s
fix(radar): nur Aenderungen ans Modell, und kein Fehlalarm nach dem Neustart
Erster Lauf des Upstream-Blicks: das Modell machte aus "unveraendert"-Zeilen
naechste Schritte und aus "Timer seit Neustart noch nicht gelaufen" ein hohes
Risiko. Beides filtert jetzt das Skript: nur ACHTUNG-Zeilen (plus Hinweis)
gehen in den Prompt, und ein Timer mit naechstem Termin auf einer Box, die
juenger als einen Tag ist, gilt als wartend, nicht als kaputt.

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

131 lines
5.5 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"
# Nur Aenderungen ans Modell. Beim ersten Lauf (04.09.) bekam es auch die
# "unveraendert"-Zeilen und erfand zu jeder einen "naechsten Schritt" — der
# Prompt-Hinweis half nicht. Fakten filtert das Skript, nicht die Prosa.
ANZ_QUELLEN="$(printf '%s\n' "$UPSTREAM" | grep -cE '^\s+(OK|ACHTUNG)' || true)"
UPSTREAM_NEU="$(printf '%s\n' "$UPSTREAM" | grep -A1 -E '^\s+ACHTUNG' | grep -vE '^--$' || true)"
[ -z "$UPSTREAM_NEU" ] && UPSTREAM_NEU=" OK nichts Neues draussen ($ANZ_QUELLEN Quellen geprueft, alle unveraendert)"
IST="$IST
UPSTREAM (was hat sich draussen getan?)
$UPSTREAM_NEU"
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