Skip to main content

ralph_workflow/git_helpers/repo/
diff_review.rs

1/// The level of truncation applied to a diff for review.
2///
3/// This enum tracks how much a diff has been abbreviated and determines
4/// what instructions should be given to the reviewer agent.
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
6pub enum DiffTruncationLevel {
7    /// No truncation - full diff is included
8    #[default]
9    Full,
10    /// Diff was semantically truncated - high-priority files shown, instruction to explore
11    Abbreviated,
12    /// Only file paths listed - instruction to explore each file's diff
13    FileList,
14    /// File list was abbreviated - instruction to explore and discover files
15    FileListAbbreviated,
16}
17
18/// The result of diff truncation for review purposes.
19///
20/// Contains both the potentially-truncated content and metadata about
21/// what truncation was applied, along with version context information.
22#[derive(Debug, Clone, PartialEq, Eq)]
23pub struct DiffReviewContent {
24    /// The content to include in the review prompt
25    pub content: String,
26    /// The level of truncation applied
27    pub truncation_level: DiffTruncationLevel,
28    /// Total number of files in the full diff (for context in messages)
29    pub total_file_count: usize,
30    /// Number of files shown in the abbreviated content (if applicable)
31    pub shown_file_count: Option<usize>,
32    /// The OID (commit SHA) that this diff is compared against (baseline)
33    pub baseline_oid: Option<String>,
34    /// Short form (first 8 chars) of the baseline OID for display
35    pub baseline_short: Option<String>,
36    /// Description of what the baseline represents (e.g., "review_baseline", "start_commit")
37    pub baseline_description: String,
38}
39
40impl DiffReviewContent {
41    /// Generate a human-readable header describing the diff's version context.
42    ///
43    /// This header is meant to be included at the beginning of the diff content
44    /// to provide clarity about what state of the code the diff represents.
45    ///
46    /// # Returns
47    ///
48    /// A formatted string like:
49    /// ```text
50    /// Diff Context: Compared against review_baseline abc12345
51    /// Current state: Working directory (includes unstaged changes)
52    /// ```
53    ///
54    /// If no baseline information is available, returns a generic message.
55    pub fn format_context_header(&self) -> String {
56        let mut lines = Vec::new();
57
58        if let Some(short) = &self.baseline_short {
59            lines.push(format!(
60                "Diff Context: Compared against {} {}",
61                self.baseline_description, short
62            ));
63        } else {
64            lines.push("Diff Context: Version information not available".to_string());
65        }
66
67        // Add information about truncation if applicable
68        match self.truncation_level {
69            DiffTruncationLevel::Full => {
70                // No truncation - full diff
71            }
72            DiffTruncationLevel::Abbreviated => {
73                lines.push(format!(
74                    "Note: Diff abbreviated - {}/{} files shown",
75                    self.shown_file_count.unwrap_or(0),
76                    self.total_file_count
77                ));
78            }
79            DiffTruncationLevel::FileList => {
80                lines.push(format!(
81                    "Note: Only file list shown - {} files changed",
82                    self.total_file_count
83                ));
84            }
85            DiffTruncationLevel::FileListAbbreviated => {
86                lines.push(format!(
87                    "Note: File list abbreviated - {}/{} files shown",
88                    self.shown_file_count.unwrap_or(0),
89                    self.total_file_count
90                ));
91            }
92        }
93
94        if lines.is_empty() {
95            String::new()
96        } else {
97            format!("{}\n", lines.join("\n"))
98        }
99    }
100}