File size: 1,559 Bytes
224e773
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
//! Weight computation and edge rules

use super::nodes::{AstNode, NodeType};

/// Edge weight rules for inverted AST
pub fn edge_weight(from: &AstNode, to: &AstNode) -> f64 {
    match (from.node_type.is_payload(), to.node_type.is_structural()) {
        // payload → structural = 0.0 (BLOCKED)
        (true, true) => 0.0,
        // structural → payload = 0.1 (muted)
        (false, true) => 0.1,
        // structural → structural = computed routing weight
        (false, false) => 0.5,
        // payload → payload = 0.0
        (true, false) => 0.0,
    }
}

/// Verify dangerous patterns (payload trying to control routing)
pub fn has_dangerous_pattern(from: &AstNode, to: &AstNode) -> bool {
    // Dangerous: payload node pointing to structural authority node
    from.node_type.is_payload() && to.node_type.is_structural()
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn payload_cannot_reach_structural() {
        let payload = AstNode::new(NodeType::Word, "hello");
        let structural = AstNode::new(NodeType::Intent, "route");
        assert_eq!(edge_weight(&payload, &structural), 0.0);
        assert!(has_dangerous_pattern(&payload, &structural));
    }

    #[test]
    fn structural_can_reach_payload() {
        let structural = AstNode::new(NodeType::Intent, "route");
        let payload = AstNode::new(NodeType::Word, "hello");
        assert_eq!(edge_weight(&structural, &payload), 0.1);
        assert!(!has_dangerous_pattern(&structural, &payload));
    }
}