Skip to main content

lean_ctx/core/property_graph/
meta.rs

1use serde::{Deserialize, Serialize};
2use std::path::PathBuf;
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
5#[serde(default)]
6pub struct PropertyGraphMetaV1 {
7    pub schema_version: u32,
8    /// RFC3339 timestamp (UTC) of the last successful build.
9    pub built_at: String,
10    /// Git HEAD (short) at build time, if available.
11    pub git_head: Option<String>,
12    /// Git dirty flag at build time, if available.
13    pub git_dirty: Option<bool>,
14    /// Node count after build.
15    pub nodes: Option<usize>,
16    /// Edge count after build.
17    pub edges: Option<usize>,
18    /// Number of source files processed during build (before filtering).
19    pub files_indexed: Option<usize>,
20    /// Build duration in milliseconds (best-effort).
21    pub build_time_ms: Option<u64>,
22}
23
24impl Default for PropertyGraphMetaV1 {
25    fn default() -> Self {
26        Self {
27            schema_version: 1,
28            built_at: String::new(),
29            git_head: None,
30            git_dirty: None,
31            nodes: None,
32            edges: None,
33            files_indexed: None,
34            build_time_ms: None,
35        }
36    }
37}
38
39pub fn meta_path(project_root: &str) -> PathBuf {
40    super::graph_dir(project_root).join("graph.meta.json")
41}
42
43pub fn load_meta(project_root: &str) -> Option<PropertyGraphMetaV1> {
44    let path = meta_path(project_root);
45    let s = std::fs::read_to_string(path).ok()?;
46    let meta: PropertyGraphMetaV1 = serde_json::from_str(&s).ok()?;
47    if meta.schema_version != 1 || meta.built_at.trim().is_empty() {
48        return None;
49    }
50    Some(meta)
51}
52
53pub fn write_meta(project_root: &str, meta: &PropertyGraphMetaV1) -> Result<PathBuf, String> {
54    let path = meta_path(project_root);
55    if let Some(parent) = path.parent() {
56        std::fs::create_dir_all(parent).map_err(|e| e.to_string())?;
57    }
58    let json = serde_json::to_string_pretty(meta).map_err(|e| e.to_string())?;
59    crate::config_io::write_atomic(&path, &json)?;
60    Ok(path)
61}