zeroclaw_config/
autonomy.rs1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
9#[cfg_attr(feature = "schema-export", derive(schemars::JsonSchema))]
10#[serde(rename_all = "lowercase")]
11pub enum AutonomyLevel {
12 ReadOnly,
14 #[default]
16 Supervised,
17 Full,
19}
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
23#[cfg_attr(feature = "schema-export", derive(schemars::JsonSchema))]
24#[serde(rename_all = "lowercase")]
25pub enum DelegationMode {
26 #[default]
28 Forbidden,
29 Allow,
31}
32
33impl crate::config::HasPropKind for DelegationMode {
34 const PROP_KIND: crate::config::PropKind = crate::config::PropKind::Enum;
35}
36
37#[derive(
47 Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default, zeroclaw_macros::Configurable,
48)]
49#[cfg_attr(feature = "schema-export", derive(schemars::JsonSchema))]
50pub struct DelegationPolicy {
51 #[serde(default)]
52 pub mode: DelegationMode,
53}
54
55impl DelegationPolicy {
56 pub fn permits(&self) -> bool {
60 matches!(self.mode, DelegationMode::Allow)
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67
68 #[test]
69 fn delegation_default_is_forbidden() {
70 assert_eq!(DelegationPolicy::default().mode, DelegationMode::Forbidden);
71 assert!(!DelegationPolicy::default().permits());
72 }
73
74 #[test]
75 fn delegation_allow_permits() {
76 let p = DelegationPolicy {
77 mode: DelegationMode::Allow,
78 };
79 assert!(p.permits());
80 assert!(!DelegationPolicy::default().permits());
81 }
82
83 #[test]
84 fn delegation_wire_format() {
85 let forbidden = toml::to_string(&DelegationPolicy::default()).unwrap();
87 assert!(forbidden.contains("mode = \"forbidden\""), "{forbidden}");
88
89 let allow = DelegationPolicy {
91 mode: DelegationMode::Allow,
92 };
93 let s = toml::to_string(&allow).unwrap();
94 assert!(s.contains("mode = \"allow\""), "{s}");
95 let back: DelegationPolicy = toml::from_str(&s).unwrap();
96 assert_eq!(back, allow);
97 }
98}
99
100#[cfg(test)]
101mod prop_exposure_tests {
102 use crate::schema::RiskProfileConfig;
103 use crate::traits::PropKind;
104
105 #[test]
106 fn delegation_policy_exposes_mode_enum_leaf() {
107 let p = RiskProfileConfig::default();
108 let mode = p
109 .prop_fields()
110 .into_iter()
111 .find(|f| f.name.ends_with("delegation_policy.mode"))
112 .expect("delegation_policy.mode leaf missing");
113 assert_eq!(mode.kind, PropKind::Enum);
114 }
115}
116
117#[cfg(all(test, feature = "schema-export"))]
118mod enum_variant_tests {
119 use super::DelegationMode;
120 use crate::schema::RiskProfileConfig;
121
122 #[test]
123 fn delegation_mode_variants_surface() {
124 let v = crate::helpers::enum_variants::<DelegationMode>();
125 assert!(v.contains("forbidden"), "{v}");
126 assert!(v.contains("allow"), "{v}");
127 }
128
129 #[test]
130 fn delegation_mode_field_carries_variants() {
131 let p = RiskProfileConfig::default();
132 let mode = p
133 .prop_fields()
134 .into_iter()
135 .find(|f| f.name.ends_with("delegation_policy.mode"))
136 .expect("mode leaf missing");
137 let variants = mode.enum_variants.map(|f| f()).unwrap_or_default();
138 assert!(
139 !variants.is_empty(),
140 "enum_variants empty — UI would render as text"
141 );
142 assert!(variants.iter().any(|v| v == "forbidden"));
143 assert!(variants.iter().any(|v| v == "allow"));
144 }
145}