Ampel / ampel (push) Failing after 22s
Der Verlauf las bisher nur den Hermes-Cron-Status ("Skript lief") und zeigte die
Laeufe vom 06. und 13.09. als "durchgelaufen", obwohl dort zurueckgerollt und
festgehalten wurde; ein abgebrochener Lauf stand als "laeuft" da. Jetzt kommt der
Verlauf aus dem Meldeprotokoll (~/mc2-notify.log), also aus dem, was autoupdate.sh
selbst je Baustein meldet.
Festgehaltene Bausteine (Pin-Register) werden zum Waechter-Hinweis mit Knopf
"Freigeben", auf der Updates-Seite markiert und in der Updates-Lampe gezaehlt.
Hermes zeigt seine laufende Version und die Zahl der neuen Aenderungen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
133 lines
7.1 KiB
Python
133 lines
7.1 KiB
Python
"""Update-Verlauf aus dem Meldeprotokoll und festgehaltene Bausteine (Box-Wart 09/2026)."""
|
|
|
|
import json
|
|
|
|
from services import update_verlauf
|
|
|
|
# Echte Formate aus ~/mc2-notify.log der Box (gekürzt), inklusive fremder Meldungen dazwischen.
|
|
PROTOKOLL = """\
|
|
2026-08-14 18:53:58 OK telegram: Mein Gehirn lädt nicht — ich kann gerade nicht richtig denken.
|
|
2026-08-23 04:31:15 QUEUED für Morgen-Digest: KRITISCH: Engine (llama.cpp)-Update auf 10588 UND Rollback fehlgeschlagen — Stack möglicherweise kaputt.
|
|
2026-08-23 07:04:17 OK telegram: 📰 DAILY NEWS 23.08.2026
|
|
|
|
• **Eine Nachricht** (Quelle, 21. August 2026)
|
|
Text der Nachricht.
|
|
2026-09-04 14:07:27 OK telegram: Router (llama-swap) aktualisiert: 252 → 253. Stack-Check grün, alles läuft.
|
|
2026-09-04 14:09:30 OK telegram: Commander, die Wochenpflege der Box ist durch — kurz für dich:
|
|
• Router (llama-swap): 252 → 253 eingespielt, Stack-Check grün.
|
|
• Engine (llama.cpp): 10733 → 10797 eingespielt, Stack-Check grün.
|
|
• Hermes-Agent: 1 Commits eingespielt, Gehirn-Check grün.
|
|
2026-09-04 14:26:29 OK telegram: Die Box startet jetzt neu — Kernel 7.0.0-31 ist eingespielt.
|
|
2026-09-06 04:31:16 QUEUED für Morgen-Digest: Engine (llama.cpp) aktualisiert: 10797 → 10819. Stack-Check grün, alles läuft.
|
|
2026-09-06 04:55:53 QUEUED für Morgen-Digest: Hermes-Update fehlgeschlagen (Gehirn-Check rot). Automatisch zurückgerollt auf 63279301b — läuft wieder. Hermes ist jetzt GEPINNT.
|
|
2026-09-06 04:55:53 QUEUED für Morgen-Digest: Commander, die Wochenpflege der Box ist durch — kurz für dich:
|
|
• Router (llama-swap): aktuell (253).
|
|
• Engine (llama.cpp): 10797 → 10819 eingespielt, Stack-Check grün.
|
|
• Hermes-Agent: Update FEHLGESCHLAGEN → zurückgerollt + GEPINNT auf 63279301b.
|
|
2026-09-10 12:00:00 OK telegram: Die Box startet jetzt neu — von Hand.
|
|
2026-09-13 04:31:07 QUEUED für Morgen-Digest: Commander, die Wochenpflege der Box ist durch — kurz für dich:
|
|
• Router (llama-swap): 253 → 255 eingespielt, Stack-Check grün.
|
|
• Engine (llama.cpp): 10936 FEHLGESCHLAGEN → zurückgerollt auf 10819 + GEPINNT.
|
|
• Hermes-Agent: gepinnt, übersprungen.
|
|
2026-09-13 04:31:07 QUEUED für Morgen-Digest: Die Box startet jetzt neu — das OS verlangt es nach dem Update (libc6 ).
|
|
2026-09-20 04:30:39 QUEUED für Morgen-Digest: Router (llama-swap) aktualisiert: 255 → 256. Stack-Check grün, alles läuft.
|
|
2026-09-20 04:35:33 QUEUED für Morgen-Digest: Commander, die Wochenpflege der Box ist durch — kurz für dich:
|
|
• Router (llama-swap): 255 → 256 eingespielt, Stack-Check grün.
|
|
• Engine (llama.cpp): 11026 → 11057 eingespielt, Stack-Check grün.
|
|
• Hermes-Agent: 1861 Commits eingespielt, Gehirn-Check grün.
|
|
2026-09-27 04:31:00 QUEUED für Morgen-Digest: Commander, die Wochenpflege der Box ist durch — kurz für dich:
|
|
• Router (llama-swap): aktuell (256).
|
|
• Engine (llama.cpp): aktuell (11057).
|
|
• Hermes-Agent: aktuell.
|
|
"""
|
|
|
|
|
|
def test_laeufe_neueste_zuerst_und_ohne_fremde_meldungen():
|
|
laeufe = update_verlauf.laeufe_aus(PROTOKOLL)
|
|
# 27.09., 20.09., 13.09., 06.09., 04.09., 23.08. — der Neustart vom 10.09. allein ist kein Lauf.
|
|
assert [lauf["start"][:10] for lauf in laeufe] == [
|
|
"2026-09-27", "2026-09-20", "2026-09-13", "2026-09-06", "2026-09-04", "2026-08-23"]
|
|
|
|
|
|
def test_gruener_sonntag_mit_einer_zeile_je_baustein():
|
|
lauf = update_verlauf.laeufe_aus(PROTOKOLL)[1]
|
|
assert lauf["anlass"] == "Updates am Sonntag"
|
|
assert (lauf["stufe"], lauf["titel"]) == ("gruen", "Eingespielt")
|
|
assert [(z["baustein"], z["ergebnis"]) for z in lauf["zeilen"]] == [
|
|
("llama-swap", "eingespielt"), ("Motor", "eingespielt"), ("Hermes", "eingespielt")]
|
|
assert lauf["zeilen"][2]["text"] == "1861 Änderungen eingespielt, Gehirn-Check grün."
|
|
|
|
|
|
def test_rueckbau_und_festhalten_werden_gelb_und_lesbar():
|
|
lauf = update_verlauf.laeufe_aus(PROTOKOLL)[2] # 13.09.
|
|
assert (lauf["stufe"], lauf["titel"]) == ("gelb", "Zurückgerollt")
|
|
zeilen = {z["baustein"]: z for z in lauf["zeilen"]}
|
|
assert zeilen["Motor"]["ergebnis"] == "zurueckgerollt"
|
|
assert zeilen["Motor"]["text"] == "10936 fehlgeschlagen → zurückgerollt auf 10819 und festgehalten."
|
|
assert zeilen["Hermes"]["ergebnis"] == "festgehalten"
|
|
assert zeilen["Neustart"]["ergebnis"] == "neustart"
|
|
|
|
|
|
def test_abgebrochener_lauf_ohne_zusammenfassung_ist_rot():
|
|
lauf = update_verlauf.laeufe_aus(PROTOKOLL)[-1] # 23.08.
|
|
assert (lauf["stufe"], lauf["titel"]) == ("rot", "Fehler")
|
|
assert lauf["zeilen"][0]["baustein"] == "Motor"
|
|
assert lauf["zeilen"][0]["text"].startswith("Kritisch: Engine (llama.cpp)-Update auf 10588")
|
|
|
|
|
|
def test_lauf_von_hand_mit_neustart_danach():
|
|
lauf = update_verlauf.laeufe_aus(PROTOKOLL)[4] # 04.09. nachmittags
|
|
assert lauf["anlass"] == "Update von Hand"
|
|
assert lauf["titel"] == "Eingespielt"
|
|
assert lauf["zeilen"][-1]["baustein"] == "Neustart"
|
|
|
|
|
|
def test_alles_aktuell_ist_grau():
|
|
lauf = update_verlauf.laeufe_aus(PROTOKOLL)[0]
|
|
assert (lauf["stufe"], lauf["titel"]) == ("grau", "Alles aktuell")
|
|
|
|
|
|
def test_laeufe_liest_die_datei_und_merkt_sich_den_stand(tmp_path, monkeypatch):
|
|
datei = tmp_path / "mc2-notify.log"
|
|
datei.write_text(PROTOKOLL, encoding="utf-8")
|
|
monkeypatch.setattr(update_verlauf, "NOTIFY_LOG", datei)
|
|
monkeypatch.setattr(update_verlauf, "_cache", {"schluessel": None, "laeufe": []})
|
|
assert len(update_verlauf.laeufe(3)) == 3
|
|
monkeypatch.setattr(update_verlauf, "NOTIFY_LOG", tmp_path / "gibt-es-nicht.log")
|
|
assert update_verlauf.laeufe() == []
|
|
|
|
|
|
def test_festgehalten_und_freigeben(tmp_path, monkeypatch):
|
|
pins = tmp_path / "mc2-pins.json"
|
|
pins.write_text(json.dumps({
|
|
"engine": {"pinned": True, "version": "10819", "datum": "2026-09-13",
|
|
"grund": "Update auf 10936 zerschoss den Stack-Check; Rollback grün"},
|
|
"hermes": {"pinned": True, "version": "63279301b", "datum": "2026-09-06", "grund": "x"},
|
|
"swap": {"pinned": False},
|
|
}), encoding="utf-8")
|
|
monkeypatch.setattr(update_verlauf, "PINS_FILE", pins)
|
|
|
|
fest = update_verlauf.festgehalten()
|
|
assert [(p["baustein"], p["seit"]) for p in fest] == [("engine", "13.09."), ("hermes", "06.09.")]
|
|
assert fest[0]["name"] == "Motor (llama.cpp)"
|
|
|
|
assert update_verlauf.freigeben("engine") is True
|
|
assert update_verlauf.freigeben("engine") is False
|
|
rest = json.loads(pins.read_text(encoding="utf-8"))
|
|
assert set(rest) == {"hermes", "swap"}
|
|
|
|
|
|
def test_waechter_meldet_festgehaltene_bausteine(tmp_path, monkeypatch):
|
|
from services import waechter
|
|
|
|
pins = tmp_path / "mc2-pins.json"
|
|
pins.write_text(json.dumps({"engine": {"pinned": True, "version": "10819", "datum": "2026-09-13",
|
|
"grund": "Update zerschoss den Stack-Check"}}), encoding="utf-8")
|
|
monkeypatch.setattr(update_verlauf, "PINS_FILE", pins)
|
|
befunde = waechter.pruefe_festgehalten()
|
|
assert len(befunde) == 1
|
|
b = befunde[0]
|
|
assert (b.id, b.stufe, b.sofort) == ("pin:engine", "gelb", True)
|
|
assert "Seit 13.09. auf 10819 festgehalten" in b.text
|
|
assert b.aktionen[0]["id"] == "freigeben" and b.aktionen[0]["baustein"] == "engine"
|