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(" (Identify free blocks between events for focused work.)")
lines.append("") 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 [] rss = external_data.get("rss_items") or []
if rss: if rss:
lines.append("NEWS HIGHLIGHTS (weave 1-2 into your briefing naturally; the full list is shown separately):") # Group articles by their primary topic
for item in rss[:3]: clusters: dict[str, list[dict]] = {}
source = item.get("feed_title") or item.get("source") or "News" uncategorized: list[dict] = []
title = item.get("title", "") for item in rss:
excerpt = (item.get("content") or item.get("snippet") or "")[:500].strip() topics = item.get("topics") or []
lines.append(f" [{source}] {title}") if topics:
if excerpt: primary = topics[0]
lines.append(f" {excerpt}") 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("") lines.append("")
return "\n".join(lines) return "\n".join(lines)