#!/usr/bin/env bash # Bagatell-Annahme — „Harmloses darf selbst" (User-Entscheid 10.07.2026, konservativ geschnitten): # Vorschlags-Branches, die AUSSCHLIESSLICH Markdown-Dateien anlegen oder ändern (Doku/Wiki — # keine einzige Code-Zeile, keine Löschungen, keine Umbenennungen, keine Skripte), spielt die # Box nachts OHNE Klick ein. Der Weg ist derselbe wie beim Klick im Auftragsbuch: # auftrag-annehmen.sh (Merge im Worktree → py_compile-Gate → Push main → Deploy → Health → # Auto-Revert). Fangnetz drumherum: Nacht-Sicherung 03:30 (Zeitmaschine) liegt davor, die # Morgenlage 04:30 berichtet danach, jede Annahme steht in Chronik + Telegram. # JEDE Code-Zeile bleibt Klick-pflichtig — dieses Skript weitet die Klasse NIE selbst aus. # # Läuft als mc2-bagatell.timer (04:10) über eine /tmp-Kopie (Selbst-Reset-Falle: die Annahme # deployt und resettet damit das Repo, in dem dieses Skript liegt). set -uo pipefail SRC="${MC2_SRC:-$HOME/mission-control-v2}" STATUS="${MC2_AUFTRAG_STATUS:-/srv/models/mc2-auftragsbuch.json}" MAX_PRO_NACHT=2 # jede Annahme startet die Zentrale kurz neu — Nachtruhe wahren cd "$SRC" || exit 0 git fetch -q --prune origin 2>/dev/null || exit 0 angenommen=0 for REF in $(git for-each-ref --format='%(refname:short)' refs/remotes/origin); do [ "$angenommen" -ge "$MAX_PRO_NACHT" ] && break BRANCH="${REF#origin/}" case "$BRANCH" in wartung/*|orchestrator/*|doku/*|feature/*) ;; *) continue ;; esac AHEAD="$(git rev-list --count "origin/main..$REF" 2>/dev/null || echo 0)" [ "${AHEAD:-0}" -gt 0 ] || continue # Nur unberührte Vorschläge: trägt der Branch schon irgendeinen Annahme-Status # (läuft/fehlgeschlagen/zurückgerollt/…), entscheidet der Commander — nicht wir. STATE="$(python3 - "$STATUS" "$BRANCH" <<'PY' import json, sys try: print((json.load(open(sys.argv[1], encoding="utf-8")).get("branches", {}).get(sys.argv[2]) or {}).get("state", "")) except Exception: print("") PY )" [ -z "$STATE" ] || continue # Bagatell-Klasse: JEDE geänderte Datei endet auf .md UND ist nur angelegt (A) oder # geändert (M). Alles andere (Löschung, Rename R…, Copy C…, Nicht-Markdown) → Klick-Pflicht. DIFF="$(git diff --name-status "origin/main...$REF" 2>/dev/null)" [ -n "$DIFF" ] || continue OK=1 while IFS=$'\t' read -r st path _rest; do [ -n "$st" ] || continue case "$st" in A|M) ;; *) OK=0; break ;; esac case "$path" in *.md) ;; *) OK=0; break ;; esac done <<< "$DIFF" [ "$OK" = 1 ] || continue N="$(printf '%s\n' "$DIFF" | wc -l | tr -d ' ')" echo "Bagatelle erkannt: $BRANCH ($N Markdown-Datei(en))" curl -sf -m 5 -X POST "${MC_ANNOUNCE_URL:-http://127.0.0.1:9001/api/voice/announce}" \ -H 'Content-Type: application/json' \ --data "$(jq -n --arg t "Bagatelle (nur Doku, $N Datei(en)): '$BRANCH' wird ohne Klick eingespielt — Fangnetz aktiv, Details in der Morgenlage." \ '{text:$t, subject:"[Bagatell-Annahme]", source:"bagatell", priority:"silent"}')" >/dev/null 2>&1 || true RUNNER="/tmp/mc2-bagatell-annehmen-$$.sh" cp "$SRC/deploy/auftrag-annehmen.sh" "$RUNNER" || continue if bash "$RUNNER" "$BRANCH"; then angenommen=$((angenommen+1)) else # auftrag-annehmen.sh hat selbst gemeldet (fehlgeschlagen/zurückgerollt) und aufgeräumt; # der Branch trägt jetzt einen Status → nächste Nacht fasst ihn niemand mehr automatisch an. echo "Bagatell-Annahme von $BRANCH nicht grün — Meldung kam vom Annahme-Runner." fi done echo "Bagatell-Lauf fertig: $angenommen eingespielt."