feat(adr): implement ADR-0109, ADR-0110, and ADR-0111

- ADR-0109: Incremental Background AST Indexing & Differential Graph Updates via Tree-Sitter
- ADR-0110: Real-Time SSE Live Activity & Log Stream (/api/events/stream)
- ADR-0111: Automated Stale Symbol Pruning & Graph Tombstoning (sweep_graph_health auto_prune_stale_files)
This commit is contained in:
Riz Ashraf committed 2026-10-07 20:17:19 +01:00
1 parent d792b50343
commit 40cab6142b
6 files changed
+146 -7

No files matched your search

+78 -3
View File
@@ -89,11 +89,86 @@ fn should_review(path: &Path) -> bool {
}
async fn trigger_autonomous_review(path: &Path, state: Arc<MemoryState>) {
info!("Triggering autonomous review for {:?}", path);
info!("Triggering autonomous review & incremental AST index for {:?}", path);
state.broadcast_activity("AUTONOMOUS", &format!("Modified: {:?}", path.file_name().unwrap_or_default()));
info!("Autonomous review complete for {:?}", path);
}
// ADR-0109: Incremental Background AST Indexing & Differential Graph Updates
let ext = path.extension().and_then(|e| e.to_str()).unwrap_or("");
if matches!(ext, "rs" | "ts" | "js" | "py" | "go" | "java" | "c" | "cpp") {
if let Ok(content) = std::fs::read_to_string(path) {
let language = match ext {
"rs" => Some(tree_sitter_rust::LANGUAGE),
"ts" | "js" => Some(tree_sitter_typescript::LANGUAGE_TYPESCRIPT),
"py" => Some(tree_sitter_python::LANGUAGE),
"java" => Some(tree_sitter_java::LANGUAGE),
"c" => Some(tree_sitter_c::LANGUAGE),
"cpp" => Some(tree_sitter_cpp::LANGUAGE),
"go" => Some(tree_sitter_go::LANGUAGE),
_ => None,
};
if let Some(lang) = language {
let mut parser = tree_sitter::Parser::new();
if parser.set_language(&lang.into()).is_ok() {
if let Some(tree) = parser.parse(&content, None) {
let mut chunks = Vec::new();
crate::indexer::extract_chunks(tree.root_node(), &content, &mut chunks, ext);
let file_str = path.to_string_lossy().to_string();
let now = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap_or_default().as_secs();
state.modify_graph(|g| {
// Ensure File entity exists
g.entities.entry(file_str.clone()).or_insert_with(|| {
crate::models::Entity {
name: file_str.clone(),
entity_type: "File".to_string(),
namespace: "global".to_string(),
file_path: Some(file_str.clone()),
created_at: Some(now),
updated_at: Some(now),
..Default::default()
}
});
for (chunk_name, chunk_code, chunk_desc) in chunks {
let symbol_name = format!("{}::{}", file_str, chunk_name);
let symbol_type = if chunk_desc.contains("struct") {
"DataStructure".to_string()
} else {
"McpTool".to_string()
};
g.entities.insert(symbol_name.clone(), crate::models::Entity {
name: symbol_name.clone(),
entity_type: symbol_type,
observations: vec![format!("AST definition: {} chars", chunk_code.len())],
namespace: "global".to_string(),
file_path: Some(file_str.clone()),
created_at: Some(now),
updated_at: Some(now),
..Default::default()
});
let rel = crate::models::Relation {
from: file_str.clone(),
to: symbol_name,
relation_type: "declares".to_string(),
namespace: "global".to_string(),
..Default::default()
};
if !g.relations.contains(&rel) {
g.relations.push(rel);
}
}
});
}
}
}
}
}
info!("Autonomous review & incremental AST index complete for {:?}", path);
}
#[cfg(test)]
mod tests {
use super::*;