From dd7b5236805cdf16431b3a9fadc9f39cfb2f6a8e Mon Sep 17 00:00:00 2001 From: Sephyi Date: Sun, 19 Apr 2026 19:02:12 +0200 Subject: [PATCH] fix(history): round float-to-int percentage conversion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The commit-type percentage shown in the project-style prompt section was computed by truncating a float cast (`as u32`), which discards the fractional part — 66.666% became 66% instead of 67%. Replace the truncating cast with `.round() as u32` so percentages round to the nearest integer, matching what users reading the prompt would expect. Add a unit test covering the round-up case (2/3 → 67%) alongside the exact-percentage case (1/3 → 33%) to guard against accidental regression to truncation. Closes audit entry F-027 from #3. --- src/services/history.rs | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/services/history.rs b/src/services/history.rs index e562b8f..68c4684 100644 --- a/src/services/history.rs +++ b/src/services/history.rs @@ -46,7 +46,7 @@ impl HistoryContext { .iter() .map(|(t, c)| { let pct = if total > 0 { - (*c as f32 / total as f32 * 100.0) as u32 + (*c as f32 / total as f32 * 100.0).round() as u32 } else { 0 }; @@ -427,6 +427,33 @@ mod tests { assert!(!ctx.uses_lowercase); // Below 80% threshold } + #[test] + fn to_prompt_section_rounds_percentages() { + // 2/3 = 66.666...% — truncation yields 66, rounding yields 67. + // 1/3 = 33.333...% — both rounding and truncation yield 33. + let ctx = HistoryContext { + type_distribution: vec![("feat".to_string(), 2), ("fix".to_string(), 1)], + scope_patterns: vec![], + avg_subject_length: 40, + uses_lowercase: true, + conventional_ratio: 1.0, + sample_subjects: vec![], + }; + + let section = ctx.to_prompt_section(10); + + assert!( + section.contains("feat (67%)"), + "expected rounded percentage 67% for 2/3, got: {}", + section + ); + assert!( + section.contains("fix (33%)"), + "expected 33% for 1/3, got: {}", + section + ); + } + #[test] fn to_prompt_section_format() { let ctx = HistoryContext {