phase0: Nachtmeldungen kommen wieder an, Sicherung mit Lucys Gedaechtnis, Token-Datei raus
Ampel / ampel (push) Successful in 26s
Ampel / ampel (push) Successful in 26s
- notify.sh sammelt nachts (00-07 Uhr) wie bisher, aber jetzt liefert mc2-morgenmeldung.timer um 07:00 alles als eine Telegram-Nachricht aus. Seit dem 21.08. las niemand die Warteschlange, alle Nachtmeldungen (auch die Sonntags-Updates) gingen verloren. Dringendes (-d, Betreff Alarm/Notfall, Text beginnt mit KRITISCH) geht sofort raus; autoupdate.sh markiert seine KRITISCH-Meldungen ausdruecklich. - backup.sh sichert zusaetzlich ~/.hermes/memories, SOUL.md, skills/, scripts/, den Box-Wart-Zustand (/srv/models/mc2-*.json), User-Units, llama-swap-Drop-ins und Lucys Stimmreferenz. restore.sh spielt Gedaechtnis und Zustand nur zurueck, wenn sie fehlen oder --mit-gedaechtnis gesetzt ist. - Update-Verlauf zaehlt die Morgenmeldung nicht als eigenen Lauf. - Waechter und Flugplan kennen den neuen Timer; deploy.sh installiert ihn. - .claude/settings.local.json aus dem Repo genommen (lokal behalten), .gitignore ergaenzt. - ruff wieder gruen (4x RUF100), AGENTS.md: Deploy macht git pull, Remote ist SSH. Tests: 86 gruen (neu: Nachtruhe, Dringendes, Morgenmeldung inkl. Telegram-Ausfall). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
4a05bc2a05
commit
648be33d21
@@ -0,0 +1,120 @@
|
||||
"""Nachtruhe und Morgenmeldung (deploy/notify.sh, deploy/morgenmeldung.sh, 24.09.2026).
|
||||
|
||||
Bis zum 24.09. parkte notify.sh nachts alles in einer Warteschlange, die niemand mehr auslieferte.
|
||||
Die Tests fahren die echten Skripte mit einem Ersatz für `hermes send`, der nur mitschreibt."""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
DEPLOY = Path(__file__).resolve().parents[2] / "deploy"
|
||||
BASH = shutil.which("bash")
|
||||
|
||||
# Unter Windows kann „bash“ die WSL-Hülle sein, die Windows-Pfade nicht versteht — dann überspringen.
|
||||
pytestmark = pytest.mark.skipif(
|
||||
BASH is None or (sys.platform == "win32" and "system32" in BASH.lower()),
|
||||
reason="braucht eine bash (Git-Bash oder Linux)",
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def umgebung(tmp_path):
|
||||
protokoll = tmp_path / "gesendet.txt"
|
||||
stub = tmp_path / "hermes-stub"
|
||||
stub.write_text(
|
||||
"#!/usr/bin/env bash\n"
|
||||
'printf "%s\\n" "$*" >> "$STUB_PROTOKOLL"\n'
|
||||
'exit "${STUB_EXIT:-0}"\n',
|
||||
encoding="utf-8", newline="\n")
|
||||
stub.chmod(0o755)
|
||||
env = {
|
||||
**os.environ,
|
||||
"MC_NOTIFY_LOG": (tmp_path / "notify.log").as_posix(),
|
||||
"MC_NIGHT_QUEUE": (tmp_path / "night-queue.txt").as_posix(),
|
||||
"MC_NOTIFY_HERMES": stub.as_posix(),
|
||||
"MC_NOTIFY_NO_ANNOUNCE": "1",
|
||||
"STUB_PROTOKOLL": protokoll.as_posix(),
|
||||
"MC_MORGENMELDUNG_PAUSE": "0",
|
||||
}
|
||||
return tmp_path, env, protokoll
|
||||
|
||||
|
||||
def _notify(env, *args, stunde="03"):
|
||||
return subprocess.run([BASH, (DEPLOY / "notify.sh").as_posix(), *args],
|
||||
env={**env, "MC_NOTIFY_STUNDE": stunde}, capture_output=True, text=True, timeout=60)
|
||||
|
||||
|
||||
def _gesendet(protokoll: Path) -> str:
|
||||
return protokoll.read_text(encoding="utf-8") if protokoll.exists() else ""
|
||||
|
||||
|
||||
def test_nachts_wird_gesammelt(umgebung):
|
||||
tmp, env, protokoll = umgebung
|
||||
assert _notify(env, "-s", "[Box-Update]", "Engine aktualisiert").returncode == 0
|
||||
assert _gesendet(protokoll) == ""
|
||||
assert (tmp / "night-queue.txt").read_text(encoding="utf-8") == "- [Box-Update]: Engine aktualisiert\n"
|
||||
assert "QUEUED für Morgen-Digest: Engine aktualisiert" in (tmp / "notify.log").read_text(encoding="utf-8")
|
||||
|
||||
|
||||
@pytest.mark.parametrize("args", [
|
||||
("-d", "-s", "[Box-Update]", "Wichtig"),
|
||||
("-s", "[Alarm]", "Lucy antwortet nicht"),
|
||||
("-s", "[Box-Update]", "KRITISCH: Update UND Rollback fehlgeschlagen"),
|
||||
])
|
||||
def test_dringendes_geht_nachts_sofort_raus(umgebung, args):
|
||||
tmp, env, protokoll = umgebung
|
||||
assert _notify(env, *args).returncode == 0
|
||||
assert "send --to telegram" in _gesendet(protokoll)
|
||||
assert not (tmp / "night-queue.txt").exists()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("stunde", ["07", "08", "09", "23"])
|
||||
def test_tagsueber_sofort(umgebung, stunde):
|
||||
tmp, env, protokoll = umgebung
|
||||
assert _notify(env, "-s", "[Test]", "Hallo", stunde=stunde).returncode == 0
|
||||
assert "Hallo" in _gesendet(protokoll)
|
||||
assert not (tmp / "night-queue.txt").exists()
|
||||
|
||||
|
||||
def _morgenmeldung(env, **extra):
|
||||
return subprocess.run([BASH, (DEPLOY / "morgenmeldung.sh").as_posix()], env={**env, **extra},
|
||||
capture_output=True, text=True, timeout=60)
|
||||
|
||||
|
||||
def test_morgenmeldung_schickt_alles_als_eine_nachricht(umgebung):
|
||||
tmp, env, protokoll = umgebung
|
||||
_notify(env, "-s", "[Box-Update]", "Router aktualisiert")
|
||||
_notify(env, "-s", "[Modell-Radar]", "Kandidat bestanden")
|
||||
assert _morgenmeldung(env).returncode == 0
|
||||
gesendet = _gesendet(protokoll)
|
||||
assert gesendet.count("send --to telegram") == 1
|
||||
assert "[Morgenmeldung]" in gesendet and "2 Meldungen" in gesendet
|
||||
assert "Router aktualisiert" in gesendet and "Kandidat bestanden" in gesendet
|
||||
assert not (tmp / "night-queue.txt").exists()
|
||||
assert (tmp / "night-queue.txt.zuletzt-gesendet").exists()
|
||||
|
||||
|
||||
def test_morgenmeldung_ohne_nachtmeldungen_schweigt(umgebung):
|
||||
_, env, protokoll = umgebung
|
||||
assert _morgenmeldung(env).returncode == 0
|
||||
assert _gesendet(protokoll) == ""
|
||||
|
||||
|
||||
def test_morgenmeldung_verliert_nichts_wenn_telegram_klemmt(umgebung):
|
||||
tmp, env, protokoll = umgebung
|
||||
_notify(env, "-s", "[Box-Update]", "Erste Nacht")
|
||||
fehl = _morgenmeldung(env, STUB_EXIT="1", MC_MORGENMELDUNG_VERSUCHE="2")
|
||||
assert fehl.returncode == 1
|
||||
assert (tmp / "night-queue.txt.senden").exists()
|
||||
|
||||
_notify(env, "-s", "[Box-Update]", "Zweite Nacht")
|
||||
protokoll.unlink()
|
||||
assert _morgenmeldung(env).returncode == 0
|
||||
gesendet = _gesendet(protokoll)
|
||||
assert "2 Meldungen" in gesendet
|
||||
assert gesendet.index("Erste Nacht") < gesendet.index("Zweite Nacht")
|
||||
assert not (tmp / "night-queue.txt.senden").exists()
|
||||
Reference in New Issue
Block a user