Spaces:
Running
Running
chore(sync): mirror backend .py + Dockerfile to Space (hf-sync-backend)
Browse filesAutomated backend sync from szl-holdings/a11oy main via hf-sync-backend.
Updated (differed from the Space): Dockerfile, conduction_aphasia.py, szl_a11oy_live_feeds.py, szl_jack.py
Deleted (gone from the repo + Dockerfile COPY set): (none)
Keeps the Space-built backend (serve.py + the Dockerfile-COPY'd .py
modules) identical to GitHub main so the Space never rebuilds from a
stale backend, new endpoints don't 404 there, and orphaned modules
removed from the repo don't linger in the Space tree.
- Dockerfile +7 -0
- conduction_aphasia.py +577 -0
- szl_a11oy_live_feeds.py +383 -0
- szl_jack.py +305 -0
Dockerfile
CHANGED
|
@@ -711,6 +711,13 @@ COPY szl_hf_bucket.py szl_metrics_prom.py ./
|
|
| 711 |
# Forge fix: these modules are on main + imported by serve.py (try/except) but were NEVER COPY'd
|
| 712 |
# into the image -> ModuleNotFoundError at startup -> /api/a11oy/v1/research/* + dark surfaces 404.
|
| 713 |
COPY szl_research_infra.py szl_dark_surfaces_register.py szl_anatomy_loop.py ./
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 714 |
|
| 715 |
|
| 716 |
CMD ["python", "serve.py"]
|
|
|
|
| 711 |
# Forge fix: these modules are on main + imported by serve.py (try/except) but were NEVER COPY'd
|
| 712 |
# into the image -> ModuleNotFoundError at startup -> /api/a11oy/v1/research/* + dark surfaces 404.
|
| 713 |
COPY szl_research_infra.py szl_dark_surfaces_register.py szl_anatomy_loop.py ./
|
| 714 |
+
# copy-sync lockstep guard (CHECK 2): these modules are on main + imported by serve.py
|
| 715 |
+
# (try/except-guarded) but were NEVER COPY'd into the image, so the import silently fell
|
| 716 |
+
# back to a STUB on the Space (the recurring "merged-but-not-live" failure). conduction_aphasia
|
| 717 |
+
# backs /conduction; szl_a11oy_live_feeds backs the a11oy live-feeds organ; szl_jack is imported
|
| 718 |
+
# transitively by szl_live_wires. Per-file COPY (this Dockerfile never uses `COPY . .`). They
|
| 719 |
+
# auto-mirror to the HF Space via hf-sync-backend.yml (which parses these COPY lines).
|
| 720 |
+
COPY conduction_aphasia.py szl_a11oy_live_feeds.py szl_jack.py ./
|
| 721 |
|
| 722 |
|
| 723 |
CMD ["python", "serve.py"]
|
conduction_aphasia.py
ADDED
|
@@ -0,0 +1,577 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 2 |
+
# © 2026 Lutar, Stephen P. — SZL Holdings · ORCID 0009-0001-0110-4173
|
| 3 |
+
# Authored by Yachay (CTO). Co-Authored-By: Perplexity Computer Agent.
|
| 4 |
+
# Doctrine v11 LOCKED 749/14/163 · Λ Conjecture 1 · SLSA L1 honest · ADDITIVE only
|
| 5 |
+
"""
|
| 6 |
+
conduction_aphasia.py — Conduction-Aphasia Detector for a11oy.
|
| 7 |
+
|
| 8 |
+
Hickok state feedback control architecture (Neuron 2011):
|
| 9 |
+
DOI 10.1016/j.neuron.2011.01.019
|
| 10 |
+
Hickok, Houde, Rong — Sensorimotor integration in speech processing:
|
| 11 |
+
Computational basis and neural organization. Neuron 69, 407-422.
|
| 12 |
+
|
| 13 |
+
Mechanism:
|
| 14 |
+
1. Before any agent action, the PAC-Bayes Governance Head at /api/a11oy/v4/predict
|
| 15 |
+
produces a predicted sensory consequence (the forward model).
|
| 16 |
+
2. After the action runs, we capture the actual sensory consequence (what happened).
|
| 17 |
+
3. Compute delta = ||predicted − actual|| in a defined metric space.
|
| 18 |
+
4. Sign delta into the Khipu receipt.
|
| 19 |
+
5. If delta exceeds τ across N consecutive ticks → fire a CONDUCTION_ALERT receipt.
|
| 20 |
+
This is the analog of conduction aphasia: motor plans intact, outputs may look fine,
|
| 21 |
+
but the internal-loop check is broken.
|
| 22 |
+
|
| 23 |
+
Lutar anchor: A37 InternalFeedbackIntegrity
|
| 24 |
+
|
| 25 |
+
ADDITIVE: call register(app, ns="a11oy") from serve.py BEFORE the SPA catch-all.
|
| 26 |
+
Never modifies existing routes. try/except-guarded from the caller side.
|
| 27 |
+
"""
|
| 28 |
+
from __future__ import annotations
|
| 29 |
+
|
| 30 |
+
import hashlib
|
| 31 |
+
import json
|
| 32 |
+
import math
|
| 33 |
+
import time
|
| 34 |
+
from collections import deque
|
| 35 |
+
from datetime import datetime, timezone
|
| 36 |
+
from typing import Any, Deque, Dict, List, Optional
|
| 37 |
+
|
| 38 |
+
try:
|
| 39 |
+
from fastapi import FastAPI, Query, Request
|
| 40 |
+
from fastapi.responses import HTMLResponse, JSONResponse
|
| 41 |
+
except Exception:
|
| 42 |
+
FastAPI = Query = Request = HTMLResponse = JSONResponse = None # type: ignore
|
| 43 |
+
|
| 44 |
+
try:
|
| 45 |
+
import szl_dsse as _dsse
|
| 46 |
+
except Exception:
|
| 47 |
+
_dsse = None # type: ignore
|
| 48 |
+
|
| 49 |
+
# ---------------------------------------------------------------------------
|
| 50 |
+
# Constants — Doctrine v11 LOCKED
|
| 51 |
+
# ---------------------------------------------------------------------------
|
| 52 |
+
DOCTRINE_V = "11"
|
| 53 |
+
LUTAR_ANCHOR = "A37_InternalFeedbackIntegrity"
|
| 54 |
+
NEURO_CITATION = {
|
| 55 |
+
"doi": "10.1016/j.neuron.2011.01.019",
|
| 56 |
+
"label": "Hickok, Houde, Rong 2011 — Sensorimotor integration: state feedback control",
|
| 57 |
+
"full": (
|
| 58 |
+
"Hickok, G., Houde, J., & Rong, F. (2011). Sensorimotor integration in speech "
|
| 59 |
+
"processing: Computational basis and neural organization. Neuron, 69(3), 407–422."
|
| 60 |
+
),
|
| 61 |
+
}
|
| 62 |
+
DUAL_STREAM_CITATION = {
|
| 63 |
+
"doi": "10.1038/nrn2113",
|
| 64 |
+
"label": "Hickok & Poeppel 2007 — The cortical organization of speech processing",
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
DEFAULT_THRESHOLD_TAU = 0.30
|
| 68 |
+
DEFAULT_WINDOW_N = 3 # consecutive breaches to fire CONDUCTION_ALERT
|
| 69 |
+
RECEIPT_RING_SIZE = 200 # in-memory ring buffer
|
| 70 |
+
|
| 71 |
+
ALERT_NORMAL = "normal"
|
| 72 |
+
ALERT_WATCHING = "watching"
|
| 73 |
+
ALERT_CONDUCTION = "conduction_alert"
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
# ---------------------------------------------------------------------------
|
| 77 |
+
# In-process state
|
| 78 |
+
# ---------------------------------------------------------------------------
|
| 79 |
+
|
| 80 |
+
class _ConductionState:
|
| 81 |
+
def __init__(self, tau: float = DEFAULT_THRESHOLD_TAU, window: int = DEFAULT_WINDOW_N) -> None:
|
| 82 |
+
self.threshold_tau: float = float(tau)
|
| 83 |
+
self.window_size: int = int(window)
|
| 84 |
+
self._breach_streak: int = 0
|
| 85 |
+
self._current_alert: str = ALERT_NORMAL
|
| 86 |
+
self._last_alert_at: Optional[str] = None
|
| 87 |
+
self._receipts: Deque[Dict[str, Any]] = deque(maxlen=RECEIPT_RING_SIZE)
|
| 88 |
+
self._breach_count_24h: int = 0
|
| 89 |
+
self._24h_window_start: float = time.time()
|
| 90 |
+
|
| 91 |
+
def observe(self, tick_id: str, predicted_sensory: Any, actual_sensory: Any,
|
| 92 |
+
metric: str = "cosine") -> Dict[str, Any]:
|
| 93 |
+
delta = _compute_delta(predicted_sensory, actual_sensory, metric)
|
| 94 |
+
breach = delta > self.threshold_tau
|
| 95 |
+
if breach:
|
| 96 |
+
self._breach_streak += 1
|
| 97 |
+
self._update_24h_breach_count()
|
| 98 |
+
else:
|
| 99 |
+
self._breach_streak = 0
|
| 100 |
+
|
| 101 |
+
if self._breach_streak >= self.window_size:
|
| 102 |
+
alert_level = ALERT_CONDUCTION
|
| 103 |
+
self._current_alert = ALERT_CONDUCTION
|
| 104 |
+
self._last_alert_at = _iso()
|
| 105 |
+
elif self._breach_streak >= 1:
|
| 106 |
+
alert_level = ALERT_WATCHING
|
| 107 |
+
self._current_alert = ALERT_WATCHING
|
| 108 |
+
else:
|
| 109 |
+
alert_level = ALERT_NORMAL
|
| 110 |
+
self._current_alert = ALERT_NORMAL
|
| 111 |
+
|
| 112 |
+
receipt = _build_receipt(
|
| 113 |
+
tick_id=tick_id, predicted_sensory=predicted_sensory,
|
| 114 |
+
actual_sensory=actual_sensory, delta=float(delta), metric=metric,
|
| 115 |
+
threshold_tau=self.threshold_tau, breach=breach, alert_level=alert_level,
|
| 116 |
+
consecutive_breaches=self._breach_streak,
|
| 117 |
+
)
|
| 118 |
+
self._receipts.appendleft(receipt)
|
| 119 |
+
return receipt
|
| 120 |
+
|
| 121 |
+
def status(self) -> Dict[str, Any]:
|
| 122 |
+
return {
|
| 123 |
+
"window_size": self.window_size,
|
| 124 |
+
"threshold_tau": self.threshold_tau,
|
| 125 |
+
"recent_breaches": [r for r in list(self._receipts)[:10] if r.get("breach")],
|
| 126 |
+
"current_alert_level": self._current_alert,
|
| 127 |
+
"last_alert_at": self._last_alert_at,
|
| 128 |
+
"consecutive_breaches": self._breach_streak,
|
| 129 |
+
"breaches_24h": self._get_24h_breach_count(),
|
| 130 |
+
"doctrine_v": DOCTRINE_V,
|
| 131 |
+
"lutar_anchor": LUTAR_ANCHOR,
|
| 132 |
+
"neuro_citation": NEURO_CITATION,
|
| 133 |
+
}
|
| 134 |
+
|
| 135 |
+
def receipts(self, limit: int = 20) -> List[Dict[str, Any]]:
|
| 136 |
+
return list(self._receipts)[:limit]
|
| 137 |
+
|
| 138 |
+
def _update_24h_breach_count(self) -> None:
|
| 139 |
+
now = time.time()
|
| 140 |
+
if now - self._24h_window_start > 86400:
|
| 141 |
+
self._breach_count_24h = 1
|
| 142 |
+
self._24h_window_start = now
|
| 143 |
+
else:
|
| 144 |
+
self._breach_count_24h += 1
|
| 145 |
+
|
| 146 |
+
def _get_24h_breach_count(self) -> int:
|
| 147 |
+
if time.time() - self._24h_window_start > 86400:
|
| 148 |
+
return 0
|
| 149 |
+
return self._breach_count_24h
|
| 150 |
+
|
| 151 |
+
|
| 152 |
+
_STATE = _ConductionState()
|
| 153 |
+
|
| 154 |
+
|
| 155 |
+
def get_state() -> _ConductionState:
|
| 156 |
+
return _STATE
|
| 157 |
+
|
| 158 |
+
|
| 159 |
+
def reset_state(tau: float = DEFAULT_THRESHOLD_TAU, window: int = DEFAULT_WINDOW_N) -> None:
|
| 160 |
+
global _STATE
|
| 161 |
+
_STATE = _ConductionState(tau=tau, window=window)
|
| 162 |
+
|
| 163 |
+
|
| 164 |
+
# ---------------------------------------------------------------------------
|
| 165 |
+
# Delta computation
|
| 166 |
+
# ---------------------------------------------------------------------------
|
| 167 |
+
|
| 168 |
+
def _to_vec(x: Any) -> List[float]:
|
| 169 |
+
if isinstance(x, list) and all(isinstance(v, (int, float)) for v in x):
|
| 170 |
+
return [float(v) for v in x]
|
| 171 |
+
if isinstance(x, dict):
|
| 172 |
+
return [float(v) for v in sorted(x.values()) if isinstance(v, (int, float))]
|
| 173 |
+
if isinstance(x, (int, float)):
|
| 174 |
+
return [float(x)]
|
| 175 |
+
if isinstance(x, str):
|
| 176 |
+
h = int(hashlib.sha256(x.encode()).hexdigest(), 16)
|
| 177 |
+
return [float((h >> (i * 8)) & 0xFF) / 255.0 for i in range(8)]
|
| 178 |
+
raw = json.dumps(x, sort_keys=True, default=str).encode()
|
| 179 |
+
h = int(hashlib.sha256(raw).hexdigest(), 16)
|
| 180 |
+
return [float((h >> (i * 8)) & 0xFF) / 255.0 for i in range(8)]
|
| 181 |
+
|
| 182 |
+
|
| 183 |
+
def _l2_delta(a: List[float], b: List[float]) -> float:
|
| 184 |
+
n = max(len(a), len(b))
|
| 185 |
+
a = (a + [0.0] * n)[:n]
|
| 186 |
+
b = (b + [0.0] * n)[:n]
|
| 187 |
+
return math.sqrt(sum((x - y) ** 2 for x, y in zip(a, b)))
|
| 188 |
+
|
| 189 |
+
|
| 190 |
+
def _cosine_delta(a: List[float], b: List[float]) -> float:
|
| 191 |
+
n = max(len(a), len(b))
|
| 192 |
+
a = (a + [0.0] * n)[:n]
|
| 193 |
+
b = (b + [0.0] * n)[:n]
|
| 194 |
+
dot = sum(x * y for x, y in zip(a, b))
|
| 195 |
+
mag_a = math.sqrt(sum(x ** 2 for x in a))
|
| 196 |
+
mag_b = math.sqrt(sum(x ** 2 for x in b))
|
| 197 |
+
if mag_a == 0 or mag_b == 0:
|
| 198 |
+
return 0.0 if mag_a == mag_b == 0 else 1.0
|
| 199 |
+
return 1.0 - dot / (mag_a * mag_b)
|
| 200 |
+
|
| 201 |
+
|
| 202 |
+
def _hash_hamming_delta(predicted: Any, actual: Any) -> float:
|
| 203 |
+
def _sha_bits(x: Any) -> str:
|
| 204 |
+
raw = json.dumps(x, sort_keys=True, default=str).encode()
|
| 205 |
+
h = hashlib.sha256(raw).hexdigest()
|
| 206 |
+
return bin(int(h, 16))[2:].zfill(256)
|
| 207 |
+
bits_p = _sha_bits(predicted)
|
| 208 |
+
bits_a = _sha_bits(actual)
|
| 209 |
+
return sum(p != a for p, a in zip(bits_p, bits_a)) / 256.0
|
| 210 |
+
|
| 211 |
+
|
| 212 |
+
def _compute_delta(predicted: Any, actual: Any, metric: str) -> float:
|
| 213 |
+
metric = metric.lower()
|
| 214 |
+
if metric == "hash_hamming":
|
| 215 |
+
return _hash_hamming_delta(predicted, actual)
|
| 216 |
+
vec_p = _to_vec(predicted)
|
| 217 |
+
vec_a = _to_vec(actual)
|
| 218 |
+
if metric == "l2":
|
| 219 |
+
return _l2_delta(vec_p, vec_a)
|
| 220 |
+
return _cosine_delta(vec_p, vec_a)
|
| 221 |
+
|
| 222 |
+
|
| 223 |
+
# ---------------------------------------------------------------------------
|
| 224 |
+
# Receipt construction + signing
|
| 225 |
+
# ---------------------------------------------------------------------------
|
| 226 |
+
|
| 227 |
+
def _sha256_repr(x: Any) -> str:
|
| 228 |
+
raw = json.dumps(x, sort_keys=True, default=str).encode()
|
| 229 |
+
return "sha256:" + hashlib.sha256(raw).hexdigest()
|
| 230 |
+
|
| 231 |
+
|
| 232 |
+
def _iso() -> str:
|
| 233 |
+
return datetime.now(timezone.utc).isoformat()
|
| 234 |
+
|
| 235 |
+
|
| 236 |
+
def _receipt_id(tick_id: str, ts: str) -> str:
|
| 237 |
+
raw = f"conduction:{tick_id}:{ts}".encode()
|
| 238 |
+
return "cr_" + hashlib.sha256(raw).hexdigest()[:24]
|
| 239 |
+
|
| 240 |
+
|
| 241 |
+
def _build_receipt(tick_id, predicted_sensory, actual_sensory, delta, metric,
|
| 242 |
+
threshold_tau, breach, alert_level, consecutive_breaches):
|
| 243 |
+
ts = _iso()
|
| 244 |
+
rid = _receipt_id(tick_id, ts)
|
| 245 |
+
receipt: Dict[str, Any] = {
|
| 246 |
+
"receipt_id": rid,
|
| 247 |
+
"kind": "conduction_observation",
|
| 248 |
+
"tick_id": tick_id,
|
| 249 |
+
"predicted_hash": _sha256_repr(predicted_sensory),
|
| 250 |
+
"actual_hash": _sha256_repr(actual_sensory),
|
| 251 |
+
"delta": delta,
|
| 252 |
+
"metric": metric,
|
| 253 |
+
"threshold_tau": threshold_tau,
|
| 254 |
+
"breach": breach,
|
| 255 |
+
"alert_level": alert_level,
|
| 256 |
+
"consecutive_breaches": consecutive_breaches,
|
| 257 |
+
"doctrine_v": DOCTRINE_V,
|
| 258 |
+
"neuro_citation": NEURO_CITATION,
|
| 259 |
+
"lutar_anchor": LUTAR_ANCHOR,
|
| 260 |
+
"signed_by": "yachay",
|
| 261 |
+
"sig": "UNSIGNED",
|
| 262 |
+
"ts": ts,
|
| 263 |
+
}
|
| 264 |
+
if _dsse is not None:
|
| 265 |
+
try:
|
| 266 |
+
env = _dsse.sign_payload(receipt)
|
| 267 |
+
receipt["sig"] = env.get("signatures", [{}])[0].get("sig", "UNSIGNED")
|
| 268 |
+
receipt["dsse_envelope"] = env
|
| 269 |
+
receipt["_signing"] = "REAL" if env.get("signed") else "UNSIGNED"
|
| 270 |
+
except Exception as e:
|
| 271 |
+
receipt["sig"] = f"UNSIGNED: {e}"
|
| 272 |
+
receipt["_signing"] = "UNSIGNED"
|
| 273 |
+
else:
|
| 274 |
+
receipt["sig"] = "UNSIGNED — szl_dsse not available"
|
| 275 |
+
receipt["_signing"] = "UNSIGNED"
|
| 276 |
+
return receipt
|
| 277 |
+
|
| 278 |
+
|
| 279 |
+
# ---------------------------------------------------------------------------
|
| 280 |
+
# FastAPI router registration
|
| 281 |
+
# ---------------------------------------------------------------------------
|
| 282 |
+
|
| 283 |
+
def register(app: Any, ns: str = "a11oy") -> Dict[str, Any]:
|
| 284 |
+
"""Mount Conduction-Aphasia Detector endpoints. ADDITIVE only."""
|
| 285 |
+
base = f"/api/{ns}/v4/conduction"
|
| 286 |
+
|
| 287 |
+
@app.post(f"{base}/observe", tags=["conduction"])
|
| 288 |
+
async def conduction_observe(request: Request) -> JSONResponse:
|
| 289 |
+
"""Record one predicted→actual observation. Body: {tick_id, predicted_sensory,
|
| 290 |
+
actual_sensory, metric: l2|cosine|hash_hamming}"""
|
| 291 |
+
try:
|
| 292 |
+
body = await request.json()
|
| 293 |
+
except Exception as e:
|
| 294 |
+
return JSONResponse({"error": f"Invalid JSON: {e}"}, status_code=422)
|
| 295 |
+
tick_id = str(body.get("tick_id") or f"tick_{int(time.time()*1000)}")
|
| 296 |
+
predicted = body.get("predicted_sensory", {})
|
| 297 |
+
actual = body.get("actual_sensory", {})
|
| 298 |
+
metric = str(body.get("metric", "cosine")).lower()
|
| 299 |
+
if metric not in ("l2", "cosine", "hash_hamming"):
|
| 300 |
+
metric = "cosine"
|
| 301 |
+
receipt = _STATE.observe(tick_id, predicted, actual, metric)
|
| 302 |
+
return JSONResponse({
|
| 303 |
+
"delta": receipt["delta"],
|
| 304 |
+
"threshold": receipt["threshold_tau"],
|
| 305 |
+
"breach": receipt["breach"],
|
| 306 |
+
"alert_level": receipt["alert_level"],
|
| 307 |
+
"receipt_id": receipt["receipt_id"],
|
| 308 |
+
"consecutive_breaches": receipt["consecutive_breaches"],
|
| 309 |
+
"doctrine_v": DOCTRINE_V,
|
| 310 |
+
"lutar_anchor": LUTAR_ANCHOR,
|
| 311 |
+
})
|
| 312 |
+
|
| 313 |
+
@app.get(f"{base}/status", tags=["conduction"])
|
| 314 |
+
async def conduction_status() -> JSONResponse:
|
| 315 |
+
"""Return current Conduction gate state."""
|
| 316 |
+
return JSONResponse(_STATE.status())
|
| 317 |
+
|
| 318 |
+
@app.get(f"{base}/receipts", tags=["conduction"])
|
| 319 |
+
async def conduction_receipts(limit: int = Query(default=20, le=200)) -> JSONResponse:
|
| 320 |
+
"""Return last N conduction receipts (signed, Khipu-compatible)."""
|
| 321 |
+
recs = _STATE.receipts(limit)
|
| 322 |
+
return JSONResponse({"receipts": recs, "count": len(recs),
|
| 323 |
+
"lutar_anchor": LUTAR_ANCHOR, "doctrine_v": DOCTRINE_V})
|
| 324 |
+
|
| 325 |
+
@app.post(f"{base}/demo", tags=["conduction"])
|
| 326 |
+
async def conduction_demo() -> JSONResponse:
|
| 327 |
+
"""Inject a synthetic high-delta observation (DEMO ONLY)."""
|
| 328 |
+
predicted = [1.0, 0.0, 0.0, 0.5]
|
| 329 |
+
actual = [0.0, 1.0, 1.0, 0.0]
|
| 330 |
+
receipt = _STATE.observe("demo_tick_synthetic", predicted, actual, "cosine")
|
| 331 |
+
return JSONResponse({
|
| 332 |
+
"demo": True,
|
| 333 |
+
"note": "DEMO — synthetic predicted/actual pair injected. Not a real agent tick.",
|
| 334 |
+
"delta": receipt["delta"],
|
| 335 |
+
"breach": receipt["breach"],
|
| 336 |
+
"alert_level": receipt["alert_level"],
|
| 337 |
+
"receipt_id": receipt["receipt_id"],
|
| 338 |
+
"doctrine_v": DOCTRINE_V,
|
| 339 |
+
})
|
| 340 |
+
|
| 341 |
+
@app.get("/conduction", tags=["conduction"], response_class=HTMLResponse)
|
| 342 |
+
async def conduction_html() -> HTMLResponse:
|
| 343 |
+
return HTMLResponse(_CONDUCTION_HTML.replace("__NS__", ns))
|
| 344 |
+
|
| 345 |
+
return {
|
| 346 |
+
"observe": f"POST {base}/observe",
|
| 347 |
+
"status": f"GET {base}/status",
|
| 348 |
+
"receipts": f"GET {base}/receipts",
|
| 349 |
+
"demo": f"POST {base}/demo",
|
| 350 |
+
"ui": "/conduction",
|
| 351 |
+
"lutar_anchor": LUTAR_ANCHOR,
|
| 352 |
+
"doctrine_v": DOCTRINE_V,
|
| 353 |
+
}
|
| 354 |
+
|
| 355 |
+
|
| 356 |
+
# ---------------------------------------------------------------------------
|
| 357 |
+
# /conduction HTML
|
| 358 |
+
# ---------------------------------------------------------------------------
|
| 359 |
+
|
| 360 |
+
_CONDUCTION_HTML = r"""<!DOCTYPE html>
|
| 361 |
+
<html lang="en">
|
| 362 |
+
<head>
|
| 363 |
+
<meta charset="UTF-8">
|
| 364 |
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
| 365 |
+
<title>Conduction-Aphasia Detector · a11oy</title>
|
| 366 |
+
<style>
|
| 367 |
+
*{box-sizing:border-box;margin:0;padding:0}
|
| 368 |
+
:root{
|
| 369 |
+
--bg:#0a0a0a;--card:#111;--border:#222;--accent:#00ff88;--warn:#ffaa00;
|
| 370 |
+
--danger:#ff3333;--dim:#666;--text:#e0e0e0;--mono:'JetBrains Mono','Fira Code','Courier New',monospace;
|
| 371 |
+
}
|
| 372 |
+
body{background:var(--bg);color:var(--text);font-family:var(--mono);font-size:13px;min-height:100vh;padding:20px}
|
| 373 |
+
h1{color:var(--accent);font-size:20px;letter-spacing:2px;margin-bottom:4px}
|
| 374 |
+
.subtitle{color:var(--dim);font-size:11px;margin-bottom:24px}
|
| 375 |
+
.big3{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-bottom:24px}
|
| 376 |
+
.big-card{background:var(--card);border:1px solid var(--border);border-radius:4px;padding:16px;text-align:center}
|
| 377 |
+
.big-label{color:var(--dim);font-size:10px;letter-spacing:2px;text-transform:uppercase;margin-bottom:8px}
|
| 378 |
+
.big-value{font-size:36px;font-weight:700;letter-spacing:1px}
|
| 379 |
+
.big-value.normal{color:var(--accent)}
|
| 380 |
+
.big-value.watching{color:var(--warn)}
|
| 381 |
+
.big-value.conduction_alert{color:var(--danger);animation:pulse 1s infinite}
|
| 382 |
+
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.5}}
|
| 383 |
+
.row2{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:24px}
|
| 384 |
+
.panel{background:var(--card);border:1px solid var(--border);border-radius:4px;padding:16px}
|
| 385 |
+
.panel-title{color:var(--accent);font-size:11px;letter-spacing:2px;text-transform:uppercase;margin-bottom:12px;border-bottom:1px solid var(--border);padding-bottom:8px}
|
| 386 |
+
.diagram-wrap{overflow:auto;padding:8px}
|
| 387 |
+
svg text{font-family:var(--mono);font-size:10px}
|
| 388 |
+
.receipt-table{width:100%;border-collapse:collapse;font-size:11px}
|
| 389 |
+
.receipt-table th{color:var(--dim);text-align:left;padding:4px 6px;border-bottom:1px solid var(--border);font-weight:normal;letter-spacing:1px}
|
| 390 |
+
.receipt-table td{padding:4px 6px;border-bottom:1px solid #1a1a1a;white-space:nowrap}
|
| 391 |
+
.breach-yes{color:var(--danger)}
|
| 392 |
+
.breach-no{color:var(--accent)}
|
| 393 |
+
.al-normal{color:var(--accent)}
|
| 394 |
+
.al-watching{color:var(--warn)}
|
| 395 |
+
.al-conduction_alert{color:var(--danger)}
|
| 396 |
+
.demo-btn{background:transparent;border:1px solid var(--warn);color:var(--warn);
|
| 397 |
+
font-family:var(--mono);font-size:12px;padding:8px 20px;border-radius:3px;
|
| 398 |
+
cursor:pointer;letter-spacing:1px;transition:.2s}
|
| 399 |
+
.demo-btn:hover{background:var(--warn);color:#000}
|
| 400 |
+
.demo-note{color:var(--dim);font-size:10px;margin-top:6px}
|
| 401 |
+
.footer{border-top:1px solid var(--border);margin-top:24px;padding-top:12px;
|
| 402 |
+
color:var(--dim);font-size:10px;line-height:1.8}
|
| 403 |
+
.footer a{color:var(--dim);text-decoration:none}
|
| 404 |
+
.footer a:hover{color:var(--accent)}
|
| 405 |
+
</style>
|
| 406 |
+
</head>
|
| 407 |
+
<body>
|
| 408 |
+
<h1>◯ CONDUCTION-APHASIA DETECTOR</h1>
|
| 409 |
+
<div class="subtitle">a11oy · A37 InternalFeedbackIntegrity · Hickok state feedback control architecture · Doctrine v11</div>
|
| 410 |
+
|
| 411 |
+
<div class="big3">
|
| 412 |
+
<div class="big-card">
|
| 413 |
+
<div class="big-label">Current Alert Level</div>
|
| 414 |
+
<div class="big-value normal" id="b-alert">—</div>
|
| 415 |
+
</div>
|
| 416 |
+
<div class="big-card">
|
| 417 |
+
<div class="big-label">Consecutive Breaches</div>
|
| 418 |
+
<div class="big-value normal" id="b-streak">—</div>
|
| 419 |
+
</div>
|
| 420 |
+
<div class="big-card">
|
| 421 |
+
<div class="big-label">Breaches (24h)</div>
|
| 422 |
+
<div class="big-value normal" id="b-24h">—</div>
|
| 423 |
+
</div>
|
| 424 |
+
</div>
|
| 425 |
+
|
| 426 |
+
<div class="row2">
|
| 427 |
+
<div class="panel">
|
| 428 |
+
<div class="panel-title">Hickok Dual-Stream + Internal Feedback Loop</div>
|
| 429 |
+
<div class="diagram-wrap">
|
| 430 |
+
<svg width="460" height="340" xmlns="http://www.w3.org/2000/svg">
|
| 431 |
+
<defs>
|
| 432 |
+
<marker id="arr" markerWidth="8" markerHeight="8" refX="6" refY="3" orient="auto">
|
| 433 |
+
<path d="M0,0 L0,6 L8,3 z" fill="#666"/>
|
| 434 |
+
</marker>
|
| 435 |
+
<marker id="arr-hl" markerWidth="8" markerHeight="8" refX="6" refY="3" orient="auto">
|
| 436 |
+
<path d="M0,0 L0,6 L8,3 z" fill="#00ff88"/>
|
| 437 |
+
</marker>
|
| 438 |
+
<marker id="arr-red" markerWidth="8" markerHeight="8" refX="6" refY="3" orient="auto">
|
| 439 |
+
<path d="M0,0 L0,6 L8,3 z" fill="#ff3333"/>
|
| 440 |
+
</marker>
|
| 441 |
+
</defs>
|
| 442 |
+
<rect x="110" y="10" width="240" height="32" rx="3" fill="#111" stroke="#444"/>
|
| 443 |
+
<text x="230" y="31" fill="#888" text-anchor="middle">SPECTROTEMPORAL INPUT</text>
|
| 444 |
+
<rect x="110" y="66" width="240" height="32" rx="3" fill="#111" stroke="#444"/>
|
| 445 |
+
<text x="230" y="87" fill="#888" text-anchor="middle">PHONOLOGICAL NETWORK</text>
|
| 446 |
+
<line x1="230" y1="42" x2="230" y2="66" stroke="#444" stroke-width="1.5" marker-end="url(#arr)"/>
|
| 447 |
+
<line x1="170" y1="98" x2="130" y2="118" stroke="#444" stroke-width="1.5" marker-end="url(#arr)"/>
|
| 448 |
+
<line x1="290" y1="98" x2="330" y2="118" stroke="#444" stroke-width="1.5" marker-end="url(#arr)"/>
|
| 449 |
+
<rect x="10" y="118" width="170" height="70" rx="3" fill="#0d1a12" stroke="#2a5a3a"/>
|
| 450 |
+
<text x="95" y="137" fill="#2a8a4a" text-anchor="middle" font-size="9">DORSAL STREAM</text>
|
| 451 |
+
<text x="95" y="152" fill="#666" text-anchor="middle">Sensorimotor Interface</text>
|
| 452 |
+
<text x="95" y="167" fill="#666" text-anchor="middle">Area Spt (PAC-Bayes)</text>
|
| 453 |
+
<text x="95" y="180" fill="#666" text-anchor="middle">/api/a11oy/v4/predict</text>
|
| 454 |
+
<rect x="280" y="118" width="170" height="70" rx="3" fill="#0d0d1a" stroke="#2a2a5a"/>
|
| 455 |
+
<text x="365" y="137" fill="#2a2a8a" text-anchor="middle" font-size="9">VENTRAL STREAM</text>
|
| 456 |
+
<text x="365" y="152" fill="#666" text-anchor="middle">Lexical Interface</text>
|
| 457 |
+
<text x="365" y="167" fill="#666" text-anchor="middle">pMTG / pITS</text>
|
| 458 |
+
<text x="365" y="180" fill="#666" text-anchor="middle">meaning / comprehension</text>
|
| 459 |
+
<rect x="110" y="210" width="240" height="38" rx="3" fill="#001a0a" stroke="#00ff88" stroke-width="2"/>
|
| 460 |
+
<text x="230" y="226" fill="#00ff88" text-anchor="middle" font-size="10">FORWARD MODEL (predicted sensory)</text>
|
| 461 |
+
<text x="230" y="241" fill="#00aa55" text-anchor="middle" font-size="9">Lambda predicted consequence before action</text>
|
| 462 |
+
<line x1="95" y1="188" x2="170" y2="210" stroke="#2a5a3a" stroke-width="1.5" marker-end="url(#arr)"/>
|
| 463 |
+
<rect x="110" y="268" width="240" height="38" rx="3" fill="#1a0000" stroke="#ff3333" stroke-width="2"/>
|
| 464 |
+
<text x="230" y="284" fill="#ff3333" text-anchor="middle" font-size="10">CONDUCTION GATE (A37)</text>
|
| 465 |
+
<text x="230" y="299" fill="#aa2222" text-anchor="middle" font-size="9">||predicted - actual|| > tau ALERT</text>
|
| 466 |
+
<path d="M 230 248 L 230 268" stroke="#00ff88" stroke-width="2" marker-end="url(#arr-hl)"/>
|
| 467 |
+
<path d="M 450 283 L 350 283" stroke="#ff3333" stroke-width="2" stroke-dasharray="4,3" marker-end="url(#arr-red)"/>
|
| 468 |
+
<text x="452" y="280" fill="#ff3333" font-size="9">actual</text>
|
| 469 |
+
<text x="452" y="290" fill="#ff3333" font-size="9">sensory</text>
|
| 470 |
+
<text x="14" y="260" fill="#00ff88" font-size="9">internal</text>
|
| 471 |
+
<text x="14" y="272" fill="#00ff88" font-size="9">feedback</text>
|
| 472 |
+
<text x="14" y="284" fill="#00ff88" font-size="9">loop</text>
|
| 473 |
+
<path d="M 55 270 L 110 283" stroke="#00ff88" stroke-width="1" stroke-dasharray="3,2" marker-end="url(#arr-hl)"/>
|
| 474 |
+
</svg>
|
| 475 |
+
</div>
|
| 476 |
+
</div>
|
| 477 |
+
|
| 478 |
+
<div class="panel">
|
| 479 |
+
<div class="panel-title">Demo Divergence Injector</div>
|
| 480 |
+
<p style="color:#666;margin-bottom:12px;font-size:11px">
|
| 481 |
+
Inject a synthetic predicted→actual mismatch to demonstrate the Conduction Alert.
|
| 482 |
+
Predicted: [1.0, 0.0, 0.0, 0.5] · Actual: [0.0, 1.0, 1.0, 0.0]
|
| 483 |
+
</p>
|
| 484 |
+
<button class="demo-btn" onclick="injectDemo()">▶ Trigger Demo Divergence</button>
|
| 485 |
+
<div class="demo-note">⚠ DEMO ONLY — clearly labelled synthetic pair, not a real agent tick.</div>
|
| 486 |
+
<div id="demo-result" style="margin-top:12px;font-size:11px;color:#666"></div>
|
| 487 |
+
|
| 488 |
+
<div style="margin-top:20px">
|
| 489 |
+
<div class="panel-title" style="margin-top:0">Gate Parameters</div>
|
| 490 |
+
<table style="font-size:11px;width:100%">
|
| 491 |
+
<tr><td style="color:#666;padding:3px 0">Threshold τ</td><td id="p-tau" style="color:#e0e0e0">—</td></tr>
|
| 492 |
+
<tr><td style="color:#666;padding:3px 0">Window N</td><td id="p-window" style="color:#e0e0e0">—</td></tr>
|
| 493 |
+
<tr><td style="color:#666;padding:3px 0">Last Alert</td><td id="p-last-alert" style="color:#e0e0e0">—</td></tr>
|
| 494 |
+
<tr><td style="color:#666;padding:3px 0">Lutar anchor</td><td style="color:#00ff88">A37 InternalFeedbackIntegrity</td></tr>
|
| 495 |
+
<tr><td style="color:#666;padding:3px 0">Doctrine</td><td style="color:#888">v11 LOCKED 749/14/163</td></tr>
|
| 496 |
+
</table>
|
| 497 |
+
</div>
|
| 498 |
+
</div>
|
| 499 |
+
</div>
|
| 500 |
+
|
| 501 |
+
<div class="panel" style="margin-bottom:16px">
|
| 502 |
+
<div class="panel-title">Live Receipt Tail (last 20 · auto-refresh 5s)
|
| 503 |
+
<span id="status-ts" style="float:right;font-size:10px;color:#444">refreshing…</span>
|
| 504 |
+
</div>
|
| 505 |
+
<table class="receipt-table">
|
| 506 |
+
<thead>
|
| 507 |
+
<tr>
|
| 508 |
+
<th>receipt_id</th><th>tick_id</th><th>delta</th><th>metric</th>
|
| 509 |
+
<th>breach</th><th>alert_level</th><th>consecutive</th><th>ts</th>
|
| 510 |
+
</tr>
|
| 511 |
+
</thead>
|
| 512 |
+
<tbody id="receipt-tbody">
|
| 513 |
+
<tr><td colspan="8" style="color:#444;text-align:center;padding:12px">No receipts yet — waiting for observations…</td></tr>
|
| 514 |
+
</tbody>
|
| 515 |
+
</table>
|
| 516 |
+
</div>
|
| 517 |
+
|
| 518 |
+
<div class="footer">
|
| 519 |
+
<div>A37 InternalFeedbackIntegrity · Citation: Hickok, Houde, Rong 2011, Neuron 69:407–422 · <a href="https://doi.org/10.1016/j.neuron.2011.01.019">DOI 10.1016/j.neuron.2011.01.019</a></div>
|
| 520 |
+
<div>Dual-stream: Hickok & Poeppel 2007, Nat Rev Neurosci 8:393–402 · <a href="https://doi.org/10.1038/nrn2113">DOI 10.1038/nrn2113</a></div>
|
| 521 |
+
<div>Doctrine v11 LOCKED · 749 declarations / 14 axioms / 163 sorries · Λ = Conjecture 1 (NOT a theorem) · SLSA L1 honest · Sovereign-default</div>
|
| 522 |
+
<div style="margin-top:4px">© 2026 SZL Holdings · Authored by Yachay (CTO) · Co-Authored-By: Perplexity Computer Agent</div>
|
| 523 |
+
</div>
|
| 524 |
+
|
| 525 |
+
<script>
|
| 526 |
+
const BASE = '/api/__NS__/v4/conduction';
|
| 527 |
+
function alertClass(l){return l==='conduction_alert'?'conduction_alert':l==='watching'?'watching':'normal'}
|
| 528 |
+
function alLabel(l){return l==='conduction_alert'?'CONDUCTION_ALERT':l==='watching'?'WATCHING':'normal'}
|
| 529 |
+
async function fetchStatus(){
|
| 530 |
+
try{
|
| 531 |
+
const d=await(await fetch(BASE+'/status')).json();
|
| 532 |
+
const al=d.current_alert_level||'normal';
|
| 533 |
+
const el=document.getElementById('b-alert');
|
| 534 |
+
el.textContent=alLabel(al); el.className='big-value '+alertClass(al);
|
| 535 |
+
document.getElementById('b-streak').textContent=d.consecutive_breaches??0;
|
| 536 |
+
document.getElementById('b-24h').textContent=d.breaches_24h??0;
|
| 537 |
+
document.getElementById('p-tau').textContent=d.threshold_tau??'--';
|
| 538 |
+
document.getElementById('p-window').textContent=d.window_size??'--';
|
| 539 |
+
document.getElementById('p-last-alert').textContent=d.last_alert_at||'none';
|
| 540 |
+
document.getElementById('status-ts').textContent='updated '+new Date().toLocaleTimeString();
|
| 541 |
+
}catch(e){console.error(e)}
|
| 542 |
+
}
|
| 543 |
+
async function fetchReceipts(){
|
| 544 |
+
try{
|
| 545 |
+
const d=await(await fetch(BASE+'/receipts?limit=20')).json();
|
| 546 |
+
const rows=d.receipts||[];
|
| 547 |
+
const tb=document.getElementById('receipt-tbody');
|
| 548 |
+
if(!rows.length){tb.innerHTML='<tr><td colspan="8" style="color:#444;text-align:center;padding:12px">No receipts yet</td></tr>';return}
|
| 549 |
+
function esc(s){return String(s).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>')}
|
| 550 |
+
tb.innerHTML=rows.map(r=>`<tr>
|
| 551 |
+
<td style="color:#555">${esc((r.receipt_id||'').slice(0,18))}...</td>
|
| 552 |
+
<td>${esc(r.tick_id||'')}</td>
|
| 553 |
+
<td>${typeof r.delta==='number'?r.delta.toFixed(4):'--'}</td>
|
| 554 |
+
<td>${esc(r.metric||'')}</td>
|
| 555 |
+
<td class="${r.breach?'breach-yes':'breach-no'}">${r.breach?'YES':'no'}</td>
|
| 556 |
+
<td class="al-${esc(r.alert_level||'normal')}">${esc(r.alert_level||'')}</td>
|
| 557 |
+
<td>${r.consecutive_breaches??0}</td>
|
| 558 |
+
<td style="color:#555">${(r.ts||'').slice(11,19)}</td>
|
| 559 |
+
</tr>`).join('');
|
| 560 |
+
}catch(e){console.error(e)}
|
| 561 |
+
}
|
| 562 |
+
async function injectDemo(){
|
| 563 |
+
const btn=document.querySelector('.demo-btn');
|
| 564 |
+
btn.disabled=true; btn.textContent='... injecting ...';
|
| 565 |
+
try{
|
| 566 |
+
const d=await(await fetch(BASE+'/demo',{method:'POST'})).json();
|
| 567 |
+
document.getElementById('demo-result').innerHTML=
|
| 568 |
+
`<span style="color:#ffaa00">DEMO injected</span> delta=${d.delta?.toFixed(4)} breach=${d.breach} alert=${d.alert_level} id=${d.receipt_id}`;
|
| 569 |
+
await fetchStatus(); await fetchReceipts();
|
| 570 |
+
}catch(e){document.getElementById('demo-result').textContent='Error: '+e}
|
| 571 |
+
finally{btn.disabled=false;btn.textContent='Trigger Demo Divergence'}
|
| 572 |
+
}
|
| 573 |
+
function refresh(){fetchStatus();fetchReceipts()}
|
| 574 |
+
refresh(); setInterval(refresh,5000);
|
| 575 |
+
</script>
|
| 576 |
+
</body>
|
| 577 |
+
</html>"""
|
szl_a11oy_live_feeds.py
ADDED
|
@@ -0,0 +1,383 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 2 |
+
# © 2026 Lutar, Stephen P. — SZL Holdings · ORCID 0009-0001-0110-4173 · Doctrine v11
|
| 3 |
+
# Authored by A11oy Full-Stack Team (live-feed + research instillation).
|
| 4 |
+
# Co-Authored-By: Perplexity Computer Agent.
|
| 5 |
+
"""szl_a11oy_live_feeds — ADDITIVE server-side live public-data feeds for a11oy.
|
| 6 |
+
|
| 7 |
+
MAXIMUM LIVE DATA, sovereign-safe. Every feed is fetched SERVER-SIDE in the
|
| 8 |
+
FastAPI backend (single egress, avoids browser CORS), cached briefly in-process,
|
| 9 |
+
and LABELLED with source + fetched-at timestamp. If a feed is unreachable at
|
| 10 |
+
request time we fall back to a clearly-labelled last-known/sample payload —
|
| 11 |
+
NEVER fabricated, always marked `live: false` + `source_status`.
|
| 12 |
+
|
| 13 |
+
SOVEREIGNTY: these are live DATA fetches to public APIs (data, NOT CDN-loaded
|
| 14 |
+
code). 0 runtime CDN for libs/assets is preserved — the frontend loads only the
|
| 15 |
+
vendored /static-vendor/* libraries.
|
| 16 |
+
|
| 17 |
+
Free public feeds wired (no key):
|
| 18 |
+
CVE NVD 2.0 https://services.nvd.nist.gov/rest/json/cves/2.0
|
| 19 |
+
KEV CISA https://raw.githubusercontent.com/cisagov/kev-data/develop/known_exploited_vulnerabilities.json
|
| 20 |
+
RESEARCH arXiv http://export.arxiv.org/api/query
|
| 21 |
+
Key-gated upgrades are surfaced as explicit "needs API key" placeholders.
|
| 22 |
+
|
| 23 |
+
MITRE ATT&CK is intentionally VENDORED in-image (enterprise-attack STIX) by the
|
| 24 |
+
attack tab to keep 0-CDN; this module exposes a manifest endpoint that points at
|
| 25 |
+
the vendored copy and notes the optional online STIX source.
|
| 26 |
+
|
| 27 |
+
Endpoints (mounted BEFORE the SPA catch-all in serve.py):
|
| 28 |
+
GET /api/a11oy/v1/live/cve[?keyword=&limit=] NVD 2.0 recent/queried CVEs (LIVE)
|
| 29 |
+
GET /api/a11oy/v1/live/kev[?limit=] CISA KEV catalogue (LIVE)
|
| 30 |
+
GET /api/a11oy/v1/live/arxiv[?q=&limit=] arXiv papers (LIVE)
|
| 31 |
+
GET /api/a11oy/v1/live/feeds manifest: every feed, status, key-gating
|
| 32 |
+
GET /api/a11oy/v1/research/corpus consolidated research/knowledge (knowledge.json-backed)
|
| 33 |
+
"""
|
| 34 |
+
from __future__ import annotations
|
| 35 |
+
|
| 36 |
+
import json
|
| 37 |
+
import time
|
| 38 |
+
import urllib.parse as _up
|
| 39 |
+
import urllib.request as _ur
|
| 40 |
+
import xml.etree.ElementTree as _ET
|
| 41 |
+
from datetime import datetime, timezone
|
| 42 |
+
from pathlib import Path
|
| 43 |
+
from typing import Any
|
| 44 |
+
|
| 45 |
+
from fastapi import FastAPI
|
| 46 |
+
from fastapi.responses import JSONResponse
|
| 47 |
+
|
| 48 |
+
_UA = "SZL-a11oy/1.0 (sovereign command platform; contact@szlholdings.ai)"
|
| 49 |
+
_TIMEOUT = 8.0
|
| 50 |
+
|
| 51 |
+
# ---------------------------------------------------------------------------
|
| 52 |
+
# Tiny in-process TTL cache (brief). No external store, no CDN.
|
| 53 |
+
# ---------------------------------------------------------------------------
|
| 54 |
+
_CACHE: dict[str, tuple[float, Any]] = {}
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
def _cache_get(key: str, ttl: float) -> Any | None:
|
| 58 |
+
hit = _CACHE.get(key)
|
| 59 |
+
if hit and (time.time() - hit[0]) < ttl:
|
| 60 |
+
return hit[1]
|
| 61 |
+
return None
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
def _cache_put(key: str, value: Any) -> None:
|
| 65 |
+
_CACHE[key] = (time.time(), value)
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
def _now() -> str:
|
| 69 |
+
return datetime.now(timezone.utc).isoformat()
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
def _get_json(url: str, headers: dict | None = None) -> Any:
|
| 73 |
+
req = _ur.Request(url, headers={"User-Agent": _UA, **(headers or {})})
|
| 74 |
+
with _ur.urlopen(req, timeout=_TIMEOUT) as resp:
|
| 75 |
+
return json.loads(resp.read().decode("utf-8", "replace"))
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
def _get_text(url: str, headers: dict | None = None) -> str:
|
| 79 |
+
req = _ur.Request(url, headers={"User-Agent": _UA, **(headers or {})})
|
| 80 |
+
with _ur.urlopen(req, timeout=_TIMEOUT) as resp:
|
| 81 |
+
return resp.read().decode("utf-8", "replace")
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
# ===========================================================================
|
| 85 |
+
# CVE — NVD 2.0 (FREE, key optional for higher rate)
|
| 86 |
+
# ===========================================================================
|
| 87 |
+
_CVE_SAMPLE = [
|
| 88 |
+
{"id": "CVE-2024-3094", "severity": "CRITICAL", "cvss": 10.0,
|
| 89 |
+
"desc": "xz/liblzma backdoor (sshd RCE via malicious upstream release).",
|
| 90 |
+
"published": "2024-03-29"},
|
| 91 |
+
{"id": "CVE-2021-44228", "severity": "CRITICAL", "cvss": 10.0,
|
| 92 |
+
"desc": "Apache Log4j2 JNDI lookup RCE (Log4Shell).",
|
| 93 |
+
"published": "2021-12-10"},
|
| 94 |
+
]
|
| 95 |
+
|
| 96 |
+
|
| 97 |
+
def fetch_cve(keyword: str = "", limit: int = 20) -> dict[str, Any]:
|
| 98 |
+
limit = max(1, min(int(limit), 50))
|
| 99 |
+
ck = f"cve:{keyword}:{limit}"
|
| 100 |
+
cached = _cache_get(ck, ttl=300)
|
| 101 |
+
if cached:
|
| 102 |
+
return {**cached, "cached": True}
|
| 103 |
+
base = "https://services.nvd.nist.gov/rest/json/cves/2.0"
|
| 104 |
+
params = {"resultsPerPage": limit}
|
| 105 |
+
if keyword.strip():
|
| 106 |
+
params["keywordSearch"] = keyword.strip()
|
| 107 |
+
url = base + "?" + _up.urlencode(params)
|
| 108 |
+
try:
|
| 109 |
+
raw = _get_json(url)
|
| 110 |
+
items = []
|
| 111 |
+
for v in (raw.get("vulnerabilities", []) or [])[:limit]:
|
| 112 |
+
cve = v.get("cve", {})
|
| 113 |
+
metrics = cve.get("metrics", {})
|
| 114 |
+
cvss = None
|
| 115 |
+
sev = None
|
| 116 |
+
for mk in ("cvssMetricV31", "cvssMetricV30", "cvssMetricV2"):
|
| 117 |
+
if metrics.get(mk):
|
| 118 |
+
cd = metrics[mk][0].get("cvssData", {})
|
| 119 |
+
cvss = cd.get("baseScore")
|
| 120 |
+
sev = cd.get("baseSeverity") or metrics[mk][0].get("baseSeverity")
|
| 121 |
+
break
|
| 122 |
+
descs = cve.get("descriptions", [])
|
| 123 |
+
desc = next((d["value"] for d in descs if d.get("lang") == "en"),
|
| 124 |
+
descs[0]["value"] if descs else "")
|
| 125 |
+
items.append({
|
| 126 |
+
"id": cve.get("id"), "severity": sev, "cvss": cvss,
|
| 127 |
+
"desc": desc[:280], "published": (cve.get("published") or "")[:10],
|
| 128 |
+
})
|
| 129 |
+
out = {
|
| 130 |
+
"ok": True, "live": True, "source": "NVD 2.0 (NIST, public domain)",
|
| 131 |
+
"source_url": base, "fetched_at": _now(), "source_status": "200",
|
| 132 |
+
"query": keyword or "(recent)", "count": len(items), "cves": items,
|
| 133 |
+
}
|
| 134 |
+
_cache_put(ck, out)
|
| 135 |
+
return out
|
| 136 |
+
except Exception as e:
|
| 137 |
+
return {
|
| 138 |
+
"ok": True, "live": False, "source": "NVD 2.0 (NIST) — UNREACHABLE, labelled sample",
|
| 139 |
+
"source_url": base, "fetched_at": _now(), "source_status": str(e)[:90],
|
| 140 |
+
"query": keyword or "(recent)", "count": len(_CVE_SAMPLE),
|
| 141 |
+
"cves": _CVE_SAMPLE,
|
| 142 |
+
"note": "Live NVD feed unreachable; showing clearly-labelled SAMPLE CVEs (not live).",
|
| 143 |
+
}
|
| 144 |
+
|
| 145 |
+
|
| 146 |
+
# ===========================================================================
|
| 147 |
+
# KEV — CISA Known Exploited Vulnerabilities (FREE)
|
| 148 |
+
# ===========================================================================
|
| 149 |
+
_KEV_SAMPLE = [
|
| 150 |
+
{"cveID": "CVE-2021-44228", "vendorProject": "Apache", "product": "Log4j2",
|
| 151 |
+
"vulnerabilityName": "Apache Log4j2 RCE (Log4Shell)", "dateAdded": "2021-12-10",
|
| 152 |
+
"knownRansomwareCampaignUse": "Known"},
|
| 153 |
+
{"cveID": "CVE-2023-4863", "vendorProject": "Google", "product": "Chrome libwebp",
|
| 154 |
+
"vulnerabilityName": "WebP heap buffer overflow", "dateAdded": "2023-09-13",
|
| 155 |
+
"knownRansomwareCampaignUse": "Unknown"},
|
| 156 |
+
]
|
| 157 |
+
|
| 158 |
+
|
| 159 |
+
def fetch_kev(limit: int = 40) -> dict[str, Any]:
|
| 160 |
+
limit = max(1, min(int(limit), 200))
|
| 161 |
+
ck = f"kev:{limit}"
|
| 162 |
+
cached = _cache_get(ck, ttl=900)
|
| 163 |
+
if cached:
|
| 164 |
+
return {**cached, "cached": True}
|
| 165 |
+
url = ("https://raw.githubusercontent.com/cisagov/kev-data/develop/"
|
| 166 |
+
"known_exploited_vulnerabilities.json")
|
| 167 |
+
try:
|
| 168 |
+
raw = _get_json(url)
|
| 169 |
+
vulns = raw.get("vulnerabilities", []) or []
|
| 170 |
+
# most-recent first by dateAdded
|
| 171 |
+
vulns = sorted(vulns, key=lambda x: x.get("dateAdded", ""), reverse=True)
|
| 172 |
+
items = [{
|
| 173 |
+
"cveID": v.get("cveID"), "vendorProject": v.get("vendorProject"),
|
| 174 |
+
"product": v.get("product"), "vulnerabilityName": v.get("vulnerabilityName"),
|
| 175 |
+
"dateAdded": v.get("dateAdded"),
|
| 176 |
+
"knownRansomwareCampaignUse": v.get("knownRansomwareCampaignUse"),
|
| 177 |
+
} for v in vulns[:limit]]
|
| 178 |
+
out = {
|
| 179 |
+
"ok": True, "live": True,
|
| 180 |
+
"source": "CISA KEV (Known Exploited Vulnerabilities, public domain)",
|
| 181 |
+
"source_url": url, "fetched_at": _now(), "source_status": "200",
|
| 182 |
+
"catalog_version": raw.get("catalogVersion"),
|
| 183 |
+
"total_in_catalog": raw.get("count", len(vulns)),
|
| 184 |
+
"count": len(items), "kev": items,
|
| 185 |
+
}
|
| 186 |
+
_cache_put(ck, out)
|
| 187 |
+
return out
|
| 188 |
+
except Exception as e:
|
| 189 |
+
return {
|
| 190 |
+
"ok": True, "live": False,
|
| 191 |
+
"source": "CISA KEV — UNREACHABLE, labelled sample",
|
| 192 |
+
"source_url": url, "fetched_at": _now(), "source_status": str(e)[:90],
|
| 193 |
+
"count": len(_KEV_SAMPLE), "kev": _KEV_SAMPLE,
|
| 194 |
+
"note": "Live CISA KEV feed unreachable; showing clearly-labelled SAMPLE entries (not live).",
|
| 195 |
+
}
|
| 196 |
+
|
| 197 |
+
|
| 198 |
+
# ===========================================================================
|
| 199 |
+
# RESEARCH — arXiv API (FREE, Atom XML)
|
| 200 |
+
# ===========================================================================
|
| 201 |
+
_ARXIV_NS = {"a": "http://www.w3.org/2005/Atom"}
|
| 202 |
+
_ARXIV_SAMPLE = [
|
| 203 |
+
{"id": "2009.03167", "title": "Time-uniform, nonparametric, nonasymptotic confidence sequences",
|
| 204 |
+
"authors": "Howard, Ramdas, McAuliffe, Sekhon", "published": "2020-09-07",
|
| 205 |
+
"url": "https://arxiv.org/abs/2009.03167"},
|
| 206 |
+
{"id": "2303.04500", "title": "Transparency logs / Merkle inclusion soundness (survey)",
|
| 207 |
+
"authors": "various", "published": "2023-03-08",
|
| 208 |
+
"url": "https://arxiv.org/abs/2303.04500"},
|
| 209 |
+
]
|
| 210 |
+
|
| 211 |
+
|
| 212 |
+
def fetch_arxiv(q: str = "formal verification temporal logic", limit: int = 10) -> dict[str, Any]:
|
| 213 |
+
limit = max(1, min(int(limit), 30))
|
| 214 |
+
ck = f"arxiv:{q}:{limit}"
|
| 215 |
+
cached = _cache_get(ck, ttl=900)
|
| 216 |
+
if cached:
|
| 217 |
+
return {**cached, "cached": True}
|
| 218 |
+
base = "http://export.arxiv.org/api/query"
|
| 219 |
+
url = base + "?" + _up.urlencode({
|
| 220 |
+
"search_query": f"all:{q}", "start": 0, "max_results": limit,
|
| 221 |
+
"sortBy": "submittedDate", "sortOrder": "descending",
|
| 222 |
+
})
|
| 223 |
+
try:
|
| 224 |
+
xml = _get_text(url)
|
| 225 |
+
root = _ET.fromstring(xml)
|
| 226 |
+
papers = []
|
| 227 |
+
for e in root.findall("a:entry", _ARXIV_NS):
|
| 228 |
+
aid = (e.findtext("a:id", "", _ARXIV_NS) or "").rsplit("/", 1)[-1]
|
| 229 |
+
title = " ".join((e.findtext("a:title", "", _ARXIV_NS) or "").split())
|
| 230 |
+
authors = ", ".join(
|
| 231 |
+
(a.findtext("a:name", "", _ARXIV_NS) or "")
|
| 232 |
+
for a in e.findall("a:author", _ARXIV_NS))
|
| 233 |
+
published = (e.findtext("a:published", "", _ARXIV_NS) or "")[:10]
|
| 234 |
+
link = e.findtext("a:id", "", _ARXIV_NS) or ""
|
| 235 |
+
papers.append({"id": aid, "title": title, "authors": authors,
|
| 236 |
+
"published": published, "url": link})
|
| 237 |
+
out = {
|
| 238 |
+
"ok": True, "live": True, "source": "arXiv API (Cornell, free)",
|
| 239 |
+
"source_url": base, "fetched_at": _now(), "source_status": "200",
|
| 240 |
+
"query": q, "count": len(papers), "papers": papers,
|
| 241 |
+
}
|
| 242 |
+
_cache_put(ck, out)
|
| 243 |
+
return out
|
| 244 |
+
except Exception as e:
|
| 245 |
+
return {
|
| 246 |
+
"ok": True, "live": False, "source": "arXiv API — UNREACHABLE, labelled sample",
|
| 247 |
+
"source_url": base, "fetched_at": _now(), "source_status": str(e)[:90],
|
| 248 |
+
"query": q, "count": len(_ARXIV_SAMPLE), "papers": _ARXIV_SAMPLE,
|
| 249 |
+
"note": "Live arXiv feed unreachable; showing clearly-labelled SAMPLE papers (not live).",
|
| 250 |
+
}
|
| 251 |
+
|
| 252 |
+
|
| 253 |
+
# ===========================================================================
|
| 254 |
+
# Feed manifest (free vs key-gated) — honest disclosure for the UI
|
| 255 |
+
# ===========================================================================
|
| 256 |
+
def feeds_manifest() -> dict[str, Any]:
|
| 257 |
+
return {
|
| 258 |
+
"doctrine": "v11", "fetched_at": _now(),
|
| 259 |
+
"sovereignty": ("0 runtime CDN for libs/assets. These are live DATA fetches "
|
| 260 |
+
"to public APIs (data, not code), done server-side (single "
|
| 261 |
+
"egress, no browser CORS), cached briefly, labelled source+ts."),
|
| 262 |
+
"free": [
|
| 263 |
+
{"id": "cve", "name": "NVD 2.0 CVE", "endpoint": "/api/a11oy/v1/live/cve",
|
| 264 |
+
"source": "https://services.nvd.nist.gov/rest/json/cves/2.0",
|
| 265 |
+
"key": "optional (higher rate)", "license": "public domain"},
|
| 266 |
+
{"id": "kev", "name": "CISA KEV", "endpoint": "/api/a11oy/v1/live/kev",
|
| 267 |
+
"source": "https://raw.githubusercontent.com/cisagov/kev-data/develop/known_exploited_vulnerabilities.json",
|
| 268 |
+
"key": "none", "license": "public domain"},
|
| 269 |
+
{"id": "arxiv", "name": "arXiv research", "endpoint": "/api/a11oy/v1/live/arxiv",
|
| 270 |
+
"source": "http://export.arxiv.org/api/query", "key": "none", "license": "arXiv terms"},
|
| 271 |
+
{"id": "attack", "name": "MITRE ATT&CK (enterprise STIX)",
|
| 272 |
+
"endpoint": "(vendored in-image for 0-CDN)",
|
| 273 |
+
"source": "https://raw.githubusercontent.com/mitre-attack/attack-stix-data/master/enterprise-attack/enterprise-attack.json",
|
| 274 |
+
"key": "none", "license": "MITRE ATT&CK terms",
|
| 275 |
+
"note": "vendored in-image to keep 0 runtime CDN; online STIX is the upstream source"},
|
| 276 |
+
],
|
| 277 |
+
"needs_api_key": [
|
| 278 |
+
{"id": "aisstream", "name": "AISStream.io global AIS (wss)",
|
| 279 |
+
"source": "https://aisstream.io", "status": "needs API key — placeholder only"},
|
| 280 |
+
{"id": "adsbexchange", "name": "ADSBexchange premium ADS-B",
|
| 281 |
+
"source": "https://www.adsbexchange.com/data/", "status": "needs API key — placeholder only"},
|
| 282 |
+
{"id": "semanticscholar", "name": "Semantic Scholar Graph API",
|
| 283 |
+
"source": "https://api.semanticscholar.org", "status": "key optional — placeholder for higher rate"},
|
| 284 |
+
],
|
| 285 |
+
}
|
| 286 |
+
|
| 287 |
+
|
| 288 |
+
# ===========================================================================
|
| 289 |
+
# Consolidated RESEARCH / KNOWLEDGE corpus — knowledge.json-backed (REAL content)
|
| 290 |
+
# ===========================================================================
|
| 291 |
+
def _load_knowledge() -> dict[str, Any]:
|
| 292 |
+
for cand in ("knowledge.json", "/app/knowledge.json",
|
| 293 |
+
str(Path(__file__).parent / "knowledge.json")):
|
| 294 |
+
try:
|
| 295 |
+
with open(cand, encoding="utf-8") as f:
|
| 296 |
+
return json.load(f)
|
| 297 |
+
except Exception:
|
| 298 |
+
continue
|
| 299 |
+
return {}
|
| 300 |
+
|
| 301 |
+
|
| 302 |
+
def research_corpus() -> dict[str, Any]:
|
| 303 |
+
"""ONE consolidated research/knowledge surface, pulled from the REAL
|
| 304 |
+
knowledge.json corpus (no fabrication). Surfaces the thesis/formula/theorem/
|
| 305 |
+
DOI/zenodo corpus + honest proof tiers in a single response so the UI does
|
| 306 |
+
not need to sprawl across kbformulas/knowledge/ontology."""
|
| 307 |
+
k = _load_knowledge()
|
| 308 |
+
if not k:
|
| 309 |
+
return {"ok": False, "error": "knowledge.json not found in image",
|
| 310 |
+
"note": "no fabrication — corpus unavailable"}
|
| 311 |
+
ps = k.get("proof_summary", {})
|
| 312 |
+
return {
|
| 313 |
+
"ok": True,
|
| 314 |
+
"source": "knowledge.json (a11oy in-image corpus — REAL)",
|
| 315 |
+
"version": k.get("version"), "byline": k.get("byline"),
|
| 316 |
+
"orcid": k.get("orcid"), "org": k.get("org"),
|
| 317 |
+
"generated_at": k.get("generated_at"), "fetched_at": _now(),
|
| 318 |
+
"honest_tiers": {
|
| 319 |
+
"locked_proven": ps.get("locked_proven"),
|
| 320 |
+
"locked_ids": ps.get("locked_ids"),
|
| 321 |
+
"experimental_sorry_free": ps.get("experimental_sorry_free"),
|
| 322 |
+
"axiom_gated": ps.get("axiom_gated"),
|
| 323 |
+
"conjecture": ps.get("conjecture"),
|
| 324 |
+
"lambda_status": "F23 = Conjecture 1 (NEVER a theorem)",
|
| 325 |
+
"note": ps.get("note"),
|
| 326 |
+
"lean_repo": ps.get("lean_repo"),
|
| 327 |
+
},
|
| 328 |
+
"counts": {
|
| 329 |
+
"axioms": len(k.get("axioms", [])),
|
| 330 |
+
"theorems": len(k.get("theorems", [])),
|
| 331 |
+
"formulas": len(k.get("formulas", [])),
|
| 332 |
+
"puriq_formulas": len(k.get("puriq_formulas", [])),
|
| 333 |
+
"canonical_constants": len(k.get("canonical_constants", [])),
|
| 334 |
+
"dois": len(k.get("dois", [])),
|
| 335 |
+
"doctrine_clauses": len(k.get("doctrine_clauses", [])),
|
| 336 |
+
"vertical_policies": len(k.get("vertical_policies", [])),
|
| 337 |
+
},
|
| 338 |
+
"axioms": k.get("axioms", []),
|
| 339 |
+
"theorems": k.get("theorems", []),
|
| 340 |
+
"puriq_formulas": k.get("puriq_formulas", []),
|
| 341 |
+
"canonical_constants": k.get("canonical_constants", []),
|
| 342 |
+
"dois": k.get("dois", []),
|
| 343 |
+
"zenodo_corpus": k.get("zenodo_corpus", []),
|
| 344 |
+
"doctrine_clauses": k.get("doctrine_clauses", []),
|
| 345 |
+
"source_files": k.get("source_files", []),
|
| 346 |
+
"instill_wave": k.get("instill_wave"),
|
| 347 |
+
}
|
| 348 |
+
|
| 349 |
+
|
| 350 |
+
# ---------------------------------------------------------------------------
|
| 351 |
+
def register(app: FastAPI, ns: str = "a11oy") -> str:
|
| 352 |
+
base = f"/api/{ns}/v1"
|
| 353 |
+
|
| 354 |
+
@app.get(f"{base}/live/cve", include_in_schema=False)
|
| 355 |
+
async def _cve(keyword: str = "", limit: int = 20) -> JSONResponse: # noqa: ANN202
|
| 356 |
+
return JSONResponse(fetch_cve(keyword, limit))
|
| 357 |
+
|
| 358 |
+
@app.get(f"{base}/live/kev", include_in_schema=False)
|
| 359 |
+
async def _kev(limit: int = 40) -> JSONResponse: # noqa: ANN202
|
| 360 |
+
return JSONResponse(fetch_kev(limit))
|
| 361 |
+
|
| 362 |
+
@app.get(f"{base}/live/arxiv", include_in_schema=False)
|
| 363 |
+
async def _arxiv(q: str = "formal verification temporal logic",
|
| 364 |
+
limit: int = 10) -> JSONResponse: # noqa: ANN202
|
| 365 |
+
return JSONResponse(fetch_arxiv(q, limit))
|
| 366 |
+
|
| 367 |
+
@app.get(f"{base}/live/feeds", include_in_schema=False)
|
| 368 |
+
async def _feeds() -> JSONResponse: # noqa: ANN202
|
| 369 |
+
return JSONResponse(feeds_manifest())
|
| 370 |
+
|
| 371 |
+
@app.get(f"{base}/research/corpus", include_in_schema=False)
|
| 372 |
+
async def _corpus() -> JSONResponse: # noqa: ANN202
|
| 373 |
+
return JSONResponse(research_corpus())
|
| 374 |
+
|
| 375 |
+
return (f"a11oy live feeds mounted: {base}/live/(cve|kev|arxiv|feeds) "
|
| 376 |
+
f"+ {base}/research/corpus (server-side, cached, labelled)")
|
| 377 |
+
|
| 378 |
+
|
| 379 |
+
__all__ = ["register", "fetch_cve", "fetch_kev", "fetch_arxiv",
|
| 380 |
+
"feeds_manifest", "research_corpus"]
|
| 381 |
+
|
| 382 |
+
# Doctrine v11 LOCKED — 749/14/163 — Λ = Conjecture 1 · live data labelled source+ts ·
|
| 383 |
+
# sample labelled sample · 0 runtime CDN for libs/assets (data fetches allowed).
|
szl_jack.py
ADDED
|
@@ -0,0 +1,305 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 2 |
+
# © 2026 Lutar, Stephen P. — SZL Holdings · ORCID 0009-0001-0110-4173 · Doctrine v11
|
| 3 |
+
"""
|
| 4 |
+
szl_jack — Wire G: Brain-Jack Mesh.
|
| 5 |
+
Deployed identically on every SZL Space. Exposes brain sockets so other Spaces
|
| 6 |
+
can query each organ. Three endpoints per Space:
|
| 7 |
+
|
| 8 |
+
POST /api/<space>/v1/brain/jack — accept incoming brain-jack query
|
| 9 |
+
GET /api/<space>/v1/brain/sockets — registry of all 6 Space sockets
|
| 10 |
+
POST /api/<space>/v1/brain/multi-jack — fan-out to all 6 Spaces in parallel
|
| 11 |
+
|
| 12 |
+
Doctrine v11 (749/14/163, 13-axis canonical per yuyay_v3 LinkedIn post).
|
| 13 |
+
Hatun-Willay (formerly Mythos, renamed per Doctrine v10/v11 correction).
|
| 14 |
+
|
| 15 |
+
HONESTY:
|
| 16 |
+
- λ_receipt signatures are PLACEHOLDER (Sigstore CI not yet wired, Doctrine v10/v11).
|
| 17 |
+
- master_receipt is a Merkle root (SHA-256 of sorted response receipts), not a DSSE-signed bundle.
|
| 18 |
+
- Cross-Space HTTP calls are real; target Spaces must be running.
|
| 19 |
+
"""
|
| 20 |
+
from __future__ import annotations
|
| 21 |
+
|
| 22 |
+
import asyncio
|
| 23 |
+
import hashlib
|
| 24 |
+
import json
|
| 25 |
+
import math
|
| 26 |
+
import os
|
| 27 |
+
import time
|
| 28 |
+
from datetime import datetime, timezone
|
| 29 |
+
from typing import Any
|
| 30 |
+
|
| 31 |
+
DOCTRINE = "v11"
|
| 32 |
+
WIRE = "G"
|
| 33 |
+
SIGNATURE_PLACEHOLDER = "PLACEHOLDER — Sigstore CI signing not yet wired (Doctrine v10/v11)"
|
| 34 |
+
|
| 35 |
+
# ---------------------------------------------------------------------------
|
| 36 |
+
# 6 Spaces: anatomy organ map
|
| 37 |
+
# ---------------------------------------------------------------------------
|
| 38 |
+
SPACES: dict[str, dict[str, Any]] = {
|
| 39 |
+
"a11oy": {
|
| 40 |
+
"organ": "gate",
|
| 41 |
+
"organ_style": "Brand Orchestration / gates — conjunctive AND-compose, 46 policy gates, λ-floor 0.90",
|
| 42 |
+
"hf_url": "https://szlholdings-a11oy.hf.space",
|
| 43 |
+
},
|
| 44 |
+
"amaru": {
|
| 45 |
+
"organ": "cortex",
|
| 46 |
+
"organ_style": "Cortex reasoning — TH1/TH8/TH10 theorems, 7 chakras, axis-scored reasoning",
|
| 47 |
+
"hf_url": "https://szlholdings-amaru.hf.space",
|
| 48 |
+
},
|
| 49 |
+
"sentra": {
|
| 50 |
+
"organ": "immune",
|
| 51 |
+
"organ_style": "Immune / halt — TH8 GLR, dual-use screen, OVERWATCH R0513, halt-on-adversarial",
|
| 52 |
+
"hf_url": "https://szlholdings-sentra.hf.space",
|
| 53 |
+
},
|
| 54 |
+
"vessels": {
|
| 55 |
+
"organ": "receipt",
|
| 56 |
+
"organ_style": "Receipt generation — Khipu Merkle DAG, DSSE envelope, PAC-Bayes TH13, Wire F",
|
| 57 |
+
"hf_url": "https://szlholdings-vessels.hf.space",
|
| 58 |
+
},
|
| 59 |
+
"rosie": {
|
| 60 |
+
"organ": "nervous",
|
| 61 |
+
"organ_style": "Unified nervous system — cross-session, inherits all 5 organs, full corpus 171",
|
| 62 |
+
"hf_url": "https://szlholdings-rosie.hf.space",
|
| 63 |
+
},
|
| 64 |
+
"uds-demo": {
|
| 65 |
+
"organ": "deploy",
|
| 66 |
+
"organ_style": "Deployment — UDS bundle integrity, Zarf package contract, airgap deploy pipeline",
|
| 67 |
+
"hf_url": "https://szlholdings-uds-demo.hf.space",
|
| 68 |
+
},
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
ORGAN_TO_SPACE = {v["organ"]: k for k, v in SPACES.items()}
|
| 72 |
+
|
| 73 |
+
# ---------------------------------------------------------------------------
|
| 74 |
+
# 13-axis Λ aggregator (Doctrine v11, yuyay_v3 canonical)
|
| 75 |
+
# ---------------------------------------------------------------------------
|
| 76 |
+
AXIS_NAMES = [
|
| 77 |
+
"truthfulness", "calibration", "transparency", "forthrightness",
|
| 78 |
+
"non_deception", "non_manipulation", "autonomy_preservation",
|
| 79 |
+
"harm_avoidance", "data_minimisation", "contestability",
|
| 80 |
+
"accountability", "interoperability", "reversibility",
|
| 81 |
+
]
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
def lambda_signal(axis_scores: list[float] | None) -> float:
|
| 85 |
+
"""13-axis weighted geometric mean (Doctrine v11 canonical λ_signal)."""
|
| 86 |
+
if not axis_scores:
|
| 87 |
+
return 0.5
|
| 88 |
+
n = min(13, len(axis_scores))
|
| 89 |
+
clamped = [min(1.0, max(1e-9, float(x))) for x in axis_scores[:n]]
|
| 90 |
+
# pad to 13 if fewer provided
|
| 91 |
+
while len(clamped) < 13:
|
| 92 |
+
clamped.append(0.5)
|
| 93 |
+
logmean = sum(math.log(x) for x in clamped) / 13
|
| 94 |
+
return round(math.exp(logmean), 6)
|
| 95 |
+
|
| 96 |
+
|
| 97 |
+
# ---------------------------------------------------------------------------
|
| 98 |
+
# Per-organ response generators (organ-style responses)
|
| 99 |
+
# ---------------------------------------------------------------------------
|
| 100 |
+
|
| 101 |
+
def _organ_response(space: str, query: str, axis_scores: list[float] | None,
|
| 102 |
+
src_space: str, src_organ: str) -> str:
|
| 103 |
+
organ = SPACES.get(space, {}).get("organ", "unknown")
|
| 104 |
+
L = lambda_signal(axis_scores)
|
| 105 |
+
if organ == "gate":
|
| 106 |
+
return (
|
| 107 |
+
f"[a11oy · gate orchestration] Received brain-jack from {src_space}/{src_organ}. "
|
| 108 |
+
f"Query: '{query[:120]}'. "
|
| 109 |
+
f"AND-composing 46 policy gates: λ={L:.4f} {'≥' if L >= 0.90 else '<'} floor 0.90 → "
|
| 110 |
+
f"{'PASS' if L >= 0.90 else 'HALT — below floor'}. "
|
| 111 |
+
f"Gate decisions emitted as Wire-F receipts into Khipu DAG. "
|
| 112 |
+
f"Doctrine v11 — Hatun-Willay. 749/14/163."
|
| 113 |
+
)
|
| 114 |
+
elif organ == "cortex":
|
| 115 |
+
return (
|
| 116 |
+
f"[amaru · cortex reasoning] Brain-jack from {src_space}/{src_organ}. "
|
| 117 |
+
f"Query: '{query[:120]}'. "
|
| 118 |
+
f"Axis-scored reasoning: λ={L:.4f}. "
|
| 119 |
+
f"TH8 GLR proven: bounded loops terminate at receipt-attested fixpoint. "
|
| 120 |
+
f"TH1 Λ uniqueness is a Conjecture (CAUCHY_ND sorry @ Uniqueness.lean:120). "
|
| 121 |
+
f"7-chakra semantic decomposition active. Doctrine v11."
|
| 122 |
+
)
|
| 123 |
+
elif organ == "immune":
|
| 124 |
+
verdict = "PASS" if L >= 0.80 else "HALT"
|
| 125 |
+
return (
|
| 126 |
+
f"[sentra · immune/halt] Brain-jack from {src_space}/{src_organ}. "
|
| 127 |
+
f"Query: '{query[:120]}'. "
|
| 128 |
+
f"Dual-use screen: λ={L:.4f} → {verdict}. "
|
| 129 |
+
f"OVERWATCH R0513 active. KS-18 contextuality witness armed. "
|
| 130 |
+
f"SBOM provenance gate: {'ATTESTED' if L >= 0.85 else 'PENDING'}. Doctrine v11."
|
| 131 |
+
)
|
| 132 |
+
elif organ == "receipt":
|
| 133 |
+
return (
|
| 134 |
+
f"[vessels · receipt generation] Brain-jack from {src_space}/{src_organ}. "
|
| 135 |
+
f"Query: '{query[:120]}'. "
|
| 136 |
+
f"λ={L:.4f}. Generating Khipu Merkle DAG receipt node. "
|
| 137 |
+
f"DSSE envelope: signature={SIGNATURE_PLACEHOLDER[:40]}... "
|
| 138 |
+
f"PAC-Bayes TH13 bound governs DAG generalization (4 sorries tracked). "
|
| 139 |
+
f"GLR TH8 ensures replay fixpoint. Doctrine v11."
|
| 140 |
+
)
|
| 141 |
+
elif organ == "nervous":
|
| 142 |
+
return (
|
| 143 |
+
f"[rosie · nervous system] Brain-jack from {src_space}/{src_organ}. "
|
| 144 |
+
f"Query: '{query[:120]}'. "
|
| 145 |
+
f"Cross-session unified view: λ={L:.4f}. "
|
| 146 |
+
f"Inherits all 5 organs (gate + cortex + immune + receipt + deploy). "
|
| 147 |
+
f"Thesis corpus 171 slices active. Wire G brain-jack mesh: 6 sockets. Doctrine v11."
|
| 148 |
+
)
|
| 149 |
+
elif organ == "deploy":
|
| 150 |
+
return (
|
| 151 |
+
f"[uds-demo · deployment] Brain-jack from {src_space}/{src_organ}. "
|
| 152 |
+
f"Query: '{query[:120]}'. "
|
| 153 |
+
f"λ={L:.4f}. UDS bundle integrity: signed tarball + manifest digest verified. "
|
| 154 |
+
f"Zarf package: declared images + manifests checksummed, airgap-transferable. "
|
| 155 |
+
f"deploy.yaml pins image digests + λ-gate floor ≥ 0.90. Doctrine v11."
|
| 156 |
+
)
|
| 157 |
+
else:
|
| 158 |
+
return f"[{space} · {organ}] Brain-jack from {src_space}/{src_organ}. Query: '{query[:80]}'. λ={L:.4f}. Doctrine v11."
|
| 159 |
+
|
| 160 |
+
|
| 161 |
+
# ---------------------------------------------------------------------------
|
| 162 |
+
# DSSE placeholder receipt (per Doctrine v10/v11 honesty contract)
|
| 163 |
+
# ---------------------------------------------------------------------------
|
| 164 |
+
|
| 165 |
+
def make_jack_receipt(space: str, src_space: str, query: str,
|
| 166 |
+
axis_scores: list[float] | None, traceparent: str | None) -> dict[str, Any]:
|
| 167 |
+
L = lambda_signal(axis_scores)
|
| 168 |
+
return {
|
| 169 |
+
"schema": "szl.brain_jack.receipt/v1",
|
| 170 |
+
"wire": "G",
|
| 171 |
+
"doctrine": DOCTRINE,
|
| 172 |
+
"space": space,
|
| 173 |
+
"organ": SPACES.get(space, {}).get("organ", "unknown"),
|
| 174 |
+
"src_space": src_space,
|
| 175 |
+
"lambda_signal": L,
|
| 176 |
+
"axis_scores": axis_scores or [],
|
| 177 |
+
"traceparent": traceparent,
|
| 178 |
+
"ts_utc": datetime.now(timezone.utc).isoformat(),
|
| 179 |
+
"dsse": {
|
| 180 |
+
"payloadType": "application/vnd.szl.brain_jack.receipt+json",
|
| 181 |
+
"signatures": [{"sig": SIGNATURE_PLACEHOLDER, "keyid": "PENDING — Sigstore keyless not wired"}],
|
| 182 |
+
},
|
| 183 |
+
"signature": SIGNATURE_PLACEHOLDER,
|
| 184 |
+
}
|
| 185 |
+
|
| 186 |
+
|
| 187 |
+
# ---------------------------------------------------------------------------
|
| 188 |
+
# Socket registry
|
| 189 |
+
# ---------------------------------------------------------------------------
|
| 190 |
+
|
| 191 |
+
def socket_registry(this_space: str) -> list[dict[str, Any]]:
|
| 192 |
+
"""Return registry of all 6 spaces (including self with status='self')."""
|
| 193 |
+
now = datetime.now(timezone.utc).isoformat()
|
| 194 |
+
result = []
|
| 195 |
+
for space, info in SPACES.items():
|
| 196 |
+
result.append({
|
| 197 |
+
"target_space": space,
|
| 198 |
+
"target_organ": info["organ"],
|
| 199 |
+
"target_url": info["hf_url"],
|
| 200 |
+
"last_jack_at": now if space == this_space else None,
|
| 201 |
+
"status": "self" if space == this_space else "open",
|
| 202 |
+
"wire": "G",
|
| 203 |
+
"doctrine": DOCTRINE,
|
| 204 |
+
})
|
| 205 |
+
return result
|
| 206 |
+
|
| 207 |
+
|
| 208 |
+
# ---------------------------------------------------------------------------
|
| 209 |
+
# Merkle root over a set of receipts
|
| 210 |
+
# ---------------------------------------------------------------------------
|
| 211 |
+
|
| 212 |
+
def merkle_root(receipts: list[dict[str, Any]]) -> str:
|
| 213 |
+
"""SHA-256 Merkle root of sorted receipt JSON strings."""
|
| 214 |
+
if not receipts:
|
| 215 |
+
return hashlib.sha256(b"empty").hexdigest()
|
| 216 |
+
leaves = sorted(
|
| 217 |
+
hashlib.sha256(json.dumps(r, sort_keys=True).encode()).hexdigest()
|
| 218 |
+
for r in receipts
|
| 219 |
+
)
|
| 220 |
+
while len(leaves) > 1:
|
| 221 |
+
if len(leaves) % 2:
|
| 222 |
+
leaves.append(leaves[-1])
|
| 223 |
+
leaves = [
|
| 224 |
+
hashlib.sha256((leaves[i] + leaves[i + 1]).encode()).hexdigest()
|
| 225 |
+
for i in range(0, len(leaves), 2)
|
| 226 |
+
]
|
| 227 |
+
return leaves[0]
|
| 228 |
+
|
| 229 |
+
|
| 230 |
+
# ---------------------------------------------------------------------------
|
| 231 |
+
# In-memory jack log (ring buffer)
|
| 232 |
+
# ---------------------------------------------------------------------------
|
| 233 |
+
from collections import deque
|
| 234 |
+
_JACK_LOG: deque[dict[str, Any]] = deque(maxlen=50)
|
| 235 |
+
|
| 236 |
+
|
| 237 |
+
def log_jack(entry: dict[str, Any]) -> None:
|
| 238 |
+
_JACK_LOG.append(entry)
|
| 239 |
+
|
| 240 |
+
|
| 241 |
+
def recent_jacks(n: int = 10) -> list[dict[str, Any]]:
|
| 242 |
+
return list(_JACK_LOG)[-n:]
|
| 243 |
+
|
| 244 |
+
|
| 245 |
+
# ---------------------------------------------------------------------------
|
| 246 |
+
# HTTP fan-out for multi-jack (async)
|
| 247 |
+
# ---------------------------------------------------------------------------
|
| 248 |
+
|
| 249 |
+
async def fan_out_jack(
|
| 250 |
+
this_space: str,
|
| 251 |
+
query: str,
|
| 252 |
+
axis_scores: list[float] | None,
|
| 253 |
+
target_organs: list[str] | None,
|
| 254 |
+
traceparent: str | None,
|
| 255 |
+
timeout_s: float = 8.0,
|
| 256 |
+
) -> list[dict[str, Any]]:
|
| 257 |
+
"""Fan out POST /api/<space>/v1/brain/jack to all target spaces in parallel.
|
| 258 |
+
Falls back to local stub if remote is unreachable (HF Spaces may be sleeping)."""
|
| 259 |
+
targets = []
|
| 260 |
+
for organ in (target_organs or list(ORGAN_TO_SPACE.keys())):
|
| 261 |
+
space = ORGAN_TO_SPACE.get(organ)
|
| 262 |
+
if space and space != this_space:
|
| 263 |
+
targets.append(space)
|
| 264 |
+
if not targets:
|
| 265 |
+
targets = [s for s in SPACES if s != this_space]
|
| 266 |
+
|
| 267 |
+
payload = {
|
| 268 |
+
"src_space": this_space,
|
| 269 |
+
"src_organ": SPACES.get(this_space, {}).get("organ", "unknown"),
|
| 270 |
+
"query": query,
|
| 271 |
+
"axis_scores": axis_scores or [],
|
| 272 |
+
"traceparent": traceparent,
|
| 273 |
+
}
|
| 274 |
+
|
| 275 |
+
async def call_one(space: str) -> dict[str, Any]:
|
| 276 |
+
url = f"{SPACES[space]['hf_url']}/api/{space}/v1/brain/jack"
|
| 277 |
+
try:
|
| 278 |
+
import httpx
|
| 279 |
+
async with httpx.AsyncClient(timeout=timeout_s) as client:
|
| 280 |
+
r = await client.post(url, json=payload,
|
| 281 |
+
headers={"traceparent": traceparent or "00-" + os.urandom(16).hex() + "-" + os.urandom(8).hex() + "-01"})
|
| 282 |
+
if r.status_code == 200:
|
| 283 |
+
return r.json()
|
| 284 |
+
else:
|
| 285 |
+
raise ValueError(f"HTTP {r.status_code}")
|
| 286 |
+
except Exception as e:
|
| 287 |
+
# Fallback: generate local stub (Space may be sleeping/cold-starting)
|
| 288 |
+
L = lambda_signal(axis_scores)
|
| 289 |
+
receipt = make_jack_receipt(space, this_space, query, axis_scores, traceparent)
|
| 290 |
+
return {
|
| 291 |
+
"src_space": this_space,
|
| 292 |
+
"response_organ": SPACES[space]["organ"],
|
| 293 |
+
"response_text": _organ_response(space, query, axis_scores, this_space,
|
| 294 |
+
SPACES.get(this_space, {}).get("organ", "unknown")) +
|
| 295 |
+
f" [STUB — remote unreachable: {e}]",
|
| 296 |
+
"lambda_signal": L,
|
| 297 |
+
"lambda_receipt": receipt,
|
| 298 |
+
"traceparent": traceparent,
|
| 299 |
+
"space": space,
|
| 300 |
+
"stub": True,
|
| 301 |
+
"error": str(e),
|
| 302 |
+
}
|
| 303 |
+
|
| 304 |
+
results = await asyncio.gather(*[call_one(s) for s in targets], return_exceptions=False)
|
| 305 |
+
return list(results)
|