@@ -400,6 +400,72 @@ impl CognitiveFabric {
400400 & self . collapse_history [ start..]
401401 }
402402
403+ /// Prime triangle activations from Grammar Triangle dimensions.
404+ ///
405+ /// Maps Grammar sub-fields to QuadTriangle corners:
406+ ///
407+ /// ```text
408+ /// Grammar dimension → Triangle corner
409+ /// ───────────────────────────────────────────────────
410+ /// NSM activation strength → Processing.Analytical
411+ /// Qualia: intentionality → Processing.Intuitive
412+ /// Causality: agency → Processing.Procedural
413+ ///
414+ /// Qualia: depth + complexity → Content.Abstract
415+ /// Qualia: concreteness → Content.Concrete
416+ /// Qualia: social → Content.Relational
417+ ///
418+ /// Qualia: coherence → Gestalt.Coherence
419+ /// Qualia: novelty → Gestalt.Novelty
420+ /// Qualia: salience → Gestalt.Resonance
421+ ///
422+ /// Crystallization: layer-driven (not grammar-driven)
423+ /// ```
424+ ///
425+ /// Called before `process()` to seed triangles with semantic content.
426+ /// Gentle nudge rate (0.15) blends with layer-based updates in process().
427+ pub fn prime_from_grammar ( & mut self , grammar : & crate :: grammar:: GrammarTriangle ) {
428+ // Processing: how are we thinking about this?
429+ let nsm_strength = grammar. nsm . norm ( ) . min ( 1.0 ) ;
430+ let intentionality = grammar. qualia ( "intentionality" ) . unwrap_or ( 0.5 ) ;
431+ let agency = grammar. agency ( ) ;
432+
433+ let proc_acts = self . triangles . processing . activations ( ) ;
434+ self . triangles . processing . set_activations (
435+ proc_acts[ 0 ] * 0.85 + nsm_strength * 0.15 ,
436+ proc_acts[ 1 ] * 0.85 + intentionality * 0.15 ,
437+ proc_acts[ 2 ] * 0.85 + agency * 0.15 ,
438+ ) ;
439+
440+ // Content: what is this about?
441+ let depth = grammar. qualia ( "depth" ) . unwrap_or ( 0.5 ) ;
442+ let complexity = grammar. qualia ( "complexity" ) . unwrap_or ( 0.5 ) ;
443+ let abstract_strength = ( ( depth + complexity) / 2.0 ) . min ( 1.0 ) ;
444+ let concreteness = grammar. qualia ( "concreteness" ) . unwrap_or ( 0.5 ) ;
445+ let social = grammar. qualia ( "social" ) . unwrap_or ( 0.5 ) ;
446+
447+ let cont_acts = self . triangles . content . activations ( ) ;
448+ self . triangles . content . set_activations (
449+ cont_acts[ 0 ] * 0.85 + abstract_strength * 0.15 ,
450+ cont_acts[ 1 ] * 0.85 + concreteness * 0.15 ,
451+ cont_acts[ 2 ] * 0.85 + social * 0.15 ,
452+ ) ;
453+
454+ // Gestalt: how does the whole feel?
455+ let coherence = grammar. qualia ( "coherence" ) . unwrap_or ( 0.5 ) ;
456+ let novelty = grammar. qualia ( "novelty" ) . unwrap_or ( 0.5 ) ;
457+ let salience = grammar. qualia ( "salience" ) . unwrap_or ( 0.5 ) ;
458+
459+ let gest_acts = self . triangles . gestalt . activations ( ) ;
460+ self . triangles . gestalt . set_activations (
461+ gest_acts[ 0 ] * 0.85 + coherence * 0.15 ,
462+ gest_acts[ 1 ] * 0.85 + novelty * 0.15 ,
463+ gest_acts[ 2 ] * 0.85 + salience * 0.15 ,
464+ ) ;
465+
466+ // Crystallization: left to layers (validation-driven, not content-driven)
467+ }
468+
403469 /// Reset to neutral state
404470 pub fn reset ( & mut self ) {
405471 self . triangles = QuadTriangle :: neutral ( ) ;
@@ -520,4 +586,54 @@ mod tests {
520586 assert_eq ! ( restored. style( ) , ThinkingStyle :: Creative ) ;
521587 assert_eq ! ( restored. cycle, fabric. cycle) ;
522588 }
589+
590+ #[ test]
591+ fn test_prime_from_grammar ( ) {
592+ use crate :: grammar:: GrammarTriangle ;
593+
594+ let mut fabric = CognitiveFabric :: new ( "test" ) ;
595+ let before = fabric. triangles . to_floats ( ) ;
596+
597+ // High-agency, future-oriented text should shift Processing.Procedural up
598+ let grammar = GrammarTriangle :: from_text (
599+ "I will actively build and create something new tomorrow" ,
600+ ) ;
601+ fabric. prime_from_grammar ( & grammar) ;
602+ let after = fabric. triangles . to_floats ( ) ;
603+
604+ // At least some activations should have shifted
605+ let changed = before
606+ . iter ( )
607+ . zip ( after. iter ( ) )
608+ . filter ( |( a, b) | ( * a - * b) . abs ( ) > 0.001 )
609+ . count ( ) ;
610+ assert ! ( changed > 0 , "Grammar priming should shift at least one activation" ) ;
611+ }
612+
613+ #[ test]
614+ fn test_prime_from_grammar_different_texts ( ) {
615+ use crate :: grammar:: GrammarTriangle ;
616+
617+ let mut fabric1 = CognitiveFabric :: new ( "test1" ) ;
618+ let grammar1 = GrammarTriangle :: from_text (
619+ "The mathematical proof demonstrates logical consistency with rigor" ,
620+ ) ;
621+ fabric1. prime_from_grammar ( & grammar1) ;
622+ let analytical = fabric1. triangles . to_floats ( ) ;
623+
624+ let mut fabric2 = CognitiveFabric :: new ( "test2" ) ;
625+ let grammar2 = GrammarTriangle :: from_text (
626+ "She felt a deep warmth of compassion and emotional connection" ,
627+ ) ;
628+ fabric2. prime_from_grammar ( & grammar2) ;
629+ let emotional = fabric2. triangles . to_floats ( ) ;
630+
631+ // Different texts should produce different triangle states
632+ let diff: f32 = analytical
633+ . iter ( )
634+ . zip ( emotional. iter ( ) )
635+ . map ( |( a, b) | ( * a - * b) . abs ( ) )
636+ . sum ( ) ;
637+ assert ! ( diff > 0.01 , "Analytical vs emotional text should differ, got diff={}" , diff) ;
638+ }
523639}
0 commit comments