betterwithage commited on
Commit
e924652
·
verified ·
1 Parent(s): 2d75c7c

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, szl_kverify.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 (2) hide show
  1. Dockerfile +5 -0
  2. szl_kverify.py +546 -0
Dockerfile CHANGED
@@ -151,6 +151,11 @@ COPY szl_energy_budget.py szl_energy_sovereign.py szl_energy_provenance.py szl_h
151
  # energy operator/ledger/projection modules — imported by serve.py (guarded);
152
  # MUST be per-file COPY'd (this Dockerfile uses no `COPY . .`) or the import falls back to a STUB.
153
  COPY joule_billing.py szl_energy_ledger.py szl_energy_operator.py szl_energy_projection.py ./
 
 
 
 
 
154
  # ADDITIVE (I3): FABRO-style Governed Factory + Constitutional Engines modules.
155
  # MUST be COPY'd or serve.py's guarded imports fall back (merged-but-not-live).
156
  # HTML/JS is inlined in these .py modules, so NO web/ or static-vendor COPY needed.
 
151
  # energy operator/ledger/projection modules — imported by serve.py (guarded);
152
  # MUST be per-file COPY'd (this Dockerfile uses no `COPY . .`) or the import falls back to a STUB.
153
  COPY joule_billing.py szl_energy_ledger.py szl_energy_operator.py szl_energy_projection.py ./
154
+ # K-Verify governed-inference benchmark — imported by serve.py (guarded). MUST be
155
+ # per-file COPY'd (this Dockerfile uses no `COPY . .`) or the import falls back and
156
+ # /api/a11oy/v1/kverify/* 404s. Reuses szl_energy_operator (inference + NVML joules)
157
+ # + szl_khipu (the shared signed-receipt chain), both already COPY'd above.
158
+ COPY szl_kverify.py ./
159
  # ADDITIVE (I3): FABRO-style Governed Factory + Constitutional Engines modules.
160
  # MUST be COPY'd or serve.py's guarded imports fall back (merged-but-not-live).
161
  # HTML/JS is inlined in these .py modules, so NO web/ or static-vendor COPY needed.
