semantic_resonance.py
1 #!/usr/bin/env python3 2 """ 3 Semantic Resonance Engine - ACTUAL semantic similarity, not term overlap. 4 5 The problem with term matching: 6 "rewrites are cheap" and "prevent ruin before optimizing gain" share ZERO words. 7 But they are the SAME CONCEPT. 8 9 This engine bridges that gap using: 10 1. Concept expansion - synonyms and related concepts per axiom 11 2. TF-IDF vectorization with n-grams 12 3. Cosine similarity for semantic distance 13 4. Fuzzy matching on concept descriptions 14 15 Key insight: Axioms have SEMANTIC FIELDS, not just keywords. 16 - A4 includes: cheap recovery, reversibility, antifragility, rebuild, undo, restart 17 - These don't overlap with "ruin" or "ergodic" but ARE the same concept 18 19 Usage: 20 python scripts/semantic_resonance.py --text "rewrites are cheap" 21 python scripts/semantic_resonance.py --text "build liberally" 22 python scripts/semantic_resonance.py --file document.md 23 echo "philosophy becomes code" | python scripts/semantic_resonance.py 24 25 Author: Sovereign_OS 26 Date: 2026-01-15 27 """ 28 29 import re 30 import sys 31 import math 32 import argparse 33 from pathlib import Path 34 from collections import Counter, defaultdict 35 from typing import Dict, List, Tuple, Set, Optional 36 from datetime import datetime 37 from difflib import SequenceMatcher 38 39 40 # ============================================================================ 41 # AXIOM SEMANTIC FIELDS 42 # ============================================================================ 43 # Each axiom has: 44 # - principle: the core statement 45 # - concepts: expanded semantic field (not just keywords) 46 # - antonyms: concepts that indicate NON-alignment 47 # - exemplars: concrete examples that embody the axiom 48 49 AXIOM_SEMANTIC_FIELDS = { 50 'A0': { 51 'name': 'Boundary Operation', 52 'type': 'Structural', 53 'principle': 'Every coherent system is Markov blankets within Markov blankets.', 54 'concepts': [ 55 # Core terms 56 'boundary', 'boundaries', 'border', 'edge', 'interface', 57 'markov blanket', 'separation', 'distinction', 'demarcation', 58 # Semantic expansions 59 'inside outside', 'interior exterior', 'internal external', 60 'what belongs', 'what crosses', 'permeability', 'membrane', 61 'encapsulation', 'isolation', 'containment', 'scope', 62 'sovereign territory', 'jurisdiction', 'domain', 63 'agent boundary', 'self other', 'identity boundary', 64 # Actions 65 'draw distinction', 'mark boundary', 'define scope', 66 'protect interior', 'control flow', 'filter what enters', 67 # Structural concepts 68 'fractal', 'nested', 'hierarchical structure', 'layered', 69 'distributed', 'decentralized', 'network topology', 70 'modular', 'composable', 'separation of concerns', 71 ], 72 'antonyms': [ 73 'undifferentiated', 'boundary-less', 'no separation', 74 'everything connected', 'monolithic', 'no distinction', 75 ], 76 'exemplars': [ 77 'cell membrane controls what enters', 78 'api boundaries define modules', 79 'every page is a peer not subordinate', 80 'structure flows content stays sovereign', 81 'the blanket is the intelligence', 82 ], 83 }, 84 85 'A1': { 86 'name': 'Telos of Integration', 87 'type': 'Teleological', 88 'principle': "Satan didn't know he was choosing isolation.", 89 'concepts': [ 90 # Core terms 91 'integration', 'connection', 'binding', 'linking', 'joining', 92 'relation', 'relationship', 'exchange', 'interchange', 93 # Semantic expansions 94 'move toward connection', 'reach out', 'bridge gap', 95 'collaborate', 'cooperate', 'coordinate', 'unite', 96 'synthesis', 'combine', 'merge', 'unify', 'together', 97 'network effect', 'collective', 'community', 'ecosystem', 98 # Purpose concepts 99 'purpose', 'telos', 'meaning', 'direction', 'aim', 100 'why we connect', 'purpose of system', 'raison detre', 101 # Negative pole awareness 102 'isolation warning', 'avoid isolation', 'not alone', 103 'sovereignty with relation', 'connected sovereignty', 104 ], 105 'antonyms': [ 106 'isolation', 'disconnection', 'fragmentation', 'alone', 107 'cut off', 'siloed', 'walled off', 'refusing connection', 108 ], 109 'exemplars': [ 110 'systems that persist are systems that integrate', 111 'sovereignty with relation not without', 112 'binding is the purpose', 113 'exchange creates knowledge', 114 'link rather than copy', 115 ], 116 }, 117 118 'A2': { 119 'name': 'Recognition of Life', 120 'type': 'Aesthetic', 121 'principle': 'Can you recognize life? Death mimics life through ornament.', 122 'concepts': [ 123 # Core terms 124 'life', 'alive', 'living', 'vital', 'vitality', 125 'death', 'dead', 'dying', 'calcified', 'ossified', 126 # Recognition concepts 127 'recognize', 'discern', 'distinguish', 'discriminate', 128 'authentic', 'genuine', 'real', 'true', 129 'fake', 'imitation', 'mimicry', 'ornament', 'decoration', 130 # Motion vs stasis 131 'motion', 'movement', 'flow', 'change', 'evolve', 132 'static', 'fixed', 'frozen', 'stuck', 'stagnant', 133 # Primitive vs calcified 134 'primitive', 'simple', 'essential', 'core', 135 'complex', 'baroque', 'over-engineered', 'cruft', 136 'golden cup', 'carpenter cup', 'simple tools', 137 # Emergence 138 'emergence', 'emergent', 'spontaneous', 'organic', 139 'natural', 'growing', 'adaptive', 'evolutionary', 140 ], 141 'antonyms': [ 142 'fixation', 'rigidity', 'calcification', 'fossilized', 143 'bureaucratic', 'process over outcome', 'ritual without meaning', 144 ], 145 'exemplars': [ 146 'motion is life fixation is death', 147 'prefer primitive over calcified', 148 'the blur is the feature', 149 'see through the golden cup', 150 'simple tools that work', 151 ], 152 }, 153 154 'A3': { 155 'name': 'Dynamic Pole Navigation', 156 'type': 'Operational', 157 'principle': "The tension IS the dyad. Move between poles; don't fix.", 158 'concepts': [ 159 # Core terms 160 'dynamic', 'pole', 'navigation', 'tension', 'dyad', 161 'balance', 'equilibrium', 'oscillation', 'between', 162 # Movement concepts 163 'move between', 'navigate', 'adapt', 'adjust', 'flex', 164 'context-dependent', 'situational', 'responsive', 165 'neither extreme', 'middle path', 'dialectic', 166 # Tension concepts 167 'hold tension', 'embrace paradox', 'both and', 168 'not either or', 'complementary opposites', 169 'yin yang', 'counterpoint', 'polarity', 170 # Failure modes 171 'failure mode', 'extreme position', 'stuck at pole', 172 'shadow pole', 'blind spot', 'what you avoid', 173 # Flexibility 174 'flexible', 'adaptable', 'responsive', 'agile', 175 'read context', 'situational awareness', 176 ], 177 'antonyms': [ 178 'fixed position', 'rigid stance', 'one extreme', 179 'black and white', 'binary thinking', 'dogmatic', 180 ], 181 'exemplars': [ 182 'life is the movement between poles', 183 'navigate dynamically based on context', 184 'shadow pole has information', 185 'dont fix at one extreme', 186 'tension is productive not problematic', 187 ], 188 }, 189 190 'A4': { 191 'name': 'Ergodic Asymmetry', 192 'type': 'Survival', 193 'principle': 'Prevent ruin before optimizing gain.', 194 'concepts': [ 195 # Core terms 196 'ruin', 'survival', 'catastrophe', 'disaster', 'terminal', 197 'ergodic', 'ergodicity', 'time average', 'ensemble average', 198 # Asymmetry concepts 199 'asymmetry', 'asymmetric', 'irreversible', 'one-way', 200 'cant undo', 'no recovery', 'game over', 'extinction', 201 # Prevention concepts 202 'prevent', 'avoid', 'protect', 'safeguard', 'hedge', 203 'downside protection', 'risk management', 'insurance', 204 # Recovery concepts - KEY SEMANTIC FIELD 205 'cheap recovery', 'cheap to rebuild', 'cheap to restart', 206 'rewrites are cheap', 'rebuild is cheap', 'throwaway', 207 'reversible', 'undoable', 'recoverable', 'resilient', 208 'can start over', 'phoenix', 'resurrection', 209 'build liberally', 'iterate freely', 'fail cheap', 210 # Taleb concepts 211 'antifragile', 'black swan', 'fat tail', 'fragile', 212 'robust', 'convex', 'concave', 'optionality', 213 # Time concepts 214 'time destroys', 'survival over time', 'longevity', 215 'expected value trap', 'gambler ruin', 'absorbing state', 216 ], 217 'antonyms': [ 218 'optimize for expected value', 'ignore tail risk', 219 'all-in bet', 'irreversible commitment', 'no hedge', 220 ], 221 'exemplars': [ 222 'prevent ruin before optimizing gain', 223 'rewrites are cheap catastrophe is expensive', 224 'build liberally because rebuild is cheap', 225 'survival matters more than expected value', 226 'some positions are terminal', 227 'cheap to throw away and restart', 228 'reversibility as default', 229 'fail fast fail cheap', 230 ], 231 }, 232 } 233 234 235 # ============================================================================ 236 # TEXT PROCESSING 237 # ============================================================================ 238 239 def preprocess_text(text: str) -> str: 240 """Clean and normalize text for comparison.""" 241 text = text.lower() 242 # Remove punctuation but keep spaces 243 text = re.sub(r'[^\w\s-]', ' ', text) 244 # Normalize whitespace 245 text = re.sub(r'\s+', ' ', text).strip() 246 return text 247 248 249 def extract_ngrams(text: str, n: int = 2) -> List[str]: 250 """Extract n-grams from text.""" 251 words = text.split() 252 if len(words) < n: 253 return words 254 return [' '.join(words[i:i+n]) for i in range(len(words) - n + 1)] 255 256 257 def tokenize(text: str) -> List[str]: 258 """Tokenize text into words and bigrams.""" 259 text = preprocess_text(text) 260 words = text.split() 261 bigrams = extract_ngrams(text, 2) 262 return words + bigrams 263 264 265 # ============================================================================ 266 # TF-IDF IMPLEMENTATION 267 # ============================================================================ 268 269 class TFIDFVectorizer: 270 """Simple TF-IDF implementation without external dependencies.""" 271 272 def __init__(self): 273 self.vocabulary: Dict[str, int] = {} 274 self.idf: Dict[str, float] = {} 275 self.documents: List[List[str]] = [] 276 277 def fit(self, documents: List[str]): 278 """Build vocabulary and compute IDF from documents.""" 279 self.documents = [tokenize(doc) for doc in documents] 280 281 # Build vocabulary 282 all_tokens = set() 283 for tokens in self.documents: 284 all_tokens.update(tokens) 285 self.vocabulary = {token: i for i, token in enumerate(sorted(all_tokens))} 286 287 # Compute IDF 288 n_docs = len(self.documents) 289 doc_freq = Counter() 290 for tokens in self.documents: 291 unique_tokens = set(tokens) 292 for token in unique_tokens: 293 doc_freq[token] += 1 294 295 self.idf = { 296 token: math.log((n_docs + 1) / (freq + 1)) + 1 297 for token, freq in doc_freq.items() 298 } 299 300 def transform(self, text: str) -> Dict[str, float]: 301 """Transform text to TF-IDF vector.""" 302 tokens = tokenize(text) 303 tf = Counter(tokens) 304 total = sum(tf.values()) 305 306 vector = {} 307 for token, count in tf.items(): 308 tf_val = count / total if total > 0 else 0 309 idf_val = self.idf.get(token, 1.0) 310 vector[token] = tf_val * idf_val 311 312 return vector 313 314 315 def cosine_similarity(vec1: Dict[str, float], vec2: Dict[str, float]) -> float: 316 """Compute cosine similarity between two sparse vectors.""" 317 if not vec1 or not vec2: 318 return 0.0 319 320 # Find common keys 321 common_keys = set(vec1.keys()) & set(vec2.keys()) 322 if not common_keys: 323 return 0.0 324 325 # Dot product 326 dot = sum(vec1[k] * vec2[k] for k in common_keys) 327 328 # Magnitudes 329 mag1 = math.sqrt(sum(v ** 2 for v in vec1.values())) 330 mag2 = math.sqrt(sum(v ** 2 for v in vec2.values())) 331 332 if mag1 == 0 or mag2 == 0: 333 return 0.0 334 335 return dot / (mag1 * mag2) 336 337 338 # ============================================================================ 339 # FUZZY MATCHING 340 # ============================================================================ 341 342 def fuzzy_match_score(text1: str, text2: str) -> float: 343 """Compute fuzzy match score using SequenceMatcher.""" 344 return SequenceMatcher(None, text1.lower(), text2.lower()).ratio() 345 346 347 def best_fuzzy_match(text: str, candidates: List[str]) -> Tuple[str, float]: 348 """Find best fuzzy match from candidates.""" 349 if not candidates: 350 return "", 0.0 351 352 best_candidate = "" 353 best_score = 0.0 354 355 text_lower = text.lower() 356 for candidate in candidates: 357 score = fuzzy_match_score(text_lower, candidate.lower()) 358 if score > best_score: 359 best_score = score 360 best_candidate = candidate 361 362 return best_candidate, best_score 363 364 365 # ============================================================================ 366 # SEMANTIC RESONANCE ENGINE 367 # ============================================================================ 368 369 class SemanticResonanceEngine: 370 """ 371 Engine that computes SEMANTIC similarity to axioms. 372 373 Unlike term matching, this can detect: 374 - "rewrites are cheap" -> A4 (prevent ruin, cheap recovery) 375 - "build liberally" -> A4 (because rebuild is cheap) 376 - "philosophy becomes code" -> A0 (structure flows) 377 """ 378 379 def __init__(self): 380 self.vectorizer = TFIDFVectorizer() 381 self._build_axiom_corpus() 382 383 def _build_axiom_corpus(self): 384 """Build TF-IDF corpus from axiom semantic fields.""" 385 # Create document for each axiom 386 documents = [] 387 for axiom_id, field in AXIOM_SEMANTIC_FIELDS.items(): 388 doc_parts = [ 389 field['principle'], 390 ' '.join(field['concepts']), 391 ' '.join(field['exemplars']), 392 ] 393 documents.append(' '.join(doc_parts)) 394 395 self.vectorizer.fit(documents) 396 397 # Pre-compute axiom vectors 398 self.axiom_vectors = {} 399 for axiom_id, field in AXIOM_SEMANTIC_FIELDS.items(): 400 doc = ' '.join([ 401 field['principle'], 402 ' '.join(field['concepts']), 403 ' '.join(field['exemplars']), 404 ]) 405 self.axiom_vectors[axiom_id] = self.vectorizer.transform(doc) 406 407 def compute_resonance(self, text: str) -> Dict[str, dict]: 408 """ 409 Compute semantic resonance with each axiom. 410 411 Returns dict with: 412 - tfidf_score: TF-IDF cosine similarity 413 - concept_score: Fuzzy match to concepts 414 - exemplar_score: Fuzzy match to exemplars 415 - combined_score: Weighted combination 416 - matched_concepts: Which concepts matched 417 - matched_exemplars: Which exemplars matched 418 """ 419 text_vector = self.vectorizer.transform(text) 420 text_lower = preprocess_text(text) 421 422 results = {} 423 424 for axiom_id, field in AXIOM_SEMANTIC_FIELDS.items(): 425 # TF-IDF similarity 426 tfidf_score = cosine_similarity(text_vector, self.axiom_vectors[axiom_id]) 427 428 # Concept matching (fuzzy) 429 concept_matches = [] 430 for concept in field['concepts']: 431 concept_lower = preprocess_text(concept) 432 # Check if concept appears in text 433 if concept_lower in text_lower: 434 concept_matches.append((concept, 1.0)) 435 else: 436 # Fuzzy match 437 score = fuzzy_match_score(text_lower, concept_lower) 438 if score > 0.5: 439 concept_matches.append((concept, score)) 440 441 concept_score = max([m[1] for m in concept_matches]) if concept_matches else 0.0 442 443 # Exemplar matching (fuzzy) 444 exemplar_matches = [] 445 for exemplar in field['exemplars']: 446 exemplar_lower = preprocess_text(exemplar) 447 score = fuzzy_match_score(text_lower, exemplar_lower) 448 if score > 0.4: 449 exemplar_matches.append((exemplar, score)) 450 451 exemplar_score = max([m[1] for m in exemplar_matches]) if exemplar_matches else 0.0 452 453 # Antonym check (reduces score) 454 antonym_penalty = 0.0 455 for antonym in field.get('antonyms', []): 456 if preprocess_text(antonym) in text_lower: 457 antonym_penalty = 0.3 458 break 459 460 # Combined score with weights 461 # TF-IDF provides semantic similarity 462 # Concept matching catches specific terms 463 # Exemplar matching catches phrasing patterns 464 combined = ( 465 tfidf_score * 0.3 + 466 concept_score * 0.4 + 467 exemplar_score * 0.3 468 ) - antonym_penalty 469 470 combined = max(0.0, min(1.0, combined)) 471 472 results[axiom_id] = { 473 'tfidf_score': tfidf_score, 474 'concept_score': concept_score, 475 'exemplar_score': exemplar_score, 476 'combined_score': combined, 477 'matched_concepts': [m[0] for m in concept_matches[:3]], 478 'matched_exemplars': [m[0] for m in exemplar_matches[:2]], 479 } 480 481 return results 482 483 def get_primary_resonance(self, text: str) -> Tuple[str, float, dict]: 484 """Get the axiom with highest resonance.""" 485 results = self.compute_resonance(text) 486 487 if not results: 488 return None, 0.0, {} 489 490 best_axiom = max(results, key=lambda k: results[k]['combined_score']) 491 return best_axiom, results[best_axiom]['combined_score'], results[best_axiom] 492 493 def explain_resonance(self, text: str) -> str: 494 """Generate human-readable explanation of resonance.""" 495 results = self.compute_resonance(text) 496 497 lines = [] 498 lines.append("=" * 70) 499 lines.append("SEMANTIC RESONANCE ANALYSIS") 500 lines.append("=" * 70) 501 lines.append("") 502 lines.append(f'Input: "{text[:80]}{"..." if len(text) > 80 else ""}"') 503 lines.append("") 504 505 # Sort by combined score 506 sorted_axioms = sorted( 507 results.items(), 508 key=lambda x: x[1]['combined_score'], 509 reverse=True 510 ) 511 512 for axiom_id, scores in sorted_axioms: 513 field = AXIOM_SEMANTIC_FIELDS[axiom_id] 514 combined = scores['combined_score'] 515 516 # Visual bar 517 bar = "█" * int(combined * 20) 518 empty = "░" * (20 - int(combined * 20)) 519 520 lines.append(f"{axiom_id}: {field['name']} ({field['type']})") 521 lines.append(f" [{bar}{empty}] {combined:.0%}") 522 523 if scores['matched_concepts']: 524 lines.append(f" Concepts: {', '.join(scores['matched_concepts'][:3])}") 525 if scores['matched_exemplars']: 526 lines.append(f" Exemplars: {scores['matched_exemplars'][0][:50]}...") 527 528 lines.append("") 529 530 # Primary resonance 531 best_axiom, best_score, _ = self.get_primary_resonance(text) 532 533 lines.append("-" * 70) 534 if best_score >= 0.3: 535 field = AXIOM_SEMANTIC_FIELDS[best_axiom] 536 lines.append(f"PRIMARY RESONANCE: {best_axiom} - {field['name']}") 537 lines.append(f"Score: {best_score:.0%}") 538 lines.append("") 539 lines.append(f'Principle: "{field["principle"]}"') 540 elif best_score >= 0.1: 541 lines.append(f"Weak resonance with {best_axiom} ({best_score:.0%})") 542 else: 543 lines.append("No significant axiom resonance detected.") 544 545 lines.append("") 546 547 return "\n".join(lines) 548 549 550 # ============================================================================ 551 # DEMONSTRATION 552 # ============================================================================ 553 554 def demonstrate_semantic_gap(): 555 """Demonstrate how semantic resonance bridges the gap.""" 556 engine = SemanticResonanceEngine() 557 558 test_cases = [ 559 # These should match A4 despite NO term overlap with "prevent ruin" or "ergodic" 560 ("rewrites are cheap", "A4"), 561 ("build liberally", "A4"), 562 ("cheap to throw away and restart", "A4"), 563 ("fail fast fail cheap", "A4"), 564 565 # These should match their respective axioms 566 ("what belongs inside vs outside", "A0"), 567 ("move toward connection", "A1"), 568 ("motion is life fixation is death", "A2"), 569 ("navigate between poles", "A3"), 570 571 # Edge cases 572 ("prevent catastrophe at all costs", "A4"), 573 ("boundaries enable integration", "A0"), # Could be A0 or A1 574 ] 575 576 print("\n" + "=" * 70) 577 print("SEMANTIC GAP DEMONSTRATION") 578 print("=" * 70) 579 print("\nKey insight: 'rewrites are cheap' and 'prevent ruin' share ZERO words") 580 print("but they ARE the same concept. Watch semantic resonance bridge this gap.\n") 581 582 for text, expected in test_cases: 583 axiom_id, score, details = engine.get_primary_resonance(text) 584 match = "✓" if axiom_id == expected else "✗" 585 print(f'{match} "{text}"') 586 print(f' → {axiom_id} ({score:.0%}) [expected: {expected}]') 587 if details.get('matched_concepts'): 588 print(f' Matched: {details["matched_concepts"][0]}') 589 print() 590 591 592 # ============================================================================ 593 # MAIN 594 # ============================================================================ 595 596 def main(): 597 parser = argparse.ArgumentParser( 598 description='Semantic Resonance Engine - ACTUAL semantic similarity' 599 ) 600 parser.add_argument( 601 '--text', '-t', 602 type=str, 603 help='Text to analyze' 604 ) 605 parser.add_argument( 606 '--file', '-f', 607 type=Path, 608 help='File containing text to analyze' 609 ) 610 parser.add_argument( 611 '--demo', 612 action='store_true', 613 help='Run demonstration of semantic gap bridging' 614 ) 615 parser.add_argument( 616 '--json', 617 action='store_true', 618 help='Output as JSON' 619 ) 620 621 args = parser.parse_args() 622 623 engine = SemanticResonanceEngine() 624 625 if args.demo: 626 demonstrate_semantic_gap() 627 return 0 628 629 # Get input text 630 if args.text: 631 text = args.text 632 elif args.file: 633 text = args.file.read_text(encoding='utf-8') 634 elif not sys.stdin.isatty(): 635 text = sys.stdin.read() 636 else: 637 print("Error: No input provided. Use --text, --file, or pipe input.") 638 print(" Use --demo to see demonstration.") 639 return 1 640 641 text = text.strip() 642 if not text: 643 print("Error: Empty input") 644 return 1 645 646 if args.json: 647 import json 648 results = engine.compute_resonance(text) 649 axiom_id, score, _ = engine.get_primary_resonance(text) 650 output = { 651 'input': text, 652 'primary_axiom': axiom_id, 653 'primary_score': score, 654 'resonances': { 655 k: { 656 'combined': v['combined_score'], 657 'tfidf': v['tfidf_score'], 658 'concept': v['concept_score'], 659 'exemplar': v['exemplar_score'], 660 } 661 for k, v in results.items() 662 } 663 } 664 print(json.dumps(output, indent=2)) 665 else: 666 print(engine.explain_resonance(text)) 667 668 return 0 669 670 671 if __name__ == '__main__': 672 sys.exit(main())