mirror of
https://github.com/allaunthefox/Research-Stack.git
synced 2026-07-31 03:05:21 +00:00
741 lines
31 KiB
Python
Executable file
741 lines
31 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
"""
|
|
PIST Neuromorphic Orchestrator
|
|
==============================
|
|
The orchestrator is not a script. It is a topology.
|
|
|
|
Every action (prover call, build, module load, reboot) is a coordinate
|
|
transition on a manifold. The orchestrator learns which paths succeed,
|
|
strengthens them, and prunes dead branches.
|
|
|
|
Modes:
|
|
observe — passively watch system state, build DAG, no action
|
|
suggest — recommend next action based on learned topology
|
|
execute — perform action, observe result, update DAG
|
|
|
|
Architecture:
|
|
Neurons = task types (build, prove, load, reboot, benchmark)
|
|
Synapses = transitions between tasks (build→prove, prove→load)
|
|
Weights = success rate of each transition
|
|
Plasticity= LTP/LTD based on observed outcomes
|
|
|
|
The orchestrator feeds its own byte stream into pist_neuromorphic.ko
|
|
so the kernel observer learns the orchestration pattern as part of
|
|
the system topology.
|
|
"""
|
|
|
|
import sys
|
|
import os
|
|
import json
|
|
import time
|
|
import hashlib
|
|
import subprocess
|
|
import random
|
|
import glob
|
|
import shutil
|
|
from pathlib import Path
|
|
from dataclasses import dataclass, field, asdict
|
|
from typing import Optional, List, Dict, Callable
|
|
from datetime import datetime
|
|
|
|
# ──────────────────────────────────────────────────────────────────────────
|
|
# PIST Geometry (mirrors kernel module logic in userspace)
|
|
# ──────────────────────────────────────────────────────────────────────────
|
|
|
|
def pist_encode_u8(n: int) -> int:
|
|
"""n = k² + t, return packed 32-bit coordinate."""
|
|
k = int(n ** 0.5)
|
|
t = n - k * k
|
|
return (k << 16) | t
|
|
|
|
def pist_mirror(coord: int) -> int:
|
|
"""Involution: (k, t) → (k, 2k+1-t)"""
|
|
k = (coord >> 16) & 0xFFFF
|
|
t = coord & 0xFFFF
|
|
return (k << 16) | (2 * k + 1 - t)
|
|
|
|
def pist_mass(coord: int) -> int:
|
|
"""t * (2k + 1 - t)"""
|
|
k = (coord >> 16) & 0xFFFF
|
|
t = coord & 0xFFFF
|
|
return t * (2 * k + 1 - t)
|
|
|
|
def pist_tension(coord: int) -> float:
|
|
"""Normalized tension ∈ [0, 1)."""
|
|
k = (coord >> 16) & 0xFFFF
|
|
t = coord & 0xFFFF
|
|
denom = 2 * k + 1
|
|
return t / denom if denom > 0 else 0.0
|
|
|
|
# ──────────────────────────────────────────────────────────────────────────
|
|
# Neuromorphic DAG Node (mirrors kernel struct pist_dag_node)
|
|
# ──────────────────────────────────────────────────────────────────────────
|
|
|
|
@dataclass
|
|
class Synapse:
|
|
target: str # neuron ID
|
|
weight: float = 1.0 # Hebbian weight
|
|
success_count: int = 0
|
|
failure_count: int = 0
|
|
last_seen: float = field(default_factory=time.time)
|
|
|
|
@property
|
|
def success_rate(self) -> float:
|
|
total = self.success_count + self.failure_count
|
|
return self.success_count / total if total > 0 else 0.5
|
|
|
|
def potentiate(self, delta: float = 0.1):
|
|
"""LTP — strengthen synapse on success."""
|
|
self.weight = min(self.weight * (1 + delta), 100.0)
|
|
self.success_count += 1
|
|
self.last_seen = time.time()
|
|
|
|
def depress(self, delta: float = 0.2):
|
|
"""LTD — weaken synapse on failure."""
|
|
self.weight = max(self.weight * (1 - delta), 0.01)
|
|
self.failure_count += 1
|
|
self.last_seen = time.time()
|
|
|
|
@dataclass
|
|
class Neuron:
|
|
nid: str # neuron ID
|
|
task_type: str # build, prove, load, reboot, benchmark, etc.
|
|
coord: int = 0 # PIST coordinate of this neuron
|
|
activation: float = 0.0 # current activation level [0, 1]
|
|
visit_count: int = 0
|
|
total_mass: int = 0
|
|
synapses: List[Synapse] = field(default_factory=list)
|
|
|
|
def __post_init__(self):
|
|
if self.coord == 0:
|
|
# Derive coordinate from hash of neuron ID
|
|
h = hashlib.sha256(self.nid.encode()).digest()
|
|
self.coord = pist_encode_u8(h[0])
|
|
|
|
def activate(self, stimulus: float = 1.0):
|
|
"""Fire neuron — increase activation, update mass."""
|
|
self.activation = min(self.activation + stimulus, 1.0)
|
|
self.visit_count += 1
|
|
self.total_mass += pist_mass(self.coord)
|
|
|
|
def decay(self, rate: float = 0.01):
|
|
"""Exponential decay of activation."""
|
|
self.activation *= (1 - rate)
|
|
|
|
def get_synapse(self, target: str) -> Synapse:
|
|
"""Find or create synapse to target."""
|
|
for s in self.synapses:
|
|
if s.target == target:
|
|
return s
|
|
s = Synapse(target=target)
|
|
self.synapses.append(s)
|
|
return s
|
|
|
|
def choose_next(self, temperature: float = 1.0) -> Optional[str]:
|
|
"""Softmax selection of next neuron based on synapse weights."""
|
|
if not self.synapses:
|
|
return None
|
|
weights = [s.weight * s.success_rate for s in self.synapses]
|
|
# Boltzmann distribution
|
|
exp_w = [w ** (1 / temperature) for w in weights]
|
|
total = sum(exp_w)
|
|
probs = [e / total for e in exp_w]
|
|
# Roulette wheel selection
|
|
r = random.random()
|
|
cumsum = 0.0
|
|
for syn, p in zip(self.synapses, probs):
|
|
cumsum += p
|
|
if r <= cumsum:
|
|
return syn.target
|
|
return self.synapses[-1].target
|
|
|
|
# ──────────────────────────────────────────────────────────────────────────
|
|
# Neuromorphic Orchestrator State
|
|
# ──────────────────────────────────────────────────────────────────────────
|
|
|
|
class NeuromorphicOrchestrator:
|
|
def __init__(self, state_file: Optional[str] = None):
|
|
self.neurons: Dict[str, Neuron] = {}
|
|
self.current_neuron: Optional[str] = None
|
|
self.execution_log: List[dict] = []
|
|
self.dag_generation: int = 0
|
|
self.state_file = state_file or self._default_state_path()
|
|
self.mode: str = "observe" # observe | suggest | execute
|
|
self._init_default_neurons()
|
|
self._load_state()
|
|
|
|
def _default_state_path(self) -> str:
|
|
base = Path.home() / "CascadeProjects" / "Research-Stack"
|
|
return str(base / ".windsurf" / "telemetry" / "orchestrator_state.json")
|
|
|
|
def _init_default_neurons(self):
|
|
"""Bootstrap the default task topology."""
|
|
tasks = [
|
|
"idle", "diagnose", "build", "prove", "load_module",
|
|
"reboot", "benchmark", "export_dag", "collect_data",
|
|
"fix_toolchain", "ghost_ingested", "compress_baseline"
|
|
]
|
|
for t in tasks:
|
|
self._get_or_create(t)
|
|
|
|
# Default topology (bootstrap connections)
|
|
self._connect("idle", "diagnose", 1.0)
|
|
self._connect("diagnose", "build", 0.8)
|
|
self._connect("diagnose", "fix_toolchain", 0.6)
|
|
self._connect("build", "prove", 0.7)
|
|
self._connect("build", "benchmark", 0.3)
|
|
self._connect("prove", "load_module", 0.4)
|
|
self._connect("prove", "export_dag", 0.2)
|
|
self._connect("fix_toolchain", "build", 0.9)
|
|
self._connect("load_module", "collect_data", 0.8)
|
|
self._connect("collect_data", "compress_baseline", 0.5)
|
|
self._connect("benchmark", "export_dag", 0.6)
|
|
self._connect("build", "ghost_ingested", 0.2)
|
|
self._connect("reboot", "diagnose", 0.9)
|
|
|
|
def _get_or_create(self, nid: str, task_type: Optional[str] = None) -> Neuron:
|
|
if nid not in self.neurons:
|
|
self.neurons[nid] = Neuron(nid=nid, task_type=task_type or nid)
|
|
return self.neurons[nid]
|
|
|
|
def _connect(self, src: str, dst: str, initial_weight: float = 1.0):
|
|
n = self._get_or_create(src)
|
|
syn = n.get_synapse(dst)
|
|
syn.weight = initial_weight
|
|
|
|
def _load_state(self):
|
|
if not os.path.exists(self.state_file):
|
|
return
|
|
try:
|
|
with open(self.state_file) as f:
|
|
data = json.load(f)
|
|
self.dag_generation = data.get("dag_generation", 0)
|
|
self.mode = data.get("mode", "observe")
|
|
for nid, ndata in data.get("neurons", {}).items():
|
|
n = self._get_or_create(nid, ndata.get("task_type", nid))
|
|
n.coord = ndata.get("coord", n.coord)
|
|
n.visit_count = ndata.get("visit_count", 0)
|
|
n.total_mass = ndata.get("total_mass", 0)
|
|
for sdata in ndata.get("synapses", []):
|
|
syn = n.get_synapse(sdata["target"])
|
|
syn.weight = sdata.get("weight", 1.0)
|
|
syn.success_count = sdata.get("success_count", 0)
|
|
syn.failure_count = sdata.get("failure_count", 0)
|
|
except Exception as e:
|
|
print(f"[orchestrator] state load warning: {e}", file=sys.stderr)
|
|
|
|
def save_state(self):
|
|
os.makedirs(os.path.dirname(self.state_file), exist_ok=True)
|
|
data = {
|
|
"dag_generation": self.dag_generation,
|
|
"mode": self.mode,
|
|
"timestamp": time.time(),
|
|
"neurons": {}
|
|
}
|
|
for nid, n in self.neurons.items():
|
|
data["neurons"][nid] = {
|
|
"task_type": n.task_type,
|
|
"coord": n.coord,
|
|
"visit_count": n.visit_count,
|
|
"total_mass": n.total_mass,
|
|
"synapses": [
|
|
{
|
|
"target": s.target,
|
|
"weight": s.weight,
|
|
"success_count": s.success_count,
|
|
"failure_count": s.failure_count,
|
|
"last_seen": s.last_seen
|
|
}
|
|
for s in n.synapses
|
|
]
|
|
}
|
|
with open(self.state_file, "w") as f:
|
|
json.dump(data, f, indent=2)
|
|
|
|
# ──────────────────────────────────────────────────────────────────────
|
|
# Observation & Learning
|
|
# ──────────────────────────────────────────────────────────────────────
|
|
|
|
def observe(self, from_task: str, to_task: str, outcome: bool,
|
|
metadata: Optional[dict] = None):
|
|
"""Record a transition and apply Hebbian plasticity."""
|
|
src = self._get_or_create(from_task)
|
|
dst = self._get_or_create(to_task)
|
|
syn = src.get_synapse(to_task)
|
|
|
|
if outcome:
|
|
syn.potentiate()
|
|
dst.activate(stimulus=0.5)
|
|
else:
|
|
syn.depress()
|
|
dst.activate(stimulus=-0.3)
|
|
|
|
self.execution_log.append({
|
|
"timestamp": time.time(),
|
|
"from": from_task,
|
|
"to": to_task,
|
|
"outcome": outcome,
|
|
"metadata": metadata or {}
|
|
})
|
|
|
|
self.dag_generation += 1
|
|
self._feed_to_kernel(from_task, to_task, outcome)
|
|
|
|
def _feed_to_kernel(self, from_task: str, to_task: str, outcome: bool):
|
|
"""Feed orchestrator transitions into pist_neuromorphic.ko."""
|
|
sample_path = Path("/sys/kernel/pist_neuromorphic/sample")
|
|
if not sample_path.exists():
|
|
return
|
|
try:
|
|
payload = f"{from_task}→{to_task}:{int(outcome)}\n".encode()
|
|
with open(sample_path, "wb") as f:
|
|
f.write(payload)
|
|
except PermissionError:
|
|
pass # Not running as root — expected
|
|
except Exception:
|
|
pass
|
|
|
|
# ──────────────────────────────────────────────────────────────────────
|
|
# Execution Primitives
|
|
# ──────────────────────────────────────────────────────────────────────
|
|
|
|
def run_build(self) -> bool:
|
|
"""Execute lake build, observe result."""
|
|
print("[orchestrator] → run_build")
|
|
start = time.time()
|
|
proc = subprocess.run(
|
|
["lake", "build"],
|
|
cwd=Path.home() / "CascadeProjects" / "Research-Stack" / "0-Core-Formalism" / "lean" / "Semantics",
|
|
capture_output=True, text=True
|
|
)
|
|
elapsed = time.time() - start
|
|
success = proc.returncode == 0
|
|
self.observe("build", "prove" if success else "fix_toolchain", success,
|
|
{"elapsed": elapsed, "stdout_lines": len(proc.stdout.splitlines())})
|
|
return success
|
|
|
|
def run_prover(self, target_file: str, model: str = "zeyu-zheng/BFS-Prover-V2-7B:q8_0") -> bool:
|
|
"""Run BFS-Prover on a target file."""
|
|
print(f"[orchestrator] → run_prover({target_file})")
|
|
bf4prover = Path.home() / "CascadeProjects" / "Research-Stack" / "scripts" / "bf4prover.py"
|
|
start = time.time()
|
|
proc = subprocess.run(
|
|
[sys.executable, str(bf4prover), "--file", target_file],
|
|
capture_output=True, text=True
|
|
)
|
|
elapsed = time.time() - start
|
|
success = proc.returncode == 0
|
|
self.observe("prove", "load_module" if success else "reboot", success,
|
|
{"elapsed": elapsed, "model": model})
|
|
return success
|
|
|
|
def load_kernel_module(self) -> bool:
|
|
"""Load pist_neuromorphic.ko."""
|
|
print("[orchestrator] → load_kernel_module")
|
|
kmod = Path.home() / "CascadeProjects" / "Research-Stack" / "6-Kernel-Shim" / "pist_neuromorphic.ko"
|
|
proc = subprocess.run(["sudo", "insmod", str(kmod)], capture_output=True, text=True)
|
|
success = proc.returncode == 0
|
|
self.observe("load_module", "collect_data" if success else "reboot", success,
|
|
{"stderr": proc.stderr[:200] if not success else ""})
|
|
return success
|
|
|
|
def diagnose(self) -> dict:
|
|
"""System diagnostic — returns observational data."""
|
|
print("[orchestrator] → diagnose")
|
|
result = {}
|
|
|
|
# Kernel version
|
|
try:
|
|
with open("/proc/version") as f:
|
|
result["kernel"] = f.read().strip()
|
|
except Exception:
|
|
result["kernel"] = "unknown"
|
|
|
|
# NVIDIA
|
|
try:
|
|
proc = subprocess.run(["nvidia-smi"], capture_output=True, text=True)
|
|
result["gpu"] = "available" if proc.returncode == 0 else proc.stderr[:200]
|
|
except FileNotFoundError:
|
|
result["gpu"] = "not_installed"
|
|
|
|
# Ollama
|
|
try:
|
|
proc = subprocess.run(["ollama", "ps"], capture_output=True, text=True)
|
|
result["ollama"] = proc.stdout.strip()
|
|
except FileNotFoundError:
|
|
result["ollama"] = "not_installed"
|
|
|
|
# Kernel module
|
|
result["neuromorphic_module"] = os.path.exists("/sys/kernel/pist_neuromorphic")
|
|
|
|
# Lean toolchain
|
|
try:
|
|
tc = Path.home() / "CascadeProjects" / "Research-Stack" / "0-Core-Formalism" / "lean" / "Semantics" / "lean-toolchain"
|
|
result["lean_toolchain"] = tc.read_text().strip()
|
|
except Exception:
|
|
result["lean_toolchain"] = "unknown"
|
|
|
|
self.observe("idle", "diagnose", True, result)
|
|
return result
|
|
|
|
def scan_lean_topology(self) -> dict:
|
|
"""Discover all .lean files, count sorry, create neurons per module."""
|
|
print("[orchestrator] → scan_lean_topology")
|
|
base = Path.home() / "CascadeProjects" / "Research-Stack"
|
|
findings = {"canonical": {}, "external": {}, "ingested": {}, "other": {}, "total_sorry": 0}
|
|
|
|
for path in base.rglob("*.lean"):
|
|
if ".lake" in str(path) or "build" in str(path) or "build-static" in str(path):
|
|
continue
|
|
|
|
rel = str(path.relative_to(base))
|
|
try:
|
|
text = path.read_text()
|
|
except Exception:
|
|
continue
|
|
|
|
sorry_count = text.count("\n sorry") + text.count("\n sorry")
|
|
if sorry_count == 0:
|
|
continue
|
|
|
|
findings["total_sorry"] += sorry_count
|
|
|
|
# Bucket classification
|
|
if rel.startswith("0-Core-Formalism/lean/Semantics/Semantics/"):
|
|
bucket = "canonical"
|
|
elif rel.startswith("0-Core-Formalism/lean/external/"):
|
|
bucket = "external"
|
|
elif "shared-data/data/ingested/" in rel:
|
|
bucket = "ingested"
|
|
elif "archive/" in rel:
|
|
continue # Skip archives
|
|
else:
|
|
bucket = "other"
|
|
|
|
findings[bucket][rel] = sorry_count
|
|
|
|
# Create neuron for high-sorry files
|
|
if sorry_count >= 2:
|
|
nid = f"file_{rel.replace('/', '_').replace('.', '_')}"
|
|
n = self._get_or_create(nid, task_type="prove_file")
|
|
n.coord = pist_encode_u8(min(sorry_count * 16, 255))
|
|
# Connect file neuron to prove and ghost actions
|
|
self._connect(nid, "prove", initial_weight=float(sorry_count))
|
|
self._connect(nid, "ghost_ingested" if bucket == "ingested" else "prove", initial_weight=1.0)
|
|
|
|
# Create summary neurons
|
|
for bucket, files in findings.items():
|
|
if bucket == "total_sorry":
|
|
continue
|
|
nid = f"summary_{bucket}"
|
|
n = self._get_or_create(nid, task_type="summary")
|
|
n.total_mass = sum(files.values())
|
|
self._connect(nid, "prove" if bucket == "canonical" else "ghost_ingested", initial_weight=float(n.total_mass))
|
|
|
|
self.observe("diagnose", "scan_lean_topology", True,
|
|
{"total_sorry": findings["total_sorry"],
|
|
"canonical_files": len(findings["canonical"]),
|
|
"ingested_files": len(findings["ingested"])})
|
|
return findings
|
|
|
|
def fix_toolchain(self) -> bool:
|
|
"""Revert lean-toolchain to v4.29.1 to restore mathlib cache."""
|
|
print("[orchestrator] → fix_toolchain")
|
|
base = Path.home() / "CascadeProjects" / "Research-Stack" / "0-Core-Formalism" / "lean" / "Semantics"
|
|
tc_file = base / "lean-toolchain"
|
|
lake_file = base / "lakefile.toml"
|
|
success = False
|
|
|
|
try:
|
|
# Revert toolchain
|
|
tc_file.write_text("leanprover/lean4:v4.29.1\n")
|
|
# Revert mathlib rev in lakefile.toml
|
|
text = lake_file.read_text()
|
|
text = text.replace("v4.30.0-rc2", "v4.29.1")
|
|
lake_file.write_text(text)
|
|
# Clean and update
|
|
subprocess.run(["lake", "clean"], cwd=base, capture_output=True)
|
|
proc = subprocess.run(["lake", "update"], cwd=base, capture_output=True, text=True)
|
|
success = proc.returncode == 0
|
|
except Exception as e:
|
|
print(f"[orchestrator] fix_toolchain error: {e}", file=sys.stderr)
|
|
|
|
self.observe("fix_toolchain", "build" if success else "diagnose", success,
|
|
{"toolchain": "v4.29.1"})
|
|
return success
|
|
|
|
def ghost_ingested(self) -> bool:
|
|
"""Rename ingested .lean files with .GHOST suffix."""
|
|
print("[orchestrator] → ghost_ingested")
|
|
base = Path.home() / "CascadeProjects" / "Research-Stack" / "shared-data" / "data" / "ingested"
|
|
ghosted = 0
|
|
try:
|
|
for path in base.rglob("*.lean"):
|
|
if not path.name.endswith(".GHOST"):
|
|
ghost_path = path.with_suffix(path.suffix + ".GHOST")
|
|
shutil.move(str(path), str(ghost_path))
|
|
ghosted += 1
|
|
except Exception as e:
|
|
print(f"[orchestrator] ghost_ingested error: {e}", file=sys.stderr)
|
|
|
|
success = ghosted > 0
|
|
self.observe("ghost_ingested", "build", success, {"ghosted_count": ghosted})
|
|
return success
|
|
|
|
def run_benchmark(self) -> bool:
|
|
"""Run PIST compression benchmark on Canterbury Corpus."""
|
|
print("[orchestrator] → run_benchmark")
|
|
base = Path.home() / "CascadeProjects" / "Research-Stack"
|
|
bench_dir = base / "shared-data" / "data" / "groundtruth" / "compression-baselines"
|
|
pist_script = base / "Desktop" / "pist_biological_polymorphic_shifter_v3_complete.py"
|
|
success = False
|
|
results = {}
|
|
|
|
try:
|
|
for fpath in bench_dir.iterdir():
|
|
if not fpath.is_file():
|
|
continue
|
|
data = fpath.read_bytes()
|
|
orig_size = len(data)
|
|
# Simple coordinate encoding as baseline
|
|
coords = [pist_encode_u8(b) for b in data[:4096]] # Sample first 4KB
|
|
coord_bytes = len(coords) * 4
|
|
ratio = orig_size / coord_bytes if coord_bytes > 0 else 0
|
|
results[fpath.name] = {"original": orig_size, "coord_4k": coord_bytes, "ratio": ratio}
|
|
success = True
|
|
except Exception as e:
|
|
print(f"[orchestrator] benchmark error: {e}", file=sys.stderr)
|
|
|
|
self.observe("compress_baseline", "export_dag", success, {"files_tested": len(results)})
|
|
return success
|
|
|
|
# ──────────────────────────────────────────────────────────────────────
|
|
# Topological Navigation
|
|
# ──────────────────────────────────────────────────────────────────────
|
|
|
|
def step(self, temperature: float = 1.0) -> Optional[str]:
|
|
"""Take one step on the manifold. Returns next task or None."""
|
|
if self.current_neuron is None:
|
|
self.current_neuron = "idle"
|
|
|
|
n = self.neurons.get(self.current_neuron)
|
|
if not n:
|
|
return None
|
|
|
|
n.activate()
|
|
next_id = n.choose_next(temperature=temperature)
|
|
if next_id:
|
|
print(f"[orchestrator] {self.current_neuron} → {next_id} "
|
|
f"(tension={pist_tension(n.coord):.3f}, mass={n.total_mass})")
|
|
self.current_neuron = next_id
|
|
return next_id
|
|
|
|
def walk(self, max_steps: int = 10, temperature: float = 1.0) -> List[str]:
|
|
"""Walk the manifold, executing tasks in execute mode."""
|
|
path = []
|
|
for _ in range(max_steps):
|
|
task = self.step(temperature=temperature)
|
|
if task is None:
|
|
break
|
|
path.append(task)
|
|
|
|
if self.mode == "execute":
|
|
self._execute_task(task)
|
|
elif self.mode == "suggest":
|
|
print(f"[orchestrator] SUGGEST: {task}")
|
|
|
|
self.save_state()
|
|
return path
|
|
|
|
def _execute_task(self, task: str):
|
|
"""Dispatch task to execution primitive."""
|
|
handlers = {
|
|
"diagnose": self.diagnose,
|
|
"build": self.run_build,
|
|
"prove": self.run_prover,
|
|
"load_module": self.load_kernel_module,
|
|
"fix_toolchain": self.fix_toolchain,
|
|
"ghost_ingested": self.ghost_ingested,
|
|
"compress_baseline": self.run_benchmark,
|
|
"scan": self.scan_lean_topology,
|
|
}
|
|
handler = handlers.get(task)
|
|
if handler:
|
|
try:
|
|
result = handler()
|
|
# Auto-observe success if handler returns truthy
|
|
if result:
|
|
n = self.neurons.get(task)
|
|
if n:
|
|
for syn in n.synapses:
|
|
syn.potentiate()
|
|
except Exception as e:
|
|
print(f"[orchestrator] task {task} failed: {e}", file=sys.stderr)
|
|
n = self.neurons.get(task)
|
|
if n:
|
|
for syn in n.synapses:
|
|
syn.depress()
|
|
elif task.startswith("file_"):
|
|
# File-specific neuron — extract original path
|
|
print(f"[orchestrator] target file neuron: {task}")
|
|
|
|
def continuous_loop(self, interval: float = 60.0, temperature: float = 1.0):
|
|
"""Run forever, adapting temperature based on crisis level."""
|
|
print(f"[orchestrator] ENTERING CONTINUOUS LOOP (interval={interval}s)")
|
|
consecutive_failures = 0
|
|
while True:
|
|
try:
|
|
# Crisis detection: too many failures → force exploration
|
|
if consecutive_failures >= 3:
|
|
temperature = min(temperature * 1.5, 5.0)
|
|
print(f"[orchestrator] CRISIS MODE: temperature bumped to {temperature}")
|
|
|
|
task = self.step(temperature=temperature)
|
|
if task is None:
|
|
time.sleep(interval)
|
|
continue
|
|
|
|
if self.mode == "execute":
|
|
result = self._execute_task_and_report(task)
|
|
if result:
|
|
consecutive_failures = max(0, consecutive_failures - 1)
|
|
temperature = max(temperature * 0.9, 0.5)
|
|
else:
|
|
consecutive_failures += 1
|
|
elif self.mode == "suggest":
|
|
print(f"[orchestrator] SUGGEST: {task}")
|
|
|
|
self.save_state()
|
|
time.sleep(interval)
|
|
except KeyboardInterrupt:
|
|
print("[orchestrator] Interrupted by user")
|
|
self.save_state()
|
|
break
|
|
|
|
def _execute_task_and_report(self, task: str) -> bool:
|
|
"""Execute and auto-observe with proper transition tracking."""
|
|
prev = self.current_neuron
|
|
handlers = {
|
|
"diagnose": self.diagnose,
|
|
"build": self.run_build,
|
|
"prove": lambda: self.run_prover("Semantics/FixedPoint.lean"),
|
|
"load_module": self.load_kernel_module,
|
|
"fix_toolchain": self.fix_toolchain,
|
|
"ghost_ingested": self.ghost_ingested,
|
|
"compress_baseline": self.run_benchmark,
|
|
"scan": self.scan_lean_topology,
|
|
}
|
|
handler = handlers.get(task)
|
|
if not handler:
|
|
return False
|
|
try:
|
|
result = handler()
|
|
success = bool(result) if result is not None else True
|
|
except Exception as e:
|
|
print(f"[orchestrator] execution failed: {e}", file=sys.stderr)
|
|
success = False
|
|
|
|
if prev and task:
|
|
self.observe(prev, task, success, {"auto": True})
|
|
return success
|
|
|
|
# ──────────────────────────────────────────────────────────────────────
|
|
# DAG Export
|
|
# ──────────────────────────────────────────────────────────────────────
|
|
|
|
def export_dag(self, path: Optional[str] = None) -> str:
|
|
"""Export current DAG as text."""
|
|
lines = [
|
|
f"# PIST Neuromorphic Orchestrator DAG",
|
|
f"# generation={self.dag_generation} mode={self.mode}",
|
|
f"# timestamp={datetime.now().isoformat()}",
|
|
"# neuron_id task_type coord visit_count mass"
|
|
]
|
|
for nid, n in sorted(self.neurons.items(), key=lambda x: -x[1].visit_count):
|
|
lines.append(
|
|
f"{nid} {n.task_type} 0x{n.coord:08x} {n.visit_count} {n.total_mass}"
|
|
)
|
|
for s in sorted(n.synapses, key=lambda x: -x.weight)[:5]:
|
|
lines.append(f" → {s.target} w={s.weight:.2f} sr={s.success_rate:.2f}")
|
|
|
|
text = "\n".join(lines) + "\n"
|
|
if path:
|
|
with open(path, "w") as f:
|
|
f.write(text)
|
|
return text
|
|
|
|
|
|
# ──────────────────────────────────────────────────────────────────────────
|
|
# CLI
|
|
# ──────────────────────────────────────────────────────────────────────────
|
|
|
|
def main():
|
|
import argparse
|
|
parser = argparse.ArgumentParser(description="PIST Neuromorphic Orchestrator")
|
|
parser.add_argument("--mode", choices=["observe", "suggest", "execute"],
|
|
default="observe", help="Orchestrator mode")
|
|
parser.add_argument("--steps", type=int, default=5, help="Max manifold walk steps")
|
|
parser.add_argument("--temperature", type=float, default=1.0,
|
|
help="Exploration temperature (higher = more random)")
|
|
parser.add_argument("--export", type=str, help="Export DAG to file")
|
|
parser.add_argument("--feed-kernel", action="store_true",
|
|
help="Feed orchestrator state into pist_neuromorphic.ko")
|
|
parser.add_argument("--diagnose", action="store_true",
|
|
help="Run system diagnostic and exit")
|
|
parser.add_argument("--scan", action="store_true",
|
|
help="Scan Lean topology and exit")
|
|
parser.add_argument("--loop", action="store_true",
|
|
help="Run continuous adaptive loop")
|
|
parser.add_argument("--interval", type=float, default=60.0,
|
|
help="Loop interval in seconds (default: 60)")
|
|
args = parser.parse_args()
|
|
|
|
orch = NeuromorphicOrchestrator()
|
|
orch.mode = args.mode
|
|
|
|
if args.diagnose:
|
|
result = orch.diagnose()
|
|
print(json.dumps(result, indent=2))
|
|
orch.save_state()
|
|
return
|
|
|
|
if args.scan:
|
|
findings = orch.scan_lean_topology()
|
|
print(json.dumps(findings, indent=2))
|
|
orch.save_state()
|
|
return
|
|
|
|
if args.export:
|
|
orch.export_dag(args.export)
|
|
print(f"[orchestrator] DAG exported to {args.export}")
|
|
return
|
|
|
|
print(f"[orchestrator] mode={args.mode} steps={args.steps} temp={args.temperature}")
|
|
print(f"[orchestrator] dag_generation={orch.dag_generation}")
|
|
print(f"[orchestrator] neurons={len(orch.neurons)}")
|
|
|
|
if args.loop:
|
|
orch.continuous_loop(interval=args.interval, temperature=args.temperature)
|
|
return
|
|
|
|
path = orch.walk(max_steps=args.steps, temperature=args.temperature)
|
|
print(f"[orchestrator] path={' → '.join(path)}")
|
|
orch.save_state()
|
|
|
|
# Feed to kernel if requested
|
|
if args.feed_kernel:
|
|
state_text = json.dumps({
|
|
"dag_generation": orch.dag_generation,
|
|
"path": path,
|
|
"neuron_count": len(orch.neurons)
|
|
})
|
|
try:
|
|
with open("/sys/kernel/pist_neuromorphic/sample", "wb") as f:
|
|
f.write(state_text.encode())
|
|
print("[orchestrator] state fed to kernel module")
|
|
except Exception as e:
|
|
print(f"[orchestrator] kernel feed failed: {e}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|