Show what the pipeline understood about each article

A muted one-line note now follows every article: the deep assessment's
topic group, format, depth and technicality, the specific topics it
extracted, and the reader interests the article matched best, e.g.

  Software engineering · analysis essay · in depth · highly technical ·
  Topics: copy-on-write, ZFS · Interests: Filesystems, Rust

It renders on the web article page footer, on the public and private
issue-page entries, in the EPUB article footer and in the EPUB "In This
Issue" index (both editions), always styled like the existing meta lines
so it stays secondary to the content.

`Pick` gains `top_interests` (serde default, no migration), filled from
the signals stage when the editor assembles the lineup; the facets were
already on the issue snapshot via `Pick.llm`, so earlier issues show the
facet and topic parts and only future issues carry interests. One shared
builder, `understanding_line` in epub::chapters, feeds every surface.

The dev seed gives four picks facets and interests so the line can be
eyeballed locally.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QVPagF6jfDv78CC5Jv2wp4
This commit is contained in:
2026-09-08 19:44:00 +00:00
co-authored by Claude Fable 5.1
parent 7ce8c65939
commit bedbcb218f
17 changed files with 285 additions and 12 deletions
+20 -1
View File
@@ -88,7 +88,25 @@ pub fn issue() -> Issue {
is_lead: true,
why: Some("The systems story with enough operational detail to matter".into()),
summary: Some("What it argues, and why it is worth the time.".into()),
llm: None,
llm: Some(Deep {
quality: 9.0,
fit: 9.0,
category: Some("Tech & Engineering".into()),
rationale: "Detailed systems analysis".into(),
paywalled_guess: false,
facets: Facets {
format: Some("analysis_essay".into()),
depth: Some("deep".into()),
topic_group: Some("software_engineering".into()),
technicality: Some("advanced".into()),
specific_topics: Some(vec!["copy-on-write".into(), "ZFS".into()]),
..Facets::default()
},
model: "fixture-model".into(),
prompt_version: 2,
assessed_at: timestamp(),
}),
top_interests: vec!["Filesystems".into(), "Rust".into()],
discussion: Some(discussion(1, 1001)),
};
let second = Pick {
@@ -99,6 +117,7 @@ pub fn issue() -> Issue {
why: Some("A small-scene delight outside the usual technical orbit".into()),
summary: None,
llm: None,
top_interests: Vec::new(),
discussion: None,
};
let mut summaries = BTreeMap::new();