1use std::path::PathBuf;
4
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
8pub enum SyncMode {
9 ReadThrough,
13 WriteThrough,
16 Mirror,
19}
20
21impl SyncMode {
22 pub fn as_str(&self) -> &'static str {
23 match self {
24 SyncMode::ReadThrough => "read_through",
25 SyncMode::WriteThrough => "write_through",
26 SyncMode::Mirror => "mirror",
27 }
28 }
29}
30
31#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
34pub struct CmaTreeRoot {
35 pub root: PathBuf,
36 pub namespace: String,
37 pub sync: SyncMode,
38}
39
40impl CmaTreeRoot {
41 pub fn new(root: PathBuf, namespace: impl Into<String>, sync: SyncMode) -> Self {
42 Self {
43 root,
44 namespace: namespace.into(),
45 sync,
46 }
47 }
48
49 pub fn memory_dir(&self) -> PathBuf {
50 self.root.join(".memory")
51 }
52
53 pub fn audit_log(&self) -> PathBuf {
54 self.root.join("audit.jsonl")
55 }
56}
57
58#[cfg(test)]
59mod tests {
60 use super::*;
61
62 #[test]
63 fn paths_are_relative_to_root() {
64 let r = CmaTreeRoot::new(
65 PathBuf::from("/tmp/agent"),
66 "primary",
67 SyncMode::WriteThrough,
68 );
69 assert_eq!(r.memory_dir(), PathBuf::from("/tmp/agent/.memory"));
70 assert_eq!(r.audit_log(), PathBuf::from("/tmp/agent/audit.jsonl"));
71 }
72
73 #[test]
74 fn sync_mode_strings_are_stable() {
75 for m in [
76 SyncMode::ReadThrough,
77 SyncMode::WriteThrough,
78 SyncMode::Mirror,
79 ] {
80 assert!(!m.as_str().is_empty());
81 }
82 }
83}