/ scripts / axiom_resonance.py
axiom_resonance.py
  1  #!/usr/bin/env python3
  2  """
  3  Axiom Resonance Checker - How high does this insight rise?
  4  
  5  The axioms are the foundation of Sovereign_OS. This script checks
  6  how strongly an insight resonates with each axiom level.
  7  
  8  The pyramid structure:
  9      A0: Boundary Operation (Structural) - the base
 10      A1: Telos of Integration (Teleological) - purpose layer
 11      A2: Recognition of Life (Aesthetic) - discrimination layer
 12      A3: Dynamic Pole Navigation (Operational) - action layer
 13      A4: Ergodic Asymmetry (Survival) - survival layer [CANDIDATE]
 14  
 15  An insight that resonates with A0 touches the structural foundation.
 16  An insight that resonates with multiple axioms is highly integrated.
 17  
 18  Usage:
 19      echo "build liberally" | python scripts/axiom_resonance.py
 20      python scripts/axiom_resonance.py --text "philosophy becomes code"
 21  """
 22  
 23  import re
 24  import sys
 25  from pathlib import Path
 26  from collections import Counter
 27  from typing import Dict, List, Tuple
 28  import argparse
 29  from datetime import datetime
 30  
 31  # Axiom definitions with their key concepts and terms
 32  AXIOMS = {
 33      'A0': {
 34          'name': 'Boundary Operation',
 35          'type': 'Structural',
 36          'principle': 'Every coherent system is Markov blankets within Markov blankets.',
 37          'terms': {
 38              'boundary', 'boundaries', 'markov', 'blanket', 'blankets',
 39              'structure', 'structural', 'coherent', 'system', 'systems',
 40              'interior', 'exterior', 'interface', 'interface', 'flow',
 41              'permeable', 'permeability', 'separation', 'inside', 'outside',
 42              'sovereign', 'sovereignty', 'agent', 'agents', 'peer', 'peers',
 43              'distributed', 'decentralized', 'hierarchy', 'hierarchical',
 44              'rhizome', 'rhizomatic', 'network', 'graph',
 45          },
 46          'concepts': [
 47              'what is inside vs outside',
 48              'boundary is intelligence',
 49              'structure flows content sovereign',
 50              'distributed knowledge',
 51              'no central authority',
 52              'every page is a peer',
 53          ]
 54      },
 55      'A1': {
 56          'name': 'Telos of Integration',
 57          'type': 'Teleological',
 58          'principle': "Satan didn't know he was choosing isolation.",
 59          'terms': {
 60              'integration', 'integrate', 'binding', 'bind', 'connection',
 61              'connect', 'connected', 'relation', 'relationship', 'exchange',
 62              'link', 'links', 'linking', 'isolation', 'isolated', 'satan',
 63              'together', 'combine', 'synthesis', 'unified', 'unity',
 64              'purpose', 'telos', 'meaning', 'coherence',
 65          },
 66          'concepts': [
 67              'move toward connection',
 68              'sovereignty with relation',
 69              'binding is the purpose',
 70              'exchange creates knowledge',
 71              'integration over isolation',
 72          ]
 73      },
 74      'A2': {
 75          'name': 'Recognition of Life',
 76          'type': 'Aesthetic',
 77          'principle': 'Can you recognize life? Death mimics life through ornament.',
 78          'terms': {
 79              'life', 'alive', 'living', 'death', 'dead', 'dying', 'mimic',
 80              'ornament', 'ornamental', 'primitive', 'calcified', 'calcify',
 81              'motion', 'movement', 'moving', 'fixation', 'fixed', 'static',
 82              'recognize', 'recognition', 'authentic', 'genuine', 'real',
 83              'emergence', 'emergent', 'spontaneous', 'organic', 'vital',
 84              'carpenter', 'cup', 'golden',
 85          },
 86          'concepts': [
 87              'motion is life',
 88              'fixation is death',
 89              'primitive over calcified',
 90              'see through ornament',
 91              'the blur is the feature',
 92          ]
 93      },
 94      'A3': {
 95          'name': 'Dynamic Pole Navigation',
 96          'type': 'Operational',
 97          'principle': "The tension IS the dyad. Move between poles; don't fix.",
 98          'terms': {
 99              'dynamic', 'pole', 'poles', 'navigation', 'navigate', 'tension',
100              'dyad', 'movement', 'balance', 'between', 'oscillate',
101              'context', 'contextual', 'adapt', 'adaptation', 'adjust',
102              'shadow', 'opposite', 'counterpoint', 'flex', 'flexible',
103              'failure', 'mode', 'modes', 'extreme', 'extremes',
104          },
105          'concepts': [
106              'tension is the dyad',
107              'move between poles',
108              'dont fix position',
109              'shadow pole has information',
110              'life is the movement',
111              'navigate dont fix',
112          ]
113      },
114      'A4': {
115          'name': 'Ergodic Asymmetry',
116          'type': 'Survival',
117          'principle': 'Prevent ruin before optimizing gain.',
118          'terms': {
119              'ruin', 'survival', 'survive', 'catastrophe', 'catastrophic',
120              'ergodic', 'ergodicity', 'terminal', 'irreversible', 'loss',
121              'gain', 'optimize', 'optimization', 'risk', 'risks',
122              'prevent', 'prevention', 'asymmetry', 'asymmetric',
123              'cheap', 'expensive', 'rewrite', 'rebuild', 'throw', 'throwaway',
124              'time', 'average', 'ensemble', 'taleb', 'antifragile',
125          },
126          'concepts': [
127              'prevent ruin',
128              'survival matters more',
129              'some positions terminal',
130              'time average not ensemble',
131              'cheap to rebuild',
132              'rewrites are cheap',
133          ]
134      },
135  }
136  
137  
138  def extract_terms(text: str) -> Counter:
139      """Extract terms from text."""
140      text = text.lower()
141      words = re.findall(r'[a-zA-Z][a-zA-Z-]*[a-zA-Z]|[a-zA-Z]', text)
142      return Counter(words)
143  
144  
145  def check_concept_match(text: str, concepts: List[str]) -> float:
146      """Check for concept-level matches (fuzzy)."""
147      text_lower = text.lower()
148      matches = 0
149      for concept in concepts:
150          # Check if concept words appear in text
151          concept_words = set(concept.split())
152          text_words = set(text_lower.split())
153          overlap = len(concept_words & text_words)
154          if overlap >= 2:  # At least 2 words match
155              matches += 1
156      return matches / len(concepts) if concepts else 0
157  
158  
159  def calculate_axiom_resonance(text: str) -> Dict[str, float]:
160      """Calculate resonance with each axiom."""
161      text_terms = extract_terms(text)
162      text_lower = text.lower()
163  
164      resonances = {}
165  
166      for axiom_id, axiom in AXIOMS.items():
167          # Term overlap
168          term_matches = sum(text_terms.get(term, 0) for term in axiom['terms'])
169          term_score = min(1.0, term_matches / 5)  # Normalize
170  
171          # Concept match
172          concept_score = check_concept_match(text, axiom['concepts'])
173  
174          # Combined score (terms + concepts)
175          resonance = (term_score * 0.6) + (concept_score * 0.4)
176          resonances[axiom_id] = resonance
177  
178      return resonances
179  
180  
181  def determine_pyramid_level(resonances: Dict[str, float]) -> Tuple[str, float]:
182      """
183      Determine where the insight rests in the pyramid.
184  
185      Returns the highest-resonating axiom and its score.
186      """
187      if not resonances:
188          return None, 0
189  
190      # Find max resonance
191      max_axiom = max(resonances, key=resonances.get)
192      max_score = resonances[max_axiom]
193  
194      return max_axiom, max_score
195  
196  
197  def print_resonance_report(text: str, resonances: Dict[str, float]):
198      """Print the axiom resonance report."""
199      print("=" * 70)
200      print("AXIOM RESONANCE ANALYSIS")
201      print("=" * 70)
202      print()
203      print(f"Input: \"{text[:80]}{'...' if len(text) > 80 else ''}\"")
204      print()
205      print("Resonance with each axiom level:")
206      print()
207  
208      # Visual pyramid (inverted)
209      levels = ['A4', 'A3', 'A2', 'A1', 'A0']  # Top to bottom
210  
211      for i, axiom_id in enumerate(levels):
212          axiom = AXIOMS[axiom_id]
213          score = resonances.get(axiom_id, 0)
214          bar = "█" * int(score * 20)
215  
216          # Pyramid indentation (inverted - wider at top)
217          indent = "  " * (4 - i)
218  
219          status = ""
220          if axiom_id == 'A4':
221              status = " [CANDIDATE]"
222  
223          print(f"{indent}{axiom_id}: {axiom['name']} ({axiom['type']}){status}")
224          print(f"{indent}    [{score:>5.0%}] {bar}")
225          print()
226  
227      # Determine pyramid level
228      max_axiom, max_score = determine_pyramid_level(resonances)
229  
230      print("-" * 70)
231  
232      if max_score >= 0.3:
233          axiom = AXIOMS[max_axiom]
234          print(f"✓ This insight rests at {max_axiom}: {axiom['name']}")
235          print(f"  Resonance: {max_score:.0%}")
236          print(f"  Type: {axiom['type']}")
237          print()
238          print(f"  Principle: \"{axiom['principle']}\"")
239      elif max_score >= 0.1:
240          print(f"~ Weak resonance with {max_axiom} ({max_score:.0%})")
241          print("  This insight may be tangential to the axiom stack.")
242      else:
243          print("⚠ No significant axiom resonance detected.")
244          print("  This insight may be:")
245          print("  - A new concept not yet integrated")
246          print("  - Operational detail without axiomatic implications")
247          print("  - A candidate for a new axiom (if persistent)")
248  
249      print()
250  
251      # Multi-axiom resonance
252      significant = [(k, v) for k, v in resonances.items() if v >= 0.15]
253      if len(significant) > 1:
254          print("Multi-axiom insight:")
255          for axiom_id, score in sorted(significant, key=lambda x: x[1], reverse=True):
256              print(f"  - {axiom_id}: {score:.0%}")
257          print()
258          print("  This insight touches multiple layers of the foundation.")
259  
260      return max_axiom, max_score
261  
262  
263  def create_canonical_entry(
264      text: str,
265      resonances: Dict[str, float],
266      max_axiom: str,
267      max_score: float,
268      output_dir: Path
269  ) -> Path:
270      """Create a canonical entry for high-resonance insights."""
271      timestamp = datetime.now().strftime('%Y%m%d-%H%M%S')
272      filename = f"{timestamp}-canonical-{max_axiom.lower()}.md"
273      filepath = output_dir / filename
274  
275      axiom = AXIOMS[max_axiom]
276  
277      lines = [
278          f"# Canonical Insight - {max_axiom}",
279          "",
280          f"*Captured: {datetime.now().strftime('%Y-%m-%d %H:%M')}*",
281          "",
282          "---",
283          "",
284          "## The Insight",
285          "",
286          f"> {text}",
287          "",
288          "## Axiom Resonance",
289          "",
290          f"**Primary:** {max_axiom} - {axiom['name']} ({max_score:.0%})",
291          f"**Type:** {axiom['type']}",
292          "",
293          f"**Principle:** \"{axiom['principle']}\"",
294          "",
295          "## All Resonances",
296          "",
297      ]
298  
299      for axiom_id in ['A0', 'A1', 'A2', 'A3', 'A4']:
300          score = resonances.get(axiom_id, 0)
301          lines.append(f"- {axiom_id}: {score:.0%}")
302  
303      lines.extend([
304          "",
305          "## Integration Notes",
306          "",
307          "Consider:",
308          f"- Adding to [[{max_axiom.replace('A', 'A').lower()}-{axiom['name'].lower().replace(' ', '-')}]] documentation",
309          "- Extracting as a derived principle",
310          "- Testing against edge cases",
311          "",
312          "---",
313          "",
314          f"*Generated by Axiom Resonance Checker | {datetime.now().strftime('%Y-%m-%d %H:%M')}*",
315      ])
316  
317      filepath.write_text('\n'.join(lines), encoding='utf-8')
318      return filepath
319  
320  
321  def main():
322      parser = argparse.ArgumentParser(
323          description='Axiom Resonance Checker - How high does this insight rise?'
324      )
325      parser.add_argument(
326          '--text', '-t',
327          type=str,
328          help='Text to analyze'
329      )
330      parser.add_argument(
331          '--file', '-f',
332          type=Path,
333          help='File containing text to analyze'
334      )
335      parser.add_argument(
336          '--canonize',
337          action='store_true',
338          help='Create canonical entry for high-resonance insights'
339      )
340      parser.add_argument(
341          '--threshold',
342          type=float,
343          default=0.25,
344          help='Minimum resonance for canonization (default: 0.25)'
345      )
346      parser.add_argument(
347          '--path', '-p',
348          type=Path,
349          default=Path(__file__).parent.parent,
350          help='Path to Sovereign_OS repo'
351      )
352  
353      args = parser.parse_args()
354  
355      # Get input text
356      if args.text:
357          text = args.text
358      elif args.file:
359          text = args.file.read_text(encoding='utf-8')
360      elif not sys.stdin.isatty():
361          text = sys.stdin.read()
362      else:
363          print("Error: No input provided. Use --text, --file, or pipe input.", file=sys.stderr)
364          return 1
365  
366      text = text.strip()
367      if not text:
368          print("Error: Empty input", file=sys.stderr)
369          return 1
370  
371      # Calculate resonances
372      resonances = calculate_axiom_resonance(text)
373  
374      # Print report
375      max_axiom, max_score = print_resonance_report(text, resonances)
376  
377      # Canonize if requested and threshold met
378      if args.canonize and max_score >= args.threshold:
379          canonical_dir = args.path / 'sessions' / 'canonical'
380          canonical_dir.mkdir(parents=True, exist_ok=True)
381  
382          filepath = create_canonical_entry(
383              text, resonances, max_axiom, max_score, canonical_dir
384          )
385          print(f"✓ Canonical entry created: {filepath}")
386      elif args.canonize:
387          print(f"⚠ Resonance ({max_score:.0%}) below threshold ({args.threshold:.0%})")
388          print("  Not canonized. Use --threshold to adjust.")
389  
390      return 0
391  
392  
393  if __name__ == '__main__':
394      sys.exit(main())