lean_ctx/core/gotcha_tracker/
persist.rs1use super::model::{Gotcha, GotchaStore};
2use std::path::PathBuf;
3
4impl GotchaStore {
5 pub fn load(project_root: &str) -> Self {
6 let hash = crate::core::project_hash::hash_project_root(project_root);
7 let path = gotcha_path(&hash);
8 if let Ok(content) = std::fs::read_to_string(&path) {
9 if let Ok(mut store) = serde_json::from_str::<GotchaStore>(&content) {
10 store.apply_decay();
11 store.pending_errors = Vec::new();
12 return store;
13 }
14 }
15 Self::new(&hash)
16 }
17
18 pub fn save(&self, project_root: &str) -> Result<(), String> {
19 let hash = crate::core::project_hash::hash_project_root(project_root);
20 let path = gotcha_path(&hash);
21 if let Some(parent) = path.parent() {
22 std::fs::create_dir_all(parent).map_err(|e| e.to_string())?;
23 }
24 let tmp = path.with_extension("tmp");
25 let json = serde_json::to_string_pretty(self).map_err(|e| e.to_string())?;
26 std::fs::write(&tmp, &json).map_err(|e| e.to_string())?;
27 std::fs::rename(&tmp, &path).map_err(|e| e.to_string())?;
28 Ok(())
29 }
30}
31
32fn gotcha_path(project_hash: &str) -> PathBuf {
33 crate::core::data_dir::lean_ctx_data_dir()
34 .unwrap_or_else(|_| PathBuf::from("."))
35 .join("knowledge")
36 .join(project_hash)
37 .join("gotchas.json")
38}
39
40pub fn load_universal_gotchas() -> Vec<Gotcha> {
45 let Ok(dir) = crate::core::data_dir::lean_ctx_data_dir() else {
46 return Vec::new();
47 };
48 let path = dir.join("universal-gotchas.json");
49 if let Ok(content) = std::fs::read_to_string(&path) {
50 serde_json::from_str(&content).unwrap_or_default()
51 } else {
52 Vec::new()
53 }
54}
55
56pub fn save_universal_gotchas(gotchas: &[Gotcha]) -> Result<(), String> {
57 let dir = crate::core::data_dir::lean_ctx_data_dir()?;
58 let path = dir.join("universal-gotchas.json");
59 let tmp = path.with_extension("tmp");
60 let json = serde_json::to_string_pretty(gotchas).map_err(|e| e.to_string())?;
61 std::fs::write(&tmp, &json).map_err(|e| e.to_string())?;
62 std::fs::rename(&tmp, &path).map_err(|e| e.to_string())?;
63 Ok(())
64}