end_of_day_synthesis.py
1 #!/usr/bin/env python3 2 """ 3 End of Day Synthesis - Torah/Talmud Convergence Workflow 4 5 "Simplify as much as possible, but no more." - Einstein 6 7 Run at day's end to: 8 1. HUNTING PARTIES - Review full day's work, connect all nodes 9 - Tie discoveries back to morning context 10 - Ensure graph coherence, reduce orphans 11 12 2. CODE SYNTHESIS - Review all code written 13 - Find duplicates, candidates for merging 14 - Identify dead code 15 - Torah/Talmud health check 16 17 3. SESSION SYNTHESIS - Tie beginning to end 18 - What did we set out to do? 19 - What did we discover? 20 - What new principles emerged? 21 22 4. SIMPLIFICATION PASS - Compress learnings 23 - Can any new code be merged with existing? 24 - Can any new principles simplify existing ones? 25 - What Talmud sharpens which Torah? 26 27 Usage: 28 python3 scripts/end_of_day_synthesis.py # Full synthesis 29 python3 scripts/end_of_day_synthesis.py --quick # Quick summary only 30 python3 scripts/end_of_day_synthesis.py --graph # Graph focus 31 python3 scripts/end_of_day_synthesis.py --code # Code focus 32 """ 33 34 import subprocess 35 import sys 36 import json 37 from pathlib import Path 38 from datetime import datetime, timedelta 39 from typing import Dict, List, Optional 40 41 REPO_ROOT = Path(__file__).parent.parent 42 SESSIONS_DIR = REPO_ROOT / "sessions" 43 SOVEREIGN_HOME = Path.home() / ".sovereign" 44 45 46 def run_script(script_path: str, args: List[str] = None) -> str: 47 """Run a script and return output.""" 48 cmd = ["python3", str(REPO_ROOT / script_path)] 49 if args: 50 cmd.extend(args) 51 try: 52 result = subprocess.run(cmd, capture_output=True, text=True, timeout=60) 53 return result.stdout + result.stderr 54 except Exception as e: 55 return f"Error: {e}" 56 57 58 def get_daily_debriefs() -> List[Path]: 59 """Get today's session debriefs.""" 60 today = datetime.now().strftime("%Y-%m-%d") 61 debrief_dir = SESSIONS_DIR / "debriefs" 62 if not debrief_dir.exists(): 63 return [] 64 return list(debrief_dir.glob(f"{today}*.md")) 65 66 67 def get_morning_context() -> Optional[Dict]: 68 """Get what we started the day with.""" 69 # Check for LIVE-COMPRESSION from start of day 70 live = SESSIONS_DIR / "LIVE-COMPRESSION.md" 71 if live.exists(): 72 content = live.read_text() 73 return {"content": content[:2000], "file": str(live)} 74 return None 75 76 77 def get_graph_stats() -> Dict: 78 """Get current graph statistics.""" 79 graph_data = SOVEREIGN_HOME / "graph-data.json" 80 if graph_data.exists(): 81 try: 82 data = json.load(open(graph_data)) 83 nodes = data.get("nodes", []) 84 edges = data.get("edges", []) 85 86 # Count orphans 87 connected = set() 88 for edge in edges: 89 connected.add(edge.get("source")) 90 connected.add(edge.get("target")) 91 92 orphan_ids = set(n.get("id") for n in nodes) - connected 93 orphan_rate = len(orphan_ids) / len(nodes) if nodes else 0 94 95 return { 96 "nodes": len(nodes), 97 "edges": len(edges), 98 "orphans": len(orphan_ids), 99 "orphan_rate": orphan_rate 100 } 101 except: 102 pass 103 return {"nodes": 0, "edges": 0, "orphans": 0, "orphan_rate": 0} 104 105 106 def get_fo_insights() -> List[Dict]: 107 """Get today's insights from FO state.""" 108 fo_state = SESSIONS_DIR / "FO-STATE.json" 109 if fo_state.exists(): 110 try: 111 data = json.load(open(fo_state)) 112 insights = data.get("insights", []) 113 114 # Filter to today 115 today = datetime.now().date() 116 today_insights = [] 117 for ins in insights: 118 ts = ins.get("timestamp", "") 119 if ts and ts.startswith(today.isoformat()): 120 today_insights.append(ins) 121 return today_insights 122 except: 123 pass 124 return [] 125 126 127 def generate_synthesis_prompt() -> str: 128 """Generate prompt for Opus synthesis agent.""" 129 130 morning = get_morning_context() 131 graph = get_graph_stats() 132 insights = get_fo_insights() 133 debriefs = get_daily_debriefs() 134 135 prompt = f"""# End of Day Synthesis Request 136 137 ## Your Task 138 139 You are a synthesis agent. Review today's work and: 140 1. Ensure all discoveries connect back to starting context 141 2. Identify simplification opportunities 142 3. Check Torah/Talmud convergence (more instances → sharper essence) 143 4. Surface unfinished threads for tomorrow 144 145 ## Today's Context 146 147 ### Morning State 148 {morning.get('content', 'Not available')[:1000] if morning else 'Not available'} 149 150 ### Graph Status 151 - Nodes: {graph['nodes']} 152 - Edges: {graph['edges']} 153 - Orphans: {graph['orphans']} ({graph['orphan_rate']:.1%} orphan rate) 154 155 ### Today's Insights ({len(insights)} captured) 156 """ 157 158 for ins in insights[:10]: 159 prompt += f"- {ins.get('content', '')[:100]}...\n" 160 161 prompt += f""" 162 163 ### Session Debriefs Found: {len(debriefs)} 164 165 ## Synthesis Questions 166 167 1. **Coherence**: Do today's discoveries connect to what we started with? 168 2. **Orphans**: Can any orphan nodes be connected? 169 3. **Simplification**: Can any new code/concepts merge with existing? 170 4. **Torah/Talmud**: Did we sharpen principles or just add instances? 171 5. **Tomorrow**: What threads should carry forward? 172 173 ## Output Format 174 175 Provide: 176 1. COHERENCE CHECK - How well did today's work connect? 177 2. SIMPLIFICATION OPPORTUNITIES - What can be merged/removed? 178 3. GRAPH HEALTH - Orphan reduction actions 179 4. PRINCIPLE EVOLUTION - Any Torah sharpening? 180 5. TOMORROW'S SEEDS - Key threads to pick up 181 182 Remember: "Simplify as much as possible, but no more." 183 """ 184 185 return prompt 186 187 188 def run_hunting_parties(): 189 """Run hunting parties for graph enrichment.""" 190 print("\n[HUNTING PARTIES] Running graph enrichment...") 191 192 # Run graph enrichment if available 193 enrichment_script = REPO_ROOT / "scripts" / "graph_enrichment.py" 194 if enrichment_script.exists(): 195 output = run_script("scripts/graph_enrichment.py", ["--quick"]) 196 print(output[:500]) 197 else: 198 print(" Graph enrichment script not found - skipping") 199 200 # Run orphan detection 201 feeder_script = REPO_ROOT / "scripts" / "graph_feeder.py" 202 if feeder_script.exists(): 203 output = run_script("scripts/graph_feeder.py", ["--status"]) 204 print(output[:500]) 205 206 207 def run_code_synthesis(): 208 """Run code synthesis analysis.""" 209 print("\n[CODE SYNTHESIS] Analyzing today's code...") 210 output = run_script("scripts/daily_code_synthesis.py", ["--today", "--report"]) 211 print(output) 212 213 214 def run_session_synthesis(): 215 """Generate session synthesis report.""" 216 print("\n[SESSION SYNTHESIS] Generating synthesis...") 217 218 prompt = generate_synthesis_prompt() 219 220 # Save prompt for review 221 synthesis_dir = SESSIONS_DIR / "synthesis" 222 synthesis_dir.mkdir(exist_ok=True) 223 224 prompt_file = synthesis_dir / f"synthesis-prompt-{datetime.now().strftime('%Y-%m-%d')}.md" 225 prompt_file.write_text(prompt) 226 print(f" Synthesis prompt saved: {prompt_file}") 227 print(f" Run this through an Opus agent for full synthesis") 228 229 return prompt 230 231 232 def print_summary(): 233 """Print end-of-day summary.""" 234 graph = get_graph_stats() 235 insights = get_fo_insights() 236 debriefs = get_daily_debriefs() 237 238 print("\n" + "=" * 60) 239 print("END OF DAY SUMMARY") 240 print("=" * 60) 241 print(f""" 242 Graph: {graph['nodes']} nodes, {graph['edges']} edges 243 Orphans: {graph['orphans']} ({graph['orphan_rate']:.1%}) 244 Insights: {len(insights)} captured today 245 Debriefs: {len(debriefs)} session reports 246 247 Torah/Talmud Health: {"Good" if graph['orphan_rate'] < 0.20 else "Needs attention"} 248 """) 249 250 251 def main(): 252 quick = "--quick" in sys.argv 253 graph_only = "--graph" in sys.argv 254 code_only = "--code" in sys.argv 255 256 print("=" * 60) 257 print("END OF DAY SYNTHESIS") 258 print("'Simplify as much as possible, but no more.'") 259 print("=" * 60) 260 261 if quick: 262 print_summary() 263 return 264 265 if graph_only: 266 run_hunting_parties() 267 print_summary() 268 return 269 270 if code_only: 271 run_code_synthesis() 272 print_summary() 273 return 274 275 # Full synthesis 276 print("\nPhase 1: Hunting Parties (Graph Enrichment)") 277 run_hunting_parties() 278 279 print("\nPhase 2: Code Synthesis") 280 run_code_synthesis() 281 282 print("\nPhase 3: Session Synthesis") 283 run_session_synthesis() 284 285 print_summary() 286 287 print("\nNext steps:") 288 print(" 1. Review synthesis prompt in sessions/synthesis/") 289 print(" 2. Run prompt through Opus for full synthesis") 290 print(" 3. Act on simplification opportunities") 291 print(" 4. Update LIVE-COMPRESSION with tomorrow's seeds") 292 293 294 if __name__ == "__main__": 295 main()