Crisp hero (prefer og:image), 7-card Highlights, no-recycle Replace + session History

- Hero blur fix: brief enrichment now prefers a page's og:image even when a
  feed thumbnail exists (feed thumbs are often tiny; the hero is shown large).
  Verified: BBC hero upgrades to the 1024px share image, ScienceDaily to 1920px.
- Today is now 'Highlights from Today' — hero + 6 (brief size 7), which also
  makes the secondary grid a balanced 3+3 instead of an orphaned 3+1.
- Replace now excludes every article seen this session (a client-side seen-set),
  so it never cycles back to something already shown.
- New session History panel (this tab only, no account): lists everything seen,
  including swapped-away stories, so they stay recoverable. Persistent
  history/favorites are tabled for sign-in later.

Tests: og:image upgrade of an existing feed image (86 total).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
jay
2026-05-31 12:56:57 +00:00
parent 9e8eddf46d
commit d8d665ee35
6 changed files with 111 additions and 37 deletions
+3 -3
View File
@@ -139,7 +139,7 @@ def main() -> None:
brief_parser = subparsers.add_parser("build-brief", help="Build/freeze a daily brief")
brief_parser.add_argument("--date", help="Brief date in YYYY-MM-DD format; defaults to today")
brief_parser.add_argument("--limit", type=int, default=5)
brief_parser.add_argument("--limit", type=int, default=7)
brief_parser.add_argument("--replace", action="store_true")
show_brief_parser = subparsers.add_parser("show-brief", help="Show a stored daily brief")
@@ -446,7 +446,7 @@ def _run_cycle_locked(conn: sqlite3.Connection, args: argparse.Namespace) -> Non
if not args.no_brief:
today = date.today().isoformat()
try:
brief_id = build_daily_brief(conn, brief_date=today, limit=5, replace=True)
brief_id = build_daily_brief(conn, brief_date=today, limit=7, replace=True)
found = enrich_brief_images(conn, today)
print(f"brief: rebuilt {today} (id {brief_id}); {found} hero image(s) enriched")
except Exception as exc:
@@ -672,7 +672,7 @@ def print_brief(rows: list[sqlite3.Row]) -> None:
print("No brief items found.")
return
date = rows[0]["brief_date"]
print(f"Five Good Things Today - {date}")
print(f"Highlights from Today - {date}")
for row in rows:
print(f"{row['rank']}. {row['title']}")
print(f" {row['source_name']} | {row['default_category']} | {row['model_name']}")