use crate::connectome_manager::ConnectomeManager;
use crate::models::{CorticalArea, CorticalID};
use crate::types::{BduError, BduResult};
use feagi_evolutionary::RuntimeGenome;
use feagi_npu_neural::types::{Precision, QuantizationSpec};
use parking_lot::RwLock;
use std::sync::Arc;
use tracing::{debug, error, info, trace, warn};
fn autogen_subregion_display_name(genome_title: &str) -> String {
let t = genome_title.trim();
if t.is_empty() || t.eq_ignore_ascii_case("untitled") {
"Autogen Circuit".to_string()
} else {
t.to_string()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DevelopmentStage {
Initialization,
Corticogenesis,
Voxelogenesis,
Neurogenesis,
Synaptogenesis,
Completed,
Failed,
}
#[derive(Debug, Clone)]
pub struct DevelopmentProgress {
pub stage: DevelopmentStage,
pub progress: u8,
pub cortical_areas_created: usize,
pub neurons_created: usize,
pub synapses_created: usize,
pub duration_ms: u64,
}
impl Default for DevelopmentProgress {
fn default() -> Self {
Self {
stage: DevelopmentStage::Initialization,
progress: 0,
cortical_areas_created: 0,
neurons_created: 0,
synapses_created: 0,
duration_ms: 0,
}
}
}
pub struct Neuroembryogenesis {
connectome_manager: Arc<RwLock<ConnectomeManager>>,
progress: Arc<RwLock<DevelopmentProgress>>,
start_time: std::time::Instant,
}
impl Neuroembryogenesis {
pub fn new(connectome_manager: Arc<RwLock<ConnectomeManager>>) -> Self {
Self {
connectome_manager,
progress: Arc::new(RwLock::new(DevelopmentProgress::default())),
start_time: std::time::Instant::now(),
}
}
pub fn get_progress(&self) -> DevelopmentProgress {
self.progress.read().clone()
}
fn sync_core_neuron_params(&self, cortical_idx: u32, area: &CorticalArea) -> BduResult<()> {
use crate::models::CorticalAreaExt;
let npu_arc = {
let manager = self.connectome_manager.read();
manager
.get_npu()
.cloned()
.ok_or_else(|| BduError::Internal("NPU not connected".to_string()))?
};
let mut npu_lock = npu_arc
.lock()
.map_err(|e| BduError::Internal(format!("Failed to lock NPU: {}", e)))?;
npu_lock.update_cortical_area_threshold_with_gradient(
cortical_idx,
area.firing_threshold(),
area.firing_threshold_increment_x(),
area.firing_threshold_increment_y(),
area.firing_threshold_increment_z(),
);
npu_lock.update_cortical_area_threshold_limit(cortical_idx, area.firing_threshold_limit());
npu_lock.update_cortical_area_leak(cortical_idx, area.leak_coefficient());
npu_lock.update_cortical_area_excitability(cortical_idx, area.neuron_excitability());
npu_lock.update_cortical_area_refractory_period(cortical_idx, area.refractory_period());
npu_lock.update_cortical_area_consecutive_fire_limit(
cortical_idx,
area.consecutive_fire_count() as u16,
);
npu_lock.update_cortical_area_snooze_period(cortical_idx, area.snooze_period());
npu_lock.update_cortical_area_mp_charge_accumulation(
cortical_idx,
area.mp_charge_accumulation(),
);
Ok(())
}
pub fn add_cortical_areas(
&mut self,
areas: Vec<CorticalArea>,
genome: &RuntimeGenome,
) -> BduResult<(usize, usize)> {
info!(target: "feagi-bdu", "🧬 Incrementally adding {} cortical areas", areas.len());
let mut total_neurons = 0;
let mut total_synapses = 0;
for area in &areas {
let mut manager = self.connectome_manager.write();
manager.add_cortical_area(area.clone())?;
info!(target: "feagi-bdu", " ✓ Added cortical area structure: {}", area.cortical_id.as_base_64());
}
use feagi_structures::genomic::cortical_area::CoreCorticalType;
let death_id = CoreCorticalType::Death.to_cortical_id();
let power_id = CoreCorticalType::Power.to_cortical_id();
let fatigue_id = CoreCorticalType::Fatigue.to_cortical_id();
let pain_id = CoreCorticalType::Pain.to_cortical_id();
let pleasure_id = CoreCorticalType::Pleasure.to_cortical_id();
let fear_id = CoreCorticalType::Fear.to_cortical_id();
let hope_id = CoreCorticalType::Hope.to_cortical_id();
let mut core_areas = Vec::new();
let mut other_areas = Vec::new();
for area in &areas {
if area.cortical_id == death_id {
core_areas.push((0, area)); } else if area.cortical_id == power_id {
core_areas.push((1, area)); } else if area.cortical_id == fatigue_id {
core_areas.push((2, area)); } else if area.cortical_id == pain_id {
core_areas.push((3, area)); } else if area.cortical_id == pleasure_id {
core_areas.push((4, area)); } else if area.cortical_id == fear_id {
core_areas.push((5, area)); } else if area.cortical_id == hope_id {
core_areas.push((6, area)); } else {
other_areas.push(area);
}
}
core_areas.sort_by_key(|(idx, _)| *idx);
if !core_areas.is_empty() {
info!(target: "feagi-bdu", " 🎯 Creating core area neurons FIRST ({} areas) for deterministic IDs", core_areas.len());
for (core_idx, area) in &core_areas {
let existing_core_neurons = {
let manager = self.connectome_manager.read();
let npu = manager.get_npu();
match npu {
Some(npu_arc) => {
let npu_lock = npu_arc.lock();
match npu_lock {
Ok(npu_guard) => {
npu_guard.get_neurons_in_cortical_area(*core_idx).len()
}
Err(_) => 0,
}
}
None => 0,
}
};
if existing_core_neurons > 0 {
self.sync_core_neuron_params(*core_idx, area)?;
let refreshed = {
let manager = self.connectome_manager.read();
manager.refresh_neuron_count_for_area(&area.cortical_id)
};
let count = refreshed.unwrap_or(existing_core_neurons);
total_neurons += count;
info!(
target: "feagi-bdu",
" ↪ Skipping core neuron creation for {} (existing={}, idx={})",
area.cortical_id.as_base_64(),
count,
core_idx
);
continue;
}
let neurons_created = {
let mut manager = self.connectome_manager.write();
manager.create_neurons_for_area(&area.cortical_id)
};
match neurons_created {
Ok(count) => {
total_neurons += count as usize;
info!(target: "feagi-bdu", " ✅ Created {} neurons for core area {} (deterministic ID: neuron {})",
count, area.cortical_id.as_base_64(), core_idx);
}
Err(e) => {
error!(target: "feagi-bdu", " ❌ FATAL: Failed to create neurons for core area {}: {}", area.cortical_id.as_base_64(), e);
return Err(e);
}
}
}
}
for area in &other_areas {
let neurons_created = {
let mut manager = self.connectome_manager.write();
manager.create_neurons_for_area(&area.cortical_id)
};
match neurons_created {
Ok(count) => {
total_neurons += count as usize;
trace!(
target: "feagi-bdu",
"Created {} neurons for area {}",
count,
area.cortical_id.as_base_64()
);
}
Err(e) => {
error!(target: "feagi-bdu", " ❌ FATAL: Failed to create neurons for {}: {}", area.cortical_id.as_base_64(), e);
return Err(e);
}
}
}
for area in &areas {
let has_dstmap = area
.properties
.get("cortical_mapping_dst")
.and_then(|v| v.as_object())
.map(|m| !m.is_empty())
.unwrap_or(false);
if !has_dstmap {
debug!(target: "feagi-bdu", " No mappings for area {}", area.cortical_id.as_base_64());
continue;
}
let synapses_created = {
let mut manager = self.connectome_manager.write();
manager.apply_cortical_mapping(&area.cortical_id)
};
match synapses_created {
Ok(count) => {
total_synapses += count as usize;
trace!(
target: "feagi-bdu",
"Created {} synapses for area {}",
count,
area.cortical_id
);
}
Err(e) => {
warn!(target: "feagi-bdu", " ⚠️ Failed to create synapses for {}: {}", area.cortical_id, e);
let estimated = estimate_synapses_for_area(area, genome);
total_synapses += estimated;
}
}
}
info!(target: "feagi-bdu", "✅ Incremental add complete: {} areas, {} neurons, {} synapses",
areas.len(), total_neurons, total_synapses);
Ok((total_neurons, total_synapses))
}
pub fn develop_from_genome(&mut self, genome: &RuntimeGenome) -> BduResult<()> {
info!(target: "feagi-bdu","🧬 Starting neuroembryogenesis for genome: {}", genome.metadata.genome_id);
let _quantization_precision = &genome.physiology.quantization_precision;
let quant_spec = QuantizationSpec::default();
info!(target: "feagi-bdu",
" Quantization precision: {:?} (range: [{}, {}] for membrane potential)",
quant_spec.precision,
quant_spec.membrane_potential_min,
quant_spec.membrane_potential_max
);
match quant_spec.precision {
Precision::FP32 => {
info!(target: "feagi-bdu", " ✓ Using FP32 (32-bit floating-point) - highest precision");
info!(target: "feagi-bdu", " Memory usage: Baseline (4 bytes/neuron for membrane potential)");
}
Precision::INT8 => {
info!(target: "feagi-bdu", " ✓ Using INT8 (8-bit integer) - memory efficient");
info!(target: "feagi-bdu", " Memory reduction: 42% (1 byte/neuron for membrane potential)");
info!(target: "feagi-bdu", " Quantization range: [{}, {}]",
quant_spec.membrane_potential_min,
quant_spec.membrane_potential_max);
}
Precision::FP16 => {
warn!(target: "feagi-bdu", " FP16 quantization requested but not yet implemented.");
warn!(target: "feagi-bdu", " FP16 support planned for future GPU optimization.");
}
}
info!(target: "feagi-bdu", " ✓ Quantization handled by DynamicNPU (dispatches at runtime)");
self.update_stage(DevelopmentStage::Initialization, 0);
self.corticogenesis(genome)?;
self.voxelogenesis(genome)?;
self.neurogenesis(genome)?;
self.synaptogenesis(genome)?;
self.update_stage(DevelopmentStage::Completed, 100);
let progress = self.progress.read();
info!(target: "feagi-bdu",
"✅ Neuroembryogenesis completed in {}ms: {} cortical areas, {} neurons, {} synapses",
progress.duration_ms,
progress.cortical_areas_created,
progress.neurons_created,
progress.synapses_created
);
Ok(())
}
fn corticogenesis(&mut self, genome: &RuntimeGenome) -> BduResult<()> {
self.update_stage(DevelopmentStage::Corticogenesis, 0);
info!(target: "feagi-bdu","🧠 Stage 1: Corticogenesis - Creating {} cortical areas", genome.cortical_areas.len());
info!(target: "feagi-bdu","🔍 Genome brain_regions check: is_empty={}, count={}",
genome.brain_regions.is_empty(), genome.brain_regions.len());
if !genome.brain_regions.is_empty() {
info!(target: "feagi-bdu"," Existing regions: {:?}", genome.brain_regions.keys().collect::<Vec<_>>());
}
let total_areas = genome.cortical_areas.len();
for (idx, (cortical_id, area)) in genome.cortical_areas.iter().enumerate() {
{
let mut manager = self.connectome_manager.write();
manager.add_cortical_area(area.clone())?;
}
let progress_pct = ((idx + 1) * 100 / total_areas.max(1)) as u8;
self.update_progress(|p| {
p.cortical_areas_created = idx + 1;
p.progress = progress_pct;
});
trace!(target: "feagi-bdu", "Created cortical area: {} ({})", cortical_id, area.name);
}
info!(target: "feagi-bdu","🔍 BRAIN REGION AUTO-GEN CHECK: genome.brain_regions.is_empty() = {}", genome.brain_regions.is_empty());
let (brain_regions_to_add, region_parent_map) = if genome.brain_regions.is_empty() {
info!(target: "feagi-bdu"," ✅ TRIGGERING AUTO-GENERATION: No brain_regions in genome - auto-generating default root region");
info!(target: "feagi-bdu"," 📊 Genome has {} cortical areas to process", genome.cortical_areas.len());
let all_cortical_ids = genome.cortical_areas.keys().cloned().collect::<Vec<_>>();
info!(target: "feagi-bdu"," 📊 Collected {} cortical area IDs: {:?}", all_cortical_ids.len(),
if all_cortical_ids.len() <= 5 {
format!("{:?}", all_cortical_ids.iter().map(|id| id.to_string()).collect::<Vec<_>>())
} else {
format!("{:?}...", all_cortical_ids[0..5].iter().map(|id| id.to_string()).collect::<Vec<_>>())
});
let mut auto_inputs = Vec::new();
let mut auto_outputs = Vec::new();
let mut ipu_areas = Vec::new(); let mut opu_areas = Vec::new(); let mut core_areas = Vec::new(); let mut custom_memory_areas = Vec::new();
for (area_id, area) in genome.cortical_areas.iter() {
let area_id_str = area_id.to_string();
let category = if area_id_str.starts_with("___") {
"CORE"
} else if let Ok(cortical_type) = area.cortical_id.as_cortical_type() {
use feagi_structures::genomic::cortical_area::CorticalAreaType;
match cortical_type {
CorticalAreaType::Core(_) => "CORE",
CorticalAreaType::BrainInput(_) => "IPU",
CorticalAreaType::BrainOutput(_) => "OPU",
CorticalAreaType::Memory(_) => "MEMORY",
CorticalAreaType::Custom(_) => "CUSTOM",
}
} else {
let cortical_group = area
.properties
.get("cortical_group")
.and_then(|v| v.as_str())
.map(|s| s.to_uppercase());
match cortical_group.as_deref() {
Some("IPU") => "IPU",
Some("OPU") => "OPU",
Some("CORE") => "CORE",
Some("MEMORY") => "MEMORY",
Some("CUSTOM") => "CUSTOM",
_ => "CUSTOM", }
};
if ipu_areas.len() + opu_areas.len() + core_areas.len() + custom_memory_areas.len()
< 5
{
let source = if area.cortical_id.as_cortical_type().is_ok() {
"cortical_id_type"
} else if area.properties.contains_key("cortical_group") {
"cortical_group"
} else {
"default_fallback"
};
if area.cortical_id.as_cortical_type().is_ok() {
let type_desc = crate::cortical_type_utils::describe_cortical_type(area);
let frame_handling =
if crate::cortical_type_utils::uses_absolute_frames(area) {
"absolute"
} else if crate::cortical_type_utils::uses_incremental_frames(area) {
"incremental"
} else {
"n/a"
};
info!(target: "feagi-bdu"," 🔍 {}, frames={}, source={}",
type_desc, frame_handling, source);
} else {
info!(target: "feagi-bdu"," 🔍 Area {}: category={}, source={}",
area_id_str, category, source);
}
}
match category {
"IPU" => {
ipu_areas.push(*area_id);
auto_inputs.push(*area_id);
}
"OPU" => {
opu_areas.push(*area_id);
auto_outputs.push(*area_id);
}
"CORE" => {
core_areas.push(*area_id);
}
"MEMORY" | "CUSTOM" => {
custom_memory_areas.push(*area_id);
}
_ => {}
}
}
info!(target: "feagi-bdu"," 📊 Classification complete: IPU={}, OPU={}, CORE={}, CUSTOM/MEMORY={}",
ipu_areas.len(), opu_areas.len(), core_areas.len(), custom_memory_areas.len());
use feagi_structures::genomic::brain_regions::{BrainRegion, RegionID, RegionType};
let mut regions_map = std::collections::HashMap::new();
let mut root_area_ids = Vec::new();
root_area_ids.extend(ipu_areas.iter().cloned());
root_area_ids.extend(opu_areas.iter().cloned());
root_area_ids.extend(core_areas.iter().cloned());
let (root_inputs, root_outputs) =
Self::analyze_region_io(&root_area_ids, &genome.cortical_areas);
let root_region_id = RegionID::new();
let root_region_id_str = root_region_id.to_string();
let mut root_region = BrainRegion::new(
root_region_id,
"Root Brain Region".to_string(),
RegionType::Undefined,
)
.expect("Failed to create root region")
.with_areas(root_area_ids.iter().cloned());
if !root_inputs.is_empty() {
root_region
.add_property("inputs".to_string(), serde_json::json!(root_inputs.clone()));
}
if !root_outputs.is_empty() {
root_region.add_property(
"outputs".to_string(),
serde_json::json!(root_outputs.clone()),
);
}
info!(target: "feagi-bdu"," ✅ Created root region with {} areas (IPU={}, OPU={}, CORE={}) - analyzed: {} inputs, {} outputs",
root_area_ids.len(), ipu_areas.len(), opu_areas.len(), core_areas.len(),
root_inputs.len(), root_outputs.len());
let mut subregion_id = None;
if !custom_memory_areas.is_empty() {
let mut custom_memory_strs: Vec<String> = custom_memory_areas
.iter()
.map(|id| id.as_base_64())
.collect();
custom_memory_strs.sort(); let combined = custom_memory_strs.join("|");
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
let mut hasher = DefaultHasher::new();
combined.hash(&mut hasher);
let hash = hasher.finish();
let hash_hex = format!("{:08x}", hash as u32);
let region_id = format!("region_autogen_{}", hash_hex);
let (subregion_inputs, subregion_outputs) =
Self::analyze_region_io(&custom_memory_areas, &genome.cortical_areas);
let autogen_position =
Self::calculate_autogen_region_position(&root_area_ids, genome);
let subregion_name = autogen_subregion_display_name(&genome.metadata.genome_title);
let mut subregion = BrainRegion::new(
RegionID::new(), subregion_name,
RegionType::Undefined, )
.expect("Failed to create subregion")
.with_areas(custom_memory_areas.iter().cloned());
subregion.add_property(
"coordinate_3d".to_string(),
serde_json::json!(autogen_position),
);
subregion.add_property("coordinate_2d".to_string(), serde_json::json!([0, 0]));
if !subregion_inputs.is_empty() {
subregion.add_property(
"inputs".to_string(),
serde_json::json!(subregion_inputs.clone()),
);
}
if !subregion_outputs.is_empty() {
subregion.add_property(
"outputs".to_string(),
serde_json::json!(subregion_outputs.clone()),
);
}
let subregion_id_str = subregion.region_id.to_string();
info!(target: "feagi-bdu"," ✅ Created subregion '{}' with {} CUSTOM/MEMORY areas ({} inputs, {} outputs)",
region_id, custom_memory_areas.len(), subregion_inputs.len(), subregion_outputs.len());
regions_map.insert(subregion_id_str.clone(), subregion);
subregion_id = Some(subregion_id_str);
}
regions_map.insert(root_region_id_str.clone(), root_region);
let total_inputs = root_inputs.len()
+ if let Some(ref sid) = subregion_id {
regions_map
.get(sid)
.and_then(|r| r.properties.get("inputs"))
.and_then(|v| v.as_array())
.map(|a| a.len())
.unwrap_or(0)
} else {
0
};
let total_outputs = root_outputs.len()
+ if let Some(ref sid) = subregion_id {
regions_map
.get(sid)
.and_then(|r| r.properties.get("outputs"))
.and_then(|v| v.as_array())
.map(|a| a.len())
.unwrap_or(0)
} else {
0
};
info!(target: "feagi-bdu"," ✅ Auto-generated {} brain region(s) with {} total cortical areas ({} total inputs, {} total outputs)",
regions_map.len(), all_cortical_ids.len(), total_inputs, total_outputs);
let mut parent_map = std::collections::HashMap::new();
if let Some(ref sub_id) = subregion_id {
parent_map.insert(sub_id.clone(), root_region_id_str.clone());
info!(target: "feagi-bdu"," 🔗 Parent relationship: {} -> {}", sub_id, root_region_id_str);
}
(regions_map, parent_map)
} else {
info!(target: "feagi-bdu"," 📋 Genome already has {} brain regions - using existing structure", genome.brain_regions.len());
let mut region_parent_map: std::collections::HashMap<String, String> =
std::collections::HashMap::new();
for (region_id, region) in &genome.brain_regions {
if let Some(pid) = region
.properties
.get("parent_region_id")
.and_then(|v| v.as_str())
{
region_parent_map.insert(region_id.clone(), pid.to_string());
}
}
if region_parent_map.is_empty() {
if let Some((root_id, _)) = genome
.brain_regions
.iter()
.find(|(_, r)| r.name == "Root Brain Region")
{
for (region_id, region) in &genome.brain_regions {
if region.name == "Root Brain Region" {
continue;
}
region_parent_map.insert(region_id.clone(), root_id.clone());
}
if !region_parent_map.is_empty() {
info!(target: "feagi-bdu",
" 🔗 Inferred {} sub-region parent link(s) under root {}",
region_parent_map.len(),
root_id
);
}
} else {
warn!(target: "feagi-bdu",
" ⚠️ brain_regions present but no 'Root Brain Region' and no parent_region_id — hierarchy may not load in BV"
);
}
}
(genome.brain_regions.clone(), region_parent_map)
};
{
let mut manager = self.connectome_manager.write();
let brain_region_count = brain_regions_to_add.len();
info!(target: "feagi-bdu"," Adding {} brain regions from genome", brain_region_count);
let root_entry = brain_regions_to_add
.iter()
.find(|(_, region)| region.name == "Root Brain Region");
if let Some((root_id, root_region)) = root_entry {
manager.add_brain_region(root_region.clone(), None)?;
debug!(target: "feagi-bdu"," ✓ Added brain region: {} (Root Brain Region) [parent=None]", root_id);
}
for (region_id, region) in brain_regions_to_add.iter() {
if region.name == "Root Brain Region" {
continue; }
let parent_id = region_parent_map.get(region_id).cloned();
manager.add_brain_region(region.clone(), parent_id.clone())?;
debug!(target: "feagi-bdu"," ✓ Added brain region: {} ({}) [parent={:?}]",
region_id, region.name, parent_id);
}
info!(target: "feagi-bdu"," Total brain regions in ConnectomeManager: {}", manager.get_brain_region_ids().len());
}
self.update_stage(DevelopmentStage::Corticogenesis, 100);
info!(target: "feagi-bdu"," ✅ Corticogenesis complete: {} cortical areas created", total_areas);
Ok(())
}
fn voxelogenesis(&mut self, _genome: &RuntimeGenome) -> BduResult<()> {
self.update_stage(DevelopmentStage::Voxelogenesis, 0);
info!(target: "feagi-bdu","📐 Stage 2: Voxelogenesis - Establishing spatial framework");
self.update_stage(DevelopmentStage::Voxelogenesis, 100);
info!(target: "feagi-bdu"," ✅ Voxelogenesis complete: Spatial framework established");
Ok(())
}
fn neurogenesis(&mut self, genome: &RuntimeGenome) -> BduResult<()> {
self.update_stage(DevelopmentStage::Neurogenesis, 0);
info!(target: "feagi-bdu","🔬 Stage 3: Neurogenesis - Generating neurons (SIMD-optimized batches)");
let expected_neurons = genome.stats.innate_neuron_count;
info!(target: "feagi-bdu"," Expected innate neurons from genome: {}", expected_neurons);
use feagi_structures::genomic::cortical_area::CoreCorticalType;
let death_id = CoreCorticalType::Death.to_cortical_id();
let power_id = CoreCorticalType::Power.to_cortical_id();
let fatigue_id = CoreCorticalType::Fatigue.to_cortical_id();
let pain_id = CoreCorticalType::Pain.to_cortical_id();
let pleasure_id = CoreCorticalType::Pleasure.to_cortical_id();
let fear_id = CoreCorticalType::Fear.to_cortical_id();
let hope_id = CoreCorticalType::Hope.to_cortical_id();
let mut core_areas = Vec::new();
let mut other_areas = Vec::new();
for (cortical_id, area) in genome.cortical_areas.iter() {
if *cortical_id == death_id {
core_areas.push((0, *cortical_id, area)); } else if *cortical_id == power_id {
core_areas.push((1, *cortical_id, area)); } else if *cortical_id == fatigue_id {
core_areas.push((2, *cortical_id, area)); } else if *cortical_id == pain_id {
core_areas.push((3, *cortical_id, area)); } else if *cortical_id == pleasure_id {
core_areas.push((4, *cortical_id, area)); } else if *cortical_id == fear_id {
core_areas.push((5, *cortical_id, area)); } else if *cortical_id == hope_id {
core_areas.push((6, *cortical_id, area)); } else {
other_areas.push((*cortical_id, area));
}
}
core_areas.sort_by_key(|(idx, _, _)| *idx);
info!(target: "feagi-bdu"," 🎯 Creating core area neurons FIRST ({} areas) for deterministic IDs", core_areas.len());
let mut total_neurons_created = 0;
let mut processed_count = 0;
let total_areas = genome.cortical_areas.len();
for (core_idx, cortical_id, area) in &core_areas {
let existing_core_neurons = {
let manager = self.connectome_manager.read();
let npu = manager.get_npu();
match npu {
Some(npu_arc) => {
let npu_lock = npu_arc.lock();
match npu_lock {
Ok(npu_guard) => {
npu_guard.get_neurons_in_cortical_area(*core_idx).len()
}
Err(_) => 0,
}
}
None => 0,
}
};
if existing_core_neurons > 0 {
self.sync_core_neuron_params(*core_idx, area)?;
let refreshed = {
let manager = self.connectome_manager.read();
manager.refresh_neuron_count_for_area(cortical_id)
};
let count = refreshed.unwrap_or(existing_core_neurons);
total_neurons_created += count;
info!(
target: "feagi-bdu",
" ↪ Skipping core neuron creation for {} (existing={}, idx={})",
cortical_id.as_base_64(),
count,
core_idx
);
processed_count += 1;
let progress_pct = (processed_count * 100 / total_areas.max(1)) as u8;
self.update_progress(|p| {
p.neurons_created = total_neurons_created;
p.progress = progress_pct;
});
continue;
}
let per_voxel_count = area
.properties
.get("neurons_per_voxel")
.and_then(|v| v.as_u64())
.unwrap_or(1) as i64;
let cortical_id_str = cortical_id.to_string();
info!(target: "feagi-bdu"," 🔋 [CORE-AREA {}] {} - dimensions: {:?}, per_voxel: {}",
core_idx, cortical_id_str, area.dimensions, per_voxel_count);
if per_voxel_count == 0 {
warn!(target: "feagi-bdu"," ⚠️ Skipping core area {} - per_voxel_neuron_cnt is 0", cortical_id_str);
continue;
}
let neurons_created = {
let manager_arc = self.connectome_manager.clone();
let mut manager = manager_arc.write();
manager.create_neurons_for_area(cortical_id)
};
match neurons_created {
Ok(count) => {
total_neurons_created += count as usize;
info!(target: "feagi-bdu"," ✅ Created {} neurons for core area {} (deterministic ID: neuron {})",
count, cortical_id_str, core_idx);
}
Err(e) => {
error!(target: "feagi-bdu"," ❌ FATAL: Failed to create neurons for core area {}: {}", cortical_id_str, e);
return Err(e);
}
}
processed_count += 1;
let progress_pct = (processed_count * 100 / total_areas.max(1)) as u8;
self.update_progress(|p| {
p.neurons_created = total_neurons_created;
p.progress = progress_pct;
});
}
info!(target: "feagi-bdu"," 📦 Creating neurons for {} other areas", other_areas.len());
for (cortical_id, area) in &other_areas {
let _per_voxel_count = area
.properties
.get("neurons_per_voxel")
.and_then(|v| v.as_u64())
.unwrap_or(1) as i64;
let per_voxel_count = area
.properties
.get("neurons_per_voxel")
.and_then(|v| v.as_u64())
.unwrap_or(1) as i64;
let cortical_id_str = cortical_id.to_string();
if per_voxel_count == 0 {
warn!(target: "feagi-bdu"," ⚠️ Skipping area {} - per_voxel_neuron_cnt is 0 (will have NO neurons!)", cortical_id_str);
continue;
}
let neurons_created = {
let manager_arc = self.connectome_manager.clone();
let mut manager = manager_arc.write();
manager.create_neurons_for_area(cortical_id)
};
match neurons_created {
Ok(count) => {
total_neurons_created += count as usize;
trace!(
target: "feagi-bdu",
"Created {} neurons for area {}",
count,
cortical_id_str
);
}
Err(e) => {
warn!(target: "feagi-bdu"," Failed to create neurons for {}: {} (NPU may not be connected)",
cortical_id_str, e);
let total_voxels = area.dimensions.width as usize
* area.dimensions.height as usize
* area.dimensions.depth as usize;
let expected = total_voxels * per_voxel_count as usize;
total_neurons_created += expected;
}
}
processed_count += 1;
let progress_pct = (processed_count * 100 / total_areas.max(1)) as u8;
self.update_progress(|p| {
p.neurons_created = total_neurons_created;
p.progress = progress_pct;
});
}
if expected_neurons > 0 && total_neurons_created != expected_neurons {
trace!(target: "feagi-bdu",
created_neurons = total_neurons_created,
genome_stats_innate = expected_neurons,
"Neuron creation complete (genome stats may only count innate neurons)"
);
}
self.update_stage(DevelopmentStage::Neurogenesis, 100);
info!(target: "feagi-bdu"," ✅ Neurogenesis complete: {} neurons created", total_neurons_created);
Ok(())
}
fn synaptogenesis(&mut self, genome: &RuntimeGenome) -> BduResult<()> {
self.update_stage(DevelopmentStage::Synaptogenesis, 0);
info!(target: "feagi-bdu","🔗 Stage 4: Synaptogenesis - Forming synaptic connections (SIMD-optimized batches)");
let expected_synapses = genome.stats.innate_synapse_count;
info!(target: "feagi-bdu"," Expected innate synapses from genome: {}", expected_synapses);
self.rebuild_memory_twin_mappings_from_genome(genome)?;
let mut total_synapses_created = 0;
let total_areas = genome.cortical_areas.len();
for (idx, (_src_cortical_id, src_area)) in genome.cortical_areas.iter().enumerate() {
let has_dstmap = src_area
.properties
.get("cortical_mapping_dst")
.and_then(|v| v.as_object())
.map(|m| !m.is_empty())
.unwrap_or(false);
if !has_dstmap {
trace!(target: "feagi-bdu", "No dstmap for area {}", &src_area.cortical_id);
continue;
}
let src_cortical_id = &src_area.cortical_id;
let src_cortical_id_str = src_cortical_id.to_string(); let synapses_created = {
let manager_arc = self.connectome_manager.clone();
let mut manager = manager_arc.write();
if let Some(dstmap) = src_area.properties.get("cortical_mapping_dst") {
if let Some(area) = manager.get_cortical_area_mut(src_cortical_id) {
area.properties
.insert("cortical_mapping_dst".to_string(), dstmap.clone());
}
}
manager.apply_cortical_mapping(src_cortical_id)
};
match synapses_created {
Ok(count) => {
total_synapses_created += count as usize;
trace!(
target: "feagi-bdu",
"Created {} synapses for area {}",
count,
src_cortical_id_str
);
}
Err(e) => {
warn!(target: "feagi-bdu"," Failed to create synapses for {}: {} (NPU may not be connected)",
src_cortical_id_str, e);
let estimated = estimate_synapses_for_area(src_area, genome);
total_synapses_created += estimated;
}
}
let progress_pct = ((idx + 1) * 100 / total_areas.max(1)) as u8;
self.update_progress(|p| {
p.synapses_created = total_synapses_created;
p.progress = progress_pct;
});
}
let npu_arc = {
let manager = self.connectome_manager.read();
manager.get_npu().cloned()
};
if let Some(npu_arc) = npu_arc {
let mut npu_lock = npu_arc
.lock()
.map_err(|e| BduError::Internal(format!("Failed to lock NPU: {}", e)))?;
npu_lock.rebuild_synapse_index();
let manager = self.connectome_manager.read();
manager.update_cached_synapse_count();
}
#[cfg(feature = "plasticity")]
{
use feagi_evolutionary::extract_memory_properties;
use feagi_npu_plasticity::{MemoryNeuronLifecycleConfig, PlasticityExecutor};
let manager = self.connectome_manager.read();
if let Some(executor) = manager.get_plasticity_executor() {
let mut registered_count = 0;
for area_id in manager.get_cortical_area_ids() {
if let Some(area) = manager.get_cortical_area(area_id) {
if let Some(mem_props) = extract_memory_properties(&area.properties) {
let upstream_areas =
manager.get_episodic_memory_upstream_cortical_areas(area_id);
if let Some(npu_arc) = manager.get_npu() {
if let Ok(mut npu) = npu_arc.lock() {
let existing_configs = npu.get_all_fire_ledger_configs();
for &upstream_idx in &upstream_areas {
let existing = existing_configs
.iter()
.find(|(idx, _)| *idx == upstream_idx)
.map(|(_, w)| *w)
.unwrap_or(0);
let desired = mem_props.temporal_depth as usize;
let resolved = existing.max(desired);
if resolved != existing {
if let Err(e) = npu.configure_fire_ledger_window(
upstream_idx,
resolved,
) {
warn!(
target: "feagi-bdu",
"Failed to configure FireLedger window for upstream area idx={} (requested={}): {}",
upstream_idx,
resolved,
e
);
}
}
}
} else {
warn!(target: "feagi-bdu", "Failed to lock NPU for FireLedger configuration");
}
}
if let Ok(exec) = executor.lock() {
let lifecycle_config = MemoryNeuronLifecycleConfig {
initial_lifespan: mem_props.init_lifespan,
lifespan_growth_rate: mem_props.lifespan_growth_rate,
longterm_threshold: mem_props.longterm_threshold,
max_reactivations: 1000,
};
exec.register_memory_area(
area.cortical_idx,
area_id.as_base_64(),
mem_props.temporal_depth,
upstream_areas.clone(),
Some(lifecycle_config),
mem_props.mp_learning_enabled,
);
registered_count += 1;
}
}
}
}
let _ = registered_count; }
}
if expected_synapses > 0 {
let diff = (total_synapses_created as i64 - expected_synapses as i64).abs();
let diff_pct = (diff as f64 / expected_synapses.max(1) as f64) * 100.0;
if diff_pct > 10.0 {
warn!(target: "feagi-bdu",
"Synapse count variance: created {} but genome stats expected {} ({:.1}% difference)",
total_synapses_created, expected_synapses, diff_pct
);
} else {
info!(target: "feagi-bdu",
"Synapse count matches genome stats within {:.1}% ({} vs {})",
diff_pct, total_synapses_created, expected_synapses
);
}
}
self.update_stage(DevelopmentStage::Synaptogenesis, 100);
info!(target: "feagi-bdu"," ✅ Synaptogenesis complete: {} synapses created", total_synapses_created);
Ok(())
}
fn rebuild_memory_twin_mappings_from_genome(
&mut self,
genome: &RuntimeGenome,
) -> BduResult<()> {
use feagi_structures::genomic::cortical_area::CorticalAreaType;
let mut repaired = 0usize;
for (memory_id, memory_area) in genome.cortical_areas.iter() {
let is_memory = matches!(
memory_area.cortical_id.as_cortical_type(),
Ok(CorticalAreaType::Memory(_))
) || memory_area
.properties
.get("is_mem_type")
.and_then(|v| v.as_bool())
.unwrap_or(false)
|| memory_area
.properties
.get("cortical_group")
.and_then(|v| v.as_str())
.is_some_and(|v| v.eq_ignore_ascii_case("MEMORY"));
if !is_memory {
continue;
}
let Some(dstmap) = memory_area
.properties
.get("cortical_mapping_dst")
.and_then(|v| v.as_object())
else {
continue;
};
for (dst_id_str, rules) in dstmap {
let Some(rule_array) = rules.as_array() else {
continue;
};
let has_replay = rule_array.iter().any(|rule| {
rule.get("morphology_id")
.and_then(|v| v.as_str())
.is_some_and(|id| id == "memory_replay")
});
if !has_replay {
continue;
}
let dst_id = match CorticalID::try_from_base_64(dst_id_str) {
Ok(id) => id,
Err(_) => {
warn!(
target: "feagi-bdu",
"Invalid twin cortical ID in memory_replay dstmap: {}",
dst_id_str
);
continue;
}
};
let Some(twin_area) = genome.cortical_areas.get(&dst_id) else {
continue;
};
let Some(upstream_id_str) = twin_area
.properties
.get("memory_twin_of")
.and_then(|v| v.as_str())
else {
continue;
};
let upstream_id = match CorticalID::try_from_base_64(upstream_id_str) {
Ok(id) => id,
Err(_) => {
warn!(
target: "feagi-bdu",
"Invalid memory_twin_of value on twin area {}: {}",
dst_id.as_base_64(),
upstream_id_str
);
continue;
}
};
let mut manager = self.connectome_manager.write();
if let Err(e) = manager.ensure_memory_twin_area(memory_id, &upstream_id) {
warn!(
target: "feagi-bdu",
"Failed to rebuild memory twin mapping for memory {} upstream {}: {}",
memory_id.as_base_64(),
upstream_id.as_base_64(),
e
);
continue;
}
repaired += 1;
}
}
info!(
target: "feagi-bdu",
"Rebuilt {} memory twin mapping(s) from genome",
repaired
);
Ok(())
}
}
fn estimate_synapses_for_area(
src_area: &CorticalArea,
genome: &feagi_evolutionary::RuntimeGenome,
) -> usize {
let dstmap = match src_area.properties.get("cortical_mapping_dst") {
Some(serde_json::Value::Object(map)) => map,
_ => return 0,
};
let mut total = 0;
for (dst_id, rules) in dstmap {
let dst_cortical_id = match feagi_evolutionary::string_to_cortical_id(dst_id) {
Ok(id) => id,
Err(_) => continue,
};
let dst_area = match genome.cortical_areas.get(&dst_cortical_id) {
Some(area) => area,
None => continue,
};
let rules_array = match rules.as_array() {
Some(arr) => arr,
None => continue,
};
for rule in rules_array {
let morphology_id = rule
.get("morphology_id")
.and_then(|v| v.as_str())
.unwrap_or("unknown");
let scalar = rule
.get("morphology_scalar")
.and_then(|v| v.as_i64())
.unwrap_or(1) as usize;
let src_per_voxel = src_area
.properties
.get("neurons_per_voxel")
.and_then(|v| v.as_u64())
.unwrap_or(1) as usize;
let dst_per_voxel = dst_area
.properties
.get("neurons_per_voxel")
.and_then(|v| v.as_u64())
.unwrap_or(1) as usize;
let src_voxels =
src_area.dimensions.width * src_area.dimensions.height * src_area.dimensions.depth;
let dst_voxels =
dst_area.dimensions.width * dst_area.dimensions.height * dst_area.dimensions.depth;
let src_neurons = src_voxels as usize * src_per_voxel;
let dst_neurons = dst_voxels as usize * dst_per_voxel as usize;
let count = match morphology_id {
"block_to_block" => src_neurons * dst_per_voxel * scalar,
"projector" | "transpose_xy" | "transpose_yz" | "transpose_xz"
| "centered_projector" => src_neurons * dst_neurons * scalar,
_ if morphology_id.contains("lateral") => src_neurons * scalar,
_ => (src_neurons * scalar).min(src_neurons * dst_neurons / 10),
};
total += count;
}
}
total
}
impl Neuroembryogenesis {
fn calculate_autogen_region_position(
root_area_ids: &[CorticalID],
genome: &feagi_evolutionary::RuntimeGenome,
) -> [i32; 3] {
if root_area_ids.is_empty() {
return [100, 0, 0];
}
let mut min_x = i32::MAX;
let mut max_x = i32::MIN;
let mut min_y = i32::MAX;
let mut max_y = i32::MIN;
let mut min_z = i32::MAX;
let mut max_z = i32::MIN;
for cortical_id in root_area_ids {
if let Some(area) = genome.cortical_areas.get(cortical_id) {
let pos: (i32, i32, i32) = area.position.into();
let dims = (
area.dimensions.width as i32,
area.dimensions.height as i32,
area.dimensions.depth as i32,
);
min_x = min_x.min(pos.0);
max_x = max_x.max(pos.0 + dims.0);
min_y = min_y.min(pos.1);
max_y = max_y.max(pos.1 + dims.1);
min_z = min_z.min(pos.2);
max_z = max_z.max(pos.2 + dims.2);
}
}
let bbox_width = (max_x - min_x).max(1);
let padding = (bbox_width / 5).max(50);
let autogen_x = max_x + padding;
let autogen_y = (min_y + max_y) / 2;
let autogen_z = (min_z + max_z) / 2;
info!(target: "feagi-bdu",
" 📐 Autogen position: ({}, {}, {}) [padding: {}]",
autogen_x, autogen_y, autogen_z, padding);
[autogen_x, autogen_y, autogen_z]
}
fn analyze_region_io(
region_area_ids: &[feagi_structures::genomic::cortical_area::CorticalID],
all_cortical_areas: &std::collections::HashMap<CorticalID, CorticalArea>,
) -> (Vec<String>, Vec<String>) {
let area_set: std::collections::HashSet<_> = region_area_ids.iter().cloned().collect();
let mut inputs = Vec::new();
let mut outputs = Vec::new();
let extract_destinations = |area: &CorticalArea| -> Vec<String> {
area.properties
.get("cortical_mapping_dst")
.and_then(|v| v.as_object())
.map(|obj| obj.keys().cloned().collect())
.unwrap_or_default()
};
for area_id in region_area_ids {
if let Some(area) = all_cortical_areas.get(area_id) {
let destinations = extract_destinations(area);
let external_destinations: Vec<_> = destinations
.iter()
.filter_map(|dest| feagi_evolutionary::string_to_cortical_id(dest).ok())
.filter(|dest_id| !area_set.contains(dest_id))
.collect();
if !external_destinations.is_empty() {
outputs.push(area_id.as_base_64());
}
}
}
for (source_area_id, source_area) in all_cortical_areas.iter() {
if area_set.contains(source_area_id) {
continue;
}
let destinations = extract_destinations(source_area);
for dest_str in destinations {
if let Ok(dest_id) = feagi_evolutionary::string_to_cortical_id(&dest_str) {
if area_set.contains(&dest_id) {
let dest_string = dest_id.as_base_64();
if !inputs.contains(&dest_string) {
inputs.push(dest_string);
}
}
}
}
}
(inputs, outputs)
}
fn update_stage(&self, stage: DevelopmentStage, progress: u8) {
let mut p = self.progress.write();
p.stage = stage;
p.progress = progress;
p.duration_ms = self.start_time.elapsed().as_millis() as u64;
}
fn update_progress<F>(&self, f: F)
where
F: FnOnce(&mut DevelopmentProgress),
{
let mut p = self.progress.write();
f(&mut p);
p.duration_ms = self.start_time.elapsed().as_millis() as u64;
}
}
#[cfg(test)]
mod tests {
use super::*;
use feagi_evolutionary::create_genome_with_core_morphologies;
use feagi_structures::genomic::cortical_area::CorticalAreaDimensions;
#[test]
fn test_neuroembryogenesis_creation() {
let manager = ConnectomeManager::instance();
let neuro = Neuroembryogenesis::new(manager);
let progress = neuro.get_progress();
assert_eq!(progress.stage, DevelopmentStage::Initialization);
assert_eq!(progress.progress, 0);
}
#[test]
fn autogen_subregion_display_name_uses_title_when_meaningful() {
assert_eq!(
autogen_subregion_display_name("My Shared Circuit"),
"My Shared Circuit"
);
}
#[test]
fn autogen_subregion_display_name_falls_back_for_untitled() {
assert_eq!(
autogen_subregion_display_name("Untitled"),
"Autogen Circuit"
);
assert_eq!(
autogen_subregion_display_name("untitled"),
"Autogen Circuit"
);
}
#[test]
fn autogen_subregion_display_name_falls_back_for_blank() {
assert_eq!(autogen_subregion_display_name(""), "Autogen Circuit");
assert_eq!(autogen_subregion_display_name(" "), "Autogen Circuit");
}
#[test]
fn test_development_from_minimal_genome() {
ConnectomeManager::reset_for_testing(); let manager = ConnectomeManager::instance();
let mut neuro = Neuroembryogenesis::new(manager.clone());
let mut genome = create_genome_with_core_morphologies(
"test_genome".to_string(),
"Test Genome".to_string(),
);
let cortical_id = CorticalID::try_from_bytes(b"cst_neur").unwrap(); let cortical_type = cortical_id
.as_cortical_type()
.expect("Failed to get cortical type");
let area = CorticalArea::new(
cortical_id,
0,
"Test Area".to_string(),
CorticalAreaDimensions::new(10, 10, 10).unwrap(),
(0, 0, 0).into(),
cortical_type,
)
.expect("Failed to create cortical area");
genome.cortical_areas.insert(cortical_id, area);
let result = neuro.develop_from_genome(&genome);
assert!(result.is_ok(), "Development failed: {:?}", result);
let progress = neuro.get_progress();
assert_eq!(progress.stage, DevelopmentStage::Completed);
assert_eq!(progress.progress, 100);
assert_eq!(progress.cortical_areas_created, 1);
println!("✅ Development completed in {}ms", progress.duration_ms);
}
}