feat(public-mood): Stimmungs-Kachel aus Foren-Quellen
Eigene Pipeline-Stufe nach factcheck, vor summary, die Foren-Artikel (media_type='forum') zu einer Themen-Zusammenfassung verarbeitet. Wird als separate Dashboard-Kachel "Öffentliche Stimmung" angezeigt — getrennt von Lagebild und Faktencheck, damit anonyme Forenposts nicht mit belegter Faktenlage verwechselt werden. - DB-Migration: incidents.public_mood (TEXT) + public_mood_updated_at (TS). - pipeline_tracker: neuer Pipeline-Step "public_mood" (DE/EN-Labels). - analyzer.generate_public_mood: Haiku-Call der Foren-Beitraege pro Quelle gruppiert und 3-6 thematische Bullets erzeugt, mit expliziter Quellen- Herkunft pro Bullet. Bei zu duennem Material gibt's keinen Output. - orchestrator: neuer Schritt zwischen Factcheck und Summary. Laedt alle Foren-Artikel der Lage (via JOIN auf sources), uebergibt sie an den Stimmungs-Agent, speichert den Markdown-Text in incidents.public_mood. - Topic-Filter (analyzer.filter_relevant_articles) markiert Foren-Quellen mit [FORUM]-Tag und bekommt im Prompt die Regel, Foren-Artikel weicher zu bewerten (Lage-Keyword im Titel reicht). Sie sollen in der Stimmungs- Kachel landen, nicht voreilig verworfen werden. - IncidentResponse-Modell: public_mood/public_mood_updated_at ergaenzt. - Frontend: neuer Tab "Öffentliche Stimmung" (nur sichtbar wenn Inhalt da), eigene Kachel mit Warn-Hinweis "keine Faktenlage". UI.renderPublicMood als einfacher Bullet-Renderer. - dashboard.html Cache-Buster fuer components.js + app.js gebumpt. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Dieser Commit ist enthalten in:
@@ -813,6 +813,26 @@ const UI = {
|
||||
return html;
|
||||
},
|
||||
|
||||
/**
|
||||
* Rendert die "Öffentliche Stimmung"-Kachel.
|
||||
* Eingabe ist Markdown mit "- "-Bullets (vom AnalyzerAgent.generate_public_mood).
|
||||
* Quellen-Pills brauchen wir hier nicht — die Bullet-Texte nennen die Foren-Herkunft
|
||||
* explizit ("auf 5ch /seiji/ ...", "Hatena-Kommentare betonen ...").
|
||||
*/
|
||||
renderPublicMood(text) {
|
||||
if (!text) return '<span style="color:var(--text-disabled);">Noch kein Stimmungsbild erfasst.</span>';
|
||||
const bulletLines = text.split("\n").map(l => l.trim()).filter(l => l.startsWith("- "));
|
||||
if (bulletLines.length === 0) {
|
||||
// Fliesstext-Fallback: HTML-escapen + Zeilenumbrueche
|
||||
return this.escape(text).replace(/\n/g, '<br>');
|
||||
}
|
||||
const items = bulletLines.map(l => {
|
||||
const body = l.replace(/^-\s+/, '');
|
||||
return `<li>${this.escape(body)}</li>`;
|
||||
}).join('');
|
||||
return `<ul style="margin:4px 0 4px 18px;line-height:1.7;">${items}</ul>`;
|
||||
},
|
||||
|
||||
/**
|
||||
* Rendert "Neueste Entwicklungen" für Live-Monitoring (adhoc).
|
||||
* Erwartet Bullets im Format "- [DD.MM. HH:MM] Text {Quelle1, Quelle2}".
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren