agileplus-domain 0.3.0

Typed intent graphs for engineering work — convert prompts into validated DAGs of intents, features, tasks, tests, and edges, then store, query, and serve them from Rust, HTTP, or MCP.
Documentation
//! `GraphMetadataBuilder` — constructs `GraphMetadata` records with sensible
//! default values for AgilePlus v1.0.0.

use crate::intent_graph::GraphMetadata;

const DEFAULT_SCHEMA_URI: &str =
    "https://phenotype.dev/schemas/agileplus-intent-ontology/v1.json";

/// Builder for graph-level metadata.
#[derive(Debug, Default)]
pub struct GraphMetadataBuilder {
    version: Option<String>,
    schema_uri: Option<String>,
    created_at: Option<String>,
    updated_at: Option<String>,
    node_count: Option<usize>,
    edge_count: Option<usize>,
    dag_valid: Option<bool>,
    source_system: Option<String>,
}

impl GraphMetadataBuilder {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn version(mut self, v: impl Into<String>) -> Self {
        self.version = Some(v.into());
        self
    }

    pub fn schema_uri(mut self, uri: impl Into<String>) -> Self {
        self.schema_uri = Some(uri.into());
        self
    }

    pub fn created_at(mut self, at: impl Into<String>) -> Self {
        self.created_at = Some(at.into());
        self
    }

    pub fn updated_at(mut self, at: impl Into<String>) -> Self {
        self.updated_at = Some(at.into());
        self
    }

    pub fn node_count(mut self, n: usize) -> Self {
        self.node_count = Some(n);
        self
    }

    pub fn edge_count(mut self, n: usize) -> Self {
        self.edge_count = Some(n);
        self
    }

    pub fn dag_valid(mut self, v: bool) -> Self {
        self.dag_valid = Some(v);
        self
    }

    pub fn source_system(mut self, s: impl Into<String>) -> Self {
        self.source_system = Some(s.into());
        self
    }

    pub fn build(self) -> Result<GraphMetadata, String> {
        let now = chrono::Utc::now().to_rfc3339();
        Ok(GraphMetadata {
            version: self.version.unwrap_or_else(|| "1.0.0".to_string()),
            schema_uri: self
                .schema_uri
                .unwrap_or_else(|| DEFAULT_SCHEMA_URI.to_string()),
            created_at: self.created_at.unwrap_or_else(|| now.clone()),
            updated_at: self.updated_at.or(Some(now)),
            node_count: self.node_count,
            edge_count: self.edge_count,
            dag_valid: self.dag_valid,
            source_system: self.source_system,
        })
    }
}