Skip to main content

SocialPhase

Enum SocialPhase 

Source
pub enum SocialPhase {
    ShyObserver,
    StartledRetreat,
    QuietlyBeloved,
    ProtectiveGuardian,
}
Expand description

Behavioral phase from the 2D (coherence × tension) space.

The four quadrants of the phase plane:

             │ Low tension        │ High tension
─────────────┼────────────────────┼──────────────────────
Low coherence│ ShyObserver        │ StartledRetreat
High coherence│ QuietlyBeloved    │ ProtectiveGuardian

Transitions use hysteresis (CCF-004) to prevent oscillation at boundaries.

Patent Claims 14–18.

Variants§

§

ShyObserver

Low coherence, low tension: minimal expression, cautious observation.

§

StartledRetreat

Low coherence, high tension: protective reflex with additional withdrawal.

§

QuietlyBeloved

High coherence, low tension: full expressive range — “small flourishes”.

§

ProtectiveGuardian

High coherence, high tension: protective but with relational context.

Implementations§

Source§

impl SocialPhase

Source

pub fn classify( effective_coherence: f32, tension: f32, prev: SocialPhase, ps: &PhaseSpace, ) -> SocialPhase

Determine the current social phase using Schmitt trigger hysteresis (CCF-004).

  • effective_coherence: output of CoherenceField::effective_coherence() in [0.0, 1.0].
  • tension: current tension from homeostasis in [0.0, 1.0].
  • prev: the phase from the previous tick (enables hysteresis).
  • ps: configurable thresholds for quadrant transitions.
