Skip to main content

terminals_core/substrate/
expert.rs

1//! ExpertProjection — MicroLM cognitive gating.
2//!
3//! Maps semantic intent to activation/gate values. The expert projection
4//! is where the MicroLM's learned specialization manifests per-atom.
5
6use super::projection::{Projection, ProjectionId};
7
8/// 3 floats: intent, activation, gate = 12 bytes.
9const EXPERT_BYTES: usize = 3 * 4;
10
11#[derive(Debug, Clone, Copy)]
12pub struct ExpertProjection {
13    /// Intent classification (0.0 = no intent, 1.0 = strong intent).
14    pub intent: f32,
15    /// Current activation level.
16    pub activation: f32,
17    /// Gate value (0.0 = closed, 1.0 = open). Controls information flow.
18    pub gate: f32,
19}
20
21impl Default for ExpertProjection {
22    fn default() -> Self {
23        Self {
24            intent: 0.0,
25            activation: 0.0,
26            gate: 1.0, // Open by default — undifferentiated potential
27        }
28    }
29}
30
31impl Projection for ExpertProjection {
32    fn byte_size() -> usize {
33        EXPERT_BYTES
34    }
35
36    fn id() -> ProjectionId {
37        ProjectionId::Expert
38    }
39
40    fn read(buf: &[u8]) -> Self {
41        assert!(buf.len() >= EXPERT_BYTES);
42        Self {
43            intent: f32::from_le_bytes([buf[0], buf[1], buf[2], buf[3]]),
44            activation: f32::from_le_bytes([buf[4], buf[5], buf[6], buf[7]]),
45            gate: f32::from_le_bytes([buf[8], buf[9], buf[10], buf[11]]),
46        }
47    }
48
49    fn write(&self, buf: &mut [u8]) {
50        assert!(buf.len() >= EXPERT_BYTES);
51        buf[0..4].copy_from_slice(&self.intent.to_le_bytes());
52        buf[4..8].copy_from_slice(&self.activation.to_le_bytes());
53        buf[8..12].copy_from_slice(&self.gate.to_le_bytes());
54    }
55
56    fn shape_hash_contribution(&self) -> u32 {
57        let mut hash = 0x811c_9dc5u32;
58        for byte in self.activation.to_bits().to_le_bytes() {
59            hash ^= byte as u32;
60            hash = hash.wrapping_mul(0x0100_0193);
61        }
62        hash
63    }
64}
65
66#[cfg(test)]
67mod tests {
68    use super::*;
69
70    #[test]
71    fn test_expert_roundtrip() {
72        let proj = ExpertProjection {
73            intent: 0.8,
74            activation: 0.6,
75            gate: 0.5,
76        };
77        let mut buf = vec![0u8; ExpertProjection::byte_size()];
78        proj.write(&mut buf);
79        let restored = ExpertProjection::read(&buf);
80        assert!((restored.intent - 0.8).abs() < 1e-6);
81        assert!((restored.activation - 0.6).abs() < 1e-6);
82        assert!((restored.gate - 0.5).abs() < 1e-6);
83    }
84}