#!/usr/bin/env python3 """ rrc_refactor_oracle.py — Chaos-game-driven RRC self-refactoring oracle. Uses the Burgers representation chaos game engine to drive refactoring decisions on the RRC domain manifold graph. Loop per iteration: 1. Read current manifold graph (354 nodes, 33 edges) 2. Build adjacency matrix from graph edges 3. Run BurgersChaosGame quantum walk (eigenvector centrality) 4. Compute centrality deltas from previous iteration 5. Generate refactoring commands: - LOW centrality → PRUNE (dead-end representation) - HIGH centrality delta → PROMOTE (split into sub-specializations) - SIMILAR centrality + strong edge → MERGE (redundant connection) - LOW internal edge density → SPLIT cluster 6. Apply commands → new manifold graph (sacrificial copy) 7. Emit receipt with delta summary 8. Goto 1 """ from __future__ import annotations import argparse import copy import hashlib import json import math import sys import time from collections import defaultdict from datetime import datetime, timezone from pathlib import Path from typing import Any, Optional import numpy as np SHIM = Path(__file__).resolve().parent sys.path.insert(0, str(SHIM)) from burgers_chaos_game import BurgersChaosGame # quantum walk engine PRUNE_CENTRALITY_THRESHOLD = 0.01 # nodes below this get pruned PROMOTE_DELTA_THRESHOLD = 0.05 # centrality delta above this gets promoted MERGE_EDGE_SIMILARITY = 0.15 # centrality diff below this + edge = merge CLUSTER_DENSITY_THRESHOLD = 0.1 # cluster density below this = split target MAX_ITERATIONS = 10 # safety limit MAX_MERGES_PER_ITER = 10 # optimal from SLO sweep (max speedup before community collapse) MINIMUM_EDGE_DENSITY = 0.005 # if graph is sparser, trigger inference fallback GRAPH_BUILDER = SHIM / "rrc_domain_manifold_graph.py" MANIFOLD_ASSIGNMENT = SHIM.parent.parent / "shared-data/data/rrc_manifold_assignment_v1.json" # Greek epigenetic state → PRUNE/MERGE preference # Higher protect_level = less likely to be pruned or merged away GREEK_PROTECT: dict[str, int] = { "Φ": 5, # Stable — never prune, prefer as merge target "Λ": 4, # Attractor — rarely prune "Κ": 3, # Poised — prune only if centrality is extremely low "Ρ": 3, # Regulated — same as Κ "Σ": 2, # Symmetric — merge with caution "Π": 2, # Potential — merge with caution "Ω": 1, # Terminal — prune freely "Ζ": 0, # Boundary — prune first } GREEK_COMPATIBLE: dict[str, list[str]] = { "Φ": ["Λ", "Κ", "Σ"], "Λ": ["Φ", "Ρ", "Π"], "Κ": ["Φ", "Ω", "Ζ"], "Ρ": ["Λ", "Ω", "Π"], "Ω": ["Κ", "Ρ", "Ζ"], "Σ": ["Φ", "Π", "Ζ"], "Π": ["Λ", "Ρ", "Σ"], "Ζ": ["Κ", "Ω", "Σ"], } # Route → keywords for graph node Greek annotation (same as rrc_manifold_assign.py) ROUTE_GREEK_KEYWORDS: list[tuple[str, list[str], str, int, str, str]] = [ ("thermodynamic_energy", [ "energy", "entropy", "heat", "carnot", "landauer", "temperature", "thermodynamic", "thermal", "dissipation", "efficiency", "joule", ], "Φ", 0, "ambidextrous", "forward"), ("geometry_topology", [ "geodesic", "metric", "stereographic", "euclidean", "manifold", "curvature", "riemann", "tensor", "topology", "holonomy", "connection", "bundle", "chart", "topological", "topology", ], "Λ", 45, "left", "forward"), ("cognitive_load", [ "cognitive", "load", "emotional", "signal", "attention", "salience", "novelty", "surprise", "gate", ], "Κ", 135, "left", "forward"), ("compression_route", [ "compress", "hutter", "encoding", "codec", "bit", "rate", "distortion", "redundancy", ], "Σ", 225, "right", "reverse"), ("magnetic_signal", [ "magnetic", "magneto", "field", "wave", "plasma", "flux", "induction", "mhd", "alfven", ], "Π", 270, "right", "reverse"), ("control_signal", [ "control", "gate", "overflow", "gain", "tuning", "cascade", "feedback", "regulator", "threshold", ], "Ρ", 90, "ambidextrous", "forward"), ("chaotic_couch", [ "chaotic", "couch", "soliton", "turbulence", "vortex", "strange", "attractor", "lyapunov", ], "Ω", 180, "ambidextrous", "reverse"), ("number_theory", [ "prime", "modulo", "congruence", "diophantine", "integer", "arithmetic", "logarithm", "lower_bound", "bound", "number", "pell", "exponential", "s-unit", "goormaghtigh", ], "Ζ", 315, "right", "reverse"), ] # ========================================================================= def load_manifold_graph(path: Path) -> dict: """Load a domain_manifold_graph_v1 JSON.""" return json.loads(path.read_text()) def load_greek_assignment(path: Path | None = None) -> dict[str, dict]: """Load Greek epigenetic states from manifold assignment, keyed by equation name.""" if path is None: path = MANIFOLD_ASSIGNMENT if not path.exists(): print(f" Greek assignment not found at {path}, skipping enrichment", file=sys.stderr) return {} data = json.loads(path.read_text()) greek_map: dict[str, dict] = {} for eq in data.get("equations", []): name = eq.get("name", "") greek_map[name] = { "greek": eq.get("greek_state", "Ζ"), "phase": eq.get("greek_phase", 315), "chirality": eq.get("greek_chirality", "right"), "direction": eq.get("greek_direction", "reverse"), "regime": eq.get("regime", ""), "route": eq.get("route", ""), } print(f" Loaded {len(greek_map)} Greek states from assignment", file=sys.stderr) return greek_map def enrich_graph_by_keywords(graph: dict) -> dict: """Annotate manifold graph nodes with Greek epigenetic state by keyword matching. Uses the same route keyword patterns as rrc_manifold_assign.py but applied at the graph-node level (domain category labels vs individual equation names). Returns the graph with Greek state, phase, chirality, direction added to each node. """ for node in graph.get("nodes", []): label = (node.get("label", "") + " " + node.get("id", "")).lower() best_route = None best_score = 0 best_greek = "Ζ" best_phase = 315 best_chirality = "right" best_direction = "reverse" for route, keywords, greek, phase, chirality, direction in ROUTE_GREEK_KEYWORDS: score = sum(1 for kw in keywords if kw.lower() in label) if score > best_score: best_score = score best_route = route best_greek = greek best_phase = phase best_chirality = chirality best_direction = direction node["greek_state"] = best_greek node["greek_route"] = best_route or "" node["greek_phase"] = best_phase node["greek_chirality"] = best_chirality node["greek_direction"] = best_direction node["greek_match_score"] = best_score return graph def enrich_graph_with_greek(graph: dict, greek_map: dict[str, dict]) -> dict: """Annotate manifold graph nodes with Greek epigenetic state. Two-phase strategy: 1. Try exact name/id match against the assignment equations (greek_map). 2. Fall back to keyword matching on graph node label + id. """ for node in graph.get("nodes", []): label = node.get("label", "") nid = node.get("id", "") matched = greek_map.get(label) or greek_map.get(nid) if matched is None: for eq_name, gs in greek_map.items(): if eq_name.lower() in label.lower() or label.lower() in eq_name.lower(): matched = gs break if matched: node["greek_state"] = matched["greek"] node["greek_phase"] = matched["phase"] node["greek_chirality"] = matched["chirality"] node["greek_direction"] = matched["direction"] node["greek_match_score"] = 10 continue # Fallback: keyword matching at route level label_lower = (label + " " + nid).lower() best_route = None best_score = 0 best_greek = "Ζ" best_phase = 315 best_chirality = "right" best_direction = "reverse" for route, keywords, greek, phase, chirality, direction in ROUTE_GREEK_KEYWORDS: score = sum(1 for kw in keywords if kw.lower() in label_lower) if score > best_score: best_score = score best_route = route best_greek = greek best_phase = phase best_chirality = chirality best_direction = direction node["greek_state"] = best_greek node["greek_route"] = best_route or "" node["greek_phase"] = best_phase node["greek_chirality"] = best_chirality node["greek_direction"] = best_direction node["greek_match_score"] = best_score return graph def greek_spectrum(graph: dict) -> dict: """Compute Greek epigenetic state distribution across graph nodes.""" counts = defaultdict(int) phase_counts = defaultdict(int) chirality_counts = defaultdict(int) direction_counts = defaultdict(int) route_counts = defaultdict(int) score_buckets = {"high": 0, "medium": 0, "low": 0, "none": 0} for node in graph.get("nodes", []): gs = node.get("greek_state", "Ζ") counts[gs] += 1 phase_counts[node.get("greek_phase", 315)] += 1 chirality_counts[node.get("greek_chirality", "right")] += 1 direction_counts[node.get("greek_direction", "reverse")] += 1 route_counts[node.get("greek_route", "")] += 1 score = node.get("greek_match_score", 0) if score >= 3: score_buckets["high"] += 1 elif score >= 1: score_buckets["medium"] += 1 elif score > 0: score_buckets["low"] += 1 else: score_buckets["none"] += 1 return { "by_greek": dict(counts), "by_phase": dict(phase_counts), "by_chirality": dict(chirality_counts), "by_direction": dict(direction_counts), "by_route": dict(route_counts), "match_quality": score_buckets, } def infer_edges_from_metadata(graph: dict) -> list[dict]: """Build edges from intrinsic node metadata without external access. Covers all edge types that don't require live arXiv queries: - kernel_internal: nodes sharing the same kernel - kernel_hub: cross-kernel hub connections - dimension_chain: adjacency along dimension axis - shared_paper: shared paper IDs in node metadata (unverified) - topic_overlap: token overlap in node labels """ nodes = graph.get("nodes", []) edges = graph.get("edges", []) existing_pairs = set() for e in edges: existing_pairs.add(tuple(sorted([e["source"], e["target"]]))) new_edges: list[dict] = [] added: set = set(existing_pairs) def add(src: str, tgt: str, etype: str, **kw): pair = tuple(sorted([src, tgt])) if pair not in added: added.add(pair) new_edges.append({"source": src, "target": tgt, "type": etype, **kw}) # Group nodes by kernel kernel_nodes: dict[str, list[dict]] = defaultdict(list) for n in nodes: kernel_nodes[n.get("kernel", "other")].append(n) node_map = {n["id"]: n for n in nodes} # Edge type 1: kernel_internal — 15% random within same kernel import random rng = random.Random(42) for kernel, members in kernel_nodes.items(): if len(members) < 2: continue for i in range(len(members)): for j in range(i + 1, len(members)): if rng.random() < 0.15: add(members[i]["id"], members[j]["id"], "kernel_internal", kernel=kernel, dimension=members[i].get("dimension")) # Edge type 2: kernel_hub — connect hubs (highest-degree node) across kernels hubs: dict[str, str] = {} for kernel, members in kernel_nodes.items(): hubs[kernel] = members[len(members) // 2]["id"] # deterministic hub kernel_names = list(kernel_nodes.keys()) for i in range(len(kernel_names)): for j in range(i + 1, len(kernel_names)): add(hubs[kernel_names[i]], hubs[kernel_names[j]], "kernel_hub", from_kernel=kernel_names[i], to_kernel=kernel_names[j]) # Edge type 3: dimension_chain — adjacent dimensions dim_groups: dict[int, list[dict]] = defaultdict(list) for n in nodes: dim_groups[n.get("dimension", -1)].append(n) for dim in sorted(dim_groups): if dim + 1 in dim_groups: a = dim_groups[dim][0] b = dim_groups[dim + 1][0] add(a["id"], b["id"], "dimension_chain", from_dim=dim, to_dim=dim + 1) # Edge type 4: shared_paper — unverified, from node metadata paper_nodes: dict[str, list[str]] = defaultdict(list) for n in nodes: for pid in n.get("papers", []): paper_nodes[pid].append(n["id"]) for pid, nids in paper_nodes.items(): for i in range(len(nids)): for j in range(i + 1, len(nids)): add(nids[i], nids[j], "shared_paper", paper_id=pid, verified=False) # Edge type 5: topic_overlap — label token overlap for i in range(len(nodes)): ni = nodes[i] ni_tokens = set(ni.get("label", "").lower().split()) for j in range(i + 1, len(nodes)): nj = nodes[j] overlap = ni_tokens & set(nj.get("label", "").lower().split()) if len(overlap) >= 2: add(ni["id"], nj["id"], "topic_overlap", overlap_count=len(overlap), shared_terms=list(overlap)[:5]) return new_edges def build_or_load_graph(path: Path, skip_live: bool = False) -> tuple[dict, str]: """Load graph, ensuring minimum edge density. Strategy: 1. Load graph from file 2. If density ≥ threshold: return as-is (origin: file) 3. If density < threshold and not skip_live: try live rebuild 4. If live rebuild fails or skip_live: apply intrinsic inference Returns (graph, origin_string) where origin_string is one of: "file" — loaded as-is, sufficient edges "live" — rebuilt via external graph builder "inferred" — fallback: edges built from node metadata """ graph = load_manifold_graph(path) nodes = graph.get("nodes", []) edges = graph.get("edges", []) n = len(nodes) density = (2 * len(edges)) / max(n * (n - 1), 1) if density >= MINIMUM_EDGE_DENSITY: return graph, "file" print(f" Graph density {density:.6f} < threshold {MINIMUM_EDGE_DENSITY}", file=sys.stderr) # Try live rebuild origin = "file" if not skip_live and GRAPH_BUILDER.exists(): try: print(f" Attempting live rebuild via {GRAPH_BUILDER.name}...", file=sys.stderr) import subprocess r = subprocess.run( [sys.executable, str(GRAPH_BUILDER)], capture_output=True, text=True, timeout=120, ) if r.returncode == 0 and path.exists(): graph = load_manifold_graph(path) edges = graph.get("edges", []) density = (2 * len(edges)) / max(n * (n - 1), 1) if density >= MINIMUM_EDGE_DENSITY: print(f" Live rebuild succeeded: {len(edges)} edges", file=sys.stderr) return graph, "live" else: print(f" Live rebuild produced {len(edges)} edges " f"(density {density:.6f}), still too sparse", file=sys.stderr) else: print(f" Live rebuild failed (rc={r.returncode}): " f"{r.stderr.strip()[-200:]}", file=sys.stderr) except (subprocess.TimeoutExpired, FileNotFoundError, OSError) as e: print(f" Live rebuild exception: {e}", file=sys.stderr) # Fallback: intrinsic inference print(f" Falling back to intrinsic edge inference from metadata...", file=sys.stderr) new_edges = infer_edges_from_metadata(graph) graph["edges"] = graph.get("edges", []) + new_edges graph["stats"] = { "total_nodes": len(nodes), "total_edges": len(graph["edges"]), "by_type": {t: sum(1 for e in graph["edges"] if e["type"] == t) for t in set(e["type"] for e in graph["edges"])}, "inferred": True, "inferred_edge_count": len(new_edges), } density = (2 * len(graph["edges"])) / max(len(nodes) * (len(nodes) - 1), 1) print(f" Inference produced {len(new_edges)} new edges, " f"density now {density:.6f}", file=sys.stderr) return graph, "inferred" def graph_to_adjacency(graph: dict) -> tuple[np.ndarray, list[str]]: """Convert domain manifold graph to adjacency matrix + node labels. Nodes = unique node IDs from the graph. Edges from the edge list. Returns (N×N adjacency, [node_id_0, ..., node_id_{N-1}]). """ nodes = graph.get("nodes", []) edges = graph.get("edges", []) node_ids = [n["id"] for n in nodes] id_to_idx = {nid: i for i, nid in enumerate(node_ids)} N = len(node_ids) A = np.zeros((N, N), dtype=np.float64) for e in edges: src = e.get("source", "") tgt = e.get("target", "") if src in id_to_idx and tgt in id_to_idx: i, j = id_to_idx[src], id_to_idx[tgt] A[i, j] = A[j, i] = 1.0 return A, node_ids def graph_stats(graph: dict) -> dict: """Compute structural statistics of the manifold graph.""" nodes = graph.get("nodes", []) edges = graph.get("edges", []) # Count by kernel/dimension kernel_counts: dict[str, int] = defaultdict(int) dim_counts: dict[int, int] = defaultdict(int) for n in nodes: kernel_counts[n.get("kernel", "unknown")] += 1 dim_counts[n.get("dimension", -1)] += 1 edge_types: dict[str, int] = defaultdict(int) for e in edges: edge_types[e.get("type", "unknown")] += 1 return { "num_nodes": len(nodes), "num_edges": len(edges), "density": (2 * len(edges)) / max(len(nodes) * (len(nodes) - 1), 1), "kernel_counts": dict(kernel_counts), "dimension_counts": dict(dim_counts), "edge_type_counts": dict(edge_types), } # ========================================================================= # II. Refactoring Command Generator # ========================================================================= def generate_refactoring_commands( graph: dict, centrality: np.ndarray, node_ids: list[str], prev_centrality: Optional[dict[str, float]] = None, *, greek_map: Optional[dict[str, dict]] = None, prune_threshold: float = PRUNE_CENTRALITY_THRESHOLD, promote_threshold: float = PROMOTE_DELTA_THRESHOLD, merge_similarity: float = MERGE_EDGE_SIMILARITY, max_merges: int = MAX_MERGES_PER_ITER, ) -> list[dict]: """Generate refactoring commands from centrality analysis. When greek_map is provided, PRUNE/MERGE decisions are modulated by Greek epigenetic state: stable states (Φ, Λ) are protected from pruning; incompatible Greek states are deprioritized for merges. Returns list of command dicts: { "action": "prune"|"promote"|"merge"|"split", "reason": str, "nodes": [str, ...], "detail": Any } """ commands: list[dict] = [] nodes_list = graph.get("nodes", []) node_lookup = {n["id"]: n for n in nodes_list} # Build centrality map keyed by node ID for ID-based delta cent_map: dict[str, float] = dict(zip(node_ids, map(float, centrality))) prev_map: dict[str, float] = prev_centrality or {} # --- PRUNE: nodes with very low centrality, modulated by Greek state --- for i, nid in enumerate(node_ids): node = node_lookup.get(nid, {}) gs = (greek_map or {}).get(nid, {}).get("greek") or node.get("greek_state", "Ζ") protect = GREEK_PROTECT.get(gs, 0) # Scale threshold: protected states need much lower centrality to be pruned effective_threshold = prune_threshold * (1.0 / (1.0 + protect * 2)) if centrality[i] < effective_threshold: commands.append({ "action": "prune", "reason": ( f"centrality {centrality[i]:.4f} < effective threshold " f"{effective_threshold:.4f} (greek={gs}, protect={protect})" ), "nodes": [nid], "detail": { "label": node.get("label", nid), "kernel": node.get("kernel", ""), "centrality": float(centrality[i]), "greek_state": gs, "protect_level": protect, }, }) # --- PROMOTE: nodes with rising centrality that are potential hubs --- if prev_map: for nid, cent in cent_map.items(): prev = prev_map.get(nid) if prev is not None: delta = cent - prev if delta > promote_threshold: node = node_lookup.get(nid, {}) commands.append({ "action": "promote", "reason": f"centrality delta {delta:.4f} > threshold {promote_threshold}", "nodes": [nid], "detail": { "label": node.get("label", nid), "kernel": node.get("kernel", ""), "centrality": cent, "delta": round(delta, 6), }, }) # --- MERGE: pairs with edge + similar centrality, modulated by Greek compatibility --- adj, _ = graph_to_adjacency(graph) merge_candidates: list[tuple[float, int, int]] = [] for i in range(len(node_ids)): for j in range(i + 1, len(node_ids)): if adj[i, j] > 0: diff = abs(centrality[i] - centrality[j]) if diff < merge_similarity: priority = centrality[i] * centrality[j] # Boost priority for compatible Greek states if greek_map is not None: ni = node_lookup.get(node_ids[i], {}) nj = node_lookup.get(node_ids[j], {}) gs_i = (greek_map.get(node_ids[i], {}).get("greek") or ni.get("greek_state", "Ζ")) gs_j = (greek_map.get(node_ids[j], {}).get("greek") or nj.get("greek_state", "Ζ")) if gs_i in GREEK_COMPATIBLE.get(gs_j, []): priority *= 1.5 # boost compatible merges elif gs_i == gs_j: priority *= 1.3 # same-state merges are safe else: priority *= 0.5 # incompatible states penalized merge_candidates.append((priority, i, j)) # Rank by boosted centrality product and cap merge_candidates.sort(reverse=True, key=lambda x: x[0]) for priority, i, j in merge_candidates[:max_merges]: ni = node_lookup.get(node_ids[i], {}) nj = node_lookup.get(node_ids[j], {}) gs_i = ni.get("greek_state", "Ζ") gs_j = nj.get("greek_state", "Ζ") commands.append({ "action": "merge", "reason": ( f"centrality prod {priority:.6f}, diff " f"{abs(centrality[i] - centrality[j]):.4f}, " f"greek={gs_i}×{gs_j}" ), "nodes": [node_ids[i], node_ids[j]], "detail": { "labels": [ni.get("label", node_ids[i]), nj.get("label", node_ids[j])], "centralities": [float(centrality[i]), float(centrality[j])], "greek_states": [gs_i, gs_j], "compatible": gs_i in GREEK_COMPATIBLE.get(gs_j, []), }, }) return commands # ========================================================================= # III. Refactoring Engine # ========================================================================= def apply_refactoring( graph: dict, commands: list[dict], dry_run: bool = True, ) -> dict: """Apply refactoring commands to produce a new graph. In dry_run mode, only reports what would change. In live mode, actually modifies the graph. Returns the (possibly modified) graph and operation log. """ if dry_run: return graph, commands # just report new_graph = copy.deepcopy(graph) nodes = new_graph.get("nodes", []) edges = new_graph.get("edges", []) removed_ids: set[str] = set() operation_log: list[dict] = [] for cmd in commands: action = cmd["action"] if action == "prune": for nid in cmd["nodes"]: # Remove from node list nodes[:] = [n for n in nodes if n["id"] != nid] removed_ids.add(nid) operation_log.append({ "action": "pruned", "node_id": nid, "reason": cmd["reason"], }) # Remove edges incident to pruned nodes edges[:] = [ e for e in edges if e["source"] not in removed_ids and e["target"] not in removed_ids ] elif action == "merge": # Keep the first node, remove the second keep_id, remove_id = cmd["nodes"] nodes[:] = [n for n in nodes if n["id"] != remove_id] removed_ids.add(remove_id) operation_log.append({ "action": "merged", "kept": keep_id, "removed": remove_id, "reason": cmd["reason"], }) # Reroute edges from removed to kept for e in edges: if e["source"] == remove_id: e["source"] = keep_id if e["target"] == remove_id: e["target"] = keep_id # Remove self-loops from reroute edges[:] = [e for e in edges if e["source"] != e["target"]] elif action == "promote": for nid in cmd["nodes"]: # Find the node node = next((n for n in nodes if n["id"] == nid), None) if node: # Add a specialization suffix new_id = f"{nid}__special" new_node = copy.deepcopy(node) new_node["id"] = new_id new_node["label"] = node.get("label", "") + " (specialized)" new_node["dimension"] = min(5, node.get("dimension", 0) + 1) nodes.append(new_node) operation_log.append({ "action": "promoted", "original": nid, "created": new_id, "reason": cmd["reason"], }) # Connect the new node back to the original edges.append({ "source": nid, "target": new_id, "type": "specialization", "promoted": True, }) elif action == "split": for nid in cmd["nodes"]: node = next((n for n in nodes if n["id"] == nid), None) if node: split_a = f"{nid}__a" split_b = f"{nid}__b" for new_id in (split_a, split_b): new_node = copy.deepcopy(node) new_node["id"] = new_id new_node["label"] = node.get("label", "") + ( " (A)" if new_id.endswith("__a") else " (B)" ) nodes.append(new_node) removed_ids.add(nid) nodes[:] = [n for n in nodes if n["id"] != nid] operation_log.append({ "action": "split", "original": nid, "created": [split_a, split_b], "reason": cmd["reason"], }) # Regenerate stats new_edges = [e for e in edges if e["source"] not in removed_ids and e["target"] not in removed_ids] deduped = [] seen_pairs = set() for e in new_edges: pair = tuple(sorted([e["source"], e["target"]])) if pair not in seen_pairs: seen_pairs.add(pair) deduped.append(e) new_graph["edges"] = deduped new_graph["stats"] = graph_stats(new_graph) return new_graph, operation_log # ========================================================================= # IV. Main Loop # ========================================================================= def run_refactor_loop( graph: dict, max_iterations: int = MAX_ITERATIONS, dry_run: bool = True, *, greek_map: Optional[dict[str, dict]] = None, prune_threshold: float = PRUNE_CENTRALITY_THRESHOLD, promote_threshold: float = PROMOTE_DELTA_THRESHOLD, merge_similarity: float = MERGE_EDGE_SIMILARITY, max_merges: int = MAX_MERGES_PER_ITER, origin: str = "file", ) -> dict: """Run the chaos-game-driven refactoring loop. Each iteration: 1. Build adjacency from current graph 2. Compute centrality via BurgersChaosGame 3. Compare with previous centrality 4. Generate commands 5. Apply commands 6. Check convergence: if no commands generated, stop Returns full history as a receipt dict. """ iteration_history: list[dict] = [] current_graph = copy.deepcopy(graph) prev_cent_map: dict[str, float] = {} for iteration in range(max_iterations): t0 = time.time() # 1. Build adjacency A, node_ids = graph_to_adjacency(current_graph) n_nodes = A.shape[0] if n_nodes == 0: iteration_history.append({ "iteration": iteration, "status": "empty_graph", "runtime_s": round(time.time() - t0, 4), }) break # 2. Quantum walk centrality game = BurgersChaosGame(A, node_ids) centrality = game.eigenvector_centrality() # Top 5 by centrality ranked = game.rank_nodes(centrality) top_5 = [(n, round(s, 6)) for n, s in ranked[:5]] # 3. Generate commands commands = generate_refactoring_commands( current_graph, centrality, node_ids, prev_cent_map, greek_map=greek_map, prune_threshold=prune_threshold, promote_threshold=promote_threshold, merge_similarity=merge_similarity, max_merges=max_merges, ) n_prune = sum(1 for c in commands if c["action"] == "prune") n_promote = sum(1 for c in commands if c["action"] == "promote") n_merge = sum(1 for c in commands if c["action"] == "merge") n_split = sum(1 for c in commands if c["action"] == "split") iter_record = { "iteration": iteration, "runtime_s": round(time.time() - t0, 4), "node_count": n_nodes, "edge_count": len(current_graph.get("edges", [])), "top_5_centrality": top_5, "top_node": top_5[0] if top_5 else None, "commands_generated": len(commands), "command_breakdown": { "prune": n_prune, "promote": n_promote, "merge": n_merge, "split": n_split, }, "preview_commands": [ { "action": c["action"], "nodes_preview": c["nodes"][:3], "reason": c["reason"][:120], } for c in commands[:10] # first 10 for readability ], } iteration_history.append(iter_record) # 4. Apply (or preview) if not dry_run and commands: new_graph, op_log = apply_refactoring( current_graph, commands, dry_run=False, ) current_graph = new_graph iter_record["applied"] = len(op_log) if op_log else 0 # 5. Save current centrality for next iteration's delta prev_cent_map = dict(zip(node_ids, map(float, centrality))) # 6. Convergence if not commands: break return { "schema": "rrc_refactor_oracle_v1", "claim_boundary": ( "chaos-game-quantum-walk-refactoring-oracle;" "greek-epigenetic-enrichment" ), "sacrificial_graph_source": "domain_manifold_graph_v1.json", "graph_origin": origin, "greek_spectrum": greek_spectrum(current_graph), "parameters": { "prune_centrality_threshold": PRUNE_CENTRALITY_THRESHOLD, "promote_delta_threshold": PROMOTE_DELTA_THRESHOLD, "merge_edge_similarity": MERGE_EDGE_SIMILARITY, "max_iterations": max_iterations, "max_merges_per_iter": max_merges, "dry_run": dry_run, }, "initial_stats": graph_stats(graph), "iteration_history": iteration_history, "final_stats": graph_stats(current_graph), "summary": { "total_iterations": len(iteration_history), "total_commands": sum( h["commands_generated"] for h in iteration_history ) if iteration_history else 0, "converged": not iteration_history[-1]["commands_generated"] if iteration_history else False, "top_node_final": iteration_history[-1]["top_node"] if iteration_history else None, }, "final_graph": current_graph, "computed_at": datetime.now(timezone.utc).isoformat(), } def main() -> int: parser = argparse.ArgumentParser( description="RRC Chaos-Game Refactoring Oracle" ) parser.add_argument( "--graph", "-g", default="/tmp/rrc_sacrificial_manifold_v1.json", help="Path to manifold graph JSON (default: sacrificial copy)", ) parser.add_argument( "--max-iterations", type=int, default=MAX_ITERATIONS, ) parser.add_argument( "--max-merges", type=int, default=MAX_MERGES_PER_ITER, help="Max merges per iteration (default: %(default)s)", ) parser.add_argument( "--apply", action="store_true", help="Actually apply refactoring (default: dry-run preview)", ) parser.add_argument( "--output", "-o", default=None, help="Output receipt path", ) parser.add_argument( "--threshold-prune", type=float, default=PRUNE_CENTRALITY_THRESHOLD, ) parser.add_argument( "--threshold-promote", type=float, default=PROMOTE_DELTA_THRESHOLD, ) parser.add_argument( "--threshold-merge", type=float, default=MERGE_EDGE_SIMILARITY, ) parser.add_argument( "--no-live", action="store_true", help="Skip live arxiv rebuild; force intrinsic fallback", ) parser.add_argument( "--save-graph", default=None, help="Save final modified graph to this path (auto: input path if --apply)", ) parser.add_argument( "--greek-assignment", default=None, help="Path to manifold assignment JSON with Greek states (default: shared-data auto-detect)", ) args = parser.parse_args() graph_path = Path(args.graph) if not graph_path.exists(): print(f"ERROR: graph not found at {graph_path}", file=sys.stderr) print("Run: cp /shared-data/data/domain_manifold_graph_v1.json " "/tmp/rrc_sacrificial_manifold_v1.json", file=sys.stderr) return 1 graph, origin = build_or_load_graph(graph_path, skip_live=args.no_live) # Load Greek epigenetic states and enrich graph nodes greek_path = Path(args.greek_assignment) if args.greek_assignment else None greek_map = load_greek_assignment(greek_path) if greek_map: graph = enrich_graph_with_greek(graph, greek_map) n_enriched = sum(1 for n in graph.get("nodes", []) if n.get("greek_match_score", 0) >= 5) else: # Keyword-only enrichment when no assignment file is available graph = enrich_graph_by_keywords(graph) n_enriched = sum(1 for n in graph.get("nodes", []) if n.get("greek_match_score", 0) >= 1) greek_spec = greek_spectrum(graph) n_high = greek_spec["match_quality"]["high"] n_med = greek_spec["match_quality"]["medium"] n_low = greek_spec["match_quality"]["low"] n_none = greek_spec["match_quality"]["none"] print(f" Greek enrichment: {n_enriched}/{len(graph.get('nodes', []))} " f"nodes annotated (high={n_high}, med={n_med}, low={n_low}, none={n_none})", file=sys.stderr) print(f" Greek spectrum: {dict(greek_spec['by_greek'])}", file=sys.stderr) stats = graph_stats(graph) print(f"RRC Refactoring Oracle — on sacrificial copy") print(f" Origin: {origin}") print(f" Initial: {stats['num_nodes']} nodes, {stats['num_edges']} edges, " f"density {stats['density']:.6f}") print(f" Dry run: {not args.apply}") print(f" Max iterations: {args.max_iterations}") print(f" Max merges/iter: {args.max_merges}") print(f" Thresholds: prune={args.threshold_prune}, " f"promote={args.threshold_promote}, " f"merge={args.threshold_merge}") if origin == "inferred": print(f" Inferred edge count: " f"{stats.get('edge_type_counts', {}).get('kernel_internal', 0)} " f"kernel_internal, " f"{stats.get('edge_type_counts', {}).get('shared_paper', 0)} " f"shared_paper, " f"{stats.get('edge_type_counts', {}).get('kernel_hub', 0)} " f"kernel_hub, " f"{stats.get('edge_type_counts', {}).get('dimension_chain', 0)} " f"dimension_chain, " f"{stats.get('edge_type_counts', {}).get('topic_overlap', 0)} " f"topic_overlap") print() result = run_refactor_loop( graph, max_iterations=args.max_iterations, dry_run=not args.apply, greek_map=greek_map, prune_threshold=args.threshold_prune, promote_threshold=args.threshold_promote, merge_similarity=args.threshold_merge, max_merges=args.max_merges, origin=origin, ) # Print results summary = result["summary"] initial = result["initial_stats"] final = result["final_stats"] print(f"Refactoring Complete — {summary['total_iterations']} iterations") print(f" Commands generated: {summary['total_commands']}") print(f" Converged: {summary['converged']}") print(f" Nodes: {initial['num_nodes']} → {final['num_nodes']}") print(f" Edges: {initial['num_edges']} → {final['num_edges']}") for h in result["iteration_history"]: cmds = h["command_breakdown"] top = h["top_node"] print( f" Iter {h['iteration']}: " f"{h['node_count']} nodes, " f"top={top[0] if top else '?'} ({top[1] if top else '?'}), " f"commands: P{cmds['prune']}+M{cmds['merge']}" f"+R{cmds['promote']}+S{cmds['split']}" f" ({h['commands_generated']} total)" ) # Save final graph if requested if args.apply and args.save_graph is None: args.save_graph = str(graph_path) # overwrite in-place by default if args.save_graph and result.get("final_graph"): save_path = Path(args.save_graph) final_graph = result["final_graph"] final_graph["stats"] = final_graph_stats = graph_stats(final_graph) save_path.write_text(json.dumps(final_graph, indent=2, default=str)) print(f" Saved refactored graph to {save_path}") # Update summary with actual final graph stats result["final_stats"] = final_graph_stats # Emit receipt if args.output: output_path = Path(args.output) else: output_path = SHIM / "rrc_refactor_oracle_receipt.json" receipt = {k: v for k, v in result.items() if k != "final_graph"} canonical = json.dumps(receipt, sort_keys=True, separators=(",", ":")) receipt["receipt_sha256"] = hashlib.sha256(canonical.encode()).hexdigest() output_path.write_text(json.dumps(receipt, indent=2, default=str)) print(f"\nReceipt: {output_path}") print(f"SHA256: {receipt['receipt_sha256']}") return 0 if __name__ == "__main__": sys.exit(main())