Examples found in repository?
examples/mbot2.rs (line 133)
60fn main() {
61    println!("CCF mBot2 — Emergent Behaviour Simulation");
62    println!("==========================================\n");
63
64    // ── Personality ──────────────────────────────────────────────────────────
65    //
66    // These three parameters shape how the robot accumulates and loses trust.
67    // They are analogous to temperament — the same events produce different
68    // magnitudes of response depending on personality.
69    //
70    // This configuration: eager to engage (high curiosity), not easily startled
71    // (low sensitivity), recovers quickly from disruption (high recovery).
72    let personality = Personality {
73        curiosity_drive:     0.8,
74        startle_sensitivity: 0.3,
75        recovery_speed:      0.7,
76    };
77
78    // ── Trust field ──────────────────────────────────────────────────────────
79    //
80    // The field maintains an independent trust state per sensory context.
81    // It starts empty — the robot has no experience yet.
82    let mut field: CoherenceField<MbotSensors, 6> = CoherenceField::new();
83
84    // ── Phase space ──────────────────────────────────────────────────────────
85    //
86    // Configurable thresholds for the four-quadrant classifier.
87    // The default values (enter 0.65 / exit 0.55 on coherence) are a good
88    // starting point. Adjust to tune how quickly the robot "warms up".
89    let ps = PhaseSpace::new();
90    let mut phase = SocialPhase::ShyObserver;
91
92    // ── Two sensor contexts ──────────────────────────────────────────────────
93    //
94    // The living room: bright, quiet, a familiar person nearby.
95    // The basement:    dark, moderate noise, no one present.
96    //
97    // These are entirely independent trust contexts. Experience in one
98    // does not transfer to the other.
99    let living_room = ContextKey::new(MbotSensors {
100        brightness:  BrightnessBand::Bright,
101        noise:       NoiseBand::Quiet,
102        presence:    PresenceSignature::Close,
103        motion:      MotionContext::Static,
104        orientation: Orientation::Upright,
105        time_period: TimePeriod::Day,
106    });
107
108    let basement = ContextKey::new(MbotSensors {
109        brightness:  BrightnessBand::Dark,
110        noise:       NoiseBand::Moderate,
111        presence:    PresenceSignature::Absent,
112        motion:      MotionContext::Static,
113        orientation: Orientation::Upright,
114        time_period: TimePeriod::Evening,
115    });
116
117    // ── Phase 1: Build trust in the living room ───────────────────────────────
118    //
119    // Simulate 80 ticks of positive interaction in the living room.
120    // The person is present, the environment is calm, interactions go well.
121    println!("Phase 1: 80 positive interactions in the living room");
122    println!("------------------------------------------------------");
123
124    for tick in 0u64..80 {
125        // alone=false: the person is present; the interaction is social
126        field.positive_interaction(&living_room, &personality, tick, false);
127
128        // instant: the current sensor-level signal (1.0 = fully coherent reading)
129        // In a real system this comes from your homeostasis / sensor fusion layer.
130        let instant: f32 = 0.9;
131        let coherence = field.effective_coherence(instant, &living_room);
132        let tension: f32 = 0.1; // calm environment
133        phase = SocialPhase::classify(coherence, tension, phase, &ps);
134
135        if tick % 20 == 19 {
136            let led = phase.led_tint();
137            println!(
138                "  tick {:>3} | coherence {:.2} | phase {:?} | LED #{:02X}{:02X}{:02X}",
139                tick + 1,
140                coherence,
141                phase,
142                led[0], led[1], led[2]
143            );
144        }
145    }
146
147    // ── Phase 2: The basement — zero trust, same robot ───────────────────────
148    //
149    // The robot is moved to the basement. It has never been here before.
150    // All the trust it built in the living room is irrelevant in this context.
151    // It starts from zero — exactly as it should.
152    println!("\nPhase 2: Robot moved to the basement (zero prior experience)");
153    println!("--------------------------------------------------------------");
154
155    let basement_coherence = field.effective_coherence(0.9, &basement);
156    let basement_tension: f32 = 0.5; // unfamiliar, slightly unnerving
157    phase = SocialPhase::classify(basement_coherence, basement_tension, phase, &ps);
158
159    let led = phase.led_tint();
160    println!(
161        "  coherence in basement: {:.2} | phase {:?} | LED #{:02X}{:02X}{:02X}",
162        basement_coherence,
163        phase,
164        led[0], led[1], led[2]
165    );
166    println!("  (Trust does not transfer. The robot earned nothing here yet.)");
167
168    // ── Phase 3: A startle event back in the living room ─────────────────────
169    //
170    // The robot returns to the familiar living room. Someone slams a door.
171    // Because the robot has deep trust in this context (earned floor > 0),
172    // the negative event causes a drop — but cannot erase the accumulated history.
173    println!("\nPhase 3: Return to living room — startle event (door slam)");
174    println!("------------------------------------------------------------");
175
176    let before = field.effective_coherence(0.9, &living_room);
177    field.negative_interaction(&living_room, &personality, 81);
178    let after = field.effective_coherence(0.9, &living_room);
179
180    println!("  coherence before startle: {:.2}", before);
181    println!("  coherence after startle:  {:.2}", after);
182    println!(
183        "  drop: {:.2} (earned floor protects against erasure)",
184        before - after
185    );
186
187    let tension: f32 = 0.55; // brief spike from the startle
188    phase = SocialPhase::classify(after, tension, phase, &ps);
189    let led = phase.led_tint();
190    println!(
191        "  phase: {:?} | LED #{:02X}{:02X}{:02X}",
192        phase, led[0], led[1], led[2]
193    );
194
195    // ── Phase 4: Recovery ─────────────────────────────────────────────────────
196    //
197    // A few more positive interactions and the robot recovers. The familiar
198    // environment reasserts itself. This is not scripted — it emerges from the
199    // accumulated trust floor protecting the relationship.
200    println!("\nPhase 4: Recovery — 5 positive interactions");
201    println!("--------------------------------------------");
202
203    for tick in 82u64..87 {
204        field.positive_interaction(&living_room, &personality, tick, false);
205    }
206    let recovered = field.effective_coherence(0.9, &living_room);
207    let tension: f32 = 0.1;
208    phase = SocialPhase::classify(recovered, tension, phase, &ps);
209    let led = phase.led_tint();
210    println!(
211        "  coherence after recovery: {:.2} | phase {:?} | LED #{:02X}{:02X}{:02X}",
212        recovered, phase, led[0], led[1], led[2]
213    );
214
215    // ── Summary ───────────────────────────────────────────────────────────────
216    println!("\nSummary");
217    println!("-------");
218    println!(
219        "  Living room trust:  {:.2} ({} interactions)",
220        field.effective_coherence(0.9, &living_room),
221        field.context_interaction_count(&living_room),
222    );
223    println!(
224        "  Basement trust:     {:.2} ({} interactions)",
225        field.effective_coherence(0.9, &basement),
226        field.context_interaction_count(&basement),
227    );
228    println!("\nThe robot knows where it belongs.");
229    println!("No rules. No scripts. Earned.");
230}
Source

