Преглед изворни кода

merge: ultraclaw/green-contract into main

Jobdori пре 2 месеци
родитељ
комит
eff9404d30
2 измењених фајлова са 153 додато и 0 уклоњено
  1. 152 0
      rust/crates/runtime/src/green_contract.rs
  2. 1 0
      rust/crates/runtime/src/lib.rs

+ 152 - 0
rust/crates/runtime/src/green_contract.rs

@@ -0,0 +1,152 @@
+use serde::{Deserialize, Serialize};
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
+#[serde(rename_all = "snake_case")]
+pub enum GreenLevel {
+    TargetedTests,
+    Package,
+    Workspace,
+    MergeReady,
+}
+
+impl GreenLevel {
+    #[must_use]
+    pub fn as_str(self) -> &'static str {
+        match self {
+            Self::TargetedTests => "targeted_tests",
+            Self::Package => "package",
+            Self::Workspace => "workspace",
+            Self::MergeReady => "merge_ready",
+        }
+    }
+}
+
+impl std::fmt::Display for GreenLevel {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{}", self.as_str())
+    }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
+pub struct GreenContract {
+    pub required_level: GreenLevel,
+}
+
+impl GreenContract {
+    #[must_use]
+    pub fn new(required_level: GreenLevel) -> Self {
+        Self { required_level }
+    }
+
+    #[must_use]
+    pub fn evaluate(self, observed_level: Option<GreenLevel>) -> GreenContractOutcome {
+        match observed_level {
+            Some(level) if level >= self.required_level => GreenContractOutcome::Satisfied {
+                required_level: self.required_level,
+                observed_level: level,
+            },
+            _ => GreenContractOutcome::Unsatisfied {
+                required_level: self.required_level,
+                observed_level,
+            },
+        }
+    }
+
+    #[must_use]
+    pub fn is_satisfied_by(self, observed_level: GreenLevel) -> bool {
+        observed_level >= self.required_level
+    }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
+#[serde(tag = "outcome", rename_all = "snake_case")]
+pub enum GreenContractOutcome {
+    Satisfied {
+        required_level: GreenLevel,
+        observed_level: GreenLevel,
+    },
+    Unsatisfied {
+        required_level: GreenLevel,
+        observed_level: Option<GreenLevel>,
+    },
+}
+
+impl GreenContractOutcome {
+    #[must_use]
+    pub fn is_satisfied(&self) -> bool {
+        matches!(self, Self::Satisfied { .. })
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn given_matching_level_when_evaluating_contract_then_it_is_satisfied() {
+        // given
+        let contract = GreenContract::new(GreenLevel::Package);
+
+        // when
+        let outcome = contract.evaluate(Some(GreenLevel::Package));
+
+        // then
+        assert_eq!(
+            outcome,
+            GreenContractOutcome::Satisfied {
+                required_level: GreenLevel::Package,
+                observed_level: GreenLevel::Package,
+            }
+        );
+        assert!(outcome.is_satisfied());
+    }
+
+    #[test]
+    fn given_higher_level_when_checking_requirement_then_it_still_satisfies_contract() {
+        // given
+        let contract = GreenContract::new(GreenLevel::TargetedTests);
+
+        // when
+        let is_satisfied = contract.is_satisfied_by(GreenLevel::Workspace);
+
+        // then
+        assert!(is_satisfied);
+    }
+
+    #[test]
+    fn given_lower_level_when_evaluating_contract_then_it_is_unsatisfied() {
+        // given
+        let contract = GreenContract::new(GreenLevel::Workspace);
+
+        // when
+        let outcome = contract.evaluate(Some(GreenLevel::Package));
+
+        // then
+        assert_eq!(
+            outcome,
+            GreenContractOutcome::Unsatisfied {
+                required_level: GreenLevel::Workspace,
+                observed_level: Some(GreenLevel::Package),
+            }
+        );
+        assert!(!outcome.is_satisfied());
+    }
+
+    #[test]
+    fn given_no_green_level_when_evaluating_contract_then_contract_is_unsatisfied() {
+        // given
+        let contract = GreenContract::new(GreenLevel::MergeReady);
+
+        // when
+        let outcome = contract.evaluate(None);
+
+        // then
+        assert_eq!(
+            outcome,
+            GreenContractOutcome::Unsatisfied {
+                required_level: GreenLevel::MergeReady,
+                observed_level: None,
+            }
+        );
+    }
+}

+ 1 - 0
rust/crates/runtime/src/lib.rs

@@ -5,6 +5,7 @@ mod compact;
 mod config;
 mod conversation;
 mod file_ops;
+pub mod green_contract;
 mod hooks;
 mod json;
 pub mod lsp_client;