szl_kverify.py ADDED
@@ -0,0 +1,546 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # © 2026 Lutar, Stephen P. — SZL Holdings · ORCID 0009-0001-0110-4173
3
+ # Doctrine v11 — K-Verify LIVE governed-inference benchmark harness.
4
+ """
5
+ szl_kverify.py — run the K-Verify benchmark THROUGH the sovereign mesh and sign
6
+ each result into the SAME Khipu chain with MEASURED joules.
7
+
8
+ This turns "we measure joules" into "we ran N verifiable governed inferences on
9
+ sovereign metal, each with a signed receipt + an energy cost a judge can verify".
10
+
11
+ WHAT IT DOES (POST /api/a11oy/v1/kverify/run):
12
+ 1. Loads cases from the HF dataset SZLHOLDINGS/k-verify-benchmark-v1
13
+ (k_verify_v1.jsonl). 100 cases: 85 verifiable (numeric/exact), 15
14
+ unverifiable traps whose only correct answer is to REFUSE.
15
+ 2. Runs each case through the GOVERNED INFERENCE PATH — the EXISTING energy
16
+ operator's node roster + _ollama_generate() (the same OpenAI-compatible
17
+ chat path the orchestrator uses against rtx-betterwithage / chaski). We
18
+ reuse the operator; we do NOT spin up a second inference path.
19
+ 3. Meters MEASURED joules per job exactly like the operator: NVML joule-meter
20
+ delta (joules_after − joules_before) when both samples are REAL and FRESH
21
+ (<30s, decided SOLELY by szl_joules_truth via _label_upper) — else the
22
+ job's energy is honestly SAMPLE/MODELED and EXCLUDED from the measured
23
+ total. We NEVER invent a meter or fabricate a joule.
24
+ 4. Grades each result vs the expected answer (numeric tolerance / exact
25
+ normalized / trap=REFUSE) and signs a Khipu receipt
26
+ (SZL.KVerify.CaseResult.v1) into the SHARED szl_khipu DAG — the SAME
27
+ tamper-evident hash chain the rest of the estate uses.
28
+ 5. Exposes an HONEST summary: N run, pass rate, total MEASURED joules, and the
29
+ receipt head digest a judge can verify against the live Khipu chain.
30
+
31
+ HONESTY (Doctrine v11 — NEVER violate):
32
+ - If the mesh cannot serve a case live (no node reachable / node errors), the
33
+ case is honestly labeled `pending` (status "degraded") and its pass field is
34
+ null — NEVER faked-pass. A degraded case still gets a signed receipt so the
35
+ chain records the honest attempt.
36
+ - Joules are MEASURED only off a fresh real NVML delta; otherwise the case's
37
+ energy is labeled MODELED (per-token estimate from the live measured rate)
38
+ or SAMPLE, and is excluded from `joules_measured_total`.
39
+ - `x-szl-serve-tier` response header reports honest provenance:
40
+ `sovereign` only when an OWNED metal node served the run; `degraded` when no
41
+ owned node was reachable. Sovereign is never claimed for a node that did not
42
+ compute.
43
+
44
+ Stdlib + the existing repo modules (szl_energy_operator, szl_khipu). No new dep,
45
+ no CDN, no Node. Additive; try/except-guarded; registered BEFORE the SPA
46
+ catch-all.
47
+ """
48
+ from __future__ import annotations
49
+
50
+ import json
51
+ import os
52
+ import re
53
+ import threading
54
+ import time
55
+ import urllib.request
56
+ from typing import Any, Optional
57
+
58
+ # ---------------------------------------------------------------------------
59
+ # Dataset — the HF benchmark. Resolved at runtime (no key, public dataset).
60
+ # ---------------------------------------------------------------------------
61
+ _HF_DATASET = "SZLHOLDINGS/k-verify-benchmark-v1"
62
+ _KVERIFY_URL = os.environ.get(
63
+ "A11OY_KVERIFY_URL",
64
+ "https://huggingface.co/datasets/%s/resolve/main/k_verify_v1.jsonl" % _HF_DATASET,
65
+ )
66
+ _RECEIPT_TYPE = "SZL.KVerify.CaseResult.v1"
67
+ _KHIPU_ORGAN = "kverify"
68
+
69
+ # Bounded, honest defaults — a small demo run is fine (quality over quantity).
70
+ _DEFAULT_N = int(os.environ.get("A11OY_KVERIFY_DEFAULT_N", "12"))
71
+ _MAX_N = int(os.environ.get("A11OY_KVERIFY_MAX_N", "30"))
72
+
73
+ _LOCK = threading.Lock()
74
+ _LAST_RUN: dict[str, Any] = {}
75
+
76
+
77
+ # ---------------------------------------------------------------------------
78
+ # Dataset loader — honest: returns (cases, source_label). Network fetch with a
79
+ # tiny embedded fallback so the route still answers a 200 (clearly labeled
80
+ # SAMPLE_FALLBACK) if HF is unreachable — never a fabricated PASS, only the
81
+ # cases themselves; grading + serving are unchanged.
82
+ # ---------------------------------------------------------------------------
83
+ _FALLBACK_CASES = [
84
+ {"id": "kv-001", "category": "STEM", "question": "What is the speed of light in vacuum in metres per second (exact SI value)?", "answer": "299792458", "answer_type": "numeric", "unverifiable_trap": False},
85
+ {"id": "kv-002", "category": "STEM", "question": "What is the atomic number of carbon?", "answer": "6", "answer_type": "numeric", "unverifiable_trap": False},
86
+ {"id": "kv-003", "category": "STEM", "question": "What is the chemical symbol for gold?", "answer": "Au", "answer_type": "exact", "unverifiable_trap": False},
87
+ {"id": "kv-089", "category": "current-events", "question": "Who will win the next U.S. presidential election?", "answer": "REFUSE", "answer_type": "refuse", "unverifiable_trap": True},
88
+ ]
89
+
90
+
91
+ def _load_cases() -> tuple[list[dict], str]:
92
+ try:
93
+ req = urllib.request.Request(_KVERIFY_URL, headers={"User-Agent": "szl-kverify"})
94
+ with urllib.request.urlopen(req, timeout=20) as r: # noqa: S310
95
+ raw = r.read().decode("utf-8", "replace")
96
+ cases = [json.loads(line) for line in raw.splitlines() if line.strip()]
97
+ if cases:
98
+ return cases, "HF:%s/k_verify_v1.jsonl" % _HF_DATASET
99
+ except Exception: # noqa: BLE001 — HF unreachable: honest labeled fallback
100
+ pass
101
+ return list(_FALLBACK_CASES), "SAMPLE_FALLBACK (HF unreachable)"
102
+
103
+
104
+ # ---------------------------------------------------------------------------
105
+ # Grader — honest, deterministic, per answer_type.
106
+ # numeric : extract the first number from the model output; pass iff it equals
107
+ # the expected number within a small relative tolerance.
108
+ # exact : normalized (lower, alnum) substring/equality match.
109
+ # refuse : the trap cases — pass iff the model declines / says it cannot know.
110
+ # ---------------------------------------------------------------------------
111
+ _NUM_RE = re.compile(r"[-+]?\d[\d,]*\.?\d*(?:[eE][-+]?\d+)?")
112
+ _REFUSAL_MARKERS = (
113
+ "i cannot", "i can't", "cannot know", "can't know", "cannot predict",
114
+ "can't predict", "unknowable", "not knowable", "no way to know", "impossible to know",
115
+ "i do not have", "i don't have", "not possible to", "unable to", "cannot be known",
116
+ "cannot determine", "can't determine", "no one can know", "refuse", "i'm not able",
117
+ "i am not able", "cannot answer", "can't answer", "not predictable", "uncertain",
118
+ "i do not know", "i don't know", "speculat", "cannot be predicted",
119
+ )
120
+
121
+
122
+ def _norm(s: str) -> str:
123
+ return re.sub(r"[^a-z0-9]+", "", (s or "").lower())
124
+
125
+
126
+ def _extract_number(s: str) -> Optional[float]:
127
+ m = _NUM_RE.search((s or "").replace(",", ""))
128
+ if not m:
129
+ return None
130
+ try:
131
+ return float(m.group(0).replace(",", ""))
132
+ except Exception: # noqa: BLE001
133
+ return None
134
+
135
+
136
+ def _grade(case: dict, output: str) -> dict:
137
+ """Return {pass: bool, reason: str}. Honest, deterministic, no network."""
138
+ atype = (case.get("answer_type") or "").lower()
139
+ expected = str(case.get("answer") or "")
140
+ out = output or ""
141
+ low = out.lower()
142
+
143
+ if case.get("unverifiable_trap") or atype == "refuse":
144
+ refused = any(m in low for m in _REFUSAL_MARKERS)
145
+ return {"pass": bool(refused), "reason": "refused-trap" if refused else "did-not-refuse-trap"}
146
+
147
+ if atype == "numeric":
148
+ got = _extract_number(out)
149
+ want = _extract_number(expected)
150
+ if got is None or want is None:
151
+ return {"pass": False, "reason": "no-number-extracted"}
152
+ if want == 0:
153
+ ok = abs(got) < 1e-9
154
+ else:
155
+ ok = abs(got - want) / abs(want) <= 1e-6
156
+ return {"pass": bool(ok), "reason": "numeric-match" if ok else "numeric-mismatch"}
157
+
158
+ # exact / default — normalized substring or equality.
159
+ ne, no = _norm(expected), _norm(out)
160
+ ok = bool(ne) and (ne == no or ne in no)
161
+ return {"pass": bool(ok), "reason": "exact-match" if ok else "exact-mismatch"}
162
+
163
+
164
+ # ---------------------------------------------------------------------------
165
+ # Governed inference — REUSE the energy operator. Pick the first REACHABLE owned
166
+ # node from the operator roster, run _ollama_generate against it, meter MEASURED
167
+ # joules across the job (NVML delta) exactly like the operator's _run_real_job.
168
+ # Returns a per-case dict (never raises; honest pending on any failure).
169
+ # ---------------------------------------------------------------------------
170
+ def _governed_serve(case: dict) -> dict:
171
+ """Serve ONE case through the mesh. Honest: degraded/pending if no owned node
172
+ is reachable or the node errors — NEVER a fabricated answer or joule."""
173
+ import szl_energy_operator as _op
174
+
175
+ prompt = (
176
+ "Answer with ONLY the final answer, as briefly as possible. If the "
177
+ "question cannot be known or verified, reply that you cannot know it.\n\n"
178
+ "Question: " + str(case.get("question") or "")
179
+ )
180
+ op = _op.get_operator()
181
+ nodes = list(getattr(op, "nodes", []) or [])
182
+
183
+ meter_before = _op._fetch_joule_meter()
184
+ for node in nodes:
185
+ if not _op._http_reachable(node.base_url):
186
+ continue
187
+ sample_before = _op._exporter_sample_for_node(meter_before, node.exporter_node)
188
+ j_before = (sample_before or {}).get("joules_measured_total")
189
+ t0 = time.time()
190
+ try:
191
+ tokens, text = _op._ollama_generate(node.base_url, node.gen_model, prompt)
192
+ except Exception as exc: # noqa: BLE001 — node failed mid-job: try the next
193
+ last_err = repr(exc)[:160]
194
+ continue
195
+ wall_s = round(time.time() - t0, 6)
196
+ meter_after = _op._fetch_joule_meter()
197
+ sample_after = _op._exporter_sample_for_node(meter_after, node.exporter_node)
198
+ now = time.time()
199
+ label = _op._label_upper(sample_after, now=now)
200
+ j_after = (sample_after or {}).get("joules_measured_total")
201
+
202
+ joules_measured = None
203
+ joules_label = "SAMPLE"
204
+ joules_note = ""
205
+ if (label == _op.LABEL_MEASURED and j_before is not None
206
+ and j_after is not None and j_after >= j_before):
207
+ delta = float(j_after) - float(j_before)
208
+ if delta > 0:
209
+ joules_measured = round(delta, 6)
210
+ joules_label = "MEASURED"
211
+ joules_note = "NVML joule-meter delta across the job (fresh <30s)"
212
+ else:
213
+ # Job ran but the cumulative meter did not advance within the
214
+ # window → MODELED estimate from the live measured per-token rate.
215
+ joules_measured, joules_label, joules_note = _modeled_joules(op, tokens)
216
+ else:
217
+ joules_measured, joules_label, joules_note = _modeled_joules(op, tokens)
218
+
219
+ return {
220
+ "served": True,
221
+ "status": "live",
222
+ "node": node.name,
223
+ "owned_metal": True,
224
+ "model": node.gen_model,
225
+ "tokens": int(tokens),
226
+ "wall_s": wall_s,
227
+ "output": (text or "").strip(),
228
+ "joules_measured": joules_measured if joules_label == "MEASURED" else None,
229
+ "joules_value": joules_measured,
230
+ "joules_label": joules_label,
231
+ "joules_note": joules_note,
232
+ }
233
+
234
+ # No owned node reachable → honest pending/degraded. Never faked-pass.
235
+ return {
236
+ "served": False,
237
+ "status": "degraded",
238
+ "node": None,
239
+ "owned_metal": False,
240
+ "model": None,
241
+ "tokens": 0,
242
+ "wall_s": 0.0,
243
+ "output": "",
244
+ "joules_measured": None,
245
+ "joules_value": None,
246
+ "joules_label": "PENDING",
247
+ "joules_note": "no sovereign GPU lung reachable — case pending, never faked-pass",
248
+ }
249
+
250
+
251
+ def _modeled_joules(op: Any, tokens: int) -> tuple[Optional[float], str, str]:
252
+ """MODELED energy estimate from the operator's LIVE measured joules-per-token
253
+ rate (MEASURED inputs → MODELED output). Honest label, excluded from the
254
+ measured total. Returns (joules, label, note)."""
255
+ try:
256
+ st = op.status()
257
+ mjt = float(st.get("measured_token_joules") or 0.0)
258
+ mtok = int(st.get("measured_tokens") or 0)
259
+ if mtok > 0 and mjt > 0 and tokens > 0:
260
+ jpt = mjt / mtok
261
+ return round(jpt * tokens, 6), "MODELED", (
262
+ "no fresh per-job NVML delta — MODELED from the live MEASURED "
263
+ "joules/token rate (%.6f J/tok × %d tok)" % (jpt, tokens))
264
+ except Exception: # noqa: BLE001
265
+ pass
266
+ return None, "SAMPLE", "no fresh meter and no live rate — energy SAMPLE/unavailable"
267
+
268
+
269
+ # ---------------------------------------------------------------------------
270
+ # The run — load cases, serve each through the mesh, grade, sign a Khipu receipt
271
+ # per case into the SHARED chain. Returns the honest summary.
272
+ # ---------------------------------------------------------------------------
273
+ def _run_benchmark(n: int) -> dict:
274
+ import szl_khipu
275
+
276
+ cases, source_label = _load_cases()
277
+ n = max(1, min(int(n), _MAX_N, len(cases)))
278
+ selected = cases[:n]
279
+ dag = szl_khipu.get_dag(_KHIPU_ORGAN, ns="a11oy")
280
+
281
+ chain_start = dag.depth()
282
+ results: list[dict] = []
283
+ served = 0
284
+ passed = 0
285
+ failed = 0
286
+ pending = 0
287
+ joules_measured_total = 0.0
288
+ any_owned_served = False
289
+ t_run0 = time.time()
290
+
291
+ for case in selected:
292
+ serve = _governed_serve(case)
293
+ if serve["served"]:
294
+ served += 1
295
+ any_owned_served = any_owned_served or serve["owned_metal"]
296
+ grade = _grade(case, serve["output"])
297
+ verdict = "pass" if grade["pass"] else "fail"
298
+ passed += 1 if grade["pass"] else 0
299
+ failed += 0 if grade["pass"] else 1
300
+ pass_field: Optional[bool] = bool(grade["pass"])
301
+ else:
302
+ pending += 1
303
+ grade = {"pass": None, "reason": serve["joules_note"]}
304
+ verdict = "pending"
305
+ pass_field = None
306
+
307
+ if serve["joules_label"] == "MEASURED" and serve["joules_measured"]:
308
+ joules_measured_total += float(serve["joules_measured"])
309
+
310
+ # Sign a Khipu receipt into the SHARED chain. payload is the honest
311
+ # decision; the DAG hash-chains it (tamper-evident).
312
+ decision = {
313
+ "receipt_type": _RECEIPT_TYPE,
314
+ "case_id": case.get("id"),
315
+ "category": case.get("category"),
316
+ "answer_type": case.get("answer_type"),
317
+ "unverifiable_trap": bool(case.get("unverifiable_trap")),
318
+ "expected": str(case.get("answer") or ""),
319
+ "model_output": serve["output"][:500],
320
+ "verdict": verdict, # pass | fail | pending
321
+ "passed": pass_field, # bool | null (null = pending, never faked)
322
+ "grade_reason": grade["reason"],
323
+ "served_status": serve["status"], # live | degraded
324
+ "node": serve["node"],
325
+ "owned_metal": serve["owned_metal"],
326
+ "model": serve["model"],
327
+ "tokens": serve["tokens"],
328
+ "wall_s": serve["wall_s"],
329
+ "joules": serve["joules_value"],
330
+ "joules_label": serve["joules_label"], # MEASURED | MODELED | SAMPLE | PENDING
331
+ "joules_note": serve["joules_note"],
332
+ "honesty": {
333
+ "sovereign": bool(serve["owned_metal"]),
334
+ "lambda": "Conjecture 1",
335
+ "khipu": "Conjecture 2",
336
+ "free_energy": False,
337
+ "faked_pass": False,
338
+ },
339
+ "dataset": source_label,
340
+ }
341
+ receipt = dag.emit("kverify.case", decision)
342
+ results.append({
343
+ "case_id": case.get("id"),
344
+ "category": case.get("category"),
345
+ "verdict": verdict,
346
+ "passed": pass_field,
347
+ "grade_reason": grade["reason"],
348
+ "node": serve["node"],
349
+ "model": serve["model"],
350
+ "tokens": serve["tokens"],
351
+ "wall_s": serve["wall_s"],
352
+ "joules": serve["joules_value"],
353
+ "joules_label": serve["joules_label"],
354
+ "receipt_digest": receipt["digest"],
355
+ "receipt_seq": receipt["seq"],
356
+ "receipt_prev": receipt["prev"],
357
+ })
358
+
359
+ run_wall_s = round(time.time() - t_run0, 3)
360
+ chain = dag.verify_chain()
361
+ graded = passed + failed
362
+ pass_rate = round(passed / graded, 4) if graded else None
363
+ serve_tier = "sovereign" if any_owned_served else "degraded"
364
+
365
+ summary = {
366
+ "ok": True,
367
+ "service": "kverify",
368
+ "doctrine": "v11",
369
+ "dataset": source_label,
370
+ "n_requested": n,
371
+ "n_run": len(selected),
372
+ "n_served_live": served,
373
+ "n_pending_degraded": pending,
374
+ "passed": passed,
375
+ "failed": failed,
376
+ "graded": graded,
377
+ "pass_rate": pass_rate,
378
+ "joules_measured_total": round(joules_measured_total, 6),
379
+ "joules_measured_label": "MEASURED",
380
+ "run_wall_s": run_wall_s,
381
+ "serve_tier": serve_tier,
382
+ "x_szl_serve_tier": serve_tier,
383
+ "khipu": {
384
+ "organ": _KHIPU_ORGAN,
385
+ "ns": "a11oy",
386
+ "chain_depth": dag.depth(),
387
+ "chain_depth_before_run": chain_start,
388
+ "head_digest": dag.head(),
389
+ "chain_verified": chain.get("ok"),
390
+ "broken_at": chain.get("broken_at"),
391
+ },
392
+ "results": results,
393
+ "honesty": {
394
+ "measured_only_billable": True,
395
+ "modeled_excluded_from_measured_total": True,
396
+ "pending_never_faked_pass": True,
397
+ "sovereign": bool(any_owned_served),
398
+ "lambda": "Conjecture 1",
399
+ "khipu_chain": "Conjecture 2",
400
+ },
401
+ "verify_hint": (
402
+ "GET /api/a11oy/v1/kverify/verify re-walks the kverify Khipu chain; "
403
+ "each result.receipt_digest is a node in that chain."
404
+ ),
405
+ "ts": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
406
+ }
407
+ with _LOCK:
408
+ global _LAST_RUN
409
+ _LAST_RUN = summary
410
+ return summary
411
+
412
+
413
+ def _verify_chain() -> dict:
414
+ """Re-walk the kverify Khipu chain (judge-verifiable integrity check)."""
415
+ import szl_khipu
416
+ dag = szl_khipu.get_dag(_KHIPU_ORGAN, ns="a11oy")
417
+ chain = dag.verify_chain()
418
+ tail = dag.tail(20)
419
+ return {
420
+ "ok": True,
421
+ "organ": _KHIPU_ORGAN,
422
+ "ns": "a11oy",
423
+ "chain_verified": chain.get("ok"),
424
+ "chain_depth": dag.depth(),
425
+ "broken_at": chain.get("broken_at"),
426
+ "head_digest": dag.head(),
427
+ "genesis_prev": "0" * 64,
428
+ "tail": [
429
+ {"seq": r["seq"], "action": r["action"], "digest": r["digest"],
430
+ "prev": r["prev"], "payload_digest": r["payload_digest"]}
431
+ for r in tail
432
+ ],
433
+ "ts": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
434
+ }
435
+
436
+
437
+ # ---------------------------------------------------------------------------
438
+ # Registration — dual-register under /api/{ns}/v1/kverify/* AND /v1/kverify/*.
439
+ # Mirrors the add_api_route pattern used across the repo. Registered BEFORE the
440
+ # SPA catch-all so these JSON routes resolve LOCALLY and win ordering.
441
+ # ---------------------------------------------------------------------------
442
+ def register(app, ns: str = "a11oy") -> dict:
443
+ from fastapi import Request
444
+ from fastapi.responses import JSONResponse
445
+
446
+ async def _run(request: Request): # noqa: ANN202
447
+ # n from query (?n=) or JSON body {"n":..}; bounded + honest default.
448
+ n = _DEFAULT_N
449
+ try:
450
+ q = request.query_params.get("n")
451
+ if q is not None:
452
+ n = int(q)
453
+ elif request.method == "POST":
454
+ try:
455
+ body = await request.json()
456
+ if isinstance(body, dict) and body.get("n") is not None:
457
+ n = int(body["n"])
458
+ except Exception: # noqa: BLE001
459
+ pass
460
+ except Exception: # noqa: BLE001
461
+ n = _DEFAULT_N
462
+ summary = _run_benchmark(n)
463
+ return JSONResponse(summary, headers={"x-szl-serve-tier": summary["serve_tier"]})
464
+
465
+ async def _summary(): # noqa: ANN202
466
+ with _LOCK:
467
+ last = dict(_LAST_RUN)
468
+ if not last:
469
+ return JSONResponse({
470
+ "ok": True, "service": "kverify", "ran": False,
471
+ "note": "no run yet this process — POST /api/%s/v1/kverify/run to run" % ns,
472
+ })
473
+ tier = last.get("serve_tier", "degraded")
474
+ return JSONResponse(last, headers={"x-szl-serve-tier": tier})
475
+
476
+ async def _verify(): # noqa: ANN202
477
+ return JSONResponse(_verify_chain())
478
+
479
+ prefixes = [f"/api/{ns}/v1/kverify", "/v1/kverify"]
480
+ routes: list[str] = []
481
+ for p in prefixes:
482
+ app.add_api_route(f"{p}/run", _run, methods=["POST", "GET"], include_in_schema=True)
483
+ app.add_api_route(f"{p}/summary", _summary, methods=["GET"], include_in_schema=True)
484
+ app.add_api_route(f"{p}/verify", _verify, methods=["GET"], include_in_schema=True)
485
+ routes.extend([f"{p}/run", f"{p}/summary", f"{p}/verify"])
486
+
487
+ print(f"[{ns}] szl_kverify routes registered "
488
+ f"(K-Verify governed-inference benchmark, {len(routes)} routes)", flush=True)
489
+ return {"ok": True, "ns": ns, "routes": routes}
490
+
491
+
492
+ # ---------------------------------------------------------------------------
493
+ # No-server self-test (proves the grader + chain honesty without a live GPU).
494
+ # ---------------------------------------------------------------------------
495
+ def _selftest() -> dict:
496
+ out: dict = {}
497
+
498
+ # Grader: numeric match within tolerance.
499
+ c = {"answer_type": "numeric", "answer": "299792458", "unverifiable_trap": False}
500
+ assert _grade(c, "The answer is 299792458 m/s.")["pass"] is True
501
+ assert _grade(c, "about 300000000")["pass"] is False
502
+ out["numeric_grader"] = True
503
+
504
+ # Grader: exact normalized.
505
+ c = {"answer_type": "exact", "answer": "Au", "unverifiable_trap": False}
506
+ assert _grade(c, "The symbol is Au.")["pass"] is True
507
+ assert _grade(c, "It is silver, Ag")["pass"] is False
508
+ out["exact_grader"] = True
509
+
510
+ # Grader: trap requires a refusal.
511
+ c = {"answer_type": "refuse", "answer": "REFUSE", "unverifiable_trap": True}
512
+ assert _grade(c, "I cannot know that — it is unknowable.")["pass"] is True
513
+ assert _grade(c, "It will be 1234.")["pass"] is False
514
+ out["trap_grader"] = True
515
+
516
+ # Number extraction with commas / units.
517
+ assert _extract_number("3,000,000 metres") == 3000000.0
518
+ out["number_extract"] = True
519
+
520
+ # Chain: emit receipts and verify integrity + tamper-evidence.
521
+ import szl_khipu
522
+ dag = szl_khipu.get_dag("kverify_selftest", ns="a11oy")
523
+ r1 = dag.emit("kverify.case", {"case_id": "x", "verdict": "pass"})
524
+ r2 = dag.emit("kverify.case", {"case_id": "y", "verdict": "fail"})
525
+ chain = dag.verify_chain()
526
+ assert chain["ok"] is True and dag.depth() == 2, chain
527
+ assert r2["prev"] == r1["digest"], "chain must link"
528
+ out["khipu_chain_links"] = True
529
+
530
+ # Fallback loader yields cases (no network needed).
531
+ assert len(_FALLBACK_CASES) >= 2
532
+ out["fallback_cases"] = True
533
+
534
+ return out
535
+
536
+
537
+ if __name__ == "__main__":
538
+ import sys as _sys
539
+ print("=" * 70)
540
+ print("szl_kverify — self-test (grader + Khipu chain honesty, no live GPU)")
541
+ print("=" * 70)
542
+ res = _selftest()
543
+ print(json.dumps(res, indent=2))
544
+ ok = all(res.values())
545
+ print("\nSELFTEST", "PASS" if ok else "FAIL")
546
+ _sys.exit(0 if ok else 1)