Discuss flow was hallucinating unrelated content when article
extraction returned empty or RAG pulled in orphan notes that looked
more relevant than the generic seed prompt.
- seed_article_discussion raises EmptyArticleError on empty body;
briefing and /news routes return 422 instead of staging an empty
synthetic tool result.
- build_context skips RAG auto-injection when user_message matches
ARTICLE_DISCUSS_SEED so the article IS the context on turn one;
follow-up turns keep RAG on.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Both the /news discuss button and the briefing discuss button now call a
shared seed_article_discussion() helper that stages the synthetic
read_article tool exchange and the conversational seed prompt — behavior
stays byte-identical across entry points. /news also auto-starts
generation so the chat screen lands on an in-flight stream.
First assistant reply in a seeded article conversation is persisted as a
Note (tags: article-summary + article topics) and backlinked via
rss_items.discussion_note_id, so the knowledge base stops being amnesiac
about articles the user has engaged with.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Discuss button on news cards was producing one-shot replies because
the model got the whole trafilatura blob dropped into history with a
canned "summarize and discuss this article" prompt — no length guard, no
prep, no invitation to converse. Large articles got silently truncated by
Ollama; small articles got a tepid reply.
This reworks discuss_article around a three-layer cache:
context_prepared → content_full → fresh trafilatura fetch
First click on a small article fetches once, writes through to both
caches, and passes the body straight into the synthetic read_article
tool-result. First click on a large article additionally runs a parallel
map step (services/article_context.py) that chunks the body on paragraph
boundaries, summarizes each ~8k chunk to ~300 words of dense factual
prose via the background model, and concatenates the summaries under
section headers — all pinned to num_ctx=16384 so the map step doesn't
itself fall victim to silent truncation. Repeat clicks on either path
skip straight to the chat turn.
The canned summary prompt is replaced with a conversational seed that
invites the user into an actual discussion rather than a one-shot
synopsis, matching the goal of "have a conversation about an article,
not just read it."
discuss_topic is intentionally left untouched — it's the multi-article
aggregation path and needs a separate rework. Follow-up task will decide
whether to retire it or rework it on the cached-context approach.
Closes task #106.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>