Article pages: structured "Why it belongs" editorial read
Per Codex — make /a/<id> feel like Upbeat Bytes has editorial judgment, not just a summary wrapper. Trust-building, short, not an essay. * article_summaries gains what_happened / why_matters / why_belongs (+ migration). * summarize.explain_article: a separate, fallback-able LLM pass producing three short notes (parsed from a labelled WHAT/MATTERS/BELONGS format). generate_summary now stores them alongside the summary, and tops up older summaries on next view. get_explanation returns them only when all three are present. * API: share_page + /api/summary expose the explanation. * share.py: renders the three-part section (accent rule) when complete; otherwise the single "Why it's here" reason line is the calm fallback. The page polls and swaps in both the summary and the section as they cache. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+9
-5
@@ -886,9 +886,12 @@ def create_app() -> FastAPI:
|
||||
if not row or row["duplicate_of"] is not None or not row["accepted"]:
|
||||
return not_found
|
||||
summary = summarize.get_summary(conn, aid)
|
||||
if not summary:
|
||||
_kick_summary(aid, background_tasks) # generate for next time; page polls
|
||||
return HTMLResponse(share.render_share_page(dict(row), PUBLIC_BASE_URL, summary=summary))
|
||||
explanation = summarize.get_explanation(conn, aid)
|
||||
if not summary or not explanation:
|
||||
_kick_summary(aid, background_tasks) # generate/top-up for next time; page polls
|
||||
return HTMLResponse(
|
||||
share.render_share_page(dict(row), PUBLIC_BASE_URL, summary=summary, explanation=explanation)
|
||||
)
|
||||
|
||||
# --- Privacy-respecting first-party analytics -------------------------
|
||||
|
||||
@@ -1243,10 +1246,11 @@ def create_app() -> FastAPI:
|
||||
def article_summary(article_id: int, background_tasks: BackgroundTasks) -> dict:
|
||||
with get_conn() as conn:
|
||||
summary = summarize.get_summary(conn, article_id)
|
||||
explanation = summarize.get_explanation(conn, article_id)
|
||||
if summary:
|
||||
return {"status": "ready", "summary": summary}
|
||||
return {"status": "ready", "summary": summary, "explanation": explanation}
|
||||
_kick_summary(article_id, background_tasks)
|
||||
return {"status": "pending", "summary": None}
|
||||
return {"status": "pending", "summary": None, "explanation": None}
|
||||
|
||||
@app.get("/today", response_class=HTMLResponse)
|
||||
def today_digest() -> HTMLResponse:
|
||||
|
||||
Reference in New Issue
Block a user