Welle 3 · Lucys Freiheiten je Aktionsart, Rückfragen mit „ja 7“, Lucy untersucht rote Hinweise, Wochenbericht
- services/lucy_autonomie.py: Stufe je Aktionsart (nur lesen, erst fragen, selbst handeln), Start „mehr Freiheit“;
Meldung danach (POST /api/lucy/gehandelt)
- services/rueckfragen.py: nummerierte Rückfragen, nur Knöpfe der Oberfläche (ERLAUBT), „ja“ führt genau die
gespeicherte Aktion aus, 24 h gültig, hinfällig wenn der Hinweis weg ist, Nachprüfung danach
- notify.sh -k: Antworttasten (Antworttastatur über den Direktweg, ohne Eingriff in Hermes)
- services/ermittlung.py: Wächter meldet rote Hinweise an Lucy; Knopf wird Rückfrage, Lucy sieht über den
api_server nach und schickt Ursache und Weg als eine Nachricht
- services/wochenbericht.py + mc2-wochenbericht.timer (So 07:30): feste Sätze, Absatz vom Modell, offene
App-Updates als Rückfragen
- MCP: Werkzeuge fragen die Freiheiten (auf_bitte), neu: freiheiten, rueckfragen, rueckfrage_beantworten,
sicherheitsupdates_einspielen, snapshot_zurueckspielen, snapshots, geraet_logs, dienst_logs
- Ausführer-Aktion journal (nur lesend), POST /api/homelab/ziele/{id}/sicherheitsupdates
- Läufe des Homelabs mit flock (Oberfläche und Steward schreiben beide)
- Skill homelab-orchestrator, SOUL-Abschnitt als Kopie in deploy/nur-box
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
dd23f3fb4c
commit
12cefb427a
@@ -35,6 +35,8 @@ import re
|
||||
import threading
|
||||
import time
|
||||
import uuid
|
||||
from collections.abc import Iterator
|
||||
from contextlib import contextmanager
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
@@ -44,6 +46,11 @@ from kern.zeit import LOCAL_TZ
|
||||
from services import announce, update_verlauf
|
||||
from services.homelab import apps, arcane, inventar, kanal, karenz, sicherheit
|
||||
|
||||
try:
|
||||
import fcntl # Linux: Sperre über Prozessgrenzen
|
||||
except ImportError: # Windows (Entwicklung): nur die Thread-Sperre
|
||||
fcntl = None
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
WARTEN_NACH_UPDATE_S = 20
|
||||
@@ -74,8 +81,25 @@ def _laeufe() -> list[dict]:
|
||||
return daten if isinstance(daten, list) else []
|
||||
|
||||
|
||||
@contextmanager
|
||||
def _datei_sperre() -> Iterator[None]:
|
||||
"""Seit 25.09.2026 schreiben zwei Prozesse Läufe: die Oberfläche (Knöpfe) und der Steward (Wartungsfenster). Ohne
|
||||
flock könnte einer den Lauf des anderen mit einer älteren Liste überschreiben."""
|
||||
if fcntl is None:
|
||||
yield
|
||||
return
|
||||
pfad = _pfad().with_suffix(".lock")
|
||||
pfad.parent.mkdir(parents=True, exist_ok=True)
|
||||
with open(pfad, "a", encoding="utf-8") as f:
|
||||
fcntl.flock(f, fcntl.LOCK_EX)
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
fcntl.flock(f, fcntl.LOCK_UN)
|
||||
|
||||
|
||||
def _merken(lauf: dict) -> None:
|
||||
with _lock:
|
||||
with _lock, _datei_sperre():
|
||||
laeufe = [x for x in _laeufe() if x["id"] != lauf["id"]] + [lauf]
|
||||
_pfad().parent.mkdir(parents=True, exist_ok=True)
|
||||
tmp = _pfad().with_suffix(".tmp")
|
||||
|
||||
Reference in New Issue
Block a user