pub fn expression_scale(&self) -> f32

Scale factor for expressive output in this phase [0.0, 1.0].

Delegates to permeability with representative mid-range values (coherence = 0.5, tension = 0.3) for backward-compatible ordering. New code should call permeability directly for full control.

Source

pub fn led_tint(&self) -> [u8; 3]

LED color tint for this phase (overlaid on reflex mode color).

Examples found in repository?
examples/mbot2.rs (line 136)
60fn main() {
61    println!("CCF mBot2 — Emergent Behaviour Simulation");
62    println!("==========================================\n");
63
64    // ── Personality ──────────────────────────────────────────────────────────
65    //
66    // These three parameters shape how the robot accumulates and loses trust.
67    // They are analogous to temperament — the same events produce different
68    // magnitudes of response depending on personality.
69    //
70    // This configuration: eager to engage (high curiosity), not easily startled
71    // (low sensitivity), recovers quickly from disruption (high recovery).
72    let personality = Personality {
73        curiosity_drive:     0.8,
74        startle_sensitivity: 0.3,
75        recovery_speed:      0.7,
76    };
77
78    // ── Trust field ──────────────────────────────────────────────────────────
79    //
80    // The field maintains an independent trust state per sensory context.
81    // It starts empty — the robot has no experience yet.
82    let mut field: CoherenceField<MbotSensors, 6> = CoherenceField::new();
83
84    // ── Phase space ──────────────────────────────────────────────────────────
85    //
86    // Configurable thresholds for the four-quadrant classifier.
87    // The default values (enter 0.65 / exit 0.55 on coherence) are a good
88    // starting point. Adjust to tune how quickly the robot "warms up".
89    let ps = PhaseSpace::new();
90    let mut phase = SocialPhase::ShyObserver;
91
92    // ── Two sensor contexts ──────────────────────────────────────────────────
93    //
94    // The living room: bright, quiet, a familiar person nearby.
95    // The basement:    dark, moderate noise, no one present.
96    //
97    // These are entirely independent trust contexts. Experience in one
98    // does not transfer to the other.
99    let living_room = ContextKey::new(MbotSensors {
100        brightness:  BrightnessBand::Bright,
101        noise:       NoiseBand::Quiet,
102        presence:    PresenceSignature::Close,
103        motion:      MotionContext::Static,
104        orientation: Orientation::Upright,
105        time_period: TimePeriod::Day,
106    });
107
108    let basement = ContextKey::new(MbotSensors {
109        brightness:  BrightnessBand::Dark,
110        noise:       NoiseBand::Moderate,
111        presence:    PresenceSignature::Absent,
112        motion:      MotionContext::Static,
113        orientation: Orientation::Upright,
114        time_period: TimePeriod::Evening,
115    });
116
117    // ── Phase 1: Build trust in the living room ───────────────────────────────
118    //
119    // Simulate 80 ticks of positive interaction in the living room.
120    // The person is present, the environment is calm, interactions go well.
121    println!("Phase 1: 80 positive interactions in the living room");
122    println!("------------------------------------------------------");
123
124    for tick in 0u64..80 {
125        // alone=false: the person is present; the interaction is social
126        field.positive_interaction(&living_room, &personality, tick, false);
127
128        // instant: the current sensor-level signal (1.0 = fully coherent reading)
129        // In a real system this comes from your homeostasis / sensor fusion layer.
130        let instant: f32 = 0.9;
131        let coherence = field.effective_coherence(instant, &living_room);
132        let tension: f32 = 0.1; // calm environment
133        phase = SocialPhase::classify(coherence, tension, phase, &ps);
134
135        if tick % 20 == 19 {
136            let led = phase.led_tint();
137            println!(
138                "  tick {:>3} | coherence {:.2} | phase {:?} | LED #{:02X}{:02X}{:02X}",
139                tick + 1,
140                coherence,
141                phase,
142                led[0], led[1], led[2]
143            );
144        }
145    }
146
147    // ── Phase 2: The basement — zero trust, same robot ───────────────────────
148    //
149    // The robot is moved to the basement. It has never been here before.
150    // All the trust it built in the living room is irrelevant in this context.
151    // It starts from zero — exactly as it should.
152    println!("\nPhase 2: Robot moved to the basement (zero prior experience)");
153    println!("--------------------------------------------------------------");
154
155    let basement_coherence = field.effective_coherence(0.9, &basement);
156    let basement_tension: f32 = 0.5; // unfamiliar, slightly unnerving
157    phase = SocialPhase::classify(basement_coherence, basement_tension, phase, &ps);
158
159    let led = phase.led_tint();
160    println!(
161        "  coherence in basement: {:.2} | phase {:?} | LED #{:02X}{:02X}{:02X}",
162        basement_coherence,
163        phase,
164        led[0], led[1], led[2]
165    );
166    println!("  (Trust does not transfer. The robot earned nothing here yet.)");
167
168    // ── Phase 3: A startle event back in the living room ─────────────────────
169    //
170    // The robot returns to the familiar living room. Someone slams a door.
171    // Because the robot has deep trust in this context (earned floor > 0),
172    // the negative event causes a drop — but cannot erase the accumulated history.
173    println!("\nPhase 3: Return to living room — startle event (door slam)");
174    println!("------------------------------------------------------------");
175
176    let before = field.effective_coherence(0.9, &living_room);
177    field.negative_interaction(&living_room, &personality, 81);
178    let after = field.effective_coherence(0.9, &living_room);
179
180    println!("  coherence before startle: {:.2}", before);
181    println!("  coherence after startle:  {:.2}", after);
182    println!(
183        "  drop: {:.2} (earned floor protects against erasure)",
184        before - after
185    );
186
187    let tension: f32 = 0.55; // brief spike from the startle
188    phase = SocialPhase::classify(after, tension, phase, &ps);
189    let led = phase.led_tint();
190    println!(
191        "  phase: {:?} | LED #{:02X}{:02X}{:02X}",
192        phase, led[0], led[1], led[2]
193    );
194
195    // ── Phase 4: Recovery ─────────────────────────────────────────────────────
196    //
197    // A few more positive interactions and the robot recovers. The familiar
198    // environment reasserts itself. This is not scripted — it emerges from the
199    // accumulated trust floor protecting the relationship.
200    println!("\nPhase 4: Recovery — 5 positive interactions");
201    println!("--------------------------------------------");
202
203    for tick in 82u64..87 {
204        field.positive_interaction(&living_room, &personality, tick, false);
205    }
206    let recovered = field.effective_coherence(0.9, &living_room);
207    let tension: f32 = 0.1;
208    phase = SocialPhase::classify(recovered, tension, phase, &ps);
209    let led = phase.led_tint();
210    println!(
211        "  coherence after recovery: {:.2} | phase {:?} | LED #{:02X}{:02X}{:02X}",
212        recovered, phase, led[0], led[1], led[2]
213    );
214
215    // ── Summary ───────────────────────────────────────────────────────────────
216    println!("\nSummary");
217    println!("-------");
218    println!(
219        "  Living room trust:  {:.2} ({} interactions)",
220        field.effective_coherence(0.9, &living_room),
221        field.context_interaction_count(&living_room),
222    );
223    println!(
224        "  Basement trust:     {:.2} ({} interactions)",
225        field.effective_coherence(0.9, &basement),
226        field.context_interaction_count(&basement),
227    );
228    println!("\nThe robot knows where it belongs.");
229    println!("No rules. No scripts. Earned.");
230}

Trait Implementations§

Source§

impl Clone for SocialPhase

Source§

fn clone(&self) -> SocialPhase

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for SocialPhase

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl PartialEq for SocialPhase

Source§

fn eq(&self, other: &SocialPhase) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Copy for SocialPhase

Source§

impl Eq for SocialPhase

Source§

impl StructuralPartialEq for SocialPhase

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.