Skip to main content

temporal_field/
lib.rs

1//! Temporal Field - Ring buffer substrate for cognitive architectures
2//!
3//! The brain does not poll - one spark cascades.
4//!
5//! ASTRO_004 compliant: No floats. Signal (polarity × magnitude × multiplier) throughout.
6//!
7//! # Core Types
8//!
9//! - **Signal**: Universal 3-byte neural signal (polarity: i8, magnitude: u8, multiplier: u8)
10//! - **TemporalField**: Ring buffer with decay and pub/sub events
11//!
12//! # Architecture: Field / Writer / Reader
13//!
14//! The system separates into three roles:
15//!
16//! 1. **Field** - The substrate: ring buffer with decay
17//! 2. **Writers** - Anything that writes to regions (cochlea, tokenizer, motor, etc.)
18//! 3. **Readers** - FieldObservers that receive events when thresholds cross
19//!
20//! Multiple writers can write to the same field (additive semantics).
21//! Multiple readers can subscribe to the same field (pub/sub).
22//! Writes automatically fire events to all readers when thresholds cross.
23//!
24//! # Core Concepts
25//!
26//! - **Ring buffer**: Fixed memory, oldest frames auto-evicted
27//! - **Decay per tick**: Time encoded in values, not metadata (retention: u8, 255 = 1.0)
28//! - **Regions**: Spatial partitioning for multi-channel integration
29//! - **Pub/sub**: Writes fire events to observers automatically
30//! - **Signal**: Compact neural representation (s = polarity × magnitude × multiplier)
31//!
32//! # Integer Conventions
33//!
34//! | Parameter | Type | Scale | Examples |
35//! |-----------|------|-------|----------|
36//! | retention | u8 | 255 = 1.0 | 242 ≈ 0.95, 230 ≈ 0.90, 128 = 0.50 |
37//! | threshold | u32 | sum of magnitude² | 524288 = 32 dims × 128² |
38//! | weight | u8 | 100 = 1.0× | 150 = 1.5×, 80 = 0.8× |
39//! | energy | u32 | Σ(magnitude²) | max = 64 × 255² = 4,161,600 |
40//!
41//! # Example: Multimodal Binding Detection
42//!
43//! This example shows the pattern used for concept grounding - detecting when
44//! audio and text patterns co-occur (e.g., hearing "door" while seeing the word).
45//!
46//! ```rust
47//! use temporal_field::{TemporalField, FieldConfig, FieldEvent, MonitoredRegion, FnObserver};
48//! use ternary_signal::Signal;
49//! use std::sync::Arc;
50//!
51//! // Region definitions (like SensoryField's ModalityRegions)
52//! const AUDIO_REGION: std::ops::Range<usize> = 0..64;
53//! const TEXT_REGION: std::ops::Range<usize> = 64..128;
54//!
55//! // 1. Create the Field (the substrate)
56//! // 128 dims, 50 frames, retention 242 (≈0.95)
57//! let config = FieldConfig::new(128, 50, 242);
58//! let mut field = TemporalField::new(config);
59//!
60//! // 2. Configure monitored regions (what triggers events)
61//! // Threshold: energy needed to activate (e.g., 100_000 = ~50 dims at mag 45)
62//! field.monitor_region(MonitoredRegion::new("audio", AUDIO_REGION, 100_000));
63//! field.monitor_region(MonitoredRegion::new("text", TEXT_REGION, 100_000));
64//! field.set_convergence_threshold(2); // Fire when 2+ regions active
65//!
66//! // 3. Subscribe Reader (binding detector)
67//! field.subscribe(Arc::new(FnObserver(|event| {
68//!     match event {
69//!         FieldEvent::Convergence { active_regions, total_energy } => {
70//!             // Binding opportunity! Audio + text co-occurred
71//!             println!("BINDING: {} regions, energy={}", active_regions.len(), total_energy);
72//!         }
73//!         FieldEvent::RegionActive { region, energy, .. } => {
74//!             println!("Region {:?} activated with energy {}", region, energy);
75//!         }
76//!         _ => {}
77//!     }
78//! })));
79//!
80//! // 4. Writers write to their regions using Signals
81//! // Cochlea writes audio features (magnitude 128 = moderate activation)
82//! let audio_features = vec![Signal::positive(128); 64];
83//! field.write_region(&audio_features, AUDIO_REGION);
84//!
85//! // Tokenizer writes text embedding
86//! let text_embedding = vec![Signal::positive(100); 64];
87//! field.write_region(&text_embedding, TEXT_REGION);
88//! // ^ This triggers Convergence event because both regions are now active
89//!
90//! // 5. Time advances - decay happens automatically
91//! field.tick(); // All magnitudes decay by retention factor
92//! ```
93//!
94//! # Key Insight
95//!
96//! The field doesn't know what audio or text means. It just knows that patterns
97//! co-occurred within a temporal window. Meaning emerges from the binding.
98
99mod config;
100mod field;
101mod observer;
102mod vector;
103
104pub use config::FieldConfig;
105pub use field::TemporalField;
106pub use observer::{FieldEvent, FieldObserver, FnObserver, MonitoredRegion, TriggerConfig};
107pub use vector::FieldVector;
108
109// Signal: Re-export from ternary-signal (the authoritative source)
110pub use ternary_signal::Signal;
111
112// Deprecated alias for v1 compatibility
113#[deprecated(since = "0.4.0", note = "Use Signal instead")]
114pub type TernarySignal = Signal;