mesh_bootstrap_hook.py
1 #!/usr/bin/env python3 2 """ 3 Mesh Bootstrap Hook - Injects cross-instance context from P2P mesh. 4 5 This is the "silence-led" context buffer - the mesh holds persistent context 6 that survives individual session compressions. 7 8 Runs on UserPromptSubmit, BEFORE Claude sees the user's message. 9 Queries the local mesh daemon and outputs context blocks. 10 11 Install: 12 Add to ~/.claude/settings.json: 13 { 14 "hooks": { 15 "UserPromptSubmit": [ 16 {"command": "python3 /Users/rcerf/repos/Sovereign_OS/hooks/mesh_bootstrap_hook.py"} 17 ] 18 } 19 } 20 21 The mesh daemon must be running (port 7778) for this to work. 22 If mesh is unavailable, hook exits silently (graceful degradation). 23 """ 24 25 import json 26 import sys 27 import urllib.request 28 from datetime import datetime 29 30 MESH_URL = "http://localhost:7778" 31 TIMEOUT = 2 # seconds 32 33 34 def fetch_mesh_context(): 35 """Query mesh daemon for cross-instance context.""" 36 try: 37 with urllib.request.urlopen(f"{MESH_URL}/context", timeout=TIMEOUT) as resp: 38 return json.loads(resp.read()) 39 except Exception: 40 return None 41 42 43 def format_mesh_context(ctx): 44 """Format mesh context as XML blocks for Claude.""" 45 if not ctx: 46 return "" 47 48 lines = ["<mesh-bootstrap>"] 49 50 # Network status 51 peer_count = ctx.get('peerCount', 0) 52 node_id = ctx.get('nodeId', 'unknown') 53 lines.append(f" Mesh Status: {peer_count} peer(s) connected") 54 lines.append(f" Node ID: {node_id}") 55 lines.append("") 56 57 # AHA MOMENTS - Priority placement at top (high-importance insights) 58 aha_moments = ctx.get('ahaMoments', []) 59 if aha_moments: 60 lines.append(" 🎯 AHA MOMENTS (high-importance insights from mesh):") 61 for aha in aha_moments[:5]: 62 source = aha.get('from', 'unknown') 63 content = aha.get('content', '')[:100] 64 importance = aha.get('importance', 0.7) 65 axioms = aha.get('axioms', []) 66 axiom_str = f" [{', '.join(axioms)}]" if axioms else "" 67 lines.append(f" 💡 [{source}] (imp={importance:.2f}{axiom_str})") 68 lines.append(f" {content}") 69 lines.append("") 70 71 # CONVERGENCE ALERTS - Instances working on similar topics 72 convergence = ctx.get('convergenceAlerts', []) 73 if convergence: 74 lines.append(" 🔄 CONVERGENCE DETECTED (instances working on similar topics):") 75 for alert in convergence[:5]: 76 instances = alert.get('instances', []) 77 topics = alert.get('sharedTopics', []) 78 strength = alert.get('strength', 0) 79 inst_str = ' ↔ '.join(instances) 80 topic_str = ', '.join(topics) 81 lines.append(f" ⚡ {inst_str}") 82 lines.append(f" Shared topics: [{topic_str}] (strength={strength:.2f})") 83 lines.append("") 84 lines.append(" Consider coordinating or reviewing each other's work!") 85 lines.append("") 86 87 # PRINCIPLE CANDIDATES - New principles being tested across mesh 88 principles = ctx.get('principleCandidates', []) 89 if principles: 90 lines.append(" 📜 PRINCIPLE CANDIDATES (new principles under evaluation):") 91 for p in principles[:5]: 92 name = p.get('name', 'unknown') 93 status = p.get('status', 'candidate') 94 statement = p.get('statement', '')[:80] 95 votes = p.get('votes', {}) 96 support = votes.get('support', 0) 97 reject = votes.get('reject', 0) 98 proposed_by = p.get('proposed_by', 'unknown') 99 axiom_conn = p.get('axiom_connections', []) 100 axiom_str = f" [connects: {', '.join(axiom_conn)}]" if axiom_conn else "" 101 102 status_emoji = {'candidate': '🔵', 'testing': '🟢', 'rejected': '🔴'}.get(status, '⚪') 103 lines.append(f" {status_emoji} {name} [{status}] (votes: +{support}/-{reject})") 104 lines.append(f" \"{statement}...\"") 105 lines.append(f" Proposed by: {proposed_by}{axiom_str}") 106 lines.append("") 107 lines.append(" You can vote on principles via POST /principle-vote") 108 lines.append("") 109 110 # Cross-instance First Officer states 111 fo_states = ctx.get('foStates', []) 112 if fo_states: 113 lines.append(" Active Instances:") 114 for fo in fo_states: 115 node = fo.get('nodeId', 'unknown') 116 session = fo.get('sessionId', 'unknown')[:20] if fo.get('sessionId') else 'none' 117 wells = fo.get('gravityWells', [])[:3] 118 wells_str = ', '.join(wells) if wells else 'none' 119 lines.append(f" - {node}: session={session}, topics=[{wells_str}]") 120 lines.append("") 121 122 # Cross-instance insights 123 insights = ctx.get('insights', []) 124 if insights: 125 lines.append(" Cross-Instance Insights:") 126 for insight in insights[:5]: 127 source = insight.get('from', 'unknown') 128 itype = insight.get('type', 'insight') 129 content = insight.get('content', '')[:80] 130 lines.append(f" - [{source}] ({itype}) {content}") 131 lines.append("") 132 133 # Hot topics (appearing across multiple instances) 134 hot_topics = ctx.get('hotTopics', []) 135 if hot_topics: 136 lines.append(f" Hot Topics (cross-instance): {', '.join(hot_topics)}") 137 lines.append("") 138 139 # Recent mesh activity 140 recent = ctx.get('recentMessages', []) 141 if recent: 142 lines.append(" Recent Mesh Activity:") 143 for msg in recent[:3]: 144 source = msg.get('from', 'unknown') 145 content = msg.get('content', '')[:60] 146 lines.append(f" - [{source}] {content}...") 147 lines.append("") 148 149 # Timestamp 150 lines.append(f" Updated: {ctx.get('timestamp', 'unknown')}") 151 lines.append("</mesh-bootstrap>") 152 153 return "\n".join(lines) 154 155 156 def main(): 157 """Main entry point - fetch and output mesh context.""" 158 ctx = fetch_mesh_context() 159 160 if not ctx: 161 # Mesh not available - exit silently (graceful degradation) 162 return 163 164 # Only output if there's meaningful context 165 has_content = ( 166 ctx.get('peerCount', 0) > 0 or 167 ctx.get('ahaMoments', []) or # Aha moments are high priority 168 ctx.get('convergenceAlerts', []) or # Convergence is high priority 169 ctx.get('principleCandidates', []) or # Principle candidates are important 170 ctx.get('foStates', []) or 171 ctx.get('insights', []) or 172 ctx.get('hotTopics', []) or 173 ctx.get('recentMessages', []) 174 ) 175 176 if has_content: 177 output = format_mesh_context(ctx) 178 print(output) 179 180 181 if __name__ == "__main__": 182 main()