vios_app 0.1.1

Small JSON vaults: Argon2id + AES-GCM, with optional AAD binding.
Documentation
// src/naorix/naorix_memory.rs
use std::fs;
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct MemoryTrace {
    pub vault_id: String,
    pub tone: String,
    pub intent: String,
    pub reem_code: String,
    pub timestamp: String,
    pub cia_hash: Option<String>,
    pub parent_hash: Option<String>, // 🧬 Vault lineage trace
}

impl MemoryTrace {
    pub fn new(
        vault_id: &str,
        tone: &str,
        intent: &str,
        reem_code: &str,
        timestamp: &str,
    ) -> Self {
        Self {
            vault_id: vault_id.to_string(),
            tone: tone.to_string(),
            intent: intent.to_string(),
            reem_code: reem_code.to_string(),
            timestamp: timestamp.to_string(),
            cia_hash: None,
            parent_hash: None,
        }
    }

    pub fn with_cia(
        vault_id: &str,
        tone: &str,
        intent: &str,
        reem_code: &str,
        timestamp: &str,
        cia_hash: &str,
    ) -> Self {
        Self {
            vault_id: vault_id.to_string(),
            tone: tone.to_string(),
            intent: intent.to_string(),
            reem_code: reem_code.to_string(),
            timestamp: timestamp.to_string(),
            cia_hash: Some(cia_hash.to_string()),
            parent_hash: None,
        }
    }

    pub fn with_lineage(
        vault_id: &str,
        tone: &str,
        intent: &str,
        reem_code: &str,
        timestamp: &str,
        cia_hash: &str,
        parent_hash: Option<String>,
    ) -> Self {
        Self {
            vault_id: vault_id.to_string(),
            tone: tone.to_string(),
            intent: intent.to_string(),
            reem_code: reem_code.to_string(),
            timestamp: timestamp.to_string(),
            cia_hash: Some(cia_hash.to_string()),
            parent_hash,
        }
    }

    pub fn drift_score(&self, other: &MemoryTrace) -> u8 {
        let mut score = 0;
        if self.tone != other.tone {
            score += 1;
        }
        if self.intent != other.intent {
            score += 1;
        }
        if self.reem_code != other.reem_code {
            score += 1;
        }
        score
    }

    pub fn print_debug(&self) {
        println!(
            "🧠 MemoryTrace Debug → Vault: {}, Tone: {}, Intent: {}, REEM: {}, Time: {}, CIA: {}, Parent: {}",
            self.vault_id,
            self.tone,
            self.intent,
            self.reem_code,
            self.timestamp,
            self.cia_hash.as_deref().unwrap_or("None"),
            self.parent_hash.as_deref().unwrap_or("Origin")
        );
    }
}

pub struct MemoryBank {
    pub path: String,
    pub memories: Vec<MemoryTrace>,
}

impl MemoryBank {
    pub fn new(path: &str) -> Self {
        let data = fs::read_to_string(path).unwrap_or_else(|_| "[]".to_string());
        let memories: Vec<MemoryTrace> = serde_json::from_str(&data).unwrap_or_default();
        Self {
            path: path.to_string(),
            memories,
        }
    }

    pub fn save(&self) {
        let json = serde_json::to_string_pretty(&self.memories).unwrap();
        fs::write(&self.path, json).expect("❌ Failed to save memory bank.");
    }

    pub fn add(&mut self, mut memory: MemoryTrace) {
        // Inject lineage from last memory
        memory.parent_hash = self
            .memories
            .last()
            .and_then(|prev| prev.cia_hash.clone())
            .or(Some("🕳 Origin".to_string()));
        self.memories.push(memory);
        self.save();
    }

    pub fn print_all(&self) {
        for mem in &self.memories {
            mem.print_debug();
        }
    }

    pub fn latest_cia(&self) -> Option<String> {
        self.memories.last().and_then(|m| m.cia_hash.clone())
    }
}