betterwithage commited on
Commit
d9ba8d6
·
verified ·
1 Parent(s): 08d3304

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, 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 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
- import hashlib as _lb_hashlib
4853
- import hmac as _lb_hmac
4854
- import re as _lb_re
4855
-
4856
- _LB_SIGN_KEY = os.environ.get("LAMBDA_BOUNTY_HMAC_KEY", "dev-key-not-for-prod")
4857
- _LB_HMAC_IS_DEV = _LB_SIGN_KEY == "dev-key-not-for-prod"
4858
- _LB_PR_RE = _lb_re.compile(r"^https://github\.com/szl-holdings/lambda-bounty/pull/\d+$")
4859
- _LB_ALLOWED_AXIOMS = ("propext", "Quot.sound", "Classical.choice")
4860
- _LB_LEDGER: _pr_col.deque = _pr_col.deque(maxlen=500)
4861
- _LB_LEDGER_LOCK = _pr_thr.Lock()
4862
- _LB_CONJECTURE = {
4863
- "id": "Conjecture 1",
4864
- "formula": "F23",
4865
- "status": "OPEN NOT a theorem",
4866
- "statement": "Any two 9-axis aggregators satisfying A1 idempotence, A2 monotonicity, "
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
- @app.get("/api/a11oy/v1/router/metrics")
7401
- @app.get("/v1/router/metrics")
7402
- async def _r3d_router_metrics() -> JSONResponse:
7403
- return JSONResponse(_r3d_router_metrics_payload())
7404
-
7405
- @app.get("/api/a11oy/v1/chaski/routing-graph")
7406
- @app.get("/v1/chaski/routing-graph")
7407
- @app.get("/api/chaski/routing-graph")
7408
- async def _r3d_routing_graph() -> JSONResponse:
7409
- return JSONResponse(_r3d_routing_graph_payload())
7410
-
7411
- @app.get("/api/a11oy/v1/reason/loop-depth")
7412
- @app.get("/v1/reason/loop-depth")
7413
- async def _r3d_loop_depth() -> JSONResponse:
7414
- return JSONResponse(_r3d_loop_depth_payload())
7415
-
7416
- @app.get("/api/a11oy/v1/consensus/votes")
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
- @app.get("/api/a11oy/v1/forecast-baseline")
8145
- @app.get("/v1/forecast-baseline")
8146
- async def a11oy_forecast_baseline_v2() -> JSONResponse:
8147
- return JSONResponse(_A11OY_FORECAST)
8148
-
8149
-
8150
- # ---- Vertical-pack registry (GAP-5): 13 verticals, live/stub. "Cyber Resilience"
8151
- # label avoids the literal forbidden string. NO amaru/sentra/rosie. ----
8152
- _A11OY_VERTICALS = [
8153
- {"id": "platform", "title": "Platform / AgentOps", "purpose": "Release Gate Intelligence", "status": "live", "owner": "eng-vp@szl"},
8154
- {"id": "pulse", "title": "Pulse", "purpose": "Founder Operating Channel", "status": "live", "owner": "ceo@szl"},
8155
- {"id": "finance", "title": "Finance / Capital Weather", "purpose": "Capital Weather", "status": "live", "owner": "cfo@szl"},
8156
- {"id": "decision_ledger", "title": "Decision Debt Ledger", "purpose": "Decision Debt Ledger", "status": "live", "owner": "cpo@szl"},
8157
- {"id": "terra", "title": "Acquisition Time Machine", "purpose": "Acquisition Time Machine", "status": "live", "owner": "ceo@szl"},
8158
- {"id": "voyage", "title": "Voyage Risk Exchange", "purpose": "Voyage Risk Exchange", "status": "live", "owner": "coo@szl"},
8159
- {"id": "counsel", "title": "Matter Flight Recorder", "purpose": "Matter Flight Recorder", "status": "live", "owner": "general-counsel@szl"},
8160
- {"id": "growth", "title": "Marketing / Growth", "purpose": "Proof-To-Pipeline Engine", "status": "live", "owner": "cmo@szl"},
8161
- {"id": "cyber", "title": "Cyber Resilience", "purpose": "Cyber Resilience Command", "status": "live", "owner": "ciso@szl"},
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