use blake3;
use dashmap::DashMap; use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::sync::{
atomic::{AtomicU32, AtomicU64, Ordering},
Arc,
};
use std::time::{SystemTime, UNIX_EPOCH};
use thiserror::Error;
use tokio::fs;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
#[derive(Debug, Error)]
pub enum SourceOfTruthError {
#[error("Work item not found: {0}")]
WorkItemNotFound(String),
#[error("Duplication detected: {0}")]
DuplicationDetected(String),
#[error("Invalid work item ID format: {0}")]
InvalidWorkItemId(String),
#[error("Canonical document conflict: {0}")]
CanonicalConflict(String),
#[error("Registry corruption detected: {0}")]
RegistryCorruption(String),
#[error("IO error: {0}")]
IoError(#[from] std::io::Error),
#[error("Serialization error: {0}")]
SerializationError(#[from] serde_json::Error),
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum WorkStatus {
Planning,
InProgress,
CodeReview,
Testing,
Completed,
Blocked(String), }
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum DuplicationCheckStatus {
Passed,
Failed(String), NotChecked,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum CanonicalStatus {
Draft,
Review,
Verified,
Deprecated,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WorkItem {
pub id: String,
pub title: String,
pub status: WorkStatus,
pub component: String,
pub files_modified: Vec<String>,
pub duplication_check: DuplicationCheckStatus,
pub source_of_truth_updated: bool,
pub verification_hash: [u8; 32],
pub completion_timestamp: Option<u64>,
pub evidence_link: String,
pub dependencies: Vec<String>,
pub blockers: Vec<String>,
pub created: u64,
pub last_updated: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CanonicalDocument {
pub file_path: String,
pub work_item_id: String,
pub verification_hash: [u8; 32],
pub last_updated: u64,
pub canonical_status: CanonicalStatus,
pub authority_level: u8, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SourceOfTruthEntry {
pub file_path: String,
pub work_item_id: String,
pub verification_hash: [u8; 32],
pub last_updated: u64,
pub canonical_status: CanonicalStatus,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DuplicationEntry {
pub content_hash: [u8; 32],
pub file_path: String,
pub function_signature: Option<String>,
pub first_occurrence: u64, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FunctionSignature {
pub name: String,
pub parameters: Vec<String>,
pub return_type: Option<String>,
pub visibility: String,
pub file_path: String,
pub line_number: u32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CodeFingerprint {
pub content_hash: [u8; 32],
pub normalized_hash: [u8; 32], pub function_count: u32,
pub line_count: u32,
pub file_path: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DocumentationEntry {
pub content_hash: [u8; 32],
pub title: String,
pub file_path: String,
pub section: String,
}
#[derive(Debug)]
pub struct SourceOfTruthRegistry {
canonical_documents: DashMap<String, CanonicalDocument>,
work_items: DashMap<String, WorkItem>,
duplication_index: DashMap<String, DuplicationEntry>,
function_signatures: DashMap<String, FunctionSignature>,
#[allow(dead_code)]
code_fingerprints: DashMap<String, CodeFingerprint>,
#[allow(dead_code)]
documentation_index: DashMap<String, DocumentationEntry>,
last_updated: AtomicU64,
version: AtomicU32,
registry_path: String,
}
impl SourceOfTruthRegistry {
pub async fn new(registry_path: String) -> Result<Self, SourceOfTruthError> {
let registry = Self {
canonical_documents: DashMap::new(),
work_items: DashMap::new(),
duplication_index: DashMap::new(),
function_signatures: DashMap::new(),
code_fingerprints: DashMap::new(),
documentation_index: DashMap::new(),
last_updated: AtomicU64::new(Self::current_timestamp()),
version: AtomicU32::new(1),
registry_path,
};
if let Some(parent) = std::path::Path::new(®istry.registry_path).parent() {
fs::create_dir_all(parent).await?;
}
if registry.load_from_disk().await.is_err() {
registry.save_to_disk().await?;
}
Ok(registry)
}
pub fn generate_work_item_id(&self) -> String {
let now = chrono::Utc::now();
let date_prefix = now.format("%Y-%m-%d").to_string();
let mut sequence = 1;
loop {
let candidate_id = format!("WI-{date_prefix}-{sequence}");
if !self.work_items.contains_key(&candidate_id) {
return candidate_id;
}
sequence += 1;
}
}
pub async fn create_work_item(
&self,
title: String,
component: String,
) -> Result<WorkItem, SourceOfTruthError> {
let work_id = self.generate_work_item_id();
let duplication_status = self.check_work_item_duplication(&title, &component).await?;
if matches!(duplication_status, DuplicationCheckStatus::Failed(_)) {
return Err(SourceOfTruthError::DuplicationDetected(format!(
"Work item title or component already exists: {title}"
)));
}
let work_item = WorkItem {
id: work_id.clone(),
title,
status: WorkStatus::Planning,
component,
files_modified: Vec::new(),
duplication_check: duplication_status,
source_of_truth_updated: false,
verification_hash: [0u8; 32],
completion_timestamp: None,
evidence_link: String::new(),
dependencies: Vec::new(),
blockers: Vec::new(),
created: Self::current_timestamp(),
last_updated: Self::current_timestamp(),
};
self.work_items.insert(work_id.clone(), work_item.clone());
self.update_last_modified();
self.save_to_disk().await?;
Ok(work_item)
}
pub async fn update_work_item_status(
&self,
work_id: &str,
new_status: WorkStatus,
) -> Result<(), SourceOfTruthError> {
use log::debug;
debug!("update_work_item_status called for work_id: {work_id}, new_status: {new_status:?}");
let mut work_item = match self.work_items.get_mut(work_id) {
Some(item) => item,
None => {
debug!("Work item not found: {work_id}");
return Err(SourceOfTruthError::WorkItemNotFound(work_id.to_string()));
}
};
if let Err(e) = self.validate_status_transition(&work_item.status, &new_status) {
debug!("Invalid status transition: {e:?}");
return Err(e);
}
work_item.status = new_status.clone();
work_item.last_updated = Self::current_timestamp();
if matches!(new_status, WorkStatus::Completed) {
work_item.completion_timestamp = Some(Self::current_timestamp());
work_item.verification_hash = self.generate_verification_hash(&work_item).await?;
work_item.source_of_truth_updated = true;
}
self.update_last_modified();
self.save_to_disk().await?;
debug!("update_work_item_status completed for work_id: {work_id}");
Ok(())
}
pub async fn check_code_duplication(
&self,
file_path: &str,
content: &str,
) -> Result<DuplicationCheckStatus, SourceOfTruthError> {
let content_hash = blake3::hash(content.as_bytes()).into();
for entry in self.duplication_index.iter() {
if entry.value().content_hash == content_hash && entry.value().file_path != file_path {
return Ok(DuplicationCheckStatus::Failed(format!(
"Exact content duplication found in {}",
entry.value().file_path
)));
}
}
let functions = self.extract_rust_functions(content)?;
for function in functions {
let signature_key = format!("{}::{}", function.name, function.parameters.join(","));
if let Some(existing) = self.function_signatures.get(&signature_key) {
if existing.file_path != file_path {
return Ok(DuplicationCheckStatus::Failed(format!(
"Function signature duplication: {} in {}",
signature_key, existing.file_path
)));
}
}
}
self.duplication_index.insert(
file_path.to_string(),
DuplicationEntry {
content_hash,
file_path: file_path.to_string(),
function_signature: None,
first_occurrence: Self::current_timestamp(),
},
);
Ok(DuplicationCheckStatus::Passed)
}
async fn check_work_item_duplication(
&self,
title: &str,
component: &str,
) -> Result<DuplicationCheckStatus, SourceOfTruthError> {
for item in self.work_items.iter() {
let work_item = item.value();
if work_item.title == title && work_item.component == component {
return Ok(DuplicationCheckStatus::Failed(format!(
"Duplicate work item: {title} in {component}"
)));
}
}
Ok(DuplicationCheckStatus::Passed)
}
fn extract_rust_functions(
&self,
content: &str,
) -> Result<Vec<FunctionSignature>, SourceOfTruthError> {
let mut functions = Vec::new();
let lines: Vec<&str> = content.lines().collect();
for (line_num, line) in lines.iter().enumerate() {
if let Some(func) = self.parse_rust_function_signature(line, line_num as u32 + 1) {
functions.push(func);
}
}
Ok(functions)
}
fn parse_rust_function_signature(
&self,
line: &str,
line_number: u32,
) -> Option<FunctionSignature> {
let trimmed = line.trim();
if trimmed.starts_with("pub fn ") || trimmed.starts_with("fn ") {
let visibility = if trimmed.starts_with("pub ") {
"pub"
} else {
"private"
};
if let Some(paren_start) = trimmed.find('(') {
if let Some(fn_start) = trimmed.find("fn ") {
let name_start = fn_start + 3;
let name = trimmed[name_start..paren_start].trim().to_string();
if let Some(paren_end) = trimmed.find(')') {
let param_str = &trimmed[paren_start + 1..paren_end];
let parameters: Vec<String> = param_str
.split(',')
.map(|p| p.trim().split(':').next().unwrap_or("").trim().to_string())
.filter(|p| !p.is_empty())
.collect();
let return_type = trimmed.find("->").map(|arrow_pos| {
trimmed[arrow_pos + 2..]
.split_whitespace()
.next()
.unwrap_or("")
.to_string()
});
return Some(FunctionSignature {
name,
parameters,
return_type,
visibility: visibility.to_string(),
file_path: String::new(), line_number,
});
}
}
}
}
None
}
fn validate_status_transition(
&self,
current: &WorkStatus,
new: &WorkStatus,
) -> Result<(), SourceOfTruthError> {
use log::debug;
match (current, new) {
(WorkStatus::Planning, WorkStatus::InProgress) => Ok(()),
(WorkStatus::InProgress, WorkStatus::CodeReview) => Ok(()),
(WorkStatus::CodeReview, WorkStatus::Testing) => Ok(()),
(WorkStatus::Testing, WorkStatus::Completed) => Ok(()),
(_, WorkStatus::Blocked(_)) => Ok(()), (WorkStatus::Blocked(_), _) => Ok(()), _ => {
debug!("Invalid status transition from {current:?} to {new:?}");
Err(SourceOfTruthError::InvalidWorkItemId(format!(
"Invalid status transition from {current:?} to {new:?}"
)))
}
}
}
async fn generate_verification_hash(
&self,
work_item: &WorkItem,
) -> Result<[u8; 32], SourceOfTruthError> {
let mut hasher = blake3::Hasher::new();
hasher.update(work_item.id.as_bytes());
hasher.update(work_item.title.as_bytes());
hasher.update(&work_item.completion_timestamp.unwrap_or(0).to_le_bytes());
for file_path in &work_item.files_modified {
if let Ok(content) = fs::read_to_string(file_path).await {
hasher.update(content.as_bytes());
}
}
Ok(hasher.finalize().into())
}
fn current_timestamp() -> u64 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_nanos() as u64
}
fn update_last_modified(&self) {
self.last_updated
.store(Self::current_timestamp(), Ordering::Relaxed);
self.version.fetch_add(1, Ordering::Relaxed);
}
async fn save_to_disk(&self) -> Result<(), SourceOfTruthError> {
let registry_data = RegistryData {
canonical_documents: self
.canonical_documents
.iter()
.map(|entry| (entry.key().clone(), entry.value().clone()))
.collect(),
work_items: self
.work_items
.iter()
.map(|entry| (entry.key().clone(), entry.value().clone()))
.collect(),
duplication_index: self
.duplication_index
.iter()
.map(|entry| (entry.key().clone(), entry.value().clone()))
.collect(),
last_updated: self.last_updated.load(Ordering::Relaxed),
version: self.version.load(Ordering::Relaxed),
};
let json_data = serde_json::to_string_pretty(®istry_data)?;
let mut file = fs::File::create(&self.registry_path).await?;
file.write_all(json_data.as_bytes()).await?;
Ok(())
}
async fn load_from_disk(&self) -> Result<(), SourceOfTruthError> {
let mut file = fs::File::open(&self.registry_path).await?;
let mut contents = String::new();
file.read_to_string(&mut contents).await?;
let registry_data: RegistryData = serde_json::from_str(&contents)?;
self.canonical_documents.clear();
self.work_items.clear();
self.duplication_index.clear();
for (key, value) in registry_data.canonical_documents {
self.canonical_documents.insert(key, value);
}
for (key, value) in registry_data.work_items {
self.work_items.insert(key, value);
}
for (key, value) in registry_data.duplication_index {
self.duplication_index.insert(key, value);
}
self.last_updated
.store(registry_data.last_updated, Ordering::Relaxed);
self.version.store(registry_data.version, Ordering::Relaxed);
Ok(())
}
}
#[derive(Debug, Serialize, Deserialize)]
struct RegistryData {
canonical_documents: HashMap<String, CanonicalDocument>,
work_items: HashMap<String, WorkItem>,
duplication_index: HashMap<String, DuplicationEntry>,
last_updated: u64,
version: u32,
}
static GLOBAL_REGISTRY: once_cell::sync::Lazy<
Arc<tokio::sync::RwLock<Option<SourceOfTruthRegistry>>>,
> = once_cell::sync::Lazy::new(|| Arc::new(tokio::sync::RwLock::new(None)));
pub async fn initialize_global_registry(registry_path: String) -> Result<(), SourceOfTruthError> {
let registry = SourceOfTruthRegistry::new(registry_path).await?;
let mut global = GLOBAL_REGISTRY.write().await;
*global = Some(registry);
Ok(())
}
pub async fn get_global_registry() -> Arc<tokio::sync::RwLock<Option<SourceOfTruthRegistry>>> {
GLOBAL_REGISTRY.clone()
}
#[cfg(test)]
mod tests {
use super::*;
use tempfile::tempdir;
#[tokio::test]
async fn test_work_item_creation() {
let temp_dir = tempdir().unwrap();
let registry_path = temp_dir
.path()
.join("registry.json")
.to_string_lossy()
.to_string();
let registry = SourceOfTruthRegistry::new(registry_path).await.unwrap();
let work_item = registry
.create_work_item("Test work item".to_string(), "test_component".to_string())
.await
.unwrap();
assert!(work_item.id.starts_with("WI-"));
assert_eq!(work_item.status, WorkStatus::Planning);
assert_eq!(work_item.duplication_check, DuplicationCheckStatus::Passed);
}
#[tokio::test]
async fn test_duplication_detection() {
let temp_dir = tempdir().unwrap();
let registry_path = temp_dir
.path()
.join("registry.json")
.to_string_lossy()
.to_string();
let registry = SourceOfTruthRegistry::new(registry_path).await.unwrap();
let _work_item1 = registry
.create_work_item("Unique title".to_string(), "component1".to_string())
.await
.unwrap();
let result = registry
.create_work_item("Unique title".to_string(), "component1".to_string())
.await;
assert!(result.is_err());
assert!(matches!(
result.unwrap_err(),
SourceOfTruthError::DuplicationDetected(_)
));
}
#[tokio::test]
async fn test_status_transition_valid() {
use tokio::time::{timeout, Duration};
use log::debug;
let temp_dir = tempdir().unwrap();
let registry_path = temp_dir
.path()
.join("registry_valid.json")
.to_string_lossy()
.to_string();
let registry = SourceOfTruthRegistry::new(registry_path).await.unwrap();
let work_item = registry
.create_work_item("Status test valid".to_string(), "test_component".to_string())
.await
.unwrap();
let valid = timeout(Duration::from_secs(10), registry.update_work_item_status(&work_item.id, WorkStatus::InProgress)).await;
match valid {
Ok(Ok(_)) => debug!("Valid status transition succeeded"),
Ok(Err(e)) => panic!("Valid status transition failed: {e:?}"),
Err(_) => panic!("Timeout on valid status transition"),
}
}
#[tokio::test]
async fn test_status_transition_invalid() {
use tokio::time::{timeout, Duration};
use log::debug;
let temp_dir = tempdir().unwrap();
let registry_path = temp_dir
.path()
.join("registry_invalid.json")
.to_string_lossy()
.to_string();
let registry = SourceOfTruthRegistry::new(registry_path).await.unwrap();
let work_item = registry
.create_work_item("Status test invalid".to_string(), "test_component".to_string())
.await
.unwrap();
let invalid = timeout(Duration::from_secs(10), registry.update_work_item_status(&work_item.id, WorkStatus::Completed)).await;
match invalid {
Ok(Ok(_)) => panic!("Invalid status transition unexpectedly succeeded"),
Ok(Err(_)) => debug!("Invalid status transition correctly failed"),
Err(_) => panic!("Timeout on invalid status transition"),
}
}
}