betterwithage commited on
Commit
c5bae02
·
verified ·
1 Parent(s): e1cb6f1

chore(sync): mirror backend .py + Dockerfile to Space (hf-sync-backend)

Browse files

Automated 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.

Files changed (4) hide show
  1. Dockerfile +7 -0
  2. conduction_aphasia.py +577 -0
  3. szl_a11oy_live_feeds.py +383 -0
  4. 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>&#9711; CONDUCTION-APHASIA DETECTOR</h1>
409
+ <div class="subtitle">a11oy &middot; A37 InternalFeedbackIntegrity &middot; Hickok state feedback control architecture &middot; 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">&mdash;</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">&mdash;</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">&mdash;</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|| &gt; 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&rarr;actual mismatch to demonstrate the Conduction Alert.
482
+ Predicted: [1.0, 0.0, 0.0, 0.5] &middot; Actual: [0.0, 1.0, 1.0, 0.0]
483
+ </p>
484
+ <button class="demo-btn" onclick="injectDemo()">&#9654; Trigger Demo Divergence</button>
485
+ <div class="demo-note">&#9888; DEMO ONLY &mdash; 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 &tau;</td><td id="p-tau" style="color:#e0e0e0">&mdash;</td></tr>
492
+ <tr><td style="color:#666;padding:3px 0">Window N</td><td id="p-window" style="color:#e0e0e0">&mdash;</td></tr>
493
+ <tr><td style="color:#666;padding:3px 0">Last Alert</td><td id="p-last-alert" style="color:#e0e0e0">&mdash;</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 &middot; auto-refresh 5s)
503
+ <span id="status-ts" style="float:right;font-size:10px;color:#444">refreshing&hellip;</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 &mdash; waiting for observations&hellip;</td></tr>
514
+ </tbody>
515
+ </table>
516
+ </div>
517
+
518
+ <div class="footer">
519
+ <div>A37 InternalFeedbackIntegrity &middot; Citation: Hickok, Houde, Rong 2011, Neuron 69:407&ndash;422 &middot; <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 &amp; Poeppel 2007, Nat Rev Neurosci 8:393&ndash;402 &middot; <a href="https://doi.org/10.1038/nrn2113">DOI 10.1038/nrn2113</a></div>
521
+ <div>Doctrine v11 LOCKED &middot; 749 declarations / 14 axioms / 163 sorries &middot; &Lambda; = Conjecture 1 (NOT a theorem) &middot; SLSA L1 honest &middot; Sovereign-default</div>
522
+ <div style="margin-top:4px">&copy; 2026 SZL Holdings &middot; Authored by Yachay (CTO) &middot; 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,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')}
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)