feat(briefing): cluster news by topic for thematic synthesis instead of flat headlines

This commit is contained in:
2026-04-08 22:07:24 -04:00
parent 4558dd578a
commit a6543c1dc5
@@ -450,17 +450,38 @@ def _unified_user_prompt(internal_data: dict, external_data: dict, slot: str, te
lines.append(" (Identify free blocks between events for focused work.)")
lines.append("")
# News highlights (top 3 with excerpts — right panel shows full list)
# News — clustered by topic for thematic synthesis
rss = external_data.get("rss_items") or []
if rss:
lines.append("NEWS HIGHLIGHTS (weave 1-2 into your briefing naturally; the full list is shown separately):")
for item in rss[:3]:
source = item.get("feed_title") or item.get("source") or "News"
title = item.get("title", "")
excerpt = (item.get("content") or item.get("snippet") or "")[:500].strip()
lines.append(f" [{source}] {title}")
if excerpt:
lines.append(f" {excerpt}")
# Group articles by their primary topic
clusters: dict[str, list[dict]] = {}
uncategorized: list[dict] = []
for item in rss:
topics = item.get("topics") or []
if topics:
primary = topics[0]
clusters.setdefault(primary, []).append(item)
else:
uncategorized.append(item)
# Sort clusters by size (most articles = most active theme)
sorted_clusters = sorted(clusters.items(), key=lambda x: len(x[1]), reverse=True)
lines.append("NEWS THEMES (synthesize 1-2 themes into your briefing; mention article count per theme):")
for topic, items in sorted_clusters[:4]:
count = len(items)
titles = [i.get("title", "") for i in items[:3]]
sources = list({i.get("feed_title") or i.get("source") or "News" for i in items})
lines.append(f" [{topic.title()}] ({count} article{'s' if count != 1 else ''} from {', '.join(sources[:2])})")
for t in titles:
lines.append(f"{t}")
# Include one excerpt for the top cluster
if items == sorted_clusters[0][1]:
excerpt = (items[0].get("content") or items[0].get("snippet") or "")[:400].strip()
if excerpt:
lines.append(f" > {excerpt}")
if uncategorized:
lines.append(f" [Other] ({len(uncategorized)} uncategorized article{'s' if len(uncategorized) != 1 else ''})")
lines.append("")
return "\n".join(lines)