1use crate::connectome_manager::ConnectomeManager;
22use crate::models::{CorticalArea, CorticalID};
23use crate::types::{BduError, BduResult};
24use feagi_evolutionary::RuntimeGenome;
25use feagi_npu_neural::types::{Precision, QuantizationSpec};
26use parking_lot::RwLock;
27use std::sync::Arc;
28use tracing::{debug, error, info, trace, warn};
29
30fn autogen_subregion_display_name(genome_title: &str) -> String {
34 let t = genome_title.trim();
35 if t.is_empty() || t.eq_ignore_ascii_case("untitled") {
36 "Autogen Circuit".to_string()
37 } else {
38 t.to_string()
39 }
40}
41
42#[derive(Debug, Clone, Copy, PartialEq, Eq)]
44pub enum DevelopmentStage {
45 Initialization,
47 Corticogenesis,
49 Voxelogenesis,
51 Neurogenesis,
53 Synaptogenesis,
55 Completed,
57 Failed,
59}
60
61#[derive(Debug, Clone)]
63pub struct DevelopmentProgress {
64 pub stage: DevelopmentStage,
66 pub progress: u8,
68 pub cortical_areas_created: usize,
70 pub neurons_created: usize,
72 pub synapses_created: usize,
74 pub duration_ms: u64,
76}
77
78impl Default for DevelopmentProgress {
79 fn default() -> Self {
80 Self {
81 stage: DevelopmentStage::Initialization,
82 progress: 0,
83 cortical_areas_created: 0,
84 neurons_created: 0,
85 synapses_created: 0,
86 duration_ms: 0,
87 }
88 }
89}
90
91pub struct Neuroembryogenesis {
99 connectome_manager: Arc<RwLock<ConnectomeManager>>,
101
102 progress: Arc<RwLock<DevelopmentProgress>>,
104
105 start_time: std::time::Instant,
107}
108
109impl Neuroembryogenesis {
110 pub fn new(connectome_manager: Arc<RwLock<ConnectomeManager>>) -> Self {
112 Self {
113 connectome_manager,
114 progress: Arc::new(RwLock::new(DevelopmentProgress::default())),
115 start_time: std::time::Instant::now(),
116 }
117 }
118
119 pub fn get_progress(&self) -> DevelopmentProgress {
121 self.progress.read().clone()
122 }
123
124 fn sync_core_neuron_params(&self, cortical_idx: u32, area: &CorticalArea) -> BduResult<()> {
128 use crate::models::CorticalAreaExt;
129
130 let npu_arc = {
131 let manager = self.connectome_manager.read();
132 manager
133 .get_npu()
134 .cloned()
135 .ok_or_else(|| BduError::Internal("NPU not connected".to_string()))?
136 };
137
138 let mut npu_lock = npu_arc
139 .lock()
140 .map_err(|e| BduError::Internal(format!("Failed to lock NPU: {}", e)))?;
141
142 npu_lock.update_cortical_area_threshold_with_gradient(
143 cortical_idx,
144 area.firing_threshold(),
145 area.firing_threshold_increment_x(),
146 area.firing_threshold_increment_y(),
147 area.firing_threshold_increment_z(),
148 );
149 npu_lock.update_cortical_area_threshold_limit(cortical_idx, area.firing_threshold_limit());
150 npu_lock.update_cortical_area_leak(cortical_idx, area.leak_coefficient());
151 npu_lock.update_cortical_area_excitability(cortical_idx, area.neuron_excitability());
152 npu_lock.update_cortical_area_refractory_period(cortical_idx, area.refractory_period());
153 npu_lock.update_cortical_area_consecutive_fire_limit(
154 cortical_idx,
155 area.consecutive_fire_count() as u16,
156 );
157 npu_lock.update_cortical_area_snooze_period(cortical_idx, area.snooze_period());
158 npu_lock.update_cortical_area_mp_charge_accumulation(
159 cortical_idx,
160 area.mp_charge_accumulation(),
161 );
162
163 Ok(())
164 }
165
166 pub fn add_cortical_areas(
178 &mut self,
179 areas: Vec<CorticalArea>,
180 genome: &RuntimeGenome,
181 ) -> BduResult<(usize, usize)> {
182 info!(target: "feagi-bdu", "🧬 Incrementally adding {} cortical areas", areas.len());
183
184 let mut total_neurons = 0;
185 let mut total_synapses = 0;
186
187 for area in &areas {
189 let mut manager = self.connectome_manager.write();
190 manager.add_cortical_area(area.clone())?;
191 info!(target: "feagi-bdu", " ✓ Added cortical area structure: {}", area.cortical_id.as_base_64());
192 }
193
194 use feagi_structures::genomic::cortical_area::CoreCorticalType;
197 let death_id = CoreCorticalType::Death.to_cortical_id();
198 let power_id = CoreCorticalType::Power.to_cortical_id();
199 let fatigue_id = CoreCorticalType::Fatigue.to_cortical_id();
200
201 let mut core_areas = Vec::new();
202 let mut other_areas = Vec::new();
203
204 for area in &areas {
206 if area.cortical_id == death_id {
207 core_areas.push((0, area)); } else if area.cortical_id == power_id {
209 core_areas.push((1, area)); } else if area.cortical_id == fatigue_id {
211 core_areas.push((2, area)); } else {
213 other_areas.push(area);
214 }
215 }
216
217 core_areas.sort_by_key(|(idx, _)| *idx);
219
220 if !core_areas.is_empty() {
222 info!(target: "feagi-bdu", " 🎯 Creating core area neurons FIRST ({} areas) for deterministic IDs", core_areas.len());
223 for (core_idx, area) in &core_areas {
224 let existing_core_neurons = {
225 let manager = self.connectome_manager.read();
226 let npu = manager.get_npu();
227 match npu {
228 Some(npu_arc) => {
229 let npu_lock = npu_arc.lock();
230 match npu_lock {
231 Ok(npu_guard) => {
232 npu_guard.get_neurons_in_cortical_area(*core_idx).len()
233 }
234 Err(_) => 0,
235 }
236 }
237 None => 0,
238 }
239 };
240
241 if existing_core_neurons > 0 {
242 self.sync_core_neuron_params(*core_idx, area)?;
243 let refreshed = {
244 let manager = self.connectome_manager.read();
245 manager.refresh_neuron_count_for_area(&area.cortical_id)
246 };
247 let count = refreshed.unwrap_or(existing_core_neurons);
248 total_neurons += count;
249 info!(
250 target: "feagi-bdu",
251 " ↪ Skipping core neuron creation for {} (existing={}, idx={})",
252 area.cortical_id.as_base_64(),
253 count,
254 core_idx
255 );
256 continue;
257 }
258 let neurons_created = {
259 let mut manager = self.connectome_manager.write();
260 manager.create_neurons_for_area(&area.cortical_id)
261 };
262
263 match neurons_created {
264 Ok(count) => {
265 total_neurons += count as usize;
266 info!(target: "feagi-bdu", " ✅ Created {} neurons for core area {} (deterministic ID: neuron {})",
267 count, area.cortical_id.as_base_64(), core_idx);
268 }
269 Err(e) => {
270 error!(target: "feagi-bdu", " ❌ FATAL: Failed to create neurons for core area {}: {}", area.cortical_id.as_base_64(), e);
271 return Err(e);
272 }
273 }
274 }
275 }
276
277 for area in &other_areas {
279 let neurons_created = {
280 let mut manager = self.connectome_manager.write();
281 manager.create_neurons_for_area(&area.cortical_id)
282 };
283
284 match neurons_created {
285 Ok(count) => {
286 total_neurons += count as usize;
287 trace!(
288 target: "feagi-bdu",
289 "Created {} neurons for area {}",
290 count,
291 area.cortical_id.as_base_64()
292 );
293 }
294 Err(e) => {
295 error!(target: "feagi-bdu", " ❌ FATAL: Failed to create neurons for {}: {}", area.cortical_id.as_base_64(), e);
296 return Err(e);
298 }
299 }
300 }
301
302 for area in &areas {
304 let has_dstmap = area
306 .properties
307 .get("cortical_mapping_dst")
308 .and_then(|v| v.as_object())
309 .map(|m| !m.is_empty())
310 .unwrap_or(false);
311
312 if !has_dstmap {
313 debug!(target: "feagi-bdu", " No mappings for area {}", area.cortical_id.as_base_64());
314 continue;
315 }
316
317 let synapses_created = {
318 let mut manager = self.connectome_manager.write();
319 manager.apply_cortical_mapping(&area.cortical_id)
320 };
321
322 match synapses_created {
323 Ok(count) => {
324 total_synapses += count as usize;
325 trace!(
326 target: "feagi-bdu",
327 "Created {} synapses for area {}",
328 count,
329 area.cortical_id
330 );
331 }
332 Err(e) => {
333 warn!(target: "feagi-bdu", " ⚠️ Failed to create synapses for {}: {}", area.cortical_id, e);
334 let estimated = estimate_synapses_for_area(area, genome);
335 total_synapses += estimated;
336 }
337 }
338 }
339
340 info!(target: "feagi-bdu", "✅ Incremental add complete: {} areas, {} neurons, {} synapses",
341 areas.len(), total_neurons, total_synapses);
342
343 Ok((total_neurons, total_synapses))
344 }
345
346 pub fn develop_from_genome(&mut self, genome: &RuntimeGenome) -> BduResult<()> {
350 info!(target: "feagi-bdu","🧬 Starting neuroembryogenesis for genome: {}", genome.metadata.genome_id);
351
352 let _quantization_precision = &genome.physiology.quantization_precision;
354 let quant_spec = QuantizationSpec::default();
356
357 info!(target: "feagi-bdu",
358 " Quantization precision: {:?} (range: [{}, {}] for membrane potential)",
359 quant_spec.precision,
360 quant_spec.membrane_potential_min,
361 quant_spec.membrane_potential_max
362 );
363
364 match quant_spec.precision {
368 Precision::FP32 => {
369 info!(target: "feagi-bdu", " ✓ Using FP32 (32-bit floating-point) - highest precision");
370 info!(target: "feagi-bdu", " Memory usage: Baseline (4 bytes/neuron for membrane potential)");
371 }
372 Precision::INT8 => {
373 info!(target: "feagi-bdu", " ✓ Using INT8 (8-bit integer) - memory efficient");
374 info!(target: "feagi-bdu", " Memory reduction: 42% (1 byte/neuron for membrane potential)");
375 info!(target: "feagi-bdu", " Quantization range: [{}, {}]",
376 quant_spec.membrane_potential_min,
377 quant_spec.membrane_potential_max);
378 }
381 Precision::FP16 => {
382 warn!(target: "feagi-bdu", " FP16 quantization requested but not yet implemented.");
383 warn!(target: "feagi-bdu", " FP16 support planned for future GPU optimization.");
384 }
386 }
387
388 info!(target: "feagi-bdu", " ✓ Quantization handled by DynamicNPU (dispatches at runtime)");
391
392 self.update_stage(DevelopmentStage::Initialization, 0);
394
395 self.corticogenesis(genome)?;
397
398 self.voxelogenesis(genome)?;
400
401 self.neurogenesis(genome)?;
403
404 self.synaptogenesis(genome)?;
406
407 self.update_stage(DevelopmentStage::Completed, 100);
409
410 let progress = self.progress.read();
411 info!(target: "feagi-bdu",
412 "✅ Neuroembryogenesis completed in {}ms: {} cortical areas, {} neurons, {} synapses",
413 progress.duration_ms,
414 progress.cortical_areas_created,
415 progress.neurons_created,
416 progress.synapses_created
417 );
418
419 Ok(())
420 }
421
422 fn corticogenesis(&mut self, genome: &RuntimeGenome) -> BduResult<()> {
424 self.update_stage(DevelopmentStage::Corticogenesis, 0);
425 info!(target: "feagi-bdu","🧠 Stage 1: Corticogenesis - Creating {} cortical areas", genome.cortical_areas.len());
426 info!(target: "feagi-bdu","🔍 Genome brain_regions check: is_empty={}, count={}",
427 genome.brain_regions.is_empty(), genome.brain_regions.len());
428 if !genome.brain_regions.is_empty() {
429 info!(target: "feagi-bdu"," Existing regions: {:?}", genome.brain_regions.keys().collect::<Vec<_>>());
430 }
431
432 let total_areas = genome.cortical_areas.len();
433
434 for (idx, (cortical_id, area)) in genome.cortical_areas.iter().enumerate() {
436 {
438 let mut manager = self.connectome_manager.write();
439 manager.add_cortical_area(area.clone())?;
440 } let progress_pct = ((idx + 1) * 100 / total_areas.max(1)) as u8;
444 self.update_progress(|p| {
445 p.cortical_areas_created = idx + 1;
446 p.progress = progress_pct;
447 });
448
449 trace!(target: "feagi-bdu", "Created cortical area: {} ({})", cortical_id, area.name);
450 }
451
452 info!(target: "feagi-bdu","🔍 BRAIN REGION AUTO-GEN CHECK: genome.brain_regions.is_empty() = {}", genome.brain_regions.is_empty());
455 let (brain_regions_to_add, region_parent_map) = if genome.brain_regions.is_empty() {
456 info!(target: "feagi-bdu"," ✅ TRIGGERING AUTO-GENERATION: No brain_regions in genome - auto-generating default root region");
457 info!(target: "feagi-bdu"," 📊 Genome has {} cortical areas to process", genome.cortical_areas.len());
458
459 let all_cortical_ids = genome.cortical_areas.keys().cloned().collect::<Vec<_>>();
461 info!(target: "feagi-bdu"," 📊 Collected {} cortical area IDs: {:?}", all_cortical_ids.len(),
462 if all_cortical_ids.len() <= 5 {
463 format!("{:?}", all_cortical_ids.iter().map(|id| id.to_string()).collect::<Vec<_>>())
464 } else {
465 format!("{:?}...", all_cortical_ids[0..5].iter().map(|id| id.to_string()).collect::<Vec<_>>())
466 });
467
468 let mut auto_inputs = Vec::new();
470 let mut auto_outputs = Vec::new();
471
472 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() {
479 let area_id_str = area_id.to_string();
486 let category = if area_id_str.starts_with("___") {
488 "CORE"
489 } else if let Ok(cortical_type) = area.cortical_id.as_cortical_type() {
490 use feagi_structures::genomic::cortical_area::CorticalAreaType;
492 match cortical_type {
493 CorticalAreaType::Core(_) => "CORE",
494 CorticalAreaType::BrainInput(_) => "IPU",
495 CorticalAreaType::BrainOutput(_) => "OPU",
496 CorticalAreaType::Memory(_) => "MEMORY",
497 CorticalAreaType::Custom(_) => "CUSTOM",
498 }
499 } else {
500 let cortical_group = area
502 .properties
503 .get("cortical_group")
504 .and_then(|v| v.as_str())
505 .map(|s| s.to_uppercase());
506
507 match cortical_group.as_deref() {
508 Some("IPU") => "IPU",
509 Some("OPU") => "OPU",
510 Some("CORE") => "CORE",
511 Some("MEMORY") => "MEMORY",
512 Some("CUSTOM") => "CUSTOM",
513 _ => "CUSTOM", }
515 };
516
517 if ipu_areas.len() + opu_areas.len() + core_areas.len() + custom_memory_areas.len()
519 < 5
520 {
521 let source = if area.cortical_id.as_cortical_type().is_ok() {
522 "cortical_id_type"
523 } else if area.properties.contains_key("cortical_group") {
524 "cortical_group"
525 } else {
526 "default_fallback"
527 };
528
529 if area.cortical_id.as_cortical_type().is_ok() {
531 let type_desc = crate::cortical_type_utils::describe_cortical_type(area);
532 let frame_handling =
533 if crate::cortical_type_utils::uses_absolute_frames(area) {
534 "absolute"
535 } else if crate::cortical_type_utils::uses_incremental_frames(area) {
536 "incremental"
537 } else {
538 "n/a"
539 };
540 info!(target: "feagi-bdu"," 🔍 {}, frames={}, source={}",
541 type_desc, frame_handling, source);
542 } else {
543 info!(target: "feagi-bdu"," 🔍 Area {}: category={}, source={}",
544 area_id_str, category, source);
545 }
546 }
547
548 match category {
550 "IPU" => {
551 ipu_areas.push(*area_id);
552 auto_inputs.push(*area_id);
553 }
554 "OPU" => {
555 opu_areas.push(*area_id);
556 auto_outputs.push(*area_id);
557 }
558 "CORE" => {
559 core_areas.push(*area_id);
560 }
561 "MEMORY" | "CUSTOM" => {
562 custom_memory_areas.push(*area_id);
563 }
564 _ => {}
565 }
566 }
567
568 info!(target: "feagi-bdu"," 📊 Classification complete: IPU={}, OPU={}, CORE={}, CUSTOM/MEMORY={}",
569 ipu_areas.len(), opu_areas.len(), core_areas.len(), custom_memory_areas.len());
570
571 use feagi_structures::genomic::brain_regions::{BrainRegion, RegionID, RegionType};
573 let mut regions_map = std::collections::HashMap::new();
574
575 let mut root_area_ids = Vec::new();
577 root_area_ids.extend(ipu_areas.iter().cloned());
578 root_area_ids.extend(opu_areas.iter().cloned());
579 root_area_ids.extend(core_areas.iter().cloned());
580
581 let (root_inputs, root_outputs) =
583 Self::analyze_region_io(&root_area_ids, &genome.cortical_areas);
584
585 let root_region_id = RegionID::new();
588 let root_region_id_str = root_region_id.to_string();
589
590 let mut root_region = BrainRegion::new(
591 root_region_id,
592 "Root Brain Region".to_string(),
593 RegionType::Undefined,
594 )
595 .expect("Failed to create root region")
596 .with_areas(root_area_ids.iter().cloned());
597
598 if !root_inputs.is_empty() {
600 root_region
601 .add_property("inputs".to_string(), serde_json::json!(root_inputs.clone()));
602 }
603 if !root_outputs.is_empty() {
604 root_region.add_property(
605 "outputs".to_string(),
606 serde_json::json!(root_outputs.clone()),
607 );
608 }
609
610 info!(target: "feagi-bdu"," ✅ Created root region with {} areas (IPU={}, OPU={}, CORE={}) - analyzed: {} inputs, {} outputs",
611 root_area_ids.len(), ipu_areas.len(), opu_areas.len(), core_areas.len(),
612 root_inputs.len(), root_outputs.len());
613
614 let mut subregion_id = None;
616 if !custom_memory_areas.is_empty() {
617 let mut custom_memory_strs: Vec<String> = custom_memory_areas
619 .iter()
620 .map(|id| id.as_base_64())
621 .collect();
622 custom_memory_strs.sort(); let combined = custom_memory_strs.join("|");
624
625 use std::collections::hash_map::DefaultHasher;
627 use std::hash::{Hash, Hasher};
628 let mut hasher = DefaultHasher::new();
629 combined.hash(&mut hasher);
630 let hash = hasher.finish();
631 let hash_hex = format!("{:08x}", hash as u32);
632 let region_id = format!("region_autogen_{}", hash_hex);
633
634 let (subregion_inputs, subregion_outputs) =
636 Self::analyze_region_io(&custom_memory_areas, &genome.cortical_areas);
637
638 let autogen_position =
640 Self::calculate_autogen_region_position(&root_area_ids, genome);
641
642 let subregion_name = autogen_subregion_display_name(&genome.metadata.genome_title);
644 let mut subregion = BrainRegion::new(
645 RegionID::new(), subregion_name,
647 RegionType::Undefined, )
649 .expect("Failed to create subregion")
650 .with_areas(custom_memory_areas.iter().cloned());
651
652 subregion.add_property(
654 "coordinate_3d".to_string(),
655 serde_json::json!(autogen_position),
656 );
657 subregion.add_property("coordinate_2d".to_string(), serde_json::json!([0, 0]));
658
659 if !subregion_inputs.is_empty() {
661 subregion.add_property(
662 "inputs".to_string(),
663 serde_json::json!(subregion_inputs.clone()),
664 );
665 }
666 if !subregion_outputs.is_empty() {
667 subregion.add_property(
668 "outputs".to_string(),
669 serde_json::json!(subregion_outputs.clone()),
670 );
671 }
672
673 let subregion_id_str = subregion.region_id.to_string();
674
675 info!(target: "feagi-bdu"," ✅ Created subregion '{}' with {} CUSTOM/MEMORY areas ({} inputs, {} outputs)",
676 region_id, custom_memory_areas.len(), subregion_inputs.len(), subregion_outputs.len());
677
678 regions_map.insert(subregion_id_str.clone(), subregion);
679 subregion_id = Some(subregion_id_str);
680 }
681
682 regions_map.insert(root_region_id_str.clone(), root_region);
683
684 let total_inputs = root_inputs.len()
686 + if let Some(ref sid) = subregion_id {
687 regions_map
688 .get(sid)
689 .and_then(|r| r.properties.get("inputs"))
690 .and_then(|v| v.as_array())
691 .map(|a| a.len())
692 .unwrap_or(0)
693 } else {
694 0
695 };
696
697 let total_outputs = root_outputs.len()
698 + if let Some(ref sid) = subregion_id {
699 regions_map
700 .get(sid)
701 .and_then(|r| r.properties.get("outputs"))
702 .and_then(|v| v.as_array())
703 .map(|a| a.len())
704 .unwrap_or(0)
705 } else {
706 0
707 };
708
709 info!(target: "feagi-bdu"," ✅ Auto-generated {} brain region(s) with {} total cortical areas ({} total inputs, {} total outputs)",
710 regions_map.len(), all_cortical_ids.len(), total_inputs, total_outputs);
711
712 let mut parent_map = std::collections::HashMap::new();
714 if let Some(ref sub_id) = subregion_id {
715 parent_map.insert(sub_id.clone(), root_region_id_str.clone());
716 info!(target: "feagi-bdu"," 🔗 Parent relationship: {} -> {}", sub_id, root_region_id_str);
717 }
718
719 (regions_map, parent_map)
720 } else {
721 info!(target: "feagi-bdu"," 📋 Genome already has {} brain regions - using existing structure", genome.brain_regions.len());
722 (
725 genome.brain_regions.clone(),
726 std::collections::HashMap::new(),
727 )
728 };
729
730 {
732 let mut manager = self.connectome_manager.write();
733 let brain_region_count = brain_regions_to_add.len();
734 info!(target: "feagi-bdu"," Adding {} brain regions from genome", brain_region_count);
735
736 let root_entry = brain_regions_to_add
738 .iter()
739 .find(|(_, region)| region.name == "Root Brain Region");
740 if let Some((root_id, root_region)) = root_entry {
741 manager.add_brain_region(root_region.clone(), None)?;
742 debug!(target: "feagi-bdu"," ✓ Added brain region: {} (Root Brain Region) [parent=None]", root_id);
743 }
744
745 for (region_id, region) in brain_regions_to_add.iter() {
747 if region.name == "Root Brain Region" {
748 continue; }
750
751 let parent_id = region_parent_map.get(region_id).cloned();
752 manager.add_brain_region(region.clone(), parent_id.clone())?;
753 debug!(target: "feagi-bdu"," ✓ Added brain region: {} ({}) [parent={:?}]",
754 region_id, region.name, parent_id);
755 }
756
757 info!(target: "feagi-bdu"," Total brain regions in ConnectomeManager: {}", manager.get_brain_region_ids().len());
758 } self.update_stage(DevelopmentStage::Corticogenesis, 100);
761 info!(target: "feagi-bdu"," ✅ Corticogenesis complete: {} cortical areas created", total_areas);
762
763 Ok(())
764 }
765
766 fn voxelogenesis(&mut self, _genome: &RuntimeGenome) -> BduResult<()> {
768 self.update_stage(DevelopmentStage::Voxelogenesis, 0);
769 info!(target: "feagi-bdu","📐 Stage 2: Voxelogenesis - Establishing spatial framework");
770
771 self.update_stage(DevelopmentStage::Voxelogenesis, 100);
775 info!(target: "feagi-bdu"," ✅ Voxelogenesis complete: Spatial framework established");
776
777 Ok(())
778 }
779
780 fn neurogenesis(&mut self, genome: &RuntimeGenome) -> BduResult<()> {
789 self.update_stage(DevelopmentStage::Neurogenesis, 0);
790 info!(target: "feagi-bdu","🔬 Stage 3: Neurogenesis - Generating neurons (SIMD-optimized batches)");
791
792 let expected_neurons = genome.stats.innate_neuron_count;
793 info!(target: "feagi-bdu"," Expected innate neurons from genome: {}", expected_neurons);
794
795 use feagi_structures::genomic::cortical_area::CoreCorticalType;
797 let death_id = CoreCorticalType::Death.to_cortical_id();
798 let power_id = CoreCorticalType::Power.to_cortical_id();
799 let fatigue_id = CoreCorticalType::Fatigue.to_cortical_id();
800
801 let mut core_areas = Vec::new();
802 let mut other_areas = Vec::new();
803
804 for (cortical_id, area) in genome.cortical_areas.iter() {
806 if *cortical_id == death_id {
807 core_areas.push((0, *cortical_id, area)); } else if *cortical_id == power_id {
809 core_areas.push((1, *cortical_id, area)); } else if *cortical_id == fatigue_id {
811 core_areas.push((2, *cortical_id, area)); } else {
813 other_areas.push((*cortical_id, area));
814 }
815 }
816
817 core_areas.sort_by_key(|(idx, _, _)| *idx);
819
820 info!(target: "feagi-bdu"," 🎯 Creating core area neurons FIRST ({} areas) for deterministic IDs", core_areas.len());
821
822 let mut total_neurons_created = 0;
823 let mut processed_count = 0;
824 let total_areas = genome.cortical_areas.len();
825
826 for (core_idx, cortical_id, area) in &core_areas {
828 let existing_core_neurons = {
829 let manager = self.connectome_manager.read();
830 let npu = manager.get_npu();
831 match npu {
832 Some(npu_arc) => {
833 let npu_lock = npu_arc.lock();
834 match npu_lock {
835 Ok(npu_guard) => {
836 npu_guard.get_neurons_in_cortical_area(*core_idx).len()
837 }
838 Err(_) => 0,
839 }
840 }
841 None => 0,
842 }
843 };
844
845 if existing_core_neurons > 0 {
846 self.sync_core_neuron_params(*core_idx, area)?;
847 let refreshed = {
848 let manager = self.connectome_manager.read();
849 manager.refresh_neuron_count_for_area(cortical_id)
850 };
851 let count = refreshed.unwrap_or(existing_core_neurons);
852 total_neurons_created += count;
853 info!(
854 target: "feagi-bdu",
855 " ↪ Skipping core neuron creation for {} (existing={}, idx={})",
856 cortical_id.as_base_64(),
857 count,
858 core_idx
859 );
860 processed_count += 1;
861 let progress_pct = (processed_count * 100 / total_areas.max(1)) as u8;
862 self.update_progress(|p| {
863 p.neurons_created = total_neurons_created;
864 p.progress = progress_pct;
865 });
866 continue;
867 }
868 let per_voxel_count = area
869 .properties
870 .get("neurons_per_voxel")
871 .and_then(|v| v.as_u64())
872 .unwrap_or(1) as i64;
873
874 let cortical_id_str = cortical_id.to_string();
875 info!(target: "feagi-bdu"," 🔋 [CORE-AREA {}] {} - dimensions: {:?}, per_voxel: {}",
876 core_idx, cortical_id_str, area.dimensions, per_voxel_count);
877
878 if per_voxel_count == 0 {
879 warn!(target: "feagi-bdu"," ⚠️ Skipping core area {} - per_voxel_neuron_cnt is 0", cortical_id_str);
880 continue;
881 }
882
883 let neurons_created = {
885 let manager_arc = self.connectome_manager.clone();
886 let mut manager = manager_arc.write();
887 manager.create_neurons_for_area(cortical_id)
888 };
889
890 match neurons_created {
891 Ok(count) => {
892 total_neurons_created += count as usize;
893 info!(target: "feagi-bdu"," ✅ Created {} neurons for core area {} (deterministic ID: neuron {})",
894 count, cortical_id_str, core_idx);
895 }
896 Err(e) => {
897 error!(target: "feagi-bdu"," ❌ FATAL: Failed to create neurons for core area {}: {}", cortical_id_str, e);
898 return Err(e);
899 }
900 }
901
902 processed_count += 1;
903 let progress_pct = (processed_count * 100 / total_areas.max(1)) as u8;
904 self.update_progress(|p| {
905 p.neurons_created = total_neurons_created;
906 p.progress = progress_pct;
907 });
908 }
909
910 info!(target: "feagi-bdu"," 📦 Creating neurons for {} other areas", other_areas.len());
912 for (cortical_id, area) in &other_areas {
913 let _per_voxel_count = area
915 .properties
916 .get("neurons_per_voxel")
917 .and_then(|v| v.as_u64())
918 .unwrap_or(1) as i64;
919
920 let per_voxel_count = area
921 .properties
922 .get("neurons_per_voxel")
923 .and_then(|v| v.as_u64())
924 .unwrap_or(1) as i64;
925
926 let cortical_id_str = cortical_id.to_string();
927
928 if per_voxel_count == 0 {
929 warn!(target: "feagi-bdu"," ⚠️ Skipping area {} - per_voxel_neuron_cnt is 0 (will have NO neurons!)", cortical_id_str);
930 continue;
931 }
932
933 let neurons_created = {
936 let manager_arc = self.connectome_manager.clone();
937 let mut manager = manager_arc.write();
938 manager.create_neurons_for_area(cortical_id)
939 }; match neurons_created {
942 Ok(count) => {
943 total_neurons_created += count as usize;
944 trace!(
945 target: "feagi-bdu",
946 "Created {} neurons for area {}",
947 count,
948 cortical_id_str
949 );
950 }
951 Err(e) => {
952 warn!(target: "feagi-bdu"," Failed to create neurons for {}: {} (NPU may not be connected)",
954 cortical_id_str, e);
955 let total_voxels = area.dimensions.width as usize
956 * area.dimensions.height as usize
957 * area.dimensions.depth as usize;
958 let expected = total_voxels * per_voxel_count as usize;
959 total_neurons_created += expected;
960 }
961 }
962
963 processed_count += 1;
964 let progress_pct = (processed_count * 100 / total_areas.max(1)) as u8;
966 self.update_progress(|p| {
967 p.neurons_created = total_neurons_created;
968 p.progress = progress_pct;
969 });
970 }
971
972 if expected_neurons > 0 && total_neurons_created != expected_neurons {
974 trace!(target: "feagi-bdu",
975 created_neurons = total_neurons_created,
976 genome_stats_innate = expected_neurons,
977 "Neuron creation complete (genome stats may only count innate neurons)"
978 );
979 }
980
981 self.update_stage(DevelopmentStage::Neurogenesis, 100);
982 info!(target: "feagi-bdu"," ✅ Neurogenesis complete: {} neurons created", total_neurons_created);
983
984 Ok(())
985 }
986
987 fn synaptogenesis(&mut self, genome: &RuntimeGenome) -> BduResult<()> {
993 self.update_stage(DevelopmentStage::Synaptogenesis, 0);
994 info!(target: "feagi-bdu","🔗 Stage 4: Synaptogenesis - Forming synaptic connections (SIMD-optimized batches)");
995
996 let expected_synapses = genome.stats.innate_synapse_count;
997 info!(target: "feagi-bdu"," Expected innate synapses from genome: {}", expected_synapses);
998
999 self.rebuild_memory_twin_mappings_from_genome(genome)?;
1000
1001 let mut total_synapses_created = 0;
1002 let total_areas = genome.cortical_areas.len();
1003
1004 for (idx, (_src_cortical_id, src_area)) in genome.cortical_areas.iter().enumerate() {
1007 let has_dstmap = src_area
1009 .properties
1010 .get("cortical_mapping_dst")
1011 .and_then(|v| v.as_object())
1012 .map(|m| !m.is_empty())
1013 .unwrap_or(false);
1014
1015 if !has_dstmap {
1016 trace!(target: "feagi-bdu", "No dstmap for area {}", &src_area.cortical_id);
1017 continue;
1018 }
1019
1020 let src_cortical_id = &src_area.cortical_id;
1024 let src_cortical_id_str = src_cortical_id.to_string(); let synapses_created = {
1026 let manager_arc = self.connectome_manager.clone();
1027 let mut manager = manager_arc.write();
1028 if let Some(dstmap) = src_area.properties.get("cortical_mapping_dst") {
1029 if let Some(area) = manager.get_cortical_area_mut(src_cortical_id) {
1030 area.properties
1031 .insert("cortical_mapping_dst".to_string(), dstmap.clone());
1032 }
1033 }
1034 manager.apply_cortical_mapping(src_cortical_id)
1035 }; match synapses_created {
1038 Ok(count) => {
1039 total_synapses_created += count as usize;
1040 trace!(
1041 target: "feagi-bdu",
1042 "Created {} synapses for area {}",
1043 count,
1044 src_cortical_id_str
1045 );
1046 }
1047 Err(e) => {
1048 warn!(target: "feagi-bdu"," Failed to create synapses for {}: {} (NPU may not be connected)",
1050 src_cortical_id_str, e);
1051 let estimated = estimate_synapses_for_area(src_area, genome);
1052 total_synapses_created += estimated;
1053 }
1054 }
1055
1056 let progress_pct = ((idx + 1) * 100 / total_areas.max(1)) as u8;
1058 self.update_progress(|p| {
1059 p.synapses_created = total_synapses_created;
1060 p.progress = progress_pct;
1061 });
1062 }
1063
1064 let npu_arc = {
1069 let manager = self.connectome_manager.read();
1070 manager.get_npu().cloned()
1071 };
1072 if let Some(npu_arc) = npu_arc {
1073 let mut npu_lock = npu_arc
1074 .lock()
1075 .map_err(|e| BduError::Internal(format!("Failed to lock NPU: {}", e)))?;
1076 npu_lock.rebuild_synapse_index();
1077
1078 let manager = self.connectome_manager.read();
1080 manager.update_cached_synapse_count();
1081 }
1082
1083 #[cfg(feature = "plasticity")]
1086 {
1087 use feagi_evolutionary::extract_memory_properties;
1088 use feagi_npu_plasticity::{MemoryNeuronLifecycleConfig, PlasticityExecutor};
1089
1090 let manager = self.connectome_manager.read();
1091 if let Some(executor) = manager.get_plasticity_executor() {
1092 let mut registered_count = 0;
1093
1094 for area_id in manager.get_cortical_area_ids() {
1096 if let Some(area) = manager.get_cortical_area(area_id) {
1097 if let Some(mem_props) = extract_memory_properties(&area.properties) {
1098 let upstream_areas = manager.get_upstream_cortical_areas(area_id);
1099
1100 if let Some(npu_arc) = manager.get_npu() {
1103 if let Ok(mut npu) = npu_arc.lock() {
1104 let existing_configs = npu.get_all_fire_ledger_configs();
1105 for &upstream_idx in &upstream_areas {
1106 let existing = existing_configs
1107 .iter()
1108 .find(|(idx, _)| *idx == upstream_idx)
1109 .map(|(_, w)| *w)
1110 .unwrap_or(0);
1111
1112 let desired = mem_props.temporal_depth as usize;
1113 let resolved = existing.max(desired);
1114 if resolved != existing {
1115 if let Err(e) = npu.configure_fire_ledger_window(
1116 upstream_idx,
1117 resolved,
1118 ) {
1119 warn!(
1120 target: "feagi-bdu",
1121 "Failed to configure FireLedger window for upstream area idx={} (requested={}): {}",
1122 upstream_idx,
1123 resolved,
1124 e
1125 );
1126 }
1127 }
1128 }
1129 } else {
1130 warn!(target: "feagi-bdu", "Failed to lock NPU for FireLedger configuration");
1131 }
1132 }
1133
1134 if let Ok(exec) = executor.lock() {
1135 let upstream_non_memory =
1136 manager.filter_non_memory_upstream_areas(&upstream_areas);
1137 let lifecycle_config = MemoryNeuronLifecycleConfig {
1138 initial_lifespan: mem_props.init_lifespan,
1139 lifespan_growth_rate: mem_props.lifespan_growth_rate,
1140 longterm_threshold: mem_props.longterm_threshold,
1141 max_reactivations: 1000,
1142 };
1143
1144 exec.register_memory_area(
1145 area.cortical_idx,
1146 area_id.as_base_64(),
1147 mem_props.temporal_depth,
1148 upstream_non_memory,
1149 Some(lifecycle_config),
1150 );
1151
1152 registered_count += 1;
1153 }
1154 }
1155 }
1156 }
1157 let _ = registered_count; }
1159 }
1160
1161 if expected_synapses > 0 {
1163 let diff = (total_synapses_created as i64 - expected_synapses as i64).abs();
1164 let diff_pct = (diff as f64 / expected_synapses.max(1) as f64) * 100.0;
1165
1166 if diff_pct > 10.0 {
1167 warn!(target: "feagi-bdu",
1168 "Synapse count variance: created {} but genome stats expected {} ({:.1}% difference)",
1169 total_synapses_created, expected_synapses, diff_pct
1170 );
1171 } else {
1172 info!(target: "feagi-bdu",
1173 "Synapse count matches genome stats within {:.1}% ({} vs {})",
1174 diff_pct, total_synapses_created, expected_synapses
1175 );
1176 }
1177 }
1178
1179 self.update_stage(DevelopmentStage::Synaptogenesis, 100);
1180 info!(target: "feagi-bdu"," ✅ Synaptogenesis complete: {} synapses created", total_synapses_created);
1181
1182 Ok(())
1183 }
1184
1185 fn rebuild_memory_twin_mappings_from_genome(
1186 &mut self,
1187 genome: &RuntimeGenome,
1188 ) -> BduResult<()> {
1189 use feagi_structures::genomic::cortical_area::CorticalAreaType;
1190 let mut repaired = 0usize;
1191
1192 for (memory_id, memory_area) in genome.cortical_areas.iter() {
1193 let is_memory = matches!(
1194 memory_area.cortical_id.as_cortical_type(),
1195 Ok(CorticalAreaType::Memory(_))
1196 ) || memory_area
1197 .properties
1198 .get("is_mem_type")
1199 .and_then(|v| v.as_bool())
1200 .unwrap_or(false)
1201 || memory_area
1202 .properties
1203 .get("cortical_group")
1204 .and_then(|v| v.as_str())
1205 .is_some_and(|v| v.eq_ignore_ascii_case("MEMORY"));
1206 if !is_memory {
1207 continue;
1208 }
1209
1210 let Some(dstmap) = memory_area
1211 .properties
1212 .get("cortical_mapping_dst")
1213 .and_then(|v| v.as_object())
1214 else {
1215 continue;
1216 };
1217
1218 for (dst_id_str, rules) in dstmap {
1219 let Some(rule_array) = rules.as_array() else {
1220 continue;
1221 };
1222 let has_replay = rule_array.iter().any(|rule| {
1223 rule.get("morphology_id")
1224 .and_then(|v| v.as_str())
1225 .is_some_and(|id| id == "memory_replay")
1226 });
1227 if !has_replay {
1228 continue;
1229 }
1230
1231 let dst_id = match CorticalID::try_from_base_64(dst_id_str) {
1232 Ok(id) => id,
1233 Err(_) => {
1234 warn!(
1235 target: "feagi-bdu",
1236 "Invalid twin cortical ID in memory_replay dstmap: {}",
1237 dst_id_str
1238 );
1239 continue;
1240 }
1241 };
1242
1243 let Some(twin_area) = genome.cortical_areas.get(&dst_id) else {
1244 continue;
1245 };
1246 let Some(upstream_id_str) = twin_area
1247 .properties
1248 .get("memory_twin_of")
1249 .and_then(|v| v.as_str())
1250 else {
1251 continue;
1252 };
1253 let upstream_id = match CorticalID::try_from_base_64(upstream_id_str) {
1254 Ok(id) => id,
1255 Err(_) => {
1256 warn!(
1257 target: "feagi-bdu",
1258 "Invalid memory_twin_of value on twin area {}: {}",
1259 dst_id.as_base_64(),
1260 upstream_id_str
1261 );
1262 continue;
1263 }
1264 };
1265
1266 let mut manager = self.connectome_manager.write();
1267 if let Err(e) = manager.ensure_memory_twin_area(memory_id, &upstream_id) {
1268 warn!(
1269 target: "feagi-bdu",
1270 "Failed to rebuild memory twin mapping for memory {} upstream {}: {}",
1271 memory_id.as_base_64(),
1272 upstream_id.as_base_64(),
1273 e
1274 );
1275 continue;
1276 }
1277 repaired += 1;
1278 }
1279 }
1280
1281 info!(
1282 target: "feagi-bdu",
1283 "Rebuilt {} memory twin mapping(s) from genome",
1284 repaired
1285 );
1286 Ok(())
1287 }
1288}
1289
1290fn estimate_synapses_for_area(
1294 src_area: &CorticalArea,
1295 genome: &feagi_evolutionary::RuntimeGenome,
1296) -> usize {
1297 let dstmap = match src_area.properties.get("cortical_mapping_dst") {
1298 Some(serde_json::Value::Object(map)) => map,
1299 _ => return 0,
1300 };
1301
1302 let mut total = 0;
1303
1304 for (dst_id, rules) in dstmap {
1305 let dst_cortical_id = match feagi_evolutionary::string_to_cortical_id(dst_id) {
1307 Ok(id) => id,
1308 Err(_) => continue,
1309 };
1310 let dst_area = match genome.cortical_areas.get(&dst_cortical_id) {
1311 Some(area) => area,
1312 None => continue,
1313 };
1314
1315 let rules_array = match rules.as_array() {
1316 Some(arr) => arr,
1317 None => continue,
1318 };
1319
1320 for rule in rules_array {
1321 let morphology_id = rule
1322 .get("morphology_id")
1323 .and_then(|v| v.as_str())
1324 .unwrap_or("unknown");
1325 let scalar = rule
1326 .get("morphology_scalar")
1327 .and_then(|v| v.as_i64())
1328 .unwrap_or(1) as usize;
1329
1330 let src_per_voxel = src_area
1332 .properties
1333 .get("neurons_per_voxel")
1334 .and_then(|v| v.as_u64())
1335 .unwrap_or(1) as usize;
1336 let dst_per_voxel = dst_area
1337 .properties
1338 .get("neurons_per_voxel")
1339 .and_then(|v| v.as_u64())
1340 .unwrap_or(1) as usize;
1341
1342 let src_voxels =
1343 src_area.dimensions.width * src_area.dimensions.height * src_area.dimensions.depth;
1344 let dst_voxels =
1345 dst_area.dimensions.width * dst_area.dimensions.height * dst_area.dimensions.depth;
1346
1347 let src_neurons = src_voxels as usize * src_per_voxel;
1348 let dst_neurons = dst_voxels as usize * dst_per_voxel as usize;
1349
1350 let count = match morphology_id {
1352 "block_to_block" => src_neurons * dst_per_voxel * scalar,
1353 "projector" | "transpose_xy" | "transpose_yz" | "transpose_xz" => {
1354 src_neurons * dst_neurons * scalar
1355 }
1356 _ if morphology_id.contains("lateral") => src_neurons * scalar,
1357 _ => (src_neurons * scalar).min(src_neurons * dst_neurons / 10),
1358 };
1359
1360 total += count;
1361 }
1362 }
1363
1364 total
1365}
1366
1367impl Neuroembryogenesis {
1368 fn calculate_autogen_region_position(
1370 root_area_ids: &[CorticalID],
1371 genome: &feagi_evolutionary::RuntimeGenome,
1372 ) -> [i32; 3] {
1373 if root_area_ids.is_empty() {
1374 return [100, 0, 0];
1375 }
1376
1377 let mut min_x = i32::MAX;
1378 let mut max_x = i32::MIN;
1379 let mut min_y = i32::MAX;
1380 let mut max_y = i32::MIN;
1381 let mut min_z = i32::MAX;
1382 let mut max_z = i32::MIN;
1383
1384 for cortical_id in root_area_ids {
1385 if let Some(area) = genome.cortical_areas.get(cortical_id) {
1386 let pos: (i32, i32, i32) = area.position.into();
1387 let dims = (
1388 area.dimensions.width as i32,
1389 area.dimensions.height as i32,
1390 area.dimensions.depth as i32,
1391 );
1392
1393 min_x = min_x.min(pos.0);
1394 max_x = max_x.max(pos.0 + dims.0);
1395 min_y = min_y.min(pos.1);
1396 max_y = max_y.max(pos.1 + dims.1);
1397 min_z = min_z.min(pos.2);
1398 max_z = max_z.max(pos.2 + dims.2);
1399 }
1400 }
1401
1402 let bbox_width = (max_x - min_x).max(1);
1403 let padding = (bbox_width / 5).max(50);
1404 let autogen_x = max_x + padding;
1405 let autogen_y = (min_y + max_y) / 2;
1406 let autogen_z = (min_z + max_z) / 2;
1407
1408 info!(target: "feagi-bdu",
1409 " 📐 Autogen position: ({}, {}, {}) [padding: {}]",
1410 autogen_x, autogen_y, autogen_z, padding);
1411
1412 [autogen_x, autogen_y, autogen_z]
1413 }
1414
1415 fn analyze_region_io(
1421 region_area_ids: &[feagi_structures::genomic::cortical_area::CorticalID],
1422 all_cortical_areas: &std::collections::HashMap<CorticalID, CorticalArea>,
1423 ) -> (Vec<String>, Vec<String>) {
1424 let area_set: std::collections::HashSet<_> = region_area_ids.iter().cloned().collect();
1425 let mut inputs = Vec::new();
1426 let mut outputs = Vec::new();
1427
1428 let extract_destinations = |area: &CorticalArea| -> Vec<String> {
1430 area.properties
1431 .get("cortical_mapping_dst")
1432 .and_then(|v| v.as_object())
1433 .map(|obj| obj.keys().cloned().collect())
1434 .unwrap_or_default()
1435 };
1436
1437 for area_id in region_area_ids {
1439 if let Some(area) = all_cortical_areas.get(area_id) {
1440 let destinations = extract_destinations(area);
1441 let external_destinations: Vec<_> = destinations
1443 .iter()
1444 .filter_map(|dest| feagi_evolutionary::string_to_cortical_id(dest).ok())
1445 .filter(|dest_id| !area_set.contains(dest_id))
1446 .collect();
1447
1448 if !external_destinations.is_empty() {
1449 outputs.push(area_id.as_base_64());
1450 }
1451 }
1452 }
1453
1454 for (source_area_id, source_area) in all_cortical_areas.iter() {
1456 if area_set.contains(source_area_id) {
1458 continue;
1459 }
1460
1461 let destinations = extract_destinations(source_area);
1462 for dest_str in destinations {
1463 if let Ok(dest_id) = feagi_evolutionary::string_to_cortical_id(&dest_str) {
1464 if area_set.contains(&dest_id) {
1465 let dest_string = dest_id.as_base_64();
1466 if !inputs.contains(&dest_string) {
1467 inputs.push(dest_string);
1468 }
1469 }
1470 }
1471 }
1472 }
1473
1474 (inputs, outputs)
1475 }
1476
1477 fn update_stage(&self, stage: DevelopmentStage, progress: u8) {
1479 let mut p = self.progress.write();
1480 p.stage = stage;
1481 p.progress = progress;
1482 p.duration_ms = self.start_time.elapsed().as_millis() as u64;
1483 }
1484
1485 fn update_progress<F>(&self, f: F)
1487 where
1488 F: FnOnce(&mut DevelopmentProgress),
1489 {
1490 let mut p = self.progress.write();
1491 f(&mut p);
1492 p.duration_ms = self.start_time.elapsed().as_millis() as u64;
1493 }
1494}
1495
1496#[cfg(test)]
1497mod tests {
1498 use super::*;
1499 use feagi_evolutionary::create_genome_with_core_morphologies;
1500 use feagi_structures::genomic::cortical_area::CorticalAreaDimensions;
1501
1502 #[test]
1503 fn test_neuroembryogenesis_creation() {
1504 let manager = ConnectomeManager::instance();
1505 let neuro = Neuroembryogenesis::new(manager);
1506
1507 let progress = neuro.get_progress();
1508 assert_eq!(progress.stage, DevelopmentStage::Initialization);
1509 assert_eq!(progress.progress, 0);
1510 }
1511
1512 #[test]
1513 fn autogen_subregion_display_name_uses_title_when_meaningful() {
1514 assert_eq!(
1515 autogen_subregion_display_name("My Shared Circuit"),
1516 "My Shared Circuit"
1517 );
1518 }
1519
1520 #[test]
1521 fn autogen_subregion_display_name_falls_back_for_untitled() {
1522 assert_eq!(
1523 autogen_subregion_display_name("Untitled"),
1524 "Autogen Circuit"
1525 );
1526 assert_eq!(
1527 autogen_subregion_display_name("untitled"),
1528 "Autogen Circuit"
1529 );
1530 }
1531
1532 #[test]
1533 fn autogen_subregion_display_name_falls_back_for_blank() {
1534 assert_eq!(autogen_subregion_display_name(""), "Autogen Circuit");
1535 assert_eq!(autogen_subregion_display_name(" "), "Autogen Circuit");
1536 }
1537
1538 #[test]
1539 fn test_development_from_minimal_genome() {
1540 ConnectomeManager::reset_for_testing(); let manager = ConnectomeManager::instance();
1542 let mut neuro = Neuroembryogenesis::new(manager.clone());
1543
1544 let mut genome = create_genome_with_core_morphologies(
1546 "test_genome".to_string(),
1547 "Test Genome".to_string(),
1548 );
1549
1550 let cortical_id = CorticalID::try_from_bytes(b"cst_neur").unwrap(); let cortical_type = cortical_id
1552 .as_cortical_type()
1553 .expect("Failed to get cortical type");
1554 let area = CorticalArea::new(
1555 cortical_id,
1556 0,
1557 "Test Area".to_string(),
1558 CorticalAreaDimensions::new(10, 10, 10).unwrap(),
1559 (0, 0, 0).into(),
1560 cortical_type,
1561 )
1562 .expect("Failed to create cortical area");
1563 genome.cortical_areas.insert(cortical_id, area);
1564
1565 let result = neuro.develop_from_genome(&genome);
1567 assert!(result.is_ok(), "Development failed: {:?}", result);
1568
1569 let progress = neuro.get_progress();
1571 assert_eq!(progress.stage, DevelopmentStage::Completed);
1572 assert_eq!(progress.progress, 100);
1573 assert_eq!(progress.cortical_areas_created, 1);
1574
1575 let mgr = manager.read();
1577 assert!(
1579 mgr.has_cortical_area(&cortical_id),
1580 "Cortical area should have been added to connectome"
1581 );
1582
1583 println!("✅ Development completed in {}ms", progress.duration_ms);
1584 }
1585}