"""AA-045-F3 Patch fuer content_briefing.py:
- Auswahl nicht mehr nur director_action='pruefen', sondern alle postbaren
Signale ohne vorhandenes Briefing (idempotent).
- Fehlerstatus briefing_error bei technischem Fehlschlag.
- Ungeeignete Signale erhalten explizites briefing_freigabe-Setzung via
compute_briefing (bestehende Logik) - kein stiller Leerzustand.
"""
p = "/opt/struktur/social-media-radar/content_briefing.py"
s = open(p).read()
old_run = '''def run(limit: int = 500, action_filter: str = "pruefen"):
conn = sqlite3.connect(str(DB_PATH))
conn.row_factory = sqlite3.Row
ensure_columns(conn)
rows = conn.execute(
"SELECT * FROM signals WHERE director_action = ? ORDER BY director_score DESC LIMIT ?",
(action_filter, limit)
).fetchall()'''
new_run = '''def run(limit: int = 500, action_filter: str = ""):
"""AA-045-F3: Befuellt Briefings fuer alle postbaren Signale ohne Briefing.
Auswahl (idempotent, ueberschreibt keine vorhandenen Briefings):
- status nicht ignoriert/veroeffentlicht
- mallorca_relevance > 0 (fachliche Grundrelevanz)
- briefing_winkel leer (noch nie gebrieft) ODER action_filter explizit gesetzt
action_filter="" bedeutet: alle postbaren; ein gesetzter Wert behaelt das
alte Verhalten (nur diese director_action) fuer Speziallaeufe bei.
"""
conn = sqlite3.connect(str(DB_PATH))
conn.row_factory = sqlite3.Row
ensure_columns(conn)
if action_filter:
rows = conn.execute(
"SELECT * FROM signals WHERE director_action = ? ORDER BY director_score DESC LIMIT ?",
(action_filter, limit)
).fetchall()
else:
rows = conn.execute(
"""
SELECT * FROM signals
WHERE status NOT IN ('ignoriert', 'veroeffentlicht')
AND COALESCE(mallorca_relevance, 0) > 0
AND COALESCE(briefing_winkel, '') = ''
ORDER BY radar_score DESC LIMIT ?
""",
(limit,)
).fetchall()'''
assert old_run in s, "run-anchor fehlt"
s = s.replace(old_run, new_run)
# Fehlerstatus je Signal in der Update-Schleife
old_loop = ''' freigabe_dist = {}
for sig in rows:
result = compute_briefing(dict(sig))
conn.execute("""
UPDATE signals SET'''
new_loop = ''' freigabe_dist = {}
errors = 0
for sig in rows:
try:
result = compute_briefing(dict(sig))
except Exception as exc:
# AA-045-F3: expliziter Fehlerstatus, Retry beim naechsten Lauf moeglich
errors += 1
try:
conn.execute(
"UPDATE signals SET briefing_error = ? WHERE signal_id = ?",
(f"briefing-failed: {exc}"[:400], sig["signal_id"])
)
except Exception:
pass
continue
conn.execute(
"UPDATE signals SET briefing_error = '' WHERE signal_id = ?",
(sig["signal_id"],)
)
conn.execute("""
UPDATE signals SET'''
assert old_loop in s, "loop-anchor fehlt"
s = s.replace(old_loop, new_loop)
# Abschluss des Loops anpassen (Einrueckung der bestehenden execute-Fortsetzung bleibt,
# aber wir muessen den try-Block schliessen). Bestehende Struktur nach dem Loop-Body:
old_tail = ''' sig["signal_id"],
))
freigabe_dist[result["briefing_freigabe"]] = freigabe_dist.get("briefing_freigabe", result["briefing_freigabe"]) and freigabe_dist.get(result["briefing_freigabe"], 0) + 1'''
# Vorsicht: Original-Zeile ist die naechste; wir patchen sie exakt:
orig_tail = ''' sig["signal_id"],
))
freigabe_dist[result["briefing_freigabe"]] = freigabe_dist.get(result["briefing_freigabe"], 0) + 1'''
new_tail = ''' sig["signal_id"],
))
freigabe_dist[result["briefing_freigabe"]] = freigabe_dist.get(result["briefing_freigabe"], 0) + 1
# AA-045-F3: SOL-006 REGEL-02 auch im neuen Pfad ausfuehren
if result["briefing_freigabe"] in ("zurueckstellen", "verwerfen"):
conn.execute(
"UPDATE signals SET director_action = 'beobachten' "
"WHERE signal_id = ? AND director_action IN ('pruefen', 'veroeffentlichen')",
(sig["signal_id"],)
)'''
assert orig_tail in s, "tail-anchor fehlt"
s = s.replace(orig_tail, new_tail)
open(p, "w").write(s)
print("content_briefing.py gepatcht")