caliban_memory/
init_import.rs1use std::path::{Path, PathBuf};
8
9#[derive(Debug, Clone, PartialEq, Eq)]
11pub struct LegacyRulesFile {
12 pub name: String,
14 pub path: PathBuf,
16 pub body: String,
18}
19
20pub const INIT_FILENAMES: &[&str] = &["AGENTS.md", ".cursorrules", ".windsurfrules"];
22
23#[must_use]
26pub fn scan_init_files(workspace_root: &Path) -> Vec<LegacyRulesFile> {
27 let mut out = Vec::new();
28 for name in INIT_FILENAMES {
29 let path = workspace_root.join(name);
30 if !path.is_file() {
31 continue;
32 }
33 match std::fs::read(&path) {
34 Ok(bytes) => out.push(LegacyRulesFile {
35 name: (*name).to_string(),
36 path,
37 body: String::from_utf8_lossy(&bytes).into_owned(),
38 }),
39 Err(e) => tracing::warn!(
40 target: caliban_common::tracing_targets::TARGET_MEMORY_INIT,
41 path = %path.display(),
42 error = %e,
43 "failed to read init file",
44 ),
45 }
46 }
47 out
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53 use std::fs;
54 use tempfile::TempDir;
55
56 #[test]
57 fn init_reads_agents_md_cursorrules_and_windsurfrules() {
58 let tmp = TempDir::new().unwrap();
59 let root = tmp.path();
60 fs::write(root.join("AGENTS.md"), "AGENTS-BODY").unwrap();
61 fs::write(root.join(".cursorrules"), "CURSOR-BODY").unwrap();
62 fs::write(root.join(".windsurfrules"), "WINDSURF-BODY").unwrap();
63
64 let found = scan_init_files(root);
65 let names: Vec<&str> = found.iter().map(|f| f.name.as_str()).collect();
66 assert_eq!(names, vec!["AGENTS.md", ".cursorrules", ".windsurfrules"]);
67 assert!(found[0].body.contains("AGENTS-BODY"));
68 assert!(found[1].body.contains("CURSOR-BODY"));
69 assert!(found[2].body.contains("WINDSURF-BODY"));
70 }
71
72 #[test]
73 fn init_omits_missing_files() {
74 let tmp = TempDir::new().unwrap();
75 let root = tmp.path();
76 fs::write(root.join(".cursorrules"), "ONLY-CURSOR").unwrap();
77 let found = scan_init_files(root);
78 assert_eq!(found.len(), 1);
79 assert_eq!(found[0].name, ".cursorrules");
80 }
81}