agpm_cli/resolver/backtracking/
types.rs

1//! Public types for backtracking results.
2//!
3//! This module contains the public types returned by the backtracking resolver.
4
5/// State of a single backtracking iteration.
6#[derive(Debug, Clone)]
7pub struct BacktrackingIteration {
8    /// Iteration number (1-indexed)
9    pub iteration: usize,
10
11    /// Conflicts detected at start of this iteration
12    pub conflicts: Vec<crate::version::conflict::VersionConflict>,
13
14    /// Updates applied during this iteration
15    pub updates: Vec<VersionUpdate>,
16
17    /// Number of transitive deps re-resolved
18    pub transitive_reresolutions: usize,
19
20    /// Whether this iteration made progress
21    pub made_progress: bool,
22}
23
24/// Reason for termination of backtracking.
25#[derive(Debug, Clone, PartialEq, Eq)]
26pub enum TerminationReason {
27    /// All conflicts successfully resolved
28    Success,
29
30    /// Reached maximum iteration limit
31    MaxIterations,
32
33    /// Reached timeout
34    Timeout,
35
36    /// No progress made (same conflicts as previous iteration)
37    NoProgress,
38
39    /// Detected oscillation (cycling between states)
40    Oscillation,
41
42    /// Failed to find compatible version
43    NoCompatibleVersion,
44}
45
46/// Result of a backtracking attempt.
47#[derive(Debug, Clone)]
48pub struct BacktrackingResult {
49    /// Whether conflicts were successfully resolved
50    pub resolved: bool,
51
52    /// List of ALL version updates made across all iterations
53    pub updates: Vec<VersionUpdate>,
54
55    /// Number of backtracking iterations performed
56    pub iterations: usize,
57
58    /// Total number of version resolutions attempted
59    pub attempted_versions: usize,
60
61    /// History of each iteration (for debugging/logging)
62    pub iteration_history: Vec<BacktrackingIteration>,
63
64    /// Total transitive deps re-resolved across all iterations
65    pub total_transitive_reresolutions: usize,
66
67    /// Reason for termination
68    pub termination_reason: TerminationReason,
69}
70
71/// Record of a version update made during backtracking.
72#[derive(Debug, Clone)]
73pub struct VersionUpdate {
74    /// Resource identifier (format: "source:required_by")
75    pub resource_id: String,
76
77    /// Original version constraint
78    pub old_version: String,
79
80    /// New version selected
81    pub new_version: String,
82
83    /// Original resolved SHA
84    pub old_sha: String,
85
86    /// New resolved SHA
87    pub new_sha: String,
88
89    /// Template variables (variant inputs) for this resource
90    pub variant_inputs: Option<serde_json::Value>,
91}
92
93#[cfg(test)]
94mod tests {
95    use super::*;
96
97    #[test]
98    fn test_backtracking_result_structure() {
99        let result = BacktrackingResult {
100            resolved: true,
101            updates: vec![VersionUpdate {
102                resource_id: "community:test".to_string(),
103                old_version: "v1.0.0".to_string(),
104                new_version: "v1.0.1".to_string(),
105                old_sha: "abc123".to_string(),
106                new_sha: "def456".to_string(),
107                variant_inputs: None,
108            }],
109            iterations: 1,
110            attempted_versions: 5,
111            iteration_history: vec![],
112            total_transitive_reresolutions: 0,
113            termination_reason: TerminationReason::Success,
114        };
115
116        assert!(result.resolved);
117        assert_eq!(result.updates.len(), 1);
118        assert_eq!(result.iterations, 1);
119        assert_eq!(result.attempted_versions, 5);
120        assert_eq!(result.termination_reason, TerminationReason::Success);
121    }
122}