Curation v2 step 6: Behind the paper, stats, run report block, lock

Behind-the-paper chapter (behind.xhtml, both editions) built from the run's
StageCounts and candidate_runs near misses; daily-epub stats [--days N];
StageCounts gains knn/feed gates and verdicts_in_prompt, timings split
into summaries + brief, the four-line §15.4 info block logged once per
run and printed by print_report; src/lock.rs flock guard on
<database_path>.lock for generate, profile rebuild, features backfill and
backfill-social; README updated for the new CLI, env vars and costs.

Implemented by a Claude agent from docs/plans/curation-v2-briefs/step6.md;
reviewed against plan §5, §15.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1rCLQeKBgnBo3oTgHuTMe
This commit is contained in:
thalladaandClaude Fable 5.1 committed 2026-09-02 16:21:06 +00:00
1 parent 05a74a0dcf
commit d261cd485d
22 files changed
+1583 -113

No files matched your search

+8 -5
View File
@@ -1,7 +1,8 @@
//! Chapter ordering and `epub-builder` assembly (spec §3.10).
//!
//! Structure: cover → From the Editor → In This Issue → sections (title page,
//! article chapters, discussion chapters) → World Briefing → colophon. The
//! Structure: cover → The Brief → In This Issue → sections (title page,
//! article chapters, discussion chapters) → World Briefing → Behind the paper
//! → colophon. The
//! chapters themselves are rendered by [`super::chapters`] and the cover by
//! [`super::cover`]; this module decides the order and zips the result.
@@ -14,8 +15,8 @@ use crate::types::{Edition, ImageAsset, Issue};
use super::EpubError;
use super::chapters::{
render_colophon, render_front_page, render_in_this_issue, render_section_page,
render_world_briefing, section_names,
render_behind_the_paper, render_colophon, render_front_page, render_in_this_issue,
render_section_page, render_world_briefing, section_names,
};
use super::cover::{CoverAsset, render_cover_page};
use super::x4;
@@ -85,6 +86,7 @@ pub fn render_all(
if let Some(world) = render_world_briefing(issue)? {
chapters.push(world);
}
chapters.push(render_behind_the_paper(issue)?);
chapters.push(render_colophon(issue)?);
if edition == Edition::X4 {
@@ -272,11 +274,12 @@ mod tests {
"sec-Niche Corner",
"art-1002",
"world",
"behind",
"colophon",
]
);
let levels: Vec<u8> = chapters.iter().map(|c| c.toc_level).collect();
assert_eq!(levels, vec![1, 1, 1, 1, 2, 3, 1, 2, 1, 1]);
assert_eq!(levels, vec![1, 1, 1, 1, 2, 3, 1, 2, 1, 1, 1]);
for chapter in &chapters {
assert_xml_ok(&chapter.xhtml);
}