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, routers/__init__.py, routers/frontier_reads.py, routers/lambda_bounty.py, routers/research_3d.py, serve.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
- routers/__init__.py +31 -0
- routers/frontier_reads.py +96 -0
- routers/lambda_bounty.py +155 -0
- routers/research_3d.py +57 -0
- serve.py +50 -198
Dockerfile
CHANGED
|
@@ -163,6 +163,13 @@ COPY knowledge.json ./static/knowledge.json
|
|
| 163 |
# registers live. (dockerfile-copy-guard verifies these sources exist on main.)
|
| 164 |
COPY a11oy_ayllu.py ./
|
| 165 |
COPY ayllu/ ./ayllu/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 166 |
# Genome registry served to the console Genome panel + /api/a11oy/v1/genome.
|
| 167 |
# Per-file COPY (this Dockerfile uses no `COPY . .`); a missing line -> the endpoint
|
| 168 |
# degrades to an honest labeled 503 (never a faked payload), the panel shows it.
|
|
|
|
| 163 |
# registers live. (dockerfile-copy-guard verifies these sources exist on main.)
|
| 164 |
COPY a11oy_ayllu.py ./
|
| 165 |
COPY ayllu/ ./ayllu/
|
| 166 |
+
# routers/ — Wave-K Dev4 serve.py decomposition (first bounded slice). serve.py
|
| 167 |
+
# imports `from routers import lambda_bounty|research_3d|frontier_reads` (guarded)
|
| 168 |
+
# and calls each register(app) BEFORE the SPA catch-all. This Dockerfile uses no
|
| 169 |
+
# `COPY . .`, so the WHOLE package dir MUST be per-dir COPY'd or the guarded
|
| 170 |
+
# imports fall back and the moved route groups (lambda-bounty intake, research-3D
|
| 171 |
+
# reads, frontier reads) silently 404 live. REFACTOR-ONLY: identical paths/order.
|
| 172 |
+
COPY routers/ ./routers/
|
| 173 |
# Genome registry served to the console Genome panel + /api/a11oy/v1/genome.
|
| 174 |
# Per-file COPY (this Dockerfile uses no `COPY . .`); a missing line -> the endpoint
|
| 175 |
# degrades to an honest labeled 503 (never a faked payload), the panel shows it.
|
routers/__init__.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""a11oy serve.py route-group package (Wave-K Dev4 — refactor-only decomposition).
|
| 2 |
+
|
| 3 |
+
BACKGROUND
|
| 4 |
+
----------
|
| 5 |
+
serve.py is a ~11.7k-line monolith. This package is the FIRST bounded slice of a
|
| 6 |
+
SAFE, CI-verified decomposition: a small number of cohesive route groups are moved
|
| 7 |
+
out of serve.py into focused modules here, each exposing a single
|
| 8 |
+
|
| 9 |
+
def register(app) -> dict
|
| 10 |
+
|
| 11 |
+
entry point. serve.py imports the package and calls each `register(app)` at the
|
| 12 |
+
SAME lexical position the routes used to occupy — i.e. BEFORE the SPA
|
| 13 |
+
`/{full_path:path}` catch-all — via the established guarded try/except pattern, so:
|
| 14 |
+
|
| 15 |
+
* every path is identical,
|
| 16 |
+
* every method is identical,
|
| 17 |
+
* the order relative to the catch-all is identical,
|
| 18 |
+
* a missing/broken group can NEVER take down the SPA (guarded), and
|
| 19 |
+
* the register() functions are IMPORTED + CALLED (register-invocation-guard clean).
|
| 20 |
+
|
| 21 |
+
This is REFACTOR-ONLY. No endpoint behavior changes. Parity is proven by
|
| 22 |
+
tools_serve_split/capture_routes.py (before/after route-table fingerprint) plus the
|
| 23 |
+
Wave-J frontier contract suite (tests/test_frontier_endpoints.py) and TestClient.
|
| 24 |
+
|
| 25 |
+
The package top-level name is `routers` (not szl_*/a11oy_*), so it is intentionally
|
| 26 |
+
OUTSIDE the guarded-import-liveness first-party scan — and the files exist anyway.
|
| 27 |
+
|
| 28 |
+
Signed-off-by: Stephen P. Lutar Jr. <stephenlutar2@gmail.com>
|
| 29 |
+
"""
|
| 30 |
+
|
| 31 |
+
__all__ = ["lambda_bounty", "research_3d", "frontier_reads"]
|
routers/frontier_reads.py
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""routers/frontier_reads.py — frontier read endpoints (moved verbatim from serve.py).
|
| 2 |
+
|
| 3 |
+
Wave-K Dev4 refactor-only extraction. Route group (all GET, read-only):
|
| 4 |
+
GET /api/a11oy/v1/forecast-baseline (+ /v1/forecast-baseline)
|
| 5 |
+
GET /api/a11oy/v1/vertical-packs (+ /v1/vertical-packs)
|
| 6 |
+
GET /api/a11oy/v1/observability/business (+ /v1/observability/business)
|
| 7 |
+
|
| 8 |
+
Shared serve.py module-scope state referenced (unchanged, via `import serve`):
|
| 9 |
+
serve._A11OY_FORECAST — forecast-baseline payload
|
| 10 |
+
serve._a11oy_build_chain — receipt-chain builder
|
| 11 |
+
serve._A11OY_CAPS — capability list (for the observability count)
|
| 12 |
+
|
| 13 |
+
`_A11OY_VERTICALS` was defined inline in the moved block and is genuinely local to
|
| 14 |
+
this group, so it moves here with the routes. Registered BEFORE the /api/a11oy/
|
| 15 |
+
{path:path} Node proxy + SPA catch-all, identical to the pre-refactor inline block.
|
| 16 |
+
|
| 17 |
+
REFACTOR-ONLY: paths, methods, and payloads are byte-identical to before.
|
| 18 |
+
|
| 19 |
+
Signed-off-by: Stephen P. Lutar Jr. <stephenlutar2@gmail.com>
|
| 20 |
+
"""
|
| 21 |
+
from __future__ import annotations
|
| 22 |
+
|
| 23 |
+
from fastapi.responses import JSONResponse
|
| 24 |
+
|
| 25 |
+
# ---- Vertical-pack registry (GAP-5): 13 verticals, live/stub. "Cyber Resilience"
|
| 26 |
+
# label avoids the literal forbidden string. NO amaru/sentra/rosie. ----
|
| 27 |
+
_A11OY_VERTICALS = [
|
| 28 |
+
{"id": "platform", "title": "Platform / AgentOps", "purpose": "Release Gate Intelligence", "status": "live", "owner": "eng-vp@szl"},
|
| 29 |
+
{"id": "pulse", "title": "Pulse", "purpose": "Founder Operating Channel", "status": "live", "owner": "ceo@szl"},
|
| 30 |
+
{"id": "finance", "title": "Finance / Capital Weather", "purpose": "Capital Weather", "status": "live", "owner": "cfo@szl"},
|
| 31 |
+
{"id": "decision_ledger", "title": "Decision Debt Ledger", "purpose": "Decision Debt Ledger", "status": "live", "owner": "cpo@szl"},
|
| 32 |
+
{"id": "terra", "title": "Acquisition Time Machine", "purpose": "Acquisition Time Machine", "status": "live", "owner": "ceo@szl"},
|
| 33 |
+
{"id": "voyage", "title": "Voyage Risk Exchange", "purpose": "Voyage Risk Exchange", "status": "live", "owner": "coo@szl"},
|
| 34 |
+
{"id": "counsel", "title": "Matter Flight Recorder", "purpose": "Matter Flight Recorder", "status": "live", "owner": "general-counsel@szl"},
|
| 35 |
+
{"id": "growth", "title": "Marketing / Growth", "purpose": "Proof-To-Pipeline Engine", "status": "live", "owner": "cmo@szl"},
|
| 36 |
+
{"id": "cyber", "title": "Cyber Resilience", "purpose": "Cyber Resilience Command", "status": "live", "owner": "ciso@szl"},
|
| 37 |
+
{"id": "firestorm", "title": "Firestorm Ops", "purpose": "Crisis Operations Command", "status": "stub", "owner": "coo@szl"},
|
| 38 |
+
{"id": "nuroforge", "title": "NuroForge", "purpose": "AI Agent Forge", "status": "stub", "owner": "cto@szl"},
|
| 39 |
+
{"id": "infra", "title": "Meridian Infra", "purpose": "Infrastructure Intelligence", "status": "stub", "owner": "eng-vp@szl"},
|
| 40 |
+
{"id": "graph", "title": "Constellation Graph", "purpose": "Cross-Domain Intelligence Graph", "status": "stub", "owner": "cto@szl"},
|
| 41 |
+
]
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
def register(app) -> dict:
|
| 45 |
+
"""Attach the frontier read route group to `app`, identically to the prior
|
| 46 |
+
inline serve.py block. Called BEFORE the Node proxy + SPA catch-all."""
|
| 47 |
+
import serve # shared module-scope state lives at serve module scope
|
| 48 |
+
|
| 49 |
+
@app.get("/api/a11oy/v1/forecast-baseline")
|
| 50 |
+
@app.get("/v1/forecast-baseline")
|
| 51 |
+
async def a11oy_forecast_baseline_v2() -> JSONResponse:
|
| 52 |
+
return JSONResponse(serve._A11OY_FORECAST)
|
| 53 |
+
|
| 54 |
+
@app.get("/api/a11oy/v1/vertical-packs")
|
| 55 |
+
@app.get("/v1/vertical-packs")
|
| 56 |
+
async def a11oy_vertical_packs_v2() -> JSONResponse:
|
| 57 |
+
live = sum(1 for v in _A11OY_VERTICALS if v["status"] == "live")
|
| 58 |
+
return JSONResponse({"total": len(_A11OY_VERTICALS), "live": live,
|
| 59 |
+
"stub": len(_A11OY_VERTICALS) - live,
|
| 60 |
+
"verticals": _A11OY_VERTICALS,
|
| 61 |
+
"honesty": "Live = shipping pack; stub = scaffolded, roadmap."})
|
| 62 |
+
|
| 63 |
+
# ---- Business Observability (5 domains) on REAL in-image data (no fabricated KPIs) ----
|
| 64 |
+
@app.get("/api/a11oy/v1/observability/business")
|
| 65 |
+
@app.get("/v1/observability/business")
|
| 66 |
+
async def a11oy_business_observability_v2() -> JSONResponse:
|
| 67 |
+
ch = serve._a11oy_build_chain(24)
|
| 68 |
+
domains = [
|
| 69 |
+
{"id": "coverage", "name": "Coverage",
|
| 70 |
+
"measure": "knowledge ontology + vertical policies",
|
| 71 |
+
"value": "10 policies · axioms→theorems→formulas graph", "status": "real"},
|
| 72 |
+
{"id": "connectivity", "name": "Connectivity",
|
| 73 |
+
"measure": "in-image capability mesh + MCP tools",
|
| 74 |
+
"value": "%d capabilities · 4 MCP tools" % len(serve._A11OY_CAPS), "status": "real"},
|
| 75 |
+
{"id": "cognitive", "name": "Cognitive",
|
| 76 |
+
"measure": "reasoning + orchestration + Λ scoring",
|
| 77 |
+
"value": "13-axis trust vector · Λ=0.919 (Conjecture 1)", "status": "real"},
|
| 78 |
+
{"id": "executive", "name": "Executive Interfaces",
|
| 79 |
+
"measure": "operator tabs + Ask & Act",
|
| 80 |
+
"value": "command tabs + grounded operator", "status": "real"},
|
| 81 |
+
{"id": "impact", "name": "Impact",
|
| 82 |
+
"measure": "signed decision receipts (hash-chained)",
|
| 83 |
+
"value": "%d signed spans · chain verified" % ch["depth"], "status": "real"},
|
| 84 |
+
]
|
| 85 |
+
return JSONResponse({
|
| 86 |
+
"domains": domains,
|
| 87 |
+
"honesty": ("Capability domains on real in-image data. We do NOT reproduce "
|
| 88 |
+
"any third-party marketing percentages as our own."),
|
| 89 |
+
"lambda_status": "Conjecture 1 (advisory)",
|
| 90 |
+
})
|
| 91 |
+
|
| 92 |
+
return {"ok": True, "ns": "a11oy", "group": "frontier-reads", "routes": [
|
| 93 |
+
"/api/a11oy/v1/forecast-baseline", "/v1/forecast-baseline",
|
| 94 |
+
"/api/a11oy/v1/vertical-packs", "/v1/vertical-packs",
|
| 95 |
+
"/api/a11oy/v1/observability/business", "/v1/observability/business",
|
| 96 |
+
]}
|
routers/lambda_bounty.py
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""routers/lambda_bounty.py — Λ-BOUNTY INTAKE receiver (moved verbatim from serve.py).
|
| 2 |
+
|
| 3 |
+
Wave-K Dev4 refactor-only extraction. Route group:
|
| 4 |
+
GET /api/lambda-bounty/healthz
|
| 5 |
+
POST /api/lambda-bounty/submit
|
| 6 |
+
GET /api/lambda-bounty/receipts
|
| 7 |
+
|
| 8 |
+
Mirrors szl-holdings/lambda-bounty/webhook/intake.py so the endpoint advertised in
|
| 9 |
+
lutar-lean/BOUNTY.md is REAL, not a 404.
|
| 10 |
+
|
| 11 |
+
HONESTY: a receipt acknowledges INTAKE only. Award eligibility is decided SOLELY by
|
| 12 |
+
the verify-proof CI on a PR to szl-holdings/lambda-bounty. This receiver never
|
| 13 |
+
declares a winner and never moves money. Λ = Conjecture 1, NOT a theorem. Registered
|
| 14 |
+
BEFORE the SPA catch-all /{full_path:path}.
|
| 15 |
+
|
| 16 |
+
DSSE/HMAC receipts are REAL when LAMBDA_BOUNTY_HMAC_KEY is present; an honest
|
| 17 |
+
"dev-key" placeholder hmac is emitted (and flagged) when absent. The ledger is
|
| 18 |
+
in-memory (ring buffer) on the Space — honest disclosure; durable receipts land in
|
| 19 |
+
the repo via the bounty-webhook GitHub Action. ADDITIVE ONLY.
|
| 20 |
+
|
| 21 |
+
This module is fully self-contained: it uses only stdlib + FastAPI response types.
|
| 22 |
+
The state (ring buffer + keys) lives here now instead of at serve.py module scope.
|
| 23 |
+
Behavior is byte-identical to the pre-refactor inline block.
|
| 24 |
+
|
| 25 |
+
Signed-off-by: Stephen P. Lutar Jr. <stephenlutar2@gmail.com>
|
| 26 |
+
"""
|
| 27 |
+
from __future__ import annotations
|
| 28 |
+
|
| 29 |
+
import collections as _pr_col
|
| 30 |
+
import hashlib as _lb_hashlib
|
| 31 |
+
import hmac as _lb_hmac
|
| 32 |
+
import json
|
| 33 |
+
import os
|
| 34 |
+
import re as _lb_re
|
| 35 |
+
import threading as _pr_thr
|
| 36 |
+
|
| 37 |
+
from fastapi import Request
|
| 38 |
+
from fastapi.responses import JSONResponse
|
| 39 |
+
|
| 40 |
+
# --- module state (was serve.py module-scope) --------------------------------
|
| 41 |
+
_LB_SIGN_KEY = os.environ.get("LAMBDA_BOUNTY_HMAC_KEY", "dev-key-not-for-prod")
|
| 42 |
+
_LB_HMAC_IS_DEV = _LB_SIGN_KEY == "dev-key-not-for-prod"
|
| 43 |
+
_LB_PR_RE = _lb_re.compile(r"^https://github\.com/szl-holdings/lambda-bounty/pull/\d+$")
|
| 44 |
+
_LB_ALLOWED_AXIOMS = ("propext", "Quot.sound", "Classical.choice")
|
| 45 |
+
_LB_LEDGER: _pr_col.deque = _pr_col.deque(maxlen=500)
|
| 46 |
+
_LB_LEDGER_LOCK = _pr_thr.Lock()
|
| 47 |
+
_LB_CONJECTURE = {
|
| 48 |
+
"id": "Conjecture 1",
|
| 49 |
+
"formula": "F23",
|
| 50 |
+
"status": "OPEN — NOT a theorem",
|
| 51 |
+
"statement": "Any two 9-axis aggregators satisfying A1 idempotence, A2 monotonicity, "
|
| 52 |
+
"A3 symmetry, A4 zero-absorption agree on every input.",
|
| 53 |
+
"arbiter": "verify-proof CI on a PR to szl-holdings/lambda-bounty (sole, no-bypass)",
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
def _lb_now() -> str:
|
| 58 |
+
import datetime as _dt
|
| 59 |
+
return _dt.datetime.now(_dt.timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
def _lb_validate(payload: dict) -> list:
|
| 63 |
+
errs = []
|
| 64 |
+
for k in ("submitter", "pr_url", "lean_toolchain", "axiom_print", "sorry_free_claim"):
|
| 65 |
+
if k not in payload:
|
| 66 |
+
errs.append(f"missing required field: {k}")
|
| 67 |
+
if "pr_url" in payload and not _LB_PR_RE.match(str(payload.get("pr_url", ""))):
|
| 68 |
+
errs.append("pr_url must be https://github.com/szl-holdings/lambda-bounty/pull/<n>")
|
| 69 |
+
if payload.get("lean_toolchain") not in (None, "leanprover/lean4:v4.13.0"):
|
| 70 |
+
errs.append("lean_toolchain must be leanprover/lean4:v4.13.0")
|
| 71 |
+
if payload.get("sorry_free_claim") is not True:
|
| 72 |
+
errs.append("sorry_free_claim must be true (CI verifies independently)")
|
| 73 |
+
sub = payload.get("submitter")
|
| 74 |
+
if not isinstance(sub, dict) or not sub.get("name"):
|
| 75 |
+
errs.append("submitter.name is required")
|
| 76 |
+
ap = payload.get("axiom_print", "")
|
| 77 |
+
if ap and "sorryAx" in str(ap):
|
| 78 |
+
errs.append("axiom_print contains sorryAx — proof is incomplete")
|
| 79 |
+
return errs
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
def _lb_prev_hash() -> str:
|
| 83 |
+
if not _LB_LEDGER:
|
| 84 |
+
return "genesis"
|
| 85 |
+
return _LB_LEDGER[-1].get("hash", "genesis")
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
def _lb_make_receipt(payload: dict, accepted: bool, errors: list) -> dict:
|
| 89 |
+
body = {
|
| 90 |
+
"receipt_type": "lambda_bounty_intake",
|
| 91 |
+
"conjecture": "Conjecture 1 (F23 Λ-aggregator uniqueness)",
|
| 92 |
+
"ts": _lb_now(),
|
| 93 |
+
"submitter": (payload.get("submitter") or {}).get("name", "?"),
|
| 94 |
+
"pr_url": payload.get("pr_url"),
|
| 95 |
+
"accepted_intake": accepted,
|
| 96 |
+
"errors": errors,
|
| 97 |
+
"eligibility_note": "Intake acknowledgement only. Award eligibility = verify-proof CI green on the PR.",
|
| 98 |
+
"prev": _lb_prev_hash(),
|
| 99 |
+
}
|
| 100 |
+
digest = _lb_hashlib.sha256(json.dumps(body, sort_keys=True).encode()).hexdigest()
|
| 101 |
+
sig = _lb_hmac.new(_LB_SIGN_KEY.encode(), digest.encode(), _lb_hashlib.sha256).hexdigest()
|
| 102 |
+
body["hash"] = digest
|
| 103 |
+
body["hmac_sha256"] = sig
|
| 104 |
+
body["hmac_key"] = "dev-key-placeholder (set LAMBDA_BOUNTY_HMAC_KEY for a real signature)" if _LB_HMAC_IS_DEV else "env-provided"
|
| 105 |
+
return body
|
| 106 |
+
|
| 107 |
+
|
| 108 |
+
def register(app) -> dict:
|
| 109 |
+
"""Attach the Λ-bounty intake route group to `app`, identically to the prior
|
| 110 |
+
inline serve.py block. Called BEFORE the SPA catch-all."""
|
| 111 |
+
|
| 112 |
+
@app.get("/api/lambda-bounty/healthz")
|
| 113 |
+
async def _lb_healthz():
|
| 114 |
+
"""Λ-bounty intake liveness + live Conjecture-1 status. Λ = NOT a theorem."""
|
| 115 |
+
return JSONResponse({"status": "ok", "service": "lambda-bounty-intake",
|
| 116 |
+
"conjecture": _LB_CONJECTURE, "doctrine": "v11",
|
| 117 |
+
"receipts_buffered": len(_LB_LEDGER)})
|
| 118 |
+
|
| 119 |
+
@app.post("/api/lambda-bounty/submit")
|
| 120 |
+
async def _lb_submit(request: Request):
|
| 121 |
+
"""Validate a Conjecture-1 submission payload, emit a hash-chained Khipu
|
| 122 |
+
intake receipt. 200 + receipt (accepted) or 422 + errors (rejected); a
|
| 123 |
+
receipt is appended either way. Eligibility is decided ONLY by verify-proof
|
| 124 |
+
CI on the PR — this never declares a winner."""
|
| 125 |
+
try:
|
| 126 |
+
payload = await request.json()
|
| 127 |
+
except Exception:
|
| 128 |
+
return JSONResponse({"error": "invalid JSON"}, status_code=400)
|
| 129 |
+
if not isinstance(payload, dict):
|
| 130 |
+
return JSONResponse({"error": "payload must be a JSON object"}, status_code=400)
|
| 131 |
+
errors = _lb_validate(payload)
|
| 132 |
+
accepted = len(errors) == 0
|
| 133 |
+
receipt = _lb_make_receipt(payload, accepted, errors)
|
| 134 |
+
with _LB_LEDGER_LOCK:
|
| 135 |
+
_LB_LEDGER.append(receipt)
|
| 136 |
+
return JSONResponse(status_code=(200 if accepted else 422), content={
|
| 137 |
+
"accepted_intake": accepted, "errors": errors, "receipt": receipt,
|
| 138 |
+
"next_step": "Open a PR to szl-holdings/lambda-bounty; verify-proof CI is the sole arbiter.",
|
| 139 |
+
})
|
| 140 |
+
|
| 141 |
+
@app.get("/api/lambda-bounty/receipts")
|
| 142 |
+
async def _lb_receipts():
|
| 143 |
+
"""Append-only intake receipt ledger as NDJSON. In-memory ring buffer
|
| 144 |
+
(maxlen=500); resets on Space rebuild (honest disclosure). Durable receipts
|
| 145 |
+
are committed to the repo by the bounty-webhook GitHub Action."""
|
| 146 |
+
from fastapi.responses import PlainTextResponse as _LBPlain
|
| 147 |
+
with _LB_LEDGER_LOCK:
|
| 148 |
+
lines = "\n".join(json.dumps(r) for r in _LB_LEDGER)
|
| 149 |
+
return _LBPlain(lines, media_type="application/x-ndjson")
|
| 150 |
+
|
| 151 |
+
return {"ok": True, "ns": "lambda-bounty", "routes": [
|
| 152 |
+
"/api/lambda-bounty/healthz",
|
| 153 |
+
"/api/lambda-bounty/submit",
|
| 154 |
+
"/api/lambda-bounty/receipts",
|
| 155 |
+
]}
|
routers/research_3d.py
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""routers/research_3d.py — research-3D read endpoints (moved verbatim from serve.py).
|
| 2 |
+
|
| 3 |
+
Wave-K Dev4 refactor-only extraction. Route group (all GET, read-only):
|
| 4 |
+
GET /api/a11oy/v1/router/metrics (+ /v1/router/metrics)
|
| 5 |
+
GET /api/a11oy/v1/chaski/routing-graph (+ /v1/chaski/routing-graph, /api/chaski/routing-graph)
|
| 6 |
+
GET /api/a11oy/v1/reason/loop-depth (+ /v1/reason/loop-depth)
|
| 7 |
+
GET /api/a11oy/v1/consensus/votes (+ /v1/consensus/votes)
|
| 8 |
+
|
| 9 |
+
These four handlers are thin JSON wrappers over the deterministic payload builders
|
| 10 |
+
`_r3d_router_metrics_payload` / `_r3d_routing_graph_payload` / `_r3d_loop_depth_payload`
|
| 11 |
+
/ `_r3d_consensus_votes_payload`, which REMAIN defined at serve.py module scope (they
|
| 12 |
+
are shared / referenced elsewhere). This module reaches them via `import serve`, which
|
| 13 |
+
is safe because register() is called from inside serve.py AFTER those helpers are
|
| 14 |
+
defined. Registered BEFORE the /api/a11oy/{path:path} Node proxy + SPA catch-all so
|
| 15 |
+
FastAPI ordered matching resolves them here (identical to the pre-refactor inline block).
|
| 16 |
+
|
| 17 |
+
REFACTOR-ONLY: paths, methods, and payloads are byte-identical to before.
|
| 18 |
+
|
| 19 |
+
Signed-off-by: Stephen P. Lutar Jr. <stephenlutar2@gmail.com>
|
| 20 |
+
"""
|
| 21 |
+
from __future__ import annotations
|
| 22 |
+
|
| 23 |
+
from fastapi.responses import JSONResponse
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
def register(app) -> dict:
|
| 27 |
+
"""Attach the research-3D read route group to `app`, identically to the prior
|
| 28 |
+
inline serve.py block. Called BEFORE the Node proxy + SPA catch-all."""
|
| 29 |
+
import serve # shared deterministic payload builders live at serve module scope
|
| 30 |
+
|
| 31 |
+
@app.get("/api/a11oy/v1/router/metrics")
|
| 32 |
+
@app.get("/v1/router/metrics")
|
| 33 |
+
async def _r3d_router_metrics() -> JSONResponse:
|
| 34 |
+
return JSONResponse(serve._r3d_router_metrics_payload())
|
| 35 |
+
|
| 36 |
+
@app.get("/api/a11oy/v1/chaski/routing-graph")
|
| 37 |
+
@app.get("/v1/chaski/routing-graph")
|
| 38 |
+
@app.get("/api/chaski/routing-graph")
|
| 39 |
+
async def _r3d_routing_graph() -> JSONResponse:
|
| 40 |
+
return JSONResponse(serve._r3d_routing_graph_payload())
|
| 41 |
+
|
| 42 |
+
@app.get("/api/a11oy/v1/reason/loop-depth")
|
| 43 |
+
@app.get("/v1/reason/loop-depth")
|
| 44 |
+
async def _r3d_loop_depth() -> JSONResponse:
|
| 45 |
+
return JSONResponse(serve._r3d_loop_depth_payload())
|
| 46 |
+
|
| 47 |
+
@app.get("/api/a11oy/v1/consensus/votes")
|
| 48 |
+
@app.get("/v1/consensus/votes")
|
| 49 |
+
async def _r3d_consensus_votes() -> JSONResponse:
|
| 50 |
+
return JSONResponse(serve._r3d_consensus_votes_payload())
|
| 51 |
+
|
| 52 |
+
return {"ok": True, "ns": "a11oy", "group": "research-3d", "routes": [
|
| 53 |
+
"/api/a11oy/v1/router/metrics", "/v1/router/metrics",
|
| 54 |
+
"/api/a11oy/v1/chaski/routing-graph", "/v1/chaski/routing-graph", "/api/chaski/routing-graph",
|
| 55 |
+
"/api/a11oy/v1/reason/loop-depth", "/v1/reason/loop-depth",
|
| 56 |
+
"/api/a11oy/v1/consensus/votes", "/v1/consensus/votes",
|
| 57 |
+
]}
|
serve.py
CHANGED
|
@@ -4849,117 +4849,21 @@ async def _a11oy_pr_lambda_v2():
|
|
| 4849 |
# land in the repo via the bounty-webhook GitHub Action. ADDITIVE ONLY.
|
| 4850 |
# Signed-off-by: Stephen P. Lutar Jr. <stephenlutar2@gmail.com>
|
| 4851 |
# ===========================================================================
|
| 4852 |
-
|
| 4853 |
-
|
| 4854 |
-
|
| 4855 |
-
|
| 4856 |
-
|
| 4857 |
-
|
| 4858 |
-
|
| 4859 |
-
|
| 4860 |
-
|
| 4861 |
-
|
| 4862 |
-
|
| 4863 |
-
|
| 4864 |
-
|
| 4865 |
-
"
|
| 4866 |
-
|
| 4867 |
-
"A3 symmetry, A4 zero-absorption agree on every input.",
|
| 4868 |
-
"arbiter": "verify-proof CI on a PR to szl-holdings/lambda-bounty (sole, no-bypass)",
|
| 4869 |
-
}
|
| 4870 |
-
|
| 4871 |
-
|
| 4872 |
-
def _lb_now() -> str:
|
| 4873 |
-
import datetime as _dt
|
| 4874 |
-
return _dt.datetime.now(_dt.timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
| 4875 |
-
|
| 4876 |
-
|
| 4877 |
-
def _lb_validate(payload: dict) -> list:
|
| 4878 |
-
errs = []
|
| 4879 |
-
for k in ("submitter", "pr_url", "lean_toolchain", "axiom_print", "sorry_free_claim"):
|
| 4880 |
-
if k not in payload:
|
| 4881 |
-
errs.append(f"missing required field: {k}")
|
| 4882 |
-
if "pr_url" in payload and not _LB_PR_RE.match(str(payload.get("pr_url", ""))):
|
| 4883 |
-
errs.append("pr_url must be https://github.com/szl-holdings/lambda-bounty/pull/<n>")
|
| 4884 |
-
if payload.get("lean_toolchain") not in (None, "leanprover/lean4:v4.13.0"):
|
| 4885 |
-
errs.append("lean_toolchain must be leanprover/lean4:v4.13.0")
|
| 4886 |
-
if payload.get("sorry_free_claim") is not True:
|
| 4887 |
-
errs.append("sorry_free_claim must be true (CI verifies independently)")
|
| 4888 |
-
sub = payload.get("submitter")
|
| 4889 |
-
if not isinstance(sub, dict) or not sub.get("name"):
|
| 4890 |
-
errs.append("submitter.name is required")
|
| 4891 |
-
ap = payload.get("axiom_print", "")
|
| 4892 |
-
if ap and "sorryAx" in str(ap):
|
| 4893 |
-
errs.append("axiom_print contains sorryAx — proof is incomplete")
|
| 4894 |
-
return errs
|
| 4895 |
-
|
| 4896 |
-
|
| 4897 |
-
def _lb_prev_hash() -> str:
|
| 4898 |
-
if not _LB_LEDGER:
|
| 4899 |
-
return "genesis"
|
| 4900 |
-
return _LB_LEDGER[-1].get("hash", "genesis")
|
| 4901 |
-
|
| 4902 |
-
|
| 4903 |
-
def _lb_make_receipt(payload: dict, accepted: bool, errors: list) -> dict:
|
| 4904 |
-
body = {
|
| 4905 |
-
"receipt_type": "lambda_bounty_intake",
|
| 4906 |
-
"conjecture": "Conjecture 1 (F23 Λ-aggregator uniqueness)",
|
| 4907 |
-
"ts": _lb_now(),
|
| 4908 |
-
"submitter": (payload.get("submitter") or {}).get("name", "?"),
|
| 4909 |
-
"pr_url": payload.get("pr_url"),
|
| 4910 |
-
"accepted_intake": accepted,
|
| 4911 |
-
"errors": errors,
|
| 4912 |
-
"eligibility_note": "Intake acknowledgement only. Award eligibility = verify-proof CI green on the PR.",
|
| 4913 |
-
"prev": _lb_prev_hash(),
|
| 4914 |
-
}
|
| 4915 |
-
digest = _lb_hashlib.sha256(json.dumps(body, sort_keys=True).encode()).hexdigest()
|
| 4916 |
-
sig = _lb_hmac.new(_LB_SIGN_KEY.encode(), digest.encode(), _lb_hashlib.sha256).hexdigest()
|
| 4917 |
-
body["hash"] = digest
|
| 4918 |
-
body["hmac_sha256"] = sig
|
| 4919 |
-
body["hmac_key"] = "dev-key-placeholder (set LAMBDA_BOUNTY_HMAC_KEY for a real signature)" if _LB_HMAC_IS_DEV else "env-provided"
|
| 4920 |
-
return body
|
| 4921 |
-
|
| 4922 |
-
|
| 4923 |
-
@app.get("/api/lambda-bounty/healthz")
|
| 4924 |
-
async def _lb_healthz():
|
| 4925 |
-
"""Λ-bounty intake liveness + live Conjecture-1 status. Λ = NOT a theorem."""
|
| 4926 |
-
return JSONResponse({"status": "ok", "service": "lambda-bounty-intake",
|
| 4927 |
-
"conjecture": _LB_CONJECTURE, "doctrine": "v11",
|
| 4928 |
-
"receipts_buffered": len(_LB_LEDGER)})
|
| 4929 |
-
|
| 4930 |
-
|
| 4931 |
-
@app.post("/api/lambda-bounty/submit")
|
| 4932 |
-
async def _lb_submit(request: Request):
|
| 4933 |
-
"""Validate a Conjecture-1 submission payload, emit a hash-chained Khipu
|
| 4934 |
-
intake receipt. 200 + receipt (accepted) or 422 + errors (rejected); a
|
| 4935 |
-
receipt is appended either way. Eligibility is decided ONLY by verify-proof
|
| 4936 |
-
CI on the PR — this never declares a winner."""
|
| 4937 |
-
try:
|
| 4938 |
-
payload = await request.json()
|
| 4939 |
-
except Exception:
|
| 4940 |
-
return JSONResponse({"error": "invalid JSON"}, status_code=400)
|
| 4941 |
-
if not isinstance(payload, dict):
|
| 4942 |
-
return JSONResponse({"error": "payload must be a JSON object"}, status_code=400)
|
| 4943 |
-
errors = _lb_validate(payload)
|
| 4944 |
-
accepted = len(errors) == 0
|
| 4945 |
-
receipt = _lb_make_receipt(payload, accepted, errors)
|
| 4946 |
-
with _LB_LEDGER_LOCK:
|
| 4947 |
-
_LB_LEDGER.append(receipt)
|
| 4948 |
-
return JSONResponse(status_code=(200 if accepted else 422), content={
|
| 4949 |
-
"accepted_intake": accepted, "errors": errors, "receipt": receipt,
|
| 4950 |
-
"next_step": "Open a PR to szl-holdings/lambda-bounty; verify-proof CI is the sole arbiter.",
|
| 4951 |
-
})
|
| 4952 |
-
|
| 4953 |
-
|
| 4954 |
-
@app.get("/api/lambda-bounty/receipts")
|
| 4955 |
-
async def _lb_receipts():
|
| 4956 |
-
"""Append-only intake receipt ledger as NDJSON. In-memory ring buffer
|
| 4957 |
-
(maxlen=500); resets on Space rebuild (honest disclosure). Durable receipts
|
| 4958 |
-
are committed to the repo by the bounty-webhook GitHub Action."""
|
| 4959 |
-
from fastapi.responses import PlainTextResponse as _LBPlain
|
| 4960 |
-
with _LB_LEDGER_LOCK:
|
| 4961 |
-
lines = "\n".join(json.dumps(r) for r in _LB_LEDGER)
|
| 4962 |
-
return _LBPlain(lines, media_type="application/x-ndjson")
|
| 4963 |
|
| 4964 |
|
| 4965 |
# ============================================================================
|
|
@@ -7397,30 +7301,23 @@ def _r3d_consensus_votes_payload() -> dict:
|
|
| 7397 |
"locked-proven stays exactly 8 " + _R3D_LOCKED8 + "."),
|
| 7398 |
}
|
| 7399 |
|
| 7400 |
-
|
| 7401 |
-
|
| 7402 |
-
|
| 7403 |
-
|
| 7404 |
-
|
| 7405 |
-
|
| 7406 |
-
|
| 7407 |
-
|
| 7408 |
-
|
| 7409 |
-
|
| 7410 |
-
|
| 7411 |
-
|
| 7412 |
-
|
| 7413 |
-
|
| 7414 |
-
|
| 7415 |
-
|
| 7416 |
-
|
| 7417 |
-
@app.get("/v1/consensus/votes")
|
| 7418 |
-
async def _r3d_consensus_votes() -> JSONResponse:
|
| 7419 |
-
return JSONResponse(_r3d_consensus_votes_payload())
|
| 7420 |
-
|
| 7421 |
-
print("[a11oy] research-3d endpoints registered BEFORE proxy: /api/a11oy/v1/"
|
| 7422 |
-
"{router/metrics,chaski/routing-graph,reason/loop-depth,consensus/votes}",
|
| 7423 |
-
file=sys.stderr)
|
| 7424 |
|
| 7425 |
|
| 7426 |
@app.get("/api/a11oy/v1/ledger")
|
|
@@ -8141,69 +8038,24 @@ _A11OY_FORECAST = {
|
|
| 8141 |
}
|
| 8142 |
|
| 8143 |
|
| 8144 |
-
|
| 8145 |
-
|
| 8146 |
-
|
| 8147 |
-
|
| 8148 |
-
|
| 8149 |
-
|
| 8150 |
-
#
|
| 8151 |
-
#
|
| 8152 |
-
|
| 8153 |
-
|
| 8154 |
-
|
| 8155 |
-
|
| 8156 |
-
|
| 8157 |
-
|
| 8158 |
-
|
| 8159 |
-
|
| 8160 |
-
|
| 8161 |
-
|
| 8162 |
-
{"id": "firestorm", "title": "Firestorm Ops", "purpose": "Crisis Operations Command", "status": "stub", "owner": "coo@szl"},
|
| 8163 |
-
{"id": "nuroforge", "title": "NuroForge", "purpose": "AI Agent Forge", "status": "stub", "owner": "cto@szl"},
|
| 8164 |
-
{"id": "infra", "title": "Meridian Infra", "purpose": "Infrastructure Intelligence", "status": "stub", "owner": "eng-vp@szl"},
|
| 8165 |
-
{"id": "graph", "title": "Constellation Graph", "purpose": "Cross-Domain Intelligence Graph", "status": "stub", "owner": "cto@szl"},
|
| 8166 |
-
]
|
| 8167 |
-
|
| 8168 |
-
|
| 8169 |
-
@app.get("/api/a11oy/v1/vertical-packs")
|
| 8170 |
-
@app.get("/v1/vertical-packs")
|
| 8171 |
-
async def a11oy_vertical_packs_v2() -> JSONResponse:
|
| 8172 |
-
live = sum(1 for v in _A11OY_VERTICALS if v["status"] == "live")
|
| 8173 |
-
return JSONResponse({"total": len(_A11OY_VERTICALS), "live": live,
|
| 8174 |
-
"stub": len(_A11OY_VERTICALS) - live,
|
| 8175 |
-
"verticals": _A11OY_VERTICALS,
|
| 8176 |
-
"honesty": "Live = shipping pack; stub = scaffolded, roadmap."})
|
| 8177 |
-
|
| 8178 |
-
|
| 8179 |
-
# ---- Business Observability (5 domains) on REAL in-image data (no fabricated KPIs) ----
|
| 8180 |
-
@app.get("/api/a11oy/v1/observability/business")
|
| 8181 |
-
@app.get("/v1/observability/business")
|
| 8182 |
-
async def a11oy_business_observability_v2() -> JSONResponse:
|
| 8183 |
-
ch = _a11oy_build_chain(24)
|
| 8184 |
-
domains = [
|
| 8185 |
-
{"id": "coverage", "name": "Coverage",
|
| 8186 |
-
"measure": "knowledge ontology + vertical policies",
|
| 8187 |
-
"value": "10 policies · axioms→theorems→formulas graph", "status": "real"},
|
| 8188 |
-
{"id": "connectivity", "name": "Connectivity",
|
| 8189 |
-
"measure": "in-image capability mesh + MCP tools",
|
| 8190 |
-
"value": "%d capabilities · 4 MCP tools" % len(_A11OY_CAPS), "status": "real"},
|
| 8191 |
-
{"id": "cognitive", "name": "Cognitive",
|
| 8192 |
-
"measure": "reasoning + orchestration + Λ scoring",
|
| 8193 |
-
"value": "13-axis trust vector · Λ=0.919 (Conjecture 1)", "status": "real"},
|
| 8194 |
-
{"id": "executive", "name": "Executive Interfaces",
|
| 8195 |
-
"measure": "operator tabs + Ask & Act",
|
| 8196 |
-
"value": "command tabs + grounded operator", "status": "real"},
|
| 8197 |
-
{"id": "impact", "name": "Impact",
|
| 8198 |
-
"measure": "signed decision receipts (hash-chained)",
|
| 8199 |
-
"value": "%d signed spans · chain verified" % ch["depth"], "status": "real"},
|
| 8200 |
-
]
|
| 8201 |
-
return JSONResponse({
|
| 8202 |
-
"domains": domains,
|
| 8203 |
-
"honesty": ("Capability domains on real in-image data. We do NOT reproduce "
|
| 8204 |
-
"any third-party marketing percentages as our own."),
|
| 8205 |
-
"lambda_status": "Conjecture 1 (advisory)",
|
| 8206 |
-
})
|
| 8207 |
|
| 8208 |
|
| 8209 |
|
|
|
|
| 4849 |
# land in the repo via the bounty-webhook GitHub Action. ADDITIVE ONLY.
|
| 4850 |
# Signed-off-by: Stephen P. Lutar Jr. <stephenlutar2@gmail.com>
|
| 4851 |
# ===========================================================================
|
| 4852 |
+
# ---------------------------------------------------------------------------
|
| 4853 |
+
# Wave-K Dev4 refactor: the Λ-bounty intake route group moved VERBATIM to
|
| 4854 |
+
# routers/lambda_bounty.py. serve.py imports + calls its register(app) HERE (at
|
| 4855 |
+
# the SAME position it used to occupy — BEFORE the SPA /{full_path:path}
|
| 4856 |
+
# catch-all) via the established guarded try/except so a missing/broken group can
|
| 4857 |
+
# NEVER take down the SPA. REFACTOR-ONLY: same paths, same methods, same order.
|
| 4858 |
+
# ---------------------------------------------------------------------------
|
| 4859 |
+
try:
|
| 4860 |
+
from routers import lambda_bounty as _lb_router
|
| 4861 |
+
_lb_reg = _lb_router.register(app)
|
| 4862 |
+
print(f"[a11oy] routers.lambda_bounty registered (Wave-K Dev4 split): {_lb_reg}",
|
| 4863 |
+
file=__import__("sys").stderr)
|
| 4864 |
+
except Exception as _lb_e: # pragma: no cover — guarded; never take down the SPA
|
| 4865 |
+
print(f"[a11oy] routers.lambda_bounty NOT registered: {_lb_e!r}; SPA + API unaffected",
|
| 4866 |
+
file=__import__("sys").stderr)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4867 |
|
| 4868 |
|
| 4869 |
# ============================================================================
|
|
|
|
| 7301 |
"locked-proven stays exactly 8 " + _R3D_LOCKED8 + "."),
|
| 7302 |
}
|
| 7303 |
|
| 7304 |
+
# ---------------------------------------------------------------------------
|
| 7305 |
+
# Wave-K Dev4 refactor: the research-3D read route group (router/metrics,
|
| 7306 |
+
# chaski/routing-graph, reason/loop-depth, consensus/votes) moved VERBATIM to
|
| 7307 |
+
# routers/research_3d.py. The deterministic payload builders _r3d_*_payload()
|
| 7308 |
+
# REMAIN at serve.py module scope (defined just above); the router reaches them
|
| 7309 |
+
# via `import serve`. register(app) is called HERE (same position — BEFORE the
|
| 7310 |
+
# /api/a11oy/{path:path} proxy + SPA catch-all) via the guarded pattern.
|
| 7311 |
+
# REFACTOR-ONLY: same paths, same methods, same payloads, same order.
|
| 7312 |
+
# ---------------------------------------------------------------------------
|
| 7313 |
+
try:
|
| 7314 |
+
from routers import research_3d as _r3d_router
|
| 7315 |
+
_r3d_reg = _r3d_router.register(app)
|
| 7316 |
+
print(f"[a11oy] routers.research_3d registered (Wave-K Dev4 split): {_r3d_reg}",
|
| 7317 |
+
file=sys.stderr)
|
| 7318 |
+
except Exception as _r3d_e: # pragma: no cover — guarded; never take down the SPA
|
| 7319 |
+
print(f"[a11oy] routers.research_3d NOT registered: {_r3d_e!r}; SPA + API unaffected",
|
| 7320 |
+
file=sys.stderr)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7321 |
|
| 7322 |
|
| 7323 |
@app.get("/api/a11oy/v1/ledger")
|
|
|
|
| 8038 |
}
|
| 8039 |
|
| 8040 |
|
| 8041 |
+
# ---------------------------------------------------------------------------
|
| 8042 |
+
# Wave-K Dev4 refactor: the frontier read route group (forecast-baseline,
|
| 8043 |
+
# vertical-packs, observability/business) moved VERBATIM to
|
| 8044 |
+
# routers/frontier_reads.py. The genuinely-local _A11OY_VERTICALS registry moved
|
| 8045 |
+
# with it; the shared serve-scope state (_A11OY_FORECAST / _a11oy_build_chain /
|
| 8046 |
+
# _A11OY_CAPS) stays here and the router reaches it via `import serve`.
|
| 8047 |
+
# register(app) is called HERE (same position — BEFORE the /api/a11oy/{path:path}
|
| 8048 |
+
# proxy + SPA catch-all) via the guarded pattern.
|
| 8049 |
+
# REFACTOR-ONLY: same paths, same methods, same payloads, same order.
|
| 8050 |
+
# ---------------------------------------------------------------------------
|
| 8051 |
+
try:
|
| 8052 |
+
from routers import frontier_reads as _fr_router
|
| 8053 |
+
_fr_reg = _fr_router.register(app)
|
| 8054 |
+
print(f"[a11oy] routers.frontier_reads registered (Wave-K Dev4 split): {_fr_reg}",
|
| 8055 |
+
file=sys.stderr)
|
| 8056 |
+
except Exception as _fr_e: # pragma: no cover — guarded; never take down the SPA
|
| 8057 |
+
print(f"[a11oy] routers.frontier_reads NOT registered: {_fr_e!r}; SPA + API unaffected",
|
| 8058 |
+
file=sys.stderr)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8059 |
|
| 8060 |
|
| 8061 |
|