diff --git a/app.py b/app.py index ed9ad5c..4c14047 100644 --- a/app.py +++ b/app.py @@ -2108,7 +2108,7 @@ def process_beat_tasks(): # Konvertiere zu Dict-Format für Legacy-Kompatibilität pending_tasks = [] for db_task in db_tasks: - if db_task.get('type') in ('agent_created', 'manual', 'orchestrated', 'agent_delegated', 'telegram', 'agent_subtask', 'standup', 'broadcast'): + if db_task.get('type') in ('agent_created', 'manual', 'orchestrated', 'agent_delegated', 'telegram', 'agent_subtask', 'broadcast'): pending_tasks.append(db_task) for task in pending_tasks: @@ -2405,12 +2405,43 @@ def start_orchestrator_beat(): # ── DAILY STANDUP ───────────────────────────────────────────────────────────── +_standup_lock = threading.Lock() + def trigger_daily_standup(): """ Tägliches Standup: Orchestrator fragt alle Team-Members nach Updates und delegiert anschließend Wissensupdates an alle Agenten. + Gegen Doppel-Trigger gesichert: nur ein Standup pro Tag möglich. """ - logger.info("[DailyStandup] Starte tägliches Standup...") + # Nur einen gleichzeitigen Standup erlauben + if not _standup_lock.acquire(blocking=False): + logger.warning("[DailyStandup] Bereits aktiv — zweiter Trigger ignoriert.") + return + + try: + # Prüfe ob heute schon ein Standup läuft oder abgeschlossen ist + today_str = datetime.now().strftime('%Y-%m-%d') + try: + con = sqlite3.connect(EMAIL_JOURNAL_DB) + existing = con.execute( + "SELECT id FROM tasks WHERE type='standup' AND created_at LIKE ? AND status != 'error'", + (f"{today_str}%",) + ).fetchone() + con.close() + except Exception: + existing = None + + if existing: + logger.warning("[DailyStandup] Standup für heute (Task #%s) bereits vorhanden — abgebrochen.", existing['id'] if existing else '?') + return + + logger.info("[DailyStandup] Starte tägliches Standup...") + _trigger_daily_standup_inner() + finally: + _standup_lock.release() + + +def _trigger_daily_standup_inner(): # Team-Members aus DB holen try: