Option A: typographic editorial tiles + single treated hero image; balance brief topics

Frontend (the premium baseline):
- The hero is now the ONLY image slot. Soft feed images get an atmospheric
  gradient overlay; no over-reliance on inconsistent RSS image quality.
- Every secondary/lane card is a uniform typographic editorial tile: no
  thumbnails, equal visual weight, a faint topic wordmark watermark, a slim
  sage top accent, consistent source, reason text as the trust signal, visible
  Replace with quiet tuning actions. Fixes the jarring mixed-media row rhythm
  and removes muddy thumbnails entirely.

Backend (composition):
- _select_diverse now balances topics: no more than 2 of one topic while other
  topics have candidates (relaxing source then topic caps only to fill), so the
  daily five stop clustering medical/science items. Candidates now carry s.topic.

Tests updated for the topic-balance contract (79 total).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
jay
2026-05-31 12:10:05 +00:00
parent ba801d90f6
commit 541f59ed6e
4 changed files with 107 additions and 118 deletions
+26 -31
View File
@@ -1,50 +1,45 @@
from goodnews.briefs import _select_diverse
def row(id, source, category):
# _select_diverse only reads these three keys; plain dicts support [] access.
return {"id": id, "source_name": source, "default_category": category}
def row(id, source, topic):
# _select_diverse reads id, source_name, topic; plain dicts support [] access.
return {"id": id, "source_name": source, "topic": topic}
def test_prefers_distinct_sources_best_first():
rows = [
row(1, "A", "science"),
row(2, "A", "science"), # same source as #1 — should be skipped while others remain
row(3, "B", "science"),
row(2, "A", "science"), # same source as #1 — skipped while others remain
row(3, "B", "health"),
row(4, "C", "environment"),
]
selected = _select_diverse(rows, limit=3)
ids = [r["id"] for r in selected]
assert ids == [1, 3, 4] # one per source, ranked order preserved
assert [r["id"] for r in _select_diverse(rows, limit=3)] == [1, 3, 4]
def test_backfills_when_sources_exhausted():
rows = [row(1, "A", "science"), row(2, "A", "science"), row(3, "A", "science")]
selected = _select_diverse(rows, limit=2)
assert len(selected) == 2 # repeats source A only because no others exist
def test_injects_second_category_without_shrinking():
def test_caps_a_topic_when_alternatives_exist():
rows = [
row(1, "A", "science"),
row(2, "B", "science"),
row(3, "C", "science"),
row(4, "D", "environment"), # the only other category, lowest ranked
row(1, "A", "science"), row(2, "B", "science"),
row(3, "C", "science"), row(4, "D", "science"),
row(5, "E", "community"), row(6, "F", "animals"), row(7, "G", "culture"),
]
selected = _select_diverse(rows, limit=3)
cats = {r["default_category"] for r in selected}
assert len(selected) == 3
assert len(cats) >= 2 # environment swapped in for diversity
assert any(r["default_category"] == "environment" for r in selected)
selected = _select_diverse(rows, limit=5, max_per_topic=2)
topics = [r["topic"] for r in selected]
assert len(selected) == 5
assert topics.count("science") == 2 # capped, even though 4 were available
assert {"community", "animals", "culture"} <= set(topics)
def test_keeps_single_category_when_no_alternative_exists():
rows = [row(1, "A", "science"), row(2, "B", "science"), row(3, "C", "science")]
selected = _select_diverse(rows, limit=3)
assert len(selected) == 3
assert {r["default_category"] for r in selected} == {"science"}
def test_relaxes_cap_when_only_one_topic_available():
rows = [row(i, f"S{i}", "science") for i in range(1, 6)]
selected = _select_diverse(rows, limit=5)
assert len(selected) == 5 # all science: cap relaxed because nothing else exists
def test_never_returns_more_than_limit():
rows = [row(i, f"S{i}", "science") for i in range(10)]
def test_backfills_repeating_source_when_needed():
rows = [row(1, "A", "science"), row(2, "A", "science"), row(3, "A", "science")]
assert len(_select_diverse(rows, limit=2)) == 2
def test_never_exceeds_limit():
rows = [row(i, f"S{i}", "science") for i in range(20)]
assert len(_select_diverse(rows, limit=5)) == 5