/// Schema types for the projection layer. /// /// A `ProjectionSchema` defines a named view over the Engram graph. /// It specifies which nodes are in scope and how to extract fields from them. use engram_core::types::MemoryTier; use serde::{Deserialize, Serialize}; use serde_json::Value; use std::collections::HashMap; /// How the projection presents data to the caller. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum ProjectionType { /// Nodes as rows; edges become foreign key references. /// Each row is a flat map of field_name → value. Relational, /// Nodes as JSON documents. /// Fields are nested under a "fields" key; metadata at the top level. Document, /// Nodes as column families (node_id → column_name → value). /// Suitable for wide, sparse schemas. WideColumn, /// Simple node_id → content mapping. /// Ignores field mappings; raw content bytes as base64. KeyValue, } /// Which nodes from the activation result set fall within this projection's scope. #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(tag = "type", content = "value")] pub enum NodeFilter { /// Include nodes whose node_type matches any of the given strings. ByType(Vec), /// Include nodes in any of the given memory tiers. ByTier(Vec), /// Include nodes whose tier name contains any of the given tag strings /// (stored in node metadata via content prefix convention). ByTag(Vec), /// Include nodes with activation strength >= threshold. ByActivationThreshold(f32), /// Include nodes whose salience >= threshold. BySalience(f32), /// All of the sub-filters must match (AND). Combined(Vec), /// Any sub-filter matches (OR). Any(Vec), /// Pass all nodes through without filtering. All, } /// Where to source a projected field's value. #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(tag = "type", content = "value")] pub enum FieldSource { /// Extract a value from the node's content, interpreted as JSON, using a dot-path. /// E.g., "user.name" extracts `{ "user": { "name": "Alice" } }["user"]["name"]`. ContentJsonPath(String), /// The node's content, raw, as a UTF-8 string (lossy). ContentRaw, /// The node's content as a base64-encoded string. ContentBase64, /// The node's unique identifier. NodeId, /// The node's type as a string. NodeType, /// The node's memory tier as a string. Tier, /// The node's current salience score. Salience, /// The node's importance (caller-set, stable). Importance, /// The activation strength at this node (from spreading activation). ActivationStrength, /// The hop count from the nearest seed node. Hops, /// The node's creation timestamp (Unix ms). CreatedAt, /// The node's last-activated timestamp (Unix ms). LastActivated, /// The node's activation count. ActivationCount, /// A literal constant value. Literal(Value), } /// One field in a projected row. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct FieldMapping { /// The name of this field in the projected output. pub field_name: String, /// Where to get the value from. pub source: FieldSource, /// If the source fails to produce a value, use this fallback. Null means omit. pub default: Option, } /// A complete schema definition. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ProjectionSchema { /// Unique name for this projection. pub name: String, /// Human-readable description. pub description: Option, /// How results are shaped. pub projection_type: ProjectionType, /// Which nodes from the activation result are included. pub node_filter: NodeFilter, /// How to extract fields from each included node. pub field_mappings: Vec, } /// One projected node in a Relational or Document projection. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ProjectedRow { /// The source node's UUID (always included). pub node_id: uuid::Uuid, /// Extracted fields as ordered map field_name → value. pub fields: HashMap, } /// The output of running a projection over an activation result set. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ProjectionResult { /// The schema that produced this result. pub schema_name: String, /// How many nodes from the activation set were in scope. pub nodes_in_scope: usize, /// The projected rows. pub rows: Vec, /// For KeyValue projection: node_id (string) → content. pub key_value: Option>, /// For WideColumn projection: node_id → column_name → value. pub wide_column: Option>>, }