diff --git a/crates/solstone-linux/src/capture_stats.rs b/crates/solstone-linux/src/capture_stats.rs index 9805f0e..1a6a258 100644 --- a/crates/solstone-linux/src/capture_stats.rs +++ b/crates/solstone-linux/src/capture_stats.rs @@ -188,17 +188,18 @@ pub fn compute_quarantine_stats(root: &Path, now: f64) -> QuarantineStats { } } +/// A held segment has two possible histories and the suffix does not record which: the +/// journal declined it, or startup recovery could not finalize an interrupted one and it +/// was never sent at all. Naming either cause asserts something we cannot know — say only +/// what is true of both, which is that the segment is held and will not be retried. pub fn format_quarantine_line(stats: &QuarantineStats) -> Option { if stats.count == 0 { return None; } match stats.oldest_age_seconds { - None => Some(format!( - "Quarantine: {} rejected segment(s) held", - stats.count - )), + None => Some(format!("Held: {} segment(s) not sent", stats.count)), Some(age) => Some(format!( - "Quarantine: {} rejected segment(s) held, oldest {}d", + "Held: {} segment(s) not sent, oldest {}d", stats.count, (age / 86_400.0) as u64 )), @@ -309,7 +310,7 @@ mod tests { oldest_age_seconds: None }) .as_deref(), - Some("Quarantine: 2 rejected segment(s) held") + Some("Held: 2 segment(s) not sent") ); } #[test] @@ -320,7 +321,7 @@ mod tests { oldest_age_seconds: Some(5.9 * 86_400.0) }) .as_deref(), - Some("Quarantine: 2 rejected segment(s) held, oldest 5d") + Some("Held: 2 segment(s) not sent, oldest 5d") ); } // AC: injected now clamps future mtimes to zero age. diff --git a/crates/solstone-linux/src/doctor.rs b/crates/solstone-linux/src/doctor.rs index 39aaca1..7bfc32e 100644 --- a/crates/solstone-linux/src/doctor.rs +++ b/crates/solstone-linux/src/doctor.rs @@ -548,15 +548,19 @@ mod tests { // tests/test_doctor.py::test_run_doctor_omits_empty_quarantine_line #[test] fn quarantine_optional() { - for value in [Some("Quarantine: 1 rejected segment(s) held".into()), None] { + for value in [Some("Held: 1 segment(s) not sent".to_owned()), None] { let mut checks = FakeChecks::all(Severity::Ok); checks.quarantine = value.clone(); let mut out = Vec::new(); run_doctor(&mut checks, &mut out); - assert_eq!( - String::from_utf8(out).unwrap().contains("Quarantine:"), - value.is_some() - ); + let rendered = String::from_utf8(out).unwrap(); + // Assert against the fixture itself rather than a separately-copied literal: + // the previous form pinned its own substring and silently stopped matching the + // line it was meant to be checking when that line's wording changed. + match &value { + Some(line) => assert!(rendered.contains(line.as_str())), + None => assert!(!rendered.contains("segment(s) not sent")), + } } } // AC: aggregation keeps warnings non-fatal and failures fatal for each warn-capable slot.