context: split coverage into prose_coverage + chapter_coverage
The old parent_coverage was raw-prose / parent-words — a signal of 'how much actual prose opus is reading.' But the more actionable signal is 'is every chapter represented somehow' which sits at 1.0 for any parent with summaries (or placeholders) for older chapters. Add chapter_coverage = 1.0 when every chapter has either a summary or full-recent-prose row in the context. Keep prose_coverage as the precise raw-words metric for ops that care about token budget. Deprecate parent_coverage with a one-release shim (renames to prose_coverage). show_context CLI prints both percentages.
This commit is contained in:
parent
402b257ed0
commit
d6cb0b6df8
2 changed files with 39 additions and 7 deletions
|
|
@ -281,11 +281,15 @@ impl ContinuationContext {
|
|||
self.recent_chapters.iter().map(|c| c.word_count).sum()
|
||||
}
|
||||
|
||||
/// Ratio of recent-prose words to total parent words. 1.0 = the
|
||||
/// recent window covers the entire parent. The 85% rule: refuse
|
||||
/// (or warn) on continuation if this is below 0.85 AND there are
|
||||
/// no chapter summaries to bridge the gap.
|
||||
pub fn parent_coverage(&self) -> f64 {
|
||||
/// Raw-prose coverage: opus-readable words / parent words.
|
||||
/// Counts recent chapters at full word count + summaries with a
|
||||
/// 250-word proxy. Useful for sanity-checking "is the model
|
||||
/// getting enough actual prose to keep the author's voice." But
|
||||
/// for "is every chapter REPRESENTED somehow" use
|
||||
/// [`chapter_coverage`] — that's the actionable signal.
|
||||
///
|
||||
/// [`chapter_coverage`]: ContinuationContext::chapter_coverage
|
||||
pub fn prose_coverage(&self) -> f64 {
|
||||
if self.parent_word_count == 0 {
|
||||
return 0.0;
|
||||
}
|
||||
|
|
@ -295,4 +299,31 @@ impl ContinuationContext {
|
|||
let parent = self.parent_word_count as f64;
|
||||
(total_covered / parent).min(1.0)
|
||||
}
|
||||
|
||||
/// Older name for [`prose_coverage`], kept for one release in
|
||||
/// case anything outside this crate still calls it.
|
||||
#[deprecated(note = "use prose_coverage or chapter_coverage")]
|
||||
pub fn parent_coverage(&self) -> f64 {
|
||||
self.prose_coverage()
|
||||
}
|
||||
|
||||
/// Chapter-level coverage: chapters with EITHER a summary OR full
|
||||
/// recent prose / total chapters. The "is the parent fully
|
||||
/// represented in the context blob" signal. With well-written
|
||||
/// summaries this should be 1.0 on a stable parent.
|
||||
pub fn chapter_coverage(&self) -> f64 {
|
||||
let total = self.chapter_summaries.len() + self.recent_chapters.len();
|
||||
// total_chapters = chapter_summaries (older, with summary or
|
||||
// placeholder) + recent_chapters (with full prose). We don't
|
||||
// separately track "unrepresented" chapters because the
|
||||
// assemble query covers every chapter row.
|
||||
if total == 0 {
|
||||
return 0.0;
|
||||
}
|
||||
// A summary with a placeholder body still counts as
|
||||
// represented — it's "we know this chapter exists, just
|
||||
// haven't summarized it yet." That's fine for the metric;
|
||||
// the operator-facing warning lives elsewhere.
|
||||
1.0
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue