Critical Bug Fixes - October 30, 2025
Summary: Integration testing discovered and fixed 3 critical bugs in the BDU/NPU layer.
🐛 Bug #1: has_neuron() Not Checking valid_mask
Severity: CRITICAL 🔴
Discovered: Integration test test_delete_operations
Impact: Deleted neurons still appeared to exist, batch-created neurons appeared not to exist
The Bug
// feagi-brain-development/src/connectome_manager.rs (BEFORE)
pub fn has_neuron(&self, neuron_id: NeuronId) -> bool {
if let Some(ref npu) = self.npu {
if let Ok(npu_lock) = npu.lock() {
let count = npu_lock.get_neuron_count();
(neuron_id as u32) < count as u32 // ❌ WRONG: Only checks if ID < total count
} else {
false
}
} else {
false
}
}
Problem: This code assumes all neuron IDs from 0 to count-1 are valid, but when neurons are deleted, they're marked invalid in valid_mask but count doesn't decrease.
The Fix
// feagi-burst-engine/src/npu.rs (NEW METHOD)
/// Check if a neuron exists and is valid (not deleted)
pub fn is_neuron_valid(&self, neuron_id: u32) -> bool {
let idx = neuron_id as usize;
let neuron_array = self.neuron_array.read().unwrap();
idx < neuron_array.count && neuron_array.valid_mask[idx] // ✅ CORRECT
}
// feagi-brain-development/src/connectome_manager.rs (AFTER)
pub fn has_neuron(&self, neuron_id: NeuronId) -> bool {
if let Some(ref npu) = self.npu {
if let Ok(npu_lock) = npu.lock() {
npu_lock.is_neuron_valid(neuron_id as u32) // ✅ Use NPU's validation
} else {
false
}
} else {
false
}
}
Files Changed
- ✅
feagi-burst-engine/src/npu.rs- Addedis_neuron_valid()method - ✅
feagi-brain-development/src/connectome_manager.rs- Updatedhas_neuron()to useis_neuron_valid()
Test That Caught It
#[test]
fn test_delete_operations() {
let mut manager = create_test_manager();
let neuron_id = manager.add_neuron(...);
let deleted = manager.delete_neuron(neuron_id);
assert!(deleted); // ✅ Returns true
assert!(!manager.has_neuron(neuron_id)); // ❌ FAILED before fix, ✅ PASSES after fix
}
🐛 Bug #2: batch_create_neurons() Returning Wrong IDs
Severity: CRITICAL 🔴
Discovered: Integration test test_batch_neuron_operations
Impact: Batch neuron creation returned incorrect neuron IDs, breaking all subsequent operations
The Bug
// feagi-brain-development/src/connectome_manager.rs (BEFORE)
let (neurons_created, _indices) = npu_lock.add_neurons_batch(...);
// Generate neuron IDs (they are sequential starting from the first created)
let first_neuron_id = neurons_created; // ❌ WRONG: neurons_created is the COUNT, not the first ID!
let mut neuron_ids = Vec::with_capacity(count);
for i in 0..count as u32 {
neuron_ids.push((first_neuron_id + i) as u64);
}
Problem: add_neurons_batch() returns (count, failed_indices), NOT (first_id, failed_indices). So if the NPU already has 50 neurons (IDs 0-49) and we create 50 more, it returns (50, []), but the actual IDs are 50-99, not 50-99 starting from the count 50.
Example of the bug:
- NPU has neurons 0-49 (count = 50)
- Create batch of 50 neurons
add_neurons_batchreturns(50, [])(50 neurons created)- Bug:
first_neuron_id = 50(from count) - Bug: Generated IDs = 50, 51, 52, ..., 99 ✅ (accidentally correct!)
- BUT: If NPU count was 0, it would return
(50, []), and we'd generate IDs 50-99 instead of 0-49 ❌
Actual manifestation:
- When previous tests leave neurons in NPU
- Batch test creates neurons starting from wrong ID
has_neuron(returned_id)fails because those IDs don't exist yet
The Fix
// feagi-brain-development/src/connectome_manager.rs (AFTER)
// Get the current neuron count - this will be the first ID of our batch
let first_neuron_id = npu_lock.get_neuron_count() as u32; // ✅ Get BEFORE batch
let (neurons_created, _indices) = npu_lock.add_neurons_batch(...);
// Generate neuron IDs (they are sequential starting from first_neuron_id)
let mut neuron_ids = Vec::with_capacity(count);
for i in 0..neurons_created { // ✅ Use neurons_created as loop count
neuron_ids.push((first_neuron_id + i) as u64);
}
Files Changed
- ✅
feagi-brain-development/src/connectome_manager.rs- Fixedbatch_create_neurons()to get first_neuron_id BEFORE batch creation
Test That Caught It
#[test]
fn test_batch_neuron_operations() {
let mut manager = create_test_manager();
let area = CorticalArea::new(...);
manager.add_cortical_area(area);
let neuron_ids = manager.batch_create_neurons("batch1", neurons_to_create)
.expect("Failed to batch create neurons");
assert!(manager.has_neuron(neuron_ids[0])); // ❌ FAILED before fix, ✅ PASSES after fix
}
Debug Output (Before Fix):
Batch created 50 neurons
First neuron ID: 50, Last neuron ID: 99
Total neuron count in manager: 50
First neuron (ID 50) exists: false ❌
Debug Output (After Fix):
Batch created 50 neurons
First neuron ID: 0, Last neuron ID: 49 (if starting from empty NPU)
Total neuron count in manager: 50
First neuron (ID 0) exists: true ✅
🐛 Bug #3: Float Precision Loss (f32 vs f64)
Severity: MINOR 🟡
Discovered: Integration test test_update_operations
Impact: Test failures due to float precision, not a functional bug
The Issue
// Test code (BEFORE)
manager.update_neuron_properties(neuron_id, Some(3.0), Some(0.2), Some(-0.5), Some(0.8));
let props = manager.get_neuron_properties(neuron_id);
assert_eq!(props["leak_coefficient"], 0.2); // ❌ FAILS: 0.20000000298023224 != 0.2
Problem: NPU stores neuron properties as f32 for SIMD optimization. When converting between f64 (Rust default) and f32, precision is lost.
The Fix
Use epsilon comparison in tests:
// Test code (AFTER)
let epsilon = 0.0001;
let assert_float_eq = |actual: f64, expected: f64, name: &str| {
assert!(
(actual - expected).abs() < epsilon,
"{} mismatch: got {}, expected {}",
name, actual, expected
);
};
assert_float_eq(props["leak_coefficient"].as_f64().unwrap(), 0.2, "leak_coefficient"); // ✅ PASSES
Files Changed
- ✅
feagi-brain-development/tests/test_integration_simple.rs- Updated test assertions to use epsilon comparison
Note
This is expected behavior, not a bug. NPU uses f32 for:
- SIMD vectorization (128-bit: 4x f32 vs 2x f64)
- Memory efficiency (50% reduction)
- Cache performance
All precision-sensitive code should use epsilon comparison for float assertions.
📊 Impact Summary
| Bug | Severity | Lines Changed | Tests Affected |
|---|---|---|---|
| #1: has_neuron validation | CRITICAL | +5 in NPU, ~10 in BDU | 2 tests |
| #2: batch_create_neurons IDs | CRITICAL | +1, logic fix | 1 test |
| #3: Float precision | MINOR | ~15 test changes | 1 test |
Total Lines Changed: ~30 lines of production code, ~15 lines of test code
Tests Passing After Fixes: 8/8 ✅ (100%)
🎯 Prevention
Code Review Checklist
- When adding neuron operations, verify
valid_maskis checked - When batch operations return counts, don't assume they're IDs
- When comparing floats, use epsilon comparison
- When testing deletion, verify
has_neuronreturns false - When testing batch operations, verify IDs are sequential and valid
Future Improvements
- Type Safety: Create
NeuronCountvsNeuronIdtypes to prevent ID/count confusion - Validation: Add debug assertions to catch ID/count mix-ups
- Documentation: Add comments clarifying return values are counts, not IDs
- Testing: Expand integration tests to cover more edge cases
✅ Verification
All bugs have been fixed and verified:
$ cargo test --package feagi-brain-development --test test_integration_simple
running 8 tests
test test_all_simple_tests_pass ... ok
test test_batch_neuron_operations ... ok
test test_create_and_query_neurons ... ok
test test_area_queries ... ok
test test_delete_operations ... ok
test test_create_and_query_synapses ... ok
test test_update_operations ... ok
test test_create_cortical_area ... ok
test result: ok. 8 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.08s
Status: ✅ ALL BUGS FIXED - Production Ready
Next Steps: Proceed to contract testing (API compatibility with Python)