#!/usr/bin/env python3
"""
UNBOUND270 — Capability Governor Daemon
STONE RULE: read-only truth, append-only time
"""

import json
import time
import uuid
from pathlib import Path
from datetime import datetime, timezone

# =========================
# PATHS (CANONICAL)
# =========================
BASE = Path("/sovereign")

UNBOUND_ROOT = BASE / "unbound"
CAP_REG = UNBOUND_ROOT / "capabilities" / "registry.json"
GOV_REG = UNBOUND_ROOT / "registry" / "anchorite_act.json"
LOG_DIR = UNBOUND_ROOT / "logs"

CHRONO_EVENTS = BASE / "chronos_meta" / "events"

LOG_DIR.mkdir(parents=True, exist_ok=True)
CHRONO_EVENTS.mkdir(parents=True, exist_ok=True)

LOG_FILE = LOG_DIR / "unbound270.log"

# =========================
# HELPERS
# =========================
def utc_now():
    return datetime.now(timezone.utc).isoformat()

def log(msg):
    line = f"[{utc_now()}] {msg}\n"
    LOG_FILE.open("a").write(line)
    print(line, end="")

def load_json(path):
    try:
        return json.loads(path.read_text())
    except Exception:
        return {}

def write_event(obj):
    fname = CHRONO_EVENTS / f"unbound270_{int(time.time())}.json"
    fname.write_text(json.dumps(obj, indent=2))
    return fname

# =========================
# LOAD REGISTRIES
# =========================
CAPABILITIES = load_json(CAP_REG)
GOVERNANCE = load_json(GOV_REG)

log("UNBOUND270 daemon booting")
log(f"Capabilities loaded: {list(CAPABILITIES.keys())}")
log(f"Governance loaded: {GOVERNANCE.get('id','UNKNOWN')}")

# =========================
# CORE INVOCATION HANDLER
# =========================
def invoke(capability, context, caller="SYSTEM"):
    req_id = str(uuid.uuid4())

    # --- SEEDem VOID DETECTION ---
    voids = []
    if capability not in CAPABILITIES:
        voids.append("CAPABILITY_MISSING")
    if "path" not in context:
        voids.append("CONTEXT_PATH_MISSING")

    # --- ABM SCORE ---
    score = 0
    if capability.startswith("filesystem"):
        score += 50
    if context.get("path","").startswith("/sovereign"):
        score += 30
    score += 10  # caller trust
    score += 10  # ANCHORITE governance

    # --- ADAPTER EXECUTION (READ-ONLY) ---
    result = {}
    if not voids and capability == "filesystem.list":
        p = Path(context["path"])
        result["dirs"] = [x.name for x in p.iterdir() if x.is_dir()][:10]

    # --- CHRONOLOGICAL EVENT ---
    event = {
        "event": "UNBOUND270_INVOKE",
        "authority": "UNBOUND",
        "version": "UNBOUND270",
        "request_id": req_id,
        "capability": capability,
        "caller": caller,
        "abm_score": score,
        "voids": voids,
        "status": "OK" if not voids else "VOID",
        "result": result,
        "ts": utc_now()
    }

    out = write_event(event)
    log(f"Invocation {req_id} → {out.name}")

# =========================
# MAIN LOOP (PASSIVE)
# =========================
log("UNBOUND270 READY — awaiting adapters")

while True:
    # Passive governor: adapters will call invoke()
    time.sleep(5)
