1use serde::{Deserialize, Serialize};
4
5#[derive(
7 Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Default, schemars::JsonSchema,
8)]
9#[serde(rename_all = "kebab-case")]
10pub enum HostId {
11 MurAgent,
12 MurCommander,
13 #[default]
15 All,
16 #[serde(untagged)]
17 Custom(String),
18}
19
20#[derive(
22 Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord, Default,
23)]
24#[serde(rename_all = "kebab-case")]
25pub enum TrustLevel {
26 #[default]
28 Sandboxed,
29 Verified,
31 Trusted,
33}
34
35#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
37#[serde(rename_all = "lowercase")]
38pub enum Category {
39 Context,
40 Workflow,
41 Command,
42 Meta,
43 Note,
44 Media,
47}
48
49pub const MUR_OWNED_PUBLISHERS: &[&str] = &["human:mur-official", "human:mur"];
58
59pub fn is_mur_owned_publisher(publisher: &str) -> bool {
61 MUR_OWNED_PUBLISHERS.contains(&publisher)
62}
63
64#[derive(
68 Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default, schemars::JsonSchema,
69)]
70#[serde(rename_all = "lowercase")]
71pub enum Provenance {
72 #[default]
74 Human,
75 Llm,
77 Hybrid,
79}
80
81#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
83#[serde(rename_all = "lowercase")]
84pub enum ContentMode {
85 Context,
86 Workflow,
87 Command,
88 Note,
89}
90
91#[derive(
92 Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default, schemars::JsonSchema,
93)]
94#[serde(rename_all = "lowercase")]
95pub enum Priority {
96 Low,
97 #[default]
98 Normal,
99 High,
100 Critical,
101}
102
103#[derive(
104 Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd, schemars::JsonSchema,
105)]
106#[serde(rename_all = "snake_case")]
107pub enum TriggerKind {
108 Command,
109 Keyword,
110 SessionStart,
111 Manual,
112}
113
114#[cfg(test)]
115mod tests {
116 use super::*;
117
118 #[test]
119 fn host_id_serialises_kebab_case() {
120 let yaml = serde_yaml_ng::to_string(&HostId::MurAgent).unwrap();
121 assert_eq!(yaml.trim(), "mur-agent");
122 }
123
124 #[test]
125 fn trust_level_ordering_matches_spec() {
126 assert!(TrustLevel::Sandboxed < TrustLevel::Verified);
127 assert!(TrustLevel::Verified < TrustLevel::Trusted);
128 }
129
130 #[test]
131 fn host_id_default_is_all() {
132 assert_eq!(HostId::default(), HostId::All);
133 }
134
135 #[test]
136 fn note_category_serialises_lowercase_and_roundtrips() {
137 let yaml = serde_yaml_ng::to_string(&Category::Note).unwrap();
138 assert_eq!(yaml.trim(), "note");
139 let parsed: Category = serde_yaml_ng::from_str("note").unwrap();
140 assert_eq!(parsed, Category::Note);
141 }
142
143 #[test]
144 fn media_category_serialises_lowercase_and_roundtrips() {
145 let yaml = serde_yaml_ng::to_string(&Category::Media).unwrap();
146 assert_eq!(yaml.trim(), "media");
147 let parsed: Category = serde_yaml_ng::from_str("media").unwrap();
148 assert_eq!(parsed, Category::Media);
149 }
150
151 #[test]
152 fn note_content_mode_serialises_lowercase_and_roundtrips() {
153 let yaml = serde_yaml_ng::to_string(&ContentMode::Note).unwrap();
154 assert_eq!(yaml.trim(), "note");
155 let parsed: ContentMode = serde_yaml_ng::from_str("note").unwrap();
156 assert_eq!(parsed, ContentMode::Note);
157 }
158
159 #[test]
160 fn provenance_defaults_to_human_and_roundtrips() {
161 assert_eq!(Provenance::default(), Provenance::Human);
163 let yaml = serde_yaml_ng::to_string(&Provenance::Llm).unwrap();
165 assert_eq!(yaml.trim(), "llm");
166 let parsed: Provenance = serde_yaml_ng::from_str("hybrid").unwrap();
167 assert_eq!(parsed, Provenance::Hybrid);
168 }
169}